From 8d66ec58e2256412a2fd50ad9e651c09af1ea8cc Mon Sep 17 00:00:00 2001 From: GrailFinder Date: Sun, 28 Apr 2024 07:03:36 +0300 Subject: Feat: auth middleware; login [wip] --- internal/handlers/auth.go | 55 ++++++++++++++++++++++++++++++++--------- internal/handlers/main.go | 26 ++++++++++++------- internal/handlers/middleware.go | 48 +++++++++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+), 20 deletions(-) create mode 100644 internal/handlers/middleware.go (limited to 'internal/handlers') diff --git a/internal/handlers/auth.go b/internal/handlers/auth.go index 435f8ff..5ec1c80 100644 --- a/internal/handlers/auth.go +++ b/internal/handlers/auth.go @@ -3,7 +3,7 @@ package handlers import ( "apjournal/internal/models" "apjournal/pkg/utils" - "fmt" + "encoding/json" "html/template" "net/http" "strings" @@ -32,21 +32,32 @@ func (h *Handlers) HandleLogin(w http.ResponseWriter, r *http.Request) { return } cleanName := utils.RemoveSpacesFromStr(username) - // allNames := h.s.CacheGetAllNames() - allNames := []string{} - if utils.StrInSlice(cleanName, allNames) { - err := fmt.Errorf("name: %s already taken", cleanName) - h.log.Error("already taken", "error", err) - abortWithError(w, err.Error()) - return - } cookie, err := h.makeCookie(cleanName, r.RemoteAddr) if err != nil { h.log.Error("failed to login", "error", err) abortWithError(w, err.Error()) + return } http.SetCookie(w, cookie) - http.Redirect(w, r, "/", 302) + // http.Redirect(w, r, "/", 302) + tmpl, err := template.ParseGlob("components/*.html") + if err != nil { + panic(err) + } + userScore, err := h.repo.DBUserScoreGet(cleanName) + if err != nil { + h.log.Warn("got db err", "err", err) + if err := h.repo.DBUserScoreCreate(&us); err != nil { + panic(err) + } + tmpl.ExecuteTemplate(w, "main", nil) + return + } + userScore.Actions, err = h.repo.DBActionList(cleanName) + if err != nil { + panic(err) + } + tmpl.ExecuteTemplate(w, "main", userScore) } func (h *Handlers) makeCookie(username string, remote string) (*http.Cookie, error) { @@ -72,10 +83,32 @@ func (h *Handlers) makeCookie(username string, remote string) (*http.Cookie, err "remote", remote, "session", session) if strings.Contains(remote, "192.168.0") { // no idea what is going on - // domainName = "192.168.0.101" cookie.Domain = "192.168.0.101" } // set ctx? // c.Set("username", username) return cookie, nil } + +func (h *Handlers) cacheGetSession(key string) (*models.Session, error) { + userSessionB, err := h.mc.Get(key) + if err != nil { + return nil, err + } + var us *models.Session + if err := json.Unmarshal(userSessionB, &us); err != nil { + return nil, err + } + return us, nil +} + +func (h *Handlers) cacheSetSession(key string, session *models.Session) error { + sesb, err := json.Marshal(session) + if err != nil { + return err + } + h.mc.Set(key, sesb) + // expire in 10 min + h.mc.Expire(key, 10*60) + return nil +} diff --git a/internal/handlers/main.go b/internal/handlers/main.go index d779f42..aa9db4f 100644 --- a/internal/handlers/main.go +++ b/internal/handlers/main.go @@ -4,6 +4,7 @@ import ( "apjournal/config" "apjournal/internal/database/repos" "apjournal/internal/models" + "apjournal/pkg/cache" "html/template" "log/slog" "net/http" @@ -18,12 +19,12 @@ import ( type Handlers struct { cfg config.Config log *slog.Logger - repo *repos.Provider + repo repos.FullRepo + mc cache.Cache } // NewHandlers constructor func NewHandlers( - // cfg config.Config, s *service.Service, l *slog.Logger, cfg config.Config, l *slog.Logger, conn *sqlx.DB, ) *Handlers { if l == nil { @@ -33,6 +34,7 @@ func NewHandlers( cfg: cfg, log: l, repo: repos.NewProvider(conn), + mc: cache.MemCache, } return h } @@ -50,13 +52,22 @@ func (h *Handlers) Ping(w http.ResponseWriter, r *http.Request) { } func (h *Handlers) MainPage(w http.ResponseWriter, r *http.Request) { - h.log.Info("got mainpage request") - // tmpl := template.Must(template.ParseFiles("components/index.html")) tmpl, err := template.ParseGlob("components/*.html") if err != nil { panic(err) } - userScore, err := h.repo.DBUserScoreGet("test") + usernameRaw := r.Context().Value("username") + h.log.Info("got mainpage request", "username", usernameRaw) + if usernameRaw == nil { + tmpl.ExecuteTemplate(w, "main", nil) + return + } + username := usernameRaw.(string) + if username == "" { + tmpl.ExecuteTemplate(w, "main", nil) + return + } + userScore, err := h.repo.DBUserScoreGet(username) if err != nil { h.log.Warn("got db err", "err", err) if err := h.repo.DBUserScoreCreate(&us); err != nil { @@ -65,13 +76,10 @@ func (h *Handlers) MainPage(w http.ResponseWriter, r *http.Request) { tmpl.ExecuteTemplate(w, "main", us) return } - userScore.Actions, err = h.repo.DBActionList("test") + userScore.Actions, err = h.repo.DBActionList(username) if err != nil { panic(err) } - // tmpl.Execute(w, us) - // us.Username = "test" - // us.BurnTime = time.Now().Add(time.Duration(24) * time.Hour) tmpl.ExecuteTemplate(w, "main", userScore) } diff --git a/internal/handlers/middleware.go b/internal/handlers/middleware.go new file mode 100644 index 0000000..28ccdbc --- /dev/null +++ b/internal/handlers/middleware.go @@ -0,0 +1,48 @@ +package handlers + +import ( + "context" + "errors" + "net/http" +) + +func (h *Handlers) GetSession(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + sessionCookie, err := r.Cookie("session_token") + if err != nil { + msg := "auth failed; failed to get session token from cookies" + h.log.Debug(msg, "error", err) + next.ServeHTTP(w, r) + return + } + sessionToken := "" + if sessionCookie.Value == "" { + sessionToken = sessionCookie.Value + } + userSession, err := h.cacheGetSession(sessionCookie.Value) + if err != nil { + msg := "auth failed; session does not exists" + err = errors.New(msg) + h.log.Debug(msg, "error", err) + next.ServeHTTP(w, r) + return + } + if userSession.IsExpired() { + h.mc.RemoveKey(sessionToken) + msg := "session is expired" + h.log.Debug(msg, "error", err, "token", sessionToken) + next.ServeHTTP(w, r) + return + } + ctx := context.WithValue(r.Context(), + "username", userSession.Username) + if err := h.cacheSetSession(sessionToken, + userSession); err != nil { + msg := "failed to marshal user session" + h.log.Warn(msg, "error", err) + next.ServeHTTP(w, r) + return + } + next.ServeHTTP(w, r.WithContext(ctx)) + }) +} -- cgit v1.2.3