Skip to content

Commit fef3090

Browse files
committed
Fix incorrectly inheriting permissions.
When child inherits from a deny parent the '*' permission should reflect permissions on all nodes not just the leaf node. Previously once a node with all permissions set to inherit was found, the check would pass. Instead it should cascade to the parent nodes and look for explicit allow/deny. Refs #8450
1 parent 18b0334 commit fef3090

File tree

2 files changed

+29
-10
lines changed

2 files changed

+29
-10
lines changed

lib/Cake/Model/Permission.php

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -129,19 +129,18 @@ public function check($aro, $aco, $action = '*') {
129129
$perms = Hash::extract($perms, '{n}.' . $this->alias);
130130
foreach ($perms as $perm) {
131131
if ($action === '*') {
132+
if (empty($perm)) {
133+
continue;
134+
}
132135
foreach ($permKeys as $key) {
133-
if (!empty($perm)) {
134-
if ($perm[$key] == -1) {
135-
return false;
136-
} elseif ($perm[$key] == 1 || $perm[$key] == 0) {
137-
$inherited[$key] = $perm[$key];
138-
}
136+
if ($perm[$key] == -1 && !(isset($inherited[$key]) && $inherited[$key] == 1)) {
137+
// Deny, but only if a child node didnt't explicitly allow
138+
return false;
139+
} elseif ($perm[$key] == 1) {
140+
// Allow & inherit from parent nodes
141+
$inherited[$key] = $perm[$key];
139142
}
140143
}
141-
142-
if (count($inherited) === count($permKeys)) {
143-
return true;
144-
}
145144
} else {
146145
switch ($perm['_' . $action]) {
147146
case -1:
@@ -153,6 +152,10 @@ public function check($aro, $aco, $action = '*') {
153152
}
154153
}
155154
}
155+
156+
if ($action === '*' && count($inherited) === count($permKeys)) {
157+
return true;
158+
}
156159
}
157160
return false;
158161
}

lib/Cake/Test/Case/Controller/Component/Acl/DbAclTest.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,12 @@ public function testInheritParentDeny() {
452452
$this->Acl->Aco->create(array('parent_id' => $this->Acl->Aco->id, 'alias' => 'town'));
453453
$this->Acl->Aco->save();
454454

455+
$this->Acl->Aco->create(array('parent_id' => null, 'alias' => 'bizzaro_world'));
456+
$this->Acl->Aco->save();
457+
458+
$this->Acl->Aco->create(array('parent_id' => $this->Acl->Aco->id, 'alias' => 'bizzaro_town'));
459+
$this->Acl->Aco->save();
460+
455461
$this->Acl->Aro->create(array('parent_id' => null, 'alias' => 'Jane'));
456462
$this->Acl->Aro->save();
457463

@@ -463,8 +469,18 @@ public function testInheritParentDeny() {
463469
$this->Acl->inherit('Jane', 'town', '*');
464470
$this->Acl->allow('Jane', 'town', 'create');
465471

472+
// Setup deny on create for parent
473+
$this->Acl->deny('Jane', 'bizzaro_world', '*');
474+
$this->Acl->allow('Jane', 'bizzaro_world', 'create');
475+
476+
// Setup inherit.
477+
$this->Acl->inherit('Jane', 'bizzaro_town', '*');
478+
466479
$this->assertTrue($this->Acl->check('Jane', 'town', 'create'), 'Should have access due to override');
467480
$this->assertTrue($this->Acl->check('Jane', 'town', '*'), 'Should have access due to inherit');
481+
482+
$this->assertTrue($this->Acl->check('Jane', 'bizzaro_town', 'create'), 'Should have access due explicit allow');
483+
$this->assertFalse($this->Acl->check('Jane', 'bizzaro_town', '*'), 'Should not have access due to inherit');
468484
}
469485

470486
/**

0 commit comments

Comments
 (0)