"""User management API: list, detail, update, approve — only owner.""" from fastapi import APIRouter, Depends, HTTPException, Query, status from sqlalchemy import select, func from sqlalchemy.ext.asyncio import AsyncSession from app.database import get_db from app.middleware.auth import require_role from app.models.user import User from app.schemas.user import UserResponse, UserUpdateRequest router = APIRouter(prefix="/api/v1/users", tags=["users"]) @router.get("", response_model=list[UserResponse]) async def list_users( page: int = Query(1, ge=1), page_size: int = Query(20, ge=1, le=100), user: User = Depends(require_role("owner")), db: AsyncSession = Depends(get_db), ): result = await db.execute( select(User).offset((page - 1) * page_size).limit(page_size) ) return result.scalars().all() @router.get("/{user_id}", response_model=UserResponse) async def get_user( user_id: str, user: User = Depends(require_role("owner")), db: AsyncSession = Depends(get_db), ): result = await db.execute(select(User).where(User.id == user_id)) target = result.scalar_one_or_none() if not target: raise HTTPException(status_code=404, detail="User not found") return target @router.patch("/{user_id}", response_model=UserResponse) async def update_user( user_id: str, body: UserUpdateRequest, user: User = Depends(require_role("owner")), db: AsyncSession = Depends(get_db), ): result = await db.execute(select(User).where(User.id == user_id)) target = result.scalar_one_or_none() if not target: raise HTTPException(status_code=404, detail="User not found") if body.role is not None: target.role = body.role if body.is_active is not None: target.is_active = body.is_active await db.commit() await db.refresh(target) return target @router.post("/{user_id}/approve", response_model=UserResponse) async def approve_user( user_id: str, user: User = Depends(require_role("owner")), db: AsyncSession = Depends(get_db), ): result = await db.execute(select(User).where(User.id == user_id)) target = result.scalar_one_or_none() if not target: raise HTTPException(status_code=404, detail="User not found") if target.is_approved: raise HTTPException(status_code=400, detail="User already approved") target.is_approved = True await db.commit() await db.refresh(target) return target