| Total Complexity | 150 |
| Total Lines | 775 |
| Duplicated Lines | 0 % |
| Changes | 1 | ||
| Bugs | 0 | Features | 0 |
Complex classes like TPermissionsManager often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use TPermissionsManager, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 144 | class TPermissionsManager extends \Prado\TModule implements IPermissions |
||
| 145 | { |
||
| 146 | public const PERMISSIONS_BEHAVIOR = 'permissions'; |
||
| 147 | |||
| 148 | public const USER_PERMISSIONS_BEHAVIOR = 'usercan'; |
||
| 149 | |||
| 150 | public const PERMISSIONS_CONFIG_BEHAVIOR = 'permissionsConfig'; |
||
| 151 | |||
| 152 | public const PERM_PERMISSIONS_SHELL = 'permissions_shell'; |
||
| 153 | |||
| 154 | public const PERM_PERMISSIONS_MANAGE_ROLES = 'permissions_manage_roles'; |
||
| 155 | |||
| 156 | public const PERM_PERMISSIONS_MANAGE_RULES = 'permissions_manage_rules'; |
||
| 157 | |||
| 158 | /** @var string[] roles that get all permissions, default [] */ |
||
| 159 | private $_superRoles; |
||
| 160 | |||
| 161 | /** @var string[] Default roles to give all users, default [] */ |
||
| 162 | private $_defaultRoles; |
||
| 163 | |||
| 164 | /** @var array<string, \Prado\Security\TAuthorizationRuleCollection> contains the rules for each permission */ |
||
| 165 | private $_permissionRules = []; |
||
| 166 | |||
| 167 | /** @var array<string, string> contains the short descriptions for each permission */ |
||
| 168 | private $_descriptions = []; |
||
| 169 | |||
| 170 | /** @var array<string, \Prado\Security\TAuthorizationRule[]> the rules to apply to newly registered Permissions */ |
||
| 171 | private $_autoRules = []; |
||
| 172 | |||
| 173 | /** @var array<string, string[]> contains the hierarchy of roles and children roles/permissions */ |
||
| 174 | private $_hierarchy = []; |
||
| 175 | |||
| 176 | /** @var bool is the module initialized */ |
||
| 177 | private $_initialized = false; |
||
| 178 | |||
| 179 | /** @var string role hierarchy and permission rules information file */ |
||
| 180 | private $_permissionFile; |
||
| 181 | |||
| 182 | /** @var numeric the priority of the Allow With Permission Rule, default 5 */ |
||
|
|
|||
| 183 | private $_autoRulePriority = 5; |
||
| 184 | |||
| 185 | /** @var bool add allow users with permission-role, default true */ |
||
| 186 | private $_autoAllowWithPermission = true; |
||
| 187 | |||
| 188 | /** @var bool add module rules, allows User's data, default true */ |
||
| 189 | private $_autoRulePresetRules = true; |
||
| 190 | |||
| 191 | /** @var bool add Deny All rule to every permissions as the last rule, default true */ |
||
| 192 | private $_autoDenyAll = true; |
||
| 193 | |||
| 194 | /** @var numeric the priority of the module Rule, usually these are Allow User As Owner, default 1000000 */ |
||
| 195 | private $_autoDenyAllPriority = 1000000; |
||
| 196 | |||
| 197 | /** @var \Prado\Util\TDbParameterModule the database module providing runtime roles and rules */ |
||
| 198 | private $_dbParameter; |
||
| 199 | |||
| 200 | /** @var numeric the priority of the module Rule, usually these are Allow User As Owner */ |
||
| 201 | private $_parameter = 'configuration:TPermissionsManager:runtime'; |
||
| 202 | |||
| 203 | // hierarchy from parameter |
||
| 204 | |||
| 205 | /** |
||
| 206 | * @param \Prado\Security\Permissions\TPermissionsManager $manager |
||
| 207 | * @return TPermissionEvent[] the dynamic events to have authorization |
||
| 208 | */ |
||
| 209 | public function getPermissions($manager) |
||
| 210 | { |
||
| 211 | return [ |
||
| 212 | new TPermissionEvent(static::PERM_PERMISSIONS_SHELL, 'Activates permissions shell commands.', 'dyRegisterShellAction'), |
||
| 213 | new TPermissionEvent(static::PERM_PERMISSIONS_MANAGE_ROLES, 'Manages Db Permissions Role Children.', ['dyAddRoleChildren', 'dyRemoveRoleChildren']), |
||
| 214 | new TPermissionEvent(static::PERM_PERMISSIONS_MANAGE_RULES, 'Manages Db Permissions Rules.', ['dyAddPermissionRule', 'dyRemovePermissionRule']) |
||
| 215 | ]; |
||
| 216 | } |
||
| 217 | |||
| 218 | /** |
||
| 219 | * @param array|TXmlElement $config the application configuration |
||
| 220 | */ |
||
| 221 | public function init($config) |
||
| 222 | { |
||
| 223 | $app = $this->getApplication(); |
||
| 224 | if (is_string($this->_dbParameter)) { |
||
| 225 | if (($dbParameter = $app->getModule($this->_dbParameter)) === null) { |
||
| 226 | throw new TConfigurationException('permissions_dbparameter_nonexistent', $this->_dbParameter); |
||
| 227 | } |
||
| 228 | if (!($dbParameter instanceof TDbParameterModule)) { |
||
| 229 | throw new TConfigurationException('permissions_dbparameter_invalid', $this->_dbParameter); |
||
| 230 | } |
||
| 231 | $this->_dbParameter = $dbParameter; |
||
| 232 | } |
||
| 233 | |||
| 234 | if ($this->_initialized) { |
||
| 235 | throw new TInvalidOperationException('permissions_init_once'); |
||
| 236 | } |
||
| 237 | $this->_initialized = true; |
||
| 238 | |||
| 239 | $manager = class_exists('\WeakReference') ? \WeakReference::create($this) : $this; |
||
| 240 | TComponent::attachClassBehavior(static::PERMISSIONS_BEHAVIOR, ['class' => 'Prado\\Security\\Permissions\\TPermissionsBehavior', 'manager' => $manager], 'Prado\\Security\\Permissions\\IPermissions', -10); |
||
| 241 | TComponent::attachClassBehavior(static::USER_PERMISSIONS_BEHAVIOR, ['class' => 'Prado\\Security\\Permissions\\TUserPermissionsBehavior', 'manager' => $manager], 'Prado\\Security\\IUser', -10); |
||
| 242 | TComponent::attachClassBehavior(static::PERMISSIONS_CONFIG_BEHAVIOR, ['class' => 'Prado\\Security\\Permissions\\TPermissionsConfigurationBehavior', 'manager' => $manager], 'Prado\\Web\\Services\\TPageConfiguration', -10); |
||
| 243 | |||
| 244 | $this->loadPermissionsData($config); |
||
| 245 | if ($this->_permissionFile !== null) { |
||
| 246 | if ($this->getApplication()->getConfigurationType() == TApplication::CONFIG_TYPE_PHP) { |
||
| 247 | $userFile = include $this->_permissionFile; |
||
| 248 | $this->loadPermissionsData($userFile); |
||
| 249 | } else { |
||
| 250 | $dom = new TXmlDocument; |
||
| 251 | $dom->loadFromFile($this->_permissionFile); |
||
| 252 | $this->loadPermissionsData($dom); |
||
| 253 | } |
||
| 254 | } |
||
| 255 | if ($this->_dbParameter) { |
||
| 256 | $this->loadPermissionsData($this->_dbParameter->get($this->_parameter)); |
||
| 257 | } |
||
| 258 | |||
| 259 | foreach (array_map('strtolower', $this->getSuperRoles() ?? []) as $role) { |
||
| 260 | $this->_hierarchy[$role] = array_merge(['all'], $this->_hierarchy[$role] ?? []); |
||
| 261 | } |
||
| 262 | |||
| 263 | $app->attachEventHandler('onAuthenticationComplete', [$this, 'registerShellAction']); |
||
| 264 | |||
| 265 | parent::init($config); |
||
| 266 | } |
||
| 267 | |||
| 268 | /** |
||
| 269 | * Registers a permission name with description and preset rules. |
||
| 270 | * @param string $permissionName name of the permission |
||
| 271 | * @param string $description description of the permission |
||
| 272 | * @param null|\Prado\Security\TAuthorizationRule[] $rules |
||
| 273 | */ |
||
| 274 | public function registerPermission($permissionName, $description, $rules = null) |
||
| 275 | { |
||
| 276 | $permission = strtolower($permissionName); |
||
| 277 | $this->_descriptions[$permission] = TPropertyValue::ensureString($description); |
||
| 278 | |||
| 279 | if ($this->_autoDenyAll === true) { |
||
| 280 | $this->_autoDenyAll = 2; |
||
| 281 | $this->addPermissionRuleInternal('*', new TAuthorizationRule('deny', '*', '*', '*', '*', $this->_autoDenyAllPriority)); |
||
| 282 | } |
||
| 283 | |||
| 284 | $this->_hierarchy['all'][] = $permission; |
||
| 285 | |||
| 286 | if (!isset($this->_permissionRules[$permission])) { |
||
| 287 | $this->_permissionRules[$permission] = new TAuthorizationRuleCollection(); |
||
| 288 | } else { |
||
| 289 | throw new TInvalidOperationException('permissions_duplicate_permission', $permissionName); |
||
| 290 | } |
||
| 291 | if ($this->_autoAllowWithPermission) { |
||
| 292 | $this->_permissionRules[$permission]->add(new TAuthorizationRule('allow', '*', $permission, '*', '*', $this->_autoRulePriority)); |
||
| 293 | } |
||
| 294 | if ($this->_autoRulePresetRules && $rules) { |
||
| 295 | if (!is_array($rules)) { |
||
| 296 | $rules = [$rules]; |
||
| 297 | } |
||
| 298 | foreach ($rules as $rule) { |
||
| 299 | $this->_permissionRules[$permission]->add($rule, is_numeric($p = $rule->getPriority()) ? $p : $this->_autoRulePriority); |
||
| 300 | } |
||
| 301 | } |
||
| 302 | foreach ($this->_autoRules as $rulePerm => $rules) { |
||
| 303 | $pos = strpos($rulePerm, '*'); |
||
| 304 | if (($pos !== false && strncmp($permission, $rulePerm, $pos) === 0) || $this->isInHierarchy($rulePerm, $permission)) { |
||
| 305 | $this->_permissionRules[$permission]->mergeWith($rules); |
||
| 306 | if ($rulePerm === $permission) { |
||
| 307 | unset($this->_autoRules[$rulePerm]); |
||
| 308 | } |
||
| 309 | } |
||
| 310 | } |
||
| 311 | } |
||
| 312 | |||
| 313 | /** |
||
| 314 | * gets the short description of the permission |
||
| 315 | * @param string $permissionName name of the permission |
||
| 316 | * @return string short description of the permission |
||
| 317 | */ |
||
| 318 | public function getPermissionDescription($permissionName) |
||
| 319 | { |
||
| 320 | return $this->_descriptions[strtolower($permissionName)]; |
||
| 321 | } |
||
| 322 | |||
| 323 | /** |
||
| 324 | * Loads the roles, children, and permission rules. |
||
| 325 | * @param array|Prado\Xml\TXMLElement configurations to parse |
||
| 326 | * @param mixed $config |
||
| 327 | */ |
||
| 328 | public function loadPermissionsData($config) |
||
| 329 | { |
||
| 330 | $isXml = false; |
||
| 331 | if (!$config || empty($config)) { |
||
| 332 | return; |
||
| 333 | } |
||
| 334 | $permissions = $roles = []; |
||
| 335 | if ($config instanceof TXmlElement) { |
||
| 336 | $isXml = true; |
||
| 337 | $roles = $config->getElementsByTagName('role'); |
||
| 338 | $permissions = $config->getElementsByTagName('permissionrule'); |
||
| 339 | } elseif (is_array($config)) { |
||
| 340 | $roles = $config['roles'] ?? []; |
||
| 341 | $permissions = $config['permissionrules'] ?? []; |
||
| 342 | } |
||
| 343 | foreach ($roles as $role => $properties) { |
||
| 344 | if ($isXml) { |
||
| 345 | $properties = array_change_key_case($properties->getAttributes()->toArray()); |
||
| 346 | $role = $properties['name'] ?? ''; |
||
| 347 | $children = array_map('trim', explode(',', $properties['children'] ?? '')); |
||
| 348 | } else { |
||
| 349 | $children = $properties; |
||
| 350 | if (is_string($children)) { |
||
| 351 | $children = array_map('trim', explode(',', $children)); |
||
| 352 | } |
||
| 353 | if (!is_array($children)) { |
||
| 354 | throw new TConfigurationException('permissions_role_children_invalid', $role, is_object($children) ? get_class($children) : $children); |
||
| 355 | } |
||
| 356 | } |
||
| 357 | |||
| 358 | $role = strtolower($role); |
||
| 359 | $children = array_map('strtolower', array_filter($children)); |
||
| 360 | |||
| 361 | $this->_hierarchy[$role] = array_merge($this->_hierarchy[$role] ?? [], $children); |
||
| 362 | } |
||
| 363 | foreach ($permissions as $name => $properties) { |
||
| 364 | if ($isXml) { |
||
| 365 | $properties = array_change_key_case($properties->getAttributes()->toArray()); |
||
| 366 | } else { |
||
| 367 | if (!is_array($properties)) { |
||
| 368 | throw new TConfigurationException('permissions_rule_invalid', $name); |
||
| 369 | } |
||
| 370 | } |
||
| 371 | if (is_numeric($name) && (!isset($properties[0]) || !$properties[0] instanceof TAuthorizationRule)) { |
||
| 372 | $name = strtolower($properties['name'] ?? ''); |
||
| 373 | if (!$name) { |
||
| 374 | throw new TConfigurationException('permissions_rules_require_name'); |
||
| 375 | } |
||
| 376 | $class = $properties['class'] ?? 'Prado\\Security\\TAuthorizationRule'; |
||
| 377 | $action = $properties['action'] ?? ''; |
||
| 378 | $users = $properties['users'] ?? ''; |
||
| 379 | $roles = $properties['roles'] ?? ''; |
||
| 380 | $verb = $properties['verb'] ?? ''; |
||
| 381 | $ips = $properties['ips'] ?? ''; |
||
| 382 | $priority = $properties['priority'] ?? ''; |
||
| 383 | |||
| 384 | $rule = new $class($action, $users, $roles, $verb, $ips, $priority); |
||
| 385 | } else { |
||
| 386 | $rule = $properties; |
||
| 387 | } |
||
| 388 | $this->addPermissionRuleInternal($name, $rule); |
||
| 389 | } |
||
| 390 | } |
||
| 391 | |||
| 392 | /** |
||
| 393 | * Adds a permission rule to a permission name. Names can contain the '*' character |
||
| 394 | * and every permission with a matching name before the '*' will get the rule |
||
| 395 | * @param string $name Permission name |
||
| 396 | * @param \Prado\Security\TAuthorizationRule|\Prado\Security\TAuthorizationRule[] $rule |
||
| 397 | */ |
||
| 398 | protected function addPermissionRuleInternal($name, $rule) |
||
| 399 | { |
||
| 400 | if (!is_array($rule)) { |
||
| 401 | $rule = [$rule]; |
||
| 402 | } |
||
| 403 | if (($pos = strpos($name, '*')) !== false) { |
||
| 404 | foreach ($this->_permissionRules as $perm => $rules) { |
||
| 405 | if (strncmp($perm, $name, $pos) === 0) { |
||
| 406 | $rules->mergeWith($rule); |
||
| 407 | } |
||
| 408 | } |
||
| 409 | $this->_autoRules[$name] = array_merge($this->_autoRules[$name] ?? [], $rule); |
||
| 410 | } elseif (isset($this->_permissionRules[$name])) { |
||
| 411 | $this->_permissionRules[$name]->mergeWith($rule); |
||
| 412 | } else { |
||
| 413 | $this->_autoRules[$name] = array_merge($this->_autoRules[$name] ?? [], $rule); |
||
| 414 | } |
||
| 415 | if (isset($this->_hierarchy[$name])) { |
||
| 416 | //Push the rule down the hierarchy to any children permissions. |
||
| 417 | $set = [$name => true]; |
||
| 418 | $hierarchy = $this->_hierarchy[$name]; |
||
| 419 | while (count($hierarchy)) { |
||
| 420 | $role = array_pop($hierarchy); |
||
| 421 | if (!isset($set[$role])) { // stop recursive hierarchy and duplicate permissions |
||
| 422 | $set[$role] = true; |
||
| 423 | if (isset($this->_permissionRules[$role])) { |
||
| 424 | $this->_permissionRules[$role]->mergeWith($rule); |
||
| 425 | } |
||
| 426 | if (isset($this->_hierarchy[$role])) { |
||
| 427 | $hierarchy = array_merge($this->_hierarchy[$role], $hierarchy); |
||
| 428 | } |
||
| 429 | } |
||
| 430 | } |
||
| 431 | } |
||
| 432 | } |
||
| 433 | |||
| 434 | /** |
||
| 435 | * Removes a permission rule from a permission name. |
||
| 436 | * @param string $name |
||
| 437 | * @param \Prado\Security\TAuthorizationRule $rule |
||
| 438 | */ |
||
| 439 | protected function removePermissionRuleInternal($name, $rule) |
||
| 440 | { |
||
| 441 | if (($pos = strpos($name, '*')) !== false) { |
||
| 442 | foreach ($this->_permissionRules as $perm => $rules) { |
||
| 443 | if (strncmp($perm, $name, $pos) === 0) { |
||
| 444 | $rules->remove($rule); |
||
| 445 | } |
||
| 446 | } |
||
| 447 | } elseif (isset($this->_permissionRules[$name])) { |
||
| 448 | $this->_permissionRules[$name]->remove($rule); |
||
| 449 | } |
||
| 450 | if (isset($this->_hierarchy[$name])) { |
||
| 451 | //Push the rule down the hierarchy to any children permissions. |
||
| 452 | $set = [$name => true]; |
||
| 453 | $hierarchy = $this->_hierarchy[$name]; |
||
| 454 | while (count($hierarchy)) { |
||
| 455 | $role = array_pop($hierarchy); |
||
| 456 | if (!isset($set[$role])) { // stop recursive hierarchy and duplicate permissions |
||
| 457 | $set[$role] = true; |
||
| 458 | if (isset($this->_permissionRules[$role])) { |
||
| 459 | $this->_permissionRules[$role]->remove($rule); |
||
| 460 | } |
||
| 461 | if (isset($this->_hierarchy[$role])) { |
||
| 462 | $hierarchy = array_merge($this->_hierarchy[$role], $hierarchy); |
||
| 463 | } |
||
| 464 | } |
||
| 465 | } |
||
| 466 | } |
||
| 467 | } |
||
| 468 | |||
| 469 | /** |
||
| 470 | * @param object $sender sender of this event handler |
||
| 471 | * @param null|mixed $param parameter for the event |
||
| 472 | */ |
||
| 473 | public function registerShellAction($sender, $param) |
||
| 474 | { |
||
| 475 | if ($this->dyRegisterShellAction(false) !== true && ($app = $this->getApplication())->isa('Prado\\Shell\\TShellApplication')) { |
||
| 476 | $app->addShellActionClass(['class' => 'Prado\\Security\\Permissions\\TPermissionsAction', 'PermissionsManager' => $this]); |
||
| 477 | } |
||
| 478 | } |
||
| 479 | |||
| 480 | /** |
||
| 481 | * checks if the $permission is in the $roles hierarchy. |
||
| 482 | * @param string[] $roles the roles to check the permission |
||
| 483 | * @param string $permission the permission-role being checked for in the hierarchy |
||
| 484 | * @param &array<string, bool> $checked the roles already checked |
||
| 485 | */ |
||
| 486 | public function isInHierarchy($roles, $permission, &$checked = []) |
||
| 487 | { |
||
| 488 | if (!$roles) { |
||
| 489 | return false; |
||
| 490 | } |
||
| 491 | if (!$checked) { |
||
| 492 | if (!is_array($roles)) { |
||
| 493 | $roles = array_filter(array_map('trim', explode(',', $roles))); |
||
| 494 | } |
||
| 495 | $roles = array_map('strtolower', $roles); |
||
| 496 | $permission = strtolower($permission); |
||
| 497 | } |
||
| 498 | if (in_array($permission, $roles)) { |
||
| 499 | return true; |
||
| 500 | } |
||
| 501 | foreach ($roles as $role) { |
||
| 502 | if (!isset($checked[$role])) { |
||
| 503 | $checked[$role] = true; |
||
| 504 | if (isset($this->_hierarchy[$role]) && $this->isInHierarchy($this->_hierarchy[$role], $permission, $checked)) { |
||
| 505 | return true; |
||
| 506 | } |
||
| 507 | } |
||
| 508 | } |
||
| 509 | return false; |
||
| 510 | } |
||
| 511 | |||
| 512 | /** |
||
| 513 | * Get the roles that are runtime from the database |
||
| 514 | * @return array<string, string[]> roles and children from the database |
||
| 515 | */ |
||
| 516 | public function getDbConfigRoles() |
||
| 517 | { |
||
| 518 | if (!$this->_dbParameter || !$this->_parameter) { |
||
| 519 | return []; |
||
| 520 | } |
||
| 521 | $runtimeData = $this->_dbParameter->get($this->_parameter) ?? []; |
||
| 522 | return $runtimeData['roles'] ?? []; |
||
| 523 | } |
||
| 524 | |||
| 525 | /** |
||
| 526 | * Get the permission rules that are runtime from the database |
||
| 527 | * @return array<string, \Prado\Security\TAuthorizationRule[]> |
||
| 528 | */ |
||
| 529 | public function getDbConfigPermissionRules() |
||
| 530 | { |
||
| 531 | if (!$this->_dbParameter || !$this->_parameter) { |
||
| 532 | return []; |
||
| 533 | } |
||
| 534 | $runtimeData = $this->_dbParameter->get($this->_parameter) ?? []; |
||
| 535 | return $runtimeData['permissionrules'] ?? []; |
||
| 536 | } |
||
| 537 | |||
| 538 | /** |
||
| 539 | * This adds children to a role within the runtime context. The children |
||
| 540 | * can be a single comma separated string. |
||
| 541 | * @param string $role the role to add children |
||
| 542 | * @param string|string[] $children the children to add to the role |
||
| 543 | * @throws TInvalidDataValueException when children is not an array |
||
| 544 | * @return bool was the method successful |
||
| 545 | */ |
||
| 546 | public function addRoleChildren($role, $children) |
||
| 547 | { |
||
| 548 | if ($this->dyAddRoleChildren(false, $role, $children) === true || !$this->_dbParameter) { |
||
| 549 | return false; |
||
| 550 | } |
||
| 551 | if (is_string($children)) { |
||
| 552 | $children = array_map('trim', explode(',', $children)); |
||
| 553 | } elseif (!is_array($children)) { |
||
| 554 | throw new TInvalidDataValueException('permissions_children_invalid', is_object($children) ? get_class($children) : $children); |
||
| 555 | } |
||
| 556 | $role = strtolower($role); |
||
| 557 | $children = array_map('strtolower', array_filter($children)); |
||
| 558 | $this->_hierarchy[$role] = array_merge($this->_hierarchy[$role] ?? [], $children); |
||
| 559 | |||
| 560 | $runtimeData = $this->_dbParameter->get($this->_parameter) ?? []; |
||
| 561 | $runtimeData['roles'] = $runtimeData['roles'] ?? []; |
||
| 562 | $runtimeData['roles'][$role] = array_unique(array_merge($runtimeData['roles'][$role] ?? [], $children)); |
||
| 563 | $this->_dbParameter->set($this->_parameter, $runtimeData); |
||
| 564 | |||
| 565 | return true; |
||
| 566 | } |
||
| 567 | |||
| 568 | /** |
||
| 569 | * This removes children from a role within the runtime context. The children |
||
| 570 | * can be a single comma separated string. |
||
| 571 | * @param string $role the role to add children |
||
| 572 | * @param string|string[] $children the children to add to the role |
||
| 573 | * @throws TInvalidDataValueException when children is not an array |
||
| 574 | * @return bool was the method successful |
||
| 575 | */ |
||
| 576 | public function removeRoleChildren($role, $children) |
||
| 577 | { |
||
| 578 | if ($this->dyRemoveRoleChildren(false, $role, $children) === true || !$this->_dbParameter) { |
||
| 579 | return false; |
||
| 580 | } |
||
| 581 | if (is_string($children)) { |
||
| 582 | $children = array_map('trim', explode(',', $children)); |
||
| 583 | } elseif (!is_array($children)) { |
||
| 584 | throw new TInvalidDataValueException('permissions_children_invalid', is_object($children) ? get_class($children) : $children); |
||
| 585 | } |
||
| 586 | $role = strtolower($role); |
||
| 587 | $children = array_map('strtolower', array_filter($children)); |
||
| 588 | $this->_hierarchy[$role] = array_values(array_diff($this->_hierarchy[$role] ?? [], $children)); |
||
| 589 | if (!$this->_hierarchy[$role]) { |
||
| 590 | unset($this->_hierarchy[$role]); |
||
| 591 | } |
||
| 592 | |||
| 593 | $runtimeData = $this->_dbParameter->get($this->_parameter) ?? []; |
||
| 594 | $runtimeData['roles'][$role] = array_values(array_diff($runtimeData['roles'][$role] ?? [], $children)); |
||
| 595 | if (!$runtimeData['roles'][$role]) { |
||
| 596 | unset($runtimeData['roles'][$role]); |
||
| 597 | } |
||
| 598 | $this->_dbParameter->set($this->_parameter, $runtimeData); |
||
| 599 | return true; |
||
| 600 | } |
||
| 601 | |||
| 602 | /** |
||
| 603 | * This method adds permission rules with in the runtime context. |
||
| 604 | * @param string $permission |
||
| 605 | * @param \Prado\Security\TAuthorizationRule $rule |
||
| 606 | * @return bool was the method successful |
||
| 607 | */ |
||
| 608 | public function addPermissionRule($permission, $rule) |
||
| 609 | { |
||
| 610 | $permission = strtolower($permission); |
||
| 611 | |||
| 612 | if ($this->dyAddPermissionRule(false, $permission, $rule) === true || !$this->_dbParameter) { |
||
| 613 | return false; |
||
| 614 | } |
||
| 615 | $this->addPermissionRuleInternal($permission, $rule); |
||
| 616 | |||
| 617 | $runtimeData = $this->_dbParameter->get($this->_parameter) ?? []; |
||
| 618 | $runtimeData['permissionrules'] = $runtimeData['permissionrules'] ?? []; |
||
| 619 | $runtimeData['permissionrules'][$permission][] = $rule; |
||
| 620 | $this->_dbParameter->set($this->_parameter, $runtimeData); |
||
| 621 | |||
| 622 | return true; |
||
| 623 | } |
||
| 624 | |||
| 625 | /** |
||
| 626 | * This method removes permission rules with in the runtime context. |
||
| 627 | * @param string $permission a permission or role to remove the rule from |
||
| 628 | * @param \Prado\Security\TAuthorizationRule $rule |
||
| 629 | * @return bool was the method successful |
||
| 630 | */ |
||
| 631 | public function removePermissionRule($permission, $rule) |
||
| 632 | { |
||
| 633 | $permission = strtolower($permission); |
||
| 634 | |||
| 635 | if ($this->dyRemovePermissionRule(false, $permission, $rule) === true || !$this->_dbParameter) { |
||
| 636 | return false; |
||
| 637 | } |
||
| 638 | |||
| 639 | $this->removePermissionRuleInternal($permission, $rule); |
||
| 640 | |||
| 641 | $runtimeData = $this->_dbParameter->get($this->_parameter) ?? []; |
||
| 642 | $runtimeData['permissionrules'] = $runtimeData['permissionrules'] ?? []; |
||
| 643 | |||
| 644 | if (($index = array_search($rule, $runtimeData['permissionrules'][$permission] ?? [], true)) === false) { |
||
| 645 | return false; |
||
| 646 | } |
||
| 647 | unset($runtimeData['permissionrules'][$permission][$index]); |
||
| 648 | if (!$runtimeData['permissionrules'][$permission]) { |
||
| 649 | unset($runtimeData['permissionrules'][$permission]); |
||
| 650 | } else { |
||
| 651 | $runtimeData['permissionrules'][$permission] = array_values($runtimeData['permissionrules'][$permission]); |
||
| 652 | } |
||
| 653 | $this->_dbParameter->set($this->_parameter, $runtimeData); |
||
| 654 | |||
| 655 | return true; |
||
| 656 | } |
||
| 657 | |||
| 658 | /** |
||
| 659 | * Gets all the roles in the hierarchy, though may not be valid roles in the application. |
||
| 660 | * @return string[] the roles in the hierarchy. |
||
| 661 | */ |
||
| 662 | public function getHierarchyRoles() |
||
| 663 | { |
||
| 664 | return array_keys($this->_hierarchy); |
||
| 665 | } |
||
| 666 | |||
| 667 | /** |
||
| 668 | * Gets the children for a specific role in the hierarchy. |
||
| 669 | * @param string $role the role to return its children |
||
| 670 | * @return null|string[] the children of a specific role. |
||
| 671 | */ |
||
| 672 | public function getHierarchyRoleChildren($role) |
||
| 673 | { |
||
| 674 | if (!$role) { |
||
| 675 | return $this->_hierarchy; |
||
| 676 | } |
||
| 677 | return $this->_hierarchy[strtolower(TPropertyValue::ensureString($role))] ?? null; |
||
| 678 | } |
||
| 679 | |||
| 680 | /** |
||
| 681 | * @param null|string $permission |
||
| 682 | * @return null|array<string, TAuthorizationRuleCollection>|TAuthorizationRuleCollection |
||
| 683 | */ |
||
| 684 | public function getPermissionRules($permission) |
||
| 685 | { |
||
| 686 | if (is_string($permission)) { |
||
| 687 | return $this->_permissionRules[strtolower($permission)] ?? null; |
||
| 688 | } else { |
||
| 689 | return $this->_permissionRules; |
||
| 690 | } |
||
| 691 | } |
||
| 692 | |||
| 693 | /** |
||
| 694 | * All super roles will get "all" roles and thus all permissions on module init. |
||
| 695 | * @return null|string[] array of rolls that get all permissions |
||
| 696 | */ |
||
| 697 | public function getSuperRoles() |
||
| 698 | { |
||
| 699 | return $this->_superRoles; |
||
| 700 | } |
||
| 701 | |||
| 702 | /** |
||
| 703 | * sets the super roles to get all permissions. |
||
| 704 | * @param string|string[] $roles of rolls that get all permissions |
||
| 705 | * @throws \Prado\Exceptions\TInvalidOperationException when the module is initialized |
||
| 706 | */ |
||
| 707 | public function setSuperRoles($roles) |
||
| 716 | ; |
||
| 717 | } |
||
| 718 | |||
| 719 | /** |
||
| 720 | * Gets the default roles of all users. |
||
| 721 | * @return null|string[] the default roles of all users |
||
| 722 | */ |
||
| 723 | public function getDefaultRoles() |
||
| 724 | { |
||
| 725 | return $this->_defaultRoles; |
||
| 726 | } |
||
| 727 | |||
| 728 | /** |
||
| 729 | * @param string|string[] $roles the default roles of all users |
||
| 730 | * @throws \Prado\Exceptions\TInvalidOperationException when the module is initialized |
||
| 731 | */ |
||
| 732 | public function setDefaultRoles($roles) |
||
| 733 | { |
||
| 734 | if ($this->_initialized) { |
||
| 735 | throw new TInvalidOperationException('permissions_property_unchangeable', 'DefaultRoles'); |
||
| 736 | } |
||
| 737 | if (!is_array($roles)) { |
||
| 738 | $roles = array_filter(array_map('trim', explode(',', $roles))); |
||
| 739 | } |
||
| 740 | $this->_defaultRoles = $roles; |
||
| 741 | } |
||
| 742 | |||
| 743 | /** |
||
| 744 | * @return string the full path to the file storing role/rule information |
||
| 745 | */ |
||
| 746 | public function getPermissionFile() |
||
| 749 | } |
||
| 750 | |||
| 751 | /** |
||
| 752 | * @param string $value role/rule data file path (in namespace form). The file format is configuration format |
||
| 753 | * whose content is similar to that role/rule block in the module configuration. |
||
| 754 | * @throws \Prado\Exceptions\TInvalidOperationException if the module is already initialized |
||
| 755 | * @throws \Prado\Exceptions\TConfigurationException if the file is not in proper namespace format |
||
| 756 | */ |
||
| 757 | public function setPermissionFile($value) |
||
| 758 | { |
||
| 759 | if ($this->_initialized) { |
||
| 760 | throw new TInvalidOperationException('permissions_property_unchangeable', 'PermissionFile'); |
||
| 761 | } elseif (($this->_permissionFile = Prado::getPathOfNamespace($value, $this->getApplication()->getConfigurationFileExt())) === null || !is_file($this->_permissionFile)) { |
||
| 762 | throw new TConfigurationException('permissions_permissionfile_invalid', $value); |
||
| 763 | } |
||
| 764 | } |
||
| 765 | |||
| 766 | /** |
||
| 767 | * @return numeric the priority of Allow With Permission and Preset Rules, default 5 |
||
| 768 | */ |
||
| 769 | public function getAutoRulePriority() |
||
| 770 | { |
||
| 771 | return $this->_autoRulePriority; |
||
| 772 | } |
||
| 773 | |||
| 774 | /** |
||
| 775 | * @param numeric $priority the priority of Allow With Permission and Preset Rules |
||
| 776 | * @throws \Prado\Exceptions\TInvalidOperationException if the module is already initialized |
||
| 777 | */ |
||
| 778 | public function setAutoRulePriority($priority) |
||
| 779 | { |
||
| 780 | if ($this->_initialized) { |
||
| 781 | throw new TInvalidOperationException('permissions_property_unchangeable', 'AutoRulePriority'); |
||
| 782 | } |
||
| 783 | $this->_autoRulePriority = is_numeric($priority) ? $priority : (float) $priority; |
||
| 784 | } |
||
| 785 | |||
| 786 | /** |
||
| 787 | * @return bool enable Allow With Permission rule, default true |
||
| 788 | */ |
||
| 789 | public function getAutoAllowWithPermission() |
||
| 790 | { |
||
| 791 | return $this->_autoAllowWithPermission; |
||
| 792 | } |
||
| 793 | |||
| 794 | /** |
||
| 795 | * @param bool $enable enable Allow With Permission rule |
||
| 796 | * @throws \Prado\Exceptions\TInvalidOperationException if the module is already initialized |
||
| 797 | */ |
||
| 798 | public function setAutoAllowWithPermission($enable) |
||
| 799 | { |
||
| 800 | if ($this->_initialized) { |
||
| 801 | throw new TInvalidOperationException('permissions_property_unchangeable', 'AutoAllowWithPermission'); |
||
| 802 | } |
||
| 803 | $this->_autoAllowWithPermission = TPropertyValue::ensureBoolean($enable); |
||
| 804 | } |
||
| 805 | |||
| 806 | /** |
||
| 807 | * @return bool enable Module Rules, default true |
||
| 808 | */ |
||
| 809 | public function getAutoPresetRules() |
||
| 810 | { |
||
| 811 | return $this->_autoRulePresetRules; |
||
| 812 | } |
||
| 813 | |||
| 814 | /** |
||
| 815 | * @param bool $enable the priority of Allow With Permission |
||
| 816 | * @throws \Prado\Exceptions\TInvalidOperationException if the module is already initialized |
||
| 817 | */ |
||
| 818 | public function setAutoPresetRules($enable) |
||
| 819 | { |
||
| 820 | if ($this->_initialized) { |
||
| 821 | throw new TInvalidOperationException('permissions_property_unchangeable', 'AutoPresetRules'); |
||
| 822 | } |
||
| 823 | $this->_autoRulePresetRules = TPropertyValue::ensureBoolean($enable); |
||
| 824 | } |
||
| 825 | |||
| 826 | /** |
||
| 827 | * @return bool the priority of Allow With Permission, default true |
||
| 828 | */ |
||
| 829 | public function getAutoDenyAll() |
||
| 832 | } |
||
| 833 | |||
| 834 | /** |
||
| 835 | * @param bool $enable the priority of Allow With Permission |
||
| 836 | * @throws \Prado\Exceptions\TInvalidOperationException if the module is already initialized |
||
| 837 | */ |
||
| 838 | public function setAutoDenyAll($enable) |
||
| 844 | } |
||
| 845 | |||
| 846 | /** |
||
| 847 | * @return numeric the priority of Deny All rule, default 999999 |
||
| 848 | */ |
||
| 849 | public function getAutoDenyAllPriority() |
||
| 850 | { |
||
| 851 | return $this->_autoDenyAllPriority; |
||
| 852 | } |
||
| 853 | |||
| 854 | /** |
||
| 855 | * @param numeric $priority the priority of Deny All rule |
||
| 856 | * @throws \Prado\Exceptions\TInvalidOperationException if the module is already initialized |
||
| 857 | */ |
||
| 858 | public function setAutoDenyAllPriority($priority) |
||
| 864 | } |
||
| 865 | |||
| 866 | /** |
||
| 867 | * @return Prado\Util\TDbParameterModule DbParameter instance |
||
| 868 | */ |
||
| 869 | public function getDbParameter() |
||
| 870 | { |
||
| 871 | return $this->_dbParameter; |
||
| 872 | } |
||
| 873 | |||
| 874 | /** |
||
| 875 | * @param IUserManager|string $provider the user manager module ID or the DbParameter object |
||
| 876 | * @throws \Prado\Exceptions\TInvalidOperationException if the module is already initialized |
||
| 877 | * @throws \Prado\Exceptions\TConfigurationException if the $provider is not a TDbParameterModule |
||
| 878 | */ |
||
| 879 | public function setDbParameter($provider) |
||
| 880 | { |
||
| 881 | if ($this->_initialized) { |
||
| 882 | throw new TInvalidOperationException('permissions_property_unchangeable', 'DbParameter'); |
||
| 883 | } |
||
| 884 | if ($provider !== null && !is_string($provider) && !($provider instanceof TDbParameterModule)) { |
||
| 885 | throw new TConfigurationException('permissions_dbparameter_invalid', is_object($provider) ? get_class($provider) : $provider); |
||
| 886 | } |
||
| 887 | $this->_dbParameter = $provider; |
||
| 888 | } |
||
| 889 | |||
| 890 | /** |
||
| 891 | * @return string name of the parameter to load |
||
| 892 | */ |
||
| 893 | public function getLoadParameter() |
||
| 896 | } |
||
| 897 | |||
| 898 | /** |
||
| 899 | * @param string $value name of the parameter to load |
||
| 900 | * @throws \Prado\Exceptions\TInvalidOperationException if the module is already initialized |
||
| 901 | */ |
||
| 902 | public function setLoadParameter($value) |
||
| 903 | { |
||
| 904 | if ($this->_initialized) { |
||
| 905 | throw new TInvalidOperationException('permissions_property_unchangeable', 'LoadParameter'); |
||
| 906 | } |
||
| 908 | } |
||
| 909 | |||
| 910 | /** |
||
| 911 | * detaches the automatic class behaviors |
||
| 912 | */ |
||
| 913 | public function __destruct() |
||
| 914 | { |
||
| 915 | TComponent::detachClassBehavior(static::PERMISSIONS_BEHAVIOR, 'Prado\\Security\\Permissions\\IPermissions'); |
||
| 916 | TComponent::detachClassBehavior(static::USER_PERMISSIONS_BEHAVIOR, 'Prado\\Security\\IUser'); |
||
| 917 | TComponent::detachClassBehavior(static::PERMISSIONS_CONFIG_BEHAVIOR, 'Prado\\Web\\Services\\TPageConfiguration'); |
||
| 918 | parent::__destruct(); |
||
| 919 | } |
||
| 920 | } |
||
| 921 |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths