summaryrefslogblamecommitdiff
path: root/pkg/app/app.go
blob: 9a2df509b4590f699c974db6b531d4b9d78df841 (plain) (tree)

























































































                                                                                                        
package app

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"strings"
	"time"

	"github.com/alexedwards/scs/boltstore"
	"github.com/alexedwards/scs/v2"
	"github.com/labstack/echo/v4"
	"github.com/labstack/echo/v4/middleware"
	session "github.com/spazzymoto/echo-scs-session"
	"gitrepo.ru/neonxp/track/pkg/config"
	"gitrepo.ru/neonxp/track/pkg/handler"
	"gitrepo.ru/neonxp/track/pkg/models"
	"go.etcd.io/bbolt"
	bolt "go.etcd.io/bbolt"
	"golang.org/x/crypto/bcrypt"
)

func App(ctx context.Context) error {
	cfg := config.New()
	db, err := bolt.Open(cfg.DBPath, 0600, nil)
	if err != nil {
		return fmt.Errorf("failed open db: %w", err)
	}
	defer db.Close()

	e := echo.New()

	sessionManager := scs.New()
	sessionManager.Store = boltstore.NewWithCleanupInterval(db, 5*time.Minute)
	sessionManager.Lifetime = 30 * 24 * time.Hour
	userHandler := handler.NewUser(db, sessionManager)
	locationHandler := handler.NewLocation(db, sessionManager)

	authFunc := func(s1, s2 string, c echo.Context) (bool, error) {
		// TODO remove this shit
		user := new(models.User)
		s1 = strings.ReplaceAll(s1, "%40", "@")

		err := db.View(func(tx *bbolt.Tx) error {
			users := tx.Bucket([]byte("users"))
			jb := users.Get([]byte(strings.ToLower(s1)))
			if jb == nil {
				return errors.New("invalid user or password")
			}
			if err := json.Unmarshal(jb, user); err != nil {
				return err
			}
			if err := bcrypt.CompareHashAndPassword(user.Password, []byte(s2)); err != nil {
				return errors.New("invalid user or password")
			}

			return nil
		})
		if err != nil {
			return false, err
		}
		sessionManager.Put(c.Request().Context(), "user", user)

		return true, nil
	}

	func(eg *echo.Group) {
		eg.POST("/user/register", userHandler.Register)
		eg.POST("/user/login", userHandler.Login)
		eg.GET("/user", userHandler.User)

		eg.GET("/point", locationHandler.AddPoint, middleware.BasicAuth(authFunc))
		eg.GET("/points", locationHandler.GetPoints)
		eg.GET("/points/last", locationHandler.GetLast)
	}(e.Group("/api"))
	e.Static("/", "./web")
	e.Use(
		middleware.Recover(),
		middleware.Logger(),
		session.LoadAndSave(sessionManager),
	)

	if err := e.Start(cfg.Listen); err != http.ErrServerClosed {
		return err
	}

	return nil
}