77
88namespace Magento \Authorization \Model \Acl \Loader ;
99
10+ use Magento \Framework \Acl ;
1011use Magento \Framework \Acl \Data \CacheInterface ;
1112use Magento \Framework \Acl \LoaderInterface ;
1213use Magento \Framework \Acl \RootResource ;
@@ -21,7 +22,12 @@ class Rule implements LoaderInterface
2122 /**
2223 * Rules array cache key
2324 */
24- const ACL_RULE_CACHE_KEY = 'authorization_rule_cached_data ' ;
25+ public const ACL_RULE_CACHE_KEY = 'authorization_rule_cached_data ' ;
26+
27+ /**
28+ * Allow everything resource id
29+ */
30+ private const ALLOW_EVERYTHING = 'Magento_Backend::all ' ;
2531
2632 /**
2733 * @var ResourceConnection
@@ -75,27 +81,74 @@ public function __construct(
7581 /**
7682 * Populate ACL with rules from external storage
7783 *
78- * @param \Magento\Framework\ Acl $acl
84+ * @param Acl $acl
7985 * @return void
8086 */
81- public function populateAcl (\ Magento \ Framework \ Acl $ acl )
87+ public function populateAcl (Acl $ acl )
8288 {
89+ $ result = $ this ->applyPermissionsAccordingToRules ($ acl );
90+ $ this ->applyDenyPermissionsForMissingRules ($ acl , ...$ result );
91+ }
92+
93+ /**
94+ * Apply ACL with rules
95+ *
96+ * @param Acl $acl
97+ * @return array[]
98+ */
99+ private function applyPermissionsAccordingToRules (Acl $ acl ): array
100+ {
101+ $ foundResources = $ foundDeniedRoles = [];
83102 foreach ($ this ->getRulesArray () as $ rule ) {
84103 $ role = $ rule ['role_id ' ];
85104 $ resource = $ rule ['resource_id ' ];
86105 $ privileges = !empty ($ rule ['privileges ' ]) ? explode (', ' , $ rule ['privileges ' ]) : null ;
87106
88107 if ($ acl ->has ($ resource )) {
108+ $ foundResources [$ resource ] = $ resource ;
89109 if ($ rule ['permission ' ] == 'allow ' ) {
90110 if ($ resource === $ this ->_rootResource ->getId ()) {
91111 $ acl ->allow ($ role , null , $ privileges );
92112 }
93113 $ acl ->allow ($ role , $ resource , $ privileges );
94114 } elseif ($ rule ['permission ' ] == 'deny ' ) {
115+ $ foundDeniedRoles [$ role ] = $ role ;
95116 $ acl ->deny ($ role , $ resource , $ privileges );
96117 }
97118 }
98119 }
120+ return [$ foundResources , $ foundDeniedRoles ];
121+ }
122+
123+ /**
124+ * Apply deny permissions for missing rules
125+ *
126+ * For all rules that were not regenerated in authorization_rule table,
127+ * when adding a new module and without re-saving all roles,
128+ * consider not present rules with deny permissions
129+ *
130+ * @param Acl $acl
131+ * @param array $resources
132+ * @param array $deniedRoles
133+ * @return void
134+ */
135+ private function applyDenyPermissionsForMissingRules (
136+ Acl $ acl ,
137+ array $ resources ,
138+ array $ deniedRoles
139+ ) {
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+ }
149+ }
150+ }
151+ }
99152 }
100153
101154 /**
0 commit comments