140 lines
4.4 KiB
Go
140 lines
4.4 KiB
Go
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
|
|
}
|
|
|
|
RespondSuccess(c, 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
|
|
}
|
|
|
|
RespondSuccess(c, 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
|
|
}
|
|
|
|
RespondSuccess(c, 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
|
|
}
|
|
RespondSuccess(c, http.StatusOK, feed)
|
|
}
|