perf(auth): avoid duplicate user lookup in require_role
require_role._check previously chained from get_current_user, which already loaded the user — then looked it up again. Inline the decode + single user fetch + must_change_password + role check so every authenticated request costs one SELECT users WHERE uuid=? instead of two.
This commit is contained in:
@@ -105,13 +105,26 @@ async def get_current_user_unchecked(request: Request) -> str:
|
|||||||
def require_role(*allowed_roles: str):
|
def require_role(*allowed_roles: str):
|
||||||
"""Factory that returns a FastAPI dependency enforcing role membership.
|
"""Factory that returns a FastAPI dependency enforcing role membership.
|
||||||
|
|
||||||
The returned dependency chains from ``get_current_user`` (JWT + must_change_password)
|
Inlines JWT decode + user lookup + must_change_password + role check so the
|
||||||
then verifies the user's role is in *allowed_roles*. Returns the full user dict so
|
user is only loaded from the DB once per request (not once in
|
||||||
endpoints can inspect ``user["uuid"]``, ``user["role"]``, etc. without a second lookup.
|
``get_current_user`` and again here). Returns the full user dict so
|
||||||
|
endpoints can inspect ``user["uuid"]``, ``user["role"]``, etc.
|
||||||
"""
|
"""
|
||||||
async def _check(current_user: str = Depends(get_current_user)) -> dict:
|
async def _check(request: Request) -> dict:
|
||||||
user = await repo.get_user_by_uuid(current_user)
|
user_uuid = await _decode_token(request)
|
||||||
if not user or user["role"] not in allowed_roles:
|
user = await repo.get_user_by_uuid(user_uuid)
|
||||||
|
if not user:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||||
|
detail="Could not validate credentials",
|
||||||
|
headers={"WWW-Authenticate": "Bearer"},
|
||||||
|
)
|
||||||
|
if user.get("must_change_password"):
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_403_FORBIDDEN,
|
||||||
|
detail="Password change required before accessing this resource",
|
||||||
|
)
|
||||||
|
if user["role"] not in allowed_roles:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_403_FORBIDDEN,
|
status_code=status.HTTP_403_FORBIDDEN,
|
||||||
detail="Insufficient permissions",
|
detail="Insufficient permissions",
|
||||||
|
|||||||
Reference in New Issue
Block a user