package middleware import ( "net/http" "strings" "time" "sql-platform/config" "sql-platform/internal/model" "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt/v5" ) type Claims struct { UserID int `json:"user_id"` Username string `json:"username"` Role string `json:"role"` jwt.RegisteredClaims } func GenerateToken(user *model.User) (string, error) { claims := Claims{ UserID: user.ID, Username: user.Username, Role: user.Role, RegisteredClaims: jwt.RegisteredClaims{ ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Duration(config.C.JWTExpire) * time.Hour)), IssuedAt: jwt.NewNumericDate(time.Now()), }, } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) return token.SignedString([]byte(config.C.JWTSecret)) } func AuthMiddleware() gin.HandlerFunc { return func(c *gin.Context) { authHeader := c.GetHeader("Authorization") if authHeader == "" { c.JSON(http.StatusUnauthorized, gin.H{"detail": "Not authenticated"}) c.Abort() return } tokenStr := strings.TrimPrefix(authHeader, "Bearer ") if tokenStr == authHeader { c.JSON(http.StatusUnauthorized, gin.H{"detail": "Invalid token format"}) c.Abort() return } claims := &Claims{} token, err := jwt.ParseWithClaims(tokenStr, claims, func(token *jwt.Token) (interface{}, error) { return []byte(config.C.JWTSecret), nil }) if err != nil || !token.Valid { c.JSON(http.StatusUnauthorized, gin.H{"detail": "Invalid or expired token"}) c.Abort() return } c.Set("user_id", claims.UserID) c.Set("username", claims.Username) c.Set("role", claims.Role) c.Next() } } func GetCurrentUser(c *gin.Context) (int, string, string) { return c.GetInt("user_id"), c.GetString("username"), c.GetString("role") } // RBAC middleware — allow specified roles (superadmin is treated as admin) func RequireRole(roles ...string) gin.HandlerFunc { roleSet := make(map[string]bool) for _, r := range roles { roleSet[r] = true } // superadmin inherits all admin privileges roleSet["superadmin"] = true return func(c *gin.Context) { role := c.GetString("role") if !roleSet[role] { c.JSON(http.StatusForbidden, gin.H{"detail": "Permission denied"}) c.Abort() return } c.Next() } }