Skip to content

Commit 4b1a0be

Browse files
committed
ACP2E-3503: Automatic enabling of new ACL permissions
1 parent 88d1367 commit 4b1a0be

File tree

1 file changed

+140
-0
lines changed

1 file changed

+140
-0
lines changed
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
<?php
2+
/**
3+
* Copyright 2024 Adobe
4+
* All Rights Reserved.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Unit\Model\Acl\Loader;
9+
10+
use Magento\Authorization\Model\Acl\Loader\Rule;
11+
use Magento\Framework\Acl;
12+
use Magento\Framework\Acl\Data\CacheInterface;
13+
use Magento\Framework\Acl\RootResource;
14+
use Magento\Framework\App\ResourceConnection;
15+
use Magento\Framework\Serialize\Serializer\Json;
16+
use PHPUnit\Framework\MockObject\Exception;
17+
use PHPUnit\Framework\MockObject\MockObject;
18+
use PHPUnit\Framework\TestCase;
19+
20+
/**
21+
* @covers \Magento\Authorization\Model\Acl\Loader\Rule
22+
*/
23+
class MissingDeclineRuleTest extends TestCase
24+
{
25+
/**
26+
* @var Rule
27+
*/
28+
private $model;
29+
30+
/**
31+
* @var RootResource
32+
*/
33+
private $rootResource;
34+
35+
/**
36+
* @var ResourceConnection|MockObject
37+
*/
38+
private $resourceMock;
39+
40+
/**
41+
* @var CacheInterface|MockObject
42+
*/
43+
private $aclDataCacheMock;
44+
45+
/**
46+
* @var Json|MockObject
47+
*/
48+
private $serializerMock;
49+
50+
/**
51+
* @inheritDoc
52+
*/
53+
protected function setUp(): void
54+
{
55+
$this->rootResource = new RootResource('Magento_Backend::all');
56+
57+
$this->resourceMock = $this->getMockBuilder(ResourceConnection::class)
58+
->addMethods(['getTable'])
59+
->onlyMethods(['getConnection'])
60+
->disableOriginalConstructor()
61+
->getMock();
62+
63+
$this->aclDataCacheMock = $this->createMock(CacheInterface::class);
64+
$this->serializerMock = $this->createPartialMock(
65+
Json::class,
66+
['serialize', 'unserialize']
67+
);
68+
69+
$this->serializerMock->method('serialize')
70+
->willReturnCallback(
71+
static function ($value) {
72+
return json_encode($value);
73+
}
74+
);
75+
76+
$this->serializerMock->method('unserialize')
77+
->willReturnCallback(
78+
static function ($value) {
79+
return json_decode($value, true);
80+
}
81+
);
82+
83+
$this->model = new Rule(
84+
$this->rootResource,
85+
$this->resourceMock,
86+
$this->aclDataCacheMock,
87+
$this->serializerMock
88+
);
89+
}
90+
91+
/**
92+
* This test ensures that any new resources, which have not been explicitly defined in the authorization_rule table,
93+
* are automatically denied for all roles unless explicitly allowed.
94+
*
95+
* @return void
96+
* @throws Exception
97+
*/
98+
public function testDenyAbsentResources(): void
99+
{
100+
// Vendor_MyModule::menu and Vendor_MyModule::report permissions are not present in the authorization_rules
101+
// table for role 3, and should be denied by default
102+
$authorizationRulesData = [
103+
['rule_id' => 1, 'role_id' => 2, 'resource_id' => 'Magento_Backend::all', 'permission' => 'deny'],
104+
['rule_id' => 2, 'role_id' => 2, 'resource_id' => 'Vendor_MyModule::index', 'permission' => 'allow'],
105+
['rule_id' => 3, 'role_id' => 2, 'resource_id' => 'Vendor_MyModule::menu', 'permission' => 'deny'],
106+
['rule_id' => 4, 'role_id' => 2, 'resource_id' => 'Vendor_MyModule::report', 'permission' => 'deny'],
107+
['rule_id' => 5, 'role_id' => 3, 'resource_id' => 'Magento_Backend::all', 'permission' => 'deny'],
108+
['rule_id' => 6, 'role_id' => 3, 'resource_id' => 'Vendor_MyModule::index', 'permission' => 'allow'],
109+
];
110+
111+
// Vendor_MyModule::configuration is a new resource that has not been defined in the authorization_rules table
112+
// for any role, and should be denied by default
113+
$getAclResourcesData = array_unique(array_column($authorizationRulesData, 'resource_id'));
114+
$getAclResourcesData[] = 'Vendor_MyModule::configuration';
115+
116+
$this->aclDataCacheMock->expects($this->once())
117+
->method('load')
118+
->with(Rule::ACL_RULE_CACHE_KEY)
119+
->willReturn(
120+
json_encode($authorizationRulesData)
121+
);
122+
123+
$aclMock = $this->createMock(Acl::class);
124+
$aclMock->method('hasResource')->willReturn(true);
125+
126+
$aclMock
127+
->expects($this->exactly(2))
128+
->method('allow');
129+
130+
$aclMock
131+
->expects($this->exactly(7))
132+
->method('deny');
133+
134+
$aclMock
135+
->method('getResources')
136+
->willReturn($getAclResourcesData);
137+
138+
$this->model->populateAcl($aclMock);
139+
}
140+
}

0 commit comments

Comments
 (0)