Панель без публичного входа: страница живёт по ADMIN_PATH, логин/пароль — ADMIN_LOGIN/ADMIN_PASSWORD из .env (пусто = админка выключена и маршруты /api/admin/* не регистрируются, прод можно не трогать). Умеет: посмотреть текущую ссылку и состояние кэша, вставить новую ссылку (проверяется скачиванием и разбором до сохранения, при ошибке откат), принудительно обновить таблицу вне интервала и без проверки modified, задать интервал в минутах (1..1440). Реализация: - backend/admin.py — cookie-сессия на HMAC (ключ = пароль, 12 часов, HttpOnly/SameSite/Secure-за-https), сравнение за постоянное время; compare_digest по байтам — кириллица в логине не роняет сервер; - schedule/settings.py — ссылка и интервал в JSON (SETTINGS_FILE), атомарная запись, терпимость к битому/недоступному файлу (тогда живёт в памяти); - schedule/cache.py — интервал вместо TTL, apply_link с откатом, force_reload, state() для панели; кэш без ссылки больше не роняет старт; - frontend: страница admin.html (вне static, прямой /admin.html закрыт) и прокси /api/admin/* с телом и Set-Cookie; - docker-compose: том schedule_data для настроек, ADMIN_* в окружении; - deploy/: nginx-конфиг и инструкция для стенда dev.schedule.our-place.ru. Тесты: 138 (новые — админ-API, сессии, ссылка/интервал, force, хранилище).
51 lines
1.6 KiB
YAML
51 lines
1.6 KiB
YAML
services:
|
|
api:
|
|
build:
|
|
context: .
|
|
target: api
|
|
environment:
|
|
SCHEDULE_LINK: ${SCHEDULE_LINK}
|
|
SCHEDULE_CACHE_TTL: ${SCHEDULE_CACHE_TTL:-900}
|
|
SCHEDULE_RETRY_AFTER: ${SCHEDULE_RETRY_AFTER:-60}
|
|
# админка: секретный путь панели и учётные данные (пусто = выключена)
|
|
ADMIN_PATH: ${ADMIN_PATH:-}
|
|
ADMIN_LOGIN: ${ADMIN_LOGIN:-}
|
|
ADMIN_PASSWORD: ${ADMIN_PASSWORD:-}
|
|
SCHEDULE_INTERVAL_MINUTES: ${SCHEDULE_INTERVAL_MINUTES:-15}
|
|
# настройки админки переживают пересборку благодаря тому /data
|
|
SETTINGS_FILE: ${SETTINGS_FILE:-/data/settings.json}
|
|
volumes:
|
|
- schedule_data:/data
|
|
ports:
|
|
- "${API_PORT:-8000}:8000"
|
|
restart: unless-stopped
|
|
healthcheck:
|
|
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/healthz', timeout=5)"]
|
|
interval: 30s
|
|
timeout: 5s
|
|
retries: 3
|
|
start_period: 10s
|
|
|
|
frontend:
|
|
build:
|
|
context: .
|
|
target: frontend
|
|
environment:
|
|
SCHEDULE_API: ${SCHEDULE_API:-http://api:8000}
|
|
ADMIN_PATH: ${ADMIN_PATH:-}
|
|
ports:
|
|
- "${FRONTEND_PORT:-8080}:8080"
|
|
restart: unless-stopped
|
|
depends_on:
|
|
api:
|
|
condition: service_healthy
|
|
healthcheck:
|
|
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8080/healthz', timeout=5)"]
|
|
interval: 30s
|
|
timeout: 5s
|
|
retries: 3
|
|
start_period: 10s
|
|
|
|
volumes:
|
|
schedule_data:
|