"""User management router (admin only).""" # Import uuid import uuid # Import APIRouter, Depends, status from fastapi from fastapi import APIRouter, Depends, status # Import Session from sqlalchemy.orm from sqlalchemy.orm import Session # Import get_db from app.database from app.database import get_db # Import require_role from app.dependencies.auth from app.dependencies.auth import require_role # Import UnitOfWork from app.domain.unit_of_work from app.domain.unit_of_work import UnitOfWork # Import User from app.models.user from app.models.user import User # Import UserCreate, UserOut, UserUpdate from app.schemas.user from app.schemas.user import UserCreate, UserOut, UserUpdate # Import log_action from app.services.audit_service from app.services.audit_service import log_action # Import from app.services.user_service from app.services.user_service import ( create_user, get_user_or_raise, list_users, update_user, ) # Assign router = APIRouter(prefix="/users", tags=["users"]) router = APIRouter(prefix="/users", tags=["users"]) # --------------------------------------------------------------------------- # GET /users — list all users # --------------------------------------------------------------------------- @router.get("", response_model=list[UserOut]) # Define function list_users_route def list_users_route( # Entry: db db: Session = Depends(get_db), # Entry: current_user current_user: User = Depends(require_role("admin")), ) -> list[UserOut]: """Return a list of all users. **Requires admin role.**.""" # Return list_users(db) return list_users(db) # --------------------------------------------------------------------------- # POST /users — create a new user # --------------------------------------------------------------------------- @router.post("", response_model=UserOut, status_code=status.HTTP_201_CREATED) # Define function create_user_route def create_user_route( # Entry: payload payload: UserCreate, # Entry: db db: Session = Depends(get_db), # Entry: current_user current_user: User = Depends(require_role("admin")), ) -> UserOut: """Create a new user. **Requires admin role.**.""" # Open context manager with UnitOfWork(db) as uow: # Assign user = create_user( user = create_user( db, # Keyword argument: username username=payload.username, # Keyword argument: email email=payload.email, # Keyword argument: password password=payload.password, # Keyword argument: role role=payload.role, ) # Call log_action() log_action( db, # Keyword argument: user_id user_id=current_user.id, # Keyword argument: action action="create_user", # Keyword argument: entity_type entity_type="user", # Keyword argument: entity_id entity_id=user.id, # Keyword argument: details details={"username": user.username, "role": user.role}, ) # Call uow.commit() uow.commit() # Reload ORM object attributes from the database db.refresh(user) # Return user return user # --------------------------------------------------------------------------- # GET /users/{id} — get a single user # --------------------------------------------------------------------------- @router.get("/{user_id}", response_model=UserOut) # Define function get_user def get_user( # Entry: user_id user_id: uuid.UUID, # Entry: db db: Session = Depends(get_db), # Entry: current_user current_user: User = Depends(require_role("admin")), ) -> UserOut: """Return a single user by ID. **Requires admin role.**.""" # Return get_user_or_raise(db, user_id) return get_user_or_raise(db, user_id) # --------------------------------------------------------------------------- # PATCH /users/{id} — update a user # --------------------------------------------------------------------------- @router.patch("/{user_id}", response_model=UserOut) # Define function update_user_route def update_user_route( # Entry: user_id user_id: uuid.UUID, # Entry: payload payload: UserUpdate, # Entry: db db: Session = Depends(get_db), # Entry: current_user current_user: User = Depends(require_role("admin")), ) -> UserOut: """Update one or more fields of an existing user. **Requires admin role.**.""" # Assign update_data = payload.model_dump(exclude_unset=True) update_data = payload.model_dump(exclude_unset=True) # Open context manager with UnitOfWork(db) as uow: # Assign user = update_user(db, user_id, **update_data) user = update_user(db, user_id, **update_data) # Call log_action() log_action( db, # Keyword argument: user_id user_id=current_user.id, # Keyword argument: action action="update_user", # Keyword argument: entity_type entity_type="user", # Keyword argument: entity_id entity_id=user.id, # Keyword argument: details details={"updated_fields": list(update_data.keys())}, ) # Call uow.commit() uow.commit() # Reload ORM object attributes from the database db.refresh(user) # Return user return user