Improve tests and harmonize permission handling

This commit is contained in:
Dennis Eichhorn 2019-04-19 20:49:46 +02:00
parent 99f429f7ed
commit 135b7bf30d
5 changed files with 314 additions and 136 deletions

View File

@ -107,14 +107,6 @@ class Account implements ArrayableInterface, \JsonSerializable
*/
protected $createdAt = null;
/**
* Permissions.
*
* @var PermissionAbstract[]
* @since 1.0.0
*/
protected $permissions = [];
/**
* Groups.
*
@ -155,6 +147,8 @@ class Account implements ArrayableInterface, \JsonSerializable
*/
protected $l11n = null;
use PermissionHandlingTrait;
/**
* Constructor.
*
@ -241,109 +235,6 @@ class Account implements ArrayableInterface, \JsonSerializable
$this->l11n = $l11n;
}
/**
* Set permissions.
*
* The method accepts an array of permissions. All existing permissions are replaced.
*
* @param PermissionAbstract[] $permissions Account permissions
*
* @return void
*
* @since 1.0.0
*/
public function setPermissions(array $permissions) : void
{
$this->permissions = $permissions;
}
/**
* Add permissions.
*
* Adds permissions to the account
*
* @param array<array|PermissionAbstract> $permissions Array of permissions to add to the account
*
* @return void
*
* @since 1.0.0
*/
public function addPermissions(array $permissions) : void
{
foreach ($permissions as $permission) {
if (\is_array($permission)) {
$this->permissions = \array_merge($this->permissions, $permission);
} else {
$this->permissions[] = $permission;
}
}
}
/**
* Add permission.
*
* Adds a single permission to the account
*
* @param PermissionAbstract $permission Permission to add to the account
*
* @return void
*
* @since 1.0.0
*/
public function addPermission(PermissionAbstract $permission) : void
{
$this->permissions[] = $permission;
}
/**
* Get permissions.
*
* @return PermissionAbstract[]
*
* @since 1.0.0
*/
public function getPermissions() : array
{
return $this->permissions;
}
/**
* Has permissions.
*
* Checks if the account has a permission defined
*
* @param int $permission Permission to check
* @param null|int $unit Unit Unit to check (null if all are acceptable)
* @param null|string $app App App to check (null if all are acceptable)
* @param null|string $module Module Module to check (null if all are acceptable)
* @param null|int $type Type (e.g. customer) (null if all are acceptable)
* @param null|int $element (e.g. customer id) (null if all are acceptable)
* @param null|int $component (e.g. address) (null if all are acceptable)
*
* @return bool Returns true if the account has the permission, false otherwise
*
* @since 1.0.0
*/
public function hasPermission(int $permission, int $unit = null, string $app = null, string $module = null, int $type = null, int $element = null, int $component = null) : bool
{
$app = $app !== null ? \strtolower($app) : $app;
foreach ($this->permissions as $p) {
if (($unit === null || $p->getUnit() === $unit || $p->getUnit() === null)
&& ($app === null || $p->getApp() === $app || $p->getApp() === null)
&& ($module === null || $p->getModule() === $module || $p->getModule() === null)
&& ($type === null || $p->getType() === $type || $p->getType() === null)
&& ($element === null || $p->getElement() === $element || $p->getElement() === null)
&& ($component === null || $p->getComponent() === $component || $p->getComponent() === null)
&& ($p->getPermission() | $permission) === $p->getPermission()
) {
return true;
}
}
return false;
}
/**
* Get name.
*

View File

@ -29,7 +29,7 @@ class Group implements ArrayableInterface, \JsonSerializable
{
/**
* Account id.
* Group id.
*
* @var int
* @since 1.0.0
@ -37,7 +37,7 @@ class Group implements ArrayableInterface, \JsonSerializable
protected $id = 0;
/**
* Account name.
* Group name.
*
* @var string
* @since 1.0.0
@ -45,7 +45,7 @@ class Group implements ArrayableInterface, \JsonSerializable
protected $name = '';
/**
* Account name.
* Group name.
*
* @var string
* @since 1.0.0
@ -53,7 +53,7 @@ class Group implements ArrayableInterface, \JsonSerializable
protected $description = '';
/**
* Account name.
* Group members.
*
* @var array
* @since 1.0.0
@ -76,13 +76,7 @@ class Group implements ArrayableInterface, \JsonSerializable
*/
protected $status = GroupStatus::INACTIVE;
/**
* Permissions.
*
* @var int[]
* @since 1.0.0
*/
protected $permissions = [];
use PermissionHandlingTrait;
/**
* Get group id.

View File

@ -0,0 +1,137 @@
<?php
/**
* Orange Management
*
* PHP Version 7.2
*
* @package phpOMS\Account
* @copyright Dennis Eichhorn
* @license OMS License 1.0
* @version 1.0.0
* @link http://website.orange-management.de
*/
declare(strict_types=1);
namespace phpOMS\Account;
/**
* Permission handling trait.
*
* @package phpOMS\Account
* @license OMS License 1.0
* @link http://website.orange-management.de
* @since 1.0.0
*/
trait PermissionHandlingTrait
{
/**
* Permissions.
*
* @var PermissionAbstract[]
* @since 1.0.0
*/
protected $permissions = [];
/**
* Set permissions.
*
* The method accepts an array of permissions. All existing permissions are replaced.
*
* @param PermissionAbstract[] $permissions Permissions
*
* @return void
*
* @since 1.0.0
*/
public function setPermissions(array $permissions) : void
{
$this->permissions = $permissions;
}
/**
* Add permissions.
*
* Adds permissions
*
* @param array<array|PermissionAbstract> $permissions Array of permissions to add
*
* @return void
*
* @since 1.0.0
*/
public function addPermissions(array $permissions) : void
{
foreach ($permissions as $permission) {
if (\is_array($permission)) {
$this->permissions = \array_merge($this->permissions, $permission);
} else {
$this->permissions[] = $permission;
}
}
}
/**
* Add permission.
*
* Adds a single permission
*
* @param PermissionAbstract $permission Permission to add
*
* @return void
*
* @since 1.0.0
*/
public function addPermission(PermissionAbstract $permission) : void
{
$this->permissions[] = $permission;
}
/**
* Get permissions.
*
* @return PermissionAbstract[]
*
* @since 1.0.0
*/
public function getPermissions() : array
{
return $this->permissions;
}
/**
* Has permissions.
*
* Checks if the permission is defined
*
* @param int $permission Permission to check
* @param null|int $unit Unit Unit to check (null if all are acceptable)
* @param null|string $app App App to check (null if all are acceptable)
* @param null|string $module Module Module to check (null if all are acceptable)
* @param null|int $type Type (e.g. customer) (null if all are acceptable)
* @param null|int $element (e.g. customer id) (null if all are acceptable)
* @param null|int $component (e.g. address) (null if all are acceptable)
*
* @return bool Returns true if the permission is set, false otherwise
*
* @since 1.0.0
*/
public function hasPermission(int $permission, int $unit = null, string $app = null, string $module = null, int $type = null, int $element = null, int $component = null) : bool
{
$app = $app !== null ? \strtolower($app) : $app;
foreach ($this->permissions as $p) {
if (($unit === null || $p->getUnit() === $unit || $p->getUnit() === null)
&& ($app === null || $p->getApp() === $app || $p->getApp() === null)
&& ($module === null || $p->getModule() === $module || $p->getModule() === null)
&& ($type === null || $p->getType() === $type || $p->getType() === null)
&& ($element === null || $p->getElement() === $element || $p->getElement() === null)
&& ($component === null || $p->getComponent() === $component || $p->getComponent() === null)
&& ($p->getPermission() | $permission) === $p->getPermission()
) {
return true;
}
}
return false;
}
}

