package middlewares import ( "net/http" "strings" configs "goGin/config" "goGin/app/services" "github.com/gin-gonic/gin" "log" ) const authClaimsKey = "auth_claims" func RequireAuth(c *gin.Context) { authHeader := strings.TrimSpace(c.GetHeader("Authorization")) if authHeader == "" { authLogf("auth: missing Authorization header path=%s", c.Request.URL.Path) c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "authorization header is required"}) return } parts := strings.SplitN(authHeader, " ", 2) if len(parts) != 2 || !strings.EqualFold(parts[0], "Bearer") || strings.TrimSpace(parts[1]) == "" { authLogf("auth: invalid authorization format path=%s header=%s", c.Request.URL.Path, authHeader) c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "invalid authorization format, expected: Bearer "}) return } jwtService := services.NewJWTService() claims, err := jwtService.ValidateToken(strings.TrimSpace(parts[1])) if err != nil { authLogf("auth: invalid token path=%s error=%v", c.Request.URL.Path, err) c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "invalid token"}) return } if claims.TokenType != services.TokenTypeAccess { authLogf("auth: non-access token used path=%s token_type=%s", c.Request.URL.Path, claims.TokenType) c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "access token required"}) return } c.Set(authClaimsKey, claims) c.Next() } func RequireAdmin(c *gin.Context) { claims, ok := GetAuthClaims(c) if !ok { authLogf("auth: RequireAdmin missing claims path=%s", c.Request.URL.Path) c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"}) return } if !claims.IsAdmin { authLogf("auth: RequireAdmin forbidden path=%s user_id=%v", c.Request.URL.Path, claims.UserID) c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"error": "admin role required"}) return } c.Next() } func RequireNormalUser(c *gin.Context) { claims, ok := GetAuthClaims(c) if !ok { authLogf("auth: RequireNormalUser missing claims path=%s", c.Request.URL.Path) c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"}) return } if claims.IsAdmin { authLogf("auth: RequireNormalUser forbidden (admin tried to access) path=%s user_id=%v", c.Request.URL.Path, claims.UserID) c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"error": "only normal users can access this endpoint"}) return } c.Next() } func GetAuthClaims(c *gin.Context) (*services.JWTClaim, bool) { raw, exists := c.Get(authClaimsKey) if !exists { return nil, false } claims, ok := raw.(*services.JWTClaim) return claims, ok } func authLogf(format string, args ...interface{}) { if configs.AppConfig != nil && configs.AppConfig.Debug { log.Printf(format, args...) } }