Skip to content

Commit 308f724

Browse files
committed
ACP2E-1013: Product is not getting added to wishlist when customer login
1 parent b01eadf commit 308f724

File tree

3 files changed

+93
-20
lines changed

3 files changed

+93
-20
lines changed

app/code/Magento/Wishlist/Controller/Index/Plugin.php

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,41 +6,48 @@
66
namespace Magento\Wishlist\Controller\Index;
77

88
use Magento\Customer\Model\Session as CustomerSession;
9+
use Magento\Framework\App\Action\HttpPostActionInterface;
10+
use Magento\Framework\App\ActionInterface;
911
use Magento\Framework\Data\Form\FormKey;
12+
use Magento\Framework\Data\Form\FormKey\Validator;
1013
use Magento\Framework\Exception\NotFoundException;
1114
use Magento\Framework\App\Config\ScopeConfigInterface;
1215
use Magento\Framework\App\RequestInterface;
1316
use Magento\Framework\App\Response\RedirectInterface;
17+
use Magento\Framework\Message\ManagerInterface;
1418
use Magento\Store\Model\ScopeInterface;
19+
use Magento\Wishlist\Model\AuthenticationStateInterface;
1520
use Magento\Wishlist\Model\DataSerializer;
1621

1722
/**
1823
* Wishlist plugin before dispatch
24+
*
25+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
1926
*/
2027
class Plugin
2128
{
2229
/**
23-
* @var \Magento\Customer\Model\Session
30+
* @var CustomerSession
2431
*/
2532
protected $customerSession;
2633

2734
/**
28-
* @var \Magento\Wishlist\Model\AuthenticationStateInterface
35+
* @var AuthenticationStateInterface
2936
*/
3037
protected $authenticationState;
3138

3239
/**
33-
* @var \Magento\Framework\App\Config\ScopeConfigInterface
40+
* @var ScopeConfigInterface
3441
*/
3542
protected $config;
3643

3744
/**
38-
* @var \Magento\Framework\App\Response\RedirectInterface
45+
* @var RedirectInterface
3946
*/
4047
protected $redirector;
4148

4249
/**
43-
* @var \Magento\Framework\Message\ManagerInterface
50+
* @var ManagerInterface
4451
*/
4552
private $messageManager;
4653

@@ -54,23 +61,30 @@ class Plugin
5461
*/
5562
private $formKey;
5663

64+
/**
65+
* @var Validator
66+
*/
67+
private $formKeyValidator;
68+
5769
/**
5870
* @param CustomerSession $customerSession
59-
* @param \Magento\Wishlist\Model\AuthenticationStateInterface $authenticationState
71+
* @param AuthenticationStateInterface $authenticationState
6072
* @param ScopeConfigInterface $config
6173
* @param RedirectInterface $redirector
62-
* @param \Magento\Framework\Message\ManagerInterface $messageManager
74+
* @param ManagerInterface $messageManager
6375
* @param DataSerializer $dataSerializer
6476
* @param FormKey $formKey
77+
* @param Validator $formKeyValidator
6578
*/
6679
public function __construct(
6780
CustomerSession $customerSession,
68-
\Magento\Wishlist\Model\AuthenticationStateInterface $authenticationState,
81+
AuthenticationStateInterface $authenticationState,
6982
ScopeConfigInterface $config,
7083
RedirectInterface $redirector,
71-
\Magento\Framework\Message\ManagerInterface $messageManager,
84+
ManagerInterface $messageManager,
7285
DataSerializer $dataSerializer,
73-
FormKey $formKey
86+
FormKey $formKey,
87+
Validator $formKeyValidator
7488
) {
7589
$this->customerSession = $customerSession;
7690
$this->authenticationState = $authenticationState;
@@ -79,18 +93,19 @@ public function __construct(
7993
$this->messageManager = $messageManager;
8094
$this->dataSerializer = $dataSerializer;
8195
$this->formKey = $formKey;
96+
$this->formKeyValidator = $formKeyValidator;
8297
}
8398

8499
/**
85100
* Perform customer authentication and wishlist feature state checks
86101
*
87-
* @param \Magento\Framework\App\ActionInterface $subject
102+
* @param ActionInterface $subject
88103
* @param RequestInterface $request
89104
* @return void
90-
* @throws \Magento\Framework\Exception\NotFoundException
105+
* @throws NotFoundException
91106
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
92107
*/
93-
public function beforeDispatch(\Magento\Framework\App\ActionInterface $subject, RequestInterface $request)
108+
public function beforeDispatch(ActionInterface $subject, RequestInterface $request)
94109
{
95110
if ($this->authenticationState->isEnabled() && !$this->customerSession->authenticate()) {
96111
$subject->getActionFlag()->set('', 'no-dispatch', true);
@@ -99,25 +114,32 @@ public function beforeDispatch(\Magento\Framework\App\ActionInterface $subject,
99114
}
100115
$data = $request->getParams();
101116
unset($data['login']);
102-
$this->customerSession->setBeforeWishlistRequest($data);
103-
$this->customerSession->setBeforeRequestParams($this->customerSession->getBeforeWishlistRequest());
104-
$this->customerSession->setBeforeModuleName('wishlist');
105-
$this->customerSession->setBeforeControllerName('index');
106-
$this->customerSession->setBeforeAction('add');
117+
if (!($subject instanceof HttpPostActionInterface) || $this->formKeyValidator->validate($request)) {
118+
$this->customerSession->setBeforeWishlistRequest($data);
119+
$this->customerSession->setBeforeRequestParams($this->customerSession->getBeforeWishlistRequest());
120+
$this->customerSession->setBeforeModuleName('wishlist');
121+
$this->customerSession->setBeforeControllerName('index');
122+
$this->customerSession->setBeforeAction($request->getActionName());
123+
}
107124

108125
if ($request->getActionName() === 'add') {
109126
$this->messageManager->addErrorMessage(__('You must login or register to add items to your wishlist.'));
110127
}
111128
} elseif ($this->customerSession->authenticate()) {
112129
if ($this->customerSession->getBeforeWishlistRequest()) {
113-
$request->setParams($this->customerSession->getBeforeWishlistRequest());
130+
$data = $this->customerSession->getBeforeWishlistRequest();
131+
// Bypass CSRF validation as the data comes from a request that was validated
132+
$data['form_key'] = $this->formKey->getFormKey();
133+
$request->clearParams();
134+
$request->setParams($data);
114135
$this->customerSession->unsBeforeWishlistRequest();
115136
} elseif ($request->getParam('token')) {
116137
// check if the token is valid and retrieve the data
117138
$data = $this->dataSerializer->unserialize($request->getParam('token'));
118139
// Bypass CSRF validation if the token is valid
119140
if ($data) {
120141
$data['form_key'] = $this->formKey->getFormKey();
142+
$request->clearParams();
121143
$request->setParams($data);
122144
}
123145
}

app/code/Magento/Wishlist/Test/Unit/Controller/Index/PluginTest.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Magento\Framework\App\Request\Http;
1616
use Magento\Framework\App\Response\RedirectInterface;
1717
use Magento\Framework\Data\Form\FormKey;
18+
use Magento\Framework\Data\Form\FormKey\Validator;
1819
use Magento\Framework\Message\ManagerInterface;
1920
use Magento\Store\App\Response\Redirect;
2021
use Magento\Store\Model\ScopeInterface;
@@ -73,6 +74,11 @@ class PluginTest extends TestCase
7374
*/
7475
private $formKey;
7576

77+
/**
78+
* @var Validator|MockObject
79+
*/
80+
private $formKeyValidator;
81+
7682
/**
7783
* @inheritdoc
7884
*/
@@ -101,6 +107,7 @@ protected function setUp(): void
101107
$this->request = $this->createMock(Http::class);
102108
$this->dataSerializer = $this->createMock(DataSerializer::class);
103109
$this->formKey = $this->createMock(FormKey::class);
110+
$this->formKeyValidator = $this->createMock(Validator::class);
104111
}
105112

106113
/**
@@ -115,7 +122,8 @@ protected function getPlugin()
115122
$this->redirector,
116123
$this->messageManager,
117124
$this->dataSerializer,
118-
$this->formKey
125+
$this->formKey,
126+
$this->formKeyValidator
119127
);
120128
}
121129

@@ -157,6 +165,11 @@ public function testBeforeDispatch()
157165
->method('getParams')
158166
->willReturn($params);
159167

168+
$this->request
169+
->expects($this->exactly(2))
170+
->method('getActionName')
171+
->willReturn('add');
172+
160173
$this->customerSession->expects($this->once())
161174
->method('authenticate')
162175
->willReturn(false);

dev/tests/integration/testsuite/Magento/Wishlist/Controller/Index/AddTest.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010
use Magento\Catalog\Api\ProductRepositoryInterface;
1111
use Magento\Customer\Model\Session;
1212
use Magento\Framework\App\Request\Http as HttpRequest;
13+
use Magento\Framework\App\ResponseInterface;
1314
use Magento\Framework\Escaper;
1415
use Magento\Framework\Message\MessageInterface;
16+
use Magento\TestFramework\Helper\Bootstrap;
1517
use Magento\TestFramework\TestCase\AbstractController;
1618
use Magento\TestFramework\Wishlist\Model\GetWishlistByCustomerId;
1719
use Laminas\Stdlib\Parameters;
@@ -27,6 +29,7 @@
2729
* @magentoDbIsolation disabled
2830
* @magentoAppArea frontend
2931
* @magentoDataFixture Magento/Customer/_files/customer.php
32+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
3033
*/
3134
class AddTest extends AbstractController
3235
{
@@ -247,6 +250,41 @@ public function testAddToWishlistOnCustomerConfirmation(): void
247250
$this->assertSuccess((int)$customer->getId(), 1, $product->getName());
248251
}
249252

253+
/**
254+
* @magentoConfigFixture current_store customer/captcha/enable 0
255+
* @magentoDataFixture Magento/Customer/_files/customer.php
256+
* @magentoDataFixture Magento/Catalog/_files/product_simple.php
257+
*/
258+
public function testAddToWishlistBeforeLogin(): void
259+
{
260+
$this->prepareReferer();
261+
$product = $this->productRepository->get('simple');
262+
$this->performAddToWishListRequest(['product' => $product->getId()]);
263+
$this->assertSessionMessages(
264+
$this->equalTo([(string)__('You must login or register to add items to your wishlist.')]),
265+
MessageInterface::TYPE_ERROR
266+
);
267+
268+
// re-initialize the application to make a second request
269+
Bootstrap::getInstance()->getBootstrap()->getApplication()->reinitialize();
270+
$this->_objectManager = Bootstrap::getObjectManager();
271+
$this->customerSession = $this->_objectManager->get(Session::class);
272+
$this->_request = null;
273+
$this->_response = null;
274+
275+
// login
276+
$this->getRequest()->setMethod(HttpRequest::METHOD_POST);
277+
$this->getRequest()->setPostValue([
278+
'login' => [
279+
'username' => 'customer@example.com',
280+
'password' => 'password',
281+
],
282+
]);
283+
$this->dispatch('customer/account/loginPost');
284+
$this->assertTrue($this->customerSession->isLoggedIn());
285+
$this->assertSuccess(1, 1, $product->getName());
286+
}
287+
250288
/**
251289
* Perform request add item to wish list.
252290
*

0 commit comments

Comments
 (0)