CasbinPolicySyncRoleTrait
Casbin policy synchronization handlers for the `roles` collection.
Handles the role branch of the live RBAC sync : direct
role_has_permissions edges, indirect role_has_policies propagation
(one Casbin row per permission of the policy keyed on the role
identifier), and the cascade-aware role vertex deletion which wipes
every Casbin trace of the role in one shot.
Subject convention : every Casbin row keyed on a role uses the role's
stable identifier (Zitadel role key, pinned at POST time and never
mutated). Legacy roles created before the pin convention fall back to
name, which is also their current Zitadel key — once
php bin/console.php auth:roles:backfill-identifiers has run, the fallback becomes
dead code.
The trait expects the consumer class to expose the following protected properties (already declared on CasbinPolicySync via constructor promotion) :
?Enforcer $enforcerstring $domain?Documents $rolesModel?Documents $permissionsModel?Documents $policiesModel?LoggerInterface $logger
Plus the standalone helper casbinSafeSubject().
Tags
Table of Contents
Methods
- registerRoleDelete() : void
- Registers cleanup of Casbin policies / groupings when a role vertex is deleted.
- addRolePermissionPolicy() : void
- Adds: p, roleIdentifier, domain, object, action, effect
- addRolePolicyPolicies() : void
- Adds policies for every permission of a policy attached to a role.
- onRoleDelete() : void
- Called when a role vertex is deleted — wipes every Casbin trace of that role.
- removeRolePermissionPolicy() : void
- Removes: p, roleIdentifier, domain, object, action, effect
- removeRolePolicyPolicies() : void
- Removes policies for every permission of a policy detached from a role.
- resolveRoleSubject() : string|null
- Resolves the Casbin subject for a role.
Methods
registerRoleDelete()
Registers cleanup of Casbin policies / groupings when a role vertex is deleted.
public
registerRoleDelete(Documents $rolesModel) : void
The cascade edge purge wired on the Roles model (role_has_permissions,
user_has_roles via RolesController::CASCADE_EDGES) removes the edges
with a raw AQL query, which bypasses per-edge afterDelete signals.
As a consequence the normal edge-level Casbin sync is never triggered
for those cascaded deletes and policies/groupings would leak.
This listener subscribes to the role model's afterDelete signal and
calls Enforcer::deleteRole($name) for every deleted role — which wipes
both the p, <roleName>, ... policies and the g, <userId>, <roleName>, ...
groupings in one shot.
Parameters
- $rolesModel : Documents
-
The roles vertex model.
addRolePermissionPolicy()
Adds: p, roleIdentifier, domain, object, action, effect
protected
addRolePermissionPolicy(string $roleKey, string $permissionKey) : void
The Casbin subject for role-level policies is the role's stable
identifier (Zitadel role key), never the mutable name. This way
a PATCH rename never has to rewrite policies — name drifts but
identifier is set once at POST time and pinned forever.
Legacy fallback: for roles created before the identifier pin
convention landed (typically the 3 seeded ones: admin/guest/superadmin
when not yet backfilled) we fall back to $role->name, which is
their current Zitadel key. Backfill command:
php bin/console.php auth:roles:backfill-identifiers.
Parameters
- $roleKey : string
- $permissionKey : string
Tags
addRolePolicyPolicies()
Adds policies for every permission of a policy attached to a role.
protected
addRolePolicyPolicies(string $roleKey, string $policyKey) : void
When a policy vertex is attached to a role via the
role_has_policies edge, every permission contained in the policy
must be materialised in Casbin keyed on the role's stable
identifier — otherwise getImplicitPermissionsForUser will not
walk through policy_has_permissions and the role's effective
permission set silently misses the policy's permissions.
Without this method, the M2M branch (service → policy) is the
only path Casbin sees, and self-service callers whose effective
permissions depend on a role-attached policy fail
validatePolicyAttachmentPermissions even though they have the
permission "on paper" (in the role's policies tab).
Parameters
- $roleKey : string
-
The role ArangoDB
_key. - $policyKey : string
-
The policy ArangoDB
_key.
Tags
onRoleDelete()
Called when a role vertex is deleted — wipes every Casbin trace of that role.
protected
onRoleDelete(Payload $payload) : void
The payload data is the OLD document (or list of documents) returned
by the ArangoDB REMOVE query, so role names are still accessible even
though the vertex is gone.
Parameters
- $payload : Payload
removeRolePermissionPolicy()
Removes: p, roleIdentifier, domain, object, action, effect
protected
removeRolePermissionPolicy(string $roleKey, string $permissionKey) : void
Same identifier-vs-name convention as addRolePermissionPolicy.
Parameters
- $roleKey : string
- $permissionKey : string
Tags
removeRolePolicyPolicies()
Removes policies for every permission of a policy detached from a role.
protected
removeRolePolicyPolicies(string $roleKey, string $policyKey) : void
Mirror of addRolePolicyPolicies.
Parameters
- $roleKey : string
-
The role ArangoDB
_key. - $policyKey : string
-
The policy ArangoDB
_key.
Tags
resolveRoleSubject()
Resolves the Casbin subject for a role.
protected
resolveRoleSubject(string $roleKey) : string|null
Roles created since the Zitadel pin convention carry their stable
identifier (Zitadel role key = Arango _key of the role vertex).
Legacy roles (admin / guest / superadmin seeded before the pin
landed, not yet backfilled) fall back to name, which is their
current Zitadel key — safe for Casbin. Once the backfill command
php bin/console.php auth:roles:backfill-identifiers has run, every role has an
identifier and the fallback becomes dead code.
Parameters
- $roleKey : string
-
The ArangoDB
_keyof the role vertex.
Tags
Return values
string|null —null if the role vertex is gone.