| 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 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 10 |  |  | /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 11 |  |  |  * Ubiquity\security\acl\cache$AclControllerParser | 
            
                                                                                                            
                            
            
                                    
            
            
                | 12 |  |  |  * This class is part of Ubiquity | 
            
                                                                                                            
                            
            
                                    
            
            
                | 13 |  |  |  * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 14 |  |  |  * @author jc | 
            
                                                                                                            
                            
            
                                    
            
            
                | 15 |  |  |  * @version 1.0.3 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 16 |  |  |  * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 17 |  |  |  */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 18 |  |  | class AclControllerParser { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 19 |  |  | 	 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 20 |  |  | 	protected $controllerClass; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 21 |  |  | 	 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 22 |  |  | 	protected $mainResource; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 23 |  |  | 	 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 24 |  |  | 	protected $mainPermission; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 25 |  |  | 	 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 26 |  |  | 	protected $permissionMap; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 27 |  |  | 	 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 28 | 2 |  | 	public function __construct() { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 29 | 2 |  | 		$this->permissionMap = new PermissionsMap(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 30 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 31 |  |  | 	 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 32 |  |  | 	public function init() { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 33 |  |  | 		$this->permissionMap->init(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 34 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 35 |  |  | 	 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 36 | 2 |  | 	public function parse($controllerClass) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 37 | 2 |  | 		$this->controllerClass = $controllerClass; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 38 | 2 |  | 		$reflect = new \ReflectionClass($controllerClass); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 39 | 2 |  | 		if (! $reflect->isAbstract() && $reflect->isSubclassOf(Controller::class)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 40 |  |  | 			try { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 41 | 2 |  | 				$annotsResource = Reflexion::getAnnotationClass($controllerClass, 'resource'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 42 | 2 |  | 				$annotsPermission = Reflexion::getAnnotationClass($controllerClass, 'permission'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 43 | 2 |  | 				$annotAllows = Reflexion::getAnnotationClass($controllerClass, 'allow'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 44 |  |  | 			} catch (\Exception $e) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 45 |  |  | 				// When controllerClass generates an exception | 
            
                                                                                                            
                            
            
                                    
            
            
                | 46 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 47 | 2 |  | 			$this->mainResource = $annotsResource[0] ?? null; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 48 | 2 |  | 			$this->mainPermission = $annotsPermission[0] ?? null; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 49 | 2 |  | 			if (\is_array($annotAllows) && \count($annotAllows) > 0) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 50 |  |  | 				$resource = $this->mainResource ? $this->mainResource->name : $reflect->getShortName(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 51 |  |  | 				$permission = $this->mainPermission ? $this->mainPermission->name : 'ALL'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 52 |  |  | 				$this->addAllows($annotAllows, $controllerClass, null, $resource, $permission); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 53 |  |  | 				$this->permissionMap->addAction($controllerClass, '*', $resource, $permission); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 54 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 55 | 2 |  | 			$methods = Reflexion::getMethods($controllerClass, \ReflectionMethod::IS_PUBLIC); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 56 | 2 |  | 			$this->parseMethods($methods); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 57 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 58 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 59 |  |  | 	 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 60 | 2 |  | 	protected function parseMethods($methods) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 61 | 2 |  | 		$hasPermission = false; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 62 | 2 |  | 		$controllerClass = $this->controllerClass; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 63 | 2 |  | 		$controller = ClassUtils::getClassSimpleName($controllerClass); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 64 | 2 |  | 		foreach ($methods as $method) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 65 | 2 |  | 			$this->parseMethod($method, $hasPermission, $controller); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 66 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 67 | 2 |  | 		if ($hasPermission || $this->mainResource != null || $this->mainPermission != null) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 68 | 2 |  | 			$permission = 'ALL'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 69 | 2 |  | 			$resource = $this->mainResource ? $this->mainResource->name : $controller; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 70 | 2 |  | 			$this->permissionMap->addAction($controllerClass, '*', $resource, $this->mainPermission ? $this->mainPermission->name : 'ALL'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 71 | 2 |  | 			AclManager::addResource($resource, $controller . '.*'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 72 | 2 |  | 			if (isset($this->mainPermission)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 73 |  |  | 				$permission = $this->mainPermission->name; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 74 |  |  | 				AclManager::addPermission($this->mainPermission->name, ($this->mainPermission->level) ?? 0); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 75 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 76 | 2 |  | 			$annotsAllow = Reflexion::getAnnotationClass($controllerClass, 'allow'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 77 | 2 |  | 			if (\is_array($annotsAllow) && \count($annotsAllow) > 0) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 78 |  |  | 				$this->addAllows($annotsAllow, $controller, '*', $resource, $permission); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 79 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 80 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 81 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 82 |  |  | 	 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 83 | 2 |  | 	protected function parseMethod(\ReflectionMethod $method, bool &$hasPermission, $controller) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 84 | 2 |  | 		$action = $method->name; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 85 | 2 |  | 		$permission = NULL; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 86 | 2 |  | 		$resource = NULL; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 87 | 2 |  | 		$controllerClass = $this->controllerClass; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 88 | 2 |  | 		if ($method->getDeclaringClass()->getName() === $controllerClass) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 89 |  |  | 			try { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 90 | 2 |  | 				$annotResource = Reflexion::getAnnotationMethod($controllerClass, $action, 'resource'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 91 | 2 |  | 				$annotPermission = Reflexion::getAnnotationMethod($controllerClass, $action, 'permission'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 92 | 2 |  | 				if ($annotResource) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 93 | 2 |  | 					$resource = $annotResource->name; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 94 | 2 |  | 					AclManager::addResource($annotResource->name, $controller . '.' . $action); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 95 |  |  | 				} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 96 | 2 |  | 				if ($annotPermission) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 97 | 2 |  | 					if(\is_int($annotPermission->name) && $annotPermission->level===0){ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 98 |  |  | 						$annotPermission->level=$annotPermission->name; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 99 |  |  | 						$annotPermission->name=null; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 100 |  |  | 					} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 101 | 2 |  | 					$permission = $annotPermission->name??\strtoupper($action); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 102 | 2 |  | 					AclManager::addPermission($permission, $annotPermission->level ?? 0); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 103 | 2 |  | 					$hasPermission = true; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 104 |  |  | 				} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 105 | 2 |  | 				$resource ??= $this->mainResource ? $this->mainResource->name : ($controller . '.' . $action); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 106 |  |  | 				 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 107 | 2 |  | 				$annotsAllow = Reflexion::getAnnotationsMethod($controllerClass, $action, 'allow'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 108 | 2 |  | 				if (\is_array($annotsAllow) && \count($annotsAllow) > 0) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 109 | 2 |  | 					$this->addAllows($annotsAllow, $controller, $action, $resource, $permission); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 110 | 2 |  | 					$this->permissionMap->addAction($controllerClass, $action, $resource, $permission ?? 'ALL'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 111 | 2 |  | 				} elseif ($permission !== null && $resource !== null) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 112 | 2 |  | 					$this->permissionMap->addAction($controllerClass, $action, $resource, $permission ?? 'ALL'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 113 |  |  | 				} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 114 |  |  | 			} catch (\Exception $e) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 115 |  |  | 				// Exception in controller code | 
            
                                                                                                            
                            
            
                                    
            
            
                | 116 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 117 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 118 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 119 |  |  | 	 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 120 | 2 |  | 	protected function addAllows($annotsAllow, $controller, $action, &$resource, &$permission) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 121 | 2 |  | 		foreach ($annotsAllow as $annotAllow) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 122 | 2 |  | 			if (isset($annotAllow->resource) && isset($resource) && \strpos($resource, '.') === FALSE && $resource !== $annotAllow->resource && $permission != null) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 123 |  |  | 				throw new AclException("Resources {$resource} and {$annotAllow->resource} are in conflict for action {$controller}.{$action}"); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 124 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 125 | 2 |  | 			if (isset($annotAllow->permission) && isset($permission) && $permission !== $annotAllow->permission) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 126 |  |  | 				throw new AclException("Permissions {$permission} and {$annotAllow->permission} are in conflict for action {$controller}.{$action}"); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 127 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 128 |  |  | 			 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 129 | 2 |  | 			$resource = ($annotAllow->resource ?? $resource)??$controller . '.' . $action; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 130 | 2 |  | 			$permission = ($annotAllow->permission ?? $permission)??\strtoupper($action); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 131 |  |  | 			 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 132 | 2 |  | 			if (\is_array($annotAllow->role)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 133 |  |  | 				foreach ($annotAllow->role as $role) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 134 |  |  | 					AclManager::addAndAllow($role, $resource, $permission); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 135 |  |  | 				} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 136 |  |  | 			} else { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 137 | 2 |  | 				AclManager::addAndAllow($annotAllow->role, $resource, $permission); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 138 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 139 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 140 |  |  | 	} | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 141 |  |  | 	 | 
            
                                                                        
                            
            
                                    
            
            
                | 142 | 2 |  | 	public function save() { | 
            
                                                                        
                            
            
                                    
            
            
                | 143 | 2 |  | 		$this->permissionMap->save(); | 
            
                                                                        
                            
            
                                    
            
            
                | 144 | 2 |  | 		AclManager::saveAll(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 145 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 146 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 147 |  |  | 	public function cacheUpdated(): bool { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 148 |  |  | 		if ($this->permissionMap->cacheUpdated()) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 149 |  |  | 			return true; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 150 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 151 |  |  | 		return AclManager::cacheUpdated(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 152 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 153 |  |  | } | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 154 |  |  |  | 
            
                                                        
            
                                    
            
            
                | 155 |  |  |  |