PrivilegeGuardTrait
Server-side privilege gate for admin components.
Presenters have PrivilegeCheckTrait::checkPrivilege(),
but it is protected and cannot be called from a component. Components have their own
mutating signals (handleAdd, handleDelete, handleToggleDeleted, ...) that can be
triggered by a hand-built URL exactly like presenter signals.
The trait does not copy the privilege logic; it asks the presenter through
PrivilegeCheckTrait::isAllowed(). That method is
public on purpose (templates call it too) and reads the array loaded once per request
in startup(), so the gate costs no extra database query.
IMPORTANT: fail-closed. A presenter outside the admin branch (no isAllowed()) and a
missing privilege both end in 403; the opposite order ("when unsure, allow") would turn
the gate into decoration.
NOTE: an unattached component is deliberately not tested: getPresenter() throws
InvalidStateException itself (its return type is Presenter, not ?Presenter), so the
signal never runs. An own is_object() check would be dead code.
Table of Contents
Methods
- isTargetAllowed() : bool
- Returns whether the logged-in user may open the given admin target. For visibility (tiles, autocomplete, buttons); it does not throw.
- requirePrivilege() : void
- Throws 403 when the logged-in user lacks the given admin privilege.
- resolvePageTarget() : string|null
- Returns the RBAC key of the target page: `<presenter>:<action>`, e.g. `:Admin:System:User:show`.
Methods
isTargetAllowed()
Returns whether the logged-in user may open the given admin target. For visibility (tiles, autocomplete, buttons); it does not throw.
protected
isTargetAllowed(string|null $key) : bool
IMPORTANT: fail-closed like requirePrivilege(): an empty key and a presenter
without isAllowed() both mean no. A component that skips this question lists the
target to everyone.
Parameters
- $key : string|null
Return values
boolrequirePrivilege()
Throws 403 when the logged-in user lacks the given admin privilege.
protected
requirePrivilege(string $key) : void
Call it as the first statement of a mutating signal, before loading data, so the check cannot be bypassed by something being written first.
Parameters
- $key : string
resolvePageTarget()
Returns the RBAC key of the target page: `<presenter>:<action>`, e.g. `:Admin:System:User:show`.
protected
static resolvePageTarget(object|null $page) : string|null
Same interpretation as Menu::filterByPrivileges(), BasePresenter::authorizeListing() and PrivilegeCheckTrait::checkCurrentPrivilege(). The key is derived from the page target only, never from a file or class name.
Returns null when the page is missing or has no presenter, so there is nothing to allow.
Parameters
- $page : object|null
-
AdminPageentity (hydrated, hence justobject)