package middleware import ( "strings" "github.com/gin-gonic/gin" "github.com/wmms/wmms/internal/service" "github.com/wmms/wmms/pkg/response" ) const ( AuthorizationHeader = "Authorization" BearerPrefix = "Bearer " UserIDKey = "user_id" UsernameKey = "username" RoleKey = "role" ) // AuthMiddleware validates JWT tokens func AuthMiddleware() gin.HandlerFunc { authSvc := service.NewAuthService() return func(c *gin.Context) { authHeader := c.GetHeader(AuthorizationHeader) if authHeader == "" { response.Unauthorized(c, "missing authorization header") c.Abort() return } if !strings.HasPrefix(authHeader, BearerPrefix) { response.Unauthorized(c, "invalid authorization format") c.Abort() return } tokenString := strings.TrimPrefix(authHeader, BearerPrefix) token, err := authSvc.ValidateToken(tokenString) if err != nil { response.Unauthorized(c, "invalid or expired token") c.Abort() return } // Set user info in context c.Set(UserIDKey, token.UserID) c.Set(UsernameKey, token.Username) c.Set(RoleKey, token.Role) c.Next() } } // AdminOnly middleware restricts access to admin role only func AdminOnly() gin.HandlerFunc { return func(c *gin.Context) { role, exists := c.Get(RoleKey) if !exists { response.Unauthorized(c, "unauthorized") c.Abort() return } if role != "admin" { response.Forbidden(c, "admin access required") c.Abort() return } c.Next() } } // GetCurrentUserID returns the current user's ID from context func GetCurrentUserID(c *gin.Context) int64 { if id, exists := c.Get(UserIDKey); exists { return id.(int64) } return 0 } // GetCurrentUsername returns the current username from context func GetCurrentUsername(c *gin.Context) string { if username, exists := c.Get(UsernameKey); exists { return username.(string) } return "" } // GetCurrentRole returns the current user's role from context func GetCurrentRole(c *gin.Context) string { if role, exists := c.Get(RoleKey); exists { return role.(string) } return "" } // OptionalAuth middleware extracts user info if token is present but doesn't require it func OptionalAuth() gin.HandlerFunc { authSvc := service.NewAuthService() return func(c *gin.Context) { authHeader := c.GetHeader(AuthorizationHeader) if authHeader == "" { c.Next() return } if !strings.HasPrefix(authHeader, BearerPrefix) { c.Next() return } tokenString := strings.TrimPrefix(authHeader, BearerPrefix) token, err := authSvc.ValidateToken(tokenString) if err != nil { c.Next() return } c.Set(UserIDKey, token.UserID) c.Set(UsernameKey, token.Username) c.Set(RoleKey, token.Role) c.Next() } }