package middleware import ( "net/http" "strings" "time" sessionHelper "synlotto-website/internal/helpers/session" "synlotto-website/internal/platform/bootstrap" "synlotto-website/internal/platform/sessionkeys" "github.com/gin-gonic/gin" ) // Tracks idle timeout using LastActivity; redirects on timeout. func AuthMiddleware() gin.HandlerFunc { return func(c *gin.Context) { app := c.MustGet("app").(*bootstrap.App) sm := app.SessionManager ctx := c.Request.Context() if v := sm.Get(ctx, sessionkeys.LastActivity); v != nil { if last, ok := v.(time.Time); ok && time.Since(last) > sm.Lifetime { _ = sm.RenewToken(ctx) sm.Put(ctx, sessionkeys.Flash, "Your session has timed out.") c.Redirect(http.StatusSeeOther, "/account/login") c.Abort() return } } sm.Put(ctx, sessionkeys.LastActivity, time.Now().UTC()) c.Next() } } // Optional remember-me using selector:verifier token pair. func RememberMiddleware(app *bootstrap.App) gin.HandlerFunc { return func(c *gin.Context) { sm := app.SessionManager ctx := c.Request.Context() // Already logged in? Skip. if sm.Exists(ctx, sessionkeys.UserID) { c.Next() return } cookie, err := c.Request.Cookie(app.Config.Session.RememberCookieName) if err != nil { c.Next() return } parts := strings.SplitN(cookie.Value, ":", 2) if len(parts) != 2 { c.Next() return } selector, verifier := parts[0], parts[1] userID, hash, expires, revokedAt, err := sessionHelper.FindToken(app.DB, selector) if err != nil || revokedAt != nil || time.Now().After(expires) { c.Next() return } if sessionHelper.HashVerifier(verifier) != hash { // Tampered token – revoke for safety. _ = sessionHelper.RevokeToken(app.DB, selector) c.Next() return } // Success → create fresh SCS session _ = sm.RenewToken(ctx) sm.Put(ctx, sessionkeys.UserID, userID) sm.Put(ctx, sessionkeys.LastActivity, time.Now().UTC()) c.Next() } } // Blocks anonymous users; redirects to login. func RequireAuth() gin.HandlerFunc { return func(c *gin.Context) { app := c.MustGet("app").(*bootstrap.App) sm := app.SessionManager if sm.GetInt(c.Request.Context(), sessionkeys.UserID) == 0 { c.Redirect(http.StatusSeeOther, "/account/login") c.Abort() return } c.Next() } }