Passed
Push — main ( b3eef2...a44813 )
by Jean-Christophe
02:19
created

AclControllerParser::addAllows()   B

Complexity

Conditions 8
Paths 4

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 9.4924

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 8
eloc 6
c 1
b 0
f 0
nc 4
nop 5
dl 0
loc 9
ccs 5
cts 7
cp 0.7143
crap 9.4924
rs 8.4444
1
<?php
2
namespace Ubiquity\security\acl\cache;
3
4
use Ubiquity\controllers\Controller;
5
use Ubiquity\orm\parser\Reflexion;
6
use Ubiquity\security\acl\AclManager;
7
use Ubiquity\cache\ClassUtils;
8
use Ubiquity\exceptions\AclException;
9
use PharIo\Manifest\ElementCollectionException;
10
11
/**
12
 * Ubiquity\security\acl\cache$AclControllerParser
13
 * This class is part of Ubiquity
14
 *
15
 * @author jc
16
 * @version 1.0.0
17
 *
18
 */
19
class AclControllerParser {
20
21
	protected $controllerClass;
22
23
	protected $mainResource;
24
25
	protected $mainPermission;
26
27
	protected $permissionMap;
28
29 1
	public function __construct() {
30 1
		$this->permissionMap = new PermissionsMap();
31 1
	}
32
33 1
	public function init() {
34 1
		$this->permissionMap->init();
35 1
	}
36
37 1
	protected function parseMethods($methods) {
38 1
		$hasPermission = false;
39 1
		$controllerClass = $this->controllerClass;
40 1
		$controller = ClassUtils::getClassSimpleName($controllerClass);
41 1
		foreach ($methods as $method) {
42 1
			$this->parseMethod($method, $hasPermission, $controller);
43
		}
44 1
		if ($hasPermission || $this->mainResource != null || $this->mainPermission != null) {
45 1
			$permission = 'ALL';
46 1
			$resource = $this->mainResource ? $this->mainResource->name : $controller;
47 1
			$this->permissionMap->addAction($controller, '*', $resource, $this->mainPermission ? $this->mainPermission->name : 'ALL');
48 1
			AclManager::addResource($resource, $controller . '.*');
49 1
			if (isset($this->mainPermission)) {
50
				$permission = $this->mainPermission->name;
51
				AclManager::addPermission($this->mainPermission->name, ($this->mainPermission->level) ?? 0);
52
			}
53 1
			$annotsAllow = Reflexion::getAnnotationClass($controllerClass, '@allow');
54 1
			if (\is_array($annotsAllow) && \count($annotsAllow) > 0) {
55
				$this->addAllows($annotsAllow, $controller, '*', $resource, $permission);
56
			}
57
		}
58 1
	}
59
60 1
	protected function parseMethod(\ReflectionMethod $method, bool &$hasPermission, $controller) {
61 1
		$action = $method->name;
62 1
		$permission = NULL;
63 1
		$resource = NULL;
64 1
		$controllerClass = $this->controllerClass;
65 1
		if ($method->getDeclaringClass()->getName() === $controllerClass) {
66
			try {
67 1
				$annotResource = Reflexion::getAnnotationMethod($controllerClass, $action, '@resource');
68 1
				$annotPermission = Reflexion::getAnnotationMethod($controllerClass, $action, '@permission');
69 1
				if ($annotResource) {
70 1
					$resource = $annotResource->name;
71 1
					AclManager::addResource($annotResource->name, $controller . '.' . $action);
72
				}
73 1
				$resource ??= $this->mainResource ? $this->mainResource->name : $controller . '.' . $action;
74 1
				if ($annotPermission) {
75
					$permission = $annotPermission->name;
76
					AclManager::addPermission($annotPermission->name, $annotPermission->level);
77
					$hasPermission = true;
78
					$this->permissionMap->addAction($controller, $action, $resource, $annotPermission->name);
79 1
				} elseif ($annotResource) {
80 1
					$this->permissionMap->addAction($controller, $action, $resource, 'ALL');
81
				}
82 1
				$annotsAllow = Reflexion::getAnnotationsMethod($controllerClass, $action, '@allow');
83 1
				if (\is_array($annotsAllow) && \count($annotsAllow) > 0) {
84 1
					$this->addAllows($annotsAllow, $controller, $action, $resource, $permission);
85
				}
86
			} catch (\Exception $e) {
87
				// Exception in controller code
88
			}
89
		}
90 1
	}
91
92 1
	protected function addAllows($annotsAllow, $controller, $action, $resource, $permission) {
93 1
		foreach ($annotsAllow as $annotAllow) {
94 1
			if (isset($annotAllow->resource) && isset($resource) && $resource !== $annotAllow->resource) {
95
				throw new AclException("Resources {$resource} and {$annotAllow->resource} are in conflict for action {$controller}.{$action}");
96
			}
97 1
			if (isset($annotAllow->permission) && isset($permission) && $permission !== $annotAllow->permission) {
98
				throw new AclException("Permissions {$permission} and {$annotAllow->permission} are in conflict for action {$controller}.{$action}");
99
			}
100 1
			AclManager::addAndAllow($annotAllow->role, $annotAllow->resource ?? $resource, $annotAllow->permission ?? $permission);
101
		}
102 1
	}
103
104 1
	public function parse($controllerClass) {
105 1
		$this->controllerClass = $controllerClass;
106 1
		$reflect = new \ReflectionClass($controllerClass);
107 1
		if (! $reflect->isAbstract() && $reflect->isSubclassOf(Controller::class)) {
108
			try {
109 1
				$annotsResource = Reflexion::getAnnotationClass($controllerClass, '@resource');
110 1
				$annotsPermission = Reflexion::getAnnotationClass($controllerClass, '@permission');
111
			} catch (\Exception $e) {
112
				// When controllerClass generates an exception
113
			}
114 1
			$this->mainResource = $annotsResource[0] ?? null;
115 1
			$this->mainPermission = $annotsPermission[0] ?? null;
116
117 1
			$methods = Reflexion::getMethods($controllerClass, \ReflectionMethod::IS_PUBLIC);
118 1
			$this->parseMethods($methods);
119
		}
120 1
	}
121
122 1
	public function save() {
123 1
		$this->permissionMap->save();
124 1
		AclManager::saveAll();
125 1
	}
126
}
127
128