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>
123 lines
8.1 KiB
HTML
123 lines
8.1 KiB
HTML
<!DOCTYPE html>
|
|
{% load forum_extras %}
|
|
{% include 'partials/head.html' %}
|
|
{% include 'partials/header.html' %}
|
|
{% include 'partials/video.html' %}
|
|
|
|
<div class="main-page">
|
|
<div class="middle-content">
|
|
<div class="body-content">
|
|
<div class="title-content"><h1>{{ topic.name }}</h1></div>
|
|
<div class="box-content">
|
|
<div class="body-box-content">
|
|
{% include 'forum/_style.html' %}
|
|
<div class="forum-wrap">
|
|
<div class="forum-actions">
|
|
{% if forum %}<a class="forum-btn" href="{% url 'forum_view_p1' forum_id=forum.id %}">← {{ forum.name }}</a>{% endif %}
|
|
{% if topic.has_views %}<span style="color:#b1997f; align-self:center">{{ topic.views }} visitas</span>{% endif %}
|
|
{% if topic.locked %}<span class="forum-badge">Tema bloqueado</span>{% endif %}
|
|
</div>
|
|
|
|
{% for post in posts %}
|
|
<div class="forum-post {% if post.deleted %}forum-deleted{% endif %}" id="post-{{ post.id }}">
|
|
<div class="left">
|
|
<div class="pname">
|
|
<a href="{% url 'forum_profile' username=post.poster %}" style="color:#e0c07a">{{ post.author.display_name|default:post.poster }}</a>
|
|
</div>
|
|
<div class="prole">{{ post.author.status }}</div>
|
|
<div class="pmeta">
|
|
{% if post.author.joindate %}Registro: {{ post.author.joindate|date:"d/m/Y" }}<br>{% endif %}
|
|
Mensajes: {{ post.author.post_count }}
|
|
</div>
|
|
</div>
|
|
<div class="right">
|
|
{% if post.deleted %}
|
|
<div class="pbody"><em>[Mensaje eliminado]</em></div>
|
|
{% else %}
|
|
<div class="pbody">{{ post.text|forum_safe }}</div>
|
|
{% endif %}
|
|
<div class="pfoot">
|
|
<span>{{ post.time }}{% if post.updated_at and post.updated_at != post.time %} · editado {{ post.updated_at }}{% endif %}</span>
|
|
<span>
|
|
{% if post.can_edit and not post.deleted %}
|
|
<a href="{% url 'forum_edit_post' post_id=post.id %}">Editar</a>
|
|
· <form class="forum-inline" action="{% url 'forum_delete_post' post_id=post.id %}" method="POST" onsubmit="return confirm('¿Borrar este mensaje?')">{% csrf_token %}<button type="submit" class="link-btn danger">Borrar</button></form>
|
|
{% endif %}
|
|
{% if post.deleted and forum_is_moderator %}
|
|
<form class="forum-inline" action="{% url 'forum_restore_post' post_id=post.id %}" method="POST">{% csrf_token %}<button type="submit" class="link-btn">Restaurar</button></form>
|
|
{% endif %}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
|
|
{% if pagination.total_pages > 1 %}
|
|
<div class="forum-pagination">
|
|
{% if pagination.has_prev %}<a href="{% url 'forum_topic' topic_id=topic.id page=pagination.prev_page %}">« Anterior</a>{% endif %}
|
|
{% for p in pagination.page_range %}
|
|
{% if p == pagination.page %}<span class="current">{{ p }}</span>
|
|
{% else %}<a href="{% url 'forum_topic' topic_id=topic.id page=p %}">{{ p }}</a>{% endif %}
|
|
{% endfor %}
|
|
{% if pagination.has_next %}<a href="{% url 'forum_topic' topic_id=topic.id page=pagination.next_page %}">Siguiente »</a>{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
|
|
<span id="post-bottom"></span>
|
|
|
|
{% if can_reply %}
|
|
<div class="forum-form" style="margin-top:20px">
|
|
<h3 style="color:#d79602">Responder</h3>
|
|
<form action="{% url 'forum_post_reply' topic_id=topic.id %}" method="POST">
|
|
{% csrf_token %}
|
|
{{ reply_form.text }}
|
|
<div class="forum-actions">
|
|
<button type="submit" class="forum-btn">Publicar respuesta</button>
|
|
</div>
|
|
</form>
|
|
{{ reply_form.media }}
|
|
</div>
|
|
{% elif topic.locked %}
|
|
<p style="color:#b1997f">Este tema está bloqueado. No se admiten nuevas respuestas.</p>
|
|
{% elif not forum_is_authenticated %}
|
|
<p><a href="{% url 'login' %}">Inicia sesión</a> para responder.</p>
|
|
{% endif %}
|
|
|
|
{% if forum_is_moderator %}
|
|
<div class="forum-form" style="margin-top:24px; border-top:1px solid rgba(255,255,255,.1); padding-top:14px">
|
|
<h3 style="color:#d79602">Moderación</h3>
|
|
<div class="forum-actions">
|
|
{% if topic.locked %}
|
|
<form class="forum-inline" action="{% url 'forum_unlock_topic' topic_id=topic.id %}" method="POST">{% csrf_token %}<button type="submit" class="forum-btn">Desbloquear</button></form>
|
|
{% else %}
|
|
<form class="forum-inline" action="{% url 'forum_lock_topic' topic_id=topic.id %}" method="POST">{% csrf_token %}<button type="submit" class="forum-btn">Bloquear</button></form>
|
|
{% endif %}
|
|
<form class="forum-inline" action="{% url 'forum_toggle_sticky' topic_id=topic.id %}" method="POST">{% csrf_token %}<button type="submit" class="forum-btn">{% if topic.sticky %}Quitar fijado{% else %}Fijar{% endif %}</button></form>
|
|
{% if topic.deleted %}
|
|
<form class="forum-inline" action="{% url 'forum_restore_topic' topic_id=topic.id %}" method="POST">{% csrf_token %}<button type="submit" class="forum-btn">Restaurar tema</button></form>
|
|
{% else %}
|
|
<form class="forum-inline" action="{% url 'forum_delete_topic' topic_id=topic.id %}" method="POST" onsubmit="return confirm('¿Borrar el tema completo?')">{% csrf_token %}<button type="submit" class="forum-btn danger">Borrar tema</button></form>
|
|
{% endif %}
|
|
</div>
|
|
{% if move_forums %}
|
|
<form action="{% url 'forum_move_topic' topic_id=topic.id %}" method="POST" style="margin-top:8px">
|
|
{% csrf_token %}
|
|
<select name="forum_id" style="padding:6px;background:rgba(0,0,0,.3);color:#e8e0d0;border:1px solid rgba(215,150,2,.4)">
|
|
{% for f in move_forums %}<option value="{{ f.id }}">{{ f.name }}</option>{% endfor %}
|
|
</select>
|
|
<button type="submit" class="forum-btn">Mover tema</button>
|
|
</form>
|
|
{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{% include 'partials/social.html' %}
|
|
{% include 'partials/footer.html' %}
|
|
{% include 'partials/final.html' %}
|