1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* TPermissionsManager class file |
5
|
|
|
* |
6
|
|
|
* @author Brad Anderson <[email protected]> |
7
|
|
|
* @link https://github.com/pradosoft/prado |
8
|
|
|
* @license https://github.com/pradosoft/prado/blob/master/LICENSE |
9
|
|
|
*/ |
10
|
|
|
|
11
|
|
|
namespace Prado\Security\Permissions; |
12
|
|
|
|
13
|
|
|
use Prado\Exceptions\TConfigurationException; |
14
|
|
|
use Prado\Exceptions\TInvalidOperationException; |
15
|
|
|
use Prado\Exceptions\TInvalidDataValueException; |
16
|
|
|
use Prado\Prado; |
17
|
|
|
use Prado\Security\TAuthorizationRule; |
18
|
|
|
use Prado\Security\TAuthorizationRuleCollection; |
19
|
|
|
use Prado\TApplication; |
20
|
|
|
use Prado\TComponent; |
21
|
|
|
use Prado\TPropertyValue; |
22
|
|
|
use Prado\Util\TDbParameterModule; |
23
|
|
|
use Prado\Xml\TXmlDocument; |
24
|
|
|
use Prado\Xml\TXmlElement; |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* TPermissionsManager class. |
28
|
|
|
* |
29
|
|
|
* TPermissionsManager handles Permissions authorization and Roll Based |
30
|
|
|
* Access Control (RBAC). Each registered Permission is given a set of |
31
|
|
|
* {@see \Prado\Security\TAuthorizationRule}s. The RBAC is based on roles |
32
|
|
|
* having children roles and permissions, with permissions being thought of |
33
|
|
|
* as special roles themselves. |
34
|
|
|
* |
35
|
|
|
* TPermissionsManager attaches {@see \Prado\Security\Permissions\TPermissionsBehavior} to all classes |
36
|
|
|
* that implement {@see \Prado\Security\Permissions\IPermissions}. This is the main mechanism |
37
|
|
|
* by which application permissions are registered. |
38
|
|
|
* |
39
|
|
|
* The role hierarchy and permission rules are unique to each application. The |
40
|
|
|
* permissions configuration is defined in the TPermissionsManager application |
41
|
|
|
* configuration or in a separate {@see PermissionsFile}. {@see \Prado\Security\Permissions\TPermissionsConfigurationBehavior} |
42
|
|
|
* enables a page configuration to have Permission Configurations as well. |
43
|
|
|
* A {@see \Prado\Util\TDbParameterModule} can be specified with {@see getDbParameter} for |
44
|
|
|
* loading dynamic roles and permissions. |
45
|
|
|
* |
46
|
|
|
* Module XML configurations (and similarly PermissionFile) follows the format, eg: |
47
|
|
|
* ```xml |
48
|
|
|
* <module id="permissions" class="Prado\Security\Permissions\TPermissionsManager" DefaultRoles="Default" SuperRoles="Administrator"> |
49
|
|
|
* <role name="Developer" children="all, param_shell_permission, cron" /> |
50
|
|
|
* <role name="Manager" children="editor, change_user_role_permission, cron_shell" /> |
51
|
|
|
* <role name="cron_shell" children="cron_add_task, cron_update_task, cron_remove_task" /> |
52
|
|
|
* <role name="cron" children="cron_shell, cron_manage_log, cron_add_task, cron_update_task, cron_remove_task" /> |
53
|
|
|
* <role name="Default" children="register_user, blog_read_posts, blog_comment"> |
54
|
|
|
* <permissionrule name="param_shell_permission" action="deny" users="*" roles="" verb="*" IPs="" /> |
55
|
|
|
* <permissionrule name="cron_shell" action="allow" users="*" roles="Developer,cron_shell,cron_manage_log" verb="*" IPs="" /> |
56
|
|
|
* <permissionrule name="register_user" action="allow" users="?" /> |
57
|
|
|
* <permissionrule name="register_user" action="allow" roles="Manager" /> |
58
|
|
|
* <permissionrule name="change_profile" action="deny" users="?" priority="0" /> |
59
|
|
|
* <permissionrule name="blog_update_posts" class="Prado\Security\Permissions\TUserOwnerRule" Priority="5" /> |
60
|
|
|
* <permissionrule name="cron" action="allow" users="admin, user1, user2" roles="*" verb="*" IPs="*" /> |
61
|
|
|
* <permissionrule name="blog_*" action="allow" users="admin, user1, user2" roles="*" verb="*" IPs="*" /> |
62
|
|
|
* <permissionrule name="*" action="deny" priority="1000" /> |
63
|
|
|
* </module> |
64
|
|
|
* ``` |
65
|
|
|
* |
66
|
|
|
* and in PHP the same file would follow the following format, eg: |
67
|
|
|
* ```php |
68
|
|
|
* 'modules' => [ |
69
|
|
|
* 'permissions' => ['class' => 'Prado\Security\Permissions\TPermissionsManager', |
70
|
|
|
* 'properties' => ['DefaultRoles' => 'Default', 'SuperRoles' => "Administrator"], |
71
|
|
|
* 'roles' => [ |
72
|
|
|
* 'Developer' => ['all', 'param_shell_permission', 'cron'], |
73
|
|
|
* 'Manager' => ['editor', 'change_user_role_permission', 'cron_shell'], |
74
|
|
|
* 'cron_shell' => ['cron_add_task', 'cron_update_task', 'cron_remove_task'], |
75
|
|
|
* 'cron' => ['cron_shell', 'cron_manage_log', 'cron_add_task', 'cron_update_task', 'cron_remove_task'], |
76
|
|
|
* 'Default' => ['register_user', 'blog_read_posts', 'blog_comment'], |
77
|
|
|
* ], |
78
|
|
|
* 'permissionRules' => [ |
79
|
|
|
* [name => 'param_shell_permission', 'action' => 'deny', 'users' => '*', roles => '*', 'verb' => '*', 'IPs' =>''], |
80
|
|
|
* [name => 'cron_shell', 'action' => 'allow', 'users' => 'Developer,cron_shell,cron_manage_log', roles => 'cron_shell', 'verb' => '*', 'IPs' =>''], |
81
|
|
|
* [name => 'register_user', 'action' => 'allow', 'users' => '?'], |
82
|
|
|
* [name => 'register_user', 'action' => 'allow', 'roles' => 'Manager'], |
83
|
|
|
* [name => 'change_profile', 'action' => 'deny', 'users' => '?', 'priority' => '0'], |
84
|
|
|
* [name => 'blog_update_posts', 'class' => 'Prado\Security\Permissions\TUserOwnerRule', 'priority' => '5'], |
85
|
|
|
* [name => 'cron', 'action' => 'allow', 'users' => 'admin, user1, user2'], |
86
|
|
|
* [name => 'blog_*', 'action' => 'allow', 'users' => 'admin, user1, user2'], |
87
|
|
|
* [name => '*', 'action' => 'deny', 'priority' => 1000] |
88
|
|
|
* ] |
89
|
|
|
* ] |
90
|
|
|
* ``` |
91
|
|
|
* |
92
|
|
|
* In this example, "cron" is not a permission, but when used as a permission, |
93
|
|
|
* all children roles/permissions will receive the rule. Permissions with children, |
94
|
|
|
* such as 'cron_shell' (above), will give all its children the rule as |
95
|
|
|
* well. |
96
|
|
|
* |
97
|
|
|
* A special role "All" is automatically created to contain all the permissions. |
98
|
|
|
* Specifying "all" as a child, is the same as specifying a role as a super role |
99
|
|
|
* via {@see setSuperRoles}. |
100
|
|
|
* |
101
|
|
|
* All users get the roles specified by {@see getDefaultRoles}. This changes |
102
|
|
|
* the default Prado behavior for guest users having no roles. |
103
|
|
|
* |
104
|
|
|
* Intermediate roles, that are not defined in the user system, may be defined in |
105
|
|
|
* the hierarchy, in the above example the "cron" role is not defined by the system, |
106
|
|
|
* but is defined in the role hierarchy. |
107
|
|
|
* |
108
|
|
|
* Permission Rules can have multiple rules. they are |
109
|
|
|
* ordered by natural specified configuration order unless the rule property |
110
|
|
|
* {@see \Prado\Security\TAuthorizationRule::setPriority} is set. |
111
|
|
|
* |
112
|
|
|
* Permissions authorization rules may use the '*' or 'perm_*' to add the rules to all |
113
|
|
|
* matching permission names. Anything before the * is matched as a permission. |
114
|
|
|
* This does not traverse the hierarchy roles matching the name, just the permissions |
115
|
|
|
* are matched for the TAuthorizationRule. |
116
|
|
|
* |
117
|
|
|
* A permission name must list itself as a role in TAuthorizationRule for the user to be |
118
|
|
|
* validated for that permission name for authorization. This is handled automatically |
119
|
|
|
* by TPermissionManager with the {@see getAutoAllowWithPermission} property. |
120
|
|
|
* By default getAutoAllowWithPermission is true, and allows any user with |
121
|
|
|
* that permission in their hierarchy to allow access to the functionality. |
122
|
|
|
* This rule priority can be set with {@see getAutoRulePriority}, |
123
|
|
|
* where the default is 5, and -thus- before user defined rules. |
124
|
|
|
* |
125
|
|
|
* The second automatic rules includes Modules have their own preset rules that can |
126
|
|
|
* be automatically added via {@see getAutoPresetRules}. By default this |
127
|
|
|
* is true. These rules typically allow owners of the data to be permitted without having |
128
|
|
|
* a permission-role. Preset rules can define their own priorities but those |
129
|
|
|
* without set priorities receive the priority from {@see getAutoRulePriority}. |
130
|
|
|
* |
131
|
|
|
* The third, and last, auto-Rule is the final {@see getAutoDenyAll DenyAll} |
132
|
|
|
* rule. This is the last rule that denies all by default. The AutoDenyAll |
133
|
|
|
* gets its rule priority from {@see getAutoDenyAllPriority}. By default, |
134
|
|
|
* deny all to all permissions is enabled and thus blocking all permissions. |
135
|
|
|
* |
136
|
|
|
* Recursive hierarchy is gracefully handled, in case of any loop structures. |
137
|
|
|
* |
138
|
|
|
* When TPermissionsManager is a module in your app, there are three permissions |
139
|
|
|
* to control user access to its function: |
140
|
|
|
* - TPermissionsManager::PERM_PERMISSIONS_SHELL 'permissions_shell' enables the shell commands. |
141
|
|
|
* - TPermissionsManager::PERM_PERMISSIONS_MANAGE_ROLES 'permissions_manage_roles' enables adding and removing roles and children. |
142
|
|
|
* - TPermissionsManager::PERM_PERMISSIONS_MANAGE_RULES 'permissions_manage_rules' enables adding and removing rules for permissions and roles. |
143
|
|
|
* |
144
|
|
|
* The role and rule management functions only work when the TDbParameter Module is specified. |
145
|
|
|
* The following gives user "admin" and all users with "Administrators" role the |
146
|
|
|
* permission to access permissions shell and its full functionality: |
147
|
|
|
* ```php |
148
|
|
|
* <role name="permissions_shell" children="permissions_manage_roles, permissions_manage_rules" /> |
149
|
|
|
* <permissionrule name="permissions_shell" action="allow" users="admin" /> |
150
|
|
|
* <permissionrule name="permissions_shell" action="allow" roles="Administrators" /> |
151
|
|
|
* ```php |
152
|
|
|
* |
153
|
|
|
* @author Brad Anderson <[email protected]> |
154
|
|
|
* @method bool dyRegisterShellAction($returnValue) |
155
|
|
|
* @method bool dyAddRoleChildren(bool $return, string $role, string[] $children) |
156
|
|
|
* @method bool dyRemoveRoleChildren(bool $return, string $role, string[] $children) |
157
|
|
|
* @method bool dyAddPermissionRule(bool $return, string $permission, \Prado\Security\TAuthorizationRule $rule) |
158
|
|
|
* @method bool dyRemovePermissionRule(bool $return, string $permission, \Prado\Security\TAuthorizationRule $rule) |
159
|
|
|
* @since 4.2.0 |
160
|
|
|
*/ |
161
|
|
|
class TPermissionsManager extends \Prado\TModule implements IPermissions |
162
|
|
|
{ |
163
|
|
|
public const PERMISSIONS_BEHAVIOR = 'permissions'; |
164
|
|
|
|
165
|
|
|
public const USER_PERMISSIONS_BEHAVIOR = 'usercan'; |
166
|
|
|
|
167
|
|
|
public const PERMISSIONS_CONFIG_BEHAVIOR = 'permissionsConfig'; |
168
|
|
|
|
169
|
|
|
public const PERM_PERMISSIONS_SHELL = 'permissions_shell'; |
170
|
|
|
|
171
|
|
|
public const PERM_PERMISSIONS_MANAGE_ROLES = 'permissions_manage_roles'; |
172
|
|
|
|
173
|
|
|
public const PERM_PERMISSIONS_MANAGE_RULES = 'permissions_manage_rules'; |
174
|
|
|
|
175
|
|
|
/** @var string[] roles that get all permissions, default [] */ |
176
|
|
|
private $_superRoles; |
177
|
|
|
|
178
|
|
|
/** @var string[] Default roles to give all users, default [] */ |
179
|
|
|
private $_defaultRoles; |
180
|
|
|
|
181
|
|
|
/** @var array<string, \Prado\Security\TAuthorizationRuleCollection> contains the rules for each permission */ |
182
|
|
|
private $_permissionRules = []; |
183
|
|
|
|
184
|
|
|
/** @var array<string, string> contains the short descriptions for each permission */ |
185
|
|
|
private $_descriptions = []; |
186
|
|
|
|
187
|
|
|
/** @var array<string, \Prado\Security\TAuthorizationRule[]> the rules to apply to newly registered Permissions */ |
188
|
|
|
private $_autoRules = []; |
189
|
|
|
|
190
|
|
|
/** @var array<string, string[]> contains the hierarchy of roles and children roles/permissions */ |
191
|
|
|
private $_hierarchy = []; |
192
|
|
|
|
193
|
|
|
/** @var bool is the module initialized */ |
194
|
|
|
private $_initialized = false; |
195
|
|
|
|
196
|
|
|
/** @var string role hierarchy and permission rules information file */ |
197
|
|
|
private $_permissionFile; |
198
|
|
|
|
199
|
|
|
/** @var numeric the priority of the Allow With Permission Rule, default 5 */ |
|
|
|
|
200
|
|
|
private $_autoRulePriority = 5; |
201
|
|
|
|
202
|
|
|
/** @var bool add allow users with permission-role, default true */ |
203
|
|
|
private $_autoAllowWithPermission = true; |
204
|
|
|
|
205
|
|
|
/** @var bool add module rules, allows User's data, default true */ |
206
|
|
|
private $_autoRulePresetRules = true; |
207
|
|
|
|
208
|
|
|
/** @var bool add Deny All rule to every permissions as the last rule, default true */ |
209
|
|
|
private $_autoDenyAll = true; |
210
|
|
|
|
211
|
|
|
/** @var numeric the priority of the module Rule, usually these are Allow User As Owner, default 1000000 */ |
212
|
|
|
private $_autoDenyAllPriority = 1000000; |
213
|
|
|
|
214
|
|
|
/** @var \Prado\Util\TDbParameterModule the database module providing runtime roles and rules */ |
215
|
|
|
private $_dbParameter; |
216
|
|
|
|
217
|
|
|
/** @var numeric the priority of the module Rule, usually these are Allow User As Owner */ |
218
|
|
|
private $_parameter = 'configuration:TPermissionsManager:runtime'; |
219
|
|
|
|
220
|
|
|
/** |
221
|
|
|
* @returtn ?TPermissionsManager The PermissionsManager for the application. |
222
|
|
|
*/ |
223
|
|
|
public static function getManager(): ?TPermissionsManager |
224
|
|
|
{ |
225
|
|
|
$app = Prado::getApplication(); |
226
|
|
|
if ($app) { |
227
|
|
|
$modules = $app->getModulesByType(self::class); |
228
|
|
|
if (count($modules)) { |
229
|
|
|
return array_values($modules)[0]; |
230
|
|
|
} |
231
|
|
|
} |
232
|
|
|
return null; |
233
|
|
|
} |
234
|
|
|
|
235
|
|
|
/** |
236
|
|
|
* @param \Prado\Security\Permissions\TPermissionsManager $manager |
237
|
|
|
* @return TPermissionEvent[] the dynamic events to have authorization |
238
|
|
|
*/ |
239
|
|
|
public function getPermissions($manager) |
240
|
|
|
{ |
241
|
|
|
return [ |
242
|
|
|
new TPermissionEvent(static::PERM_PERMISSIONS_SHELL, 'Activates permissions shell commands.', 'dyRegisterShellAction'), |
243
|
|
|
new TPermissionEvent(static::PERM_PERMISSIONS_MANAGE_ROLES, 'Manages Db Permissions Role Children.', ['dyAddRoleChildren', 'dyRemoveRoleChildren']), |
244
|
|
|
new TPermissionEvent(static::PERM_PERMISSIONS_MANAGE_RULES, 'Manages Db Permissions Rules.', ['dyAddPermissionRule', 'dyRemovePermissionRule']), |
245
|
|
|
]; |
246
|
|
|
} |
247
|
|
|
|
248
|
|
|
/** |
249
|
|
|
* @param array|TXmlElement $config the application configuration |
250
|
|
|
*/ |
251
|
|
|
public function init($config) |
252
|
|
|
{ |
253
|
|
|
$app = $this->getApplication(); |
254
|
|
|
if (is_string($this->_dbParameter)) { |
|
|
|
|
255
|
|
|
if (($dbParameter = $app->getModule($this->_dbParameter)) === null) { |
256
|
|
|
throw new TConfigurationException('permissions_dbparameter_nonexistent', $this->_dbParameter); |
257
|
|
|
} |
258
|
|
|
if (!($dbParameter instanceof TDbParameterModule)) { |
259
|
|
|
throw new TConfigurationException('permissions_dbparameter_invalid', $this->_dbParameter); |
260
|
|
|
} |
261
|
|
|
$this->_dbParameter = $dbParameter; |
262
|
|
|
} |
263
|
|
|
|
264
|
|
|
if ($this->_initialized) { |
265
|
|
|
throw new TInvalidOperationException('permissions_init_once'); |
266
|
|
|
} |
267
|
|
|
$this->_initialized = true; |
268
|
|
|
|
269
|
|
|
$manager = \WeakReference::create($this); |
270
|
|
|
TComponent::attachClassBehavior(static::PERMISSIONS_BEHAVIOR, ['class' => TPermissionsBehavior::class, 'permissionsmanager' => $manager], IPermissions::class, -10); |
|
|
|
|
271
|
|
|
TComponent::attachClassBehavior(static::USER_PERMISSIONS_BEHAVIOR, ['class' => TUserPermissionsBehavior::class, 'permissionsmanager' => $manager], \Prado\Security\IUser::class, -10); |
272
|
|
|
TComponent::attachClassBehavior(static::PERMISSIONS_CONFIG_BEHAVIOR, ['class' => TPermissionsConfigurationBehavior::class, 'permissionsmanager' => $manager], \Prado\Web\Services\TPageConfiguration::class, -10); |
273
|
|
|
|
274
|
|
|
$this->loadPermissionsData($config); |
275
|
|
|
if ($this->_permissionFile !== null) { |
276
|
|
|
if ($this->getApplication()->getConfigurationType() == TApplication::CONFIG_TYPE_PHP) { |
277
|
|
|
$userFile = include $this->_permissionFile; |
278
|
|
|
$this->loadPermissionsData($userFile); |
279
|
|
|
} else { |
280
|
|
|
$dom = new TXmlDocument(); |
281
|
|
|
$dom->loadFromFile($this->_permissionFile); |
282
|
|
|
$this->loadPermissionsData($dom); |
283
|
|
|
} |
284
|
|
|
} |
285
|
|
|
if ($this->_dbParameter) { |
286
|
|
|
$this->loadPermissionsData($this->_dbParameter->get($this->_parameter)); |
287
|
|
|
} |
288
|
|
|
|
289
|
|
|
foreach (array_map('strtolower', $this->getSuperRoles() ?? []) as $role) { |
290
|
|
|
$this->_hierarchy[$role] = array_merge(['all'], $this->_hierarchy[$role] ?? []); |
291
|
|
|
} |
292
|
|
|
|
293
|
|
|
$app->attachEventHandler('onAuthenticationComplete', [$this, 'registerShellAction']); |
294
|
|
|
|
295
|
|
|
parent::init($config); |
|
|
|
|
296
|
|
|
} |
297
|
|
|
|
298
|
|
|
/** |
299
|
|
|
* Registers a permission name with description and preset rules. |
300
|
|
|
* @param string $permissionName name of the permission |
301
|
|
|
* @param string $description description of the permission |
302
|
|
|
* @param null|\Prado\Security\TAuthorizationRule[] $rules |
303
|
|
|
*/ |
304
|
|
|
public function registerPermission($permissionName, $description, $rules = null) |
305
|
|
|
{ |
306
|
|
|
$permission = strtolower($permissionName); |
307
|
|
|
$this->_descriptions[$permission] = TPropertyValue::ensureString($description); |
308
|
|
|
|
309
|
|
|
if ($this->_autoDenyAll === true) { |
310
|
|
|
$this->_autoDenyAll = 2; |
|
|
|
|
311
|
|
|
$this->addPermissionRuleInternal('*', new TAuthorizationRule('deny', '*', '*', '*', '*', $this->_autoDenyAllPriority)); |
312
|
|
|
} |
313
|
|
|
|
314
|
|
|
$this->_hierarchy['all'][] = $permission; |
315
|
|
|
|
316
|
|
|
if (!isset($this->_permissionRules[$permission])) { |
317
|
|
|
$this->_permissionRules[$permission] = new TAuthorizationRuleCollection(); |
318
|
|
|
} else { |
319
|
|
|
throw new TInvalidOperationException('permissions_duplicate_permission', $permissionName); |
320
|
|
|
} |
321
|
|
|
if ($this->_autoAllowWithPermission) { |
322
|
|
|
$this->_permissionRules[$permission]->add(new TAuthorizationRule('allow', '*', $permission, '*', '*', $this->_autoRulePriority)); |
323
|
|
|
} |
324
|
|
|
if ($this->_autoRulePresetRules && $rules) { |
325
|
|
|
if (!is_array($rules)) { |
|
|
|
|
326
|
|
|
$rules = [$rules]; |
327
|
|
|
} |
328
|
|
|
foreach ($rules as $rule) { |
329
|
|
|
$this->_permissionRules[$permission]->add($rule, is_numeric($p = $rule->getPriority()) ? $p : $this->_autoRulePriority); |
330
|
|
|
} |
331
|
|
|
} |
332
|
|
|
foreach ($this->_autoRules as $rulePerm => $rules) { |
333
|
|
|
$pos = strpos($rulePerm, '*'); |
334
|
|
|
if (($pos !== false && strncmp($permission, $rulePerm, $pos) === 0) || $this->isInHierarchy($rulePerm, $permission)) { |
|
|
|
|
335
|
|
|
$this->_permissionRules[$permission]->mergeWith($rules); |
336
|
|
|
if ($rulePerm === $permission) { |
337
|
|
|
unset($this->_autoRules[$rulePerm]); |
338
|
|
|
} |
339
|
|
|
} |
340
|
|
|
} |
341
|
|
|
} |
342
|
|
|
|
343
|
|
|
/** |
344
|
|
|
* gets the short description of the permission |
345
|
|
|
* @param string $permissionName name of the permission |
346
|
|
|
* @return string short description of the permission |
347
|
|
|
*/ |
348
|
|
|
public function getPermissionDescription($permissionName) |
349
|
|
|
{ |
350
|
|
|
return $this->_descriptions[strtolower($permissionName)]; |
351
|
|
|
} |
352
|
|
|
|
353
|
|
|
/** |
354
|
|
|
* Loads the roles, children, and permission rules. |
355
|
|
|
* @param array|\Prado\Xml\TXmlElement $config configurations to parse |
356
|
|
|
*/ |
357
|
|
|
public function loadPermissionsData($config) |
358
|
|
|
{ |
359
|
|
|
$isXml = false; |
360
|
|
|
if (!$config) { |
361
|
|
|
return; |
362
|
|
|
} |
363
|
|
|
$permissions = $roles = []; |
364
|
|
|
if ($config instanceof TXmlElement) { |
365
|
|
|
$isXml = true; |
366
|
|
|
$roles = $config->getElementsByTagName('role'); |
367
|
|
|
$permissions = $config->getElementsByTagName('permissionrule'); |
368
|
|
|
} elseif (is_array($config)) { |
|
|
|
|
369
|
|
|
$roles = $config['roles'] ?? []; |
370
|
|
|
$permissions = $config['permissionrules'] ?? []; |
371
|
|
|
} |
372
|
|
|
foreach ($roles as $role => $properties) { |
373
|
|
|
if ($isXml) { |
374
|
|
|
$properties = array_change_key_case($properties->getAttributes()->toArray()); |
375
|
|
|
$role = $properties['name'] ?? ''; |
376
|
|
|
$children = array_map('trim', explode(',', $properties['children'] ?? '')); |
377
|
|
|
} else { |
378
|
|
|
$children = $properties; |
379
|
|
|
if (is_string($children)) { |
380
|
|
|
$children = array_map('trim', explode(',', $children)); |
381
|
|
|
} |
382
|
|
|
if (!is_array($children)) { |
383
|
|
|
throw new TConfigurationException('permissions_role_children_invalid', $role, is_object($children) ? $children::class : $children); |
384
|
|
|
} |
385
|
|
|
} |
386
|
|
|
|
387
|
|
|
$role = strtolower($role); |
388
|
|
|
$children = array_map('strtolower', array_filter($children)); |
389
|
|
|
|
390
|
|
|
$this->_hierarchy[$role] = array_merge($this->_hierarchy[$role] ?? [], $children); |
391
|
|
|
} |
392
|
|
|
foreach ($permissions as $name => $properties) { |
393
|
|
|
if ($isXml) { |
394
|
|
|
$properties = array_change_key_case($properties->getAttributes()->toArray()); |
395
|
|
|
} else { |
396
|
|
|
if (!is_array($properties)) { |
397
|
|
|
throw new TConfigurationException('permissions_rule_invalid', $name); |
398
|
|
|
} |
399
|
|
|
} |
400
|
|
|
if (is_numeric($name) && (!isset($properties[0]) || !$properties[0] instanceof TAuthorizationRule)) { |
401
|
|
|
$name = strtolower($properties['name'] ?? ''); |
402
|
|
|
if (!$name) { |
403
|
|
|
throw new TConfigurationException('permissions_rules_require_name'); |
404
|
|
|
} |
405
|
|
|
$class = $properties['class'] ?? TAuthorizationRule::class; |
406
|
|
|
$action = $properties['action'] ?? ''; |
407
|
|
|
$users = $properties['users'] ?? ''; |
408
|
|
|
$roles = $properties['roles'] ?? ''; |
409
|
|
|
$verb = $properties['verb'] ?? ''; |
410
|
|
|
$ips = $properties['ips'] ?? ''; |
411
|
|
|
$priority = $properties['priority'] ?? ''; |
412
|
|
|
|
413
|
|
|
$rule = new $class($action, $users, $roles, $verb, $ips, $priority); |
414
|
|
|
} else { |
415
|
|
|
$rule = $properties; |
416
|
|
|
} |
417
|
|
|
$this->addPermissionRuleInternal($name, $rule); |
418
|
|
|
} |
419
|
|
|
} |
420
|
|
|
|
421
|
|
|
/** |
422
|
|
|
* Adds a permission rule to a permission name. Names can contain the '*' character |
423
|
|
|
* and every permission with a matching name before the '*' will get the rule |
424
|
|
|
* @param string $name Permission name |
425
|
|
|
* @param \Prado\Security\TAuthorizationRule|\Prado\Security\TAuthorizationRule[] $rule |
426
|
|
|
*/ |
427
|
|
|
protected function addPermissionRuleInternal($name, $rule) |
428
|
|
|
{ |
429
|
|
|
if (!is_array($rule)) { |
430
|
|
|
$rule = [$rule]; |
431
|
|
|
} |
432
|
|
|
if (($pos = strpos($name, '*')) !== false) { |
433
|
|
|
foreach ($this->_permissionRules as $perm => $rules) { |
434
|
|
|
if (strncmp($perm, $name, $pos) === 0) { |
435
|
|
|
$rules->mergeWith($rule); |
436
|
|
|
} |
437
|
|
|
} |
438
|
|
|
$this->_autoRules[$name] = array_merge($this->_autoRules[$name] ?? [], $rule); |
439
|
|
|
} elseif (isset($this->_permissionRules[$name])) { |
440
|
|
|
$this->_permissionRules[$name]->mergeWith($rule); |
441
|
|
|
} else { |
442
|
|
|
$this->_autoRules[$name] = array_merge($this->_autoRules[$name] ?? [], $rule); |
443
|
|
|
} |
444
|
|
|
if (isset($this->_hierarchy[$name])) { |
445
|
|
|
//Push the rule down the hierarchy to any children permissions. |
446
|
|
|
$set = [$name => true]; |
447
|
|
|
$hierarchy = $this->_hierarchy[$name]; |
448
|
|
|
while (count($hierarchy)) { |
449
|
|
|
$role = array_pop($hierarchy); |
450
|
|
|
if (!isset($set[$role])) { // stop recursive hierarchy and duplicate permissions |
451
|
|
|
$set[$role] = true; |
452
|
|
|
if (isset($this->_permissionRules[$role])) { |
453
|
|
|
$this->_permissionRules[$role]->mergeWith($rule); |
454
|
|
|
} |
455
|
|
|
if (isset($this->_hierarchy[$role])) { |
456
|
|
|
$hierarchy = array_merge($this->_hierarchy[$role], $hierarchy); |
457
|
|
|
} |
458
|
|
|
} |
459
|
|
|
} |
460
|
|
|
} |
461
|
|
|
} |
462
|
|
|
|
463
|
|
|
/** |
464
|
|
|
* Removes a permission rule from a permission name. |
465
|
|
|
* @param string $name |
466
|
|
|
* @param \Prado\Security\TAuthorizationRule $rule |
467
|
|
|
*/ |
468
|
|
|
protected function removePermissionRuleInternal($name, $rule) |
469
|
|
|
{ |
470
|
|
|
if (($pos = strpos($name, '*')) !== false) { |
471
|
|
|
foreach ($this->_permissionRules as $perm => $rules) { |
472
|
|
|
if (strncmp($perm, $name, $pos) === 0) { |
473
|
|
|
$rules->remove($rule); |
474
|
|
|
} |
475
|
|
|
} |
476
|
|
|
} elseif (isset($this->_permissionRules[$name])) { |
477
|
|
|
$this->_permissionRules[$name]->remove($rule); |
478
|
|
|
} |
479
|
|
|
if (isset($this->_hierarchy[$name])) { |
480
|
|
|
//Push the rule down the hierarchy to any children permissions. |
481
|
|
|
$set = [$name => true]; |
482
|
|
|
$hierarchy = $this->_hierarchy[$name]; |
483
|
|
|
while (count($hierarchy)) { |
484
|
|
|
$role = array_pop($hierarchy); |
485
|
|
|
if (!isset($set[$role])) { // stop recursive hierarchy and duplicate permissions |
486
|
|
|
$set[$role] = true; |
487
|
|
|
if (isset($this->_permissionRules[$role])) { |
488
|
|
|
$this->_permissionRules[$role]->remove($rule); |
489
|
|
|
} |
490
|
|
|
if (isset($this->_hierarchy[$role])) { |
491
|
|
|
$hierarchy = array_merge($this->_hierarchy[$role], $hierarchy); |
492
|
|
|
} |
493
|
|
|
} |
494
|
|
|
} |
495
|
|
|
} |
496
|
|
|
} |
497
|
|
|
|
498
|
|
|
/** |
499
|
|
|
* @param object $sender sender of this event handler |
500
|
|
|
* @param null|mixed $param parameter for the event |
501
|
|
|
*/ |
502
|
|
|
public function registerShellAction($sender, $param) |
|
|
|
|
503
|
|
|
{ |
504
|
|
|
if ($this->dyRegisterShellAction(false) !== true && ($app = $this->getApplication()) instanceof \Prado\Shell\TShellApplication) { |
505
|
|
|
$app->addShellActionClass(['class' => TPermissionsAction::class, 'PermissionsManager' => $this]); |
|
|
|
|
506
|
|
|
} |
507
|
|
|
} |
508
|
|
|
|
509
|
|
|
/** |
510
|
|
|
* checks if the $permission is in the $roles hierarchy. |
511
|
|
|
* @param string[] $roles the roles to check the permission |
512
|
|
|
* @param string $permission the permission-role being checked for in the hierarchy |
513
|
|
|
* @param array<string, bool> &$checked the roles already checked |
514
|
|
|
*/ |
515
|
|
|
public function isInHierarchy($roles, $permission, &$checked = []) |
516
|
|
|
{ |
517
|
|
|
if (!$roles) { |
|
|
|
|
518
|
|
|
return false; |
519
|
|
|
} |
520
|
|
|
if (!$checked) { |
521
|
|
|
if (!is_array($roles)) { |
|
|
|
|
522
|
|
|
$roles = array_filter(array_map('trim', explode(',', $roles))); |
523
|
|
|
} |
524
|
|
|
$roles = array_map('strtolower', $roles); |
525
|
|
|
$permission = strtolower($permission); |
526
|
|
|
} |
527
|
|
|
if (in_array($permission, $roles)) { |
528
|
|
|
return true; |
529
|
|
|
} |
530
|
|
|
foreach ($roles as $role) { |
531
|
|
|
if (!isset($checked[$role])) { |
532
|
|
|
$checked[$role] = true; |
533
|
|
|
if (isset($this->_hierarchy[$role]) && $this->isInHierarchy($this->_hierarchy[$role], $permission, $checked)) { |
534
|
|
|
return true; |
535
|
|
|
} |
536
|
|
|
} |
537
|
|
|
} |
538
|
|
|
return false; |
539
|
|
|
} |
540
|
|
|
|
541
|
|
|
/** |
542
|
|
|
* Get the roles that are runtime from the database |
543
|
|
|
* @return array<string, string[]> roles and children from the database |
544
|
|
|
*/ |
545
|
|
|
public function getDbConfigRoles() |
546
|
|
|
{ |
547
|
|
|
if (!$this->_dbParameter || !$this->_parameter) { |
548
|
|
|
return []; |
549
|
|
|
} |
550
|
|
|
$runtimeData = $this->_dbParameter->get($this->_parameter) ?? []; |
551
|
|
|
return $runtimeData['roles'] ?? []; |
552
|
|
|
} |
553
|
|
|
|
554
|
|
|
/** |
555
|
|
|
* Get the permission rules that are runtime from the database |
556
|
|
|
* @return array<string, \Prado\Security\TAuthorizationRule[]> |
557
|
|
|
*/ |
558
|
|
|
public function getDbConfigPermissionRules() |
559
|
|
|
{ |
560
|
|
|
if (!$this->_dbParameter || !$this->_parameter) { |
561
|
|
|
return []; |
562
|
|
|
} |
563
|
|
|
$runtimeData = $this->_dbParameter->get($this->_parameter) ?? []; |
564
|
|
|
return $runtimeData['permissionrules'] ?? []; |
565
|
|
|
} |
566
|
|
|
|
567
|
|
|
/** |
568
|
|
|
* This adds children to a role within the runtime context. The children |
569
|
|
|
* can be a single comma separated string. |
570
|
|
|
* @param string $role the role to add children |
571
|
|
|
* @param string|string[] $children the children to add to the role |
572
|
|
|
* @throws TInvalidDataValueException when children is not an array |
573
|
|
|
* @return bool was the method successful |
574
|
|
|
*/ |
575
|
|
|
public function addRoleChildren($role, $children) |
576
|
|
|
{ |
577
|
|
|
if ($this->dyAddRoleChildren(false, $role, $children) === true || !$this->_dbParameter) { |
|
|
|
|
578
|
|
|
return false; |
579
|
|
|
} |
580
|
|
|
if (is_string($children)) { |
581
|
|
|
$children = array_map('trim', explode(',', $children)); |
582
|
|
|
} elseif (!is_array($children)) { |
|
|
|
|
583
|
|
|
throw new TInvalidDataValueException('permissions_children_invalid', is_object($children) ? $children::class : $children); |
584
|
|
|
} |
585
|
|
|
$role = strtolower($role); |
586
|
|
|
$children = array_map('strtolower', array_filter($children)); |
587
|
|
|
$this->_hierarchy[$role] = array_merge($this->_hierarchy[$role] ?? [], $children); |
588
|
|
|
|
589
|
|
|
$runtimeData = $this->_dbParameter->get($this->_parameter) ?? []; |
590
|
|
|
$runtimeData['roles'] ??= []; |
591
|
|
|
$runtimeData['roles'][$role] = array_unique(array_merge($runtimeData['roles'][$role] ?? [], $children)); |
592
|
|
|
$this->_dbParameter->set($this->_parameter, $runtimeData); |
593
|
|
|
|
594
|
|
|
return true; |
595
|
|
|
} |
596
|
|
|
|
597
|
|
|
/** |
598
|
|
|
* This removes children from a role within the runtime context. The children |
599
|
|
|
* can be a single comma separated string. |
600
|
|
|
* @param string $role the role to add children |
601
|
|
|
* @param string|string[] $children the children to add to the role |
602
|
|
|
* @throws TInvalidDataValueException when children is not an array |
603
|
|
|
* @return bool was the method successful |
604
|
|
|
*/ |
605
|
|
|
public function removeRoleChildren($role, $children) |
606
|
|
|
{ |
607
|
|
|
if ($this->dyRemoveRoleChildren(false, $role, $children) === true || !$this->_dbParameter) { |
|
|
|
|
608
|
|
|
return false; |
609
|
|
|
} |
610
|
|
|
if (is_string($children)) { |
611
|
|
|
$children = array_map('trim', explode(',', $children)); |
612
|
|
|
} elseif (!is_array($children)) { |
|
|
|
|
613
|
|
|
throw new TInvalidDataValueException('permissions_children_invalid', is_object($children) ? $children::class : $children); |
614
|
|
|
} |
615
|
|
|
$role = strtolower($role); |
616
|
|
|
$children = array_map('strtolower', array_filter($children)); |
617
|
|
|
$this->_hierarchy[$role] = array_values(array_diff($this->_hierarchy[$role] ?? [], $children)); |
618
|
|
|
if (!$this->_hierarchy[$role]) { |
619
|
|
|
unset($this->_hierarchy[$role]); |
620
|
|
|
} |
621
|
|
|
|
622
|
|
|
$runtimeData = $this->_dbParameter->get($this->_parameter) ?? []; |
623
|
|
|
$runtimeData['roles'][$role] = array_values(array_diff($runtimeData['roles'][$role] ?? [], $children)); |
624
|
|
|
if (!$runtimeData['roles'][$role]) { |
625
|
|
|
unset($runtimeData['roles'][$role]); |
626
|
|
|
} |
627
|
|
|
$this->_dbParameter->set($this->_parameter, $runtimeData); |
628
|
|
|
return true; |
629
|
|
|
} |
630
|
|
|
|
631
|
|
|
/** |
632
|
|
|
* This method adds permission rules with in the runtime context. |
633
|
|
|
* @param string $permission |
634
|
|
|
* @param \Prado\Security\TAuthorizationRule $rule |
635
|
|
|
* @return bool was the method successful |
636
|
|
|
*/ |
637
|
|
|
public function addPermissionRule($permission, $rule) |
638
|
|
|
{ |
639
|
|
|
$permission = strtolower($permission); |
640
|
|
|
|
641
|
|
|
if ($this->dyAddPermissionRule(false, $permission, $rule) === true || !$this->_dbParameter) { |
642
|
|
|
return false; |
643
|
|
|
} |
644
|
|
|
$this->addPermissionRuleInternal($permission, $rule); |
645
|
|
|
|
646
|
|
|
$runtimeData = $this->_dbParameter->get($this->_parameter) ?? []; |
647
|
|
|
$runtimeData['permissionrules'] ??= []; |
648
|
|
|
$runtimeData['permissionrules'][$permission][] = $rule; |
649
|
|
|
$this->_dbParameter->set($this->_parameter, $runtimeData); |
650
|
|
|
|
651
|
|
|
return true; |
652
|
|
|
} |
653
|
|
|
|
654
|
|
|
/** |
655
|
|
|
* This method removes permission rules with in the runtime context. |
656
|
|
|
* @param string $permission a permission or role to remove the rule from |
657
|
|
|
* @param \Prado\Security\TAuthorizationRule $rule |
658
|
|
|
* @return bool was the method successful |
659
|
|
|
*/ |
660
|
|
|
public function removePermissionRule($permission, $rule) |
661
|
|
|
{ |
662
|
|
|
$permission = strtolower($permission); |
663
|
|
|
|
664
|
|
|
if ($this->dyRemovePermissionRule(false, $permission, $rule) === true || !$this->_dbParameter) { |
665
|
|
|
return false; |
666
|
|
|
} |
667
|
|
|
|
668
|
|
|
$this->removePermissionRuleInternal($permission, $rule); |
669
|
|
|
|
670
|
|
|
$runtimeData = $this->_dbParameter->get($this->_parameter) ?? []; |
671
|
|
|
$runtimeData['permissionrules'] ??= []; |
672
|
|
|
|
673
|
|
|
if (($index = array_search($rule, $runtimeData['permissionrules'][$permission] ?? [], true)) === false) { |
674
|
|
|
return false; |
675
|
|
|
} |
676
|
|
|
unset($runtimeData['permissionrules'][$permission][$index]); |
677
|
|
|
if (!$runtimeData['permissionrules'][$permission]) { |
678
|
|
|
unset($runtimeData['permissionrules'][$permission]); |
679
|
|
|
} else { |
680
|
|
|
$runtimeData['permissionrules'][$permission] = array_values($runtimeData['permissionrules'][$permission]); |
681
|
|
|
} |
682
|
|
|
$this->_dbParameter->set($this->_parameter, $runtimeData); |
683
|
|
|
|
684
|
|
|
return true; |
685
|
|
|
} |
686
|
|
|
|
687
|
|
|
/** |
688
|
|
|
* Gets all the roles in the hierarchy, though may not be valid roles in the application. |
689
|
|
|
* @return string[] the roles in the hierarchy. |
690
|
|
|
*/ |
691
|
|
|
public function getHierarchyRoles() |
692
|
|
|
{ |
693
|
|
|
return array_keys($this->_hierarchy); |
694
|
|
|
} |
695
|
|
|
|
696
|
|
|
/** |
697
|
|
|
* Gets the children for a specific role in the hierarchy. |
698
|
|
|
* @param string $role the role to return its children |
699
|
|
|
* @return null|string[] the children of a specific role. |
700
|
|
|
*/ |
701
|
|
|
public function getHierarchyRoleChildren($role) |
702
|
|
|
{ |
703
|
|
|
if (!$role) { |
704
|
|
|
return $this->_hierarchy; |
|
|
|
|
705
|
|
|
} |
706
|
|
|
return $this->_hierarchy[strtolower(TPropertyValue::ensureString($role))] ?? null; |
707
|
|
|
} |
708
|
|
|
|
709
|
|
|
/** |
710
|
|
|
* @param null|string $permission |
711
|
|
|
* @return null|array<string, TAuthorizationRuleCollection>|TAuthorizationRuleCollection |
712
|
|
|
*/ |
713
|
|
|
public function getPermissionRules($permission) |
714
|
|
|
{ |
715
|
|
|
if (is_string($permission)) { |
716
|
|
|
return $this->_permissionRules[strtolower($permission)] ?? null; |
717
|
|
|
} else { |
718
|
|
|
return $this->_permissionRules; |
719
|
|
|
} |
720
|
|
|
} |
721
|
|
|
|
722
|
|
|
/** |
723
|
|
|
* All super roles will get "all" roles and thus all permissions on module init. |
724
|
|
|
* @return null|string[] array of rolls that get all permissions |
725
|
|
|
*/ |
726
|
|
|
public function getSuperRoles() |
727
|
|
|
{ |
728
|
|
|
return $this->_superRoles; |
729
|
|
|
} |
730
|
|
|
|
731
|
|
|
/** |
732
|
|
|
* sets the super roles to get all permissions. |
733
|
|
|
* @param string|string[] $roles of rolls that get all permissions |
734
|
|
|
* @throws \Prado\Exceptions\TInvalidOperationException when the module is initialized |
735
|
|
|
*/ |
736
|
|
|
public function setSuperRoles($roles) |
737
|
|
|
{ |
738
|
|
|
if ($this->_initialized) { |
739
|
|
|
throw new TInvalidOperationException('permissions_property_unchangeable', 'SuperRoles'); |
740
|
|
|
} |
741
|
|
|
if (!is_array($roles)) { |
742
|
|
|
$roles = array_map('trim', explode(',', $roles)); |
743
|
|
|
} |
744
|
|
|
$this->_superRoles = array_filter($roles); |
745
|
|
|
; |
746
|
|
|
} |
747
|
|
|
|
748
|
|
|
/** |
749
|
|
|
* Gets the default roles of all users. |
750
|
|
|
* @return null|string[] the default roles of all users |
751
|
|
|
*/ |
752
|
|
|
public function getDefaultRoles() |
753
|
|
|
{ |
754
|
|
|
return $this->_defaultRoles; |
755
|
|
|
} |
756
|
|
|
|
757
|
|
|
/** |
758
|
|
|
* @param string|string[] $roles the default roles of all users |
759
|
|
|
* @throws \Prado\Exceptions\TInvalidOperationException when the module is initialized |
760
|
|
|
*/ |
761
|
|
|
public function setDefaultRoles($roles) |
762
|
|
|
{ |
763
|
|
|
if ($this->_initialized) { |
764
|
|
|
throw new TInvalidOperationException('permissions_property_unchangeable', 'DefaultRoles'); |
765
|
|
|
} |
766
|
|
|
if (!is_array($roles)) { |
767
|
|
|
$roles = array_filter(array_map('trim', explode(',', $roles))); |
768
|
|
|
} |
769
|
|
|
$this->_defaultRoles = $roles; |
770
|
|
|
} |
771
|
|
|
|
772
|
|
|
/** |
773
|
|
|
* @return string the full path to the file storing role/rule information |
774
|
|
|
*/ |
775
|
|
|
public function getPermissionFile() |
776
|
|
|
{ |
777
|
|
|
return $this->_permissionFile; |
778
|
|
|
} |
779
|
|
|
|
780
|
|
|
/** |
781
|
|
|
* @param string $value role/rule data file path (in namespace form). The file format is configuration format |
782
|
|
|
* whose content is similar to that role/rule block in the module configuration. |
783
|
|
|
* @throws \Prado\Exceptions\TInvalidOperationException if the module is already initialized |
784
|
|
|
* @throws \Prado\Exceptions\TConfigurationException if the file is not in proper namespace format |
785
|
|
|
*/ |
786
|
|
|
public function setPermissionFile($value) |
787
|
|
|
{ |
788
|
|
|
if ($this->_initialized) { |
789
|
|
|
throw new TInvalidOperationException('permissions_property_unchangeable', 'PermissionFile'); |
790
|
|
|
} elseif (($this->_permissionFile = Prado::getPathOfNamespace($value, $this->getApplication()->getConfigurationFileExt())) === null || !is_file($this->_permissionFile)) { |
791
|
|
|
throw new TConfigurationException('permissions_permissionfile_invalid', $value); |
792
|
|
|
} |
793
|
|
|
} |
794
|
|
|
|
795
|
|
|
/** |
796
|
|
|
* @return numeric the priority of Allow With Permission and Preset Rules, default 5 |
797
|
|
|
*/ |
798
|
|
|
public function getAutoRulePriority() |
799
|
|
|
{ |
800
|
|
|
return $this->_autoRulePriority; |
801
|
|
|
} |
802
|
|
|
|
803
|
|
|
/** |
804
|
|
|
* @param numeric $priority the priority of Allow With Permission and Preset Rules |
805
|
|
|
* @throws \Prado\Exceptions\TInvalidOperationException if the module is already initialized |
806
|
|
|
*/ |
807
|
|
|
public function setAutoRulePriority($priority) |
808
|
|
|
{ |
809
|
|
|
if ($this->_initialized) { |
810
|
|
|
throw new TInvalidOperationException('permissions_property_unchangeable', 'AutoRulePriority'); |
811
|
|
|
} |
812
|
|
|
$this->_autoRulePriority = is_numeric($priority) ? $priority : (float) $priority; |
|
|
|
|
813
|
|
|
} |
814
|
|
|
|
815
|
|
|
/** |
816
|
|
|
* @return bool enable Allow With Permission rule, default true |
817
|
|
|
*/ |
818
|
|
|
public function getAutoAllowWithPermission() |
819
|
|
|
{ |
820
|
|
|
return $this->_autoAllowWithPermission; |
821
|
|
|
} |
822
|
|
|
|
823
|
|
|
/** |
824
|
|
|
* @param bool $enable enable Allow With Permission rule |
825
|
|
|
* @throws \Prado\Exceptions\TInvalidOperationException if the module is already initialized |
826
|
|
|
*/ |
827
|
|
|
public function setAutoAllowWithPermission($enable) |
828
|
|
|
{ |
829
|
|
|
if ($this->_initialized) { |
830
|
|
|
throw new TInvalidOperationException('permissions_property_unchangeable', 'AutoAllowWithPermission'); |
831
|
|
|
} |
832
|
|
|
$this->_autoAllowWithPermission = TPropertyValue::ensureBoolean($enable); |
833
|
|
|
} |
834
|
|
|
|
835
|
|
|
/** |
836
|
|
|
* @return bool enable Module Rules, default true |
837
|
|
|
*/ |
838
|
|
|
public function getAutoPresetRules() |
839
|
|
|
{ |
840
|
|
|
return $this->_autoRulePresetRules; |
841
|
|
|
} |
842
|
|
|
|
843
|
|
|
/** |
844
|
|
|
* @param bool $enable the priority of Allow With Permission |
845
|
|
|
* @throws \Prado\Exceptions\TInvalidOperationException if the module is already initialized |
846
|
|
|
*/ |
847
|
|
|
public function setAutoPresetRules($enable) |
848
|
|
|
{ |
849
|
|
|
if ($this->_initialized) { |
850
|
|
|
throw new TInvalidOperationException('permissions_property_unchangeable', 'AutoPresetRules'); |
851
|
|
|
} |
852
|
|
|
$this->_autoRulePresetRules = TPropertyValue::ensureBoolean($enable); |
853
|
|
|
} |
854
|
|
|
|
855
|
|
|
/** |
856
|
|
|
* @return bool the priority of Allow With Permission, default true |
857
|
|
|
*/ |
858
|
|
|
public function getAutoDenyAll() |
859
|
|
|
{ |
860
|
|
|
return $this->_autoDenyAll > 0; |
861
|
|
|
} |
862
|
|
|
|
863
|
|
|
/** |
864
|
|
|
* @param bool $enable the priority of Allow With Permission |
865
|
|
|
* @throws \Prado\Exceptions\TInvalidOperationException if the module is already initialized |
866
|
|
|
*/ |
867
|
|
|
public function setAutoDenyAll($enable) |
868
|
|
|
{ |
869
|
|
|
if ($this->_initialized) { |
870
|
|
|
throw new TInvalidOperationException('permissions_property_unchangeable', 'AutoDenyAll'); |
871
|
|
|
} |
872
|
|
|
$this->_autoDenyAll = TPropertyValue::ensureBoolean($enable); |
873
|
|
|
} |
874
|
|
|
|
875
|
|
|
/** |
876
|
|
|
* @return numeric the priority of Deny All rule, default 999999 |
877
|
|
|
*/ |
878
|
|
|
public function getAutoDenyAllPriority() |
879
|
|
|
{ |
880
|
|
|
return $this->_autoDenyAllPriority; |
881
|
|
|
} |
882
|
|
|
|
883
|
|
|
/** |
884
|
|
|
* @param numeric $priority the priority of Deny All rule |
885
|
|
|
* @throws \Prado\Exceptions\TInvalidOperationException if the module is already initialized |
886
|
|
|
*/ |
887
|
|
|
public function setAutoDenyAllPriority($priority) |
888
|
|
|
{ |
889
|
|
|
if ($this->_initialized) { |
890
|
|
|
throw new TInvalidOperationException('permissions_property_unchangeable', 'AutoDenyAllPriority'); |
891
|
|
|
} |
892
|
|
|
$this->_autoDenyAllPriority = is_numeric($priority) ? $priority : (float) $priority; |
|
|
|
|
893
|
|
|
} |
894
|
|
|
|
895
|
|
|
/** |
896
|
|
|
* @return \Prado\Util\TDbParameterModule DbParameter instance |
897
|
|
|
*/ |
898
|
|
|
public function getDbParameter() |
899
|
|
|
{ |
900
|
|
|
return $this->_dbParameter; |
901
|
|
|
} |
902
|
|
|
|
903
|
|
|
/** |
904
|
|
|
* @param \Prado\Security\IUserManager|string $provider the user manager module ID or the DbParameter object |
905
|
|
|
* @throws \Prado\Exceptions\TInvalidOperationException if the module is already initialized |
906
|
|
|
* @throws \Prado\Exceptions\TConfigurationException if the $provider is not a TDbParameterModule |
907
|
|
|
*/ |
908
|
|
|
public function setDbParameter($provider) |
909
|
|
|
{ |
910
|
|
|
if ($this->_initialized) { |
911
|
|
|
throw new TInvalidOperationException('permissions_property_unchangeable', 'DbParameter'); |
912
|
|
|
} |
913
|
|
|
if ($provider !== null && !is_string($provider) && !($provider instanceof TDbParameterModule)) { |
914
|
|
|
throw new TConfigurationException('permissions_dbparameter_invalid', is_object($provider) ? $provider::class : $provider); |
915
|
|
|
} |
916
|
|
|
$this->_dbParameter = $provider; |
|
|
|
|
917
|
|
|
} |
918
|
|
|
|
919
|
|
|
/** |
920
|
|
|
* @return string name of the parameter to load |
921
|
|
|
*/ |
922
|
|
|
public function getLoadParameter() |
923
|
|
|
{ |
924
|
|
|
return $this->_parameter; |
925
|
|
|
} |
926
|
|
|
|
927
|
|
|
/** |
928
|
|
|
* @param string $value name of the parameter to load |
929
|
|
|
* @throws \Prado\Exceptions\TInvalidOperationException if the module is already initialized |
930
|
|
|
*/ |
931
|
|
|
public function setLoadParameter($value) |
932
|
|
|
{ |
933
|
|
|
if ($this->_initialized) { |
934
|
|
|
throw new TInvalidOperationException('permissions_property_unchangeable', 'LoadParameter'); |
935
|
|
|
} |
936
|
|
|
$this->_parameter = $value; |
|
|
|
|
937
|
|
|
} |
938
|
|
|
|
939
|
|
|
/** |
940
|
|
|
* detaches the automatic class behaviors |
941
|
|
|
*/ |
942
|
|
|
public function __destruct() |
943
|
|
|
{ |
944
|
|
|
TComponent::detachClassBehavior(static::PERMISSIONS_BEHAVIOR, IPermissions::class); |
945
|
|
|
TComponent::detachClassBehavior(static::USER_PERMISSIONS_BEHAVIOR, \Prado\Security\IUser::class); |
946
|
|
|
TComponent::detachClassBehavior(static::PERMISSIONS_CONFIG_BEHAVIOR, \Prado\Web\Services\TPageConfiguration::class); |
947
|
|
|
parent::__destruct(); |
948
|
|
|
} |
949
|
|
|
} |
950
|
|
|
|
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