Add break-glass override plumbing for policy-held actions
Adds caller_is_role(), the body-answering counterpart to require_role, for routes that serve everyone but treat one class of caller differently. A scoped personal token is always refused here, matching require_role: scopes gate individual permissions, not roles. That invariant stops a leaked scoped agent token from inheriting override authority just because its owner is an admin - a scoped PAT is a narrower caller than its owner, admin included. Frontend enqueueCommand now carries policyoverride with overridereason. Both are required together server-side and an override without a stated reason is rejected, so the caller must collect the reason before sending rather than discovering the refusal after the fact.
This commit is contained in:
@@ -125,6 +125,32 @@ def caller_holds(permission_name: str) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
def caller_is_role(rolename: str) -> bool:
|
||||
"""Whether THIS caller holds a role, without refusing the request.
|
||||
|
||||
The body-answering counterpart to require_role, for a route that serves
|
||||
everyone but treats one class of caller differently - break-glass override
|
||||
being the case that prompted it.
|
||||
|
||||
A scoped personal token is ALWAYS refused here, matching require_role: scopes
|
||||
gate individual permissions, not roles. This is the invariant that keeps a
|
||||
leaked scoped agent token from inheriting override authority just because the
|
||||
token's owner happens to be an admin. A scoped PAT is a narrower caller than
|
||||
its owner, including when that owner is an admin.
|
||||
|
||||
Guests hold no roles, so an unauthenticated caller is always False.
|
||||
"""
|
||||
user = currentuser()
|
||||
if user is None:
|
||||
return False
|
||||
try:
|
||||
if get_jwt().get('patscopes') is not None:
|
||||
return False
|
||||
return user.hasrole(rolename)
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
def require_permission(permission_name: str):
|
||||
"""Gate a route behind a single permission. Admin role bypasses.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user