View File

@ -24,6 +24,9 @@ use phpOMS\Localization\Localization;
require_once __DIR__ . '/../Autoloader.php';
/**
* @testdox phpOMS\tests\Account\Account: Base account/user representation
*/
class AccountTest extends \PHPUnit\Framework\TestCase
{
protected $l11nManager = null;
@ -33,6 +36,9 @@ class AccountTest extends \PHPUnit\Framework\TestCase
$this->l11nManager = new L11nManager('Api');
}
/**
* @testdox The account has the expected member variables
*/
public function testAttributes() : void
{
$account = new Account();
@ -55,6 +61,9 @@ class AccountTest extends \PHPUnit\Framework\TestCase
self::assertObjectHasAttribute('l11n', $account);
}
/**
* @testdox The account has the expected default values after initialization
*/
public function testDefault() : void
{
$account = new Account();
@ -99,16 +108,14 @@ class AccountTest extends \PHPUnit\Framework\TestCase
self::assertEquals($array, $account->jsonSerialize());
}
public function testSetGet() : void
/**
* @testdox The account names can be set and retrieved correctly
*/
public function testSetAndGetAccountNames() : void
{
$account = new Account();
/* Just test if no error happens */
$account->generatePassword('abcd');
$account->addGroup(new Group());
self::assertEquals(1, \count($account->getGroups()));
$account->setName('Login');
self::assertEquals('Login', $account->getName());
@ -121,17 +128,65 @@ class AccountTest extends \PHPUnit\Framework\TestCase
$account->setName3('Duck');
self::assertEquals('Duck', $account->getName3());
$account->setEmail('d.duck@duckburg.com');
self::assertEquals('d.duck@duckburg.com', $account->getEmail());
$account->setName('Login');
self::assertEquals('Login', $account->getName());
}
/**
* @testdox Groups can be added to an account
*/
public function testAddAndGetGroup() : void
{
$account = new Account();
$account->generatePassword('abcd');
$account->addGroup(new Group());
self::assertEquals(1, \count($account->getGroups()));
}
/**
* @testdox An account can have a valid email address
*/
public function testSetAndGetAccountEmail() : void
{
$account = new Account();
$account->generatePassword('abcd');
$account->setEmail('d.duck@duckburg.com');
self::assertEquals('d.duck@duckburg.com', $account->getEmail());
}
/**
* @testdox The default status of the account can be changed to a different valid status
*/
public function testChangeStatus() : void
{
$account = new Account();
$account->generatePassword('abcd');
$account->setStatus(AccountStatus::ACTIVE);
self::assertEquals(AccountStatus::ACTIVE, $account->getStatus());
}
/**
* @testdox The default type of the account can be changed to a different valid type
*/
public function testChangeType() : void
{
$account = new Account();
$account->generatePassword('abcd');
$account->setType(AccountType::GROUP);
self::assertEquals(AccountType::GROUP, $account->getType());
}
/**
* @testdox Account permissions can be added and checked for existence
*/
public function testPermissionHandling() : void
{
$account = new Account();
$account->generatePassword('abcd');
$account->addPermission(new class extends PermissionAbstract {});
self::assertEquals(1, \count($account->getPermissions()));
@ -156,15 +211,36 @@ class AccountTest extends \PHPUnit\Framework\TestCase
self::assertFalse($account->hasPermission(PermissionType::READ, 1, 'a', 'a', 1, 1, 1));
self::assertTrue($account->hasPermission(PermissionType::NONE));
}
/**
* @testdox An account can have it's own localization
*/
public function testLocalization() : void
{
$account = new Account();
$account->generatePassword('abcd');
$account->setL11n(new Localization());
self::assertInstanceOf('\phpOMS\Localization\Localization', $account->getL11n());
}
/**
* @testdox An account 'last activity' timestamp can be updated and retrieved
*/
public function testLastChange() : void
{
$account = new Account();
$account->generatePassword('abcd');
$datetime = new \DateTime('now');
$account->updateLastActive();
self::assertEquals($datetime->format('Y-m-d h:i:s'), $account->getLastActive()->format('Y-m-d h:i:s'));
}
/**
* @testdox An account can only have a valid email
*/
public function testEmailException() : void
{
self::expectException(\InvalidArgumentException::class);
@ -173,19 +249,37 @@ class AccountTest extends \PHPUnit\Framework\TestCase
$account->setEmail('d.duck!@#%@duckburg');
}
/**
* @testdox An account can only have valid account status
*/
public function testStatusException() : void
{
self::expectException(\phpOMS\Stdlib\Base\Exception\InvalidEnumValue::class);
$account = new Account();
$account->setStatus(99);
$rand = 0;
do {
$rand = \mt_rand(PHP_INT_MIN, PHP_INT_MAX);
} while (AccountStatus::isValidValue($rand));
$account->setStatus($rand);
}
/**
* @testdox An account can only have valid account types
*/
public function testTypeException() : void
{
self::expectException(\phpOMS\Stdlib\Base\Exception\InvalidEnumValue::class);
$account = new Account();
$account->setType(99);
$rand = 0;
do {
$rand = \mt_rand(PHP_INT_MIN, PHP_INT_MAX);
} while (AccountType::isValidValue($rand));
$account->setType($rand);
}
}

