"""Общий вход: внешняя личность → пользователь → сессия. Прод-безопасный модуль (без импортов dev-провайдера). Используется и Telegram-входом, и 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.errors import ForbiddenError from app.models import User from app.services import audit_service, user_service def login_with_identity( session: Session, response: Response, request: Request, identity: ExternalIdentity ) -> User: user = user_service.get_or_create_from_identity(session, identity) if not user.is_active: raise ForbiddenError("Аккаунт отключён администратором.", code="ACCOUNT_DISABLED") security.set_user_session(response, user.id, identity.provider) # type: ignore[arg-type] audit_service.record( session, actor_id=user.id, action="login", entity_type="user", entity_id=user.id, payload={"provider": identity.provider}, ip=request.client.host if request.client else None, user_agent=request.headers.get("user-agent"), ) session.commit() return user