Комментарии про методы входа приведены к факту (логин/пароль и Telegram везде, stub только в development): config.py, .env.example, telegram.py, dev_stub.py, dev_auth.py, login.py. admin_login.py больше не обещает «строже игроцкого» — описаны реальные лимиты; client_ip — адрес за прокси уже даёт uvicorn. Подсказки деплоя: run.ps1/run.sh (build-push на ПК, `up -d` на Pi), compose, .env.example (build-push.ps1), Caddyfile (туннель-контейнер вместо autossh); ratelimit.py ссылается на core/events.py вместо CLAUDE.md. Удалены неиспользуемые scripts/export-prod.sh (с блоком export-ignore в .gitattributes и упоминаниями в README), db/init_db.py и случайно закоммиченный файл «h -u origin dev…». #70 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LqSoRj99iwVEH5U5fnZgsd
46 lines
1.8 KiB
Python
46 lines
1.8 KiB
Python
"""Общий вход: внешняя личность → пользователь → сессия.
|
||
|
||
Прод-безопасный модуль (без импортов dev-провайдера). establish_session зовут вход через
|
||
Telegram, /auth/login, /auth/register и dev-вход.
|
||
"""
|
||
from __future__ import annotations
|
||
|
||
from fastapi import Request, Response
|
||
from sqlmodel import Session
|
||
|
||
from app.auth.provider import ExternalIdentity
|
||
from app.core import security
|
||
from app.core.security import client_ip
|
||
from app.core.errors import ForbiddenError
|
||
from app.models import User
|
||
from app.services import audit_service, user_service
|
||
|
||
|
||
def establish_session(
|
||
session: Session, response: Response, request: Request, user: User, provider: str
|
||
) -> User:
|
||
"""Открыть сессию уже найденному/созданному пользователю (cookie + аудит)."""
|
||
if not user.is_active:
|
||
raise ForbiddenError("Аккаунт отключён администратором.", code="ACCOUNT_DISABLED")
|
||
security.set_user_session(response, user.id, provider, user.token_version) # type: ignore[arg-type]
|
||
audit_service.record(
|
||
session,
|
||
actor_id=user.id,
|
||
action="login",
|
||
entity_type="user",
|
||
entity_id=user.id,
|
||
payload={"provider": provider},
|
||
ip=client_ip(request),
|
||
user_agent=request.headers.get("user-agent"),
|
||
)
|
||
session.commit()
|
||
return user
|
||
|
||
|
||
def login_with_identity(
|
||
session: Session, response: Response, request: Request, identity: ExternalIdentity
|
||
) -> User:
|
||
"""Вход с авто-созданием (dev-вход по нику): ник подбирается автоматически."""
|
||
user = user_service.get_or_create_from_identity(session, identity)
|
||
return establish_session(session, response, request, user, identity.provider)
|