Объявления: модель, API игрока и админки, очистка HTML
Объявление администрации показывается игроку окном в свой период, пока игрок
не закроет его («Понятно»). Отметка о закрытии хранится на сервере с номером
версии: правка с «показать заново» поднимает версию, и закрывшие прежнюю
увидят объявление снова — ответ помечен updated («обновлено»). Флаг
show_to_new_players=false прячет объявление от зарегистрировавшихся после
начала показа. Пересекающиеся объявления идут от старого к новому.
Текст приходит HTML-ом из редактора админки и сохраняется только после
очистки по белому списку (b, em, mark и mark.red, p, br): атрибуты
отбрасываются, script/style/svg — вместе с содержимым, текст экранируется
заново. Фронт вставляет только этот HTML.
API: GET /api/announcements/pending, POST /api/announcements/{id}/ack;
админка — список со статусом и счётчиком «закрыли N из M», создание, правка,
«снять с показа», удаление, всё в аудит. SSE-событие announcements активным
игрокам. Миграция 0015 идемпотентная.
Тесты: очистка (XSS-попытки, вложенные div), права, период и порядок,
«новые игроки», повторный показ, снятие, удаление, валидация. #84
Перенесено в main без рейтинга из a0a0e52; миграция 0015 — сразу от 0013
(как в ec0445f).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -8,7 +8,7 @@ from __future__ import annotations
|
||||
from sqlmodel import Session, select
|
||||
|
||||
from app.core.events import hub
|
||||
from app.models import GroupMember, Match, MatchParticipant
|
||||
from app.models import GroupMember, Match, MatchParticipant, User
|
||||
|
||||
|
||||
def _group_member_ids(session: Session, group_id: int) -> list[int]:
|
||||
@@ -87,3 +87,13 @@ def invitations_changed(user_id: int) -> None:
|
||||
def notifications_changed(user_id: int) -> None:
|
||||
"""У пользователя появилось/изменилось уведомление — пусть подтянет список."""
|
||||
hub.publish([user_id], {"type": "notifications"})
|
||||
|
||||
|
||||
def announcements_changed(session: Session) -> None:
|
||||
"""Админ создал, поправил, снял или удалил объявление — всем активным игрокам:
|
||||
открытые вкладки перезапросят, что показать. Объявление, чей период начнётся
|
||||
позже, клиент подхватит сам — периодическим перезапросом."""
|
||||
ids = session.exec(
|
||||
select(User.id).where(User.role == "player", User.is_active.is_(True)) # type: ignore[union-attr]
|
||||
).all()
|
||||
hub.publish(ids, {"type": "announcements"})
|
||||
|
||||
Reference in New Issue
Block a user