package middleware import ( "context" "veza-backend-api/internal/models" "veza-backend-api/internal/response" "github.com/gin-gonic/gin" "github.com/google/uuid" ) // PlaylistPermissionChecker définit l'interface pour vérifier les permissions de playlist // T0484: Interface pour permettre le mocking dans les tests // MIGRATION UUID: Utilise maintenant uuid.UUID au lieu de int64 type PlaylistPermissionChecker interface { CheckPermission(ctx context.Context, playlistID, userID uuid.UUID, requiredPermission models.PlaylistPermission) (bool, error) } // CheckPlaylistPermission crée un middleware qui vérifie si un utilisateur a une permission spécifique sur une playlist // T0484: Create Playlist Permission Middleware // Le middleware vérifie: // - Si l'utilisateur est le propriétaire (a toutes les permissions) // - Si l'utilisateur est collaborateur avec la permission requise // - Si la playlist est publique et la permission est "read" func CheckPlaylistPermission(playlistService PlaylistPermissionChecker, requiredPermission models.PlaylistPermission) 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 } // Extraire playlistID depuis les paramètres de la route // MIGRATION UUID: Parse playlistID comme UUID au lieu de int64 playlistIDStr := c.Param("id") if playlistIDStr == "" { response.BadRequest(c, "playlist id is required") c.Abort() return } playlistID, err := uuid.Parse(playlistIDStr) if err != nil { response.BadRequest(c, "invalid playlist id format (expected UUID)") c.Abort() return } // Vérifier la permission via le service hasPermission, err := playlistService.CheckPermission(c.Request.Context(), playlistID, userID, requiredPermission) if err != nil { // Si la playlist n'existe pas, retourner 404 if err.Error() == "playlist not found" { response.NotFound(c, "playlist not found") c.Abort() return } response.InternalServerError(c, "failed to check permission") c.Abort() return } if !hasPermission { response.Forbidden(c, "forbidden") c.Abort() return } // Permission accordée, continuer c.Next() } } // RequirePlaylistOwner crée un middleware qui exige que l'utilisateur soit le propriétaire de la playlist // T0484: Helper pour vérifier l'ownership func RequirePlaylistOwner(playlistService PlaylistPermissionChecker) gin.HandlerFunc { return CheckPlaylistPermission(playlistService, models.PlaylistPermissionAdmin) } // RequirePlaylistWrite crée un middleware qui exige que l'utilisateur ait la permission write ou admin // T0484: Helper pour vérifier la permission d'écriture func RequirePlaylistWrite(playlistService PlaylistPermissionChecker) gin.HandlerFunc { return CheckPlaylistPermission(playlistService, models.PlaylistPermissionWrite) } // RequirePlaylistRead crée un middleware qui exige que l'utilisateur ait la permission read, write ou admin // T0484: Helper pour vérifier la permission de lecture func RequirePlaylistRead(playlistService PlaylistPermissionChecker) gin.HandlerFunc { return CheckPlaylistPermission(playlistService, models.PlaylistPermissionRead) }