From 997d60138a096f91f1f8b6114ad65f2d7c4db56f Mon Sep 17 00:00:00 2001 From: Leopoldadmin Date: Fri, 3 Jul 2026 20:43:55 +0000 Subject: [PATCH] Fix route: use model_fields_set to pass _UNSET when role_id not sent, None when explicitly null --- app/routes/users.py | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/app/routes/users.py b/app/routes/users.py index bbcd792..fd18659 100644 --- a/app/routes/users.py +++ b/app/routes/users.py @@ -13,7 +13,7 @@ from app.core.db import get_db from app.core.notifications import create_notification from app.deps import get_current_user, require_admin from app.schemas.user import UserCreate, UserUpdate -from app.services.user_service import user_service +from app.services.user_service import user_service, _UNSET router = APIRouter(prefix="/api/v1/users", tags=["users"]) @@ -21,7 +21,7 @@ router = APIRouter(prefix="/api/v1/users", tags=["users"]) def _parse_role_id(raw: str | None) -> uuid.UUID | None: """Convert a string body value into a UUID or None. - Empty string and None are both treated as "no role_id". + Empty string and None are both treated as "clear role_id". """ if raw is None or raw == "": return None @@ -138,7 +138,12 @@ async def update_user( db: AsyncSession = Depends(get_db), current_user: dict = Depends(require_admin), ): - """Update a user (admin only).""" + """Update a user (admin only). + + Uses ``model_fields_set`` to detect whether ``role_id`` was explicitly + present in the request body (even if sent as ``null``). This allows + the caller to clear the FK by sending ``role_id: null``. + """ tenant_id = uuid.UUID(current_user["tenant_id"]) acting_user_id = uuid.UUID(current_user["user_id"]) try: @@ -148,17 +153,26 @@ async def update_user( 400, detail={"detail": "Invalid user_id", "code": "invalid_id"} ) from None + # Determine if role_id was explicitly sent (Pydantic v2) + role_id_sent = "role_id" in body.model_fields_set + changes: dict[str, Any] = {} if body.name is not None: changes["name"] = body.name if body.role is not None: changes["role"] = body.role - if body.role_id is not None: + if role_id_sent: changes["role_id"] = body.role_id if body.is_active is not None: changes["is_active"] = body.is_active - role_id = _parse_role_id(body.role_id) + # Pass _UNSET sentinel when role_id was not in the request body + # so the service leaves the existing value untouched. + role_id: uuid.UUID | None | Any + if role_id_sent: + role_id = _parse_role_id(body.role_id) + else: + role_id = _UNSET user = await user_service.update_user( db,