Files
vesti/openspec/changes/archive/2026-09-15-sources-admin/design.md
T

3.3 KiB
Raw Blame History

Design: sources-admin

Модель данных и источник истины

  • sources/sources.yaml — источник истины (в Git). Краулеры при запуске вызывают sync_sources_to_db() → таблица sources.
  • Любое веб-изменение: сначала пишем в yaml (upsert_source_yaml / delete_source_yaml / toggle enabled), затем синкаем yaml → БД (sync_yaml_to_db_and_back), чтобы бд-строка не расходилась.

Изменения в sources/sources.py

  1. delete_source_db(slug) — удаляет строку из sources по slug. Связанные данные: posts (FK source_id) — задаём source_id=NULL (посты остаются историей, без источника); runs — source_id=NULL; rss_state — DELETE; classifications — не трогаем (привязаны к posts). Порядок: delete_source_yaml (yaml) → delete_source_db (БД).
  2. set_source_enabled(slug, enabled) — обновляет enabled в yaml (через upsert_source_yaml с ключом enabled) и в БД (sync_yaml_to_db_and_back). Пауза: enabled=false; снятие: enabled=true.
  3. add_or_update_source(data) — валидация (slug обязателен, уникален; crawler ∈ {telegram, rss}; priority ∈ {P0..P3}; для rss — feed_url обязателен) → upsert_source_yaml → sync_yaml_to_db_and_back → возврат slug.

Веб-слой (web/app.py)

  • GET /sources — страница (за auth): таблица всех источников (slug, name, crawler, direction, lang, priority, enabled, url/feed_url, last_fetch/status), форма добавления, кнопки действий. Шаблон web/templates/sources.html.
  • POST /sources/add — добавление (форма). Redirect на /sources.
  • POST /sources/update/<slug> — переименование/правка полей.
  • POST /sources/{slug}/toggle — пауза/снятие с паузы.
  • POST /sources/{slug}/delete — удаление (с подтверждением на стороне формы: onclick="return confirm(...)").
  • Все POST — с _require_auth, следуют паттерну /crawlers (async + form).
  • Валидация ошибок → flash message + редирект (не 500).
  • Навбар: ссылка «Источники» между «Краулеры» и «Выйти».

Шаблон sources.html

  • Таблица + модальный диалог (Bootstrap) для add/edit (одна форма).
  • Кнопки: Изменить (заполняет модалку), Удалить (confirm), Пауза/Снять (toggle).
  • Приоритет — селект P0/P1/P2/P3; crawler — селект telegram/rss; direction — селект из DIRECTIONS_CANON (keywords) + «—».
  • Для rss: поле feed_url; для telegram: channel.

Безопасность

  • Пароль ADMIN_PASSWORD, как на /crawlers.
  • slug — белый список [a-z0-9_-], валидация на добавление (иначе 400).
  • Удаление — только POST + confirm (никаких GET-удалений).