Fix route: use model_fields_set to pass _UNSET when role_id not sent, None when explicitly null
This commit is contained in:
+19
-5
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user