diff --git a/docs/FORO.md b/docs/FORO.md index 0d95111..fd20a59 100644 --- a/docs/FORO.md +++ b/docs/FORO.md @@ -59,12 +59,11 @@ en `forum/permissions.py`: - Acceso a temas de foros ocultos/borrados bloqueado también por URL directa (no solo en los listados). -> ⚠️ **Recomendación para todo el sitio** (fuera del foro): `novawow/settings.py` -> no incluye `django.middleware.csrf.CsrfViewMiddleware`, por lo que el resto de -> formularios POST del portal (app `home`) **no** validan CSRF. El foro está -> protegido con `@csrf_protect`, pero conviene activar el middleware global y -> revisar que las vistas POST de `home` lleven `{% csrf_token %}` (algunas ya lo -> llevan; las AJAX usan `@csrf_exempt`). +> ✅ **CSRF global activado** (todo el portal): `novawow/settings.py` ya incluye +> `django.middleware.csrf.CsrfViewMiddleware`. Las peticiones AJAX (jQuery) envían +> la cabecera `X-CSRFToken` automáticamente (`$.ajaxSetup` en `partials/head.html`), +> los formularios nativos llevan `{% csrf_token %}`, y solo los webhooks externos +> (`stripe_webhook`, `sumup_webhook`) mantienen `@csrf_exempt`. ## Editor diff --git a/home/templates/partials/head.html b/home/templates/partials/head.html index 9248f1d..bf117cb 100644 --- a/home/templates/partials/head.html +++ b/home/templates/partials/head.html @@ -40,6 +40,19 @@ + + + diff --git a/home/templates/partials/register.html b/home/templates/partials/register.html index e83bcfe..34e03a6 100644 --- a/home/templates/partials/register.html +++ b/home/templates/partials/register.html @@ -55,6 +55,7 @@
+ {% csrf_token %} diff --git a/home/templates/partials/store/store_novawow.html b/home/templates/partials/store/store_novawow.html index 159c26e..74f4105 100644 --- a/home/templates/partials/store/store_novawow.html +++ b/home/templates/partials/store/store_novawow.html @@ -131,7 +131,7 @@ // Crear la sesión de pago con Stripe fetch('/es/store-novawow/', { method: 'POST', - headers: { 'Content-Type': 'application/json' }, + headers: { 'Content-Type': 'application/json', 'X-CSRFToken': window.CSRF_TOKEN }, body: JSON.stringify({ character: personajeSeleccionado, carrito: carrito, diff --git a/home/views.py b/home/views.py index 79fc9fe..43bd7f6 100644 --- a/home/views.py +++ b/home/views.py @@ -185,7 +185,6 @@ def _set_game_account_session(request, game_account): request.session['account_id'] = game_account['id'] -@csrf_exempt def login_view(request): if request.method == 'POST': form = LoginForm(request.POST) @@ -334,7 +333,6 @@ def logout_view(request): return redirect('index') # Vistas adicionales -@csrf_exempt def register_view(request): if request.method == 'POST': password = request.POST.get('password', '').strip() @@ -1345,7 +1343,6 @@ def rename_cancel_view(request): return redirect('login') return render(request, 'account/rename_cancel.html') -@csrf_exempt def restore_character_view(request): # Verifica si el usuario está autenticado y obtiene su nombre de usuario username = request.session.get('username') @@ -1428,7 +1425,6 @@ def restore_character_view(request): 'character_list': character_list }) -@csrf_exempt def restore_items_view(request): username = request.session.get('username') if not username: diff --git a/novawow/settings.py b/novawow/settings.py index 4df406d..1c98aba 100644 --- a/novawow/settings.py +++ b/novawow/settings.py @@ -141,6 +141,7 @@ MIDDLEWARE = [ 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.locale.LocaleMiddleware', 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'home.middleware.MaintenanceMiddleware',