73 lines
1.7 KiB
Go
73 lines
1.7 KiB
Go
package middleware
|
|
|
|
import (
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/golang-jwt/jwt/v5"
|
|
)
|
|
|
|
// JWTAuth validates the JWT token in the Authorization header.
|
|
func JWTAuth() gin.HandlerFunc {
|
|
secret := []byte(getEnv("JWT_ACCESS_SECRET", "dev-access-secret"))
|
|
|
|
return func(c *gin.Context) {
|
|
authHeader := c.GetHeader("Authorization")
|
|
if authHeader == "" {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"code": -1, "message": "Missing authorization header"})
|
|
c.Abort()
|
|
return
|
|
}
|
|
|
|
parts := strings.SplitN(authHeader, " ", 2)
|
|
if len(parts) != 2 || parts[0] != "Bearer" {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"code": -1, "message": "Invalid authorization format"})
|
|
c.Abort()
|
|
return
|
|
}
|
|
|
|
token, err := jwt.Parse(parts[1], func(t *jwt.Token) (interface{}, error) {
|
|
return secret, nil
|
|
})
|
|
if err != nil || !token.Valid {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"code": -1, "message": "Invalid token"})
|
|
c.Abort()
|
|
return
|
|
}
|
|
|
|
claims, ok := token.Claims.(jwt.MapClaims)
|
|
if !ok {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"code": -1, "message": "Invalid claims"})
|
|
c.Abort()
|
|
return
|
|
}
|
|
|
|
c.Set("userId", claims["sub"])
|
|
c.Set("role", claims["role"])
|
|
c.Next()
|
|
}
|
|
}
|
|
|
|
// RequireAdmin checks that the authenticated user has an admin role.
|
|
func RequireAdmin() gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
role, _ := c.Get("role")
|
|
roleStr, _ := role.(string)
|
|
if roleStr != "admin" && roleStr != "super_admin" {
|
|
c.JSON(http.StatusForbidden, gin.H{"code": -1, "message": "Admin access required"})
|
|
c.Abort()
|
|
return
|
|
}
|
|
c.Next()
|
|
}
|
|
}
|
|
|
|
func getEnv(key, fallback string) string {
|
|
if v := os.Getenv(key); v != "" {
|
|
return v
|
|
}
|
|
return fallback
|
|
}
|