Добавление аутентификации логин/пароль (#24) #53

Merged
NotBigGhost merged 4 commits from issue-24-login-password into dev 2026-09-13 15:36:51 +03:00
Showing only changes of commit a09766c031 - Show all commits
+17 -9
View File
@@ -1,7 +1,7 @@
# Forbidden Stars — учёт партий
Мобильное веб-приложение для учёта партий настольной игры **Forbidden Stars**:
профили игроков (вход через Telegram, пока — dev-заглушка), группы, создание партий
профили игроков (вход по логину и паролю или через Telegram), группы, создание партий
с рандомом фракций и фильтром по дополнениям группы, статистика и общий топ, админ-панель.
- **Бэкенд / ядро + API:** Python · FastAPI · SQLModel · SQLite
@@ -91,8 +91,8 @@ npm run gen:api # сгенерирует типы из живог
npm run dev # http://127.0.0.1:5173 или http://localhost:5173 (оба стека)
```
Вход в dev-режиме — экран `/login`: в деве доступны оба метода (Telegram + вход по нику),
в проде — только Telegram (см. раздел «Аутентификация»).
Вход в dev-режиме — экран `/login`: логин/пароль, Telegram и вход по нику без пароля (stub);
в проде stub нет (см. раздел «Аутентификация»).
## Production (Docker на Pi)
@@ -108,7 +108,7 @@ FastAPI отдаёт собранный SPA и API с одного origin. Ми
## Test — локальный прод-клон в контейнере
Тот же образ и поведение, что и прод (FastAPI отдаёт SPA, БД на томе, вход игроков
только через Telegram), но на своей машине — для проверки прод-сборки до выката на Pi.
по логину/паролю или через Telegram), но на своей машине — для проверки прод-сборки до выката на Pi.
Изолированные тома и порт **8080** (не конфликтует с dev-uvicorn на :8000).
Проще всего — через лаунчер: поставить `APP_ENV=test` в `.env` и запустить `.\run.ps1`.
@@ -123,8 +123,8 @@ docker compose -f docker-compose.test.yml down -v # остановить и с
- Читает **тот же `.env`**, что dev/prod (отдельного `.env.test` больше нет); внутри
контейнера `APP_ENV` форсится в `test` (см. `docker-compose.test.yml`).
- Данные — на отдельных томах `db-data-test` / `uploads-data-test` (не пересекаются с dev и Pi).
- Вход: **админ-панель** (`/admin/login`) работает сразу по логину/паролю; вход **игроков** —
только через Telegram (нужен бот + публичный HTTPS/туннель на `localhost:8080`).
- Вход: **админ-панель** (`/admin/login`) работает сразу по логину/паролю; **игроки** —
по логину/паролю сразу, через Telegram — при боте и публичном HTTPS/туннеле на `localhost:8080`.
- **Не используйте `$` в секретах.** Единый `.env` читают и pydantic (dev — `$` дословно),
и docker compose (test/prod — `$` = подстановка переменной). Чтобы значение совпадало
везде, в `SECRET_KEY`/`ADMIN_PASSWORD` не должно быть `$`. Удобно генерировать так:
@@ -136,9 +136,17 @@ docker compose -f docker-compose.test.yml down -v # остановить и с
| | dev | test / prod |
|---|---|---|
| Telegram Login Widget | ✓ | ✓ (единственный) |
| Вход по нику (stub) | ✓ | ✗ (физически отсутствует) |
| Логин (= ник) и пароль | ✓ | ✓ (основной) |
| Telegram Login Widget | ✓ | ✓ |
| Вход по нику без пароля (stub) | ✓ | ✗ (физически отсутствует) |
- **Логин и пароль** (`app/auth/password.py`) — основной вход. Логин — это ник игрока
(смена ника меняет логин). Пароль: от 8 символов, не длиннее 72 байт, хранится bcrypt.
От перебора — окно 15 минут в памяти процесса: 5 неудач на пару «IP + логин» и 20 на IP,
дальше `429 TOO_MANY_ATTEMPTS`. Игрок без пароля (из Telegram или созданный до паролей)
после входа видит обязательное окно «Задайте пароль». В профиле пароль меняется (нужен
текущий) и привязывается Telegram (ник не меняется). Забытый пароль задаёт админ
на вкладке аккаунтов — почту приложение не хранит.
- **Stub-вход (по нику)** — только для разработки. Его код **физически не попадает в прод:**
файлы `backend/app/auth/dev_stub.py` и `backend/app/routers/dev_auth.py` исключены из
Docker-образа (`.dockerignore`), роутер подключается лишь при `APP_ENV=development`
@@ -165,7 +173,7 @@ docker compose -f docker-compose.test.yml down -v # остановить и с
| Env-файл | единый `.env` | единый `.env` | единый `.env` (на Pi) |
| Раздача SPA | Vite (HMR), :5173 | FastAPI, :8080 | FastAPI, :8000 |
| База данных | `backend/data/dev/…` | том `db-data-test` (`/data`) | том `db-data` (`/data`) |
| Вход игроков | Telegram + ник (stub) | только Telegram | только Telegram |
| Вход игроков | пароль + Telegram + ник (stub) | пароль + Telegram | пароль + Telegram |
- **Один `.env` на машину** в корне (рядом с `.env.example`). `APP_ENV` в нём решает, что
запустит лаунчер (`development`/`test`); прод-контейнер это значение **игнорирует** и всегда