View File

@ -15,11 +15,19 @@ namespace phpOMS\tests\Account;
use phpOMS\Account\Group;
use phpOMS\Account\GroupStatus;
use phpOMS\Account\PermissionAbstract;
use phpOMS\Account\PermissionType;
require_once __DIR__ . '/../Autoloader.php';
/**
* @testdox phpOMS\tests\Account\Group: Base group representation
*/
class GroupTest extends \PHPUnit\Framework\TestCase
{
/**
* @testdox The group has the expected member variables
*/
public function testAttributes() : void
{
$group = new Group();
@ -35,6 +43,9 @@ class GroupTest extends \PHPUnit\Framework\TestCase
self::assertObjectHasAttribute('status', $group);
}
/**
* @testdox The group has the expected default values after initialization
*/
public function testDefault() : void
{
$group = new Group();
@ -59,7 +70,10 @@ class GroupTest extends \PHPUnit\Framework\TestCase
self::assertEquals($array, $group->jsonSerialize());
}
public function testSetGet() : void
/**
* @testdox The group name and description can be set and retrieved correctly
*/
public function testSetAndGetGroupNameDescription() : void
{
$group = new Group();
@ -68,16 +82,64 @@ class GroupTest extends \PHPUnit\Framework\TestCase
$group->setDescription('Animal');
self::assertEquals('Animal', $group->getDescription());
}
/**
* @testdox Group permissions can be added and checked for existence
*/
public function testPermissionHandling() : void
{
$group = new Group();
$group->addPermission(new class extends PermissionAbstract {});
self::assertEquals(1, \count($group->getPermissions()));
$group->setPermissions([
new class extends PermissionAbstract {},
new class extends PermissionAbstract {},
]);
self::assertEquals(2, \count($group->getPermissions()));
$group->addPermissions([
new class extends PermissionAbstract {},
new class extends PermissionAbstract {},
]);
self::assertEquals(4, \count($group->getPermissions()));
$group->addPermissions([[
new class extends PermissionAbstract {},
new class extends PermissionAbstract {},
]]);
self::assertEquals(6, \count($group->getPermissions()));
self::assertFalse($group->hasPermission(PermissionType::READ, 1, 'a', 'a', 1, 1, 1));
self::assertTrue($group->hasPermission(PermissionType::NONE));
}
/**
* @testdox The default status of the group can be changed to a different valid status
*/
public function testChangeStatus() : void
{
$group = new Group();
$group->setStatus(GroupStatus::ACTIVE);
self::assertEquals(GroupStatus::ACTIVE, $group->getStatus());
}
/**
* @testdox A group can only have valid group status
*/
public function testStatusException() : void
{
self::expectException(\phpOMS\Stdlib\Base\Exception\InvalidEnumValue::class);
$account = new Group();
$account->setStatus(99);
$group = new Group();
$rand = 0;
do {
$rand = \mt_rand(PHP_INT_MIN, PHP_INT_MAX);
} while (GroupStatus::isValidValue($rand));
$group->setStatus($rand);
}
}