Skip to content

Commit f605b71

Browse files
authored
Merge pull request #7447 from magento-cia/2.4.5-bugfixes-020822
Bugfixes
2 parents aabf11d + 3023c43 commit f605b71

File tree

7 files changed

+246
-41
lines changed

7 files changed

+246
-41
lines changed

app/code/Magento/Checkout/Model/DefaultConfigProvider.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
use Magento\Quote\Model\QuoteIdMaskFactory;
3232
use Magento\Store\Model\ScopeInterface;
3333
use Magento\Ui\Component\Form\Element\Multiline;
34+
use Magento\Framework\Escaper;
3435

3536
/**
3637
* Default Config Provider for checkout
@@ -191,6 +192,11 @@ class DefaultConfigProvider implements ConfigProviderInterface
191192
*/
192193
private $configPostProcessor;
193194

195+
/**
196+
* @var Escaper
197+
*/
198+
private $escaper;
199+
194200
/**
195201
* @param CheckoutHelper $checkoutHelper
196202
* @param Session $checkoutSession
@@ -222,6 +228,7 @@ class DefaultConfigProvider implements ConfigProviderInterface
222228
* @param AddressMetadataInterface $addressMetadata
223229
* @param AttributeOptionManagementInterface $attributeOptionManager
224230
* @param CustomerAddressDataProvider|null $customerAddressData
231+
* @param Escaper|null $escaper
225232
* @codeCoverageIgnore
226233
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
227234
*/
@@ -255,7 +262,8 @@ public function __construct(
255262
CaptchaConfigPostProcessorInterface $configPostProcessor,
256263
AddressMetadataInterface $addressMetadata = null,
257264
AttributeOptionManagementInterface $attributeOptionManager = null,
258-
CustomerAddressDataProvider $customerAddressData = null
265+
CustomerAddressDataProvider $customerAddressData = null,
266+
Escaper $escaper = null
259267
) {
260268
$this->checkoutHelper = $checkoutHelper;
261269
$this->checkoutSession = $checkoutSession;
@@ -289,6 +297,7 @@ public function __construct(
289297
$this->customerAddressData = $customerAddressData ?:
290298
ObjectManager::getInstance()->get(CustomerAddressDataProvider::class);
291299
$this->configPostProcessor = $configPostProcessor;
300+
$this->escaper = $escaper ?? ObjectManager::getInstance()->get(Escaper::class);
292301
}
293302

294303
/**
@@ -343,6 +352,7 @@ public function getConfig()
343352
'shipping/shipping_policy/shipping_policy_content',
344353
ScopeInterface::SCOPE_STORE
345354
);
355+
$policyContent = $this->escaper->escapeHtml($policyContent);
346356
$output['shippingPolicy'] = [
347357
'isEnabled' => $this->scopeConfig->isSetFlag(
348358
'shipping/shipping_policy/enable_shipping_policy',

app/code/Magento/Customer/Controller/Account/Confirmation.php

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
declare(strict_types=1);
7+
68
namespace Magento\Customer\Controller\Account;
79

810
use Magento\Customer\Api\AccountManagementInterface;
@@ -13,22 +15,26 @@
1315
use Magento\Framework\App\Action\HttpPostActionInterface as HttpPostActionInterface;
1416
use Magento\Framework\App\Action\Context;
1517
use Magento\Framework\App\ObjectManager;
18+
use Magento\Framework\Controller\Result\Redirect;
19+
use Magento\Framework\Exception\LocalizedException;
20+
use Magento\Framework\Exception\NoSuchEntityException;
1621
use Magento\Framework\Exception\State\InvalidTransitionException;
22+
use Magento\Framework\View\Result\Page;
1723
use Magento\Framework\View\Result\PageFactory;
1824
use Magento\Store\Model\StoreManagerInterface;
1925

2026
/**
21-
* Class Confirmation. Send confirmation link to specified email
27+
* Send confirmation link to specified email
2228
*/
2329
class Confirmation extends AbstractAccount implements HttpGetActionInterface, HttpPostActionInterface
2430
{
2531
/**
26-
* @var \Magento\Store\Model\StoreManagerInterface
32+
* @var StoreManagerInterface
2733
*/
2834
protected $storeManager;
2935

3036
/**
31-
* @var \Magento\Customer\Api\AccountManagementInterface
37+
* @var AccountManagementInterface
3238
*/
3339
protected $customerAccountManagement;
3440

@@ -53,7 +59,7 @@ class Confirmation extends AbstractAccount implements HttpGetActionInterface, Ht
5359
* @param PageFactory $resultPageFactory
5460
* @param StoreManagerInterface $storeManager
5561
* @param AccountManagementInterface $customerAccountManagement
56-
* @param Url $customerUrl
62+
* @param Url|null $customerUrl
5763
*/
5864
public function __construct(
5965
Context $context,
@@ -74,48 +80,52 @@ public function __construct(
7480
/**
7581
* Send confirmation link to specified email
7682
*
77-
* @return \Magento\Framework\Controller\Result\Redirect|\Magento\Framework\View\Result\Page
83+
* @return Redirect|Page
84+
* @throws LocalizedException
7885
*/
7986
public function execute()
8087
{
8188
if ($this->session->isLoggedIn()) {
82-
/** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */
83-
$resultRedirect = $this->resultRedirectFactory->create();
84-
$resultRedirect->setPath('*/*/');
85-
return $resultRedirect;
89+
return $this->getRedirect('*/*/');
8690
}
8791

88-
// try to confirm by email
8992
$email = $this->getRequest()->getPost('email');
90-
if ($email) {
91-
/** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */
92-
$resultRedirect = $this->resultRedirectFactory->create();
9393

94+
if ($email) {
9495
try {
9596
$this->customerAccountManagement->resendConfirmation(
9697
$email,
9798
$this->storeManager->getStore()->getWebsiteId()
9899
);
99100
$this->messageManager->addSuccessMessage(__('Please check your email for confirmation key.'));
101+
return $this->getRedirect('*/*/index', ['_secure' => true]);
100102
} catch (InvalidTransitionException $e) {
101103
$this->messageManager->addSuccessMessage(__('This email does not require confirmation.'));
102-
} catch (\Exception $e) {
103-
$this->messageManager->addExceptionMessage($e, __('Wrong email.'));
104-
$resultRedirect->setPath('*/*/*', ['email' => $email, '_secure' => true]);
105-
return $resultRedirect;
104+
return $this->getRedirect('*/*/index', ['_secure' => true]);
105+
} catch (NoSuchEntityException $e) {
106+
$this->messageManager->addErrorMessage(__('Wrong email.'));
106107
}
107-
$this->session->setUsername($email);
108-
$resultRedirect->setPath('*/*/index', ['_secure' => true]);
109-
return $resultRedirect;
110108
}
111109

112-
/** @var \Magento\Framework\View\Result\Page $resultPage */
113110
$resultPage = $this->resultPageFactory->create();
114-
$resultPage->getLayout()->getBlock('accountConfirmation')->setEmail(
115-
$this->getRequest()->getParam('email', $email)
116-
)->setLoginUrl(
117-
$this->customerUrl->getLoginUrl()
118-
);
111+
$resultPage->getLayout()->getBlock('accountConfirmation')
112+
->setEmail($email)
113+
->setLoginUrl($this->customerUrl->getLoginUrl());
119114
return $resultPage;
120115
}
116+
117+
/**
118+
* Returns redirect object
119+
*
120+
* @param string $path
121+
* @param array $params
122+
* @return Redirect
123+
*/
124+
private function getRedirect(string $path, array $params = []): Redirect
125+
{
126+
$resultRedirect = $this->resultRedirectFactory->create();
127+
$resultRedirect->setPath($path, $params);
128+
129+
return $resultRedirect;
130+
}
121131
}

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

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
use Magento\Framework\Webapi\Rest\Request as RestRequest;
1212
use Magento\Customer\Api\Data\CustomerInterface;
1313
use Magento\Customer\Api\CustomerRepositoryInterface;
14+
use Magento\Authorization\Model\UserContextInterface;
15+
use Magento\Framework\App\ObjectManager;
1416

1517
/**
1618
* Update customer by id from request param
@@ -22,12 +24,19 @@ class UpdateCustomer
2224
*/
2325
private $request;
2426

27+
/**
28+
* @var UserContextInterface
29+
*/
30+
private $userContext;
31+
2532
/**
2633
* @param RestRequest $request
34+
* @param UserContextInterface|null $userContext
2735
*/
28-
public function __construct(RestRequest $request)
36+
public function __construct(RestRequest $request, ?UserContextInterface $userContext = null)
2937
{
3038
$this->request = $request;
39+
$this->userContext = $userContext ?? ObjectManager::getInstance()->get(UserContextInterface::class);
3140
}
3241

3342
/**
@@ -43,10 +52,14 @@ public function beforeSave(
4352
CustomerInterface $customer,
4453
?string $passwordHash = null
4554
): array {
46-
$customerId = $this->request->getParam('customerId');
55+
$customerSessionId = $this->userContext->getUserType() === $this->userContext::USER_TYPE_CUSTOMER ?
56+
(int)$this->userContext->getUserId() : 0;
57+
$customerId = (int)$this->request->getParam('customerId');
4758
$bodyParams = $this->request->getBodyParams();
4859
if (!isset($bodyParams['customer']['Id']) && $customerId) {
49-
$customer = $this->getUpdatedCustomer($customerRepository->getById($customerId), $customer);
60+
if ($customerId === $customerSessionId || $customerSessionId === 0) {
61+
$customer = $this->getUpdatedCustomer($customerRepository->getById($customerId), $customer);
62+
}
5063
}
5164

5265
return [$customer, $passwordHash];
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
namespace Magento\Quote\Plugin\Webapi\Controller\Rest;
8+
9+
use Magento\Webapi\Controller\Rest\ParamsOverrider;
10+
11+
/**
12+
* Validates Quote Data
13+
*/
14+
class ValidateQuoteData
15+
{
16+
private const QUOTE_KEY = 'quote';
17+
18+
/**
19+
* Before Overriding to validate data
20+
*
21+
* @param ParamsOverrider $subject
22+
* @param array $inputData
23+
* @param array $parameters
24+
* @return array[]
25+
*
26+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
27+
*/
28+
29+
public function beforeOverride(ParamsOverrider $subject, array $inputData, array $parameters): array
30+
{
31+
if (isset($inputData[self:: QUOTE_KEY])) {
32+
$inputData[self:: QUOTE_KEY] = $this->validateInputData($inputData[self:: QUOTE_KEY]);
33+
};
34+
return [$inputData, $parameters];
35+
}
36+
37+
/**
38+
* Validates InputData
39+
*
40+
* @param array $inputData
41+
* @return array
42+
*/
43+
private function validateInputData(array $inputData): array
44+
{
45+
$result = [];
46+
47+
$data = array_filter($inputData, function ($k) use (&$result) {
48+
$key = is_string($k) ? strtolower($k) : $k;
49+
return !isset($result[$key]) && ($result[$key] = true);
50+
}, ARRAY_FILTER_USE_KEY);
51+
52+
return array_map(function ($value) {
53+
return is_array($value) ? $this->validateInputData($value) : $value;
54+
}, $data);
55+
}
56+
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Quote\Test\Unit\Plugin\Webapi\Controller\Rest;
8+
9+
use Exception;
10+
use Magento\Framework\App\ObjectManager;
11+
use Magento\Quote\Plugin\Webapi\Controller\Rest\ValidateQuoteData;
12+
use PHPUnit\Framework\TestCase;
13+
use ReflectionClass;
14+
15+
/**
16+
* Unit test for ValidateQuoteData plugin
17+
*/
18+
class ValidateQuoteDataTest extends TestCase
19+
{
20+
21+
/**
22+
* @var ValidateQuoteData
23+
*/
24+
private $validateQuoteDataObject;
25+
26+
/**
27+
* @var ReflectionClass
28+
*
29+
*/
30+
private $reflectionObject;
31+
32+
/**
33+
* @inheritdoc
34+
*/
35+
protected function setUp(): void
36+
{
37+
$this->validateQuoteDataObject = ObjectManager::getInstance()->get(ValidateQuoteData::class);
38+
$this->reflectionObject = new ReflectionClass(get_class($this->validateQuoteDataObject));
39+
}
40+
/**
41+
* Test if the quote array is valid
42+
*
43+
* @param array $array
44+
* @param array $result
45+
* @dataProvider dataProviderInputData
46+
* @throws Exception
47+
*/
48+
public function testValidateInputData(array $array, array $result)
49+
{
50+
$this->assertEquals(
51+
$result,
52+
$this->invokeValidateInputData('validateInputData', [$array])
53+
);
54+
}
55+
56+
/**
57+
* @param string $methodName
58+
* @param array $arguments
59+
* @return mixed
60+
* @throws Exception
61+
*/
62+
private function invokeValidateInputData(string $methodName, array $arguments = [])
63+
{
64+
$validateInputDataMethod = $this->reflectionObject->getMethod($methodName);
65+
$validateInputDataMethod->setAccessible(true);
66+
return $validateInputDataMethod->invokeArgs($this->validateQuoteDataObject, $arguments);
67+
}
68+
69+
/**
70+
* @return array
71+
*/
72+
public function dataProviderInputData(): array
73+
{
74+
return [
75+
[
76+
['person' =>
77+
[
78+
'id' => -1,
79+
'Id' => 1,
80+
'name' =>
81+
[
82+
'firstName' => 'John',
83+
'LastName' => 'S'
84+
],
85+
'isHavingVehicle' => 1,
86+
'address' =>
87+
[
88+
'street' => '4th Street',
89+
'Street' => '2nd Street',
90+
'city' => 'Atlanta'
91+
],
92+
]
93+
],
94+
['person' =>
95+
[
96+
'id' => -1,
97+
'name' =>
98+
[
99+
'firstName' => 'John',
100+
'LastName' => 'S'
101+
],
102+
'isHavingVehicle' => 1,
103+
'address' =>
104+
[
105+
'street' => '4th Street',
106+
'city' => 'Atlanta'
107+
],
108+
]
109+
],
110+
]
111+
];
112+
}
113+
}

0 commit comments

Comments
 (0)