diff --git a/veza-backend-api/docs/docs.go b/veza-backend-api/docs/docs.go index 199cd8ce0..b758bf8b2 100644 --- a/veza-backend-api/docs/docs.go +++ b/veza-backend-api/docs/docs.go @@ -64,19 +64,13 @@ const docTemplate = `{ "403": { "description": "No license", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/veza-backend-api_internal_response.APIResponse" } }, "404": { "description": "Not Found", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/veza-backend-api_internal_response.APIResponse" } } } @@ -119,21 +113,15 @@ const docTemplate = `{ } }, "400": { - "description": "Bad Request", + "description": "Validation Error", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/veza-backend-api_internal_response.APIResponse" } }, "401": { "description": "Unauthorized", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/veza-backend-api_internal_response.APIResponse" } } } @@ -214,21 +202,15 @@ const docTemplate = `{ } }, "400": { - "description": "Bad Request", + "description": "Validation Error", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/veza-backend-api_internal_response.APIResponse" } }, "401": { "description": "Unauthorized", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/veza-backend-api_internal_response.APIResponse" } } } diff --git a/veza-backend-api/docs/swagger.json b/veza-backend-api/docs/swagger.json index 3f3ad5b8b..b514ad25b 100644 --- a/veza-backend-api/docs/swagger.json +++ b/veza-backend-api/docs/swagger.json @@ -58,19 +58,13 @@ "403": { "description": "No license", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/veza-backend-api_internal_response.APIResponse" } }, "404": { "description": "Not Found", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/veza-backend-api_internal_response.APIResponse" } } } @@ -113,21 +107,15 @@ } }, "400": { - "description": "Bad Request", + "description": "Validation Error", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/veza-backend-api_internal_response.APIResponse" } }, "401": { "description": "Unauthorized", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/veza-backend-api_internal_response.APIResponse" } } } @@ -208,21 +196,15 @@ } }, "400": { - "description": "Bad Request", + "description": "Validation Error", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/veza-backend-api_internal_response.APIResponse" } }, "401": { "description": "Unauthorized", "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "$ref": "#/definitions/veza-backend-api_internal_response.APIResponse" } } } diff --git a/veza-backend-api/docs/swagger.yaml b/veza-backend-api/docs/swagger.yaml index d2e6e94eb..6caf5843c 100644 --- a/veza-backend-api/docs/swagger.yaml +++ b/veza-backend-api/docs/swagger.yaml @@ -558,15 +558,11 @@ paths: "403": description: No license schema: - additionalProperties: - type: string - type: object + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' "404": description: Not Found schema: - additionalProperties: - type: string - type: object + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' security: - BearerAuth: [] summary: Get download URL @@ -592,17 +588,13 @@ paths: schema: $ref: '#/definitions/veza-backend-api_internal_core_marketplace.Order' "400": - description: Bad Request + description: Validation Error schema: - additionalProperties: - type: string - type: object + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' "401": description: Unauthorized schema: - additionalProperties: - type: string - type: object + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' security: - BearerAuth: [] summary: Create a new order @@ -653,17 +645,13 @@ paths: schema: $ref: '#/definitions/veza-backend-api_internal_core_marketplace.Product' "400": - description: Bad Request + description: Validation Error schema: - additionalProperties: - type: string - type: object + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' "401": description: Unauthorized schema: - additionalProperties: - type: string - type: object + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' security: - BearerAuth: [] summary: Create a new product diff --git a/veza-backend-api/internal/errors/errors.go b/veza-backend-api/internal/errors/errors.go index 6f2097c07..7eca3870d 100644 --- a/veza-backend-api/internal/errors/errors.go +++ b/veza-backend-api/internal/errors/errors.go @@ -67,3 +67,11 @@ func NewUnauthorizedError(message string) *AppError { Message: message, } } + +// NewForbiddenError crée une nouvelle erreur "forbidden" +func NewForbiddenError(message string) *AppError { + return &AppError{ + Code: ErrCodeForbidden, + Message: message, + } +} diff --git a/veza-backend-api/internal/handlers/marketplace.go b/veza-backend-api/internal/handlers/marketplace.go index cd80bda15..215ad0c3b 100644 --- a/veza-backend-api/internal/handlers/marketplace.go +++ b/veza-backend-api/internal/handlers/marketplace.go @@ -1,12 +1,11 @@ package handlers import ( - "net/http" - "github.com/gin-gonic/gin" "github.com/google/uuid" "go.uber.org/zap" "veza-backend-api/internal/core/marketplace" + "veza-backend-api/internal/response" ) // MarketplaceHandler gère les opérations de la marketplace @@ -43,8 +42,9 @@ type CreateProductRequest struct { // @Security BearerAuth // @Param product body CreateProductRequest true "Product info" // @Success 201 {object} marketplace.Product -// @Failure 400 {object} map[string]string -// @Failure 401 {object} map[string]string +// @Success 201 {object} marketplace.Product +// @Failure 400 {object} response.APIResponse "Validation Error" +// @Failure 401 {object} response.APIResponse "Unauthorized" // @Router /api/v1/marketplace/products [post] func (h *MarketplaceHandler) CreateProduct(c *gin.Context) { userID := c.MustGet("user_id").(uuid.UUID) @@ -68,7 +68,7 @@ func (h *MarketplaceHandler) CreateProduct(c *gin.Context) { if req.TrackID != "" { trackUUID, err := uuid.Parse(req.TrackID) if err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid track_id format"}) + response.BadRequest(c, "Invalid track_id format") return } product.TrackID = &trackUUID @@ -76,18 +76,18 @@ func (h *MarketplaceHandler) CreateProduct(c *gin.Context) { if err := h.service.CreateProduct(c.Request.Context(), product); err != nil { if err == marketplace.ErrInvalidSeller { - c.JSON(http.StatusForbidden, gin.H{"error": "You do not own this track"}) + response.Forbidden(c, "You do not own this track") return } if err == marketplace.ErrTrackNotFound { - c.JSON(http.StatusNotFound, gin.H{"error": "Track not found"}) + response.NotFound(c, "Track not found") return } - c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create product"}) + response.InternalServerError(c, "Failed to create product") return } - RespondSuccess(c, http.StatusCreated, product) + response.Created(c, product) } // CreateOrderRequest DTO pour la création de commande @@ -106,8 +106,9 @@ type CreateOrderRequest struct { // @Security BearerAuth // @Param order body CreateOrderRequest true "Order items" // @Success 201 {object} marketplace.Order -// @Failure 400 {object} map[string]string -// @Failure 401 {object} map[string]string +// @Success 201 {object} marketplace.Order +// @Failure 400 {object} response.APIResponse "Validation Error" +// @Failure 401 {object} response.APIResponse "Unauthorized" // @Router /api/v1/marketplace/orders [post] func (h *MarketplaceHandler) CreateOrder(c *gin.Context) { buyerID := c.MustGet("user_id").(uuid.UUID) @@ -122,7 +123,7 @@ func (h *MarketplaceHandler) CreateOrder(c *gin.Context) { for _, item := range req.Items { pid, err := uuid.Parse(item.ProductID) if err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid product_id: " + item.ProductID}) + response.BadRequest(c, "Invalid product_id: "+item.ProductID) return } items = append(items, marketplace.NewOrderItem{ProductID: pid}) @@ -130,11 +131,11 @@ func (h *MarketplaceHandler) CreateOrder(c *gin.Context) { order, err := h.service.CreateOrder(c.Request.Context(), buyerID, items) if err != nil { - c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + response.InternalServerError(c, err.Error()) return } - RespondSuccess(c, http.StatusCreated, order) + response.Created(c, order) } // GetDownloadURL récupère l'URL de téléchargement pour un achat @@ -146,8 +147,8 @@ func (h *MarketplaceHandler) CreateOrder(c *gin.Context) { // @Security BearerAuth // @Param product_id path string true "Product ID" // @Success 200 {object} map[string]string -// @Failure 403 {object} map[string]string "No license" -// @Failure 404 {object} map[string]string +// @Failure 403 {object} response.APIResponse "No license" +// @Failure 404 {object} response.APIResponse "Not Found" // @Router /api/v1/marketplace/download/{product_id} [get] func (h *MarketplaceHandler) GetDownloadURL(c *gin.Context) { userID := c.MustGet("user_id").(uuid.UUID) @@ -155,25 +156,25 @@ func (h *MarketplaceHandler) GetDownloadURL(c *gin.Context) { productID, err := uuid.Parse(productIDStr) if err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid product_id"}) + response.BadRequest(c, "Invalid product_id") return } url, err := h.service.GetDownloadURL(c.Request.Context(), userID, productID) if err != nil { if err == marketplace.ErrNoLicense { - c.JSON(http.StatusForbidden, gin.H{"error": "No valid license for this product"}) + response.Forbidden(c, "No valid license for this product") return } if err == marketplace.ErrTrackNotFound { - c.JSON(http.StatusNotFound, gin.H{"error": "Track file not found"}) + response.NotFound(c, "Track file not found") return } - c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get download URL"}) + response.InternalServerError(c, "Failed to get download URL") return } - RespondSuccess(c, http.StatusOK, gin.H{"url": url}) + response.Success(c, gin.H{"url": url}) } // ListProducts liste les produits @@ -198,9 +199,9 @@ func (h *MarketplaceHandler) ListProducts(c *gin.Context) { products, err := h.service.ListProducts(c.Request.Context(), filters) if err != nil { - c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to list products"}) + response.InternalServerError(c, "Failed to list products") return } - RespondSuccess(c, http.StatusOK, products) + response.Success(c, products) }