from fastapi import APIRouter, HTTPException, status, Depends from fastapi.responses import JSONResponse import httpx from loguru import logger from typing import Annotated from app.core.config import settings # ИСПРАВЛЕНИЕ ЗДЕСЬ from app.api.v1.schemas.auth import TokenRequest, TokenResponse, UserInfoResponse # --- ДОБАВЛЕНО ДЛЯ НОВОГО ЭНДПОИНТА --- from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials router = APIRouter() bearer_scheme = HTTPBearer() YANDEX_TOKEN_URL = "https://oauth.yandex.ru/token" # --- ДОБАВЛЕНО ДЛЯ НОВОГО ЭНДПОИНТА --- YANDEX_USERINFO_URL = "https://login.yandex.ru/info" @router.post("/token", response_model=TokenResponse, summary="Обмен кода авторизации на токен доступа") async def exchange_code_for_token(request: TokenRequest): """ Принимает временный 'code' от фронтенда, обменивает его на 'access_token' у Яндекса и возвращает токен клиенту. """ logger.info("Attempting to exchange authorization code for an access token.") payload = { 'grant_type': 'authorization_code', 'code': request.code, 'client_id': settings.YANDEX_CLIENT_ID, 'client_secret': settings.YANDEX_CLIENT_SECRET } try: async with httpx.AsyncClient() as client: response = await client.post(YANDEX_TOKEN_URL, data=payload) response.raise_for_status() token_data = response.json() logger.success("Successfully received access token from Yandex.") return TokenResponse( access_token=token_data.get("access_token"), token_type=token_data.get("token_type", "bearer") ) except httpx.HTTPStatusError as e: error_details = e.response.json() logger.error(f"Yandex OAuth error: {e.response.status_code} - {error_details}") raise HTTPException( status_code=e.response.status_code, detail=f"Yandex OAuth error: {error_details.get('error_description', 'Unknown error')}" ) except Exception as e: logger.opt(exception=True).error("An unexpected error occurred during token exchange.") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="An internal server error occurred." ) # --- НОВЫЙ ЭНДПОИНТ --- @router.get("/userinfo", response_model=UserInfoResponse, summary="Получение информации о пользователе") async def get_user_info(credentials: Annotated[HTTPAuthorizationCredentials, Depends(bearer_scheme)]): """ Используя access_token, получает информацию о пользователе Яндекса. Токен должен быть передан в заголовке 'Authorization: Bearer '. """ token = credentials.credentials headers = {'Authorization': f'OAuth {token}'} try: async with httpx.AsyncClient() as client: response = await client.get(YANDEX_USERINFO_URL, headers=headers) response.raise_for_status() user_data = response.json() logger.info(f"Fetched user info for login: {user_data.get('login')}") return UserInfoResponse(**user_data) except httpx.HTTPStatusError as e: error_details = e.response.json() logger.error(f"Yandex UserInfo API error: {e.response.status_code} - {error_details}") raise HTTPException( status_code=e.response.status_code, detail=f"Yandex API Error: {error_details.get('error_description', 'Unknown error')}" ) except Exception: logger.opt(exception=True).error("An unexpected error occurred while fetching user info.") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="An internal server error occurred." )