209 lines
5.9 KiB
Go
209 lines
5.9 KiB
Go
//go:build ignore
|
|
// +build ignore
|
|
|
|
// TODO: Réactiver two_factor_handlers après stabilisation du noyau et alignement des services (AuthService.GetUserByID)
|
|
|
|
package handlers
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"go.uber.org/zap"
|
|
|
|
"veza-backend-api/internal/services"
|
|
)
|
|
|
|
// TwoFactorHandlers handles 2FA-related API endpoints
|
|
type TwoFactorHandlers struct {
|
|
twoFactorService *services.TwoFactorService
|
|
authService *services.AuthService
|
|
logger *zap.Logger
|
|
}
|
|
|
|
// NewTwoFactorHandlers creates new 2FA handlers
|
|
func NewTwoFactorHandlers(twoFactorService *services.TwoFactorService, authService *services.AuthService, logger *zap.Logger) *TwoFactorHandlers {
|
|
return &TwoFactorHandlers{
|
|
twoFactorService: twoFactorService,
|
|
authService: authService,
|
|
logger: logger,
|
|
}
|
|
}
|
|
|
|
// InitTwoFactorHandlers initializes 2FA handlers
|
|
func InitTwoFactorHandlers(twoFactorService *services.TwoFactorService, authService *services.AuthService, logger *zap.Logger) {
|
|
handlers := NewTwoFactorHandlers(twoFactorService, authService, logger)
|
|
|
|
// Store handlers globally for route registration
|
|
TwoFactorHandlersInstance = handlers
|
|
}
|
|
|
|
// TwoFactorHandlersInstance holds the global 2FA handlers instance
|
|
var TwoFactorHandlersInstance *TwoFactorHandlers
|
|
|
|
// SetupTwoFactor initiates 2FA setup for a user
|
|
func (h *TwoFactorHandlers) SetupTwoFactor(c *gin.Context) {
|
|
userID := c.GetInt64("user_id")
|
|
|
|
// Get user information
|
|
user, err := h.authService.GetUserByID(c.Request.Context(), userID)
|
|
if err != nil {
|
|
h.logger.Error("Failed to get user", zap.Error(err))
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get user information"})
|
|
return
|
|
}
|
|
|
|
// Check if 2FA is already enabled
|
|
enabled, err := h.twoFactorService.GetTwoFactorStatus(c.Request.Context(), userID)
|
|
if err != nil {
|
|
h.logger.Error("Failed to get 2FA status", zap.Error(err))
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get 2FA status"})
|
|
return
|
|
}
|
|
|
|
if enabled {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "2FA is already enabled"})
|
|
return
|
|
}
|
|
|
|
// Generate 2FA setup
|
|
setup, err := h.twoFactorService.GenerateSecret(user)
|
|
if err != nil {
|
|
h.logger.Error("Failed to generate 2FA setup", zap.Error(err))
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to generate 2FA setup"})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"success": true,
|
|
"setup": setup,
|
|
})
|
|
}
|
|
|
|
// EnableTwoFactor enables 2FA for a user
|
|
func (h *TwoFactorHandlers) EnableTwoFactor(c *gin.Context) {
|
|
userID := c.GetInt64("user_id")
|
|
|
|
var req struct {
|
|
Secret string `json:"secret" binding:"required"`
|
|
Code string `json:"code" binding:"required"`
|
|
RecoveryCodes []string `json:"recovery_codes" binding:"required"`
|
|
}
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
// Verify the code first
|
|
valid, err := h.twoFactorService.VerifyTwoFactor(c.Request.Context(), userID, req.Code)
|
|
if err != nil {
|
|
h.logger.Error("Failed to verify 2FA code", zap.Error(err))
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to verify 2FA code"})
|
|
return
|
|
}
|
|
|
|
if !valid {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid 2FA code"})
|
|
return
|
|
}
|
|
|
|
// Enable 2FA
|
|
err = h.twoFactorService.EnableTwoFactor(c.Request.Context(), userID, req.Secret, req.RecoveryCodes)
|
|
if err != nil {
|
|
h.logger.Error("Failed to enable 2FA", zap.Error(err))
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to enable 2FA"})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"success": true,
|
|
"message": "2FA enabled successfully",
|
|
})
|
|
}
|
|
|
|
// DisableTwoFactor disables 2FA for a user
|
|
func (h *TwoFactorHandlers) DisableTwoFactor(c *gin.Context) {
|
|
userID := c.GetInt64("user_id")
|
|
|
|
var req struct {
|
|
Code string `json:"code" binding:"required"`
|
|
}
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
// Verify the code first
|
|
valid, err := h.twoFactorService.VerifyTwoFactor(c.Request.Context(), userID, req.Code)
|
|
if err != nil {
|
|
h.logger.Error("Failed to verify 2FA code", zap.Error(err))
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to verify 2FA code"})
|
|
return
|
|
}
|
|
|
|
if !valid {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid 2FA code"})
|
|
return
|
|
}
|
|
|
|
// Disable 2FA
|
|
err = h.twoFactorService.DisableTwoFactor(c.Request.Context(), userID)
|
|
if err != nil {
|
|
h.logger.Error("Failed to disable 2FA", zap.Error(err))
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to disable 2FA"})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"success": true,
|
|
"message": "2FA disabled successfully",
|
|
})
|
|
}
|
|
|
|
// VerifyTwoFactor verifies a 2FA code
|
|
func (h *TwoFactorHandlers) VerifyTwoFactor(c *gin.Context) {
|
|
userID := c.GetInt64("user_id")
|
|
|
|
var req services.TwoFactorVerification
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
// Verify the code
|
|
valid, err := h.twoFactorService.VerifyTwoFactor(c.Request.Context(), userID, req.Code)
|
|
if err != nil {
|
|
h.logger.Error("Failed to verify 2FA code", zap.Error(err))
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to verify 2FA code"})
|
|
return
|
|
}
|
|
|
|
if !valid {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid 2FA code"})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"success": true,
|
|
"message": "2FA code verified successfully",
|
|
})
|
|
}
|
|
|
|
// GetTwoFactorStatus gets the 2FA status for a user
|
|
func (h *TwoFactorHandlers) GetTwoFactorStatus(c *gin.Context) {
|
|
userID := c.GetInt64("user_id")
|
|
|
|
enabled, err := h.twoFactorService.GetTwoFactorStatus(c.Request.Context(), userID)
|
|
if err != nil {
|
|
h.logger.Error("Failed to get 2FA status", zap.Error(err))
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get 2FA status"})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"success": true,
|
|
"enabled": enabled,
|
|
})
|
|
}
|