2025-12-03 19:29:37 +00:00
|
|
|
package handlers
|
|
|
|
|
|
|
|
|
|
import (
|
chore: consolidate CI, E2E, backend and frontend updates
- CI: workflows updates (cd, ci), remove playwright.yml
- E2E: global-setup, auth/playlists/profile specs
- Remove playwright-report and test-results artifacts from tracking
- Backend: auth, handlers, services, workers, migrations
- Frontend: components, features, vite config
- Add e2e-results.json to gitignore
- Docs: REMEDIATION_PROGRESS, audit archive
- Rust: chat-server, stream-server updates
2026-02-17 15:43:21 +00:00
|
|
|
"bytes"
|
2025-12-16 16:23:49 +00:00
|
|
|
"context"
|
2025-12-03 19:29:37 +00:00
|
|
|
"encoding/json"
|
P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.
Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.
Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).
Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.
Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 10:14:38 +00:00
|
|
|
"errors"
|
|
|
|
|
"fmt"
|
|
|
|
|
"io"
|
2025-12-03 19:29:37 +00:00
|
|
|
"net/http"
|
2026-03-13 23:44:46 +00:00
|
|
|
"os"
|
2025-12-03 19:29:37 +00:00
|
|
|
"strconv"
|
|
|
|
|
"strings"
|
|
|
|
|
"time"
|
|
|
|
|
|
2026-03-05 18:27:34 +00:00
|
|
|
"veza-backend-api/internal/common"
|
2025-12-03 19:29:37 +00:00
|
|
|
"veza-backend-api/internal/dto"
|
P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.
Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.
Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).
Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.
Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 10:14:38 +00:00
|
|
|
apperrors "veza-backend-api/internal/errors"
|
2025-12-03 19:29:37 +00:00
|
|
|
"veza-backend-api/internal/validators"
|
|
|
|
|
|
|
|
|
|
"github.com/gin-gonic/gin"
|
2025-12-16 16:23:49 +00:00
|
|
|
"github.com/google/uuid"
|
2025-12-03 19:29:37 +00:00
|
|
|
"go.uber.org/zap"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// ResponseData représente la structure standardisée des réponses API
|
|
|
|
|
type ResponseData struct {
|
|
|
|
|
Success bool `json:"success"`
|
|
|
|
|
Message string `json:"message,omitempty"`
|
|
|
|
|
Data interface{} `json:"data,omitempty"`
|
|
|
|
|
Error string `json:"error,omitempty"`
|
|
|
|
|
Timestamp time.Time `json:"timestamp"`
|
|
|
|
|
RequestID string `json:"request_id,omitempty"`
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-25 14:14:26 +00:00
|
|
|
// PaginationData représente les données de pagination standardisées
|
|
|
|
|
// INT-007: Standardize pagination format with snake_case for consistency
|
2025-12-03 19:29:37 +00:00
|
|
|
type PaginationData struct {
|
2026-01-13 18:47:57 +00:00
|
|
|
Page int `json:"page"`
|
|
|
|
|
Limit int `json:"limit"`
|
|
|
|
|
Total int64 `json:"total"`
|
|
|
|
|
TotalPages int `json:"total_pages"`
|
|
|
|
|
HasNext bool `json:"has_next"`
|
|
|
|
|
HasPrev bool `json:"has_prev"` // INT-007: Changed from HasPrevious to HasPrev for consistency
|
|
|
|
|
NextCursor string `json:"next_cursor,omitempty"`
|
|
|
|
|
PrevCursor string `json:"prev_cursor,omitempty"` // INT-007: Changed from PreviousCursor to PrevCursor for consistency
|
2025-12-03 19:29:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// PaginatedResponse représente une réponse paginée
|
|
|
|
|
type PaginatedResponse struct {
|
|
|
|
|
ResponseData
|
|
|
|
|
Pagination PaginationData `json:"pagination"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ValidationError et ValidationErrors sont maintenant dans internal/dto/validation.go
|
|
|
|
|
// pour éviter les cycles d'import. Utiliser dto.ValidationError et dto.ValidationErrors
|
|
|
|
|
|
|
|
|
|
// CommonHandler contient les dépendances communes aux handlers
|
|
|
|
|
type CommonHandler struct {
|
|
|
|
|
logger *zap.Logger
|
|
|
|
|
validator *validators.Validator // GO-013: Validator centralisé
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NewCommonHandler crée une nouvelle instance de CommonHandler
|
|
|
|
|
// GO-013: Initialise le validator centralisé
|
|
|
|
|
func NewCommonHandler(logger *zap.Logger) *CommonHandler {
|
|
|
|
|
return &CommonHandler{
|
|
|
|
|
logger: logger,
|
|
|
|
|
validator: validators.NewValidator(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ValidateRequest valide une requête avec le validator centralisé
|
|
|
|
|
// GO-013: Helper pour valider les requêtes et retourner des erreurs formatées
|
|
|
|
|
func (h *CommonHandler) ValidateRequest(c *gin.Context, req interface{}) bool {
|
|
|
|
|
validationErrors := h.validator.Validate(req)
|
|
|
|
|
if len(validationErrors) > 0 {
|
|
|
|
|
h.RespondWithValidationError(c, validationErrors)
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// RespondWithSuccess répond avec une réponse de succès
|
|
|
|
|
func (h *CommonHandler) RespondWithSuccess(c *gin.Context, data interface{}, message string) {
|
2025-12-06 16:21:59 +00:00
|
|
|
// Utiliser la structure unifiée APIResponse via RespondSuccess
|
|
|
|
|
// Si message est présent, on l'encapsule avec les données
|
|
|
|
|
if message != "" {
|
|
|
|
|
RespondSuccess(c, http.StatusOK, gin.H{
|
|
|
|
|
"message": message,
|
|
|
|
|
"data": data,
|
|
|
|
|
})
|
|
|
|
|
} else {
|
|
|
|
|
RespondSuccess(c, http.StatusOK, data)
|
2025-12-03 19:29:37 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// RespondWithError répond avec une erreur
|
|
|
|
|
func (h *CommonHandler) RespondWithError(c *gin.Context, statusCode int, message string, err error) {
|
2025-12-06 16:21:59 +00:00
|
|
|
// Utiliser la structure unifiée APIResponse
|
|
|
|
|
// On crée une structure d'erreur ad-hoc pour correspondre à l'interface attendue par APIResponse.Error (qui est interface{})
|
|
|
|
|
// Ou mieux, on utilise RespondWithError qui attend un code, message et détails
|
2025-12-13 02:34:34 +00:00
|
|
|
|
2025-12-06 16:21:59 +00:00
|
|
|
// Note: RespondWithError est defined in error_response.go et attend (c, code, message, details...)
|
|
|
|
|
// Ici on a statusCode HTTP. RespondWithError attend un ErrorCode interne.
|
|
|
|
|
// C'est un conflit de signature.
|
|
|
|
|
// On va donc construire manuellement la réponse d'erreur unifiée.
|
2025-12-13 02:34:34 +00:00
|
|
|
|
2025-12-06 16:21:59 +00:00
|
|
|
errResponse := gin.H{
|
|
|
|
|
"code": statusCode,
|
|
|
|
|
"message": message,
|
|
|
|
|
"details": nil,
|
2025-12-03 19:29:37 +00:00
|
|
|
}
|
|
|
|
|
if err != nil {
|
|
|
|
|
h.logger.Error("Handler error",
|
|
|
|
|
zap.String("error", err.Error()),
|
|
|
|
|
zap.String("request_id", c.GetString("request_id")),
|
|
|
|
|
zap.String("endpoint", c.Request.URL.Path),
|
|
|
|
|
)
|
2025-12-06 16:21:59 +00:00
|
|
|
// On pourrait ajouter err.Error() dans details, mais pour sécurité on évite d'exposer l'erreur brute sauf si nécessaire
|
2025-12-03 19:29:37 +00:00
|
|
|
}
|
|
|
|
|
|
2025-12-06 16:21:59 +00:00
|
|
|
c.JSON(statusCode, APIResponse{
|
|
|
|
|
Success: false,
|
|
|
|
|
Data: nil,
|
|
|
|
|
Error: errResponse,
|
|
|
|
|
})
|
2025-12-03 19:29:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// RespondWithValidationError répond avec des erreurs de validation
|
|
|
|
|
// GO-013: Utilise dto.ValidationError pour éviter les cycles d'import
|
|
|
|
|
func (h *CommonHandler) RespondWithValidationError(c *gin.Context, errors []dto.ValidationError) {
|
2025-12-06 16:21:59 +00:00
|
|
|
// Adapter pour l'enveloppe unifiée
|
|
|
|
|
// Code 400 ou 422
|
2025-12-13 02:34:34 +00:00
|
|
|
|
2025-12-06 16:21:59 +00:00
|
|
|
c.JSON(http.StatusBadRequest, APIResponse{
|
|
|
|
|
Success: false,
|
|
|
|
|
Data: nil,
|
|
|
|
|
Error: gin.H{
|
|
|
|
|
"code": http.StatusBadRequest,
|
|
|
|
|
"message": "Validation failed",
|
|
|
|
|
"details": errors,
|
|
|
|
|
},
|
|
|
|
|
})
|
2025-12-03 19:29:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// RespondWithPaginatedData répond avec des données paginées
|
2025-12-25 14:14:26 +00:00
|
|
|
// INT-007: Standardize pagination response format
|
2025-12-03 19:29:37 +00:00
|
|
|
func (h *CommonHandler) RespondWithPaginatedData(c *gin.Context, data interface{}, pagination PaginationData, message string) {
|
2025-12-06 16:21:59 +00:00
|
|
|
// Pour la pagination, on met tout dans Data
|
|
|
|
|
responseData := gin.H{
|
|
|
|
|
"list": data,
|
|
|
|
|
"pagination": pagination,
|
|
|
|
|
}
|
|
|
|
|
if message != "" {
|
|
|
|
|
responseData["message"] = message
|
2025-12-03 19:29:37 +00:00
|
|
|
}
|
|
|
|
|
|
2025-12-06 16:21:59 +00:00
|
|
|
RespondSuccess(c, http.StatusOK, responseData)
|
2025-12-03 19:29:37 +00:00
|
|
|
}
|
|
|
|
|
|
2025-12-25 14:14:26 +00:00
|
|
|
// BuildPaginationData construit une PaginationData standardisée à partir des paramètres
|
|
|
|
|
// INT-007: Helper pour standardiser la création de PaginationData
|
|
|
|
|
func BuildPaginationData(page, limit int, total int64) PaginationData {
|
|
|
|
|
totalPages := int((total + int64(limit) - 1) / int64(limit))
|
|
|
|
|
if totalPages == 0 {
|
|
|
|
|
totalPages = 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return PaginationData{
|
|
|
|
|
Page: page,
|
|
|
|
|
Limit: limit,
|
|
|
|
|
Total: total,
|
|
|
|
|
TotalPages: totalPages,
|
|
|
|
|
HasNext: page < totalPages,
|
|
|
|
|
HasPrev: page > 1,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// BuildPaginationDataWithCursor construit une PaginationData avec curseurs
|
|
|
|
|
// INT-007: Helper pour pagination cursor-based
|
|
|
|
|
func BuildPaginationDataWithCursor(limit int, total int64, nextCursor, prevCursor string) PaginationData {
|
|
|
|
|
// Pour cursor-based, on ne peut pas calculer totalPages exactement
|
|
|
|
|
// mais on peut indiquer s'il y a une page suivante/précédente
|
|
|
|
|
hasNext := nextCursor != ""
|
|
|
|
|
hasPrev := prevCursor != ""
|
|
|
|
|
|
|
|
|
|
return PaginationData{
|
|
|
|
|
Limit: limit,
|
|
|
|
|
Total: total,
|
|
|
|
|
HasNext: hasNext,
|
|
|
|
|
HasPrev: hasPrev,
|
|
|
|
|
NextCursor: nextCursor,
|
|
|
|
|
PrevCursor: prevCursor,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-03 19:29:37 +00:00
|
|
|
// BindJSON lie les données JSON de la requête à une structure
|
P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.
Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.
Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).
Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.
Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 10:14:38 +00:00
|
|
|
// DEPRECATED: Utiliser BindAndValidateJSON à la place pour une gestion d'erreurs robuste
|
2025-12-03 19:29:37 +00:00
|
|
|
func (h *CommonHandler) BindJSON(c *gin.Context, obj interface{}) error {
|
|
|
|
|
if err := c.ShouldBindJSON(obj); err != nil {
|
|
|
|
|
h.logger.Warn("Failed to bind JSON",
|
|
|
|
|
zap.Error(err),
|
|
|
|
|
zap.String("request_id", c.GetString("request_id")),
|
|
|
|
|
)
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.
Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.
Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).
Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.
Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 10:14:38 +00:00
|
|
|
// BindAndValidateJSON lie et valide les données JSON de la requête de manière robuste
|
|
|
|
|
// P0: JSON Hardening - Garantit qu'aucune erreur de parsing/validation ne passe silencieusement
|
|
|
|
|
//
|
|
|
|
|
// Comportement:
|
|
|
|
|
// - Vérifie la taille du body (max 10MB par défaut)
|
|
|
|
|
// - Parse le JSON avec ShouldBindJSON (Gin)
|
|
|
|
|
// - Valide avec le validator centralisé
|
|
|
|
|
// - Retourne une AppError avec code approprié (400 pour JSON malformé, 422 pour validation)
|
|
|
|
|
//
|
|
|
|
|
// Usage:
|
|
|
|
|
//
|
|
|
|
|
// var req MyRequest
|
|
|
|
|
// if appErr := h.BindAndValidateJSON(c, &req); appErr != nil {
|
|
|
|
|
// RespondWithAppError(c, appErr)
|
|
|
|
|
// return
|
|
|
|
|
// }
|
|
|
|
|
func (h *CommonHandler) BindAndValidateJSON(c *gin.Context, obj interface{}) *apperrors.AppError {
|
|
|
|
|
requestID := c.GetString("request_id")
|
2026-03-05 18:27:34 +00:00
|
|
|
maxSize := common.GetMaxJSONBodySize()
|
P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.
Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.
Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).
Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.
Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 10:14:38 +00:00
|
|
|
|
2026-03-05 18:27:34 +00:00
|
|
|
// 1. Vérifier la taille du body (TASK-SEC-005: 1MB défaut)
|
|
|
|
|
if c.Request.ContentLength > maxSize {
|
P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.
Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.
Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).
Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.
Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 10:14:38 +00:00
|
|
|
h.logger.Warn("Request body too large",
|
|
|
|
|
zap.Int64("content_length", c.Request.ContentLength),
|
2026-03-05 18:27:34 +00:00
|
|
|
zap.Int64("max_size", maxSize),
|
P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.
Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.
Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).
Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.
Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 10:14:38 +00:00
|
|
|
zap.String("request_id", requestID),
|
|
|
|
|
zap.String("endpoint", c.Request.URL.Path),
|
|
|
|
|
)
|
|
|
|
|
return apperrors.New(
|
|
|
|
|
apperrors.ErrCodeValidation,
|
2026-03-05 18:27:34 +00:00
|
|
|
fmt.Sprintf("Request body too large: maximum size is %d bytes", maxSize),
|
P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.
Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.
Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).
Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.
Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 10:14:38 +00:00
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 2. Limiter la lecture du body pour éviter les attaques par body trop gros
|
2026-03-05 18:27:34 +00:00
|
|
|
c.Request.Body = http.MaxBytesReader(c.Writer, c.Request.Body, maxSize)
|
P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.
Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.
Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).
Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.
Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 10:14:38 +00:00
|
|
|
|
chore: consolidate CI, E2E, backend and frontend updates
- CI: workflows updates (cd, ci), remove playwright.yml
- E2E: global-setup, auth/playlists/profile specs
- Remove playwright-report and test-results artifacts from tracking
- Backend: auth, handlers, services, workers, migrations
- Frontend: components, features, vite config
- Add e2e-results.json to gitignore
- Docs: REMEDIATION_PROGRESS, audit archive
- Rust: chat-server, stream-server updates
2026-02-17 15:43:21 +00:00
|
|
|
// 3. Parser le JSON avec DisallowUnknownFields (rejette les champs inconnus)
|
|
|
|
|
body, err := io.ReadAll(c.Request.Body)
|
|
|
|
|
if err != nil {
|
|
|
|
|
h.logger.Warn("Failed to read request body",
|
|
|
|
|
zap.Error(err),
|
|
|
|
|
zap.String("request_id", requestID),
|
|
|
|
|
zap.String("endpoint", c.Request.URL.Path),
|
|
|
|
|
)
|
|
|
|
|
return apperrors.New(apperrors.ErrCodeValidation, "Failed to read request body")
|
|
|
|
|
}
|
|
|
|
|
c.Request.Body = io.NopCloser(bytes.NewReader(body)) // Restore for middleware
|
|
|
|
|
|
|
|
|
|
decoder := json.NewDecoder(bytes.NewReader(body))
|
|
|
|
|
decoder.DisallowUnknownFields()
|
|
|
|
|
if err := decoder.Decode(obj); err != nil {
|
P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.
Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.
Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).
Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.
Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 10:14:38 +00:00
|
|
|
// Analyser le type d'erreur pour retourner le bon code
|
|
|
|
|
var jsonSyntaxError *json.SyntaxError
|
|
|
|
|
var jsonUnmarshalTypeError *json.UnmarshalTypeError
|
|
|
|
|
var maxBytesError *http.MaxBytesError
|
|
|
|
|
|
|
|
|
|
switch {
|
|
|
|
|
case errors.As(err, &maxBytesError):
|
|
|
|
|
// Body trop gros (dépassement de la limite)
|
|
|
|
|
h.logger.Warn("Request body exceeds maximum size",
|
|
|
|
|
zap.Error(err),
|
|
|
|
|
zap.String("request_id", requestID),
|
|
|
|
|
zap.String("endpoint", c.Request.URL.Path),
|
|
|
|
|
)
|
|
|
|
|
return apperrors.New(
|
|
|
|
|
apperrors.ErrCodeValidation,
|
2026-03-05 18:27:34 +00:00
|
|
|
fmt.Sprintf("Request body too large: maximum size is %d bytes", common.GetMaxJSONBodySize()),
|
P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.
Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.
Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).
Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.
Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 10:14:38 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
case errors.As(err, &jsonSyntaxError):
|
|
|
|
|
// JSON syntaxiquement invalide
|
|
|
|
|
h.logger.Warn("Invalid JSON syntax",
|
|
|
|
|
zap.Error(err),
|
|
|
|
|
zap.Int64("offset", jsonSyntaxError.Offset),
|
|
|
|
|
zap.String("request_id", requestID),
|
|
|
|
|
zap.String("endpoint", c.Request.URL.Path),
|
|
|
|
|
)
|
|
|
|
|
return apperrors.New(
|
|
|
|
|
apperrors.ErrCodeValidation,
|
|
|
|
|
fmt.Sprintf("Invalid JSON syntax at offset %d: %s", jsonSyntaxError.Offset, jsonSyntaxError.Error()),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
case errors.As(err, &jsonUnmarshalTypeError):
|
|
|
|
|
// Type incorrect pour un champ
|
|
|
|
|
h.logger.Warn("Invalid JSON type",
|
|
|
|
|
zap.Error(err),
|
|
|
|
|
zap.String("field", jsonUnmarshalTypeError.Field),
|
|
|
|
|
zap.String("type", jsonUnmarshalTypeError.Type.String()),
|
|
|
|
|
zap.String("request_id", requestID),
|
|
|
|
|
zap.String("endpoint", c.Request.URL.Path),
|
|
|
|
|
)
|
|
|
|
|
return apperrors.New(
|
|
|
|
|
apperrors.ErrCodeInvalidFormat,
|
|
|
|
|
fmt.Sprintf("Invalid type for field '%s': expected %s", jsonUnmarshalTypeError.Field, jsonUnmarshalTypeError.Type.String()),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
case errors.Is(err, io.EOF):
|
|
|
|
|
// Body vide
|
|
|
|
|
h.logger.Warn("Empty request body",
|
|
|
|
|
zap.String("request_id", requestID),
|
|
|
|
|
zap.String("endpoint", c.Request.URL.Path),
|
|
|
|
|
)
|
|
|
|
|
return apperrors.New(
|
|
|
|
|
apperrors.ErrCodeValidation,
|
|
|
|
|
"Request body is empty or invalid JSON",
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
case errors.Is(err, io.ErrUnexpectedEOF):
|
|
|
|
|
// JSON incomplet
|
|
|
|
|
h.logger.Warn("Incomplete JSON",
|
|
|
|
|
zap.Error(err),
|
|
|
|
|
zap.String("request_id", requestID),
|
|
|
|
|
zap.String("endpoint", c.Request.URL.Path),
|
|
|
|
|
)
|
|
|
|
|
return apperrors.New(
|
|
|
|
|
apperrors.ErrCodeValidation,
|
|
|
|
|
"Incomplete or malformed JSON",
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
// Erreur générique de binding (peut inclure des erreurs de validation Gin)
|
|
|
|
|
// On va laisser le validator gérer les erreurs de validation
|
|
|
|
|
// Si c'est une erreur de binding Gin (ex: unknown field), on la traite ici
|
|
|
|
|
errStr := err.Error()
|
|
|
|
|
if strings.Contains(errStr, "unknown field") || strings.Contains(errStr, "unknown") {
|
|
|
|
|
h.logger.Warn("Unknown fields in JSON",
|
|
|
|
|
zap.Error(err),
|
|
|
|
|
zap.String("request_id", requestID),
|
|
|
|
|
zap.String("endpoint", c.Request.URL.Path),
|
|
|
|
|
)
|
|
|
|
|
return apperrors.New(
|
|
|
|
|
apperrors.ErrCodeValidation,
|
|
|
|
|
"Unknown fields in JSON payload",
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Pour les autres erreurs de binding, on considère que c'est une erreur de validation
|
2025-12-25 00:32:54 +00:00
|
|
|
// Les erreurs de validation de binding Gin (comme "required", "url", "min") doivent être retournées
|
P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.
Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.
Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).
Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.
Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 10:14:38 +00:00
|
|
|
h.logger.Debug("JSON binding error (will be handled by validator)",
|
|
|
|
|
zap.Error(err),
|
|
|
|
|
zap.String("request_id", requestID),
|
|
|
|
|
zap.String("endpoint", c.Request.URL.Path),
|
|
|
|
|
)
|
2025-12-26 10:04:25 +00:00
|
|
|
// Améliorer le message d'erreur pour les validations courantes
|
|
|
|
|
errMsg := err.Error()
|
|
|
|
|
if strings.Contains(errMsg, "Password") && strings.Contains(errMsg, "min") {
|
|
|
|
|
errMsg = "Le mot de passe doit contenir au moins 12 caractères"
|
|
|
|
|
} else if strings.Contains(errMsg, "PasswordConfirm") && strings.Contains(errMsg, "eqfield") {
|
|
|
|
|
errMsg = "Les mots de passe ne correspondent pas"
|
|
|
|
|
} else if strings.Contains(errMsg, "Email") && strings.Contains(errMsg, "email") {
|
|
|
|
|
errMsg = "Format d'email invalide"
|
|
|
|
|
} else if strings.Contains(errMsg, "Username") && strings.Contains(errMsg, "min") {
|
|
|
|
|
errMsg = "Le nom d'utilisateur doit contenir au moins 3 caractères"
|
|
|
|
|
} else if strings.Contains(errMsg, "required") {
|
|
|
|
|
// Extraire le nom du champ
|
|
|
|
|
if strings.Contains(errMsg, "Password") {
|
|
|
|
|
errMsg = "Le mot de passe est requis"
|
|
|
|
|
} else if strings.Contains(errMsg, "Email") {
|
|
|
|
|
errMsg = "L'email est requis"
|
|
|
|
|
} else if strings.Contains(errMsg, "PasswordConfirm") {
|
|
|
|
|
errMsg = "La confirmation du mot de passe est requise"
|
|
|
|
|
} else if strings.Contains(errMsg, "Username") {
|
|
|
|
|
errMsg = "Le nom d'utilisateur est requis"
|
|
|
|
|
} else {
|
|
|
|
|
errMsg = fmt.Sprintf("Validation failed: %s", errMsg)
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
errMsg = fmt.Sprintf("Validation failed: %s", errMsg)
|
|
|
|
|
}
|
2026-01-13 18:47:57 +00:00
|
|
|
|
2025-12-25 00:32:54 +00:00
|
|
|
// Retourner l'erreur de validation de binding
|
|
|
|
|
return apperrors.New(
|
|
|
|
|
apperrors.ErrCodeValidation,
|
2025-12-26 10:04:25 +00:00
|
|
|
errMsg,
|
2025-12-25 00:32:54 +00:00
|
|
|
)
|
P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.
Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.
Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).
Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.
Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 10:14:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 4. Valider avec le validator centralisé
|
|
|
|
|
validationErrors := h.validator.Validate(obj)
|
|
|
|
|
if len(validationErrors) > 0 {
|
|
|
|
|
// Convertir dto.ValidationError en errors.ErrorDetail
|
|
|
|
|
details := make([]apperrors.ErrorDetail, 0, len(validationErrors))
|
|
|
|
|
for _, ve := range validationErrors {
|
|
|
|
|
details = append(details, apperrors.ErrorDetail{
|
|
|
|
|
Field: ve.Field,
|
|
|
|
|
Message: ve.Message,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
h.logger.Warn("Validation failed",
|
|
|
|
|
zap.Int("error_count", len(validationErrors)),
|
|
|
|
|
zap.String("request_id", requestID),
|
|
|
|
|
zap.String("endpoint", c.Request.URL.Path),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return apperrors.NewValidationError("Validation failed", details...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-03 19:29:37 +00:00
|
|
|
// GetUserIDFromContext extrait l'ID utilisateur du contexte
|
|
|
|
|
func (h *CommonHandler) GetUserIDFromContext(c *gin.Context) (string, error) {
|
|
|
|
|
userID, exists := c.Get("user_id")
|
|
|
|
|
if !exists {
|
P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.
Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.
Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).
Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.
Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 10:14:38 +00:00
|
|
|
return "", apperrors.NewUnauthorizedError("User not authenticated")
|
2025-12-03 19:29:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
userIDStr, ok := userID.(string)
|
|
|
|
|
if !ok {
|
P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.
Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.
Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).
Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.
Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 10:14:38 +00:00
|
|
|
return "", apperrors.New(apperrors.ErrCodeValidation, "Invalid user ID type")
|
2025-12-03 19:29:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return userIDStr, nil
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-16 16:23:49 +00:00
|
|
|
// GetUserIDUUID extrait l'ID utilisateur du contexte comme uuid.UUID (MOD-P1-001)
|
|
|
|
|
// Retourne false si user_id est absent ou invalide (répond déjà avec 401)
|
|
|
|
|
func GetUserIDUUID(c *gin.Context) (uuid.UUID, bool) {
|
|
|
|
|
userIDInterface, exists := c.Get("user_id")
|
|
|
|
|
if !exists {
|
|
|
|
|
RespondWithAppError(c, apperrors.NewUnauthorizedError("unauthorized"))
|
|
|
|
|
return uuid.Nil, false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
userID, ok := userIDInterface.(uuid.UUID)
|
|
|
|
|
if !ok {
|
|
|
|
|
RespondWithAppError(c, apperrors.NewUnauthorizedError("unauthorized"))
|
|
|
|
|
return uuid.Nil, false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return userID, true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// WithTimeout crée un context avec timeout pour les opérations I/O critiques (MOD-P1-004)
|
|
|
|
|
// Utilise le timeout par défaut de 5s pour DB/Redis, ou le timeout fourni
|
|
|
|
|
func WithTimeout(ctx context.Context, timeout time.Duration) (context.Context, context.CancelFunc) {
|
|
|
|
|
if timeout == 0 {
|
|
|
|
|
timeout = 5 * time.Second // Default timeout pour DB/Redis
|
|
|
|
|
}
|
|
|
|
|
return context.WithTimeout(ctx, timeout)
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-12 05:13:38 +00:00
|
|
|
// SECURITY(MEDIUM-004): clampLimit ensures limit is within [1, 100].
|
|
|
|
|
// Prevents unbounded queries that could cause DoS.
|
|
|
|
|
func clampLimit(limit int) int {
|
|
|
|
|
if limit < 1 {
|
|
|
|
|
return 20
|
|
|
|
|
}
|
|
|
|
|
if limit > 100 {
|
|
|
|
|
return 100
|
|
|
|
|
}
|
|
|
|
|
return limit
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-03 19:29:37 +00:00
|
|
|
// GetPaginationParams extrait les paramètres de pagination de la requête
|
|
|
|
|
func (h *CommonHandler) GetPaginationParams(c *gin.Context) (page, limit int, cursor string) {
|
|
|
|
|
page = 1
|
|
|
|
|
limit = 20
|
|
|
|
|
|
|
|
|
|
if pageStr := c.Query("page"); pageStr != "" {
|
|
|
|
|
if p, err := strconv.Atoi(pageStr); err == nil && p > 0 {
|
|
|
|
|
page = p
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if limitStr := c.Query("limit"); limitStr != "" {
|
|
|
|
|
if l, err := strconv.Atoi(limitStr); err == nil && l > 0 && l <= 100 {
|
|
|
|
|
limit = l
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cursor = c.Query("cursor")
|
|
|
|
|
return page, limit, cursor
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ValidatePagination valide les paramètres de pagination
|
|
|
|
|
// GO-013: Utilise dto.ValidationError
|
|
|
|
|
func (h *CommonHandler) ValidatePagination(page, limit int) []dto.ValidationError {
|
|
|
|
|
var validationErrors []dto.ValidationError
|
|
|
|
|
|
|
|
|
|
if page < 1 {
|
|
|
|
|
validationErrors = append(validationErrors, dto.ValidationError{
|
|
|
|
|
Field: "page",
|
|
|
|
|
Message: "Page must be greater than 0",
|
|
|
|
|
Value: strconv.Itoa(page),
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if limit < 1 || limit > 100 {
|
|
|
|
|
validationErrors = append(validationErrors, dto.ValidationError{
|
|
|
|
|
Field: "limit",
|
|
|
|
|
Message: "Limit must be between 1 and 100",
|
|
|
|
|
Value: strconv.Itoa(limit),
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return validationErrors
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// LogRequest log une requête entrante
|
|
|
|
|
func (h *CommonHandler) LogRequest(c *gin.Context, operation string) {
|
|
|
|
|
h.logger.Info("Request received",
|
|
|
|
|
zap.String("method", c.Request.Method),
|
|
|
|
|
zap.String("path", c.Request.URL.Path),
|
|
|
|
|
zap.String("operation", operation),
|
|
|
|
|
zap.String("user_id", c.GetString("user_id")),
|
|
|
|
|
zap.String("request_id", c.GetString("request_id")),
|
|
|
|
|
zap.String("ip", c.ClientIP()),
|
|
|
|
|
zap.String("user_agent", c.Request.UserAgent()),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// LogResponse log une réponse sortante
|
|
|
|
|
func (h *CommonHandler) LogResponse(c *gin.Context, statusCode int, duration time.Duration) {
|
|
|
|
|
h.logger.Info("Response sent",
|
|
|
|
|
zap.Int("status_code", statusCode),
|
|
|
|
|
zap.Duration("duration", duration),
|
|
|
|
|
zap.String("request_id", c.GetString("request_id")),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SetRequestID middleware pour ajouter un ID de requête
|
|
|
|
|
func (h *CommonHandler) SetRequestID() gin.HandlerFunc {
|
|
|
|
|
return func(c *gin.Context) {
|
|
|
|
|
requestID := c.GetHeader("X-Request-ID")
|
|
|
|
|
if requestID == "" {
|
|
|
|
|
requestID = generateRequestID()
|
|
|
|
|
}
|
|
|
|
|
c.Set("request_id", requestID)
|
|
|
|
|
c.Header("X-Request-ID", requestID)
|
|
|
|
|
c.Next()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// generateRequestID génère un ID de requête unique
|
|
|
|
|
func generateRequestID() string {
|
|
|
|
|
return strconv.FormatInt(time.Now().UnixNano(), 36)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ValidateRequiredFields valide que les champs requis sont présents
|
|
|
|
|
// GO-013: Utilise dto.ValidationError
|
|
|
|
|
func (h *CommonHandler) ValidateRequiredFields(fields map[string]interface{}) []dto.ValidationError {
|
|
|
|
|
var validationErrors []dto.ValidationError
|
|
|
|
|
|
|
|
|
|
for field, value := range fields {
|
|
|
|
|
if value == nil || value == "" {
|
|
|
|
|
validationErrors = append(validationErrors, dto.ValidationError{
|
|
|
|
|
Field: field,
|
|
|
|
|
Message: "This field is required",
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return validationErrors
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SanitizeString nettoie une chaîne de caractères
|
|
|
|
|
func (h *CommonHandler) SanitizeString(input string) string {
|
|
|
|
|
// Supprimer les caractères de contrôle et les espaces en début/fin
|
|
|
|
|
cleaned := strings.TrimSpace(input)
|
|
|
|
|
|
|
|
|
|
// Limiter la longueur
|
|
|
|
|
if len(cleaned) > 1000 {
|
|
|
|
|
cleaned = cleaned[:1000]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return cleaned
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ParseJSON parse du JSON de manière sécurisée
|
|
|
|
|
func (h *CommonHandler) ParseJSON(data []byte, v interface{}) error {
|
|
|
|
|
if err := json.Unmarshal(data, v); err != nil {
|
|
|
|
|
h.logger.Error("Failed to parse JSON", zap.Error(err))
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-06 16:21:59 +00:00
|
|
|
// SafeMarshalJSON sérialise en JSON de manière sécurisée
|
|
|
|
|
func (h *CommonHandler) SafeMarshalJSON(v interface{}) ([]byte, error) {
|
2025-12-03 19:29:37 +00:00
|
|
|
data, err := json.Marshal(v)
|
|
|
|
|
if err != nil {
|
|
|
|
|
h.logger.Error("Failed to marshal JSON", zap.Error(err))
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return data, nil
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-13 23:44:46 +00:00
|
|
|
// GetClientIP obtient l'IP réelle du client via Gin's trusted proxy mechanism.
|
|
|
|
|
// SECURITY(REM-006): Uses c.ClientIP() which respects SetTrustedProxies() instead of
|
|
|
|
|
// manually parsing X-Forwarded-For (which is spoofable).
|
2025-12-03 19:29:37 +00:00
|
|
|
func (h *CommonHandler) GetClientIP(c *gin.Context) string {
|
|
|
|
|
return c.ClientIP()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// RateLimitKey génère une clé pour le rate limiting
|
|
|
|
|
func (h *CommonHandler) RateLimitKey(c *gin.Context, prefix string) string {
|
|
|
|
|
userID := c.GetString("user_id")
|
|
|
|
|
if userID != "" {
|
|
|
|
|
return prefix + ":user:" + userID
|
|
|
|
|
}
|
|
|
|
|
return prefix + ":ip:" + h.GetClientIP(c)
|
|
|
|
|
}
|
2026-03-13 23:44:46 +00:00
|
|
|
|
|
|
|
|
// GetAllowedWebSocketOrigins returns the list of allowed origins for WebSocket connections.
|
|
|
|
|
// SECURITY(REM-001): Replaces InsecureSkipVerify: true with explicit origin whitelist.
|
|
|
|
|
func GetAllowedWebSocketOrigins() []string {
|
|
|
|
|
originsStr := os.Getenv("CORS_ALLOWED_ORIGINS")
|
|
|
|
|
if originsStr == "" {
|
|
|
|
|
// Default development origins
|
|
|
|
|
return []string{"http://localhost:*", "http://127.0.0.1:*", "http://veza.fr:*"}
|
|
|
|
|
}
|
|
|
|
|
origins := strings.Split(originsStr, ",")
|
|
|
|
|
var patterns []string
|
|
|
|
|
for _, o := range origins {
|
|
|
|
|
o = strings.TrimSpace(o)
|
|
|
|
|
if o != "" {
|
|
|
|
|
patterns = append(patterns, o)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if len(patterns) == 0 {
|
|
|
|
|
return []string{"http://localhost:*"}
|
|
|
|
|
}
|
|
|
|
|
return patterns
|
|
|
|
|
}
|