Админка нужна на «голом» сервере, поэтому возвращаю её в основную ветку. Она выключена, пока не заданы 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-образе (том настроек, запись истории).
31 lines
1.9 KiB
Plaintext
31 lines
1.9 KiB
Plaintext
# --- расписание --------------------------------------------------------------
|
||
# Публичная ссылка на Яндекс.Диск с таблицей расписания (обязательна)
|
||
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=
|