import secrets from logging import getLogger from fastapi import APIRouter from sqlmodel import select from apps.esia.sign import get_url from apps.users.models import User from clients import clients as c from database import AsyncSessionDep from shared import exceptions as e from shared.redis import client as cache from . import schema as s logger = getLogger(__name__) router = APIRouter( prefix='/esia', tags=[ 'ESIA', ], ) @router.get('/login', response_model=s.LoginURL) async def login(): url = get_url() return s.LoginURL(url=url) @router.post('/callback') async def callback(session: AsyncSessionDep, code: str): token = None for i in range(3): try: token = await c.esia_api.access_token(code) break except Exception: logger.warning( 'Error occurred while accessing ESI API. Retrying...' ) if i == 2: raise if token is None: raise e.BadRequestException esia_user = await c.esia_api.get_user_info( token.access_token, token.id_token ) try: vita_user = await c.vitacore_api.findBySnils(esia_user.snils) patId = vita_user.patId except e.UnknownException: raise e.BadRequestException(detail='Patient not found') from None existing_user_stmt = select(User).where(User.vita_id == patId).limit(1) existing_user = ( await session.execute(existing_user_stmt) ).scalar_one_or_none() if existing_user is None: user = User(vita_id=patId) session.add(user) await session.commit() await session.refresh(user) else: user = existing_user access_token = secrets.token_urlsafe(32) await cache.set(access_token, f'user:{user.id}') return s.Token(access_token=access_token)