"""Vérifie le jeton CSRF (voir core/csrf.py) sur toute requête qui modifie quelque chose — un before_request de plus, dans le même esprit que core/auth_guard.py (une seule garde globale plutôt que de toucher aux ~90 routes existantes une par une). Toute l'appli soumet ses formulaires ET ses fetch() via une seule voie : pjax.js intercepte CHAQUE
interne et le transforme lui-même en fetch() (voir static/pjax.js) — aucun formulaire de ce moteur ne fait donc jamais de vraie soumission HTML native. static/csrf_fetch.js patche window.fetch une seule fois pour y ajouter automatiquement l'en-tête X-CSRFToken sur toute requête non-GET de l'appli (celles de pjax.js comprises) : pas besoin de modifier individuellement les nombreux appels fetch() déjà écrits à la main dans screen_edit.html/game_dashboard.html/ play.html.""" from flask import abort, request, session from .flask_app import app _SAFE_METHODS = {"GET", "HEAD", "OPTIONS"} @app.before_request def _verify_csrf_token(): if request.method in _SAFE_METHODS: return None if app.config.get("TESTING"): # Les tests appellent les routes directement via le client de # test Flask (de vraies requêtes HTTP, mais jamais passées par le # navigateur/static/csrf_fetch.js qui pose l'en-tête) — même # convention que Flask-WTF (WTF_CSRF_ENABLED désactivé en test). # Ce garde a ses PROPRES tests dédiés (test_csrf.py), qui # réactivent la vérification explicitement pour la mettre à # l'épreuve. return None submitted = request.headers.get("X-CSRFToken") or request.form.get("csrf_token") expected = session.get("csrf_token") if not expected or not submitted or submitted != expected: abort(400, description="Jeton de sécurité manquant ou expiré — recharge la page et réessaie.") return None