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

695 lines
24 KiB
Go
Raw Normal View History

2025-12-03 19:29:37 +00:00
package handlers
import (
"fmt"
2025-12-03 19:29:37 +00:00
"net/http"
"strings"
"time"
2026-01-07 18:39:21 +00:00
"veza-backend-api/internal/config"
2025-12-03 19:29:37 +00:00
"veza-backend-api/internal/core/auth"
"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-16 16:23:49 +00:00
2025-12-03 19:29:37 +00:00
// "veza-backend-api/internal/response" // Removed this import
"veza-backend-api/internal/services"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"go.uber.org/zap"
)
// Login gère la connexion des utilisateurs
// @Summary User Login
2026-01-07 18:39:21 +00:00
// @Description Authenticate user and return access token. Refresh token is set in httpOnly cookie.
// @Tags Auth
// @Accept json
// @Produce json
// @Param request body dto.LoginRequest true "Login Credentials"
2026-01-07 18:39:21 +00:00
// @Success 200 {object} dto.LoginResponse "Access token returned in body, refresh token in httpOnly cookie"
// @Failure 400 {object} handlers.APIResponse "Validation or Bad Request"
// @Failure 401 {object} handlers.APIResponse "Invalid credentials"
// @Failure 500 {object} handlers.APIResponse "Internal Error"
// @Router /auth/login [post]
2026-01-07 18:39:21 +00:00
func Login(authService *auth.AuthService, sessionService *services.SessionService, twoFactorService *services.TwoFactorService, logger *zap.Logger, cfg *config.Config) gin.HandlerFunc {
2025-12-03 19:29:37 +00:00
return func(c *gin.Context) {
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
commonHandler := NewCommonHandler(logger)
2025-12-03 19:29:37 +00:00
var req dto.LoginRequest
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
if appErr := commonHandler.BindAndValidateJSON(c, &req); appErr != nil {
RespondWithAppError(c, appErr)
2025-12-03 19:29:37 +00:00
return
}
// req.RememberMe is a bool, not *bool, so no need to check for nil or indirect
rememberMe := req.RememberMe
if logger != nil {
logger.Info("Login handler processing request",
zap.String("email", req.Email),
zap.Bool("remember_me", rememberMe),
)
}
2025-12-16 16:23:49 +00:00
// MOD-P1-004: Ajouter timeout context pour opération DB critique (login)
ctx, cancel := WithTimeout(c.Request.Context(), 5*time.Second)
defer cancel()
user, tokens, err := authService.Login(ctx, req.Email, req.Password, rememberMe)
2025-12-03 19:29:37 +00:00
if err != nil {
// MOD-P1-002: Improved error handling
errMsg := err.Error()
if strings.Contains(strings.ToLower(errMsg), "email not verified") {
2025-12-16 16:23:49 +00:00
RespondWithAppError(c, apperrors.New(apperrors.ErrCodeForbidden, "Email not verified"))
2025-12-03 19:29:37 +00:00
return
}
if strings.Contains(strings.ToLower(errMsg), "account is locked") {
// Return 423 Locked or 403 Forbidden
// Using c.JSON to specific 423 for clarity
c.JSON(http.StatusLocked, gin.H{
"success": false,
"error": gin.H{
"code": 423,
"message": "Account is locked. Please try again later.",
},
})
2025-12-03 19:29:37 +00:00
return
}
// Check for invalid credentials (case insensitive)
if strings.Contains(strings.ToLower(errMsg), "invalid credentials") ||
strings.Contains(strings.ToLower(errMsg), "user not found") ||
strings.Contains(strings.ToLower(errMsg), "record not found") {
fmt.Println("DEBUG: Using c.JSON(401)")
// Try direct JSON response to rule out helper issues
c.JSON(http.StatusUnauthorized, gin.H{
"success": false,
"error": gin.H{
"code": 401,
"message": "Invalid credentials",
},
})
return
}
// Fallback: log and return 500
if logger != nil {
logger.Error("Login error fell through to 500", zap.Error(err))
}
2025-12-16 16:23:49 +00:00
RespondWithAppError(c, apperrors.Wrap(apperrors.ErrCodeInternal, "Failed to authenticate", err))
2025-12-03 19:29:37 +00:00
return
}
// BE-API-001: Check if 2FA is enabled for user
var requires2FA bool
if twoFactorService != nil {
requires2FA, err = twoFactorService.GetTwoFactorStatus(ctx, user.ID)
if err != nil {
logger.Warn("Failed to check 2FA status", zap.Error(err), zap.String("user_id", user.ID.String()))
// Continue without 2FA check if error
requires2FA = false
}
}
// If 2FA is required, return flag without tokens
if requires2FA {
RespondSuccess(c, http.StatusOK, dto.LoginResponse{
User: dto.UserResponse{
ID: user.ID,
Email: user.Email,
Username: user.Username,
},
Requires2FA: true,
})
return
}
2025-12-03 19:29:37 +00:00
if sessionService != nil {
ipAddress := c.ClientIP()
userAgent := c.GetHeader("User-Agent")
if userAgent == "" {
userAgent = "Unknown"
}
expiresIn := 30 * 24 * time.Hour
if rememberMe {
expiresIn = 90 * 24 * time.Hour
}
sessionReq := &services.SessionCreateRequest{
UserID: user.ID,
Token: tokens.AccessToken,
IPAddress: ipAddress,
UserAgent: userAgent,
ExpiresIn: expiresIn,
}
2025-12-16 16:23:49 +00:00
// MOD-P1-004: Ajouter timeout context pour opération DB (session)
sessionCtx, sessionCancel := WithTimeout(c.Request.Context(), 3*time.Second)
defer sessionCancel()
if _, err := sessionService.CreateSession(sessionCtx, sessionReq); err != nil {
2025-12-03 19:29:37 +00:00
if logger != nil {
logger.Warn("Failed to create session after login",
zap.String("user_id", user.ID.String()),
zap.String("ip_address", ipAddress),
zap.Error(err),
)
}
}
}
2026-01-07 18:39:21 +00:00
// SECURITY: Set refresh token in httpOnly cookie
refreshTokenExpires := 30 * 24 * time.Hour // 30 jours par défaut
if rememberMe {
refreshTokenExpires = 90 * 24 * time.Hour // 90 jours si remember me
}
// Utiliser http.Cookie pour supporter SameSite avec configuration depuis env
refreshTokenCookie := &http.Cookie{
Name: "refresh_token",
Value: tokens.RefreshToken,
Path: cfg.CookiePath,
Domain: cfg.CookieDomain,
MaxAge: int(refreshTokenExpires.Seconds()),
HttpOnly: cfg.CookieHttpOnly,
Secure: cfg.ShouldUseSecureCookies(),
SameSite: cfg.GetCookieSameSite(),
}
http.SetCookie(c.Writer, refreshTokenCookie)
// SECURITY: Set access token in httpOnly cookie
accessTokenExpires := authService.JWTService.GetConfig().AccessTokenTTL
accessTokenCookie := &http.Cookie{
Name: "access_token",
Value: tokens.AccessToken,
Path: cfg.CookiePath,
Domain: cfg.CookieDomain,
MaxAge: int(accessTokenExpires.Seconds()),
HttpOnly: cfg.CookieHttpOnly,
Secure: cfg.ShouldUseSecureCookies(),
SameSite: cfg.GetCookieSameSite(),
}
http.SetCookie(c.Writer, accessTokenCookie)
2026-01-07 18:39:21 +00:00
// Retourner uniquement l'access token dans le body (pas le refresh token)
RespondSuccess(c, http.StatusOK, dto.LoginResponse{
2025-12-03 19:29:37 +00:00
User: dto.UserResponse{
ID: user.ID,
Email: user.Email,
Username: user.Username,
2025-12-03 19:29:37 +00:00
},
Token: dto.TokenResponse{
2026-01-07 18:39:21 +00:00
AccessToken: tokens.AccessToken,
// RefreshToken: tokens.RefreshToken, // ❌ Ne plus retourner dans le body
ExpiresIn: int(authService.JWTService.GetConfig().AccessTokenTTL.Seconds()),
2025-12-03 19:29:37 +00:00
},
})
}
}
// Register gère l'inscription des utilisateurs
// @Summary User Registration
// @Description Register a new user account
// @Tags Auth
// @Accept json
// @Produce json
// @Param request body dto.RegisterRequest true "Registration Data"
// @Success 201 {object} dto.RegisterResponse
// @Failure 400 {object} handlers.APIResponse "Validation Error"
// @Failure 409 {object} handlers.APIResponse "User already exists"
// @Failure 500 {object} handlers.APIResponse "Internal Error"
// @Router /auth/register [post]
2026-01-07 18:39:21 +00:00
func Register(authService *auth.AuthService, sessionService *services.SessionService, logger *zap.Logger, cfg *config.Config) gin.HandlerFunc {
2025-12-03 19:29:37 +00:00
return func(c *gin.Context) {
// FIX #6: Utiliser logger.Debug() pour les logs de debug au lieu de logger.Info()
logger.Debug("Register handler called", zap.String("path", c.Request.URL.Path), zap.String("method", c.Request.Method))
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
commonHandler := NewCommonHandler(logger)
2025-12-03 19:29:37 +00:00
var req dto.RegisterRequest
logger.Debug("Before BindAndValidateJSON")
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
if appErr := commonHandler.BindAndValidateJSON(c, &req); appErr != nil {
logger.Debug("BindAndValidateJSON failed", zap.Error(appErr))
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
RespondWithAppError(c, appErr)
2025-12-03 19:29:37 +00:00
return
}
logger.Debug("After BindAndValidateJSON success", zap.String("email", req.Email), zap.String("username", req.Username))
2025-12-03 19:29:37 +00:00
logger.Debug("Handler register start", zap.String("email", req.Email), zap.String("username", req.Username))
2025-12-16 16:23:49 +00:00
// MOD-P1-004: Ajouter timeout context pour opération DB critique (register)
ctx, cancel := WithTimeout(c.Request.Context(), 5*time.Second)
defer cancel()
logger.Debug("Calling auth service register", zap.String("email", req.Email))
user, tokens, err := authService.Register(ctx, req.Email, req.Username, req.Password)
logger.Debug("Auth service register returned", zap.Error(err), zap.Bool("user_nil", user == nil), zap.Bool("tokens_nil", tokens == nil))
2025-12-03 19:29:37 +00:00
if err != nil {
2025-12-16 16:23:49 +00:00
// MOD-P1-002: Utiliser RespondWithAppError au lieu de gin.H{"error"}
2025-12-03 19:29:37 +00:00
switch {
case services.IsUserAlreadyExistsError(err):
2025-12-16 16:23:49 +00:00
RespondWithAppError(c, apperrors.New(apperrors.ErrCodeConflict, "User already exists"))
2025-12-03 19:29:37 +00:00
case services.IsInvalidEmail(err):
2025-12-16 16:23:49 +00:00
RespondWithAppError(c, apperrors.NewValidationError("Invalid email format"))
2025-12-03 19:29:37 +00:00
case services.IsWeakPassword(err):
2025-12-16 16:23:49 +00:00
RespondWithAppError(c, apperrors.NewValidationError("Password does not meet requirements"))
2025-12-03 19:29:37 +00:00
default:
// Log l'erreur complète pour diagnostic
commonHandler.logger.Error("Registration failed - FULL ERROR",
zap.Error(err),
zap.String("error_type", fmt.Sprintf("%T", err)),
zap.String("error_string", err.Error()),
zap.String("email", req.Email),
zap.String("username", req.Username),
)
2025-12-16 16:23:49 +00:00
RespondWithAppError(c, apperrors.Wrap(apperrors.ErrCodeInternal, "Failed to create user", err))
2025-12-03 19:29:37 +00:00
}
return
}
// MVP: Créer une session en base pour permettre l'utilisation immédiate du token
// (comme dans Login)
if sessionService != nil {
logger.Debug("Creating session after registration", zap.String("user_id", user.ID.String()))
ipAddress := c.ClientIP()
userAgent := c.GetHeader("User-Agent")
if userAgent == "" {
userAgent = "Unknown"
}
// Session par défaut: 30 jours
expiresIn := 30 * 24 * time.Hour
sessionCtx, sessionCancel := WithTimeout(c.Request.Context(), 3*time.Second)
defer sessionCancel()
sessionReq := &services.SessionCreateRequest{
UserID: user.ID,
Token: tokens.AccessToken,
IPAddress: ipAddress,
UserAgent: userAgent,
ExpiresIn: expiresIn,
}
if _, err := sessionService.CreateSession(sessionCtx, sessionReq); err != nil {
logger.Warn("Failed to create session after registration",
zap.String("user_id", user.ID.String()),
zap.String("ip_address", ipAddress),
zap.Error(err),
)
// Non-bloquant: on continue même si la session n'est pas créée
// L'utilisateur pourra se reconnecter pour créer une session
} else {
logger.Debug("Session created successfully after registration", zap.String("user_id", user.ID.String()))
}
} else {
logger.Warn("SessionService not available - skipping session creation after registration")
}
2026-01-07 18:39:21 +00:00
// SECURITY: Set refresh token in httpOnly cookie
refreshTokenExpires := 30 * 24 * time.Hour // 30 jours par défaut
// Utiliser http.Cookie pour supporter SameSite avec configuration depuis env
refreshTokenCookie := &http.Cookie{
Name: "refresh_token",
Value: tokens.RefreshToken,
Path: cfg.CookiePath,
Domain: cfg.CookieDomain,
MaxAge: int(refreshTokenExpires.Seconds()),
HttpOnly: cfg.CookieHttpOnly,
Secure: cfg.ShouldUseSecureCookies(),
SameSite: cfg.GetCookieSameSite(),
}
http.SetCookie(c.Writer, refreshTokenCookie)
// SECURITY: Set access token in httpOnly cookie
accessTokenExpires := authService.JWTService.GetConfig().AccessTokenTTL
accessTokenCookie := &http.Cookie{
Name: "access_token",
Value: tokens.AccessToken,
Path: cfg.CookiePath,
Domain: cfg.CookieDomain,
MaxAge: int(accessTokenExpires.Seconds()),
HttpOnly: cfg.CookieHttpOnly,
Secure: cfg.ShouldUseSecureCookies(),
SameSite: cfg.GetCookieSameSite(),
}
http.SetCookie(c.Writer, accessTokenCookie)
2026-01-07 18:39:21 +00:00
// Construire la réponse avec uniquement l'access token (pas le refresh token)
response := dto.RegisterResponse{
2025-12-03 19:29:37 +00:00
User: dto.UserResponse{
ID: user.ID,
Email: user.Email,
Username: user.Username,
},
Token: dto.TokenResponse{
2026-01-07 18:39:21 +00:00
AccessToken: tokens.AccessToken,
// RefreshToken: tokens.RefreshToken, // ❌ Ne plus retourner dans le body
ExpiresIn: tokens.ExpiresIn,
},
}
RespondSuccess(c, http.StatusCreated, response)
2025-12-03 19:29:37 +00:00
}
}
// Refresh gère le rafraîchissement d'un access token
// @Summary Refresh Token
// @Description Get a new access token using a refresh token
// @Tags Auth
// @Accept json
// @Produce json
// @Param request body dto.RefreshRequest true "Refresh Token"
// @Success 200 {object} dto.TokenResponse
// @Failure 400 {object} handlers.APIResponse "Validation Error"
// @Failure 401 {object} handlers.APIResponse "Invalid/Expired Refresh Token"
// @Failure 500 {object} handlers.APIResponse "Internal Error"
// @Router /auth/refresh [post]
2026-01-07 18:39:21 +00:00
func Refresh(authService *auth.AuthService, sessionService *services.SessionService, logger *zap.Logger, cfg *config.Config) gin.HandlerFunc {
2025-12-03 19:29:37 +00:00
return func(c *gin.Context) {
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
commonHandler := NewCommonHandler(logger)
2026-01-07 18:39:21 +00:00
// SECURITY: Récupérer le refresh token depuis le cookie httpOnly (priorité)
// Fallback sur le body JSON pour compatibilité avec l'ancien système
var refreshToken string
if cookie, err := c.Cookie("refresh_token"); err == nil && cookie != "" {
refreshToken = cookie
} else {
// Fallback: lire depuis le body JSON (mode legacy)
var req dto.RefreshRequest
if appErr := commonHandler.BindAndValidateJSON(c, &req); appErr != nil {
RespondWithAppError(c, appErr)
return
}
refreshToken = req.RefreshToken
}
if refreshToken == "" {
RespondWithAppError(c, apperrors.NewUnauthorizedError("Refresh token is required"))
2025-12-03 19:29:37 +00:00
return
}
2026-01-07 18:39:21 +00:00
tokens, err := authService.Refresh(c.Request.Context(), refreshToken)
2025-12-03 19:29:37 +00:00
if err != nil {
2025-12-16 16:23:49 +00:00
// MOD-P1-002: Utiliser RespondWithAppError au lieu de gin.H{"error"}
2025-12-03 19:29:37 +00:00
if strings.Contains(err.Error(), "invalid refresh token") ||
strings.Contains(err.Error(), "not found") ||
strings.Contains(err.Error(), "expired") ||
strings.Contains(err.Error(), "token version mismatch") {
2025-12-16 16:23:49 +00:00
RespondWithAppError(c, apperrors.NewUnauthorizedError("Invalid refresh token"))
2025-12-03 19:29:37 +00:00
return
}
2025-12-16 16:23:49 +00:00
RespondWithAppError(c, apperrors.Wrap(apperrors.ErrCodeInternal, "Failed to refresh token", err))
2025-12-03 19:29:37 +00:00
return
}
// INT-017: Créer une nouvelle session lors du refresh token
if sessionService != nil {
// Récupérer l'ID utilisateur depuis le refresh token
2026-01-07 18:39:21 +00:00
claims, err := authService.JWTService.ValidateToken(refreshToken)
if err == nil && claims != nil {
ipAddress := c.ClientIP()
userAgent := c.GetHeader("User-Agent")
if userAgent == "" {
userAgent = "Unknown"
}
// Utiliser la même durée d'expiration que le token d'accès
expiresIn := 30 * 24 * time.Hour
if authService.JWTService != nil {
expiresIn = authService.JWTService.GetConfig().AccessTokenTTL
}
sessionReq := &services.SessionCreateRequest{
UserID: claims.UserID,
Token: tokens.AccessToken,
IPAddress: ipAddress,
UserAgent: userAgent,
ExpiresIn: expiresIn,
}
// MOD-P1-004: Ajouter timeout context pour opération DB (session)
sessionCtx, sessionCancel := WithTimeout(c.Request.Context(), 3*time.Second)
defer sessionCancel()
if _, err := sessionService.CreateSession(sessionCtx, sessionReq); err != nil {
if logger != nil {
logger.Warn("Failed to create session after refresh",
zap.String("user_id", claims.UserID.String()),
zap.String("ip_address", ipAddress),
zap.Error(err),
)
}
}
}
}
2026-01-07 18:39:21 +00:00
// SECURITY: Set refresh token in httpOnly cookie
// Utiliser la même durée que le refresh token original (30 jours par défaut)
refreshTokenExpires := 30 * 24 * time.Hour
// Utiliser http.Cookie pour supporter SameSite avec configuration depuis env
refreshTokenCookie := &http.Cookie{
Name: "refresh_token",
Value: tokens.RefreshToken,
Path: cfg.CookiePath,
Domain: cfg.CookieDomain,
MaxAge: int(refreshTokenExpires.Seconds()),
HttpOnly: cfg.CookieHttpOnly,
Secure: cfg.ShouldUseSecureCookies(),
SameSite: cfg.GetCookieSameSite(),
}
http.SetCookie(c.Writer, refreshTokenCookie)
// SECURITY: Set access token in httpOnly cookie
accessTokenExpires := authService.JWTService.GetConfig().AccessTokenTTL
accessTokenCookie := &http.Cookie{
Name: "access_token",
Value: tokens.AccessToken,
Path: cfg.CookiePath,
Domain: cfg.CookieDomain,
MaxAge: int(accessTokenExpires.Seconds()),
HttpOnly: cfg.CookieHttpOnly,
Secure: cfg.ShouldUseSecureCookies(),
SameSite: cfg.GetCookieSameSite(),
}
http.SetCookie(c.Writer, accessTokenCookie)
// Calculate ExpiresIn from tokens if available, otherwise use JWTService config
expiresIn := tokens.ExpiresIn
if expiresIn == 0 && authService.JWTService != nil {
expiresIn = int(authService.JWTService.GetConfig().AccessTokenTTL.Seconds())
}
2026-01-07 18:39:21 +00:00
// Retourner uniquement l'access token dans le body (pas le refresh token)
RespondSuccess(c, http.StatusOK, dto.TokenResponse{
2026-01-07 18:39:21 +00:00
AccessToken: tokens.AccessToken,
// RefreshToken: tokens.RefreshToken, // ❌ Ne plus retourner dans le body
ExpiresIn: expiresIn,
2025-12-03 19:29:37 +00:00
})
}
}
// Logout gère la déconnexion des utilisateurs
// @Summary Logout
// @Description Revoke refresh token and current session
// @Tags Auth
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param request body object{refresh_token=string} true "Refresh Token to revoke"
// @Success 200 {object} handlers.APIResponse "Success message"
// @Failure 400 {object} handlers.APIResponse "Validation Error"
// @Failure 401 {object} handlers.APIResponse "Unauthorized"
// @Router /auth/logout [post]
2026-01-07 18:39:21 +00:00
func Logout(authService *auth.AuthService, sessionService *services.SessionService, logger *zap.Logger, cfg *config.Config) gin.HandlerFunc {
2025-12-03 19:29:37 +00:00
return func(c *gin.Context) {
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
commonHandler := NewCommonHandler(logger)
2025-12-03 19:29:37 +00:00
userIDInterface, 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
RespondWithAppError(c, apperrors.NewUnauthorizedError("User not authenticated"))
2025-12-03 19:29:37 +00:00
return
}
userID, ok := userIDInterface.(uuid.UUID)
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
RespondWithAppError(c, apperrors.New(apperrors.ErrCodeInternal, "Invalid user ID type in context"))
2025-12-03 19:29:37 +00:00
return
}
var req struct {
RefreshToken string `json:"refresh_token" binding:"required"`
}
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
if appErr := commonHandler.BindAndValidateJSON(c, &req); appErr != nil {
RespondWithAppError(c, appErr)
2025-12-03 19:29:37 +00:00
return
}
if err := authService.Logout(c.Request.Context(), userID, req.RefreshToken); err != nil {
// Log the error but don't fail the request to prevent leaking info
}
if sessionService != nil {
authHeader := c.GetHeader("Authorization")
if authHeader != "" && strings.HasPrefix(authHeader, "Bearer ") {
token := strings.TrimPrefix(authHeader, "Bearer ")
if err := sessionService.RevokeSession(c.Request.Context(), token); err != nil {
// Log the error but don't fail the request
}
}
}
2026-01-07 18:39:21 +00:00
// SECURITY: Supprimer le cookie refresh_token lors du logout
refreshTokenCookie := &http.Cookie{
Name: "refresh_token",
Value: "",
Path: cfg.CookiePath,
Domain: cfg.CookieDomain,
MaxAge: -1, // Supprimer le cookie
HttpOnly: cfg.CookieHttpOnly,
Secure: cfg.ShouldUseSecureCookies(),
SameSite: cfg.GetCookieSameSite(),
}
http.SetCookie(c.Writer, refreshTokenCookie)
RespondSuccess(c, http.StatusOK, gin.H{"message": "Logged out successfully"})
2025-12-03 19:29:37 +00:00
}
}
// VerifyEmail gère la vérification de l'email
// @Summary Verify Email
// @Description Verify user email address using a token
// @Tags Auth
// @Accept json
// @Produce json
// @Param token query string true "Verification Token"
// @Success 200 {object} handlers.APIResponse "Success message"
// @Failure 400 {object} handlers.APIResponse "Invalid Token"
// @Router /auth/verify-email [post]
2025-12-03 19:29:37 +00:00
func VerifyEmail(authService *auth.AuthService) gin.HandlerFunc {
return func(c *gin.Context) {
token := c.Query("token")
if token == "" {
2025-12-16 16:23:49 +00:00
// MOD-P1-002: Utiliser RespondWithAppError au lieu de gin.H{"error"}
RespondWithAppError(c, apperrors.NewValidationError("Token required"))
2025-12-03 19:29:37 +00:00
return
}
if err := authService.VerifyEmail(c.Request.Context(), token); err != nil {
2025-12-16 16:23:49 +00:00
// MOD-P1-002: Utiliser RespondWithAppError au lieu de gin.H{"error"}
RespondWithAppError(c, apperrors.Wrap(apperrors.ErrCodeValidation, "Email verification failed", err))
2025-12-03 19:29:37 +00:00
return
}
RespondSuccess(c, http.StatusOK, gin.H{"message": "Email verified successfully"})
2025-12-03 19:29:37 +00:00
}
}
// ResendVerification gère la demande de renvoi d'email de vérification
// @Summary Resend Verification Email
// @Description Resend the email verification link
// @Tags Auth
// @Accept json
// @Produce json
// @Param request body dto.ResendVerificationRequest true "Email"
// @Success 200 {object} handlers.APIResponse "Success message"
// @Failure 400 {object} handlers.APIResponse "Validation Error"
// @Router /auth/resend-verification [post]
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
func ResendVerification(authService *auth.AuthService, logger *zap.Logger) gin.HandlerFunc {
2025-12-03 19:29:37 +00:00
return func(c *gin.Context) {
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
commonHandler := NewCommonHandler(logger)
2025-12-03 19:29:37 +00:00
var req dto.ResendVerificationRequest
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
if appErr := commonHandler.BindAndValidateJSON(c, &req); appErr != nil {
RespondWithAppError(c, appErr)
2025-12-03 19:29:37 +00:00
return
}
if err := authService.ResendVerificationEmail(c.Request.Context(), req.Email); err != nil {
2025-12-16 16:23:49 +00:00
// MOD-P1-002: Utiliser RespondWithAppError au lieu de gin.H{"error"}
2025-12-03 19:29:37 +00:00
if strings.Contains(err.Error(), "email already verified") {
2025-12-16 16:23:49 +00:00
RespondWithAppError(c, apperrors.NewValidationError(err.Error()))
2025-12-03 19:29:37 +00:00
return
}
2025-12-16 16:23:49 +00:00
RespondWithAppError(c, apperrors.Wrap(apperrors.ErrCodeInternal, "Failed to resend verification email", err))
return
2025-12-03 19:29:37 +00:00
}
RespondSuccess(c, http.StatusOK, gin.H{"message": "Verification email sent if account exists"})
2025-12-03 19:29:37 +00:00
}
}
// CheckUsername vérifie la disponibilité d'un nom d'utilisateur
// @Summary Check Username Availability
// @Description Check if a username is already taken
// @Tags Auth
// @Accept json
// @Produce json
// @Param username query string true "Username to check"
// @Success 200 {object} handlers.APIResponse{data=object{available=boolean,username=string}}
// @Failure 400 {object} handlers.APIResponse "Missing Username"
// @Router /auth/check-username [get]
2025-12-03 19:29:37 +00:00
func CheckUsername(authService *auth.AuthService) gin.HandlerFunc {
return func(c *gin.Context) {
username := c.Query("username")
if username == "" {
2025-12-16 16:23:49 +00:00
// MOD-P1-002: Utiliser RespondWithAppError au lieu de gin.H{"error"}
RespondWithAppError(c, apperrors.NewValidationError("Username is required"))
2025-12-03 19:29:37 +00:00
return
}
_, err := authService.GetUserByUsername(c.Request.Context(), username)
available := err != nil
RespondSuccess(c, http.StatusOK, gin.H{
2025-12-03 19:29:37 +00:00
"available": available,
"username": username,
})
}
}
// GetMe retourne les informations de l'utilisateur connecté
// @Summary Get Current User
// @Description Get profile information of the currently logged-in user
// @Tags Auth
// @Accept json
// @Produce json
// @Security BearerAuth
// @Success 200 {object} handlers.APIResponse{data=object}
// @Failure 401 {object} handlers.APIResponse "Unauthorized"
// @Failure 404 {object} handlers.APIResponse "User not found"
// @Router /auth/me [get]
func GetMe(userService *services.UserService) gin.HandlerFunc {
2025-12-03 19:29:37 +00:00
return func(c *gin.Context) {
userID, exists := c.Get("user_id")
if !exists {
2025-12-16 16:23:49 +00:00
// MOD-P1-002: Utiliser RespondWithAppError au lieu de gin.H{"error"}
RespondWithAppError(c, apperrors.NewUnauthorizedError("Unauthorized"))
2025-12-03 19:29:37 +00:00
return
}
// Convert userID to uuid.UUID
userUUID, ok := userID.(uuid.UUID)
if !ok {
// Try to parse as string if it's not already a UUID
userIDStr, ok := userID.(string)
if !ok {
RespondWithAppError(c, apperrors.New(apperrors.ErrCodeValidation, "invalid user id type"))
return
}
parsedUUID, err := uuid.Parse(userIDStr)
if err != nil {
RespondWithAppError(c, apperrors.New(apperrors.ErrCodeValidation, "invalid user id format"))
return
}
userUUID = parsedUUID
}
// Fetch full user from database
user, err := userService.GetProfileByID(userUUID)
if err != nil {
RespondWithAppError(c, apperrors.New(apperrors.ErrCodeNotFound, "user not found"))
return
}
// Return full user object
RespondSuccess(c, http.StatusOK, user)
2025-12-03 19:29:37 +00:00
}
}