package middleware import ( "net/http" "strings" "time" "game-admin/internal/config" "game-admin/internal/models" "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt/v5" ) type Claims struct { UserID int64 `json:"user_id"` Email string `json:"email"` Username string `json:"username"` Role models.Role `json:"role"` jwt.RegisteredClaims } func GenerateToken(user *models.User, cfg *config.Config) (string, error) { claims := Claims{ UserID: user.ID, Email: user.Email, Username: user.Username, Role: user.Role, RegisteredClaims: jwt.RegisteredClaims{ ExpiresAt: jwt.NewNumericDate(time.Now().Add(72 * time.Hour)), IssuedAt: jwt.NewNumericDate(time.Now()), }, } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) return token.SignedString([]byte(cfg.JWTSecret)) } func AuthRequired(cfg *config.Config) gin.HandlerFunc { return func(c *gin.Context) { header := c.GetHeader("Authorization") if header == "" { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Authorization header required"}) return } parts := strings.SplitN(header, " ", 2) if len(parts) != 2 || parts[0] != "Bearer" { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Invalid authorization format"}) return } claims := &Claims{} token, err := jwt.ParseWithClaims(parts[1], claims, func(t *jwt.Token) (interface{}, error) { return []byte(cfg.JWTSecret), nil }) if err != nil || !token.Valid { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Invalid or expired token"}) return } c.Set("user_id", claims.UserID) c.Set("user_email", claims.Email) c.Set("user_role", claims.Role) c.Set("username", claims.Username) c.Next() } } func RoleRequired(roles ...models.Role) gin.HandlerFunc { return func(c *gin.Context) { role, _ := c.Get("user_role") userRole := role.(models.Role) for _, r := range roles { if userRole == r { c.Next() return } } c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"error": "Insufficient permissions"}) } }