Passed
Push — main ( 441a12...f99148 )
by Jean-Christophe
02:19
created

AclControllerParser::init()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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