Files
NovaWoW/docs/FORO.md
T
Inna b5d46fad5c Activa CSRF global en el portal (CsrfViewMiddleware)
- 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>
2026-07-12 17:42:34 +00:00

99 lines
4.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Foro integrado (app `forum`)
Foro de comunidad reimplementado en Django dentro de NovaWoW, con el **diseño
del propio sitio** (usa los `partials` head/header/footer). Portado desde la app
Symfony *NovaWeb-main*, contra las **mismas tablas** en la base de datos
`acore_web`.
## Arquitectura
- **BD**: `acore_web` (5ª conexión Django, `DB_NAME_WEB`). Acceso por SQL directo
(`connections['acore_web']`), mismo estilo que el resto del proyecto.
- **Tablas**: `forum_categories`, `forums`, `forum_topics`, `forum_posts`,
`forum_reads`. (La tabla legacy `forum_forums` NO se usa.)
- **Identidad del autor**: la cuenta de juego en sesión de NovaWoW
(`session['account_id']` / `session['username']`). No usa las cookies del
proyecto original.
## Funcionalidad (completa)
- Portada con categorías y foros (contadores de temas/mensajes, último tema).
- Ver foro: lista de temas paginada.
- Ver tema: posts paginados, con panel de autor (rol, registro, nº de mensajes).
- Crear tema, responder, editar y borrar el post propio.
- Moderación: fijar/desfijar, bloquear/desbloquear, mover, borrar/restaurar temas
y posts.
- Buscador de temas (por título y contenido) **paginado** en `/es/forum/search`.
- Contador de **visitas** por tema (columna opcional `forum_topics.views`).
- Perfil público básico (`/es/profile/<usuario>`).
- El autor se muestra con un **nombre legible** (parte local del email de la
cuenta) en vez de `<bnetId>#1`.
Rutas bajo `/es/forum...` (idénticas al original: `app_forum`, `forum_view`,
`forum_topic`, `forum_create_topic`, etc.).
## Modelo de permisos (simplificado)
En vez de la matriz `group_level`×`permission` del original (enrevesada y con
acciones que quedaban deshabilitadas por falta de filas), se usa un modelo claro
en `forum/permissions.py`:
- **Ver**: foros públicos (`visibility=1`, `deleted=0`) visibles para todos.
- **Publicar / responder / crear tema**: cualquier usuario con sesión iniciada y
cuenta de juego seleccionada.
- **Editar / borrar** un post: su autor, o un moderador.
- **Moderar**: cuentas con `gmlevel >= FORUM_MOD_GMLEVEL` (por defecto **2**),
leído de `acore_auth.account_access`.
## Seguridad
- El texto de los posts se **sanea con `nh3`** (allowlist de etiquetas) al
guardar — `forum/sanitize.py` — evitando el XSS que tenía el original (que
renderizaba HTML del editor sin filtrar). Se renderiza con `|safe` ya saneado.
- **Todas** las acciones que modifican datos (publicar, responder, editar, mover,
bloquear/desbloquear, fijar, borrar/restaurar temas y posts) van por **POST**, y
las vistas mutadoras llevan **`@csrf_protect`** (fuerza la validación CSRF por
vista aunque el middleware global no esté activo).
- El HTML de los posts también se **sanea al renderizar** con el filtro
`forum_safe` (defensa en profundidad frente a datos heredados sin sanear).
- Acceso a temas de foros ocultos/borrados bloqueado también por URL directa
(no solo en los listados).
> ✅ **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
Los mensajes se escriben con **CKEditor 5** (el mismo editor que usa el resto de
NovaWoW), vía `forum/forms.py` (`TopicForm`, `ReplyForm`, `EditPostForm`). El
HTML que produce el editor se **sanea con nh3** al guardar, así que el rich text
es seguro.
## Despliegue
1. Crear/usar la BD `acore_web` y aplicar el esquema:
```bash
mysql acore_web < sql/forum_schema.sql
```
(Si ya existe la BD del portal Symfony con esas tablas, apunta `DB_NAME_WEB`
a ella y omite este paso.)
- Opcional (contador de visitas): `mysql acore_web < sql/forum_views.sql`.
El foro detecta la columna automáticamente y funciona sin ella.
2. Configurar variables de entorno:
```
DB_NAME_WEB=acore_web
FORUM_MOD_GMLEVEL=2
FORUM_TOPICS_PER_PAGE=20
FORUM_POSTS_PER_PAGE=15
```
3. El enlace «FOROS» del menú COMUNIDAD ya apunta al foro interno (`/es/forum`).
## Notas / posibles mejoras
- Sistema de nicks propio del foro (ahora el nombre visible es la parte local del
email de la cuenta).
- Avatares de usuario y firmas.