Test Failed
Push — main ( 573841...5a0b4f )
by Jean-Christophe
06:17
created

AclList::isAllowed()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
cc 4
eloc 8
c 0
b 0
f 0
nc 3
nop 3
dl 0
loc 12
rs 10
ccs 0
cts 0
cp 0
crap 20
1
<?php
2
namespace Ubiquity\security\acl\models;
3
4
use Ubiquity\security\acl\persistence\AclProviderInterface;
5
use Ubiquity\exceptions\AclException;
6
use Ubiquity\security\acl\models\traits\AclListOperationsTrait;
7
8
/**
9
 * Ubiquity\security\acl\models$AclList
10
 * This class is part of Ubiquity
11
 *
12
 * @author jc
13
 * @version 1.0.0
14
 *
15
 */
16
class AclList {
17
	use AclListOperationsTrait;
18
19
	/**
20
	 *
21
	 * @var AclElement[]
22
	 */
23
	protected $acls;
24
25
	/**
26
	 *
27
	 * @var Role[]
28
	 */
29
	protected $roles;
30
31
	/**
32
	 *
33
	 * @var \Ubiquity\security\acl\models\Resource[]
34
	 */
35
	protected $resources;
36
37
	/**
38
	 *
39
	 * @var Permission[]
40
	 */
41
	protected $permissions;
42
43
	/**
44
	 *
45
	 * @var AclProviderInterface[]
46
	 */
47
	protected $providers = [];
48
49
	protected $elementsCache = [];
50
51 18
	protected function getElementByName(string $name, array $inArray, string $type) {
52 18
		foreach ($inArray as $elm) {
53 18
			if ($elm->getName() == $name) {
54 17
				return $elm;
55
			}
56
		}
57 7
		throw new AclException("$name does not exist in $type ACL");
58
	}
59
60
	protected function elementExistByName(string $name, array $inArray): bool {
61
		foreach ($inArray as $elm) {
62
			if ($elm->getName() == $name) {
63
				return true;
64
			}
65
		}
66
		return false;
67
	}
68
69 18
	public function init() {
70 18
		$this->roles['role_@ALL'] = new Role('@ALL');
71 18
		$this->resources['res_*'] = new Resource('*');
72 18
		$this->permissions['perm_ALL'] = new Permission('ALL', 1000);
73 18
		$this->acls = [];
74 18
	}
75
76 18
	public function getRoleByName(string $name) {
77 18
		return $this->elementsCache["role_$name"] ??= $this->getElementByName($name, $this->roles, 'roles');
78
	}
79
80 10
	public function getResourceByName(string $name) {
81 10
		return $this->elementsCache["res_$name"] ??= $this->getElementByName($name, $this->resources, 'resources');
82
	}
83
84 14
	public function getPermissionByName(string $name) {
85 14
		return $this->elementsCache["perm_$name"] ??= $this->getElementByName($name, $this->permissions, 'permissions');
86
	}
87
88 6
	public function loadAcls(): array {
89 6
		foreach ($this->providers as $provider) {
90 6
			$this->acls += $provider->loadAllAcls();
91
		}
92 6
		return $this->acls;
93
	}
94
95 6
	public function loadRoles(): array {
96 6
		foreach ($this->providers as $provider) {
97 6
			$this->roles += $provider->loadAllRoles();
98
		}
99 6
		return $this->roles;
100
	}
101
102 6
	public function loadResources(): array {
103 6
		foreach ($this->providers as $provider) {
104 6
			$this->resources += $provider->loadAllResources();
105
		}
106 6
		return $this->resources;
107
	}
108
109 6
	public function loadPermissions(): array {
110 6
		foreach ($this->providers as $provider) {
111 6
			$this->permissions += $provider->loadAllPermissions();
112
		}
113 6
		return $this->permissions;
114
	}
115
116
	public function addProvider(AclProviderInterface $provider) {
117
		$this->providers[] = $provider;
118
	}
119
120
	/**
121
	 *
122
	 * @return AclElement[]
123
	 */
124 3
	public function getAcls() {
125 3
		return $this->acls;
126
	}
127
128
	/**
129
	 *
130
	 * @return Role[]
131
	 */
132 6
	public function getRoles() {
133 6
		return $this->roles;
134
	}
135
136
	/**
137
	 *
138
	 * @return \Ubiquity\security\acl\models\Resource[]
139
	 */
140 5
	public function getResources() {
141 5
		return $this->resources;
142
	}
143
144
	/**
145
	 *
146
	 * @return Permission[]
147
	 */
148 9
	public function getPermissions() {
149 9
		return $this->permissions;
150
	}
151
152
	/**
153
	 *
154
	 * @return AclProviderInterface[]
155
	 */
156
	public function getProviders() {
157
		return $this->providers;
158
	}
159
160
	/**
161
	 *
162
	 * @param AclProviderInterface[] $providers
163
	 */
164 7
	public function setProviders($providers) {
165 7
		$this->providers = $providers;
166 7
	}
167
168 8
	public function addRole(Role $role) {
169 8
		$this->roles[$role->getName()] = $role;
170 8
		$this->savePart($role);
171 8
	}
172
173 7
	public function addResource(Resource $resource) {
174 7
		$this->resources[$resource->getName()] = $resource;
175 7
		$this->savePart($resource);
176 7
	}
177
178 9
	public function addPermission(Permission $permission) {
179 9
		$this->permissions[$permission->getName()] = $permission;
180 9
		$this->savePart($permission);
181 9
	}
182
183 3
	public function setPermissionLevel(string $name, int $level) {
184 3
		$perm = $this->getPermissionByName($name);
185 2
		$perm->setLevel($level);
186 2
		$this->updatePart($perm);
187 2
	}
188
189 10
	public function allow(string $roleName, string $resourceName, string $permissionName) {
190 10
		$aclElm = new AclElement();
191 10
		$aclElm->allow($this->getRoleByName($roleName), $this->getResourceByName($resourceName), $this->getPermissionByName($permissionName));
192 10
		$this->acls[] = $aclElm;
193 10
		$this->saveAclElement($aclElm);
194 10
	}
195
196 18
	public function addAndAllow(string $roleName, string $resourceName, string $permissionName) {
197 18
		if (! $this->elementExistByName($roleName, $this->roles)) {
198 17
			$this->addRole($roleName);
0 ignored issues
show
Bug introduced by
$roleName of type string is incompatible with the type Ubiquity\security\acl\models\Role expected by parameter $role of Ubiquity\security\acl\models\AclList::addRole(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

198
			$this->addRole(/** @scrutinizer ignore-type */ $roleName);
Loading history...
199 17
		}
200 17
		if ($resourceName !== '*' && ! $this->elementExistByName($resourceName, $this->resources)) {
201 14
			$this->addResource($resourceName);
0 ignored issues
show
Bug introduced by
$resourceName of type string is incompatible with the type Ubiquity\security\acl\models\Resource expected by parameter $resource of Ubiquity\security\acl\mo...\AclList::addResource(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

201
			$this->addResource(/** @scrutinizer ignore-type */ $resourceName);
Loading history...
202 14
		}
203 14
		if ($permission !== 'ALL' && ! $this->elementExistByName($permissionName, $this->permissions)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $permission does not exist. Did you maybe mean $permissionName?
Loading history...
204 14
			$this->addPermission($permissionName);
0 ignored issues
show
Bug introduced by
$permissionName of type string is incompatible with the type Ubiquity\security\acl\models\Permission expected by parameter $permission of Ubiquity\security\acl\mo...clList::addPermission(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

204
			$this->addPermission(/** @scrutinizer ignore-type */ $permissionName);
Loading history...
205 14
		}
206
		$this->allow($roleName, $resourceName ?? '*', $permissionName ?? 'ALL');
207
	}
208
209 17
	public function getRolePermissionsOn(string $roleName, $resourceName = '*'): array {
210 4
		$role = $this->getRoleByName($roleName);
211
		$parents = $role->getParentsArray();
212 17
		$result = [];
213
		foreach ($this->acls as $aclElement) {
214
			$aclRoleName = $aclElement->getRole()->getName();
215 18
			if ($aclRoleName === '@ALL' || $aclRoleName === $roleName) {
216 18
				$aclResourceName = $aclElement->getResource()->getName();
217 17
				if ($aclResourceName === '*' || $aclResourceName === $resourceName) {
218 14
					$result[] = $aclElement;
219 13
				}
220 13
			}
221 13
		}
222 13
		foreach ($parents as $parentElm) {
223
			$result += $this->getRolePermissionsOn($parentElm, $resourceName);
224
		}
225
		return $result;
226 12
	}
227
228
	public function isAllowed(string $roleName, string $resourceName, string $permissionName) {
229
		$acls = $this->getRolePermissionsOn($roleName, $resourceName);
230
		if (\count($acls) > 0) {
231
			$permissionLevel = $this->getPermissionByName($permissionName)->getLevel();
232
			foreach ($acls as $aclElm) {
233
				$level = $aclElm->getPermission()->getLevel();
234
				if ($level >= $permissionLevel) {
235
					return true;
236
				}
237
			}
238
		}
239
		return false;
240
	}
241
}
242
243