Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tests for access tree #241

Merged
merged 5 commits into from
Feb 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/bc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ jobs:
os: >-
['ubuntu-latest']
php: >-
['8.1']
['8.3']
4 changes: 4 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,15 @@ jobs:
php:
- 8.1
- 8.2
- 8.3

exclude:
- os: windows-latest
php: 8.2

- os: windows-latest
php: 8.3

steps:
- name: Checkout.
uses: actions/checkout@v3
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/composer-require-checker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,5 @@ jobs:
os: >-
['ubuntu-latest']
php: >-
['8.1', '8.2']
['8.3']
extensions: uopz
2 changes: 1 addition & 1 deletion .github/workflows/mutation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
os: >-
['ubuntu-latest']
php: >-
['8.1']
['8.3']
extensions: uopz
min-covered-msi: 100
secrets:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/rector.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ jobs:
os: >-
['ubuntu-latest']
php: >-
['8.1']
['8.3']
extensions: uopz
2 changes: 1 addition & 1 deletion .github/workflows/static.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,5 @@ jobs:
os: >-
['ubuntu-latest']
php: >-
['8.1', '8.2']
['8.1', '8.2', '8.3']
extensions: uopz
2 changes: 1 addition & 1 deletion src/ItemsStorageInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* A storage for RBAC roles and permissions used in {@see Manager}.
*
* @psalm-type ItemsIndexedByName = array<string, Permission|Role>
* @psalm-type AccessTree = non-empty-array<string, array{
* @psalm-type AccessTree = array<string, array{
* item: Permission|Role,
* children: array<string, Permission|Role>
* }>
Expand Down
2 changes: 0 additions & 2 deletions src/ManagerInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,6 @@ public function updateRole(string $name, Role $role): self;
public function removeRole(string $name): self;

/**
* @param Permission $permission
*
* @throws ItemAlreadyExistsException
*/
public function addPermission(Permission $permission): self;
Expand Down
6 changes: 2 additions & 4 deletions src/SimpleItemsStorage.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

namespace Yiisoft\Rbac;

use RuntimeException;

/**
* @psalm-type RawItem = array{
* type: Item::TYPE_*,
Expand Down Expand Up @@ -110,8 +108,8 @@ public function getParents(string $name): array

public function getAccessTree(string $name): array
{
if (!$this->exists($name)) {
throw new RuntimeException('Base item not found.');
if (!array_key_exists($name, $this->items)) {
return [];
}

$result = [$name => ['item' => $this->items[$name], 'children' => []]];
Expand Down
96 changes: 94 additions & 2 deletions tests/Common/ItemsStorageTestTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,16 @@ protected function setUp(): void
ClockMock::freeze(new DateTime('2023-05-10 08:24:39'));
}

if ($this->name() === 'testGetAccessTree') {
ClockMock::freeze(new DateTime('2023-12-24 17:51:18'));
}

$this->populateItemsStorage();
}

protected function tearDown(): void
{
if ($this->name() === 'testAddWithCurrentTimestamps') {
if (in_array($this->name(), ['testAddWithCurrentTimestamps', 'testGetAccessTree'], strict: true)) {
ClockMock::reset();
}

Expand Down Expand Up @@ -390,6 +394,94 @@ public function testGetParents(string $childName, array $expectedParents): void
}
}

public static function dataGetAccessTree(): array
{
$createdAt = (new DateTime('2023-12-24 17:51:18'))->getTimestamp();
$postsViewPermission = (new Permission('posts.view'))->withCreatedAt($createdAt)->withUpdatedAt($createdAt);
$postsCreatePermission = (new Permission('posts.create'))->withCreatedAt($createdAt)->withUpdatedAt($createdAt);
$postsDeletePermission = (new Permission('posts.delete'))->withCreatedAt($createdAt)->withUpdatedAt($createdAt);
$postsViewerRole = (new Role('posts.viewer'))->withCreatedAt($createdAt)->withUpdatedAt($createdAt);
$postsRedactorRole = (new Role('posts.redactor'))->withCreatedAt($createdAt)->withUpdatedAt($createdAt);
$postsAdminRole = (new Role('posts.admin'))->withCreatedAt($createdAt)->withUpdatedAt($createdAt);

return [
[
'posts.view',
[
'posts.view' => ['item' => $postsViewPermission, 'children' => []],
'posts.viewer' => ['item' => $postsViewerRole, 'children' => ['posts.view' => $postsViewPermission]],
'posts.redactor' => [
'item' => $postsRedactorRole,
'children' => ['posts.view' => $postsViewPermission, 'posts.viewer' => $postsViewerRole],
],
'posts.admin' => [
'item' => $postsAdminRole,
'children' => [
'posts.view' => $postsViewPermission,
'posts.viewer' => $postsViewerRole,
'posts.redactor' => $postsRedactorRole,
],
],
],
],
[
'posts.create',
[
'posts.create' => ['item' => $postsCreatePermission, 'children' => []],
'posts.redactor' => [
'item' => $postsRedactorRole,
'children' => ['posts.create' => $postsCreatePermission],
],
'posts.admin' => [
'item' => $postsAdminRole,
'children' => [
'posts.create' => $postsCreatePermission,
'posts.redactor' => $postsRedactorRole,
],
],
],
],
[
'posts.delete',
[
'posts.delete' => ['item' => $postsDeletePermission, 'children' => []],
'posts.admin' => [
'item' => $postsAdminRole,
'children' => [
'posts.delete' => $postsDeletePermission,
],
],
],
],
[
'posts.viewer',
[
'posts.viewer' => ['item' => $postsViewerRole, 'children' => []],
'posts.redactor' => [
'item' => $postsRedactorRole,
'children' => ['posts.viewer' => $postsViewerRole],
],
'posts.admin' => [
'item' => $postsAdminRole,
'children' => [
'posts.viewer' => $postsViewerRole,
'posts.redactor' => $postsRedactorRole,
],
],
],
],
['non-existing', []],
];
}

/**
* @dataProvider dataGetAccessTree
*/
public function testGetAccessTree(string $name, array $expectedAccessTree): void
{
$this->assertEquals($expectedAccessTree, $this->getItemsStorage()->getAccessTree($name));
}

public function testRemoveChildren(): void
{
$testStorage = $this->getItemsStorageForModificationAssertions();
Expand Down Expand Up @@ -610,7 +702,6 @@ protected function getItemsStorageForModificationAssertions(): ItemsStorageInter

protected function getFixtures(): array
{
$time = time();
$itemsMap = [
'Parent 1' => Item::TYPE_ROLE,
'Parent 2' => Item::TYPE_ROLE,
Expand Down Expand Up @@ -638,6 +729,7 @@ protected function getFixtures(): array
'posts.update' => Item::TYPE_PERMISSION,
'posts.delete' => Item::TYPE_PERMISSION,
];
$time = time();

$items = [];
foreach ($itemsMap as $name => $type) {
Expand Down
Loading