0 follower

Final Class Yiisoft\Rbac\Manager

InheritanceYiisoft\Rbac\Manager
ImplementsYiisoft\Rbac\ManagerInterface

Helps to manage RBAC hierarchy and check for permissions.

Method Details

Hide inherited methods

__construct() public method

public mixed __construct ( Yiisoft\Rbac\ItemsStorageInterface $itemsStorage, Yiisoft\Rbac\AssignmentsStorageInterface $assignmentsStorage, Yiisoft\Rbac\RuleFactoryInterface|null $ruleFactory null, boolean $enableDirectPermissions false, boolean $includeRolesInAccessChecks false, \Psr\Clock\ClockInterface|null $clock null )
$itemsStorage Yiisoft\Rbac\ItemsStorageInterface

Items storage.

$assignmentsStorage Yiisoft\Rbac\AssignmentsStorageInterface

Assignments storage.

$ruleFactory Yiisoft\Rbac\RuleFactoryInterface|null

Rule factory.

$enableDirectPermissions boolean

Whether to enable assigning permissions directly to user. Prefer assigning roles only.

$includeRolesInAccessChecks boolean

Whether to include roles (in addition to permissions) during access checks in {@see \Yiisoft\Rbac\Manager::userHasPermission()}.

$clock \Psr\Clock\ClockInterface|null

Instance of ClockInterface implementation to be used for getting current time.

                public function __construct(
    private readonly ItemsStorageInterface $itemsStorage,
    private readonly AssignmentsStorageInterface $assignmentsStorage,
    ?RuleFactoryInterface $ruleFactory = null,
    private readonly bool $enableDirectPermissions = false,
    private readonly bool $includeRolesInAccessChecks = false,
    private readonly ?ClockInterface $clock = null,
) {
    $this->ruleFactory = $ruleFactory ?? new SimpleRuleFactory();
}

            
addChild() public method

public self addChild ( string $parentName, string $childName )
$parentName string
$childName string

                public function addChild(string $parentName, string $childName): self
{
    $this->assertFutureChild($parentName, $childName);
    $this->itemsStorage->addChild($parentName, $childName);
    return $this;
}

            
addPermission() public method

public self addPermission ( Yiisoft\Rbac\Permission $permission )
$permission Yiisoft\Rbac\Permission

                public function addPermission(Permission $permission): self
{
    $this->addItem($permission);
    return $this;
}

            
addRole() public method

public self addRole ( Yiisoft\Rbac\Role $role )
$role Yiisoft\Rbac\Role

                public function addRole(Role $role): self
{
    $this->addItem($role);
    return $this;
}

            
assign() public method

public self assign ( string $itemName, integer|\Stringable|string $userId, integer|null $createdAt null )
$itemName string
$userId integer|\Stringable|string
$createdAt integer|null

                public function assign(string $itemName, int|Stringable|string $userId, ?int $createdAt = null): self
{
    $userId = (string) $userId;
    $item = $this->itemsStorage->get($itemName);
    if ($item === null) {
        throw new InvalidArgumentException("There is no item named \"$itemName\".");
    }
    if (!$this->enableDirectPermissions && $item->getType() === Item::TYPE_PERMISSION) {
        throw new InvalidArgumentException(
            'Assigning permissions directly is disabled. Prefer assigning roles only.',
        );
    }
    if ($this->assignmentsStorage->exists($itemName, $userId)) {
        return $this;
    }
    $assignment = new Assignment($userId, $itemName, $createdAt ?? $this->getCurrentTimestamp());
    $this->assignmentsStorage->add($assignment);
    return $this;
}

            
canAddChild() public method

public boolean canAddChild ( string $parentName, string $childName )
$parentName string
$childName string

                public function canAddChild(string $parentName, string $childName): bool
{
    try {
        $this->assertFutureChild($parentName, $childName);
    } catch (RuntimeException) {
        return false;
    }
    return true;
}

            
getChildRoles() public method

public array getChildRoles ( string $roleName )
$roleName string

                public function getChildRoles(string $roleName): array
{
    if (!$this->itemsStorage->roleExists($roleName)) {
        throw new InvalidArgumentException("Role \"$roleName\" not found.");
    }
    return $this->itemsStorage->getAllChildRoles($roleName);
}

            
getDefaultRoleNames() public method

public array getDefaultRoleNames ( )

                public function getDefaultRoleNames(): array
{
    return $this->defaultRoleNames;
}

            
getDefaultRoles() public method

