118 lines
3.2 KiB
Go
118 lines
3.2 KiB
Go
package middleware
|
|
|
|
import (
|
|
"context"
|
|
|
|
"veza-backend-api/internal/response"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
// RoleChecker définit l'interface minimale pour vérifier les rôles et permissions
|
|
// Permet d'utiliser des mocks dans les tests sans modifier la signature publique
|
|
// MIGRATION UUID: Utilise maintenant uuid.UUID au lieu de int64
|
|
type RoleChecker interface {
|
|
HasRole(ctx context.Context, userID uuid.UUID, roleName string) (bool, error)
|
|
HasPermission(ctx context.Context, userID uuid.UUID, resource, action string) (bool, error)
|
|
}
|
|
|
|
// RequireRole crée un middleware qui exige qu'un utilisateur ait un rôle spécifique
|
|
func RequireRole(roleService RoleChecker, roleName string) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
// Récupérer user_id du contexte (doit être défini par AuthMiddleware)
|
|
userIDInterface, exists := c.Get("user_id")
|
|
if !exists {
|
|
response.Unauthorized(c, "unauthorized")
|
|
c.Abort()
|
|
return
|
|
}
|
|
|
|
// Extraire user_id comme uuid.UUID (défini par AuthMiddleware)
|
|
// MIGRATION UUID: Support uuid.UUID directement, plus de conversion en int64
|
|
var userID uuid.UUID
|
|
switch v := userIDInterface.(type) {
|
|
case uuid.UUID:
|
|
userID = v
|
|
case string:
|
|
// Support legacy: si c'est une string, essayer de la parser en UUID
|
|
parsed, err := uuid.Parse(v)
|
|
if err != nil {
|
|
response.Unauthorized(c, "invalid user id format")
|
|
c.Abort()
|
|
return
|
|
}
|
|
userID = parsed
|
|
default:
|
|
response.Unauthorized(c, "invalid user id type")
|
|
c.Abort()
|
|
return
|
|
}
|
|
|
|
// Vérifier si l'utilisateur a le rôle requis
|
|
hasRole, err := roleService.HasRole(c.Request.Context(), userID, roleName)
|
|
if err != nil {
|
|
response.InternalServerError(c, "failed to check role")
|
|
c.Abort()
|
|
return
|
|
}
|
|
|
|
if !hasRole {
|
|
response.Forbidden(c, "insufficient permissions")
|
|
c.Abort()
|
|
return
|
|
}
|
|
|
|
c.Next()
|
|
}
|
|
}
|
|
|
|
// RequirePermission crée un middleware qui exige qu'un utilisateur ait une permission spécifique
|
|
func RequirePermission(roleService RoleChecker, resource, action string) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
// Récupérer user_id du contexte (doit être défini par AuthMiddleware)
|
|
userIDInterface, exists := c.Get("user_id")
|
|
if !exists {
|
|
response.Unauthorized(c, "unauthorized")
|
|
c.Abort()
|
|
return
|
|
}
|
|
|
|
// Extraire user_id comme uuid.UUID (défini par AuthMiddleware)
|
|
// MIGRATION UUID: Support uuid.UUID directement, plus de conversion en int64
|
|
var userID uuid.UUID
|
|
switch v := userIDInterface.(type) {
|
|
case uuid.UUID:
|
|
userID = v
|
|
case string:
|
|
// Support legacy: si c'est une string, essayer de la parser en UUID
|
|
parsed, err := uuid.Parse(v)
|
|
if err != nil {
|
|
response.Unauthorized(c, "invalid user id format")
|
|
c.Abort()
|
|
return
|
|
}
|
|
userID = parsed
|
|
default:
|
|
response.Unauthorized(c, "invalid user id type")
|
|
c.Abort()
|
|
return
|
|
}
|
|
|
|
// Vérifier si l'utilisateur a la permission requise
|
|
hasPermission, err := roleService.HasPermission(c.Request.Context(), userID, resource, action)
|
|
if err != nil {
|
|
response.InternalServerError(c, "failed to check permission")
|
|
c.Abort()
|
|
return
|
|
}
|
|
|
|
if !hasPermission {
|
|
response.Forbidden(c, "insufficient permissions")
|
|
c.Abort()
|
|
return
|
|
}
|
|
|
|
c.Next()
|
|
}
|
|
}
|