Skip to content

Commit

Permalink
Check item exists on add role or permission (#129)
Browse files Browse the repository at this point in the history
  • Loading branch information
vjik committed Apr 6, 2022
1 parent 5d95f90 commit cf96986
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 1 deletion.
24 changes: 24 additions & 0 deletions src/Exception/ItemAlreadyExistsException.php
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Rbac\Exception;

use RuntimeException;
use Throwable;
use Yiisoft\Rbac\Item;

final class ItemAlreadyExistsException extends RuntimeException
{
public function __construct(Item $item, int $code = 0, ?Throwable $previous = null)
{
parent::__construct(
sprintf(
'Role or permission with name "%s" already exists.',
$item->getName()
),
$code,
$previous
);
}
}
9 changes: 9 additions & 0 deletions src/ItemsStorageInterface.php
Expand Up @@ -31,6 +31,15 @@ public function getAll(): array;
*/
public function get(string $name): ?Item;

/**
* Returns whether named role or permission exists.
*
* @param string $name The role or the permission name.
*
* @return bool Whether named role or permission exists.
*/
public function exists(string $name): bool;

/**
* Adds the role or the permission to RBAC system.
*
Expand Down
14 changes: 13 additions & 1 deletion src/Manager.php
Expand Up @@ -9,6 +9,7 @@
use InvalidArgumentException;
use RuntimeException;
use Yiisoft\Access\AccessCheckerInterface;
use Yiisoft\Rbac\Exception\ItemAlreadyExistsException;

use function array_key_exists;
use function get_class;
Expand Down Expand Up @@ -372,7 +373,7 @@ private function ensureStringUserId($userId): string
)
);
}
return (string)$userId;
return (string) $userId;
}

/**
Expand Down Expand Up @@ -401,6 +402,8 @@ public function getUserIdsByRoleName(string $roleName): array
/**
* @param Role $role
*
* @throws ItemAlreadyExistsException
*
* @return self
*/
public function addRole(Role $role): self
Expand Down Expand Up @@ -439,6 +442,8 @@ public function updateRole(string $name, Role $role): self
/**
* @param Permission $permission
*
* @throws ItemAlreadyExistsException
*
* @return self
*/
public function addPermission(Permission $permission): self
Expand Down Expand Up @@ -570,8 +575,15 @@ private function executeRule(string $user, Item $item, array $params): bool
->execute($user, $item, $params);
}

/**
* @throws ItemAlreadyExistsException
*/
private function addItem(Item $item): void
{
if ($this->itemsStorage->exists($item->getName())) {
throw new ItemAlreadyExistsException($item);
}

$time = time();
if (!$item->hasCreatedAt()) {
$item = $item->withCreatedAt($time);
Expand Down
33 changes: 33 additions & 0 deletions tests/Exception/ItemAlreadyExistsExceptionTest.php
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Rbac\Tests\Exception;

use Exception;
use PHPUnit\Framework\TestCase;
use Yiisoft\Rbac\Exception\ItemAlreadyExistsException;
use Yiisoft\Rbac\Role;

final class ItemAlreadyExistsExceptionTest extends TestCase
{
public function testBase(): void
{
$exception = new ItemAlreadyExistsException(new Role('reader'));

$this->assertSame('Role or permission with name "reader" already exists.', $exception->getMessage());
$this->assertSame(0, $exception->getCode());
$this->assertNull($exception->getPrevious());
}

public function testCodeAndPreviousException(): void
{
$code = 212;
$previousException = new Exception();

$exception = new ItemAlreadyExistsException(new Role('reader'), $code, $previousException);

$this->assertSame($code, $exception->getCode());
$this->assertSame($previousException, $exception->getPrevious());
}
}
17 changes: 17 additions & 0 deletions tests/ManagerTest.php
Expand Up @@ -8,6 +8,7 @@
use PHPUnit\Framework\TestCase;
use RuntimeException;
use Yiisoft\Rbac\AssignmentsStorageInterface;
use Yiisoft\Rbac\Exception\ItemAlreadyExistsException;
use Yiisoft\Rbac\Exception\RuleNotFoundException;
use Yiisoft\Rbac\Manager;
use Yiisoft\Rbac\Permission;
Expand Down Expand Up @@ -644,6 +645,22 @@ public function testAddRole(): void
$this->assertSame($manager, $returnedManager);
}

public function testAddAlreadyExistsItem(): void
{
$manager = new Manager(
new FakeItemsStorage(),
new FakeAssignmentsStorage(),
new SimpleRuleFactory(),
);
$manager->addRole(new Role('reader'));

$permission = new Permission('reader');

$this->expectException(ItemAlreadyExistsException::class);
$this->expectExceptionMessage('Role or permission with name "reader" already exists.');
$manager->addPermission($permission);
}

public function testRemoveRole(): void
{
$manager = $this->createManager();
Expand Down
5 changes: 5 additions & 0 deletions tests/Support/FakeItemsStorage.php
Expand Up @@ -24,6 +24,11 @@ public function get(string $name): ?Item
return $this->items[$name] ?? null;
}

public function exists(string $name): bool
{
return array_key_exists($name, $this->items);
}

public function add(Item $item): void
{
$this->items[$item->getName()] = $item;
Expand Down

0 comments on commit cf96986

Please sign in to comment.