Skip to content

Commit 7daf5e0

Browse files
authored
ENGCOM-7665: #26089: Customer Sharing Options not respected in REST API. #28213
2 parents e55c352 + 4e96002 commit 7daf5e0

File tree

2 files changed

+253
-6
lines changed

2 files changed

+253
-6
lines changed

app/code/Magento/Customer/Model/Plugin/CustomerAuthorization.php

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@
77
namespace Magento\Customer\Model\Plugin;
88

99
use Magento\Authorization\Model\UserContextInterface;
10+
use Magento\Customer\Model\CustomerFactory;
11+
use Magento\Customer\Model\ResourceModel\Customer as CustomerResource;
1012
use Magento\Integration\Api\AuthorizationServiceInterface as AuthorizationService;
13+
use Magento\Store\Model\StoreManagerInterface;
1114

1215
/**
1316
* Plugin around \Magento\Framework\Authorization::isAllowed
@@ -19,16 +22,41 @@ class CustomerAuthorization
1922
/**
2023
* @var UserContextInterface
2124
*/
22-
protected $userContext;
25+
private $userContext;
26+
27+
/**
28+
* @var CustomerFactory
29+
*/
30+
private $customerFactory;
31+
32+
/**
33+
* @var CustomerResource
34+
*/
35+
private $customerResource;
36+
37+
/**
38+
* @var StoreManagerInterface
39+
*/
40+
private $storeManager;
2341

