package middleware import ( "net/http" "strings" "github.com/gin-gonic/gin" "git.mchus.pro/mchus/quoteforge/internal/models" "git.mchus.pro/mchus/quoteforge/internal/services" ) const ( AuthUserKey = "auth_user" AuthClaimsKey = "auth_claims" ) func Auth(authService *services.AuthService) gin.HandlerFunc { return func(c *gin.Context) { authHeader := c.GetHeader("Authorization") if authHeader == "" { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{ "error": "authorization header required", }) return } parts := strings.SplitN(authHeader, " ", 2) if len(parts) != 2 || parts[0] != "Bearer" { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{ "error": "invalid authorization header format", }) return } claims, err := authService.ValidateToken(parts[1]) if err != nil { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{ "error": err.Error(), }) return } c.Set(AuthClaimsKey, claims) c.Next() } } func RequireRole(roles ...models.UserRole) gin.HandlerFunc { return func(c *gin.Context) { claims, exists := c.Get(AuthClaimsKey) if !exists { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{ "error": "authentication required", }) return } authClaims := claims.(*services.Claims) for _, role := range roles { if authClaims.Role == role { c.Next() return } } c.AbortWithStatusJSON(http.StatusForbidden, gin.H{ "error": "insufficient permissions", }) } } func RequireEditor() gin.HandlerFunc { return RequireRole(models.RoleEditor, models.RolePricingAdmin, models.RoleAdmin) } func RequirePricingAdmin() gin.HandlerFunc { return RequireRole(models.RolePricingAdmin, models.RoleAdmin) } func RequireAdmin() gin.HandlerFunc { return RequireRole(models.RoleAdmin) } // GetClaims extracts auth claims from context func GetClaims(c *gin.Context) *services.Claims { claims, exists := c.Get(AuthClaimsKey) if !exists { return nil } return claims.(*services.Claims) } // GetUserID extracts user ID from context func GetUserID(c *gin.Context) uint { claims := GetClaims(c) if claims == nil { return 0 } return claims.UserID }