From 5bc24987446575027dbaa0fb3ce8cd2879edd26e Mon Sep 17 00:00:00 2001 From: senke Date: Wed, 24 Dec 2025 11:41:50 +0100 Subject: [PATCH] [BE-API-027] be-api: Implement user liked tracks endpoint - Standardized GetUserLikedTracks handler to use RespondSuccess/RespondWithAppError - Added limit validation (max 100) - Moved route from setupTrackRoutes to setupUserRoutes in protected group - Handler uses existing TrackLikeService methods - Handler returns paginated results with tracks, total, limit, and offset - Handler uses standard API response format Phase: PHASE-2 Priority: P1 Progress: 34/267 (12.7%) --- VEZA_COMPLETE_MVP_TODOLIST.json | 13 +++++++- veza-backend-api/internal/api/router.go | 31 ++++++++++++++++--- .../internal/core/track/handler.go | 21 +++++++------ 3 files changed, 50 insertions(+), 15 deletions(-) diff --git a/VEZA_COMPLETE_MVP_TODOLIST.json b/VEZA_COMPLETE_MVP_TODOLIST.json index da1f8ff0f..fc8ba198a 100644 --- a/VEZA_COMPLETE_MVP_TODOLIST.json +++ b/VEZA_COMPLETE_MVP_TODOLIST.json @@ -2282,7 +2282,18 @@ "description": "GET /api/v1/users/:id/likes returns all tracks liked by user", "owner": "backend", "estimated_hours": 2, - "status": "todo", + "status": "completed", + "completion": { + "completed_at": "2025-12-23T10:05:30Z", + "actual_hours": 0.5, + "commits": [], + "files_changed": [ + "veza-backend-api/internal/core/track/handler.go", + "veza-backend-api/internal/api/router.go" + ], + "notes": "Standardized GetUserLikedTracks handler to use RespondSuccess and RespondWithAppError. Handler already existed and was working correctly. Added limit validation (max 100). Moved route from setupTrackRoutes to setupUserRoutes in protected group. Handler uses existing TrackLikeService.GetUserLikedTracks and GetUserLikedTracksCount methods. Handler returns paginated results with tracks, total, limit, and offset. Handler uses standard API response format.", + "issues_encountered": [] + }, "files_involved": [], "implementation_steps": [ { diff --git a/veza-backend-api/internal/api/router.go b/veza-backend-api/internal/api/router.go index 7e64ab877..1e2f0011b 100644 --- a/veza-backend-api/internal/api/router.go +++ b/veza-backend-api/internal/api/router.go @@ -414,6 +414,31 @@ func (r *APIRouter) setupUserRoutes(router *gin.RouterGroup) { avatarHandler := handlers.NewAvatarHandler(imageService, userService) protected.POST("/:userId/avatar", avatarHandler.UploadAvatar) // BE-API-021: Upload avatar endpoint protected.DELETE("/:userId/avatar", avatarHandler.DeleteAvatar) // BE-API-022: Delete avatar endpoint + + // BE-API-027: User liked tracks endpoint + // Initialize TrackLikeService and minimal TrackHandler for user liked tracks + uploadDir := r.config.UploadDir + if uploadDir == "" { + uploadDir = "uploads/tracks" + } + likeService := services.NewTrackLikeService(r.db.GormDB, r.logger) + trackService := trackcore.NewTrackService(r.db.GormDB, r.logger, uploadDir) + trackUploadService := services.NewTrackUploadService(r.db.GormDB, r.logger) + var redisClient *redis.Client + if r.config != nil { + redisClient = r.config.RedisClient + } + chunksDir := uploadDir + "/chunks" + chunkService := services.NewTrackChunkService(chunksDir, redisClient, r.logger) + streamService := services.NewStreamService(r.config.StreamServerURL, r.logger) + trackHandlerForLikes := trackcore.NewTrackHandler( + trackService, + trackUploadService, + chunkService, + likeService, + streamService, + ) + protected.GET("/:id/likes", trackHandlerForLikes.GetUserLikedTracks) // BE-API-027: Get user liked tracks endpoint } } } @@ -605,11 +630,7 @@ func (r *APIRouter) setupTrackRoutes(router *gin.RouterGroup) { // Note: Internal routes are now set up in setupInternalRoutes() to avoid // path prefix issues when setupTrackRoutes is called with a RouterGroup - - users := router.Group("/users") - { - users.GET("/:id/likes", trackHandler.GetUserLikedTracks) - } + // BE-API-027: User liked tracks route moved to setupUserRoutes } // setupChatRoutes configure les routes de chat diff --git a/veza-backend-api/internal/core/track/handler.go b/veza-backend-api/internal/core/track/handler.go index a1a9ba188..056f92ea9 100644 --- a/veza-backend-api/internal/core/track/handler.go +++ b/veza-backend-api/internal/core/track/handler.go @@ -1312,18 +1312,18 @@ func (h *TrackHandler) GetTrackLikes(c *gin.Context) { } // GetUserLikedTracks gère la récupération des tracks likés par un utilisateur +// GET /api/v1/users/:id/likes +// BE-API-027: Implement user liked tracks endpoint func (h *TrackHandler) GetUserLikedTracks(c *gin.Context) { userIDStr := c.Param("id") if userIDStr == "" { - // MOD-P2-003: Utiliser AppError au lieu de gin.H - h.respondWithError(c, http.StatusBadRequest, "user id is required") + handlers.RespondWithAppError(c, apperrors.NewValidationError("user id is required")) return } userID, err := uuid.Parse(userIDStr) if err != nil { - // MOD-P2-003: Utiliser AppError au lieu de gin.H - h.respondWithError(c, http.StatusBadRequest, "invalid user id") + handlers.RespondWithAppError(c, apperrors.NewValidationError("invalid user id")) return } @@ -1331,6 +1331,10 @@ func (h *TrackHandler) GetUserLikedTracks(c *gin.Context) { limit := 20 // default if limitStr := c.Query("limit"); limitStr != "" { if parsedLimit, err := strconv.Atoi(limitStr); err == nil && parsedLimit > 0 { + // Limiter à un maximum raisonnable + if parsedLimit > 100 { + parsedLimit = 100 + } limit = parsedLimit } } @@ -1344,19 +1348,18 @@ func (h *TrackHandler) GetUserLikedTracks(c *gin.Context) { tracks, err := h.likeService.GetUserLikedTracks(c.Request.Context(), userID, limit, offset) if err != nil { - // MOD-P2-003: Utiliser AppError au lieu de gin.H - h.respondWithError(c, http.StatusInternalServerError, err.Error()) + handlers.RespondWithAppError(c, apperrors.Wrap(apperrors.ErrCodeInternal, "failed to get user liked tracks", err)) return } total, err := h.likeService.GetUserLikedTracksCount(c.Request.Context(), userID) if err != nil { - // MOD-P2-003: Utiliser AppError au lieu de gin.H - h.respondWithError(c, http.StatusInternalServerError, err.Error()) + handlers.RespondWithAppError(c, apperrors.Wrap(apperrors.ErrCodeInternal, "failed to get user liked tracks count", err)) return } - c.JSON(http.StatusOK, gin.H{ + // BE-API-027: Standardize response format + handlers.RespondSuccess(c, http.StatusOK, gin.H{ "tracks": tracks, "total": total, "limit": limit,