package handlers import ( "net/http" "github.com/gin-gonic/gin" "github.com/google/uuid" "go.uber.org/zap" "veza-backend-api/internal/core/social" ) // SocialHandler gère les opérations sociales type SocialHandler struct { service social.SocialService commonHandler *CommonHandler } // NewSocialHandler crée une nouvelle instance de SocialHandler func NewSocialHandler(service social.SocialService, logger *zap.Logger) *SocialHandler { return &SocialHandler{ service: service, commonHandler: NewCommonHandler(logger), } } // CreatePostRequest DTO pour la création de post // GO-013: Validation améliorée avec tags go-validator type CreatePostRequest struct { Content string `json:"content" binding:"required,min=1,max=5000"` Attachments map[string]string `json:"attachments"` // track_id, playlist_id (UUID strings) } // CreatePost crée un post // GO-013: Utilise validator centralisé pour validation améliorée // P0: JSON Hardening - Utilise BindAndValidateJSON pour une gestion robuste des erreurs func (h *SocialHandler) CreatePost(c *gin.Context) { userID := c.MustGet("user_id").(uuid.UUID) var req CreatePostRequest if appErr := h.commonHandler.BindAndValidateJSON(c, &req); appErr != nil { RespondWithAppError(c, appErr) return } attachments := make(map[string]uuid.UUID) for k, v := range req.Attachments { if id, err := uuid.Parse(v); err == nil { attachments[k] = id } } post, err := h.service.CreatePost(c.Request.Context(), userID, req.Content, attachments) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create post"}) return } c.JSON(http.StatusCreated, post) } // ToggleLikeRequest DTO pour liker // GO-013: Validation améliorée avec tags go-validator type ToggleLikeRequest struct { TargetID string `json:"target_id" binding:"required,uuid"` TargetType string `json:"target_type" binding:"required,oneof=post track playlist"` } // ToggleLike like ou unlike un objet // GO-013: Utilise validator centralisé pour validation améliorée // P0: JSON Hardening - Utilise BindAndValidateJSON pour une gestion robuste des erreurs func (h *SocialHandler) ToggleLike(c *gin.Context) { userID := c.MustGet("user_id").(uuid.UUID) var req ToggleLikeRequest if appErr := h.commonHandler.BindAndValidateJSON(c, &req); appErr != nil { RespondWithAppError(c, appErr) return } // UUID validation déjà fait par binding tag, mais on garde le parse pour compatibilité targetID, err := uuid.Parse(req.TargetID) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid target_id format"}) return } liked, err := h.service.ToggleLike(c.Request.Context(), userID, targetID, req.TargetType) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to toggle like"}) return } c.JSON(http.StatusOK, gin.H{"liked": liked}) } // AddCommentRequest DTO pour commenter // GO-013: Validation améliorée avec tags go-validator type AddCommentRequest struct { TargetID string `json:"target_id" binding:"required,uuid"` TargetType string `json:"target_type" binding:"required,oneof=post track playlist"` Content string `json:"content" binding:"required,min=1,max=2000"` } // AddComment ajoute un commentaire // GO-013: Utilise validator centralisé pour validation améliorée // P0: JSON Hardening - Utilise BindAndValidateJSON pour une gestion robuste des erreurs func (h *SocialHandler) AddComment(c *gin.Context) { userID := c.MustGet("user_id").(uuid.UUID) var req AddCommentRequest if appErr := h.commonHandler.BindAndValidateJSON(c, &req); appErr != nil { RespondWithAppError(c, appErr) return } // UUID validation déjà fait par binding tag, mais on garde le parse pour compatibilité targetID, err := uuid.Parse(req.TargetID) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid target_id format"}) return } comment, err := h.service.AddComment(c.Request.Context(), userID, targetID, req.TargetType, req.Content) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to add comment"}) return } c.JSON(http.StatusCreated, comment) } // GetFeed récupère le feed global func (h *SocialHandler) GetFeed(c *gin.Context) { feed, err := h.service.GetGlobalFeed(c.Request.Context(), 20, 0) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get feed"}) return } c.JSON(http.StatusOK, feed) }