Adds removal of exceptions as well as error handling.
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LotGD\Core\Exceptions;
|
||||
|
||||
/**
|
||||
* Exception if an existing entity is tried to create again.
|
||||
*/
|
||||
class EntityAlreadyExistsException extends EntityException
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LotGD\Core\Exceptions;
|
||||
|
||||
/**
|
||||
* Exception if a non-existing entity is requested.
|
||||
*/
|
||||
class EntityDoesNotExistException extends EntityException
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LotGD\Core\Exceptions;
|
||||
|
||||
/**
|
||||
* A basic entity exception
|
||||
*/
|
||||
class EntityException extends CoreException
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LotGD\Core\Exceptions;
|
||||
|
||||
/**
|
||||
* Exception if an existing entity is tried to create again.
|
||||
*/
|
||||
class PermissionAlreadyExistsException extends EntityAlreadyExistsException
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LotGD\Core\Exceptions;
|
||||
|
||||
/**
|
||||
* Exception if an existing entity is tried to create again.
|
||||
*/
|
||||
class PermissionDoesNotExistException extends EntityDoesNotExistException
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LotGD\Core\Exceptions;
|
||||
|
||||
/**
|
||||
* Exception if a requested permission id has not been found.
|
||||
*/
|
||||
class PermissionIdNotFoundException extends EntityDoesNotExistException
|
||||
{
|
||||
|
||||
}
|
||||
@@ -28,4 +28,16 @@ interface PermissionableInterface
|
||||
* @return Permission
|
||||
*/
|
||||
public function getRawPermission(string $permissionId): Permission;
|
||||
|
||||
/**
|
||||
* Adds a permission with a set state.
|
||||
* @param \LotGD\Core\Models\Permission $permission
|
||||
*/
|
||||
public function addPermission(Permission $permission, int $state);
|
||||
|
||||
/**
|
||||
* Removes a permission with a given id.
|
||||
* @param string $permissionId
|
||||
*/
|
||||
public function removePermission(string $permissionId);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace LotGD\Core;
|
||||
|
||||
use LotGD\Core\Exceptions\PermissionIdNotFoundException;
|
||||
use LotGD\Core\Models\PermissionableInterface;
|
||||
use LotGD\Core\Models\Permission;
|
||||
|
||||
/**
|
||||
* Permissions can be managed with the PermissionManager.
|
||||
@@ -101,4 +103,77 @@ class PermissionManager
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a permission entity from the database by a permission id.
|
||||
* @param string $permissionId
|
||||
* @return Permission
|
||||
* @throws PermissionIdNotFoundException
|
||||
*/
|
||||
private function findPermission(string $permissionId): Permission
|
||||
{
|
||||
$em = $this->game->getEntityManager();
|
||||
$result = $em->getRepository(Permission::class)->find($permissionId);
|
||||
|
||||
if ($result) {
|
||||
return $result;
|
||||
} else {
|
||||
throw new PermissionIdNotFoundException("Permission {$permissionId} was not found.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows an actor a permission given by the permission id.
|
||||
* @param PermissionableInterface $actor
|
||||
* @param string $permissionId
|
||||
*/
|
||||
public function allow(
|
||||
PermissionableInterface $actor,
|
||||
string $permissionId
|
||||
) {
|
||||
if ($actor->hasPermission($permissionId)) {
|
||||
if ($this->isAllowed($actor, $permissionId) == false) {
|
||||
$permission = $actor->getPermission($permissionId);
|
||||
$permission->setState(static::Allowed);
|
||||
}
|
||||
} else {
|
||||
$permission = $this->findPermission($permissionId);
|
||||
$actor->addPermission($permission, static::Allowed);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Denies an actor a permission given by the permission id.
|
||||
* @param PermissionableInterface $actor
|
||||
* @param string $permissionId
|
||||
*/
|
||||
public function deny(
|
||||
PermissionableInterface $actor,
|
||||
string $permissionId
|
||||
) {
|
||||
if ($actor->hasPermission($permissionId)) {
|
||||
if ($this->isDenied($actor, $permissionId) == false) {
|
||||
$permission = $actor->getPermission($permissionId);
|
||||
$permission->setState(static::Denied);
|
||||
}
|
||||
} else {
|
||||
$permission = $this->findPermission($permissionId);
|
||||
$actor->addPermission($permission, static::Denied);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a permission from an actor.
|
||||
* @param PermissionableInterface $actor
|
||||
* @param string $permissionId
|
||||
*/
|
||||
public function remove(
|
||||
PermissionableInterface $actor,
|
||||
string $permissionId
|
||||
) {
|
||||
if ($actor->hasPermission($permissionId)) {
|
||||
$permissionAssoc = $actor->getPermission($permissionId);
|
||||
$actor->removePermission($permissionId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
namespace LotGD\Core\Tools\Model;
|
||||
|
||||
use LotGD\Core\Models\Permission;
|
||||
use LotGD\Core\Models\PermissionableInterface;
|
||||
|
||||
/**
|
||||
* Tools to work with a permission type field.
|
||||
@@ -12,32 +13,70 @@ trait PermissionAssociationable
|
||||
{
|
||||
/**
|
||||
* @Id @ManyToOne(targetEntity="LotGD\Core\Models\Permission", inversedBy="permission")
|
||||
* @JoinColumn(name="permission_id", referencedColumnName="id")
|
||||
* @JoinColumn(name="permission", referencedColumnName="id")
|
||||
*/
|
||||
protected $permission;
|
||||
/** @Column(type="integer") */
|
||||
protected $permissionState;
|
||||
|
||||
public function getId(): string
|
||||
{
|
||||
return $this->permission->getId();
|
||||
}
|
||||
|
||||
public function getLibrary(): string
|
||||
{
|
||||
return $this->permission->getLibrary();
|
||||
public function __construct(PermissionableInterface $owner, Permission $permission, int $state) {
|
||||
$this->owner = $owner;
|
||||
$this->permission = $permission;
|
||||
$this->permissionState = $state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current state of the permission.
|
||||
* @return int
|
||||
*/
|
||||
public function getState(): int
|
||||
{
|
||||
return $this->permissionState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current state of the permission.
|
||||
* @param int $state
|
||||
*/
|
||||
public function setState(int $state)
|
||||
{
|
||||
$this->permissionState = $state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this permission is set to a given state.
|
||||
* @param int $state
|
||||
* @return bool
|
||||
*/
|
||||
public function checkState(int $state): bool
|
||||
{
|
||||
return $this->permissionState == $state ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the permission id.
|
||||
* @see Permission->getId()
|
||||
* @return string
|
||||
*/
|
||||
public function getId(): string
|
||||
{
|
||||
return $this->permission->getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the permission library.
|
||||
* @see Permission->getLibrary()
|
||||
* @return string
|
||||
*/
|
||||
public function getLibrary(): string
|
||||
{
|
||||
return $this->permission->getLibrary();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Permission entity.
|
||||
* @return Permission
|
||||
*/
|
||||
public function getPermission(): Permission
|
||||
{
|
||||
return $this->permission;
|
||||
|
||||
@@ -3,9 +3,12 @@ declare(strict_types=1);
|
||||
|
||||
namespace LotGD\Core\Tools\Model;
|
||||
|
||||
use LotGD\Core\Exceptions\PermissionAlreadyExistsException;
|
||||
use LotGD\Core\Exceptions\PermissionDoesNotExistException;
|
||||
use LotGD\Core\Models\Permission;
|
||||
use LotGD\Core\Models\PermissionAssociationInterface;
|
||||
|
||||
|
||||
/**
|
||||
* Tools to work with a permission type field.
|
||||
*/
|
||||
@@ -16,6 +19,12 @@ trait Permissionable
|
||||
|
||||
protected function loadPermissions()
|
||||
{
|
||||
if (empty($this->permissionAssociationEntity)) {
|
||||
throw new PermissionAssociationEntityMissingException(
|
||||
"The permissionable entity does not have the property permissionAssociationEntity set."
|
||||
);
|
||||
}
|
||||
|
||||
if (empty($this->_permissions)) {
|
||||
foreach ($this->permissions as $permission) {
|
||||
$this->_permissions[$permission->getId()] = $permission;
|
||||
@@ -43,4 +52,31 @@ trait Permissionable
|
||||
|
||||
return $this->_permissions[$permissionId]->getPermission();
|
||||
}
|
||||
|
||||
public function addPermission(Permission $permission, int $state)
|
||||
{
|
||||
$this->loadPermissions();
|
||||
|
||||
if ($this->hasPermission($permission->getId())) {
|
||||
$permissionId = $permission->getId();
|
||||
throw new PermissionAlreadyExistsException("The permission with the id {$permissionId} has already been set on this actor.");
|
||||
} else {
|
||||
$permissionAssoc = new $this->permissionAssociationEntity($this, $permission, $state);
|
||||
$this->permissions->add($permissionAssoc);
|
||||
$this->_permissions[$permissionAssoc->getId()] = $permissionAssoc;
|
||||
}
|
||||
}
|
||||
|
||||
public function removePermission(string $permissionId)
|
||||
{
|
||||
$this->loadPermissions();
|
||||
|
||||
if ($this->hasPermission($permissionId)) {
|
||||
$permissionAssoc = $this->getPermission($permissionId);
|
||||
$this->permissions->removeElement($permissionAssoc);
|
||||
unset($this->_permissions[$permissionId]);
|
||||
} else {
|
||||
throw new PermissionDoesNotExistException("The permission with the id {$permissionId} has not been set on this actor.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,9 @@ use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
use LotGD\Core\Game;
|
||||
use LotGD\Core\PermissionManager;
|
||||
use LotGD\Core\Exceptions\PermissionAlreadyExistsException;
|
||||
use LotGD\Core\Exceptions\PermissionDoesNotExistException;
|
||||
use LotGD\Core\Exceptions\PermissionIdNotFoundException;
|
||||
use LotGD\Core\Models\Permission;
|
||||
use LotGD\Core\Models\PermissionableInterface;
|
||||
use LotGD\Core\Models\PermissionAssociationInterface;
|
||||
@@ -60,6 +63,26 @@ class PermissionManagerTest extends CoreModelTestCase
|
||||
$this->assertInstanceOf(UserPermissionAssociation::class, $permission);
|
||||
}
|
||||
|
||||
public function testIfAddingAnAlreadySetPermissionToAnUserResultsInException()
|
||||
{
|
||||
$em = $this->getEntityManager();
|
||||
$user = $em->getRepository(User::class)->find(1);
|
||||
$permission = $em->getRepository(Permission::class)->find("test/permission_two");
|
||||
|
||||
$this->expectException(PermissionAlreadyExistsException::class);
|
||||
$user->addPermission($permission, PermissionManager::Denied);
|
||||
}
|
||||
|
||||
public function testIfRemovingANotSetPermissionFromAnUserResultsInException()
|
||||
{
|
||||
$em = $this->getEntityManager();
|
||||
$user = $em->getRepository(User::class)->find(1);
|
||||
$permission = $em->getRepository(Permission::class)->find("test/permission_tri");
|
||||
|
||||
$this->expectException(PermissionDoesNotExistException::class);
|
||||
$user->removePermission("test/permission_tri");
|
||||
}
|
||||
|
||||
public function testIfHasPermissionSetWorksAsExpected()
|
||||
{
|
||||
$em = $this->getEntityManager();
|
||||
@@ -96,6 +119,170 @@ class PermissionManagerTest extends CoreModelTestCase
|
||||
$this->assertFalse($permissionManager->isDenied($user, "test/permission_none"));
|
||||
}
|
||||
|
||||
public function testIfAllowingAnAllowedPermissionWorks()
|
||||
{
|
||||
$em = $this->getEntityManager();
|
||||
$user = $em->getRepository(User::class)->find(1);
|
||||
$permissionManager = $this->getPermissionManager($em);
|
||||
|
||||
$this->assertFalse($permissionManager->hasPermissionSet($user, "test/permission_tri"));
|
||||
$permissionManager->allow($user, "test/permission_one");
|
||||
$this->assertTrue($permissionManager->isAllowed($user, "test/permission_one"));
|
||||
|
||||
$em->flush();
|
||||
$em->clear();
|
||||
|
||||
$user = $em->getRepository(User::class)->find(1);
|
||||
$this->assertTrue($permissionManager->isAllowed($user, "test/permission_one"));
|
||||
}
|
||||
|
||||
public function testIfAllowingAnDeniedPermissionWorks()
|
||||
{
|
||||
$em = $this->getEntityManager();
|
||||
$user = $em->getRepository(User::class)->find(1);
|
||||
$permissionManager = $this->getPermissionManager($em);
|
||||
|
||||
$this->assertTrue($permissionManager->isDenied($user, "test/permission_two"));
|
||||
$permissionManager->allow($user, "test/permission_two");
|
||||
$this->assertTrue($permissionManager->isAllowed($user, "test/permission_two"));
|
||||
|
||||
$em->flush();
|
||||
$em->clear();
|
||||
|
||||
$user = $em->getRepository(User::class)->find(1);
|
||||
$this->assertTrue($permissionManager->isAllowed($user, "test/permission_two"));
|
||||
}
|
||||
|
||||
public function testIfAllowingANonExistingPermissionWorks()
|
||||
{
|
||||
$em = $this->getEntityManager();
|
||||
$user = $em->getRepository(User::class)->find(1);
|
||||
$permissionManager = $this->getPermissionManager($em);
|
||||
|
||||
$this->assertFalse($permissionManager->hasPermissionSet($user, "test/permission_tri"));
|
||||
$permissionManager->allow($user, "test/permission_tri");
|
||||
$this->assertTrue($permissionManager->isAllowed($user, "test/permission_tri"));
|
||||
|
||||
$em->flush();
|
||||
$em->clear();
|
||||
|
||||
$user = $em->getRepository(User::class)->find(1);
|
||||
$this->assertTrue($permissionManager->isAllowed($user, "test/permission_tri"));
|
||||
}
|
||||
|
||||
public function testIfDenyingAnAllowedPermissionWorks()
|
||||
{
|
||||
$em = $this->getEntityManager();
|
||||
$user = $em->getRepository(User::class)->find(1);
|
||||
$permissionManager = $this->getPermissionManager($em);
|
||||
|
||||
$this->assertTrue($permissionManager->isAllowed($user, "test/permission_one"));
|
||||
$permissionManager->deny($user, "test/permission_one");
|
||||
$this->assertTrue($permissionManager->isDenied($user, "test/permission_one"));
|
||||
|
||||
$em->flush();
|
||||
$em->clear();
|
||||
|
||||
$user = $em->getRepository(User::class)->find(1);
|
||||
$this->assertTrue($permissionManager->isDenied($user, "test/permission_one"));
|
||||
}
|
||||
|
||||
public function testIfDenyingAnDeniedPermissionWorks()
|
||||
{
|
||||
$em = $this->getEntityManager();
|
||||
$user = $em->getRepository(User::class)->find(1);
|
||||
$permissionManager = $this->getPermissionManager($em);
|
||||
|
||||
$this->assertTrue($permissionManager->isDenied($user, "test/permission_two"));
|
||||
$permissionManager->deny($user, "test/permission_two");
|
||||
$this->assertTrue($permissionManager->isDenied($user, "test/permission_two"));
|
||||
|
||||
$em->flush();
|
||||
$em->clear();
|
||||
|
||||
$user = $em->getRepository(User::class)->find(1);
|
||||
$this->assertTrue($permissionManager->isDenied($user, "test/permission_two"));
|
||||
}
|
||||
|
||||
public function testIfDenyingANonExistingPermissionWorks()
|
||||
{
|
||||
$em = $this->getEntityManager();
|
||||
$user = $em->getRepository(User::class)->find(1);
|
||||
$permissionManager = $this->getPermissionManager($em);
|
||||
|
||||
$this->assertFalse($permissionManager->hasPermissionSet($user, "test/permission_tri"));
|
||||
$permissionManager->deny($user, "test/permission_tri");
|
||||
$this->assertTrue($permissionManager->isDenied($user, "test/permission_tri"));
|
||||
|
||||
$em->flush();
|
||||
$em->clear();
|
||||
|
||||
$user = $em->getRepository(User::class)->find(1);
|
||||
$this->assertTrue($permissionManager->isDenied($user, "test/permission_tri"));
|
||||
}
|
||||
|
||||
public function testIfRemovingAnAllowedPermissionWorks()
|
||||
{
|
||||
$em = $this->getEntityManager();
|
||||
$user = $em->getRepository(User::class)->find(1);
|
||||
$permissionManager = $this->getPermissionManager($em);
|
||||
|
||||
$this->assertTrue($permissionManager->isAllowed($user, "test/permission_one"));
|
||||
$permissionManager->remove($user, "test/permission_one");
|
||||
$this->assertFalse($permissionManager->hasPermissionSet($user, "test/permission_one"));
|
||||
|
||||
$em->flush();
|
||||
$em->clear();
|
||||
|
||||
$user = $em->getRepository(User::class)->find(1);
|
||||
$this->assertFalse($permissionManager->hasPermissionSet($user, "test/permission_one"));
|
||||
}
|
||||
|
||||
public function testIfRemovingADeniedPermissionWorks()
|
||||
{
|
||||
$em = $this->getEntityManager();
|
||||
$user = $em->getRepository(User::class)->find(1);
|
||||
$permissionManager = $this->getPermissionManager($em);
|
||||
|
||||
$this->assertTrue($permissionManager->isDenied($user, "test/permission_two"));
|
||||
$permissionManager->remove($user, "test/permission_two");
|
||||
$this->assertFalse($permissionManager->hasPermissionSet($user, "test/permission_two"));
|
||||
|
||||
$em->flush();
|
||||
$em->clear();
|
||||
|
||||
$user = $em->getRepository(User::class)->find(1);
|
||||
$this->assertFalse($permissionManager->hasPermissionSet($user, "test/permission_two"));
|
||||
}
|
||||
|
||||
public function testIfRemovingANonExistingPermissionWorks()
|
||||
{
|
||||
$em = $this->getEntityManager();
|
||||
$user = $em->getRepository(User::class)->find(1);
|
||||
$permissionManager = $this->getPermissionManager($em);
|
||||
|
||||
$this->assertFalse($permissionManager->hasPermissionSet($user, "test/permission_tri"));
|
||||
$permissionManager->remove($user, "test/permission_tri");
|
||||
$this->assertFalse($permissionManager->hasPermissionSet($user, "test/permission_tri"));
|
||||
|
||||
$em->flush();
|
||||
$em->clear();
|
||||
|
||||
$user = $em->getRepository(User::class)->find(1);
|
||||
$this->assertFalse($permissionManager->hasPermissionSet($user, "test/permission_tri"));
|
||||
}
|
||||
|
||||
public function testIfRequestingANonExistingPermissionThrowsAnException()
|
||||
{
|
||||
$em = $this->getEntityManager();
|
||||
$user = $em->getRepository(User::class)->find(1);
|
||||
$permissionManager = $this->getPermissionManager($em);
|
||||
|
||||
$this->expectException(PermissionIdNotFoundException::class);
|
||||
|
||||
$permissionManager->allow($user, "test/non_existing_permission");
|
||||
}
|
||||
|
||||
public function testSomething()
|
||||
{
|
||||
$this->assertTrue(True);
|
||||
|
||||
@@ -22,9 +22,11 @@ class User implements PermissionableInterface {
|
||||
private $id;
|
||||
/** @Column(type="string", length=50); */
|
||||
private $name;
|
||||
/** @OneToMany(targetEntity="UserPermissionAssociation", mappedBy="owner", cascade={"persist", "remove"}) */
|
||||
/** @OneToMany(targetEntity="UserPermissionAssociation", mappedBy="owner", cascade={"persist", "remove"}, orphanRemoval=true) */
|
||||
private $permissions;
|
||||
|
||||
private $permissionAssociationEntity = UserPermissionAssociation::class;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->permissions = new ArrayCollection();
|
||||
|
||||
@@ -18,6 +18,7 @@ class UserPermissionAssociation implements PermissionAssociationInterface {
|
||||
|
||||
/**
|
||||
* @Id @ManyToOne(targetEntity="User", inversedBy="permissions")
|
||||
* @JoinColumn(name="owner", referencedColumnName="id")
|
||||
*/
|
||||
private $owner;
|
||||
}
|
||||
@@ -5,12 +5,12 @@ testUsers:
|
||||
name: "Test User 1"
|
||||
testUserAssociations:
|
||||
-
|
||||
owner_id: 1
|
||||
permission_id: "test/permission_one"
|
||||
owner: 1
|
||||
permission: "test/permission_one"
|
||||
permissionState: 1
|
||||
-
|
||||
owner_id: 1
|
||||
permission_id: "test/permission_two"
|
||||
owner: 1
|
||||
permission: "test/permission_two"
|
||||
permissionState: -1
|
||||
|
||||
permissions:
|
||||
|
||||
Reference in New Issue
Block a user