Files
freelancer-match/backend/app/api/auth.py
T

85 lines
3.1 KiB
Python
Raw Normal View History

"""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"]}