veza/veza-backend-api/internal/handlers/comment_handler.go

250 lines
6.9 KiB
Go

package handlers
import (
"errors"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"go.uber.org/zap"
"veza-backend-api/internal/services"
)
// CommentHandler gère les opérations sur les commentaires de tracks
type CommentHandler struct {
commentService *services.CommentService
commonHandler *CommonHandler
}
// NewCommentHandler crée un nouveau handler de commentaires
func NewCommentHandler(commentService *services.CommentService, logger *zap.Logger) *CommentHandler {
return &CommentHandler{
commentService: commentService,
commonHandler: NewCommonHandler(logger),
}
}
// CreateCommentRequest représente la requête pour créer un commentaire
type CreateCommentRequest struct {
Content string `json:"content" binding:"required,min=1,max=5000"`
ParentID *uuid.UUID `json:"parent_id,omitempty"` // Changed to *uuid.UUID
}
// UpdateCommentRequest représente la requête pour mettre à jour un commentaire
type UpdateCommentRequest struct {
Content string `json:"content" binding:"required,min=1,max=5000"`
}
// CreateComment gère la création d'un commentaire sur un track
func (h *CommentHandler) CreateComment(c *gin.Context) {
userID := c.MustGet("user_id").(uuid.UUID)
if userID == uuid.Nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
return
}
trackIDStr := c.Param("id")
if trackIDStr == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "track id is required"})
return
}
trackID, err := uuid.Parse(trackIDStr) // Changed to uuid.Parse
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid track id"})
return
}
var req CreateCommentRequest
if appErr := h.commonHandler.BindAndValidateJSON(c, &req); appErr != nil {
RespondWithAppError(c, appErr)
return
}
comment, err := h.commentService.CreateComment(c.Request.Context(), trackID, userID, req.Content, 0.0, req.ParentID) // req.ParentID is already *uuid.UUID
if err != nil {
if errors.Is(err, services.ErrTrackNotFound) {
c.JSON(http.StatusNotFound, gin.H{"error": "track not found"})
return
}
if errors.Is(err, services.ErrParentCommentNotFound) {
c.JSON(http.StatusNotFound, gin.H{"error": "parent comment not found"})
return
}
if errors.Is(err, services.ErrParentTrackMismatch) {
c.JSON(http.StatusBadRequest, gin.H{"error": "parent comment does not belong to the same track"})
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusCreated, gin.H{"comment": comment})
}
// GetComments gère la récupération des commentaires d'un track
func (h *CommentHandler) GetComments(c *gin.Context) {
trackIDStr := c.Param("id")
if trackIDStr == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "track id is required"})
return
}
trackID, err := uuid.Parse(trackIDStr) // Changed to uuid.Parse
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid track id"})
return
}
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
limit, _ := strconv.Atoi(c.DefaultQuery("limit", "20"))
if page < 1 {
page = 1
}
if limit < 1 {
limit = 20
}
if limit > 100 {
limit = 100
}
comments, total, err := h.commentService.GetComments(c.Request.Context(), trackID, page, limit)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{
"comments": comments,
"total": total,
"page": page,
"limit": limit,
})
}
// UpdateComment gère la mise à jour d'un commentaire
func (h *CommentHandler) UpdateComment(c *gin.Context) {
userID := c.MustGet("user_id").(uuid.UUID)
if userID == uuid.Nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
return
}
commentIDStr := c.Param("id")
if commentIDStr == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "comment id is required"})
return
}
commentID, err := uuid.Parse(commentIDStr) // Changed to uuid.Parse
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid comment id"})
return
}
var req UpdateCommentRequest
if appErr := h.commonHandler.BindAndValidateJSON(c, &req); appErr != nil {
RespondWithAppError(c, appErr)
return
}
comment, err := h.commentService.UpdateComment(c.Request.Context(), commentID, userID, req.Content)
if err != nil {
if errors.Is(err, services.ErrCommentNotFound) {
c.JSON(http.StatusNotFound, gin.H{"error": "comment not found"})
return
}
if errors.Is(err, services.ErrForbidden) {
c.JSON(http.StatusForbidden, gin.H{"error": "unauthorized: you can only edit your own comments"})
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"comment": comment})
}
// DeleteComment gère la suppression d'un commentaire
func (h *CommentHandler) DeleteComment(c *gin.Context) {
userID := c.MustGet("user_id").(uuid.UUID)
if userID == uuid.Nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
return
}
commentIDStr := c.Param("id")
if commentIDStr == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "comment id is required"})
return
}
commentID, err := uuid.Parse(commentIDStr) // Changed to uuid.Parse
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid comment id"})
return
}
err = h.commentService.DeleteComment(c.Request.Context(), commentID, userID, false) // Added false for isAdmin
if err != nil {
if errors.Is(err, services.ErrCommentNotFound) {
c.JSON(http.StatusNotFound, gin.H{"error": "comment not found"})
return
}
if errors.Is(err, services.ErrForbidden) {
c.JSON(http.StatusForbidden, gin.H{"error": "unauthorized: you can only delete your own comments"})
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"message": "comment deleted successfully"})
}
// GetReplies gère la récupération des réponses d'un commentaire
func (h *CommentHandler) GetReplies(c *gin.Context) {
parentIDStr := c.Param("id")
if parentIDStr == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "parent comment id is required"})
return
}
parentID, err := uuid.Parse(parentIDStr) // Changed to uuid.Parse
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid parent comment id"})
return
}
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
limit, _ := strconv.Atoi(c.DefaultQuery("limit", "20"))
if page < 1 {
page = 1
}
if limit < 1 {
limit = 20
}
if limit > 100 {
limit = 100
}
replies, total, err := h.commentService.GetReplies(c.Request.Context(), parentID, page, limit)
if err != nil {
if errors.Is(err, services.ErrParentCommentNotFound) {
c.JSON(http.StatusNotFound, gin.H{"error": "parent comment not found"})
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{
"replies": replies,
"total": total,
"page": page,
"limit": limit,
})
}