recover_account_view era un stub que solo renderizaba (los formularios no tenían
backend y el HTML arrastraba un reCAPTCHA de otro dominio). Ahora es funcional:
Backend:
- Modelo PasswordReset (token+email+expiración 1h) + migración 0014.
- recover_account_view maneja POST JSON con 3 tipos, todo por email (bnet), con
respuestas genéricas anti-enumeración:
* password: crea token y envía enlace de reset (emails/password_reset.html).
* accountname: envía las cuentas de juego ligadas (emails/account_names.html).
* activation: reenvía el enlace de activación pendiente (emails/activation.html).
- reset_password_view: GET valida el token (isla), POST re-deriva el verifier
SRP6 v2 de la cuenta bnet (bnet.bnet_make_registration) y lo actualiza; marca el
token usado. Ruta 'reset-password'.
- Resiliente si la BD de cuentas (AzerothCore) no está disponible: mensaje limpio,
nunca 500.
Frontend (islas Vite): RecoverForm.tsx (selector de tipo + email) y
ResetPassword.tsx (nueva contraseña con token). Se elimina el reCAPTCHA roto; se
puede añadir uno propio si se aportan claves.
Verificado en producción: los 3 flujos devuelven éxito genérico; reset valida
token y contraseñas; token válido no provoca 500.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Seguridad / dinero:
- store_novawow_view: recalcula precios y valida ítems contra la BD (Item) en vez
de confiar en el precio/ítems que manda el cliente; guarda en sesión un carrito
ya validado para la entrega
- *_success_view (x9): @require_paid_stripe verifica el pago real en Stripe por
session_id (Stripe lo añade a la success_url) y marca StripeLog.fulfilled para
evitar re-entregas; cierra el bypass de ir directo a la success-url sin pagar
- gold_character_view: deja de truncar el precio (int(4.99)->4); pasa el precio real
Correctitud / 500s:
- change_password_view: .get(...,'') evita AttributeError si falta un campo
- revive_character_view: lógica de éxito corregida (vacío=éxito, no vacío=error,
None=fallo de comunicación) — antes marcaba error como éxito y caía a HTML
- store category y recruit_a_friend: guardas para Category.DoesNotExist y cuenta None
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>