README: вход по логину и паролю

В таблицах методов входа (раздел «Аутентификация» и сводка окружений) пароль
теперь основной способ во всех окружениях, Telegram — второй, stub остаётся
только в dev. Описаны правила пароля, защита от перебора, обязательное окно для
аккаунтов без пароля, привязка Telegram и восстановление пароля через админку.
Поправлены места, где test-клон описывался как «только Telegram».

#24

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XfTsytzT6TojfmprRDKiV6
This commit is contained in:
2026-09-13 14:12:50 +03:00
co-authored by Claude Opus 5
parent 462079d835
commit a09766c031
+17 -9
View File
@@ -1,7 +1,7 @@
# Forbidden Stars — учёт партий # Forbidden Stars — учёт партий
Мобильное веб-приложение для учёта партий настольной игры **Forbidden Stars**: Мобильное веб-приложение для учёта партий настольной игры **Forbidden Stars**:
профили игроков (вход через Telegram, пока — dev-заглушка), группы, создание партий профили игроков (вход по логину и паролю или через Telegram), группы, создание партий
с рандомом фракций и фильтром по дополнениям группы, статистика и общий топ, админ-панель. с рандомом фракций и фильтром по дополнениям группы, статистика и общий топ, админ-панель.
- **Бэкенд / ядро + API:** Python · FastAPI · SQLModel · SQLite - **Бэкенд / ядро + 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 (оба стека) npm run dev # http://127.0.0.1:5173 или http://localhost:5173 (оба стека)
``` ```
Вход в dev-режиме — экран `/login`: в деве доступны оба метода (Telegram + вход по нику), Вход в dev-режиме — экран `/login`: логин/пароль, Telegram и вход по нику без пароля (stub);
в проде — только Telegram (см. раздел «Аутентификация»). в проде stub нет (см. раздел «Аутентификация»).
## Production (Docker на Pi) ## Production (Docker на Pi)
@@ -108,7 +108,7 @@ FastAPI отдаёт собранный SPA и API с одного origin. Ми
## Test — локальный прод-клон в контейнере ## Test — локальный прод-клон в контейнере
Тот же образ и поведение, что и прод (FastAPI отдаёт SPA, БД на томе, вход игроков Тот же образ и поведение, что и прод (FastAPI отдаёт SPA, БД на томе, вход игроков
только через Telegram), но на своей машине — для проверки прод-сборки до выката на Pi. по логину/паролю или через Telegram), но на своей машине — для проверки прод-сборки до выката на Pi.
Изолированные тома и порт **8080** (не конфликтует с dev-uvicorn на :8000). Изолированные тома и порт **8080** (не конфликтует с dev-uvicorn на :8000).
Проще всего — через лаунчер: поставить `APP_ENV=test` в `.env` и запустить `.\run.ps1`. Проще всего — через лаунчер: поставить `APP_ENV=test` в `.env` и запустить `.\run.ps1`.
@@ -123,8 +123,8 @@ docker compose -f docker-compose.test.yml down -v # остановить и с
- Читает **тот же `.env`**, что dev/prod (отдельного `.env.test` больше нет); внутри - Читает **тот же `.env`**, что dev/prod (отдельного `.env.test` больше нет); внутри
контейнера `APP_ENV` форсится в `test` (см. `docker-compose.test.yml`). контейнера `APP_ENV` форсится в `test` (см. `docker-compose.test.yml`).
- Данные — на отдельных томах `db-data-test` / `uploads-data-test` (не пересекаются с dev и Pi). - Данные — на отдельных томах `db-data-test` / `uploads-data-test` (не пересекаются с dev и Pi).
- Вход: **админ-панель** (`/admin/login`) работает сразу по логину/паролю; вход **игроков** — - Вход: **админ-панель** (`/admin/login`) работает сразу по логину/паролю; **игроки** —
только через Telegram (нужен бот + публичный HTTPS/туннель на `localhost:8080`). по логину/паролю сразу, через Telegram — при боте и публичном HTTPS/туннеле на `localhost:8080`.
- **Не используйте `$` в секретах.** Единый `.env` читают и pydantic (dev — `$` дословно), - **Не используйте `$` в секретах.** Единый `.env` читают и pydantic (dev — `$` дословно),
и docker compose (test/prod — `$` = подстановка переменной). Чтобы значение совпадало и docker compose (test/prod — `$` = подстановка переменной). Чтобы значение совпадало
везде, в `SECRET_KEY`/`ADMIN_PASSWORD` не должно быть `$`. Удобно генерировать так: везде, в `SECRET_KEY`/`ADMIN_PASSWORD` не должно быть `$`. Удобно генерировать так:
@@ -136,9 +136,17 @@ docker compose -f docker-compose.test.yml down -v # остановить и с
| | dev | test / prod | | | 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-вход (по нику)** — только для разработки. Его код **физически не попадает в прод:** - **Stub-вход (по нику)** — только для разработки. Его код **физически не попадает в прод:**
файлы `backend/app/auth/dev_stub.py` и `backend/app/routers/dev_auth.py` исключены из файлы `backend/app/auth/dev_stub.py` и `backend/app/routers/dev_auth.py` исключены из
Docker-образа (`.dockerignore`), роутер подключается лишь при `APP_ENV=development` Docker-образа (`.dockerignore`), роутер подключается лишь при `APP_ENV=development`
@@ -165,7 +173,7 @@ docker compose -f docker-compose.test.yml down -v # остановить и с
| Env-файл | единый `.env` | единый `.env` | единый `.env` (на Pi) | | Env-файл | единый `.env` | единый `.env` | единый `.env` (на Pi) |
| Раздача SPA | Vite (HMR), :5173 | FastAPI, :8080 | FastAPI, :8000 | | Раздача SPA | Vite (HMR), :5173 | FastAPI, :8080 | FastAPI, :8000 |
| База данных | `backend/data/dev/…` | том `db-data-test` (`/data`) | том `db-data` (`/data`) | | База данных | `backend/data/dev/…` | том `db-data-test` (`/data`) | том `db-data` (`/data`) |
| Вход игроков | Telegram + ник (stub) | только Telegram | только Telegram | | Вход игроков | пароль + Telegram + ник (stub) | пароль + Telegram | пароль + Telegram |
- **Один `.env` на машину** в корне (рядом с `.env.example`). `APP_ENV` в нём решает, что - **Один `.env` на машину** в корне (рядом с `.env.example`). `APP_ENV` в нём решает, что
запустит лаунчер (`development`/`test`); прод-контейнер это значение **игнорирует** и всегда запустит лаунчер (`development`/`test`); прод-контейнер это значение **игнорирует** и всегда