"""FluentGerman.ai — User management router (admin only).""" from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from app.auth import hash_password, require_admin from app.database import get_db from app.models import User from app.schemas import UserCreate, UserOut, UserUpdate router = APIRouter(prefix="/api/users", tags=["users"], dependencies=[Depends(require_admin)]) @router.get("/", response_model=list[UserOut]) async def list_users(db: AsyncSession = Depends(get_db)): result = await db.execute(select(User).where(User.is_admin == False).order_by(User.created_at.desc())) # noqa: E712 return result.scalars().all() @router.post("/", response_model=UserOut, status_code=status.HTTP_201_CREATED) async def create_user(body: UserCreate, db: AsyncSession = Depends(get_db)): # Check uniqueness existing = await db.execute( select(User).where((User.username == body.username) | (User.email == body.email)) ) if existing.scalar_one_or_none(): raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail="Username or email already exists") user = User( username=body.username, email=body.email, hashed_password=hash_password(body.password), ) db.add(user) await db.commit() await db.refresh(user) return user @router.put("/{user_id}", response_model=UserOut) async def update_user(user_id: int, body: UserUpdate, db: AsyncSession = Depends(get_db)): result = await db.execute(select(User).where(User.id == user_id)) user = result.scalar_one_or_none() if not user: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User not found") if body.username is not None: user.username = body.username if body.email is not None: user.email = body.email if body.password is not None: user.hashed_password = hash_password(body.password) if body.is_active is not None: user.is_active = body.is_active await db.commit() await db.refresh(user) return user @router.delete("/{user_id}", status_code=status.HTTP_204_NO_CONTENT) async def delete_user(user_id: int, db: AsyncSession = Depends(get_db)): result = await db.execute(select(User).where(User.id == user_id)) user = result.scalar_one_or_none() if not user: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User not found") await db.delete(user) await db.commit()