veza/veza-backend-api/internal/api/routes_playlists.go
senke ac182d9f35
Some checks failed
Backend API CI / test-unit (push) Failing after 0s
Backend API CI / test-integration (push) Failing after 0s
Frontend CI / test (push) Failing after 0s
Storybook Audit / Build & audit Storybook (push) Failing after 0s
feat(v0.10.4): Playlists collaboratives - F136, F140, F141, F143, F145
Backend:
- F141: GET /discover/playlists/editorial for editorial playlists
- F143: GET /playlists/shared/:token (public, no auth)
- F145: POST /playlists/import (JSON), GET /playlists/:id/export/m3u
- F136: GET /playlists/favoris (creates Favoris playlist if needed)
- Repo: GetFavorisByUserID, service GetOrCreateFavorisPlaylist

Frontend:
- SharedPlaylistPage at /playlists/shared/:token (public route)
- Editorial playlists section in DiscoverPage
- Export M3U in ExportPlaylistButton dropdown
- Import JSON via ImportPlaylistButton (PlaylistListPage)
- Favoris sidebar link, FavorisRedirectPage, AddToFavorisButton on tracks

Roadmap: v0.10.4 marked DONE
2026-03-09 16:49:05 +01:00

89 lines
4 KiB
Go

package api
import (
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"veza-backend-api/internal/handlers"
"veza-backend-api/internal/repositories"
"veza-backend-api/internal/services"
)
// setupPlaylistRoutes configure les routes pour les playlists
func (r *APIRouter) setupPlaylistRoutes(router *gin.RouterGroup) {
playlistRepo := repositories.NewPlaylistRepository(r.db.GormDB)
playlistTrackRepo := repositories.NewPlaylistTrackRepository(r.db.GormDB)
playlistCollaboratorRepo := repositories.NewPlaylistCollaboratorRepository(r.db.GormDB)
userRepo := repositories.NewGormUserRepository(r.db.GormDB)
playlistService := services.NewPlaylistService(
playlistRepo,
playlistTrackRepo,
playlistCollaboratorRepo,
userRepo,
r.logger,
)
playlistShareService := services.NewPlaylistShareService(r.db.GormDB)
playlistService.SetPlaylistShareService(playlistShareService)
playlistFollowService := services.NewPlaylistFollowService(r.db.GormDB, r.logger)
playlistService.SetPlaylistFollowService(playlistFollowService)
playlistHandler := handlers.NewPlaylistHandler(playlistService, r.db.GormDB, r.logger)
playlistHandler.SetPlaylistFollowService(playlistFollowService)
playlistAnalyticsService := services.NewPlaylistAnalyticsService(r.db.GormDB, r.logger)
playlistHandler.SetPlaylistAnalyticsService(playlistAnalyticsService)
playlists := router.Group("/playlists")
// v0.10.4 F143: Public route - no auth required
playlists.GET("/shared/:token", playlistHandler.GetPlaylistByShareToken)
if r.config.AuthMiddleware != nil {
playlists.Use(r.config.AuthMiddleware.RequireAuth())
r.applyCSRFProtection(playlists)
{
playlists.GET("", playlistHandler.GetPlaylists)
playlists.POST("", playlistHandler.CreatePlaylist)
playlists.POST("/import", playlistHandler.ImportPlaylist) // v0.10.4 F145
playlists.GET("/search", playlistHandler.SearchPlaylists)
playlists.GET("/recommendations", playlistHandler.GetRecommendations)
playlists.GET("/favoris", playlistHandler.GetFavorisPlaylist) // v0.10.4 F136
playlists.GET("/:id", playlistHandler.GetPlaylist)
playlists.GET("/:id/analytics", playlistHandler.GetPlaylistStats)
playlistOwnerResolver := func(c *gin.Context) (uuid.UUID, error) {
playlistIDStr := c.Param("id")
playlistID, err := uuid.Parse(playlistIDStr)
if err != nil {
return uuid.Nil, err
}
playlist, err := playlistRepo.GetByID(c.Request.Context(), playlistID)
if err != nil {
return uuid.Nil, err
}
return playlist.UserID, nil
}
playlists.PUT("/:id", r.config.AuthMiddleware.RequireOwnershipOrAdmin("playlist", playlistOwnerResolver), playlistHandler.UpdatePlaylist)
playlists.DELETE("/:id", r.config.AuthMiddleware.RequireOwnershipOrAdmin("playlist", playlistOwnerResolver), playlistHandler.DeletePlaylist)
playlists.POST("/:id/tracks", playlistHandler.AddTrack)
playlists.DELETE("/:id/tracks/:track_id", playlistHandler.RemoveTrack)
playlists.PUT("/:id/tracks/reorder", playlistHandler.ReorderTracks)
playlists.POST("/:id/collaborators", r.config.AuthMiddleware.RequireOwnershipOrAdmin("playlist", playlistOwnerResolver), playlistHandler.AddCollaborator)
playlists.GET("/:id/collaborators", playlistHandler.GetCollaborators)
playlists.PUT("/:id/collaborators/:userId", r.config.AuthMiddleware.RequireOwnershipOrAdmin("playlist", playlistOwnerResolver), playlistHandler.UpdateCollaboratorPermission)
playlists.DELETE("/:id/collaborators/:userId", r.config.AuthMiddleware.RequireOwnershipOrAdmin("playlist", playlistOwnerResolver), playlistHandler.RemoveCollaborator)
playlists.POST("/:id/share", r.config.AuthMiddleware.RequireOwnershipOrAdmin("playlist", playlistOwnerResolver), playlistHandler.CreateShareLink)
exportHandler := handlers.NewPlaylistExportHandler(playlistService)
playlists.GET("/:id/export/json", exportHandler.ExportPlaylistJSON)
playlists.GET("/:id/export/csv", exportHandler.ExportPlaylistCSV)
playlists.GET("/:id/export/m3u", exportHandler.ExportPlaylistM3U) // v0.10.4 F145
playlists.POST("/:id/duplicate", playlistHandler.DuplicatePlaylist)
}
}
}