from fastapi import APIRouter, HTTPException, status, Request from sqlalchemy import select from app.api.deps import DbSession, CurrentUser from app.core.security import verify_password, get_password_hash, create_access_token from app.core.rate_limit import limiter from app.models import User from app.schemas import UserRegister, UserLogin, TokenResponse, UserPrivate router = APIRouter(prefix="/auth", tags=["auth"]) @router.post("/register", response_model=TokenResponse) @limiter.limit("5/minute") async def register(request: Request, data: UserRegister, db: DbSession): # Check if login already exists result = await db.execute(select(User).where(User.login == data.login.lower())) if result.scalar_one_or_none(): raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Login already registered", ) # Create user user = User( login=data.login.lower(), password_hash=get_password_hash(data.password), nickname=data.nickname, ) db.add(user) await db.commit() await db.refresh(user) # Generate token access_token = create_access_token(subject=user.id) return TokenResponse( access_token=access_token, user=UserPrivate.model_validate(user), ) @router.post("/login", response_model=TokenResponse) @limiter.limit("10/minute") async def login(request: Request, data: UserLogin, db: DbSession): # Find user result = await db.execute(select(User).where(User.login == data.login.lower())) user = result.scalar_one_or_none() if not user or not verify_password(data.password, user.password_hash): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Incorrect login or password", ) # Generate token access_token = create_access_token(subject=user.id) return TokenResponse( access_token=access_token, user=UserPrivate.model_validate(user), ) @router.get("/me", response_model=UserPrivate) async def get_me(current_user: CurrentUser): """Get current user's full profile (including private data)""" return UserPrivate.model_validate(current_user)