- Backend: helper verify_turnstile en _base (verifica el token contra
challenges.cloudflare.com/siteverify; fail-closed ante error de red; si no hay
secreto configurado, no bloquea). Se exige en el POST de login_view,
register_view y recover_account_view -> rechazo con mensaje si falla.
- settings: TURNSTILE_SITE_KEY / TURNSTILE_SECRET_KEY desde .env (el secreto NO
se commitea). La clave de sitio se expone a las plantillas por el context
processor (TURNSTILE_SITE_KEY).
- Frontend: hook useTurnstile (carga el script de Cloudflare una vez y renderiza
el widget, devuelve el token). LoginForm/RegisterForm/RecoverForm incluyen el
widget, mandan cf-turnstile-response y deshabilitan el submit hasta tener token.
El sitekey llega por data-sitekey en el div de montaje.
Verificado: sin token los 3 POST se rechazan; siteverify acepta la clave secreta
(error invalid-input-response con token falso, no invalid-input-secret).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
register_view ya devolvía JSON en POST, así que sin cambio de backend:
RegisterForm.tsx replica register.js (password/conf con mostrar-ocultar, email/conf,
reclutador opcional, checkbox de términos que habilita el botón) y hace fetch
form-urlencoded + CSRF a {% url 'register' %}. El mensaje de éxito llega como HTML
(dangerouslySetInnerHTML); los de error como texto en rojo.
- partials/register.html: el <form> + register.js se sustituyen por #register-app
(data-csrf/data-register-url) + {% vite_asset %}. Info-box y rama "ya conectado"
siguen en Django.
- Nueva entry 'register' en vite.config.ts.
Verificado: check OK, la página monta la isla, POST con datos inválidos devuelve
el JSON de validación correcto.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- añade django.middleware.csrf.CsrfViewMiddleware a MIDDLEWARE (estaba ausente:
el CSRF estaba desactivado en todo el sitio)
- head.html: $.ajaxSetup envía X-CSRFToken en todo POST AJAX de jQuery + expone
window.CSRF_TOKEN (fuerza la cookie csrftoken en cada página)
- store_novawow.html: el fetch() nativo ahora manda X-CSRFToken (era el único que
se rompía al activar el middleware)
- register.html: añade {% csrf_token %} al formulario
- retira @csrf_exempt de login/register/restore_character/restore_items
(solo los webhooks stripe/sumup siguen exentos)
- auditoría previa: el resto de POST (AJAX jQuery + forms nativos con token) ya cubierto
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- home/bnet.py: SRP6 v2 (PBKDF2-HMAC-SHA512) para battlenet_accounts y SRP6
Grunt (SHA1) para las cuentas de juego, con helpers bnet<->game account
- login por email contra battlenet_accounts; selector de cuenta de juego
cuando la cuenta bnet tiene varias (my_account redirige al selector)
- registro/activación crean battlenet_accounts + account enlazada (<bnetId>#1,
battlenet_account/battlenet_index)
- cambio de contraseña sobre battlenet_accounts; cambio de email recalcula
salt/verifier (el usuario SRP depende del email)
- AccountActivation: identidad por email (username/salt/verifier opcionales) + migración
- plantillas login/register por email + nueva plantilla del selector
- docs/MIGRACION_3.4.3.md con el detalle y los pasos de verificación
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>