public array getDefaultRoles ( )

                public function getDefaultRoles(): array
{
    return $this->filterStoredRoles($this->defaultRoleNames);
}

            
getGuestRole() public method

public Yiisoft\Rbac\Role|null getGuestRole ( )

                public function getGuestRole(): ?Role
{
    if ($this->guestRoleName === null) {
        return null;
    }
    $role = $this->getRole($this->guestRoleName);
    if ($role === null) {
        throw new RuntimeException("Guest role with name \"$this->guestRoleName\" does not exist.");
    }
    return $role;
}

            
getGuestRoleName() public method

public string|null getGuestRoleName ( )

                public function getGuestRoleName(): ?string
{
    return $this->guestRoleName;
}

            
getItemsByUserId() public method

public array getItemsByUserId ( integer|\Stringable|string $userId )
$userId integer|\Stringable|string

                public function getItemsByUserId(int|Stringable|string $userId): array
{
    $userId = (string) $userId;
    $assignments = $this->assignmentsStorage->getByUserId($userId);
    $assignmentNames = array_keys($assignments);
    return array_merge(
        $this->getDefaultRoles(),
        $this->itemsStorage->getByNames($assignmentNames),
        $this->itemsStorage->getAllChildren($assignmentNames),
    );
}

            
getPermission() public method

public Yiisoft\Rbac\Permission|null getPermission ( string $name )
$name string

                public function getPermission(string $name): ?Permission
{
    return $this->itemsStorage->getPermission($name);
}

            
getPermissionsByRoleName() public method

public array getPermissionsByRoleName ( string $roleName )
$roleName string

                public function getPermissionsByRoleName(string $roleName): array
{
    return $this->itemsStorage->getAllChildPermissions($roleName);
}

            
getPermissionsByUserId() public method

public array getPermissionsByUserId ( integer|\Stringable|string $userId )
$userId integer|\Stringable|string

                public function getPermissionsByUserId(int|Stringable|string $userId): array
{
    $userId = (string) $userId;
    $assignments = $this->assignmentsStorage->getByUserId($userId);
    if (empty($assignments)) {
        return [];
    }
    $assignmentNames = array_keys($assignments);
    return array_merge(
        $this->itemsStorage->getPermissionsByNames($assignmentNames),
        $this->itemsStorage->getAllChildPermissions($assignmentNames),
    );
}

            
getRole() public method

public Yiisoft\Rbac\Role|null getRole ( string $name )
$name string

                public function getRole(string $name): ?Role
{
    return $this->itemsStorage->getRole($name);
}

            
getRolesByUserId() public method

public array getRolesByUserId ( integer|\Stringable|string $userId )
$userId integer|\Stringable|string

                public function getRolesByUserId(int|Stringable|string $userId): array
{
    $userId = (string) $userId;
    $assignments = $this->assignmentsStorage->getByUserId($userId);
    $assignmentNames = array_keys($assignments);
    return array_merge(
        $this->getDefaultRoles(),
        $this->itemsStorage->getRolesByNames($assignmentNames),
        $this->itemsStorage->getAllChildRoles($assignmentNames),
    );
}

            
getUserIdsByRoleName() public method

public array getUserIdsByRoleName ( string $roleName )
$roleName string

                public function getUserIdsByRoleName(string $roleName): array
{
    $roleNames = [$roleName, ...array_keys($this->itemsStorage->getParents($roleName))];
    return array_map(
        static fn(Assignment $assignment): string => $assignment->getUserId(),
        $this->assignmentsStorage->getByItemNames($roleNames),
    );
}

            
hasChild() public method

public boolean hasChild ( string $parentName, string $childName )
$parentName string
$childName string

                public function hasChild(string $parentName, string $childName): bool
{
    return $this->itemsStorage->hasDirectChild($parentName, $childName);
}

            
hasChildren() public method

public boolean hasChildren ( string $parentName )
$parentName string

                public function hasChildren(string $parentName): bool
{
    return $this->itemsStorage->hasChildren($parentName);
}

            
removeChild() public method

public self removeChild ( string $parentName, string $childName )
$parentName string
$childName string

                public function removeChild(string $parentName, string $childName): self
{
    $this->itemsStorage->removeChild($parentName, $childName);
    return $this;
}

            
removeChildren() public method

