package auth import ( "context" "net/http" "github.com/gin-gonic/gin" "github.com/google/uuid" "github.com/mattnite/forgejo-tickets/internal/models" ) const userContextKey = "user" type requestContextKey string const userRequestContextKey requestContextKey = "user" func (s *Service) SessionMiddleware(c *gin.Context) { session, err := s.store.Get(c.Request, sessionCookieName) if err != nil || session.IsNew { c.Next() return } userIDStr, ok := session.Values["user_id"].(string) if !ok { c.Next() return } userID, err := uuid.Parse(userIDStr) if err != nil { c.Next() return } var user models.User if err := s.db.First(&user, "id = ?", userID).Error; err != nil { c.Next() return } c.Set(userContextKey, &user) // Also store on the request context so the template renderer can access it c.Request = c.Request.WithContext(context.WithValue(c.Request.Context(), userRequestContextKey, &user)) c.Next() } func RequireAuth(c *gin.Context) { if CurrentUser(c) == nil { c.Redirect(http.StatusSeeOther, "/login") c.Abort() return } c.Next() } func RequireAdmin(c *gin.Context) { user := CurrentUser(c) if user == nil { c.Redirect(http.StatusSeeOther, "/login") c.Abort() return } if !user.IsAdmin() { c.Redirect(http.StatusSeeOther, "/") c.Abort() return } c.Next() } func CurrentUser(c *gin.Context) *models.User { user, exists := c.Get(userContextKey) if !exists { return nil } u, ok := user.(*models.User) if !ok { return nil } return u } // CurrentUserFromRequest retrieves the current user from the request context. // Used by the template renderer which receives *http.Request instead of *gin.Context. func CurrentUserFromRequest(r *http.Request) *models.User { user, _ := r.Context().Value(userRequestContextKey).(*models.User) return user }