From b0066d575d90c9e94817317af722b0219cdd3205 Mon Sep 17 00:00:00 2001 From: "Eric Richer eric.richer@vistoconsulting.com" Date: Tue, 9 Jul 2024 14:52:34 -0400 Subject: [PATCH] Added PermissionInterface (#55) Signed-off-by: Eric Richer eric.richer@vistoconsulting.com --- data/FlatRole.php.dist | 60 +++++--- data/HierarchicalRole.php.dist | 69 +++++---- data/Permission.php.dist | 25 ++- data/Role.php.dist | 135 +++++++++++++++++ src/Assertion/AssertionInterface.php | 3 +- src/Assertion/AssertionSet.php | 3 +- src/Permission/PermissionInterface.php | 17 +++ src/Rbac.php | 9 +- src/RbacInterface.php | 7 +- src/Role/Role.php | 14 +- src/Role/RoleInterface.php | 8 +- src/Service/AuthorizationService.php | 12 +- src/Service/AuthorizationServiceInterface.php | 6 +- test/Asset/FlatRole.php | 82 ++++++++-- test/Asset/HierarchicalRole.php | 98 +++++++++--- test/Asset/Permission.php | 77 ++++++++++ test/Asset/Role.php | 143 ++++++++++++++++++ test/Asset/SimpleAssertion.php | 3 +- 18 files changed, 656 insertions(+), 115 deletions(-) create mode 100644 data/Role.php.dist create mode 100644 src/Permission/PermissionInterface.php create mode 100644 test/Asset/Permission.php create mode 100644 test/Asset/Role.php diff --git a/data/FlatRole.php.dist b/data/FlatRole.php.dist index 109d6bba..2f8fa131 100644 --- a/data/FlatRole.php.dist +++ b/data/FlatRole.php.dist @@ -16,15 +16,20 @@ * and is licensed under the MIT license. */ +declare(strict_types=1); + use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; -use Rbac\Role\RoleInterface; use LmcRbac\Permission\PermissionInterface; +use LmcRbac\Role\RoleInterface; /** * @ORM\Entity * @ORM\Table(name="roles") */ +#[ORM\Entity] +#[ORM\Table(name: 'roles')] class FlatRole implements RoleInterface { /** @@ -34,21 +39,25 @@ class FlatRole implements RoleInterface * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") */ - protected $id; + #[ORM\Id] + #[ORM\Column(name: 'id', type: 'integer')] + #[ORM\GeneratedValue(strategy: 'AUTO')] + protected ?int $id; /** * @var string|null * - * @ORM\Column(type="string", length=48, unique=true) + * @ORM\Column(type="string", length=255, unique=true) */ - protected $name; + #[ORM\Column(name: 'name', type: 'string', length: 255, unique: true)] + protected ?string $name; /** - * @var PermissionInterface[]|\Doctrine\Common\Collections\Collection - * + * @var Permission[]|Collection * @ORM\ManyToMany(targetEntity="Permission", indexBy="name", fetch="EAGER", cascade={"persist"}) */ - protected $permissions; + #[ORM\ManyToMany(targetEntity: "Persmission", cascade: ["persist"], fetch: "EAGER", indexBy: "name")] + protected array|Collection|ArrayCollection $permissions; /** * Init the Doctrine collection @@ -61,9 +70,9 @@ class FlatRole implements RoleInterface /** * Get the role identifier * - * @return int + * @return int|null */ - public function getId() + public function getId(): ?int { return $this->id; } @@ -71,12 +80,12 @@ class FlatRole implements RoleInterface /** * Set the role name * - * @param string $name + * @param string $name * @return void */ - public function setName($name) + public function setName(string $name): void { - $this->name = (string) $name; + $this->name = $name; } /** @@ -84,15 +93,15 @@ class FlatRole implements RoleInterface * * @return string */ - public function getName() + public function getName(): string { return $this->name; } /** - * {@inheritDoc} + * @inheritDoc */ - public function addPermission($permission) + public function addPermission(PermissionInterface|string $permission): void { if (is_string($permission)) { $permission = new Permission($permission); @@ -102,13 +111,30 @@ class FlatRole implements RoleInterface } /** - * {@inheritDoc} + * @inheritDoc */ - public function hasPermission($permission) + public function hasPermission(PermissionInterface|string $permission): bool { // This can be a performance problem if your role has a lot of permissions. Please refer // to the cookbook to an elegant way to solve this issue return isset($this->permissions[(string) $permission]); } + + + + public function getChildren(): iterable + { + return []; + } + + public function hasChildren(): bool + { + return false; + } + + public function addChild(RoleInterface $role): void + { + // Do nothing + } } diff --git a/data/HierarchicalRole.php.dist b/data/HierarchicalRole.php.dist index 9066025b..6b21bdd1 100644 --- a/data/HierarchicalRole.php.dist +++ b/data/HierarchicalRole.php.dist @@ -16,16 +16,20 @@ * and is licensed under the MIT license. */ +declare(strict_types=1); + use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; -use Rbac\Role\HierarchicalRoleInterface; -use LmcRbac\Permission\PermissionInterface; +use LmcRbac\Role\RoleInterface; /** * @ORM\Entity * @ORM\Table(name="roles") */ -class HierarchicalRole implements HierarchicalRoleInterface +#[ORM\Entity] +#[ORM\Table(name: 'roles')] +class HierarchicalRole implements RoleInterface { /** * @var int|null @@ -34,44 +38,50 @@ class HierarchicalRole implements HierarchicalRoleInterface * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") */ - protected $id; + #[ORM\Id] + #[ORM\Column(name: 'id', type: 'integer')] + #[ORM\GeneratedValue(strategy: 'AUTO')] + protected ?int $id = null; /** * @var string|null * * @ORM\Column(type="string", length=48, unique=true) */ - protected $name; + #[ORM\Column(name: 'name', type: 'string', length: 255, unique: true)] + protected ?string $name; /** - * @var HierarchicalRoleInterface[]|\Doctrine\Common\Collections\Collection + * @var RoleInterface[]|Collection * * @ORM\ManyToMany(targetEntity="HierarchicalRole") */ - protected $children = []; + #[ORM\ManyToMany(targetEntity: RoleInterface::class)] + protected array|Collection|ArrayCollection $children = []; /** - * @var PermissionInterface[]|\Doctrine\Common\Collections\Collection + * @var Permission[]|Collection * * @ORM\ManyToMany(targetEntity="Permission", indexBy="name", fetch="EAGER") */ - protected $permissions; + #[ORM\ManyToMany(targetEntity: Permission::class, fetch: 'EAGER', indexBy: 'name')] + protected array|Collection|ArrayCollection $permissions; /** * Init the Doctrine collection */ public function __construct() { - $this->children = new ArrayCollection(); + $this->children = new ArrayCollection(); $this->permissions = new ArrayCollection(); } /** * Get the role identifier * - * @return int + * @return int|null */ - public function getId() + public function getId(): ?int { return $this->id; } @@ -79,12 +89,12 @@ class HierarchicalRole implements HierarchicalRoleInterface /** * Set the role name * - * @param string $name + * @param string $name * @return void */ - public function setName($name) + public function setName(string $name): void { - $this->name = (string) $name; + $this->name = $name; } /** @@ -92,23 +102,25 @@ class HierarchicalRole implements HierarchicalRoleInterface * * @return string */ - public function getName() + public function getName(): string { return $this->name; } /** - * {@inheritDoc} + * @param RoleInterface $child + * @return void */ - public function addChild(HierarchicalRoleInterface $child) + public function addChild(RoleInterface $role): void { - $this->children[] = $child; + $this->children[] = $role; } /** - * {@inheritDoc} + * @param string|Permission $permission + * @return void */ - public function addPermission($permission) + public function addPermission(string|Permission|\LmcRbac\Permission\PermissionInterface $permission): void { if (is_string($permission)) { $permission = new Permission($permission); @@ -118,9 +130,10 @@ class HierarchicalRole implements HierarchicalRoleInterface } /** - * {@inheritDoc} + * @param $permission + * @return bool */ - public function hasPermission($permission) + public function hasPermission(string|\LmcRbac\Permission\PermissionInterface $permission): bool { // This can be a performance problem if your role has a lot of permissions. Please refer // to the cookbook to an elegant way to solve this issue @@ -129,18 +142,18 @@ class HierarchicalRole implements HierarchicalRoleInterface } /** - * {@inheritDoc} + * @inheritDoc */ - public function getChildren() + public function getChildren(): iterable { return $this->children; } /** - * {@inheritDoc} + * @inheritDoc */ - public function hasChildren() + public function hasChildren(): bool { - return !$this->children->isEmpty(); + return ! $this->children->isEmpty(); } } diff --git a/data/Permission.php.dist b/data/Permission.php.dist index 945a65f2..f6d84fef 100644 --- a/data/Permission.php.dist +++ b/data/Permission.php.dist @@ -1,4 +1,6 @@ name = (string) $name; + $this->name = $name; } /** * Get the permission identifier * - * @return int + * @return int|null */ - public function getId() + public function getId(): ?int { return $this->id; } /** - * {@inheritDoc} + * @inheritDoc */ - public function __toString() + public function __toString(): string { return $this->name; } diff --git a/data/Role.php.dist b/data/Role.php.dist new file mode 100644 index 00000000..7df58dbc --- /dev/null +++ b/data/Role.php.dist @@ -0,0 +1,135 @@ +name = $name; + $this->children = new ArrayCollection(); + $this->permissions = new ArrayCollection(); + } + + /** + * Get the role identifier + * + * @return int|null + */ + public function getId(): ?int + { + return $this->id; + } + + /** + * Add a permission + * + * @param string|PermissionInterface $name + * @return void + */ + public function addPermission(string|PermissionInterface $permission): void + { + $permission = new \Permission($permission); + + $this->permissions[(string) $permission] = $permission; + } + + public function getName(): string + { + return $this->name; + } + + public function hasPermission(string|PermissionInterface $permission): bool + { + return isset($this->permissions[(string) $permission]); + } + + public function addChild(RoleInterface $child): void + { + $this->children[] = $child; + } + + public function getChildren(): iterable + { + return $this->children; + } + + public function hasChildren(): bool + { + return ! $this->children->isEmpty(); + } +} diff --git a/src/Assertion/AssertionInterface.php b/src/Assertion/AssertionInterface.php index e6fa97b3..33dbbe81 100644 --- a/src/Assertion/AssertionInterface.php +++ b/src/Assertion/AssertionInterface.php @@ -22,6 +22,7 @@ namespace LmcRbac\Assertion; use LmcRbac\Identity\IdentityInterface; +use LmcRbac\Permission\PermissionInterface; /** * Interface that you can implement for dynamic assertions @@ -34,7 +35,7 @@ interface AssertionInterface { public function assert( - string $permission, + PermissionInterface|string $permission, IdentityInterface $identity = null, mixed $context = null ): bool; diff --git a/src/Assertion/AssertionSet.php b/src/Assertion/AssertionSet.php index d3ee87de..82eccb17 100644 --- a/src/Assertion/AssertionSet.php +++ b/src/Assertion/AssertionSet.php @@ -23,6 +23,7 @@ use LmcRbac\Exception; use LmcRbac\Identity\IdentityInterface; +use LmcRbac\Permission\PermissionInterface; class AssertionSet implements AssertionInterface { @@ -61,7 +62,7 @@ public function __construct( $this->assertions = $assertions; } - public function assert(string $permission, IdentityInterface $identity = null, $context = null): bool + public function assert(PermissionInterface|string $permission, IdentityInterface $identity = null, $context = null): bool { if (empty($this->assertions)) { return false; diff --git a/src/Permission/PermissionInterface.php b/src/Permission/PermissionInterface.php new file mode 100644 index 00000000..59b6e4bf --- /dev/null +++ b/src/Permission/PermissionInterface.php @@ -0,0 +1,17 @@ + + */ + +interface PermissionInterface +{ + /** + * Get the permission name + * @return string + */ + public function __toString(): string; +} diff --git a/src/Rbac.php b/src/Rbac.php index 02c66435..2534c02a 100644 --- a/src/Rbac.php +++ b/src/Rbac.php @@ -22,6 +22,7 @@ namespace LmcRbac; use Generator; +use LmcRbac\Permission\PermissionInterface; use LmcRbac\Role\RoleInterface; use Traversable; @@ -33,11 +34,11 @@ class Rbac implements RbacInterface /** * Determines if access is granted by checking the roles for permission. * - * @param RoleInterface|RoleInterface[]|Traversable $roles - * @param string $permission + * @param RoleInterface|iterable $roles + * @param string|PermissionInterface $permission * @return bool */ - public function isGranted($roles, string $permission): bool + public function isGranted(RoleInterface|iterable $roles, string|PermissionInterface $permission): bool { if ($roles instanceof Traversable) { $roles = iterator_to_array($roles); @@ -48,7 +49,7 @@ public function isGranted($roles, string $permission): bool } foreach ($this->flattenRoles($roles) as $role) { - /* @var \LmcRbac\Role\RoleInterface $role */ + /* @var RoleInterface $role */ if ($role->hasPermission($permission)) { return true; } diff --git a/src/RbacInterface.php b/src/RbacInterface.php index f236f54b..6957c9a5 100644 --- a/src/RbacInterface.php +++ b/src/RbacInterface.php @@ -2,6 +2,7 @@ namespace LmcRbac; +use LmcRbac\Permission\PermissionInterface; use LmcRbac\Role\RoleInterface; use Traversable; @@ -10,10 +11,10 @@ interface RbacInterface /** * Determines if access is granted by checking the roles for permission. * - * @param Traversable|RoleInterface|RoleInterface[] $roles - * @param string $permission + * @param iterable|RoleInterface $roles + * @param PermissionInterface|string $permission * @return bool */ - public function isGranted(RoleInterface|Traversable|array $roles, string $permission): bool; + public function isGranted(RoleInterface|iterable $roles, PermissionInterface|string $permission): bool; } diff --git a/src/Role/Role.php b/src/Role/Role.php index 52a3feea..58bafc4c 100644 --- a/src/Role/Role.php +++ b/src/Role/Role.php @@ -21,6 +21,8 @@ namespace LmcRbac\Role; +use LmcRbac\Permission\PermissionInterface; + /** * Simple implementation for a role without hierarchy * and using strings as permissions @@ -57,14 +59,14 @@ public function getPermissions(): array return $this->permissions; } - public function addPermission(string $permission): void + public function addPermission(PermissionInterface|string $permission): void { - $this->permissions[$permission] = $permission; + $this->permissions[$permission] = (string) $permission; } - public function hasPermission(string $permission): bool + public function hasPermission(PermissionInterface|string $permission): bool { - if (isset($this->permissions[$permission])) { + if (isset($this->permissions[(string) $permission])) { return true; } @@ -87,8 +89,8 @@ public function getChildren(): iterable return $this->children; } - public function addChild(Role $child): void + public function addChild(RoleInterface $role): void { - $this->children[$child->getName()] = $child; + $this->children[$role->getName()] = $role; } } diff --git a/src/Role/RoleInterface.php b/src/Role/RoleInterface.php index 646a73c2..258c1c46 100644 --- a/src/Role/RoleInterface.php +++ b/src/Role/RoleInterface.php @@ -21,6 +21,8 @@ namespace LmcRbac\Role; +use LmcRbac\Permission\PermissionInterface; + /** * Interface for a role * @@ -30,7 +32,11 @@ interface RoleInterface { public function getName(): string; - public function hasPermission(string $permission): bool; + public function hasPermission(PermissionInterface|string $permission): bool; + + public function addChild(RoleInterface $role): void; + + public function addPermission(PermissionInterface $permission): void; public function hasChildren(): bool; diff --git a/src/Service/AuthorizationService.php b/src/Service/AuthorizationService.php index 097fe813..f9462936 100644 --- a/src/Service/AuthorizationService.php +++ b/src/Service/AuthorizationService.php @@ -23,7 +23,7 @@ use LmcRbac\Assertion\AssertionPluginManagerInterface; use LmcRbac\Assertion\AssertionSet; -use LmcRbac\Identity\IdentityInterface; +use LmcRbac\Permission\PermissionInterface; use LmcRbac\RbacInterface; /** @@ -58,7 +58,7 @@ public function __construct( $this->assertions = $assertions; } - public function isGranted(string $permission, mixed $context = null): bool + public function isGranted(string|PermissionInterface $permission, mixed $context = null): bool { $roles = $this->roleService->getIdentityRoles(null, $context); @@ -70,14 +70,14 @@ public function isGranted(string $permission, mixed $context = null): bool return false; } - if (empty($this->assertions[$permission])) { + if (empty($this->assertions[(string) $permission])) { return true; } - if (\is_array($this->assertions[$permission])) { - $permissionAssertions = $this->assertions[$permission]; + if (\is_array($this->assertions[(string) $permission])) { + $permissionAssertions = $this->assertions[(string) $permission]; } else { - $permissionAssertions = [$this->assertions[$permission]]; + $permissionAssertions = [$this->assertions[(string) $permission]]; } $assertionSet = new AssertionSet($this->assertionPluginManager, $permissionAssertions); diff --git a/src/Service/AuthorizationServiceInterface.php b/src/Service/AuthorizationServiceInterface.php index 8ae3af50..383295fa 100644 --- a/src/Service/AuthorizationServiceInterface.php +++ b/src/Service/AuthorizationServiceInterface.php @@ -21,7 +21,7 @@ namespace LmcRbac\Service; -use LmcRbac\Identity\IdentityInterface; +use LmcRbac\Permission\PermissionInterface; /** * Minimal interface for an authorization service @@ -34,9 +34,9 @@ interface AuthorizationServiceInterface /** * Check if the permission is granted to the current identity * - * @param string $permission + * @param PermissionInterface|string $permission * @param mixed|null $context * @return bool */ - public function isGranted(string $permission, mixed $context = null): bool; + public function isGranted(PermissionInterface|string $permission, mixed $context = null): bool; } diff --git a/test/Asset/FlatRole.php b/test/Asset/FlatRole.php index 73e5a1d4..b8d75654 100644 --- a/test/Asset/FlatRole.php +++ b/test/Asset/FlatRole.php @@ -23,12 +23,21 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; +use Doctrine\ORM\Mapping as ORM; +use LmcRbac\Permission\PermissionInterface; use LmcRbac\Role\RoleInterface; +/** + * There is no specific implementation of a flot role. + * A flot role is a simple utilization of the Laminas\Permission\Rbac\Role without children + */ + /** * @ORM\Entity - * @ORM\Table(name="roles") + * @ORM\Table(name="flat_roles") */ +#[ORM\Entity] +#[ORM\Table(name: 'flat_roles')] class FlatRole implements RoleInterface { /** @@ -38,56 +47,101 @@ class FlatRole implements RoleInterface * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") */ - protected $id; + #[ORM\Id] + #[ORM\Column(name: 'id', type: 'integer')] + #[ORM\GeneratedValue(strategy: 'AUTO')] + protected ?int $id; /** * @var string|null * - * @ORM\Column(type="string", length=32, unique=true) + * @ORM\Column(type="string", length=255, unique=true) */ - protected $name; + #[ORM\Column(name: 'name', type: 'string', length: 255, unique: true)] + protected ?string $name; /** - * @var Collection[] + * @var Permission[]|Collection + * @ORM\ManyToMany(targetEntity="Permission", indexBy="name", fetch="EAGER", cascade={"persist"}) */ - protected $permissions; + #[ORM\ManyToMany(targetEntity: 'Persmission', cascade: ['persist'], fetch: 'EAGER', indexBy: 'name')] + protected array|Collection|ArrayCollection $permissions; /** * Init the Doctrine collection */ - public function __construct(string $name) + public function __construct($name) { - $this->name = $name; + $this->name = (string) $name; $this->permissions = new ArrayCollection(); } /** * Get the role identifier * - * @return int + * @return int|null */ - public function getId() + public function getId(): ?int { return $this->id; } + /** + * Add a permission + * + * @param string $name + * @return void + */ + public function setName(string $name): void + { + $this->name = $name; + } + + /** + * Get the role name + * + * @return string + */ public function getName(): string { return $this->name; } - public function hasPermission(string $permission): bool + /** + * @inheritDoc + */ + public function addPermission(PermissionInterface|string $permission): void { - return isset($this->permissions[$permission]); + if (is_string($permission)) { + $permission = new Permission($permission); + } + + $this->permissions[(string) $permission] = $permission; } - public function hasChildren(): bool + /** + * @inheritDoc + */ + public function hasPermission(PermissionInterface|string $permission): bool + { + // This can be a performance problem if your role has a lot of permissions. Please refer + // to the cookbook to an elegant way to solve this issue + + return isset($this->permissions[(string) $permission]); + } + + public function addChild(RoleInterface $role): void { - return false; + // Do nothing } public function getChildren(): iterable { return []; } + + public function hasChildren(): bool + { + // Do nothing + } } diff --git a/test/Asset/HierarchicalRole.php b/test/Asset/HierarchicalRole.php index 6e2a6eb9..0fab5457 100644 --- a/test/Asset/HierarchicalRole.php +++ b/test/Asset/HierarchicalRole.php @@ -23,13 +23,16 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; -use LmcRbac\Role\HierarchicalRoleInterface; +use Doctrine\ORM\Mapping as ORM; +use LmcRbac\Permission\PermissionInterface; use LmcRbac\Role\RoleInterface; /** * @ORM\Entity * @ORM\Table(name="hierarchical_roles") */ +#[ORM\Entity] +#[ORM\Table(name: 'hierarchical_roles')] class HierarchicalRole implements RoleInterface { /** @@ -39,71 +42,122 @@ class HierarchicalRole implements RoleInterface * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") */ - protected $id; + #[ORM\Id] + #[ORM\Column(name: 'id', type: 'integer')] + #[ORM\GeneratedValue(strategy: 'AUTO')] + protected ?int $id = null; /** * @var string|null * - * @ORM\Column(type="string", length=32, unique=true) + * @ORM\Column(type="string", length=48, unique=true) */ - protected $name; + #[ORM\Column(name: 'name', type: 'string', length: 255, unique: true)] + protected ?string $name; /** * @var RoleInterface[]|Collection * * @ORM\ManyToMany(targetEntity="HierarchicalRole") */ - protected $children; + #[ORM\ManyToMany(targetEntity: RoleInterface::class)] + protected array|Collection|ArrayCollection $children = []; /** - * @var string[] + * @var Permission[]|Collection * * @ORM\ManyToMany(targetEntity="Permission", indexBy="name", fetch="EAGER") */ - protected $permissions; + #[ORM\ManyToMany(targetEntity: Permission::class, fetch: 'EAGER', indexBy: 'name')] + protected array|Collection|ArrayCollection $permissions; /** * Init the Doctrine collection - * - * @param string $name */ - public function __construct(string $name) + public function __construct() { - $this->name = $name; + $this->children = new ArrayCollection(); $this->permissions = new ArrayCollection(); } /** * Get the role identifier * - * @return int + * @return int|null */ - public function getId() + public function getId(): ?int { return $this->id; } - public function hasChildren(): bool + /** + * Set the role name + * + * @param string $name + * @return void + */ + public function setName(string $name): void { - return ! empty($this->children); + $this->name = $name; } - public function getChildren(): iterable + /** + * Get the role name + * + * @return string + */ + public function getName(): string { - return $this->children; + return $this->name; } - public function getName(): string + /** + * @param RoleInterface $role + * @return void + */ + public function addChild(RoleInterface $role): void { - return $this->name; + $this->children[] = $role; } - public function hasPermission(string $permission): bool + /** + * @param string|PermissionInterface $permission + * @return void + */ + public function addPermission(string|PermissionInterface $permission): void + { + if (is_string($permission)) { + $permission = new Permission($permission); + } + + $this->permissions[(string) $permission] = $permission; + } + + /** + * @param string|PermissionInterface $permission + * @return bool + */ + public function hasPermission(string|PermissionInterface $permission): bool { + // This can be a performance problem if your role has a lot of permissions. Please refer + // to the cookbook to an elegant way to solve this issue + + return isset($this->permissions[(string) $permission]); } - public function addChild(RoleInterface $child): void + /** + * @inheritDoc + */ + public function getChildren(): iterable + { + return $this->children; + } + + /** + * @inheritDoc + */ + public function hasChildren(): bool { - $this->children[$child->getName()] = $child; + return ! $this->children->isEmpty(); } } diff --git a/test/Asset/Permission.php b/test/Asset/Permission.php new file mode 100644 index 00000000..ca2c5eb9 --- /dev/null +++ b/test/Asset/Permission.php @@ -0,0 +1,77 @@ +name = $name; + } + + /** + * Get the permission identifier + * + * @return int|null + */ + public function getId(): ?int + { + return $this->id; + } + + public function __toString(): string + { + return $this->name; + } +} diff --git a/test/Asset/Role.php b/test/Asset/Role.php new file mode 100644 index 00000000..600e0445 --- /dev/null +++ b/test/Asset/Role.php @@ -0,0 +1,143 @@ +name = $name; + $this->children = new ArrayCollection(); + $this->permissions = new ArrayCollection(); + } + + /** + * Get the role identifier + * + * @return int|null + */ + public function getId(): ?int + { + return $this->id; + } + + /** + * Add a permission + * + * @param string $name + * @return void + */ + public function addPermission(string $name): void + { + $permission = new Permission($name); + + $this->permissions[$name] = $permission; + } + + public function getName(): string + { + return $this->name; + } + + public function hasPermission(PermissionInterface|string $permission): bool + { + return isset($this->permissions[(string) $permission]); + } + + public function addChild(RoleInterface $role): void + { + $this->children[] = $role; + } + + public function getChildren(): iterable + { + return $this->children; + } + + public function hasChildren(): bool + { + return false; + } +} diff --git a/test/Asset/SimpleAssertion.php b/test/Asset/SimpleAssertion.php index 93022ce9..063946c6 100644 --- a/test/Asset/SimpleAssertion.php +++ b/test/Asset/SimpleAssertion.php @@ -23,6 +23,7 @@ use LmcRbac\Assertion\AssertionInterface; use LmcRbac\Identity\IdentityInterface; +use LmcRbac\Permission\PermissionInterface; class SimpleAssertion implements AssertionInterface { @@ -41,7 +42,7 @@ public function __construct(bool $willAssert = true) $this->willAssert = $willAssert; } - public function assert(string $permission, IdentityInterface $identity = null, $context = null): bool + public function assert(string|PermissionInterface $permission, IdentityInterface $identity = null, $context = null): bool { $this->called++;