Protect advanced request diagnostics for non-admins
Magent CI/CD / verify (push) Successful in 11m8s
Magent CI/CD / deploy-prod (push) Skipped
Magent CI/CD / deploy-beta (push) Successful in 19s

This commit is contained in:
2026-08-31 16:09:17 +12:00
parent ecf9b230c1
commit 3402e53c31
3 changed files with 129 additions and 21 deletions
+21 -7
View File
@@ -255,13 +255,25 @@ def _user_can_use_search_auto(user: Dict[str, Any]) -> bool:
return bool(user.get("auto_search_enabled", True))
def _filter_snapshot_actions_for_user(snapshot: Snapshot, user: Dict[str, Any]) -> Snapshot:
if _user_can_use_search_auto(user):
return snapshot
snapshot.actions = [action for action in snapshot.actions if action.id != "search_auto"]
def _filter_snapshot_for_user(snapshot: Snapshot, user: Dict[str, Any]) -> Snapshot:
if not _user_can_use_search_auto(user):
snapshot.actions = [action for action in snapshot.actions if action.id != "search_auto"]
if user.get("role") != "admin":
# The standard request view is intentionally collaborative, but service payloads can
# contain requester identities, internal URLs, download hashes and diagnostic errors.
snapshot.timeline = []
snapshot.raw = {}
return snapshot
def _require_advanced_request_access(user: Dict[str, Any]) -> None:
if user.get("role") != "admin":
raise HTTPException(
status_code=403,
detail="Advanced request details are available to administrators only",
)
def _quality_profile_id(value: Any) -> Optional[int]:
if isinstance(value, int):
return value
@@ -1766,7 +1778,7 @@ async def get_snapshot(request_id: str, user: Dict[str, str] = Depends(get_curre
if client.configured():
await _ensure_request_access(client, int(request_id), user)
snapshot = await build_snapshot(request_id)
return _filter_snapshot_actions_for_user(snapshot, user)
return _filter_snapshot_for_user(snapshot, user)
@router.post("/{request_id}/actions/recheck")
@@ -1825,7 +1837,7 @@ async def action_recheck(request_id: str, user: Dict[str, str] = Depends(get_cur
_cache_set(f"request:{request_id}", fresh_request)
_refresh_recent_cache_from_db()
snapshot = _filter_snapshot_actions_for_user(await build_snapshot(request_id), user)
snapshot = _filter_snapshot_for_user(await build_snapshot(request_id), user)
status_label = str((snapshot.presentation.get("status") or {}).get("label") or "Status updated")
message = f"Recheck complete. {status_label}."
await asyncio.to_thread(
@@ -2403,7 +2415,7 @@ async def ai_triage(request_id: str, user: Dict[str, str] = Depends(get_current_
client = JellyseerrClient(runtime.jellyseerr_base_url, runtime.jellyseerr_api_key)
if client.configured():
await _ensure_request_access(client, int(request_id), user)
snapshot = _filter_snapshot_actions_for_user(await build_snapshot(request_id), user)
snapshot = _filter_snapshot_for_user(await build_snapshot(request_id), user)
return triage_snapshot(snapshot)
@@ -2759,6 +2771,7 @@ async def action_readd(request_id: str, user: Dict[str, str] = Depends(get_curre
async def request_history(
request_id: str, limit: int = 10, user: Dict[str, str] = Depends(get_current_user)
) -> dict:
_require_advanced_request_access(user)
runtime = get_runtime_settings()
client = JellyseerrClient(runtime.jellyseerr_base_url, runtime.jellyseerr_api_key)
if client.configured():
@@ -2771,6 +2784,7 @@ async def request_history(
async def request_actions(
request_id: str, limit: int = 10, user: Dict[str, str] = Depends(get_current_user)
) -> dict:
_require_advanced_request_access(user)
runtime = get_runtime_settings()
client = JellyseerrClient(runtime.jellyseerr_base_url, runtime.jellyseerr_api_key)
if client.configured():