2442
/**
2543
* Inject dependencies.
2644
*
2745
* @param UserContextInterface $userContext
46+
* @param CustomerFactory $customerFactory
47+
* @param CustomerResource $customerResource
48+
* @param StoreManagerInterface $storeManager
2849
*/
29-
public function __construct(UserContextInterface $userContext)
30-
{
50+
public function __construct(
51+
UserContextInterface $userContext,
52+
CustomerFactory $customerFactory,
53+
CustomerResource $customerResource,
54+
StoreManagerInterface $storeManager
55+
) {
3156
$this->userContext = $userContext;
57+
$this->customerFactory = $customerFactory;
58+
$this->customerResource = $customerResource;
59+
$this->storeManager = $storeManager;
3260
}
3361

3462
/**
@@ -53,9 +81,15 @@ public function aroundIsAllowed(
5381
&& $this->userContext->getUserId()
5482
&& $this->userContext->getUserType() === UserContextInterface::USER_TYPE_CUSTOMER
5583
) {
56-
return true;
57-
} else {
58-
return $proceed($resource, $privilege);
84+
$customer = $this->customerFactory->create();
85+
$this->customerResource->load($customer, $this->userContext->getUserId());
86+
$currentStoreId = $this->storeManager->getStore()->getId();
87+
$sharedStoreIds = $customer->getSharedStoreIds();
88+
if (in_array($currentStoreId, $sharedStoreIds)) {
89+
return true;
90+
}
5991
}
92+
93+
return $proceed($resource, $privilege);
6094
}
6195
}
Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
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\Api;
9+
10+
use Magento\Customer\Api\Data\CustomerInterface;
11+
use Magento\Customer\Model\CustomerRegistry;
12+
use Magento\Framework\Registry;
13+
use Magento\Framework\Webapi\Rest\Request;
14+
use Magento\Integration\Api\CustomerTokenServiceInterface;
15+
use Magento\Integration\Model\Oauth\Token as TokenModel;
16+
use Magento\TestFramework\Helper\Bootstrap;
17+
use Magento\TestFramework\Helper\Customer as CustomerHelper;
18+
use Magento\TestFramework\TestCase\WebapiAbstract;
19+
20+
/**
21+
* @magentoApiDataFixture Magento/Customer/_files/customer.php
22+
* @magentoApiDataFixture Magento/Store/_files/second_website_with_two_stores.php
23+
*/
24+
class CustomerSharingOptionsTest extends WebapiAbstract
25+
{
26+
const RESOURCE_PATH = '/V1/customers/me';
27+
const REPO_SERVICE = 'customerCustomerRepositoryV1';
28+
const SERVICE_VERSION = 'V1';
29+
30+
/**
31+
* @var CustomerRepositoryInterface
32+
*/
33+
private $customerRepository;
34+
35+
/**
36+
* @var CustomerRegistry
37+
*/
38+
private $customerRegistry;
39+
40+
/**
41+
* @var CustomerHelper
42+
*/
43+
private $customerHelper;
44+
45+
/**
46+
* @var TokenModel
47+
*/
48+
private $token;
49+
50+
/**
51+
* @var CustomerInterface
52+
*/
53+
private $customerData;
54+
55+
/**
56+
* @var CustomerTokenServiceInterface
57+
*/
58+
private $tokenService;
59+
60+
/**
61+
* Execute per test initialization.
62+
*/
63+
public function setUp(): void
64+
{
65+
$this->customerRegistry = Bootstrap::getObjectManager()->get(
66+
\Magento\Customer\Model\CustomerRegistry::class
67+
);
68+
69+
$this->customerRepository = Bootstrap::getObjectManager()->get(
70+
CustomerRepositoryInterface::class,
71+
['customerRegistry' => $this->customerRegistry]
72+
);
73+
74+
$this->customerHelper = new CustomerHelper();
75+
$this->customerData = $this->customerHelper->createSampleCustomer();
76+
$this->tokenService = Bootstrap::getObjectManager()->get(CustomerTokenServiceInterface::class);
77+
78+
// get token
79+
$this->resetTokenForCustomerSampleData();
80+
}
81+
82+
/**
83+
* Ensure that fixture customer and his addresses are deleted.
84+
*/
85+
public function tearDown(): void
86+
{
87+
$this->customerRepository = null;
88+
89+
/** @var Registry $registry */
90+
$registry = Bootstrap::getObjectManager()->get(Registry::class);
91+
$registry->unregister('isSecureArea');
92+
$registry->register('isSecureArea', true);
93+
94+
$registry->unregister('isSecureArea');
95+
$registry->register('isSecureArea', false);
96+
parent::tearDown();
97+
}
98+
99+
/**
100+
* @param string $storeCode
101+
* @param bool $expectingException
102+
* @dataProvider getCustomerDataWebsiteScopeDataProvider
103+
*
104+
* @magentoConfigFixture default_store customer/account_share/scope 1
105+
*/
106+
public function testGetCustomerDataWebsiteScope(string $storeCode, bool $expectingException)
107+
{
108+
$this->_markTestAsRestOnly('SOAP is difficult to generate exception messages, inconsistencies in WSDL');
109+
$this->processGetCustomerData($storeCode, $expectingException);
110+
}
111+
112+
/**
113+
* @param string $storeCode
114+
* @param bool $expectingException
115+
* @dataProvider getCustomerDataGlobalScopeDataProvider
116+
*
117+
* @magentoConfigFixture customer/account_share/scope 0
118+
*/
119+
public function testGetCustomerDataGlobalScope(string $storeCode, bool $expectingException)
120+
{
121+
$this->processGetCustomerData($storeCode, $expectingException);
122+
}
123+
124+
/**
125+
* @param string $storeCode
126+
* @param bool $expectingException
127+
*/
128+
private function processGetCustomerData(string $storeCode, bool $expectingException)
129+
{
130+
$serviceInfo = [
131+
'rest' => [
132+
'resourcePath' => self::RESOURCE_PATH,
133+
'httpMethod' => Request::HTTP_METHOD_GET,
134+
'token' => $this->token,
135+
],
136+
'soap' => [
137+
'service' => self::REPO_SERVICE,
138+
'serviceVersion' => self::SERVICE_VERSION,
139+
'operation' => self::REPO_SERVICE . 'GetSelf',
140+
'token' => $this->token
141+
]
142+
];
143+
$arguments = [];
144+
if (TESTS_WEB_API_ADAPTER === 'soap') {
145+
$arguments['customerId'] = 0;
146+
}
147+
148+
if ($expectingException) {
149+
self::expectException(\Exception::class);
150+
self::expectExceptionMessage("The consumer isn't authorized to access %resources.");
151+
}
152+
153+
$this->_webApiCall($serviceInfo, $arguments, null, $storeCode);
154+
}
155+
156+
/**
157+
* Data provider for testGetCustomerDataWebsiteScope.
158+
*
159+
* @return array
160+
*/
161+
public function getCustomerDataWebsiteScopeDataProvider(): array
162+
{
163+
return [
164+
'Default Store View' => [
165+
'store_code' => 'default',
166+
'exception' => false
167+
],
168+
'Custom Store View' => [
169+
'store_code' => 'fixture_second_store',
170+
'exception' => true
171+
]
172+
];
173+
}
174+
175+
/**
176+
* Data provider for testGetCustomerDataGlobalScope.
177+
*
178+
* @return array
179+
*/
180+
public function getCustomerDataGlobalScopeDataProvider(): array
181+
{
182+
return [
183+
'Default Store View' => [
184+
'store_code' => 'default',
185+
'exception' => false
186+
],
187+
'Custom Store View' => [
188+
'store_code' => 'fixture_second_store',
189+
'exception' => false
190+
]
191+
];
192+
}
193+
194+
/**
195+
* Sets the test's access token for the created customer sample data
196+
*/
197+
private function resetTokenForCustomerSampleData()
198+
{
199+
$this->resetTokenForCustomer($this->customerData[CustomerInterface::EMAIL], 'test@123');
200+
}
201+
202+
/**
203+
* Sets the test's access token for a particular username and password.
204+
*
205+
* @param string $username
206+
* @param string $password
207+
*/
208+
private function resetTokenForCustomer($username, $password)
209+
{
210+
$this->token = $this->tokenService->createCustomerAccessToken($username, $password);
211+
$this->customerRegistry->remove($this->customerRepository->get($username)->getId());
212+
}
213+
}

0 commit comments

Comments
 (0)