Files
secure-online-shop/app/api/auth.py
T

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)