from flask import redirect, render_template, request, session, url_for import auth from core.flask_app import app @app.route("/register/2fa", methods=["GET", "POST"]) def register_2fa(): user_id = session.get("pending_register_user_id") if not user_id: return redirect(url_for("register")) user = auth.get_user_by_id(user_id) if not user: session.pop("pending_register_user_id", None) return redirect(url_for("register")) error = None if request.method == "POST": locked_seconds = auth.seconds_locked_remaining(user) if locked_seconds: error = auth.lockout_message(locked_seconds) elif not auth.verify_totp(user["totp_secret"], request.form.get("code", "")): just_locked_minutes = auth.record_failed_attempt(user_id) error = auth.lockout_message(just_locked_minutes * 60) if just_locked_minutes else \ "Code invalide — vérifie l'heure de ton téléphone et réessaie." else: auth.reset_failed_attempts(user_id) auth.confirm_totp(user_id) session.pop("pending_register_user_id", None) session["user_id"] = user_id # Générés ici, une seule fois, à l'instant même où la 2FA # devient active (voir auth/recovery_codes.py) : c'est la SEULE # occasion où ils sont visibles en clair (seul leur hash reste # en base) — posés en session pour être affichés une unique # fois par la page suivante (voir core/recovery_codes_flash.py # et le modal dans base.html), plutôt que d'interrompre ici la # redirection habituelle vers le tableau de bord/l'accueil. session["recovery_codes_to_show"] = auth.generate_recovery_codes(user_id) if user["role"] == "admin": return redirect(url_for("index")) # Un compte "user" (pas "admin") n'a plus de projet créé # d'office ici — voir routes/onboarding/onboarding_new.py : il # choisit d'abord un type de jeu et nomme son projet, PUIS # auth.set_project_slug() y est appelé (core/auth_guard.py # renvoie ici tout compte sans project_slug). Un admin, lui, # reste libre de créer ses jeux comme avant ("+ Nouveau jeu"), # aucun projet ne lui est imposé d'office. return redirect(url_for("onboarding_new")) qr_svg = auth.totp_qrcode_svg(user["totp_secret"], user["email"]) return render_template( "auth/register_2fa.html", error=error, qr_svg=qr_svg, secret=user["totp_secret"], email=user["email"], )