Skip to content

Commit ddee804

Browse files
committed
#26089: Customer Sharing Options not respected in REST API.
1 parent 40a7876 commit ddee804

File tree

2 files changed

+241
-6
lines changed

2 files changed

+241
-6
lines changed

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

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

99
use Magento\Authorization\Model\UserContextInterface;
10+
use Magento\Customer\Model\CustomerFactory;
1011
use Magento\Integration\Api\AuthorizationServiceInterface as AuthorizationService;
12+
use Magento\Store\Model\StoreManagerInterface;
1113

1214
/**
1315
* Plugin around \Magento\Framework\Authorization::isAllowed
@@ -19,16 +21,33 @@ class CustomerAuthorization
1921
/**
2022
* @var UserContextInterface
2123
*/
22-
protected $userContext;
24+
private $userContext;
25+
26+
/**
27+
* @var StoreManagerInterface
28+
*/
29+
private $storeManager;
30+
31+
/**
32+
* @var CustomerFactory
33+
*/
34+
private $customerFactory;
2335

2436
/**
2537
* Inject dependencies.
2638
*
2739
* @param UserContextInterface $userContext
40+
* @param CustomerFactory $customerFactory
41+
* @param StoreManagerInterface $storeManager
2842
*/
29-
public function __construct(UserContextInterface $userContext)
30-
{
43+
public function __construct(
44+
UserContextInterface $userContext,
45+
CustomerFactory $customerFactory,
46+
StoreManagerInterface $storeManager
47+
) {
3148
$this->userContext = $userContext;
49+
$this->customerFactory = $customerFactory;
50+
$this->storeManager = $storeManager;
3251
}
3352

3453
/**
@@ -53,9 +72,14 @@ public function aroundIsAllowed(
5372
&& $this->userContext->getUserId()
5473
&& $this->userContext->getUserType() === UserContextInterface::USER_TYPE_CUSTOMER
5574
) {
56-
return true;
57-
} else {
58-
return $proceed($resource, $privilege);
75+
$customer = $this->customerFactory->create()->load($this->userContext->getUserId());
76+
$currentStoreId = $this->storeManager->getStore()->getId();
77+
$sharedStoreIds = $customer->getSharedStoreIds();
78+
if (in_array($currentStoreId, $sharedStoreIds)) {
79+
return true;
80+
}
5981
}
82+
83+
return $proceed($resource, $privilege);
6084
}
6185
}
Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
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()
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()
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 customer/account_share/scope 1
105+
*/
106+
public function testGetCustomerDataWebsiteScope(string $storeCode, bool $expectingException)
107+
{
108+
$this->processGetCustomerData($storeCode, $expectingException);
109+
}
110+
111+
/**
112+
* @param string $storeCode
113+
* @param bool $expectingException
114+
* @dataProvider getCustomerDataGlobalScopeDataProvider
115+
*
116+
* @magentoConfigFixture customer/account_share/scope 0
117+
*/
118+
public function testGetCustomerDataGlobalScope(string $storeCode, bool $expectingException)
119+
{
120+
$this->processGetCustomerData($storeCode, $expectingException);
121+
}
122+
123+
/**
124+
* @param string $storeCode
125+
* @param bool $expectingException
126+
*/
127+
private function processGetCustomerData(string $storeCode, bool $expectingException)
128+
{
129+
$serviceInfo = [
130+
'rest' => [
131+
'resourcePath' => self::RESOURCE_PATH,
132+
'httpMethod' => Request::HTTP_METHOD_GET,
133+
'token' => $this->token,
134+
],
135+
'soap' => [
136+
'service' => self::REPO_SERVICE,
137+
'serviceVersion' => self::SERVICE_VERSION,
138+
'operation' => self::REPO_SERVICE . 'GetSelf',
139+
'token' => $this->token
140+
]
141+
];
142+
$arguments = [];
143+
if (TESTS_WEB_API_ADAPTER === 'soap') {
144+
$arguments['customerId'] = 0;
145+
}
146+
if ($expectingException) {
147+
$this->expectException(\Exception::class);
148+
$this->expectExceptionMessage("The consumer isn't authorized to access %resources.");
149+
}
150+
151+
$this->_webApiCall($serviceInfo, $arguments, null, $storeCode);
152+
}
153+
154+
/**
155+
* Data provider for testGetCustomerDataWebsiteScope.
156+
*
157+
* @return array
158+
*/
159+
public function getCustomerDataWebsiteScopeDataProvider(): array
160+
{
161+
return [
162+
'Default Store View' => [
163+
'store_code' => 'default',
164+
'exception' => false
165+
],
166+
'Custom Store View' => [
167+
'store_code' => 'fixture_second_store',
168+
'exception' => true
169+
]
170+
];
171+
}
172+
173+
/**
174+
* Data provider for testGetCustomerDataGlobalScope.
175+
*
176+
* @return array
177+
*/
178+
public function getCustomerDataGlobalScopeDataProvider(): array
179+
{
180+
return [
181+
'Default Store View' => [
182+
'store_code' => 'default',
183+
'exception' => false
184+
],
185+
'Custom Store View' => [
186+
'store_code' => 'fixture_second_store',
187+
'exception' => false
188+
]
189+
];
190+
}
191+
192+
/**
193+
* Sets the test's access token for the created customer sample data
194+
*/
195+
private function resetTokenForCustomerSampleData()
196+
{
197+
$this->resetTokenForCustomer($this->customerData[CustomerInterface::EMAIL], 'test@123');
198+
}
199+
200+
/**
201+
* Sets the test's access token for a particular username and password.
202+
*
203+
* @param string $username
204+
* @param string $password
205+
*/
206+
private function resetTokenForCustomer($username, $password)
207+
{
208+
$this->token = $this->tokenService->createCustomerAccessToken($username, $password);
209+
$this->customerRegistry->remove($this->customerRepository->get($username)->getId());
210+
}
211+
}

0 commit comments

Comments
 (0)