Игроки входили только через Telegram, а вход по нику без пароля (stub) есть лишь в dev. Теперь основной вход во всех окружениях: POST /api/auth/register и POST /api/auth/login, логин — это ник. Stub в прод не переносится: он пускает без секрета и по-прежнему живёт только в dev. Новый код лежит в прод-модуле auth/password.py и dev-модули не импортирует. Схема БД не меняется: колонка password_hash и провайдер local есть с первой миграции, на них построен вход админа. Пароль от 8 символов и не длиннее 72 байт: дальше bcrypt 5 бросает ValueError. Схема API режет тело длиннее 128 символов ещё до bcrypt. Игроком входит только role='player', так что учётка админа не открывает сессию игрока, и наоборот. Неизвестный логин и аккаунт без пароля сверяются с фиктивным хешем и получают ту же 401 INVALID_CREDENTIALS: по ответу и его времени нельзя понять, есть ли логин. От перебора — скользящее окно 15 минут в памяти процесса (рассчитано на один воркер, как SSE-шина): 5 неудач на пару «IP + логин» и 20 на IP, дальше 429 TOO_MANY_ATTEMPTS с retry_after. Пока блок стоит, пароль не проверяется вовсе. Успешный вход сбрасывает счётчик пары, но не IP. В MeRead появилось has_password: по нему фронт попросит задать пароль тех, у кого его нет. Метод password добавлен в /auth/config. #24 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XfTsytzT6TojfmprRDKiV6
16 lines
574 B
Python
16 lines
574 B
Python
"""Доступные методы входа по окружению.
|
|
|
|
Логин/пароль и Telegram — всегда; stub (вход по нику без пароля) — только в development.
|
|
Здесь НЕТ импорта dev-провайдера, чтобы прод-образ не зависел от dev-кода.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from app.core.config import settings
|
|
|
|
|
|
def enabled_methods() -> list[str]:
|
|
methods = ["password", "telegram"]
|
|
if settings.is_development:
|
|
methods.append("stub")
|
|
return methods
|