f1tness_parser/backend/app/api/v1/users.py
2026-10-23 20:30:41 +03:00

80 lines
2.5 KiB
Python

from typing import List, Optional
from fastapi import APIRouter, Depends, HTTPException, status
from app.api.deps import get_user_repository
from app.core.database.user_repository import EmailTakenError, UserRepository
from app.core.dto.user import UserDTO, UserRole
from app.core.security import hash_password
from app.schemas.users import UserCreate, UserUpdate
router = APIRouter()
EMAIL_TAKEN = HTTPException(status_code=409, detail="Email already registered")
@router.post("/", response_model=UserDTO, status_code=status.HTTP_201_CREATED)
async def create_user(
payload: UserCreate,
repository: UserRepository = Depends(get_user_repository),
):
try:
return await repository.create(
email=payload.email,
password_hash=hash_password(payload.password),
first_name=payload.first_name,
last_name=payload.last_name,
role=payload.role,
)
except EmailTakenError:
raise EMAIL_TAKEN
@router.get("/", response_model=List[UserDTO])
async def list_users(
role: Optional[UserRole] = None,
repository: UserRepository = Depends(get_user_repository),
):
return await repository.list(role)
@router.get("/{user_id}/", response_model=UserDTO)
async def get_user(
user_id: int,
repository: UserRepository = Depends(get_user_repository),
):
user = await repository.get(user_id)
if user is None:
raise HTTPException(status_code=404, detail="User not found")
return user
@router.patch("/{user_id}/", response_model=UserDTO)
async def update_user(
user_id: int,
payload: UserUpdate,
repository: UserRepository = Depends(get_user_repository),
):
values = payload.model_dump(exclude_unset=True)
if "password" in values:
values["password_hash"] = hash_password(values.pop("password"))
# null makes no sense for these columns
if any(values.get(name, "") is None for name in ("email", "role", "is_active", "password_hash")):
raise HTTPException(status_code=422, detail="Field must not be null")
try:
user = await repository.update(user_id, values)
except EmailTakenError:
raise EMAIL_TAKEN
if user is None:
raise HTTPException(status_code=404, detail="User not found")
return user
@router.delete("/{user_id}/")
async def delete_user(
user_id: int,
repository: UserRepository = Depends(get_user_repository),
):
if not await repository.delete(user_id):
raise HTTPException(status_code=404, detail="User not found")
return {"status": "ok"}