2026-02-15 13:44:33 +00:00
|
|
|
package config
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
|
"veza-backend-api/internal/middleware"
|
|
|
|
|
)
|
|
|
|
|
|
2026-02-22 16:52:50 +00:00
|
|
|
// InitMiddlewaresForTest initializes middlewares for integration/E2E tests.
|
|
|
|
|
// Exported for use by internal/integration and tests packages.
|
|
|
|
|
func (c *Config) InitMiddlewaresForTest() error {
|
|
|
|
|
return c.initMiddlewares()
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-15 13:44:33 +00:00
|
|
|
// initMiddlewares initialise tous les middlewares
|
|
|
|
|
func (c *Config) initMiddlewares() error {
|
|
|
|
|
// Rate limiter global (avec Redis)
|
|
|
|
|
// En développement, augmenter les limites pour éviter les erreurs lors des tests
|
|
|
|
|
ipLimit := getEnvInt("RATE_LIMIT_IP_PER_MINUTE", 200) // Augmenté de 100 à 200 en dev
|
|
|
|
|
ipBurst := getEnvInt("RATE_LIMIT_IP_BURST", 20) // Augmenté de 10 à 20 en dev
|
|
|
|
|
userLimit := getEnvInt("RATE_LIMIT_USER_PER_MINUTE", 1000)
|
|
|
|
|
userBurst := getEnvInt("RATE_LIMIT_USER_BURST", 100)
|
|
|
|
|
|
|
|
|
|
rateLimiterConfig := &middleware.RateLimiterConfig{
|
|
|
|
|
IPRequestsPerMinute: ipLimit,
|
|
|
|
|
IPBurst: ipBurst,
|
|
|
|
|
UserRequestsPerMinute: userLimit,
|
|
|
|
|
UserBurst: userBurst,
|
|
|
|
|
RedisClient: c.RedisClient,
|
|
|
|
|
KeyPrefix: "veza:rate_limit",
|
|
|
|
|
}
|
|
|
|
|
c.RateLimiter = middleware.NewRateLimiter(rateLimiterConfig)
|
|
|
|
|
|
|
|
|
|
// Simple rate limiter (T0015) - sans dépendance Redis
|
|
|
|
|
window := time.Duration(c.RateLimitWindow) * time.Second
|
|
|
|
|
c.SimpleRateLimiter = middleware.NewSimpleRateLimiter(c.RateLimitLimit, window)
|
|
|
|
|
|
|
|
|
|
// Rate limiter par endpoint
|
|
|
|
|
endpointLimiterConfig := &middleware.EndpointLimiterConfig{
|
|
|
|
|
RedisClient: c.RedisClient,
|
|
|
|
|
KeyPrefix: "veza:endpoint_limit",
|
|
|
|
|
}
|
|
|
|
|
endpointLimits := middleware.DefaultEndpointLimits()
|
|
|
|
|
// Override defaults with config (PR-3)
|
|
|
|
|
endpointLimits.LoginAttempts = c.AuthRateLimitLoginAttempts
|
|
|
|
|
endpointLimits.LoginWindow = time.Duration(c.AuthRateLimitLoginWindow) * time.Minute
|
|
|
|
|
// A04: Limites register assouplies en dev (20/heure au lieu de 3/heure)
|
|
|
|
|
endpointLimits.RegisterAttempts = getDefaultRegisterAttempts(c.Env)
|
|
|
|
|
endpointLimits.RegisterWindow = time.Hour
|
|
|
|
|
|
|
|
|
|
c.EndpointLimiter = middleware.NewEndpointLimiter(endpointLimiterConfig, endpointLimits)
|
|
|
|
|
|
|
|
|
|
// BE-SVC-002: Initialize per-user rate limiter
|
|
|
|
|
userRateLimiterConfig := &middleware.UserRateLimiterConfig{
|
|
|
|
|
RequestsPerMinute: getEnvAsInt("USER_RATE_LIMIT_PER_MINUTE", 1000), // Default: 1000 requests per minute per user
|
|
|
|
|
Burst: getEnvAsInt("USER_RATE_LIMIT_BURST", 100), // Default: 100 burst
|
|
|
|
|
Window: time.Minute,
|
|
|
|
|
RedisClient: c.RedisClient,
|
|
|
|
|
KeyPrefix: "user_rate_limit",
|
|
|
|
|
Logger: c.Logger,
|
|
|
|
|
}
|
|
|
|
|
c.UserRateLimiter = middleware.NewUserRateLimiter(userRateLimiterConfig)
|
|
|
|
|
|
feat(developer): add API keys backend (Lot C)
- Migration 082: api_keys table (user_id, name, prefix, hashed_key, scopes, last_used_at, expires_at)
- APIKey model, APIKeyService (Create, List, Delete, ValidateAPIKey)
- APIKeyHandler: GET/POST/DELETE /api/v1/developer/api-keys
- AuthMiddleware: X-API-Key and Bearer vza_* accepted as alternative to JWT
- CSRF: skip for API key auth (stateless)
- Key format: vza_ prefix, SHA-256 hashed storage
2026-02-19 23:18:36 +00:00
|
|
|
// Middleware d'authentification (supports JWT and X-API-Key for developer keys)
|
2026-02-15 13:44:33 +00:00
|
|
|
c.AuthMiddleware = middleware.NewAuthMiddleware(
|
|
|
|
|
c.SessionService,
|
|
|
|
|
c.AuditService,
|
|
|
|
|
c.PermissionService,
|
|
|
|
|
c.JWTService,
|
|
|
|
|
c.UserService,
|
feat(developer): add API keys backend (Lot C)
- Migration 082: api_keys table (user_id, name, prefix, hashed_key, scopes, last_used_at, expires_at)
- APIKey model, APIKeyService (Create, List, Delete, ValidateAPIKey)
- APIKeyHandler: GET/POST/DELETE /api/v1/developer/api-keys
- AuthMiddleware: X-API-Key and Bearer vza_* accepted as alternative to JWT
- CSRF: skip for API key auth (stateless)
- Key format: vza_ prefix, SHA-256 hashed storage
2026-02-19 23:18:36 +00:00
|
|
|
c.APIKeyService,
|
2026-02-26 18:34:45 +00:00
|
|
|
c.TokenBlacklist, // VEZA-SEC-006: nil if Redis unavailable (implements TokenBlacklistChecker)
|
2026-02-15 13:44:33 +00:00
|
|
|
c.Logger,
|
|
|
|
|
)
|
2026-02-21 04:22:43 +00:00
|
|
|
if c.PresenceService != nil {
|
|
|
|
|
c.AuthMiddleware.SetPresenceService(c.PresenceService)
|
|
|
|
|
}
|
2026-02-15 13:44:33 +00:00
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SetupMiddleware configure les middlewares globaux
|
|
|
|
|
// DÉPRÉCIÉ : Cette méthode est conservée pour compatibilité mais ne fait plus rien
|
|
|
|
|
// Les middlewares globaux sont maintenant configurés dans internal/api/router.go via APIRouter.Setup()
|
2026-02-27 08:43:25 +00:00
|
|
|
// NOTE: CORS could use c.CORSOrigins from config in api/router.go
|
2026-02-15 13:44:33 +00:00
|
|
|
func (c *Config) SetupMiddleware(router *gin.Engine) {
|
|
|
|
|
// No-op : Les middlewares sont configurés dans api/router.go
|
|
|
|
|
// Cette méthode existe uniquement pour compatibilité avec cmd/main.go (legacy)
|
|
|
|
|
// qui sera désactivé dans le Chantier 1 - Étape 2
|
|
|
|
|
}
|