Skip to content

Commit 11f1813

Browse files
AnujNehraAnujNehra
authored andcommitted
ACP2E-1776: Creating customer(-s) via Async REST API ignores group_id
1 parent e3f166f commit 11f1813

File tree

2 files changed

+190
-0
lines changed

2 files changed

+190
-0
lines changed
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Magento\Customer\Plugin;
10+
11+
use Magento\Customer\Api\Data\CustomerInterface;
12+
use Magento\Framework\App\ObjectManager;
13+
use Magento\Framework\AuthorizationInterface;
14+
use Magento\Framework\Exception\AuthorizationException;
15+
use Magento\AsynchronousOperations\Model\MassSchedule;
16+
17+
/**
18+
* Plugin to validate anonymous request for asynchronous operations containing group id.
19+
*/
20+
class AsyncRequestCustomerGroupAuthorization
21+
{
22+
/**
23+
* Authorization level of a basic admin session
24+
*
25+
* @see _isAllowed()
26+
*/
27+
public const ADMIN_RESOURCE = 'Magento_Customer::manage';
28+
29+
/**
30+
* @var AuthorizationInterface
31+
*/
32+
private $authorization;
33+
34+
/**
35+
*
36+
* @param AuthorizationInterface|null $authorization
37+
*/
38+
public function __construct(
39+
AuthorizationInterface $authorization = null
40+
) {
41+
$objectManager = ObjectManager::getInstance();
42+
$this->authorization = $authorization ?? $objectManager->get(AuthorizationInterface::class);
43+
}
44+
45+
/**
46+
* Validate groupId for anonymous request
47+
*
48+
* @param MassSchedule $massSchedule
49+
* @param string $topic
50+
* @param array $entitiesArray
51+
* @param string|null $groupId
52+
* @param string|null $userId
53+
* @return void
54+
* @throws AuthorizationException
55+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
56+
*/
57+
public function beforePublishMass(
58+
MassSchedule $massSchedule,
59+
string $topic,
60+
array $entitiesArray,
61+
string $groupId = null,
62+
string $userId = null
63+
): void {
64+
foreach ($entitiesArray as $entityParams) {
65+
foreach ($entityParams as $entity) {
66+
if ($entity instanceof CustomerInterface) {
67+
$groupId = $entity->getGroupId();
68+
if (isset($groupId) && !$this->authorization->isAllowed(self::ADMIN_RESOURCE)) {
69+
$params = ['resources' => self::ADMIN_RESOURCE];
70+
throw new AuthorizationException(
71+
__("The consumer isn't authorized to access %resources.", $params)
72+
);
73+
}
74+
}
75+
}
76+
}
77+
}
78+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Customer\Test\Plugin;
9+
10+
use Magento\AsynchronousOperations\Model\MassSchedule;
11+
use Magento\Customer\Api\CustomerRepositoryInterface;
12+
use Magento\Customer\Api\Data\CustomerInterface;
13+
use Magento\Framework\Authorization;
14+
use Magento\Framework\Exception\AuthorizationException;
15+
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
16+
use Magento\Customer\Plugin\AsyncRequestCustomerGroupAuthorization;
17+
use PHPUnit\Framework\MockObject\MockObject;
18+
use PHPUnit\Framework\TestCase;
19+
20+
/**
21+
* Test for validating anonymous request for asynchronous operations containing group id.
22+
*/
23+
class AsyncRequestCustomerGroupAuthorizationTest extends TestCase
24+
{
25+
/**
26+
* @var Authorization|MockObject
27+
*/
28+
private $authorizationMock;
29+
30+
/**
31+
* @var AsyncRequestCustomerGroupAuthorization
32+
*/
33+
private $plugin;
34+
35+
/**
36+
* @var MassSchedule|MockObject
37+
*/
38+
private $massScheduleMock;
39+
40+
/**
41+
* @var CustomerRepositoryInterface|MockObject
42+
*/
43+
private $customerRepository;
44+
45+
/**
46+
* @inheritDoc
47+
*/
48+
protected function setUp(): void
49+
{
50+
$objectManager = new ObjectManager($this);
51+
$this->authorizationMock = $this->createMock(Authorization::class);
52+
$this->plugin = $objectManager->getObject(AsyncRequestCustomerGroupAuthorization::class, [
53+
'authorization' => $this->authorizationMock
54+
]);
55+
$this->massScheduleMock = $this->createMock(MassSchedule::class);
56+
$this->customerRepository = $this->getMockForAbstractClass(CustomerRepositoryInterface::class);
57+
}
58+
59+
/**
60+
* Verify that only authorized request will be able to change groupId
61+
*
62+
* @param int $groupId
63+
* @param int $customerId
64+
* @param bool $isAllowed
65+
* @param int $willThrowException
66+
* @return void
67+
* @throws AuthorizationException
68+
* @dataProvider customerDataProvider
69+
*/
70+
public function testBeforePublishMass(
71+
int $groupId,
72+
int $customerId,
73+
bool $isAllowed,
74+
int $willThrowException
75+
): void {
76+
if ($willThrowException) {
77+
$this->expectException(AuthorizationException::class);
78+
} else {
79+
$this->expectNotToPerformAssertions();
80+
}
81+
$customer = $this->getMockForAbstractClass(CustomerInterface::class);
82+
$customer->method('getGroupId')->willReturn($groupId);
83+
$customer->method('getId')->willReturn($customerId);
84+
$this->customerRepository->method('getById')->with($customerId)->willReturn($customer);
85+
$entitiesArray = [
86+
[$customer, 'Password1', '']
87+
];
88+
$this->authorizationMock
89+
->expects($this->once())
90+
->method('isAllowed')
91+
->with('Magento_Customer::manage')
92+
->willReturn($isAllowed);
93+
$this->plugin->beforePublishMass(
94+
$this->massScheduleMock,
95+
'async.magento.customer.api.accountmanagementinterface.createaccount.post',
96+
$entitiesArray,
97+
'',
98+
''
99+
);
100+
}
101+
102+
/**
103+
* @return array
104+
*/
105+
public function customerDataProvider(): array
106+
{
107+
return [
108+
[3, 1, false, 1],
109+
[3, 1, true, 0]
110+
];
111+
}
112+
}

0 commit comments

Comments
 (0)