Oihana PHP Arango

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 $enforcer
  • string $domain
  • ?Documents $rolesModel
  • ?Documents $permissionsModel
  • ?Documents $policiesModel
  • ?LoggerInterface $logger

Plus the standalone helper casbinSafeSubject().

Tags
author

Marc Alcaraz

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
throws
BindException
ContainerExceptionInterface
ArangoException
NotFoundExceptionInterface
ReflectionException

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
throws
BindException
ContainerExceptionInterface
ArangoException
NotFoundExceptionInterface
ReflectionException

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
throws
BindException
ContainerExceptionInterface
ArangoException
NotFoundExceptionInterface
ReflectionException

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
throws
BindException
ContainerExceptionInterface
ArangoException
NotFoundExceptionInterface
ReflectionException

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 _key of the role vertex.

Tags
throws
BindException
ContainerExceptionInterface
ArangoException
NotFoundExceptionInterface
ReflectionException
Return values
string|null

null if the role vertex is gone.

On this page

Search results