Upgrade configuration and Docker stack to v2.0.0

This commit is contained in:
2026-06-22 14:49:56 -04:00
parent 2f2a5e9b4a
commit 0d2ecbd218
19 changed files with 779 additions and 495 deletions
+26 -10
View File
@@ -8,8 +8,12 @@ Limites par plan (par heure) :
- free : 20 uploads, 50 AI
- standard : 100 uploads, 200 AI
- premium : 500 uploads, 1000 AI
Supporte le stockage Redis pour la persistence des compteurs.
"""
import logging
from contextvars import ContextVar
from slowapi import Limiter
from slowapi.util import get_remote_address
from starlette.requests import Request
@@ -18,21 +22,31 @@ from app.config import settings
logger = logging.getLogger(__name__)
# ContextVar pour transmettre le plan du client au rate limiter dynamique
_current_client_plan: ContextVar[str] = ContextVar("current_client_plan", default="free")
def _get_client_id_from_request(request: Request) -> str:
"""
Extrait le client_id depuis la state de la requête.
Encode le plan pour isoler les buckets par plan.
Fallback vers l'IP si le client n'est pas encore authentifié.
"""
# Le client_id est injecté par le middleware ou la dépendance auth
client_id = getattr(request.state, "client_id", None)
plan = getattr(request.state, "client_plan", "free")
if client_id:
return str(client_id)
return f"{client_id}:{plan}"
return get_remote_address(request)
# Instance globale du limiter
limiter = Limiter(key_func=_get_client_id_from_request)
# Stockage Redis pour les compteurs (si configuré), sinon mémoire
if settings.RATE_LIMIT_STORAGE_URL:
limiter = Limiter(
key_func=_get_client_id_from_request,
storage_uri=settings.RATE_LIMIT_STORAGE_URL,
)
else:
limiter = Limiter(key_func=_get_client_id_from_request)
def get_upload_rate_limit(plan: str) -> str:
@@ -55,11 +69,13 @@ def get_ai_rate_limit(plan: str) -> str:
return limits.get(plan, limits["free"])
def upload_rate_limit_key(request: Request) -> str:
"""Clé dynamique pour le rate limiting des uploads."""
return _get_client_id_from_request(request)
def dynamic_upload_limit() -> str:
"""Callable pour slowapi — lit le plan depuis le ContextVar."""
plan = _current_client_plan.get()
return get_upload_rate_limit(plan)
def ai_rate_limit_key(request: Request) -> str:
"""Clé dynamique pour le rate limiting des endpoints AI."""
return _get_client_id_from_request(request)
def dynamic_ai_limit() -> str:
"""Callable pour slowapi — lit le plan depuis le ContextVar."""
plan = _current_client_plan.get()
return get_ai_rate_limit(plan)