"""Auth endpoints: регистрация, логин, OAuth.""" import logging from datetime import timedelta from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select from app.core.database import get_db from app.core.security import ( hash_password, verify_password, create_access_token, create_refresh_token, get_current_user ) from app.schemas.user import UserCreate, UserLogin from app.schemas.auth import TokenPair from app.models.user import User, FreelancerProfile logger = logging.getLogger(__name__) router = APIRouter(prefix="/api/auth", tags=["auth"]) @router.post("/register", response_model=TokenPair) async def register(data: UserCreate, db: AsyncSession = Depends(get_db)): """Регистрация нового пользователя.""" # Проверка email result = await db.execute(select(User).where(User.email == data.email)) if result.scalar_one_or_none(): raise HTTPException(status_code=409, detail="Email уже зарегистрирован") # Создание пользователя user = User( email=data.email, password_hash=hash_password(data.password), role=data.role, full_name=data.full_name, ) db.add(user) await db.commit() await db.refresh(user) # Создаём профиль фрилансера по умолчанию if data.role in ("freelancer", "both"): profile = FreelancerProfile( user_id=user.id, skills=data.full_name or [], # заполняется позже ) db.add(profile) await db.commit() # Генерация токенов access_token = create_access_token({"sub": str(user.id), "role": data.role}) refresh_token = create_refresh_token({"sub": str(user.id)}) return TokenPair(access_token=access_token, refresh_token=refresh_token) @router.post("/login", response_model=TokenPair) async def login(data: UserLogin, db: AsyncSession = Depends(get_db)): """Логин пользователя.""" result = await db.execute(select(User).where(User.email == data.email)) user = result.scalar_one_or_none() if not user or not verify_password(data.password, user.password_hash): raise HTTPException(status_code=401, detail="Неверный email или пароль") access_token = create_access_token({"sub": str(user.id), "role": user.role}) refresh_token = create_refresh_token({"sub": str(user.id)}) return TokenPair(access_token=access_token, refresh_token=refresh_token) @router.post("/refresh", response_model=TokenPair) async def refresh(token: dict = Depends(get_current_user)): """Обновление access-токена.""" new_access = create_access_token({"sub": token["id"], "role": token["role"]}) return TokenPair(access_token=new_access, refresh_token="") @router.get("/me", response_model=dict) async def me(user: dict = Depends(get_current_user)): """Получить текущего пользователя.""" return {"user_id": user["id"], "role": user["role"]}