89ea16ba4d
- CSRF real en las vistas mutadoras con @csrf_protect (el middleware global no estaba activo; verificado: POST sin token -> 403). Se documenta el hueco global. - bloquea acceso a temas de foros ocultos/borrados por URL directa (view_topic y reply) - conteo de posts respeta borrados para moderadores (paginación correcta) - tema bloqueado impide editar/borrar posts a no-moderadores (_topic_locked_for) - moderador ve el formulario de respuesta en temas bloqueados (can_reply) - filtro forum_safe: sanea el HTML también al renderizar (defensa en profundidad) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
100 lines
4.4 KiB
Markdown
100 lines
4.4 KiB
Markdown
# 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).
|
||
|
||
> ⚠️ **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`).
|
||
|
||
## 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.
|