public self removeChildren ( string $parentName )
$parentName string

                public function removeChildren(string $parentName): self
{
    $this->itemsStorage->removeChildren($parentName);
    return $this;
}

            
removePermission() public method

public self removePermission ( string $name )
$name string

                public function removePermission(string $name): self
{
    $this->removeItem($name);
    return $this;
}

            
removeRole() public method

public self removeRole ( string $name )
$name string

                public function removeRole(string $name): self
{
    $this->removeItem($name);
    return $this;
}

            
revoke() public method

public self revoke ( string $itemName, integer|\Stringable|string $userId )
$itemName string
$userId integer|\Stringable|string

                public function revoke(string $itemName, int|Stringable|string $userId): self
{
    $this->assignmentsStorage->remove($itemName, (string) $userId);
    return $this;
}

            
revokeAll() public method

public self revokeAll ( integer|\Stringable|string $userId )
$userId integer|\Stringable|string

                public function revokeAll(int|Stringable|string $userId): self
{
    $this->assignmentsStorage->removeByUserId((string) $userId);
    return $this;
}

            
setDefaultRoleNames() public method

public self setDefaultRoleNames ( array|Closure $roleNames )
$roleNames array|Closure

                public function setDefaultRoleNames(array|Closure $roleNames): self
{
    $this->defaultRoleNames = $this->getDefaultRoleNamesForUpdate($roleNames);
    return $this;
}

            
setGuestRoleName() public method

public self setGuestRoleName ( string|null $name )
$name string|null

                public function setGuestRoleName(?string $name): self
{
    $this->guestRoleName = $name;
    return $this;
}

            
updatePermission() public method

public self updatePermission ( string $name, Yiisoft\Rbac\Permission $permission )
$name string
$permission Yiisoft\Rbac\Permission

                public function updatePermission(string $name, Permission $permission): self
{
    $this->assertItemNameForUpdate($permission, $name);
    $this->itemsStorage->update($name, $permission);
    $this->assignmentsStorage->renameItem($name, $permission->getName());
    return $this;
}

            
updateRole() public method

public self updateRole ( string $name, Yiisoft\Rbac\Role $role )
$name string
$role Yiisoft\Rbac\Role

                public function updateRole(string $name, Role $role): self
{
    $this->assertItemNameForUpdate($role, $name);
    $this->itemsStorage->update($name, $role);
    $this->assignmentsStorage->renameItem($name, $role->getName());
    return $this;
}

            
userHasPermission() public method

public boolean userHasPermission ( integer|string|\Stringable|null $userId, string $permissionName, array $parameters = [] )
$userId integer|string|\Stringable|null
$permissionName string
$parameters array

                public function userHasPermission(
    int|string|Stringable|null $userId,
    string $permissionName,
    array $parameters = [],
): bool {
    $item = $this->itemsStorage->get($permissionName);
    if ($item === null) {
        return false;
    }
    if (!$this->includeRolesInAccessChecks && $item->getType() === Item::TYPE_ROLE) {
        return false;
    }
    if ($userId !== null) {
        $guestRole = null;
    } else {
        $guestRole = $this->getGuestRole();
        if ($guestRole === null) {
            return false;
        }
    }
    $hierarchy = $this->itemsStorage->getHierarchy($item->getName());
    $itemNames = array_map(static fn(array $treeItem): string => $treeItem['item']->getName(), $hierarchy);
    $userItemNames = $guestRole !== null
        ? [$guestRole->getName()]
        : $this->filterUserItemNames((string) $userId, $itemNames);
    $userItemNamesMap = [];
    foreach ($userItemNames as $userItemName) {
        $userItemNamesMap[$userItemName] = null;
    }
    foreach ($hierarchy as $data) {
        if (
            !array_key_exists($data['item']->getName(), $userItemNamesMap)
            || !$this->executeRule($userId === null ? $userId : (string) $userId, $data['item'], $parameters)
        ) {
            continue;
        }
        $hasPermission = true;
        foreach ($data['children'] as $childItem) {
            if (!$this->executeRule($userId === null ? $userId : (string) $userId, $childItem, $parameters)) {
                $hasPermission = false;
                /**
                 * @infection-ignore-all Break_
                 * Replacing with `continue` works as well, but there is no point in further checks, because at
                 * least one failed rule execution means access is not granted via current iterated hierarchy
                 * branch.
                 */
                break;
            }
        }
        if ($hasPermission) {
            return true;
        }
    }
    return false;
}