Skip to content

Commit ad71f7a

Browse files
committed
ACP2E-3503: Automatic enabling of new ACL permissions
1 parent 5184c06 commit ad71f7a

File tree

1 file changed

+51
-23
lines changed
  • app/code/Magento/Authorization/Model/Acl/Loader

1 file changed

+51
-23
lines changed

app/code/Magento/Authorization/Model/Acl/Loader/Rule.php

Lines changed: 51 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?php
22
/**
3-
* Copyright © Magento, Inc. All rights reserved.
4-
* See COPYING.txt for license details.
3+
* Copyright 2012 Adobe
4+
* All Rights Reserved.
55
*/
66
declare(strict_types=1);
77

@@ -87,7 +87,7 @@ public function __construct(
8787
public function populateAcl(Acl $acl)
8888
{
8989
$result = $this->applyPermissionsAccordingToRules($acl);
90-
$this->applyDenyPermissionsForMissingRules($acl, ...$result);
90+
$this->denyPermissionsForMissingRules($acl, $result);
9191
}
9292

9393
/**
@@ -98,56 +98,84 @@ public function populateAcl(Acl $acl)
9898
*/
9999
private function applyPermissionsAccordingToRules(Acl $acl): array
100100
{
101-
$foundResources = $foundDeniedRoles = [];
101+
$appliedRolePermissionsPerResource = [];
102102
foreach ($this->getRulesArray() as $rule) {
103103
$role = $rule['role_id'];
104104
$resource = $rule['resource_id'];
105105
$privileges = !empty($rule['privileges']) ? explode(',', $rule['privileges']) : null;
106106

107107
if ($acl->hasResource($resource)) {
108-
$foundResources[$resource] = $resource;
108+
109+
$appliedRolePermissionsPerResource[$resource]['allow'] =
110+
$appliedRolePermissionsPerResource[$resource]['allow'] ?? [];
111+
$appliedRolePermissionsPerResource[$resource]['deny'] =
112+
$appliedRolePermissionsPerResource[$resource]['deny'] ?? [];
113+
109114
if ($rule['permission'] == 'allow') {
110115
if ($resource === $this->_rootResource->getId()) {
111116
$acl->allow($role, null, $privileges);
112117
}
113118
$acl->allow($role, $resource, $privileges);
119+
$appliedRolePermissionsPerResource[$resource]['allow'][] = $role;
114120
} elseif ($rule['permission'] == 'deny') {
115-
$foundDeniedRoles[$role] = $role;
116121
$acl->deny($role, $resource, $privileges);
122+
$appliedRolePermissionsPerResource[$resource]['deny'][] = $role;
117123
}
118124
}
119125
}
120-
return [$foundResources, $foundDeniedRoles];
126+
127+
return $appliedRolePermissionsPerResource;
121128
}
122129

123130
/**
124-
* Apply deny permissions for missing rules
131+
* Deny permissions for missing rules
125132
*
126133
* For all rules that were not regenerated in authorization_rule table,
127134
* when adding a new module and without re-saving all roles,
128135
* consider not present rules with deny permissions
129136
*
130137
* @param Acl $acl
131-
* @param array $resources
132-
* @param array $deniedRoles
138+
* @param array $appliedRolePermissionsPerResource
133139
* @return void
134140
*/
135-
private function applyDenyPermissionsForMissingRules(
136-
Acl $acl,
137-
array $resources,
138-
array $deniedRoles
141+
private function denyPermissionsForMissingRules(
142+
Acl $acl,
143+
array $appliedRolePermissionsPerResource,
139144
) {
140-
if (count($resources) && count($deniedRoles)
141-
//ignore denying missing permission if all are allowed
142-
&& !(count($resources) === 1 && isset($resources[static::ALLOW_EVERYTHING]))
143-
) {
144-
foreach ($acl->getResources() as $resource) {
145-
if (!isset($resources[$resource])) {
146-
foreach ($deniedRoles as $role) {
147-
$acl->deny($role, $resource, null);
148-
}
145+
$consolidatedDeniedRoleIds = array_unique(
146+
array_merge(
147+
...array_column($appliedRolePermissionsPerResource, 'deny')
148+
)
149+
);
150+
151+
$hasAppliedPermissions = count($appliedRolePermissionsPerResource) > 0;
152+
$hasDeniedRoles = count($consolidatedDeniedRoleIds) > 0;
153+
$allAllowed = count($appliedRolePermissionsPerResource) === 1
154+
&& isset($appliedRolePermissionsPerResource[static::ALLOW_EVERYTHING]);
155+
156+
if ($hasAppliedPermissions && $hasDeniedRoles && !$allAllowed) {
157+
// Add the resources that are not present in the rules at all,
158+
// assuming that they must be denied for all roles by default
159+
$resourcesUndefinedInAuthorizationRules =
160+
array_diff($acl->getResources(), array_keys($appliedRolePermissionsPerResource));
161+
$assumeDeniedRoleListPerResource =
162+
array_fill_keys($resourcesUndefinedInAuthorizationRules, $consolidatedDeniedRoleIds);
163+
164+
// Add the resources that are permitted for one role and not present in others at all,
165+
// assuming that they must be denied for all other roles by default
166+
foreach ($appliedRolePermissionsPerResource as $resource => $permissions) {
167+
$allowedRoles = $permissions['allow'];
168+
$deniedRoles = $permissions['deny'];
169+
$assumedDeniedRoles = array_diff($consolidatedDeniedRoleIds, $allowedRoles, $deniedRoles);
170+
if ($assumedDeniedRoles) {
171+
$assumeDeniedRoleListPerResource[$resource] = $assumedDeniedRoles;
149172
}
150173
}
174+
175+
// Deny permissions for missing rules
176+
foreach ($assumeDeniedRoleListPerResource as $resource => $denyRoles) {
177+
$acl->deny($denyRoles, $resource, null);
178+
}
151179
}
152180
}
153181

0 commit comments

Comments
 (0)