70 lines
1.9 KiB
Python
70 lines
1.9 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import Annotated
|
|
|
|
from fastapi import APIRouter, Depends, Request, status
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.api.dependencies import get_current_user
|
|
from app.core.exceptions import UnauthorizedError
|
|
from app.core.rate_limit import login_rate_limiter
|
|
from app.db.session import get_db
|
|
from app.models.user import User
|
|
from app.schemas.auth import LoginRequest, TokenResponse, UserCreate, UserResponse
|
|
from app.services.auth_service import AuthService
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.post(
|
|
"/register",
|
|
response_model=UserResponse,
|
|
status_code=status.HTTP_201_CREATED,
|
|
summary="Register a customer account",
|
|
)
|
|
def register_user(
|
|
payload: UserCreate,
|
|
db: Annotated[Session, Depends(get_db)],
|
|
) -> UserResponse:
|
|
user = AuthService(db).register_user(payload)
|
|
return UserResponse.model_validate(user)
|
|
|
|
|
|
@router.post(
|
|
"/login",
|
|
response_model=TokenResponse,
|
|
status_code=status.HTTP_200_OK,
|
|
summary="Authenticate and receive a JWT access token",
|
|
)
|
|
def login(
|
|
payload: LoginRequest,
|
|
request: Request,
|
|
db: Annotated[Session, Depends(get_db)],
|
|
) -> TokenResponse:
|
|
client_host = request.client.host if request.client else "unknown"
|
|
throttle_key = login_rate_limiter.build_key(payload.username, client_host)
|
|
|
|
if login_rate_limiter.is_limited(throttle_key):
|
|
login_rate_limiter.raise_limit_exceeded()
|
|
|
|
try:
|
|
access_token = AuthService(db).authenticate_user(payload)
|
|
except UnauthorizedError:
|
|
login_rate_limiter.record_failure(throttle_key)
|
|
raise
|
|
|
|
login_rate_limiter.reset(throttle_key)
|
|
return TokenResponse(access_token=access_token)
|
|
|
|
|
|
@router.get(
|
|
"/me",
|
|
response_model=UserResponse,
|
|
status_code=status.HTTP_200_OK,
|
|
summary="Get the authenticated user profile",
|
|
)
|
|
def get_me(
|
|
current_user: Annotated[User, Depends(get_current_user)],
|
|
) -> UserResponse:
|
|
return UserResponse.model_validate(current_user)
|