Init first files
This commit is contained in:
65
backend/app/api/routes/admin_users.py
Normal file
65
backend/app/api/routes/admin_users.py
Normal file
@@ -0,0 +1,65 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from app.core.db import get_db
|
||||
from app.core.deps import require_roles
|
||||
from app.core.security import hash_password
|
||||
from app.models.models import User
|
||||
from app.schemas.user import UserCreate, UserOut, UserUpdate
|
||||
from app.services.audit import write_audit_log
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("", response_model=list[UserOut])
|
||||
async def list_users(admin: User = Depends(require_roles("admin")), db: AsyncSession = Depends(get_db)) -> list[UserOut]:
|
||||
users = (await db.scalars(select(User).order_by(User.id.asc()))).all()
|
||||
_ = admin
|
||||
return [UserOut.model_validate(user) for user in users]
|
||||
|
||||
|
||||
@router.post("", response_model=UserOut, status_code=status.HTTP_201_CREATED)
|
||||
async def create_user(payload: UserCreate, admin: User = Depends(require_roles("admin")), db: AsyncSession = Depends(get_db)) -> UserOut:
|
||||
exists = await db.scalar(select(User).where(User.email == payload.email))
|
||||
if exists:
|
||||
raise HTTPException(status_code=409, detail="Email already exists")
|
||||
user = User(email=payload.email, password_hash=hash_password(payload.password), role=payload.role)
|
||||
db.add(user)
|
||||
await db.commit()
|
||||
await db.refresh(user)
|
||||
await write_audit_log(db, "admin.user.create", admin.id, {"created_user_id": user.id})
|
||||
return UserOut.model_validate(user)
|
||||
|
||||
|
||||
@router.put("/{user_id}", response_model=UserOut)
|
||||
async def update_user(
|
||||
user_id: int,
|
||||
payload: UserUpdate,
|
||||
admin: User = Depends(require_roles("admin")),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
) -> UserOut:
|
||||
user = await db.scalar(select(User).where(User.id == user_id))
|
||||
if not user:
|
||||
raise HTTPException(status_code=404, detail="User not found")
|
||||
update_data = payload.model_dump(exclude_unset=True)
|
||||
if "password" in update_data and update_data["password"]:
|
||||
user.password_hash = hash_password(update_data.pop("password"))
|
||||
for key, value in update_data.items():
|
||||
setattr(user, key, value)
|
||||
await db.commit()
|
||||
await db.refresh(user)
|
||||
await write_audit_log(db, "admin.user.update", admin.id, {"updated_user_id": user.id})
|
||||
return UserOut.model_validate(user)
|
||||
|
||||
|
||||
@router.delete("/{user_id}")
|
||||
async def delete_user(user_id: int, admin: User = Depends(require_roles("admin")), db: AsyncSession = Depends(get_db)) -> dict:
|
||||
if user_id == admin.id:
|
||||
raise HTTPException(status_code=400, detail="Cannot delete yourself")
|
||||
user = await db.scalar(select(User).where(User.id == user_id))
|
||||
if not user:
|
||||
raise HTTPException(status_code=404, detail="User not found")
|
||||
await db.delete(user)
|
||||
await db.commit()
|
||||
await write_audit_log(db, "admin.user.delete", admin.id, {"deleted_user_id": user_id})
|
||||
return {"status": "deleted"}
|
||||
Reference in New Issue
Block a user