// Package handlers provides HTTP request handlers for the API. package handlers import ( "net/http" "strings" "github.com/gin-gonic/gin" "github.com/imc/backend/internal/auth" ) // AuthContextKey is the key used to store auth context in gin.Context. const AuthContextKey = "auth" // AuthMiddleware validates JWT tokens and sets up the auth context. // Returns 401 if the token is missing, invalid, or expired. func AuthMiddleware(jwtManager *auth.JWTManager) gin.HandlerFunc { return func(c *gin.Context) { authHeader := c.GetHeader("Authorization") if authHeader == "" { c.AbortWithStatusJSON(http.StatusUnauthorized, Response{Error: "authorization header required"}) return } parts := strings.SplitN(authHeader, " ", 2) if len(parts) != 2 || strings.ToLower(parts[0]) != "bearer" { c.AbortWithStatusJSON(http.StatusUnauthorized, Response{Error: "invalid authorization header format"}) return } claims, err := jwtManager.ValidateToken(parts[1]) if err != nil { c.AbortWithStatusJSON(http.StatusUnauthorized, Response{Error: "invalid token"}) return } authCtx := &auth.Context{ UserID: claims.UserID, Username: claims.Username, Role: auth.Role(claims.Role), } c.Set(AuthContextKey, authCtx) c.Next() } } // GetAuthContext retrieves the auth context from the gin.Context. // Returns nil if the context is not set (auth middleware was not used). func GetAuthContext(c *gin.Context) *auth.Context { if ctx, exists := c.Get(AuthContextKey); exists { if authCtx, ok := ctx.(*auth.Context); ok { return authCtx } } return nil } // RequireAdmin is a middleware that checks if the current user is an admin. // Returns 403 Forbidden if the user is not an admin. func RequireAdmin() gin.HandlerFunc { return func(c *gin.Context) { authCtx := GetAuthContext(c) if authCtx == nil || !authCtx.IsAdmin() { c.AbortWithStatusJSON(http.StatusForbidden, Response{Error: "admin access required"}) return } c.Next() } }