Passed
Push — main ( 610fba...dd0d39 )
by Jean-Christophe
02:42
created

AclControllerParser::parse()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 15
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 4.0119

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 11
c 1
b 0
f 0
nc 4
nop 1
dl 0
loc 15
ccs 10
cts 11
cp 0.9091
crap 4.0119
rs 9.9
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
				$resource ??= $this->mainResource ? $this->mainResource->name : $controller . '.' . $action;
75 1
				if ($annotPermission) {
76
					$permission = $annotPermission->name;
77
					AclManager::addPermission($annotPermission->name, $annotPermission->level);
78
					$hasPermission = true;
79
					$this->permissionMap->addAction($controller, $action, $resource, $annotPermission->name);
80 1
				} elseif ($annotResource) {
81 1
					$this->permissionMap->addAction($controller, $action, $resource, 'ALL');
82
				}
83 1
				$annotsAllow = Reflexion::getAnnotationsMethod($controllerClass, $action, '@allow');
84 1
				if (\is_array($annotsAllow) && \count($annotsAllow) > 0) {
85 1
					$resource = $annotResource ? $annotResource->name : NULL;
86 1
					$this->addAllows($annotsAllow, $controller, $action, $resource, $permission);
87
				}
88 1
				$this->permissionMap->addAction($controller, $action, $resource, $permission);
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) {
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
			AclManager::addAndAllow($annotAllow->role, $resource = $annotAllow->resource ?? $resource, $permission = $annotAllow->permission ?? $permission);
104
		}
105 1
	}
106
107 1
	public function parse($controllerClass) {
108 1
		$this->controllerClass = $controllerClass;
109 1
		$reflect = new \ReflectionClass($controllerClass);
110 1
		if (! $reflect->isAbstract() && $reflect->isSubclassOf(Controller::class)) {
111
			try {
112 1
				$annotsResource = Reflexion::getAnnotationClass($controllerClass, '@resource');
113 1
				$annotsPermission = Reflexion::getAnnotationClass($controllerClass, '@permission');
114
			} catch (\Exception $e) {
115
				// When controllerClass generates an exception
116
			}
117 1
			$this->mainResource = $annotsResource[0] ?? null;
118 1
			$this->mainPermission = $annotsPermission[0] ?? null;
119
120 1
			$methods = Reflexion::getMethods($controllerClass, \ReflectionMethod::IS_PUBLIC);
121 1
			$this->parseMethods($methods);
122
		}
123 1
	}
124
125 1
	public function save() {
126 1
		$this->permissionMap->save();
127 1
		AclManager::saveAll();
128 1
	}
129
}
130
131