package handlers import ( "context" "net/http" "github.com/gin-gonic/gin" "github.com/google/uuid" "go.uber.org/zap" "veza-backend-api/internal/middleware" ) // CSRFHandler gère les handlers pour la protection CSRF type CSRFHandler struct { csrfMiddleware CSRFMiddlewareInterface logger *zap.Logger } // CSRFMiddlewareInterface defines methods needed for CSRF handler type CSRFMiddlewareInterface interface { GetToken(ctx context.Context, userID uuid.UUID) (string, error) } // NewCSRFHandler crée un nouveau handler CSRF func NewCSRFHandler(csrfMiddleware *middleware.CSRFMiddleware, logger *zap.Logger) *CSRFHandler { return &CSRFHandler{ csrfMiddleware: csrfMiddleware, logger: logger, } } // NewCSRFHandlerWithInterface creates a new CSRF handler with interface (for testing) func NewCSRFHandlerWithInterface(csrfMiddleware CSRFMiddlewareInterface, logger *zap.Logger) *CSRFHandler { return &CSRFHandler{ csrfMiddleware: csrfMiddleware, logger: logger, } } // GetCSRFToken retourne un token CSRF pour l'utilisateur authentifié // GET /api/v1/csrf-token func (h *CSRFHandler) GetCSRFToken() gin.HandlerFunc { return func(c *gin.Context) { // Récupérer le userID depuis le contexte (défini par AuthMiddleware.OptionalAuth) userIDInterface, exists := c.Get("user_id") if !exists { // Si pas d'utilisateur authentifié, on retourne un token public/anonyme // Le middleware CSRF côté serveur ignore la validation si user_id est absent du contexte // Action 1.3.2.1: Use wrapped format helper RespondSuccess(c, http.StatusOK, gin.H{ "csrf_token": "public-anonymous-token", }) return } userID, ok := userIDInterface.(uuid.UUID) if !ok { h.logger.Error("Invalid user_id type in context") // Action 1.3.2.1: Use wrapped format helper for errors RespondWithError(c, 500, "Internal server error") return } // Générer ou récupérer le token CSRF ctx := c.Request.Context() token, err := h.csrfMiddleware.GetToken(ctx, userID) if err != nil { h.logger.Error("Failed to get CSRF token", zap.Error(err), zap.String("user_id", userID.String()), ) // Action 1.3.2.1: Use wrapped format helper for errors RespondWithError(c, 500, "Failed to generate CSRF token") return } // Retourner le token // Action 1.3.2.1: Use wrapped format helper RespondSuccess(c, http.StatusOK, gin.H{ "csrf_token": token, }) } }