v0.9.8 beta
This commit is contained in:
parent
2a4de3ce21
commit
9024fa92a0
18 changed files with 269 additions and 260 deletions
|
|
@ -9,6 +9,7 @@ import (
|
|||
"go.uber.org/zap"
|
||||
"gorm.io/gorm"
|
||||
|
||||
apperrors "veza-backend-api/internal/errors"
|
||||
"veza-backend-api/internal/core/marketplace"
|
||||
)
|
||||
|
||||
|
|
@ -41,7 +42,7 @@ func (h *AdminTransferHandler) GetTransfers(c *gin.Context) {
|
|||
if sellerIDStr := c.Query("seller_id"); sellerIDStr != "" {
|
||||
sellerID, err := uuid.Parse(sellerIDStr)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid seller_id"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("invalid seller_id"))
|
||||
return
|
||||
}
|
||||
query = query.Where("seller_id = ?", sellerID)
|
||||
|
|
@ -56,7 +57,7 @@ func (h *AdminTransferHandler) GetTransfers(c *gin.Context) {
|
|||
var total int64
|
||||
if err := query.Count(&total).Error; err != nil {
|
||||
h.logger.Error("GetTransfers count failed", zap.Error(err))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to count transfers"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to count transfers", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -76,7 +77,7 @@ func (h *AdminTransferHandler) GetTransfers(c *gin.Context) {
|
|||
var transfers []marketplace.SellerTransfer
|
||||
if err := query.Order("created_at DESC").Limit(limit).Offset(offset).Find(&transfers).Error; err != nil {
|
||||
h.logger.Error("GetTransfers find failed", zap.Error(err))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch transfers"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to fetch transfers", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -89,34 +90,34 @@ func (h *AdminTransferHandler) GetTransfers(c *gin.Context) {
|
|||
// RetryTransfer manually retries a failed transfer.
|
||||
func (h *AdminTransferHandler) RetryTransfer(c *gin.Context) {
|
||||
if h.ts == nil {
|
||||
c.JSON(http.StatusServiceUnavailable, gin.H{"error": "Stripe Connect is not enabled"})
|
||||
RespondWithAppError(c, apperrors.NewServiceUnavailableError("Stripe Connect is not enabled"))
|
||||
return
|
||||
}
|
||||
|
||||
idStr := c.Param("id")
|
||||
if idStr == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "transfer id required"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("transfer id required"))
|
||||
return
|
||||
}
|
||||
transferID, err := uuid.Parse(idStr)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid transfer id"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("invalid transfer id"))
|
||||
return
|
||||
}
|
||||
|
||||
var t marketplace.SellerTransfer
|
||||
if err := h.db.First(&t, transferID).Error; err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "transfer not found"})
|
||||
RespondWithAppError(c, apperrors.NewNotFoundError("transfer"))
|
||||
return
|
||||
}
|
||||
h.logger.Error("RetryTransfer find failed", zap.Error(err), zap.String("transfer_id", idStr))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch transfer"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to fetch transfer", err))
|
||||
return
|
||||
}
|
||||
|
||||
if t.Status != "failed" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "only failed transfers can be retried"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("only failed transfers can be retried"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -129,7 +130,7 @@ func (h *AdminTransferHandler) RetryTransfer(c *gin.Context) {
|
|||
h.logger.Error("RetryTransfer save failed", zap.Error(saveErr))
|
||||
}
|
||||
h.logger.Error("RetryTransfer CreateTransfer failed", zap.Error(err), zap.String("transfer_id", idStr))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Transfer failed: " + err.Error()})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Transfer failed", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -137,7 +138,7 @@ func (h *AdminTransferHandler) RetryTransfer(c *gin.Context) {
|
|||
t.ErrorMessage = ""
|
||||
if err := h.db.Save(&t).Error; err != nil {
|
||||
h.logger.Error("RetryTransfer save failed", zap.Error(err))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update transfer"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to update transfer", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ import (
|
|||
"net/http"
|
||||
"path/filepath"
|
||||
|
||||
apperrors "veza-backend-api/internal/errors"
|
||||
"veza-backend-api/internal/services"
|
||||
|
||||
chatws "veza-backend-api/internal/websocket/chat"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
|
@ -55,64 +55,64 @@ func (h *ChatAttachmentHandler) UploadChatAttachment(c *gin.Context) {
|
|||
|
||||
roomID, err := uuid.Parse(c.Param("roomId"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid room ID"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("Invalid room ID"))
|
||||
return
|
||||
}
|
||||
|
||||
if !h.permissions.CanRead(c.Request.Context(), userID, roomID) {
|
||||
c.JSON(http.StatusForbidden, gin.H{"error": "Not allowed to access this conversation"})
|
||||
RespondWithAppError(c, apperrors.NewForbiddenError("Not allowed to access this conversation"))
|
||||
return
|
||||
}
|
||||
|
||||
fileHeader, err := c.FormFile("file")
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "No file provided"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("No file provided"))
|
||||
return
|
||||
}
|
||||
|
||||
if fileHeader.Size > chatAttachmentMaxSize {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "File too large. Max 50MB"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("File too large. Max 50MB"))
|
||||
return
|
||||
}
|
||||
|
||||
if fileHeader.Size == 0 {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Empty file"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("Empty file"))
|
||||
return
|
||||
}
|
||||
|
||||
fileType := h.validator.GetFileTypeFromPath(fileHeader.Filename)
|
||||
if fileType == "unknown" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Unsupported file type. Allowed: mp3, wav, ogg, jpg, png, pdf"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("Unsupported file type. Allowed: mp3, wav, ogg, jpg, png, pdf"))
|
||||
return
|
||||
}
|
||||
|
||||
validationResult, err := h.validator.ValidateFile(c.Request.Context(), fileHeader, fileType)
|
||||
if err != nil {
|
||||
h.logger.Warn("Chat attachment validation failed", zap.Error(err), zap.String("filename", fileHeader.Filename))
|
||||
c.JSON(http.StatusUnprocessableEntity, gin.H{"error": "File validation failed: " + err.Error()})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("File validation failed: "+err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
if !validationResult.Valid {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": validationResult.Error})
|
||||
RespondWithAppError(c, apperrors.NewValidationError(validationResult.Error))
|
||||
return
|
||||
}
|
||||
|
||||
if validationResult.Quarantined {
|
||||
c.JSON(http.StatusUnprocessableEntity, gin.H{"error": "File rejected: virus detected"})
|
||||
RespondWithAppError(c, apperrors.NewForbiddenError("File rejected: virus detected"))
|
||||
return
|
||||
}
|
||||
|
||||
file, err := fileHeader.Open()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to read file"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to read file", err))
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
data, err := io.ReadAll(file)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to read file"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to read file", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -125,7 +125,7 @@ func (h *ChatAttachmentHandler) UploadChatAttachment(c *gin.Context) {
|
|||
_, err = h.s3Service.UploadFile(c.Request.Context(), data, key, fileHeader.Header.Get("Content-Type"))
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to upload chat attachment", zap.Error(err), zap.String("key", key))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to upload file"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to upload file", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -84,12 +84,12 @@ func NewChatHandlerWithInterface(chatService ChatServiceInterfaceForChatHandler,
|
|||
func (h *ChatHandler) GetToken(c *gin.Context) {
|
||||
userIDVal, exists := c.Get("user_id")
|
||||
if !exists {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
|
||||
RespondWithAppError(c, apperrors.NewUnauthorizedError("unauthorized"))
|
||||
return
|
||||
}
|
||||
userID, ok := userIDVal.(uuid.UUID)
|
||||
if !ok || userID == uuid.Nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
|
||||
RespondWithAppError(c, apperrors.NewUnauthorizedError("unauthorized"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -106,7 +106,7 @@ func (h *ChatHandler) GetToken(c *gin.Context) {
|
|||
token, err := h.chatService.GenerateToken(userID, username)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to generate chat token", zap.Error(err))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to generate token"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("failed to generate token", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import (
|
|||
"net/http"
|
||||
"strconv"
|
||||
|
||||
apperrors "veza-backend-api/internal/errors"
|
||||
"veza-backend-api/internal/repositories"
|
||||
|
||||
chatws "veza-backend-api/internal/websocket/chat"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
|
@ -51,18 +51,18 @@ func (h *ChatSearchHandler) SearchMessages(c *gin.Context) {
|
|||
|
||||
roomID, err := uuid.Parse(c.Param("roomId"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid room ID"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("Invalid room ID"))
|
||||
return
|
||||
}
|
||||
|
||||
if !h.permissions.CanRead(c.Request.Context(), userID, roomID) {
|
||||
c.JSON(http.StatusForbidden, gin.H{"error": "Not allowed to access this conversation"})
|
||||
RespondWithAppError(c, apperrors.NewForbiddenError("Not allowed to access this conversation"))
|
||||
return
|
||||
}
|
||||
|
||||
query := c.Query("q")
|
||||
if query == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "query parameter 'q' is required"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("query parameter 'q' is required"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -85,7 +85,7 @@ func (h *ChatSearchHandler) SearchMessages(c *gin.Context) {
|
|||
messages, total, err := h.msgRepo.Search(c.Request.Context(), roomID, query, limit, offset)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to search messages", zap.Error(err))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to search messages"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to search messages", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import (
|
|||
"github.com/google/uuid"
|
||||
"go.uber.org/zap"
|
||||
|
||||
apperrors "veza-backend-api/internal/errors"
|
||||
"veza-backend-api/internal/services"
|
||||
)
|
||||
|
||||
|
|
@ -45,7 +46,7 @@ func (h *CloudHandler) getUserID(c *gin.Context) (uuid.UUID, error) {
|
|||
func (h *CloudHandler) ListFolders(c *gin.Context) {
|
||||
userID, err := h.getUserID(c)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
|
||||
RespondWithAppError(c, apperrors.NewUnauthorizedError("unauthorized"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -53,7 +54,7 @@ func (h *CloudHandler) ListFolders(c *gin.Context) {
|
|||
if pidStr := c.Query("parent_id"); pidStr != "" {
|
||||
pid, err := uuid.Parse(pidStr)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid parent_id"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("invalid parent_id"))
|
||||
return
|
||||
}
|
||||
parentID = &pid
|
||||
|
|
@ -62,7 +63,7 @@ func (h *CloudHandler) ListFolders(c *gin.Context) {
|
|||
folders, err := h.cloudService.ListFolders(c.Request.Context(), userID, parentID)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to list folders", zap.Error(err))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to list folders"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("failed to list folders", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -72,7 +73,7 @@ func (h *CloudHandler) ListFolders(c *gin.Context) {
|
|||
func (h *CloudHandler) CreateFolder(c *gin.Context) {
|
||||
userID, err := h.getUserID(c)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
|
||||
RespondWithAppError(c, apperrors.NewUnauthorizedError("unauthorized"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -81,7 +82,7 @@ func (h *CloudHandler) CreateFolder(c *gin.Context) {
|
|||
ParentID *string `json:"parent_id"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "name is required"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("name is required"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -89,7 +90,7 @@ func (h *CloudHandler) CreateFolder(c *gin.Context) {
|
|||
if req.ParentID != nil && *req.ParentID != "" {
|
||||
pid, err := uuid.Parse(*req.ParentID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid parent_id"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("invalid parent_id"))
|
||||
return
|
||||
}
|
||||
parentID = &pid
|
||||
|
|
@ -98,11 +99,11 @@ func (h *CloudHandler) CreateFolder(c *gin.Context) {
|
|||
folder, err := h.cloudService.CreateFolder(c.Request.Context(), userID, req.Name, parentID)
|
||||
if err != nil {
|
||||
if errors.Is(err, services.ErrFolderNotFound) {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "parent folder not found"})
|
||||
RespondWithAppError(c, apperrors.NewNotFoundError("parent folder"))
|
||||
return
|
||||
}
|
||||
h.logger.Error("Failed to create folder", zap.Error(err))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to create folder"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("failed to create folder", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -112,13 +113,13 @@ func (h *CloudHandler) CreateFolder(c *gin.Context) {
|
|||
func (h *CloudHandler) RenameFolder(c *gin.Context) {
|
||||
userID, err := h.getUserID(c)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
|
||||
RespondWithAppError(c, apperrors.NewUnauthorizedError("unauthorized"))
|
||||
return
|
||||
}
|
||||
|
||||
folderID, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid folder id"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("invalid folder id"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -126,16 +127,16 @@ func (h *CloudHandler) RenameFolder(c *gin.Context) {
|
|||
Name string `json:"name" binding:"required"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "name is required"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("name is required"))
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.cloudService.RenameFolder(c.Request.Context(), userID, folderID, req.Name); err != nil {
|
||||
if errors.Is(err, services.ErrFolderNotFound) {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "folder not found"})
|
||||
RespondWithAppError(c, apperrors.NewNotFoundError("folder"))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to rename folder"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("failed to rename folder", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -145,22 +146,22 @@ func (h *CloudHandler) RenameFolder(c *gin.Context) {
|
|||
func (h *CloudHandler) DeleteFolder(c *gin.Context) {
|
||||
userID, err := h.getUserID(c)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
|
||||
RespondWithAppError(c, apperrors.NewUnauthorizedError("unauthorized"))
|
||||
return
|
||||
}
|
||||
|
||||
folderID, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid folder id"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("invalid folder id"))
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.cloudService.DeleteFolder(c.Request.Context(), userID, folderID); err != nil {
|
||||
if errors.Is(err, services.ErrFolderNotFound) {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "folder not found"})
|
||||
RespondWithAppError(c, apperrors.NewNotFoundError("folder"))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to delete folder"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("failed to delete folder", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -170,7 +171,7 @@ func (h *CloudHandler) DeleteFolder(c *gin.Context) {
|
|||
func (h *CloudHandler) ListFiles(c *gin.Context) {
|
||||
userID, err := h.getUserID(c)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
|
||||
RespondWithAppError(c, apperrors.NewUnauthorizedError("unauthorized"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -178,7 +179,7 @@ func (h *CloudHandler) ListFiles(c *gin.Context) {
|
|||
if fidStr := c.Query("folder_id"); fidStr != "" {
|
||||
fid, err := uuid.Parse(fidStr)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid folder_id"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("invalid folder_id"))
|
||||
return
|
||||
}
|
||||
folderID = &fid
|
||||
|
|
@ -187,7 +188,7 @@ func (h *CloudHandler) ListFiles(c *gin.Context) {
|
|||
files, err := h.cloudService.ListFiles(c.Request.Context(), userID, folderID)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to list files", zap.Error(err))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to list files"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("failed to list files", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -197,20 +198,20 @@ func (h *CloudHandler) ListFiles(c *gin.Context) {
|
|||
func (h *CloudHandler) UploadFile(c *gin.Context) {
|
||||
userID, err := h.getUserID(c)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
|
||||
RespondWithAppError(c, apperrors.NewUnauthorizedError("unauthorized"))
|
||||
return
|
||||
}
|
||||
|
||||
file, header, err := c.Request.FormFile("file")
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "file is required"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("file is required"))
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
data, err := io.ReadAll(file)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to read file"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("failed to read file", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -223,7 +224,7 @@ func (h *CloudHandler) UploadFile(c *gin.Context) {
|
|||
if fidStr := c.PostForm("folder_id"); fidStr != "" {
|
||||
fid, err := uuid.Parse(fidStr)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid folder_id"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("invalid folder_id"))
|
||||
return
|
||||
}
|
||||
folderID = &fid
|
||||
|
|
@ -232,19 +233,19 @@ func (h *CloudHandler) UploadFile(c *gin.Context) {
|
|||
result, err := h.cloudService.UploadFile(c.Request.Context(), userID, folderID, header.Filename, data, mimeType)
|
||||
if err != nil {
|
||||
if errors.Is(err, services.ErrQuotaExceeded) {
|
||||
c.JSON(http.StatusForbidden, gin.H{"error": "storage quota exceeded"})
|
||||
RespondWithAppError(c, apperrors.NewForbiddenError("storage quota exceeded"))
|
||||
return
|
||||
}
|
||||
if errors.Is(err, services.ErrInvalidMimeType) {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid file type"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("invalid file type"))
|
||||
return
|
||||
}
|
||||
if errors.Is(err, services.ErrFileTooLarge) {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "file too large (max 500MB)"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("file too large (max 500MB)"))
|
||||
return
|
||||
}
|
||||
h.logger.Error("Failed to upload file", zap.Error(err))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to upload file"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("failed to upload file", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -254,19 +255,19 @@ func (h *CloudHandler) UploadFile(c *gin.Context) {
|
|||
func (h *CloudHandler) GetFile(c *gin.Context) {
|
||||
userID, err := h.getUserID(c)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
|
||||
RespondWithAppError(c, apperrors.NewUnauthorizedError("unauthorized"))
|
||||
return
|
||||
}
|
||||
|
||||
fileID, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid file id"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("invalid file id"))
|
||||
return
|
||||
}
|
||||
|
||||
file, err := h.cloudService.GetFileByID(c.Request.Context(), userID, fileID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "file not found"})
|
||||
RespondWithAppError(c, apperrors.NewNotFoundError("file"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -276,22 +277,22 @@ func (h *CloudHandler) GetFile(c *gin.Context) {
|
|||
func (h *CloudHandler) DeleteFile(c *gin.Context) {
|
||||
userID, err := h.getUserID(c)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
|
||||
RespondWithAppError(c, apperrors.NewUnauthorizedError("unauthorized"))
|
||||
return
|
||||
}
|
||||
|
||||
fileID, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid file id"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("invalid file id"))
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.cloudService.DeleteFile(c.Request.Context(), userID, fileID); err != nil {
|
||||
if errors.Is(err, services.ErrFileNotFound) {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "file not found"})
|
||||
RespondWithAppError(c, apperrors.NewNotFoundError("file"))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to delete file"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("failed to delete file", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -302,23 +303,23 @@ func (h *CloudHandler) DeleteFile(c *gin.Context) {
|
|||
func (h *CloudHandler) StreamFile(c *gin.Context) {
|
||||
userID, err := h.getUserID(c)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
|
||||
RespondWithAppError(c, apperrors.NewUnauthorizedError("unauthorized"))
|
||||
return
|
||||
}
|
||||
|
||||
fileID, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid file id"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("invalid file id"))
|
||||
return
|
||||
}
|
||||
|
||||
data, file, err := h.cloudService.StreamFile(c.Request.Context(), userID, fileID)
|
||||
if err != nil {
|
||||
if errors.Is(err, services.ErrFileNotFound) {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "file not found"})
|
||||
RespondWithAppError(c, apperrors.NewNotFoundError("file"))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to stream file"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("failed to stream file", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -336,7 +337,7 @@ func (h *CloudHandler) StreamFile(c *gin.Context) {
|
|||
rangeStr := strings.TrimPrefix(rangeHeader, "bytes=")
|
||||
parts := strings.SplitN(rangeStr, "-", 2)
|
||||
if len(parts) != 2 {
|
||||
c.JSON(http.StatusRequestedRangeNotSatisfiable, gin.H{"error": "invalid range"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("invalid range"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -344,7 +345,7 @@ func (h *CloudHandler) StreamFile(c *gin.Context) {
|
|||
if parts[0] != "" {
|
||||
start, err = strconv.ParseInt(parts[0], 10, 64)
|
||||
if err != nil || start < 0 || start >= totalSize {
|
||||
c.JSON(http.StatusRequestedRangeNotSatisfiable, gin.H{"error": "invalid range start"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("invalid range start"))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
@ -359,7 +360,7 @@ func (h *CloudHandler) StreamFile(c *gin.Context) {
|
|||
}
|
||||
|
||||
if start > end {
|
||||
c.JSON(http.StatusRequestedRangeNotSatisfiable, gin.H{"error": "invalid range"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("invalid range"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -372,13 +373,13 @@ func (h *CloudHandler) StreamFile(c *gin.Context) {
|
|||
func (h *CloudHandler) GetQuota(c *gin.Context) {
|
||||
userID, err := h.getUserID(c)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
|
||||
RespondWithAppError(c, apperrors.NewUnauthorizedError("unauthorized"))
|
||||
return
|
||||
}
|
||||
|
||||
quota, err := h.cloudService.GetQuota(c.Request.Context(), userID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to get quota"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("failed to get quota", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -397,24 +398,24 @@ func (h *CloudHandler) GetQuota(c *gin.Context) {
|
|||
func (h *CloudHandler) ListVersions(c *gin.Context) {
|
||||
userID, err := h.getUserID(c)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
|
||||
RespondWithAppError(c, apperrors.NewUnauthorizedError("unauthorized"))
|
||||
return
|
||||
}
|
||||
|
||||
fileID, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid file id"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("invalid file id"))
|
||||
return
|
||||
}
|
||||
|
||||
versions, err := h.cloudService.ListVersions(c.Request.Context(), userID, fileID)
|
||||
if err != nil {
|
||||
if errors.Is(err, services.ErrFileNotFound) {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "file not found"})
|
||||
RespondWithAppError(c, apperrors.NewNotFoundError("file"))
|
||||
return
|
||||
}
|
||||
h.logger.Error("Failed to list versions", zap.Error(err))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to list versions"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("failed to list versions", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -425,30 +426,30 @@ func (h *CloudHandler) ListVersions(c *gin.Context) {
|
|||
func (h *CloudHandler) RestoreVersion(c *gin.Context) {
|
||||
userID, err := h.getUserID(c)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
|
||||
RespondWithAppError(c, apperrors.NewUnauthorizedError("unauthorized"))
|
||||
return
|
||||
}
|
||||
|
||||
fileID, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid file id"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("invalid file id"))
|
||||
return
|
||||
}
|
||||
|
||||
versionStr := c.Param("version")
|
||||
version, err := strconv.Atoi(versionStr)
|
||||
if err != nil || version < 1 {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid version"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("invalid version"))
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.cloudService.RestoreVersion(c.Request.Context(), userID, fileID, version); err != nil {
|
||||
if errors.Is(err, services.ErrFileNotFound) {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "file not found"})
|
||||
RespondWithAppError(c, apperrors.NewNotFoundError("file"))
|
||||
return
|
||||
}
|
||||
h.logger.Error("Failed to restore version", zap.Error(err))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to restore version"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("failed to restore version", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -459,13 +460,13 @@ func (h *CloudHandler) RestoreVersion(c *gin.Context) {
|
|||
func (h *CloudHandler) ShareFile(c *gin.Context) {
|
||||
userID, err := h.getUserID(c)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
|
||||
RespondWithAppError(c, apperrors.NewUnauthorizedError("unauthorized"))
|
||||
return
|
||||
}
|
||||
|
||||
fileID, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid file id"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("invalid file id"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -490,11 +491,11 @@ func (h *CloudHandler) ShareFile(c *gin.Context) {
|
|||
share, err := h.cloudService.ShareFile(c.Request.Context(), userID, fileID, req.Permissions, req.ExpiresInHours)
|
||||
if err != nil {
|
||||
if errors.Is(err, services.ErrFileNotFound) {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "file not found"})
|
||||
RespondWithAppError(c, apperrors.NewNotFoundError("file"))
|
||||
return
|
||||
}
|
||||
h.logger.Error("Failed to share file", zap.Error(err))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to share file"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("failed to share file", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -512,17 +513,17 @@ func (h *CloudHandler) ShareFile(c *gin.Context) {
|
|||
func (h *CloudHandler) GetSharedFile(c *gin.Context) {
|
||||
token := c.Param("token")
|
||||
if token == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "token required"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("token required"))
|
||||
return
|
||||
}
|
||||
|
||||
file, err := h.cloudService.GetSharedFile(c.Request.Context(), token)
|
||||
if err != nil {
|
||||
if errors.Is(err, services.ErrShareExpired) || errors.Is(err, services.ErrShareNotFound) || errors.Is(err, services.ErrFileNotFound) {
|
||||
c.JSON(http.StatusGone, gin.H{"error": "share link expired"})
|
||||
RespondWithAppError(c, apperrors.NewNotFoundError("share link expired"))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "file not found"})
|
||||
RespondWithAppError(c, apperrors.NewNotFoundError("file"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -533,24 +534,24 @@ func (h *CloudHandler) GetSharedFile(c *gin.Context) {
|
|||
func (h *CloudHandler) CreateVersion(c *gin.Context) {
|
||||
userID, err := h.getUserID(c)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
|
||||
RespondWithAppError(c, apperrors.NewUnauthorizedError("unauthorized"))
|
||||
return
|
||||
}
|
||||
|
||||
fileID, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid file id"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("invalid file id"))
|
||||
return
|
||||
}
|
||||
|
||||
version, err := h.cloudService.CreateVersion(c.Request.Context(), userID, fileID)
|
||||
if err != nil {
|
||||
if errors.Is(err, services.ErrFileNotFound) {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "file not found"})
|
||||
RespondWithAppError(c, apperrors.NewNotFoundError("file"))
|
||||
return
|
||||
}
|
||||
h.logger.Error("Failed to create version", zap.Error(err))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to create version"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("failed to create version", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -561,24 +562,24 @@ func (h *CloudHandler) CreateVersion(c *gin.Context) {
|
|||
func (h *CloudHandler) PublishAsTrack(c *gin.Context) {
|
||||
userID, err := h.getUserID(c)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
|
||||
RespondWithAppError(c, apperrors.NewUnauthorizedError("unauthorized"))
|
||||
return
|
||||
}
|
||||
|
||||
fileID, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid file id"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("invalid file id"))
|
||||
return
|
||||
}
|
||||
|
||||
file, err := h.cloudService.GetFileByID(c.Request.Context(), userID, fileID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "file not found"})
|
||||
RespondWithAppError(c, apperrors.NewNotFoundError("file"))
|
||||
return
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(file.MimeType, "audio/") {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "only audio files can be published as tracks"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("only audio files can be published as tracks"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -228,19 +228,19 @@ func (h *CommentHandler) UpdateComment(c *gin.Context) {
|
|||
return // Erreur déjà envoyée par GetUserIDUUID
|
||||
}
|
||||
if userID == uuid.Nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
|
||||
RespondWithAppError(c, apperrors.NewUnauthorizedError("unauthorized"))
|
||||
return
|
||||
}
|
||||
|
||||
commentIDStr := c.Param("id")
|
||||
if commentIDStr == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "comment id is required"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("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"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("invalid comment id"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -256,18 +256,18 @@ func (h *CommentHandler) UpdateComment(c *gin.Context) {
|
|||
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"})
|
||||
RespondWithAppError(c, apperrors.NewNotFoundError("comment"))
|
||||
return
|
||||
}
|
||||
if errors.Is(err, services.ErrForbidden) {
|
||||
c.JSON(http.StatusForbidden, gin.H{"error": "unauthorized: you can only edit your own comments"})
|
||||
RespondWithAppError(c, apperrors.NewForbiddenError("unauthorized: you can only edit your own comments"))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to update comment", err))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"comment": comment})
|
||||
RespondSuccess(c, http.StatusOK, gin.H{"comment": comment})
|
||||
}
|
||||
|
||||
// DeleteComment gère la suppression d'un commentaire
|
||||
|
|
@ -342,13 +342,13 @@ func (h *CommentHandler) DeleteComment(c *gin.Context) {
|
|||
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"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("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"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("invalid parent comment id"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -368,14 +368,14 @@ func (h *CommentHandler) GetReplies(c *gin.Context) {
|
|||
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"})
|
||||
RespondWithAppError(c, apperrors.NewNotFoundError("parent comment"))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to get replies", err))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
RespondSuccess(c, http.StatusOK, gin.H{
|
||||
"replies": replies,
|
||||
"total": total,
|
||||
"page": page,
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
apperrors "veza-backend-api/internal/errors"
|
||||
"veza-backend-api/internal/services"
|
||||
)
|
||||
|
||||
|
|
@ -22,7 +23,7 @@ func NewFeatureFlagHandler(svc *services.FeatureFlagService) *FeatureFlagHandler
|
|||
func (h *FeatureFlagHandler) List(c *gin.Context) {
|
||||
list, err := h.svc.List(c.Request.Context())
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to list feature flags"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to list feature flags", err))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"feature_flags": list})
|
||||
|
|
@ -32,7 +33,7 @@ func (h *FeatureFlagHandler) List(c *gin.Context) {
|
|||
func (h *FeatureFlagHandler) Toggle(c *gin.Context) {
|
||||
name := c.Param("name")
|
||||
if name == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "name is required"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("name is required"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -40,13 +41,13 @@ func (h *FeatureFlagHandler) Toggle(c *gin.Context) {
|
|||
Enabled bool `json:"enabled"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "enabled is required"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("enabled is required"))
|
||||
return
|
||||
}
|
||||
|
||||
flag, err := h.svc.Toggle(c.Request.Context(), name, req.Enabled)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to toggle feature flag", err))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, flag)
|
||||
|
|
|
|||
|
|
@ -330,14 +330,14 @@ func (h *GearHandler) DeleteGear(c *gin.Context) {
|
|||
func (h *GearHandler) ListPublicGear(c *gin.Context) {
|
||||
username := c.Param("id") // route uses :id to match /users/:id/* pattern
|
||||
if username == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "username is required"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("username is required"))
|
||||
return
|
||||
}
|
||||
|
||||
items, err := h.gearService.ListPublicGearByUsername(c.Request.Context(), username)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to list public gear", zap.String("username", username), zap.Error(err))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to list gear"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("failed to list gear", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,13 +5,13 @@ import (
|
|||
"encoding/json"
|
||||
"errors"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
|
||||
apperrors "veza-backend-api/internal/errors"
|
||||
"veza-backend-api/internal/models"
|
||||
"veza-backend-api/internal/services"
|
||||
wsmsg "veza-backend-api/internal/websocket"
|
||||
|
|
@ -97,7 +97,7 @@ func (h *PlaybackWebSocketHandler) WebSocketHandler(c *gin.Context) {
|
|||
return // Erreur déjà envoyée par GetUserIDUUID
|
||||
}
|
||||
if userID == uuid.Nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
|
||||
RespondWithAppError(c, apperrors.NewUnauthorizedError("unauthorized"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ func (h *PresenceHandler) GetPresence(c *gin.Context) {
|
|||
p, err := h.presenceService.GetPresenceForViewer(c.Request.Context(), userID, viewerID)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to get presence", zap.Error(err), zap.String("user_id", userID.String()))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get presence"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to get presence", err))
|
||||
return
|
||||
}
|
||||
if p == nil {
|
||||
|
|
@ -117,7 +117,7 @@ func (h *PresenceHandler) UpdatePresence(c *gin.Context) {
|
|||
|
||||
if err := h.presenceService.UpdatePresenceFull(c.Request.Context(), userID, input); err != nil {
|
||||
h.logger.Error("Failed to update presence", zap.Error(err), zap.String("user_id", userID.String()))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update presence"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to update presence", err))
|
||||
return
|
||||
}
|
||||
RespondSuccess(c, http.StatusOK, gin.H{"message": "Presence updated"})
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ import (
|
|||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
"gorm.io/gorm"
|
||||
|
||||
apperrors "veza-backend-api/internal/errors"
|
||||
)
|
||||
|
||||
// PrivacyOptOut sets the CCPA "Do Not Sell" preference for the authenticated user.
|
||||
|
|
@ -23,7 +25,7 @@ func PrivacyOptOut(db *gorm.DB) gin.HandlerFunc {
|
|||
return func(c *gin.Context) {
|
||||
userID, ok := GetUserIDUUID(c)
|
||||
if !ok || userID == uuid.Nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "Authentication required"})
|
||||
RespondWithAppError(c, apperrors.NewUnauthorizedError("Authentication required"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -38,7 +40,7 @@ func PrivacyOptOut(db *gorm.DB) gin.HandlerFunc {
|
|||
`, userID)
|
||||
|
||||
if result.Error != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save privacy preference"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to save privacy preference", result.Error))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import (
|
|||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
|
||||
apperrors "veza-backend-api/internal/errors"
|
||||
"veza-backend-api/internal/services"
|
||||
)
|
||||
|
||||
|
|
@ -32,7 +33,7 @@ func (h *ReportHandler) ListReports(c *gin.Context) {
|
|||
Offset: offset,
|
||||
})
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to list reports"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to list reports", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -51,24 +52,24 @@ func (h *ReportHandler) ResolveReport(c *gin.Context) {
|
|||
reportIDStr := c.Param("id")
|
||||
reportID, err := uuid.Parse(reportIDStr)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid report ID"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("Invalid report ID"))
|
||||
return
|
||||
}
|
||||
|
||||
userID, ok := GetUserIDUUID(c)
|
||||
if !ok || userID == uuid.Nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "Authentication required"})
|
||||
RespondWithAppError(c, apperrors.NewUnauthorizedError("Authentication required"))
|
||||
return
|
||||
}
|
||||
|
||||
var req services.ResolveReportRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "action is required"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("action is required"))
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.reportService.Resolve(c.Request.Context(), reportID, userID, req.Action); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to resolve report", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -79,19 +80,19 @@ func (h *ReportHandler) ResolveReport(c *gin.Context) {
|
|||
func (h *ReportHandler) CreateReport(c *gin.Context) {
|
||||
userID, ok := GetUserIDUUID(c)
|
||||
if !ok || userID == uuid.Nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "Authentication required"})
|
||||
RespondWithAppError(c, apperrors.NewUnauthorizedError("Authentication required"))
|
||||
return
|
||||
}
|
||||
|
||||
var req services.CreateReportRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "content_type and reason are required"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("content_type and reason are required"))
|
||||
return
|
||||
}
|
||||
|
||||
report, err := h.reportService.Create(c.Request.Context(), userID, req)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create report"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to create report", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,14 +54,14 @@ func (h *RoomHandler) CreateRoom(c *gin.Context) {
|
|||
// Récupérer l'ID utilisateur du contexte
|
||||
userIDInterface, exists := c.Get("user_id")
|
||||
if !exists {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "User not authenticated"})
|
||||
RespondWithAppError(c, apperrors.NewUnauthorizedError("User not authenticated"))
|
||||
return
|
||||
}
|
||||
|
||||
// Convertir userID en uuid.UUID
|
||||
userID, ok := userIDInterface.(uuid.UUID)
|
||||
if !ok {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Invalid user ID type in context"})
|
||||
RespondWithAppError(c, apperrors.NewInternalError("Invalid user ID type in context"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -84,7 +84,7 @@ func (h *RoomHandler) CreateRoom(c *gin.Context) {
|
|||
zap.Error(err),
|
||||
zap.String("user_id", userID.String()),
|
||||
zap.String("room_name", req.Name))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create conversation"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to create conversation", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -102,14 +102,14 @@ func (h *RoomHandler) GetUserRooms(c *gin.Context) {
|
|||
// Récupérer l'ID utilisateur du contexte
|
||||
userIDInterface, exists := c.Get("user_id")
|
||||
if !exists {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "User not authenticated"})
|
||||
RespondWithAppError(c, apperrors.NewUnauthorizedError("User not authenticated"))
|
||||
return
|
||||
}
|
||||
|
||||
// Convertir userID en uuid.UUID
|
||||
userID, ok := userIDInterface.(uuid.UUID)
|
||||
if !ok {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Invalid user ID type in context"})
|
||||
RespondWithAppError(c, apperrors.NewInternalError("Invalid user ID type in context"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -119,7 +119,7 @@ func (h *RoomHandler) GetUserRooms(c *gin.Context) {
|
|||
h.logger.Error("failed to get user rooms",
|
||||
zap.Error(err),
|
||||
zap.String("user_id", userID.String()))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch conversations"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to fetch conversations", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -136,7 +136,7 @@ func (h *RoomHandler) GetRoom(c *gin.Context) {
|
|||
roomIDStr := c.Param("id")
|
||||
roomID, err := uuid.Parse(roomIDStr)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid room ID"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("Invalid room ID"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -144,13 +144,13 @@ func (h *RoomHandler) GetRoom(c *gin.Context) {
|
|||
room, err := h.roomService.GetRoom(c.Request.Context(), roomID)
|
||||
if err != nil {
|
||||
if errors.Is(err, services.ErrRoomNotFound) {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "Conversation not found"})
|
||||
RespondWithAppError(c, apperrors.NewNotFoundError("Conversation"))
|
||||
return
|
||||
}
|
||||
h.logger.Error("failed to get room",
|
||||
zap.Error(err),
|
||||
zap.String("room_id", roomID.String()))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get conversation"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to get conversation", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -221,7 +221,7 @@ func (h *RoomHandler) AddMember(c *gin.Context) {
|
|||
roomIDStr := c.Param("id")
|
||||
roomID, err := uuid.Parse(roomIDStr)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid room ID"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("Invalid room ID"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -238,7 +238,7 @@ func (h *RoomHandler) AddMember(c *gin.Context) {
|
|||
zap.Error(err),
|
||||
zap.String("room_id", roomID.String()),
|
||||
zap.String("user_id", req.UserID.String()))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to add member"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to add member", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -256,7 +256,7 @@ func (h *RoomHandler) GetRoomHistory(c *gin.Context) {
|
|||
conversationIDStr := c.Param("id")
|
||||
conversationID, err := uuid.Parse(conversationIDStr)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid conversation ID"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("Invalid conversation ID"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -274,13 +274,13 @@ func (h *RoomHandler) GetRoomHistory(c *gin.Context) {
|
|||
result, err := h.roomService.GetRoomHistoryWithCursor(c.Request.Context(), conversationID, limitInt, cursor)
|
||||
if err != nil {
|
||||
if errors.Is(err, services.ErrRoomNotFound) {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "Conversation not found"})
|
||||
RespondWithAppError(c, apperrors.NewNotFoundError("Conversation"))
|
||||
return
|
||||
}
|
||||
h.logger.Error("failed to get room history",
|
||||
zap.Error(err),
|
||||
zap.String("conversation_id", conversationID.String()))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get conversation history"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to get conversation history", err))
|
||||
return
|
||||
}
|
||||
resp := gin.H{"messages": result.Messages}
|
||||
|
|
@ -300,13 +300,13 @@ func (h *RoomHandler) GetRoomHistory(c *gin.Context) {
|
|||
messages, err := h.roomService.GetRoomHistory(c.Request.Context(), conversationID, limitInt, offsetInt)
|
||||
if err != nil {
|
||||
if errors.Is(err, services.ErrRoomNotFound) {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "Conversation not found"})
|
||||
RespondWithAppError(c, apperrors.NewNotFoundError("Conversation"))
|
||||
return
|
||||
}
|
||||
h.logger.Error("failed to get room history",
|
||||
zap.Error(err),
|
||||
zap.String("conversation_id", conversationID.String()))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get conversation history"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to get conversation history", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -446,21 +446,21 @@ func (h *RoomHandler) CreateInvitation(c *gin.Context) {
|
|||
}
|
||||
roomID, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid room ID"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("Invalid room ID"))
|
||||
return
|
||||
}
|
||||
resp, err := h.roomService.CreateInvitation(c.Request.Context(), roomID, userID)
|
||||
if err != nil {
|
||||
if err.Error() == "forbidden: only owner or admin can create invitations" {
|
||||
c.JSON(http.StatusForbidden, gin.H{"error": err.Error()})
|
||||
RespondWithAppError(c, apperrors.NewForbiddenError(err.Error()))
|
||||
return
|
||||
}
|
||||
if errors.Is(err, services.ErrRoomNotFound) {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "Conversation not found"})
|
||||
RespondWithAppError(c, apperrors.NewNotFoundError("Conversation"))
|
||||
return
|
||||
}
|
||||
h.logger.Error("failed to create invitation", zap.Error(err), zap.String("room_id", roomID.String()))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create invitation"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to create invitation", err))
|
||||
return
|
||||
}
|
||||
RespondSuccess(c, http.StatusCreated, resp)
|
||||
|
|
@ -475,17 +475,17 @@ func (h *RoomHandler) JoinByToken(c *gin.Context) {
|
|||
}
|
||||
token, err := uuid.Parse(c.Param("token"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid token"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("Invalid token"))
|
||||
return
|
||||
}
|
||||
roomID, err := h.roomService.JoinByToken(c.Request.Context(), token, userID)
|
||||
if err != nil {
|
||||
if err.Error() == "invitation not found or expired" {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
|
||||
RespondWithAppError(c, apperrors.NewNotFoundError(err.Error()))
|
||||
return
|
||||
}
|
||||
h.logger.Error("failed to join via token", zap.Error(err), zap.String("token", token.String()))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to join"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to join", err))
|
||||
return
|
||||
}
|
||||
RespondSuccess(c, http.StatusOK, gin.H{"room_id": roomID})
|
||||
|
|
@ -500,25 +500,25 @@ func (h *RoomHandler) KickMember(c *gin.Context) {
|
|||
}
|
||||
roomID, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid room ID"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("Invalid room ID"))
|
||||
return
|
||||
}
|
||||
targetUserID, err := uuid.Parse(c.Param("userId"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user ID"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("Invalid user ID"))
|
||||
return
|
||||
}
|
||||
if err := h.roomService.KickMember(c.Request.Context(), roomID, targetUserID, requestUserID); err != nil {
|
||||
if err.Error() == "forbidden: only owner or admin can remove members" {
|
||||
c.JSON(http.StatusForbidden, gin.H{"error": err.Error()})
|
||||
RespondWithAppError(c, apperrors.NewForbiddenError(err.Error()))
|
||||
return
|
||||
}
|
||||
if errors.Is(err, services.ErrRoomNotFound) {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "Conversation not found"})
|
||||
RespondWithAppError(c, apperrors.NewNotFoundError("Conversation"))
|
||||
return
|
||||
}
|
||||
h.logger.Error("failed to kick member", zap.Error(err), zap.String("room_id", roomID.String()))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to remove member"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to remove member", err))
|
||||
return
|
||||
}
|
||||
RespondSuccess(c, http.StatusOK, gin.H{"message": "Member removed successfully"})
|
||||
|
|
@ -533,19 +533,19 @@ func (h *RoomHandler) LeaveRoom(c *gin.Context) {
|
|||
}
|
||||
roomID, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid conversation ID"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("Invalid conversation ID"))
|
||||
return
|
||||
}
|
||||
if err := h.roomService.RemoveMember(c.Request.Context(), roomID, userID); err != nil {
|
||||
if errors.Is(err, services.ErrRoomNotFound) {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "Conversation not found"})
|
||||
RespondWithAppError(c, apperrors.NewNotFoundError("Conversation"))
|
||||
return
|
||||
}
|
||||
h.logger.Error("failed to leave room",
|
||||
zap.Error(err),
|
||||
zap.String("room_id", roomID.String()),
|
||||
zap.String("user_id", userID.String()))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to leave conversation"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to leave conversation", err))
|
||||
return
|
||||
}
|
||||
h.logger.Info("user left room",
|
||||
|
|
@ -563,12 +563,12 @@ func (h *RoomHandler) UpdateMemberRole(c *gin.Context) {
|
|||
}
|
||||
roomID, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid conversation ID"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("Invalid conversation ID"))
|
||||
return
|
||||
}
|
||||
targetUserID, err := uuid.Parse(c.Param("userId"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user ID"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("Invalid user ID"))
|
||||
return
|
||||
}
|
||||
var req services.UpdateMemberRoleRequest
|
||||
|
|
@ -581,15 +581,15 @@ func (h *RoomHandler) UpdateMemberRole(c *gin.Context) {
|
|||
err.Error() == "forbidden: cannot change owner role" ||
|
||||
err.Error() == "forbidden: owner cannot change their own role" ||
|
||||
err.Error() == "forbidden: cannot promote to owner via this endpoint" {
|
||||
c.JSON(http.StatusForbidden, gin.H{"error": err.Error()})
|
||||
RespondWithAppError(c, apperrors.NewForbiddenError(err.Error()))
|
||||
return
|
||||
}
|
||||
if errors.Is(err, services.ErrRoomNotFound) {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "Conversation or member not found"})
|
||||
RespondWithAppError(c, apperrors.NewNotFoundError("Conversation or member"))
|
||||
return
|
||||
}
|
||||
h.logger.Error("failed to update member role", zap.Error(err))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update member role"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to update member role", err))
|
||||
return
|
||||
}
|
||||
RespondSuccess(c, http.StatusOK, gin.H{"message": "Member role updated successfully"})
|
||||
|
|
@ -605,17 +605,17 @@ func (h *RoomHandler) GetMembers(c *gin.Context) {
|
|||
roomIDStr := c.Param("id")
|
||||
roomID, err := uuid.Parse(roomIDStr)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid room ID"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("Invalid room ID"))
|
||||
return
|
||||
}
|
||||
resp, err := h.roomService.GetRoomMembers(c.Request.Context(), roomID, userID)
|
||||
if err != nil {
|
||||
if errors.Is(err, services.ErrRoomNotFound) {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "Conversation not found"})
|
||||
RespondWithAppError(c, apperrors.NewNotFoundError("Conversation"))
|
||||
return
|
||||
}
|
||||
h.logger.Error("failed to get room members", zap.Error(err), zap.String("room_id", roomID.String()))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get members"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to get members", err))
|
||||
return
|
||||
}
|
||||
RespondSuccess(c, http.StatusOK, resp)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import (
|
|||
"errors"
|
||||
"net/http"
|
||||
|
||||
apperrors "veza-backend-api/internal/errors"
|
||||
"veza-backend-api/internal/core/marketplace"
|
||||
"veza-backend-api/internal/services"
|
||||
|
||||
|
|
@ -37,7 +38,7 @@ type ConnectOnboardRequest struct {
|
|||
// ConnectOnboard starts Stripe Connect onboarding and returns the onboarding URL
|
||||
func (h *SellHandler) ConnectOnboard(c *gin.Context) {
|
||||
if h.stripeConnect == nil {
|
||||
c.JSON(http.StatusServiceUnavailable, gin.H{"error": "Stripe Connect is not enabled"})
|
||||
RespondWithAppError(c, apperrors.NewServiceUnavailableError("Stripe Connect is not enabled"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -60,11 +61,11 @@ func (h *SellHandler) ConnectOnboard(c *gin.Context) {
|
|||
url, err := h.stripeConnect.CreateOnboardingLink(c.Request.Context(), userID, returnURL, refreshURL)
|
||||
if err != nil {
|
||||
if errors.Is(err, services.ErrStripeConnectDisabled) {
|
||||
c.JSON(http.StatusServiceUnavailable, gin.H{"error": "Stripe Connect is not enabled"})
|
||||
RespondWithAppError(c, apperrors.NewServiceUnavailableError("Stripe Connect is not enabled"))
|
||||
return
|
||||
}
|
||||
h.logger.Error("CreateOnboardingLink failed", zap.Error(err), zap.String("user_id", userID.String()))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create onboarding link"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to create onboarding link", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -74,7 +75,7 @@ func (h *SellHandler) ConnectOnboard(c *gin.Context) {
|
|||
// ConnectCallback syncs account status after Stripe redirect (called by frontend after return)
|
||||
func (h *SellHandler) ConnectCallback(c *gin.Context) {
|
||||
if h.stripeConnect == nil {
|
||||
c.JSON(http.StatusServiceUnavailable, gin.H{"error": "Stripe Connect is not enabled"})
|
||||
RespondWithAppError(c, apperrors.NewServiceUnavailableError("Stripe Connect is not enabled"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -85,15 +86,15 @@ func (h *SellHandler) ConnectCallback(c *gin.Context) {
|
|||
|
||||
if err := h.stripeConnect.HandleOnboardingCallback(c.Request.Context(), userID); err != nil {
|
||||
if errors.Is(err, services.ErrNoStripeAccount) {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "No Stripe account found"})
|
||||
RespondWithAppError(c, apperrors.NewNotFoundError("Stripe account"))
|
||||
return
|
||||
}
|
||||
if errors.Is(err, services.ErrStripeConnectDisabled) {
|
||||
c.JSON(http.StatusServiceUnavailable, gin.H{"error": "Stripe Connect is not enabled"})
|
||||
RespondWithAppError(c, apperrors.NewServiceUnavailableError("Stripe Connect is not enabled"))
|
||||
return
|
||||
}
|
||||
h.logger.Error("HandleOnboardingCallback failed", zap.Error(err), zap.String("user_id", userID.String()))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to sync account status"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to sync account status", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -103,7 +104,7 @@ func (h *SellHandler) ConnectCallback(c *gin.Context) {
|
|||
// GetBalance returns the seller's Stripe Connect balance
|
||||
func (h *SellHandler) GetBalance(c *gin.Context) {
|
||||
if h.stripeConnect == nil {
|
||||
c.JSON(http.StatusServiceUnavailable, gin.H{"error": "Stripe Connect is not enabled"})
|
||||
RespondWithAppError(c, apperrors.NewServiceUnavailableError("Stripe Connect is not enabled"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -115,11 +116,11 @@ func (h *SellHandler) GetBalance(c *gin.Context) {
|
|||
bal, err := h.stripeConnect.GetBalance(c.Request.Context(), userID)
|
||||
if err != nil {
|
||||
if errors.Is(err, services.ErrStripeConnectDisabled) {
|
||||
c.JSON(http.StatusServiceUnavailable, gin.H{"error": "Stripe Connect is not enabled"})
|
||||
RespondWithAppError(c, apperrors.NewServiceUnavailableError("Stripe Connect is not enabled"))
|
||||
return
|
||||
}
|
||||
h.logger.Error("GetBalance failed", zap.Error(err), zap.String("user_id", userID.String()))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get balance"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to get balance", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -140,7 +141,7 @@ func (h *SellHandler) GetSellerTransfers(c *gin.Context) {
|
|||
var transfers []marketplace.SellerTransfer
|
||||
if err := h.db.Where("seller_id = ?", userID).Order("created_at DESC").Find(&transfers).Error; err != nil {
|
||||
h.logger.Error("GetSellerTransfers failed", zap.Error(err), zap.String("user_id", userID.String()))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch transfers"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to fetch transfers", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ func (sh *SessionHandler) Logout() gin.HandlerFunc {
|
|||
// Récupérer l'ID utilisateur depuis le contexte
|
||||
userIDInterface, exists := c.Get("user_id")
|
||||
if !exists {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "User not authenticated"})
|
||||
RespondWithAppError(c, apperrors.NewUnauthorizedError("User not authenticated"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -137,25 +137,25 @@ func (sh *SessionHandler) Logout() gin.HandlerFunc {
|
|||
var err error
|
||||
userID, err = uuid.Parse(v)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Invalid user ID format"})
|
||||
RespondWithAppError(c, apperrors.NewInternalError("Invalid user ID format"))
|
||||
return
|
||||
}
|
||||
default:
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Invalid user ID type"})
|
||||
RespondWithAppError(c, apperrors.NewInternalError("Invalid user ID type"))
|
||||
return
|
||||
}
|
||||
|
||||
// Récupérer le token depuis le header Authorization
|
||||
authHeader := c.GetHeader("Authorization")
|
||||
if authHeader == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Authorization header required"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("Authorization header required"))
|
||||
return
|
||||
}
|
||||
|
||||
// Extraire le token
|
||||
tokenParts := strings.Split(authHeader, " ")
|
||||
if len(tokenParts) != 2 || tokenParts[0] != "Bearer" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid Authorization header format"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("Invalid Authorization header format"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -168,7 +168,7 @@ func (sh *SessionHandler) Logout() gin.HandlerFunc {
|
|||
zap.Error(err),
|
||||
zap.String("user_id", userID.String()),
|
||||
)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to logout"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to logout", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -189,7 +189,7 @@ func (sh *SessionHandler) LogoutAll() gin.HandlerFunc {
|
|||
// Récupérer l'ID utilisateur depuis le contexte
|
||||
userIDInterface, exists := c.Get("user_id")
|
||||
if !exists {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "User not authenticated"})
|
||||
RespondWithAppError(c, apperrors.NewUnauthorizedError("User not authenticated"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -201,11 +201,11 @@ func (sh *SessionHandler) LogoutAll() gin.HandlerFunc {
|
|||
var err error
|
||||
userID, err = uuid.Parse(v)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Invalid user ID format"})
|
||||
RespondWithAppError(c, apperrors.NewInternalError("Invalid user ID format"))
|
||||
return
|
||||
}
|
||||
default:
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Invalid user ID type"})
|
||||
RespondWithAppError(c, apperrors.NewInternalError("Invalid user ID type"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -216,7 +216,7 @@ func (sh *SessionHandler) LogoutAll() gin.HandlerFunc {
|
|||
zap.Error(err),
|
||||
zap.String("user_id", userID.String()),
|
||||
)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to logout all sessions"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to logout all sessions", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -239,7 +239,7 @@ func (sh *SessionHandler) LogoutOthers() gin.HandlerFunc {
|
|||
return func(c *gin.Context) {
|
||||
userIDInterface, exists := c.Get("user_id")
|
||||
if !exists {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "User not authenticated"})
|
||||
RespondWithAppError(c, apperrors.NewUnauthorizedError("User not authenticated"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -251,11 +251,11 @@ func (sh *SessionHandler) LogoutOthers() gin.HandlerFunc {
|
|||
var err error
|
||||
userID, err = uuid.Parse(v)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Invalid user ID format"})
|
||||
RespondWithAppError(c, apperrors.NewInternalError("Invalid user ID format"))
|
||||
return
|
||||
}
|
||||
default:
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Invalid user ID type"})
|
||||
RespondWithAppError(c, apperrors.NewInternalError("Invalid user ID type"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -274,7 +274,7 @@ func (sh *SessionHandler) LogoutOthers() gin.HandlerFunc {
|
|||
zap.Error(err),
|
||||
zap.String("user_id", userID.String()),
|
||||
)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to revoke other sessions"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to revoke other sessions", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -291,7 +291,7 @@ func (sh *SessionHandler) GetSessions() gin.HandlerFunc {
|
|||
// Récupérer l'ID utilisateur depuis le contexte
|
||||
userIDInterface, exists := c.Get("user_id")
|
||||
if !exists {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "User not authenticated"})
|
||||
RespondWithAppError(c, apperrors.NewUnauthorizedError("User not authenticated"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -303,11 +303,11 @@ func (sh *SessionHandler) GetSessions() gin.HandlerFunc {
|
|||
var err error
|
||||
userID, err = uuid.Parse(v)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Invalid user ID format"})
|
||||
RespondWithAppError(c, apperrors.NewInternalError("Invalid user ID format"))
|
||||
return
|
||||
}
|
||||
default:
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Invalid user ID type"})
|
||||
RespondWithAppError(c, apperrors.NewInternalError("Invalid user ID type"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -328,7 +328,7 @@ func (sh *SessionHandler) GetSessions() gin.HandlerFunc {
|
|||
zap.Error(err),
|
||||
zap.String("user_id", userID.String()),
|
||||
)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get sessions"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to get sessions", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -360,7 +360,7 @@ func (sh *SessionHandler) RevokeSession() gin.HandlerFunc {
|
|||
// Récupérer l'ID utilisateur depuis le contexte
|
||||
userIDInterface, exists := c.Get("user_id")
|
||||
if !exists {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "User not authenticated"})
|
||||
RespondWithAppError(c, apperrors.NewUnauthorizedError("User not authenticated"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -372,11 +372,11 @@ func (sh *SessionHandler) RevokeSession() gin.HandlerFunc {
|
|||
var err error
|
||||
userID, err = uuid.Parse(v)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Invalid user ID format"})
|
||||
RespondWithAppError(c, apperrors.NewInternalError("Invalid user ID format"))
|
||||
return
|
||||
}
|
||||
default:
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Invalid user ID type"})
|
||||
RespondWithAppError(c, apperrors.NewInternalError("Invalid user ID type"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -384,7 +384,7 @@ func (sh *SessionHandler) RevokeSession() gin.HandlerFunc {
|
|||
sessionIDStr := c.Param("session_id")
|
||||
sessionID, err := uuid.Parse(sessionIDStr)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid session ID"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("Invalid session ID"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -395,7 +395,7 @@ func (sh *SessionHandler) RevokeSession() gin.HandlerFunc {
|
|||
zap.Error(err),
|
||||
zap.String("user_id", userID.String()),
|
||||
)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get sessions"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to get sessions", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -411,7 +411,7 @@ func (sh *SessionHandler) RevokeSession() gin.HandlerFunc {
|
|||
}
|
||||
|
||||
if !sessionFound {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "Session not found"})
|
||||
RespondWithAppError(c, apperrors.NewNotFoundError("Session"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -423,7 +423,7 @@ func (sh *SessionHandler) RevokeSession() gin.HandlerFunc {
|
|||
zap.Error(err),
|
||||
zap.String("user_id", userID.String()),
|
||||
)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to revoke session"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to revoke session", err))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
"strconv"
|
||||
|
||||
"veza-backend-api/internal/core/social"
|
||||
apperrors "veza-backend-api/internal/errors"
|
||||
"veza-backend-api/internal/utils"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
|
@ -69,7 +70,7 @@ func (h *SocialHandler) CreatePost(c *gin.Context) {
|
|||
|
||||
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"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to create post", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -102,13 +103,13 @@ func (h *SocialHandler) ToggleLike(c *gin.Context) {
|
|||
// 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"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("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"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to toggle like", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -142,13 +143,13 @@ func (h *SocialHandler) AddComment(c *gin.Context) {
|
|||
// 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"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("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"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to add comment", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -197,7 +198,7 @@ func (h *SocialHandler) GetFeed(c *gin.Context) {
|
|||
if useCursorKeyset {
|
||||
feed, nextCursor, err := h.service.GetGlobalFeedWithCursor(c.Request.Context(), limit, cursor, feedType, userID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get feed"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to get feed", err))
|
||||
return
|
||||
}
|
||||
RespondSuccess(c, http.StatusOK, gin.H{
|
||||
|
|
@ -209,7 +210,7 @@ func (h *SocialHandler) GetFeed(c *gin.Context) {
|
|||
|
||||
feed, err := h.service.GetGlobalFeed(c.Request.Context(), limit, offset, feedType, userID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get feed"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to get feed", err))
|
||||
return
|
||||
}
|
||||
nextCursor := ""
|
||||
|
|
@ -234,7 +235,7 @@ func (h *SocialHandler) GetExplore(c *gin.Context) {
|
|||
}
|
||||
tags, err := h.service.GetTrendingHashtags(c.Request.Context(), limit)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get explore data"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to get explore data", err))
|
||||
return
|
||||
}
|
||||
// suggested_users: placeholder - can add users not followed with most followers
|
||||
|
|
@ -257,7 +258,7 @@ func (h *SocialHandler) GetTrending(c *gin.Context) {
|
|||
|
||||
tags, err := h.service.GetTrendingHashtags(c.Request.Context(), limit)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get trending"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to get trending", err))
|
||||
return
|
||||
}
|
||||
RespondSuccess(c, http.StatusOK, gin.H{"tags": tags})
|
||||
|
|
@ -268,7 +269,7 @@ func (h *SocialHandler) GetPostsByUser(c *gin.Context) {
|
|||
userIDStr := c.Param("user_id")
|
||||
userID, err := uuid.Parse(userIDStr)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user ID"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("Invalid user ID"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -289,7 +290,7 @@ func (h *SocialHandler) GetPostsByUser(c *gin.Context) {
|
|||
|
||||
posts, err := h.service.GetPostsByUser(c.Request.Context(), userID, limit, offset)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get posts"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to get posts", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -139,20 +139,20 @@ func (h *GroupHandler) JoinGroup(c *gin.Context) {
|
|||
|
||||
groupID, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid group ID"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("Invalid group ID"))
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.service.JoinGroup(c.Request.Context(), userID, groupID); err != nil {
|
||||
if errors.Is(err, social.ErrGroupNotFound) {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "Group not found"})
|
||||
RespondWithAppError(c, apperrors.NewNotFoundError("Group"))
|
||||
return
|
||||
}
|
||||
if errors.Is(err, social.ErrAlreadyMember) {
|
||||
c.JSON(http.StatusConflict, gin.H{"error": "Already a member"})
|
||||
RespondWithAppError(c, apperrors.New(apperrors.ErrCodeConflict, "Already a member"))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to join group"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to join group", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -168,24 +168,24 @@ func (h *GroupHandler) LeaveGroup(c *gin.Context) {
|
|||
|
||||
groupID, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid group ID"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("Invalid group ID"))
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.service.LeaveGroup(c.Request.Context(), userID, groupID); err != nil {
|
||||
if errors.Is(err, social.ErrGroupNotFound) {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "Group not found"})
|
||||
RespondWithAppError(c, apperrors.NewNotFoundError("Group"))
|
||||
return
|
||||
}
|
||||
if errors.Is(err, social.ErrNotMember) {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Not a member of this group"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("Not a member of this group"))
|
||||
return
|
||||
}
|
||||
if errors.Is(err, social.ErrCannotLeaveOwned) {
|
||||
c.JSON(http.StatusForbidden, gin.H{"error": "Creator cannot leave group"})
|
||||
RespondWithAppError(c, apperrors.NewForbiddenError("Creator cannot leave group"))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to leave group"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to leave group", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -201,25 +201,25 @@ func (h *GroupHandler) RequestToJoin(c *gin.Context) {
|
|||
|
||||
groupID, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid group ID"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("Invalid group ID"))
|
||||
return
|
||||
}
|
||||
|
||||
req, err := h.service.RequestToJoin(c.Request.Context(), userID, groupID)
|
||||
if err != nil {
|
||||
if errors.Is(err, social.ErrGroupNotFound) {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "Group not found"})
|
||||
RespondWithAppError(c, apperrors.NewNotFoundError("Group"))
|
||||
return
|
||||
}
|
||||
if errors.Is(err, social.ErrAlreadyMember) {
|
||||
c.JSON(http.StatusConflict, gin.H{"error": "Already a member"})
|
||||
RespondWithAppError(c, apperrors.New(apperrors.ErrCodeConflict, "Already a member"))
|
||||
return
|
||||
}
|
||||
if errors.Is(err, social.ErrRequestAlreadyExist) {
|
||||
c.JSON(http.StatusConflict, gin.H{"error": "Join request already pending"})
|
||||
RespondWithAppError(c, apperrors.New(apperrors.ErrCodeConflict, "Join request already pending"))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to request join"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to request join", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -239,17 +239,17 @@ func (h *GroupHandler) ListJoinRequests(c *gin.Context) {
|
|||
|
||||
groupID, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid group ID"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("Invalid group ID"))
|
||||
return
|
||||
}
|
||||
|
||||
requests, err := h.service.ListJoinRequests(c.Request.Context(), groupID, userID)
|
||||
if err != nil {
|
||||
if errors.Is(err, social.ErrForbidden) {
|
||||
c.JSON(http.StatusForbidden, gin.H{"error": "Forbidden"})
|
||||
RespondWithAppError(c, apperrors.NewForbiddenError("Forbidden"))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to list requests"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to list requests", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -265,20 +265,20 @@ func (h *GroupHandler) ApproveJoinRequest(c *gin.Context) {
|
|||
|
||||
requestID, err := uuid.Parse(c.Param("request_id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request ID"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("Invalid request ID"))
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.service.ApproveJoinRequest(c.Request.Context(), requestID, userID); err != nil {
|
||||
if errors.Is(err, social.ErrRequestNotFound) {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "Request not found"})
|
||||
RespondWithAppError(c, apperrors.NewNotFoundError("Request"))
|
||||
return
|
||||
}
|
||||
if errors.Is(err, social.ErrForbidden) {
|
||||
c.JSON(http.StatusForbidden, gin.H{"error": "Forbidden"})
|
||||
RespondWithAppError(c, apperrors.NewForbiddenError("Forbidden"))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to approve request"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to approve request", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -294,20 +294,20 @@ func (h *GroupHandler) RejectJoinRequest(c *gin.Context) {
|
|||
|
||||
requestID, err := uuid.Parse(c.Param("request_id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request ID"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("Invalid request ID"))
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.service.RejectJoinRequest(c.Request.Context(), requestID, userID); err != nil {
|
||||
if errors.Is(err, social.ErrRequestNotFound) {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "Request not found"})
|
||||
RespondWithAppError(c, apperrors.NewNotFoundError("Request"))
|
||||
return
|
||||
}
|
||||
if errors.Is(err, social.ErrForbidden) {
|
||||
c.JSON(http.StatusForbidden, gin.H{"error": "Forbidden"})
|
||||
RespondWithAppError(c, apperrors.NewForbiddenError("Forbidden"))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to reject request"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to reject request", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -329,13 +329,13 @@ func (h *GroupHandler) InviteMember(c *gin.Context) {
|
|||
|
||||
groupID, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid group ID"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("Invalid group ID"))
|
||||
return
|
||||
}
|
||||
|
||||
var req InviteMemberRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("Invalid request body"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -346,35 +346,35 @@ func (h *GroupHandler) InviteMember(c *gin.Context) {
|
|||
inviteeID, err = h.service.ResolveInviteeByEmailOrID(c.Request.Context(), *req.Email)
|
||||
if err != nil {
|
||||
if errors.Is(err, social.ErrUserNotFound) {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "User not found"})
|
||||
RespondWithAppError(c, apperrors.NewNotFoundError("User"))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to resolve user"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to resolve user", err))
|
||||
return
|
||||
}
|
||||
} else {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "email or user_id required"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("email or user_id required"))
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.service.InviteMember(c.Request.Context(), userID, groupID, inviteeID); err != nil {
|
||||
if errors.Is(err, social.ErrForbidden) {
|
||||
c.JSON(http.StatusForbidden, gin.H{"error": "Forbidden"})
|
||||
RespondWithAppError(c, apperrors.NewForbiddenError("Forbidden"))
|
||||
return
|
||||
}
|
||||
if errors.Is(err, social.ErrAlreadyMember) {
|
||||
c.JSON(http.StatusConflict, gin.H{"error": "User is already a member"})
|
||||
RespondWithAppError(c, apperrors.New(apperrors.ErrCodeConflict, "User is already a member"))
|
||||
return
|
||||
}
|
||||
if errors.Is(err, social.ErrUserNotFound) {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "User not found"})
|
||||
RespondWithAppError(c, apperrors.NewNotFoundError("User"))
|
||||
return
|
||||
}
|
||||
if err.Error() == "invitation already pending" {
|
||||
c.JSON(http.StatusConflict, gin.H{"error": "Invitation already pending"})
|
||||
RespondWithAppError(c, apperrors.New(apperrors.ErrCodeConflict, "Invitation already pending"))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to invite member"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to invite member", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -395,32 +395,32 @@ func (h *GroupHandler) UpdateMemberRole(c *gin.Context) {
|
|||
|
||||
groupID, err := uuid.Parse(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid group ID"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("Invalid group ID"))
|
||||
return
|
||||
}
|
||||
|
||||
targetUserID, err := uuid.Parse(c.Param("user_id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user ID"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("Invalid user ID"))
|
||||
return
|
||||
}
|
||||
|
||||
var req UpdateMemberRoleRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body"})
|
||||
RespondWithAppError(c, apperrors.NewValidationError("Invalid request body"))
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.service.UpdateMemberRole(c.Request.Context(), userID, groupID, targetUserID, req.Role); err != nil {
|
||||
if errors.Is(err, social.ErrForbidden) {
|
||||
c.JSON(http.StatusForbidden, gin.H{"error": "Forbidden"})
|
||||
RespondWithAppError(c, apperrors.NewForbiddenError("Forbidden"))
|
||||
return
|
||||
}
|
||||
if errors.Is(err, social.ErrNotMember) {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "User is not a member"})
|
||||
RespondWithAppError(c, apperrors.NewNotFoundError("User"))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update role"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to update role", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
apperrors "veza-backend-api/internal/errors"
|
||||
"veza-backend-api/internal/services"
|
||||
)
|
||||
|
||||
|
|
@ -32,7 +33,7 @@ func (h *TagHandler) Suggest(c *gin.Context) {
|
|||
|
||||
suggestions, err := h.tagService.Suggest(c.Request.Context(), q, limit)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to get suggestions"})
|
||||
RespondWithAppError(c, apperrors.NewInternalErrorWrap("failed to get suggestions", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue