feat: LocalPro Finder — продакшн проект (отзывы, рейтинги, чат, AI-оценка, диагностика, подписки)
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
"""Аутентификация — регистрация, логин, JWT-токены"""
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy import select
|
||||
import uuid
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from ...core.database import async_session_factory, User, UserRole
|
||||
from ...utils.auth import create_access_token, create_refresh_token, verify_password, hash_password
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
class RegisterRequest(BaseModel):
|
||||
email: str
|
||||
password: str
|
||||
role: str = "client" # client | master
|
||||
first_name: str
|
||||
last_name: str
|
||||
phone: str | None = None
|
||||
|
||||
|
||||
class LoginRequest(BaseModel):
|
||||
email: str
|
||||
password: str
|
||||
|
||||
|
||||
@router.post("/register")
|
||||
async def register(req: RegisterRequest, session: AsyncSession = Depends(async_session_factory)):
|
||||
"""Регистрация пользователя."""
|
||||
|
||||
existing = await session.execute(select(User).where(User.email == req.email))
|
||||
if existing.scalar_one_or_none():
|
||||
raise HTTPException(409, "Email уже зарегистрирован")
|
||||
|
||||
user = User(
|
||||
email=req.email,
|
||||
password_hash=hash_password(req.password),
|
||||
role=UserRole(req.role),
|
||||
first_name=req.first_name,
|
||||
last_name=req.last_name,
|
||||
phone=req.phone,
|
||||
)
|
||||
session.add(user)
|
||||
await session.commit()
|
||||
|
||||
access_token = create_access_token(str(user.id))
|
||||
refresh_token = create_refresh_token(str(user.id))
|
||||
|
||||
return {
|
||||
"user_id": str(user.id),
|
||||
"email": user.email,
|
||||
"role": user.role.value,
|
||||
"access_token": access_token,
|
||||
"refresh_token": refresh_token,
|
||||
}
|
||||
|
||||
|
||||
@router.post("/login")
|
||||
async def login(req: LoginRequest, session: AsyncSession = Depends(async_session_factory)):
|
||||
"""Логин."""
|
||||
|
||||
result = await session.execute(select(User).where(User.email == req.email))
|
||||
user = result.scalar_one_or_none()
|
||||
|
||||
if not user or not verify_password(req.password, user.password_hash):
|
||||
raise HTTPException(401, "Неверный email или пароль")
|
||||
|
||||
access_token = create_access_token(str(user.id))
|
||||
refresh_token = create_refresh_token(str(user.id))
|
||||
|
||||
return {
|
||||
"user_id": str(user.id),
|
||||
"email": user.email,
|
||||
"role": user.role.value,
|
||||
"access_token": access_token,
|
||||
"refresh_token": refresh_token,
|
||||
}
|
||||
|
||||
|
||||
@router.post("/refresh")
|
||||
async def refresh_token(req: dict, session: AsyncSession = Depends(async_session_factory)):
|
||||
"""Обновить токен."""
|
||||
|
||||
from ...utils.auth import decode_refresh_token
|
||||
user_id = decode_refresh_token(req["refresh_token"])
|
||||
access_token = create_access_token(user_id)
|
||||
return {"access_token": access_token}
|
||||
|
||||
|
||||
@router.get("/me")
|
||||
async def get_me(user=Depends(get_current_user), session: AsyncSession = Depends(async_session_factory)):
|
||||
"""Получить данные текущего пользователя."""
|
||||
|
||||
user = await session.get(User, uuid.UUID(str(user.id)))
|
||||
return {
|
||||
"id": str(user.id),
|
||||
"email": user.email,
|
||||
"first_name": user.first_name,
|
||||
"last_name": user.last_name,
|
||||
"phone": user.phone,
|
||||
"role": user.role.value,
|
||||
"avatar_url": user.avatar_url,
|
||||
}
|
||||
Reference in New Issue
Block a user