Авторизация: форма входа, cookie-сессия, защита /api/* (кроме health/login/me/logout)

This commit is contained in:
2026-08-26 00:38:23 +07:00
parent 5dcc4ce1ad
commit d9eccfb4b7
7 changed files with 482 additions and 17 deletions

View File

@@ -39,6 +39,40 @@ npm install
npm start
```
После запуска редактор закрыт cookie-сессией. По умолчанию логин — `admin`,
а пароль генерируется при старте сервера и печатается в консоль (баннер
`APP_PASSWORD не задан. Сгенерирован случайный пароль`). Чтобы зафиксировать
учётные данные, задайте переменные окружения `APP_USER` / `APP_PASSWORD`.
Подробнее — в разделе «Авторизация».
## Авторизация
Редактор «Кадр» закрыт cookie-сессией: все `/api/*` эндпоинты, кроме
`/api/health`, `/api/login`, `/api/me`, `/api/logout`, требуют валидную
сессию, иначе возвращают `401 {"ok":false,"error":"Требуется авторизация."}`.
На главной странице поверх редактора показывается форма входа, которая
блокирует работу, пока владелец не войдёт. Статические файлы и `/api/health`
остаются публичными.
Учётные данные задаются переменными окружения:
- `APP_USER` — логин владельца (по умолчанию `admin`).
- `APP_PASSWORD` — пароль. Если не задан или пуст, сервер генерирует
случайный 16-символьный пароль при старте и печатает его в консоль/лог
контейнера (баннер `APP_PASSWORD не задан. Сгенерированный пароль`).
Сессия — cookie `kadr_session`:
- срок жизни 7 суток;
- скользящая (sliding): продлевается при каждой активности;
- `HttpOnly`, `SameSite=Lax`, без `Secure` (приложение работает по HTTP
в локальной сети);
- сессии хранятся в памяти сервера — перезапуск сбрасывает все входы.
Публичные эндпоинты: `GET /api/health`, `POST /api/login`,
`GET /api/me`, `POST /api/logout`. Вход в систему — `POST /api/login`
с JSON-телом `{"username": "...", "password": "..."}`.
## Docker
Образ собирается на базе `node:22-bookworm-slim` (Debian, glibc) — Codex CLI
@@ -54,6 +88,8 @@ docker run -d --name kadr-photo-editor -p 3000:3000 ^
-v "$env:USERPROFILE\.codex:/root/.codex" ^
-v "${PWD}\history:/app/history" ^
-e COMFY_URL=http://192.168.31.240:8188 ^
-e APP_USER=admin ^
-e APP_PASSWORD=your-strong-password ^
kadr-photo-editor
```
@@ -83,6 +119,8 @@ docker run -d --name kadr-photo-editor -p 3000:3000 ^
-v "$env:USERPROFILE\.codex:/root/.codex" ^
-v "${PWD}\history:/app/history" ^
-e COMFY_URL=http://192.168.31.240:8188 ^
-e APP_USER=admin ^
-e APP_PASSWORD=your-strong-password ^
git.byte-mate.ru/coder/photo-editor:latest
```
@@ -141,6 +179,13 @@ Workflow `.gitea/workflows/deploy.yml` разворачивает сервис
в ChatGPT API через прокси. Переменные `HTTP(S)_PROXY` и `NO_PROXY`
прописаны в `deploy/docker-compose.yml` (внутренние адреса — ComfyUI,
свой хост — идут напрямую).
6. **Авторизация владельца**: секреты `APP_USER` / `APP_PASSWORD`
(Settings → Actions → Secrets) передаются workflow deploy-portainer
в переменные окружения стека. Если секреты не заданы (пустые значения),
сервер использует дефолты: логин `admin` и сгенерированный при старте
пароль, напечатанный в лог контейнера. Альтернатива — задать переменные
вручную в Portainer UI: стек `photo-editor` → **Edit** → **Environment
variables** → `APP_USER` / `APP_PASSWORD`.
Поведение: если стека нет — создаёт; если есть — обновляет с
`RepullImageAndRedeploy=true` (всегда перетягивает свежий образ). Контейнер