Files
schedule/.env.example
Vladislav Kopnin 5b3c9dc00a Админка в master: секретный путь, ссылка, интервал, force, блокировка входа, история
Админка нужна на «голом» сервере, поэтому возвращаю её в основную ветку. Она
выключена, пока не заданы ADMIN_LOGIN/ADMIN_PASSWORD: маршруты /api/admin/* не
регистрируются, страницы нет — обычная установка ничего не замечает.

Панель (открывается по секретному пути ADMIN_PATH, кнопки входа на сайте нет,
вход по логину/паролю):
- состояние: группы, когда обновлялось, дата файла на Диске, изменился ли
  файл при последнем чтении (sha256), ошибки, путь файла настроек;
- новая ссылка на таблицу: проверяется скачиванием, при ошибке откат;
- интервал обновления (TTL) в минутах;
- «Обновить сейчас»: принудительно перечитывает таблицу (качает файл всегда,
  интервал — только если на Диске изменилась дата);
- история входов: последняя попытка (откуда, когда, успешна ли) и последний
  успешный вход — и в панели, и в логе службы.

Защита входа: ADMIN_MAX_ATTEMPTS неудач (по умолчанию 3), затем блокировка на
ADMIN_LOCKOUT_MINUTES минут (по умолчанию 15) — всё из .env.

Реализация:
- backend/admin.py: cookie-сессия на HMAC (ключ — пароль, 12 ч, HttpOnly,
  SameSite, Secure за https), сравнение за постоянное время, реальный IP из
  X-Forwarded-For, логирование каждой попытки;
- schedule/settings.py: ссылка, интервал и история входов в JSON; путь по
  умолчанию data/settings.json (в docker — том schedule_data), при
  недоступности файла настройки живут в памяти и панель предупреждает;
- cache.py: apply_link (с проверкой и откатом), force_reload, state();
- frontend: страница админки по ADMIN_PATH (вне static, noindex) и прокси
  /api/admin/* с телом и Set-Cookie;
- install.sh пишет переменные админки в .env, Dockerfile копирует admin.py.

Тесты: 156. Проверено локально (страница, 3 попытки -> блокировка, история) и
в собранном docker-образе (том настроек, запись истории).
2026-10-10 11:12:29 +03:00

31 lines
1.9 KiB
Plaintext
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.

# --- расписание --------------------------------------------------------------
# Публичная ссылка на Яндекс.Диск с таблицей расписания (обязательна)
SCHEDULE_LINK=
# Как часто перечитывать таблицу, минут
SCHEDULE_INTERVAL_MINUTES=15
# Устаревшее: интервал в секундах (используется, только если не задан предыдущий)
SCHEDULE_CACHE_TTL=900
# Пауза между повторными попытками, если источник недоступен, секунд
SCHEDULE_RETRY_AFTER=60
# --- порты (только для docker) -------------------------------------------------
# Оба порта публикуются на 127.0.0.1 (жёстко задано в docker-compose.yml):
# снаружи сервисы отдаёт nginx, напрямую в интернет они не смотрят.
API_PORT=8000
FRONTEND_PORT=8080
# --- админка (необязательно) ----------------------------------------------------
# Пока эти переменные пустые, админка выключена и наружу ничего не торчит.
# Секретный путь страницы админки: придумайте длинный, например /panel-8f3a91x7
ADMIN_PATH=
# Логин и пароль администратора
ADMIN_LOGIN=
ADMIN_PASSWORD=
# Сколько неудачных попыток входа допускается и на сколько минут блокировать после них
ADMIN_MAX_ATTEMPTS=3
ADMIN_LOCKOUT_MINUTES=15
# Где хранить настройки админки (ссылка, интервал, история входов).
# Пусто = data/settings.json в корне проекта; в docker задаётся автоматически.
SETTINGS_FILE=