Skip to content

Commit 01441da

Browse files
author
Ievgen Shakhsuvarov
committed
MAGETWO-37037: Customers information leak via checkout
1 parent 78959d7 commit 01441da

File tree

3 files changed

+295
-0
lines changed

3 files changed

+295
-0
lines changed

app/code/Magento/Multishipping/Model/Checkout/Type/Multishipping.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use Magento\Customer\Api\AddressRepositoryInterface;
1212
use Magento\Framework\Pricing\PriceCurrencyInterface;
1313
use Magento\Sales\Model\Order\Email\Sender\OrderSender;
14+
use Magento\Framework\Exception\LocalizedException;
1415

1516
/**
1617
* Multishipping checkout model
@@ -453,6 +454,7 @@ public function setShippingItemsInformation($info)
453454
*
454455
* @param int $quoteItemId
455456
* @param array $data array('qty'=>$qty, 'address'=>$customerAddressId)
457+
* @throws \Magento\Framework\Exception\LocalizedException
456458
* @return \Magento\Multishipping\Model\Checkout\Type\Multishipping
457459
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
458460
* @SuppressWarnings(PHPMD.NPathComplexity)
@@ -462,6 +464,11 @@ protected function _addShippingItem($quoteItemId, $data)
462464
$qty = isset($data['qty']) ? (int)$data['qty'] : 1;
463465
//$qty = $qty > 0 ? $qty : 1;
464466
$addressId = isset($data['address']) ? $data['address'] : false;
467+
468+
if (!$this->isAddressIdApplicable($addressId)) {
469+
throw new LocalizedException(__('Please check shipping address information.'));
470+
}
471+
465472
$quoteItem = $this->getQuote()->getItemById($quoteItemId);
466473

467474
if ($addressId && $quoteItem) {
@@ -503,10 +510,14 @@ protected function _addShippingItem($quoteItemId, $data)
503510
* Reimport customer address info to quote shipping address
504511
*
505512
* @param int $addressId customer address id
513+
* @throws \Magento\Framework\Exception\LocalizedException
506514
* @return \Magento\Multishipping\Model\Checkout\Type\Multishipping
507515
*/
508516
public function updateQuoteCustomerShippingAddress($addressId)
509517
{
518+
if (!$this->isAddressIdApplicable($addressId)) {
519+
throw new LocalizedException(__('Please check shipping address information.'));
520+
}
510521
try {
511522
$address = $this->addressRepository->getById($addressId);
512523
} catch (\Exception $e) {
@@ -530,10 +541,14 @@ public function updateQuoteCustomerShippingAddress($addressId)
530541
* Reimport customer billing address to quote
531542
*
532543
* @param int $addressId customer address id
544+
* @throws \Magento\Framework\Exception\LocalizedException
533545
* @return \Magento\Multishipping\Model\Checkout\Type\Multishipping
534546
*/
535547
public function setQuoteCustomerBillingAddress($addressId)
536548
{
549+
if (!$this->isAddressIdApplicable($addressId)) {
550+
throw new LocalizedException(__('Please check billing address information.'));
551+
}
537552
try {
538553
$address = $this->addressRepository->getById($addressId);
539554
} catch (\Exception $e) {
@@ -931,4 +946,22 @@ public function getCustomer()
931946
{
932947
return $this->_customerSession->getCustomerDataObject();
933948
}
949+
950+
/**
951+
* Check if specified address ID belongs to customer.
952+
*
953+
* @param $addressId
954+
* @return bool
955+
*/
956+
protected function isAddressIdApplicable($addressId)
957+
{
958+
$applicableAddressIds = array_map(function($address) {
959+
/** @var \Magento\Customer\Api\Data\AddressInterface $address */
960+
return $address->getId();
961+
}, $this->getCustomer()->getAddresses());
962+
if (in_array($addressId, $applicableAddressIds)) {
963+
return true;
964+
}
965+
return false;
966+
}
934967
}
Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
<?php
2+
/**
3+
* Copyright © 2015 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Multishipping\Test\Unit\Model\Checkout\Type;
7+
8+
class MultishippingTest extends \PHPUnit_Framework_TestCase
9+
{
10+
/**
11+
* @var \Magento\Multishipping\Model\Checkout\Type\Multishipping
12+
*/
13+
protected $model;
14+
15+
/**
16+
* @var \PHPUnit_Framework_MockObject_MockObject
17+
*/
18+
protected $checkoutSessionMock;
19+
20+
/**
21+
* @var \PHPUnit_Framework_MockObject_MockObject
22+
*/
23+
protected $customerSessionMock;
24+
25+
/**
26+
* @var \PHPUnit_Framework_MockObject_MockObject
27+
*/
28+
protected $customerMock;
29+
30+
/**
31+
* @var \PHPUnit_Framework_MockObject_MockObject
32+
*/
33+
protected $quoteMock;
34+
35+
/**
36+
* @var \PHPUnit_Framework_MockObject_MockObject
37+
*/
38+
protected $helperMock;
39+
40+
/**
41+
* @var \PHPUnit_Framework_MockObject_MockObject
42+
*/
43+
protected $filterBuilderMock;
44+
45+
/**
46+
* @var \PHPUnit_Framework_MockObject_MockObject
47+
*/
48+
protected $addressRepositoryMock;
49+
50+
/**
51+
* @var \PHPUnit_Framework_MockObject_MockObject
52+
*/
53+
protected $searchCriteriaBuilderMock;
54+
55+
protected function setUp()
56+
{
57+
$this->checkoutSessionMock = $this->getMock('\Magento\Checkout\Model\Session', [], [], '', false);
58+
$this->customerSessionMock = $this->getMock('\Magento\Customer\Model\Session', [], [], '', false);
59+
$orderFactoryMock = $this->getMock('\Magento\Sales\Model\OrderFactory', [], [], '', false);
60+
$eventManagerMock = $this->getMock('\Magento\Framework\Event\ManagerInterface', [], [], '', false);
61+
$scopeConfigMock = $this->getMock('\Magento\Framework\App\Config\ScopeConfigInterface', [], [], '', false);
62+
$sessionMock = $this->getMock('\Magento\Framework\Session\Generic', [], [], '', false);
63+
$addressFactoryMock = $this->getMock('\Magento\Quote\Model\Quote\AddressFactory', [], [], '', false);
64+
$toOrderMock = $this->getMock('\Magento\Quote\Model\Quote\Address\ToOrder', [], [], '', false);
65+
$toOrderAddressMock = $this->getMock('\Magento\Quote\Model\Quote\Address\ToOrderAddress', [], [], '', false);
66+
$toOrderPaymentMock = $this->getMock('\Magento\Quote\Model\Quote\Payment\ToOrderPayment', [], [], '', false);
67+
$toOrderItemMock = $this->getMock('\Magento\Quote\Model\Quote\Item\ToOrderItem', [], [], '', false);
68+
$storeManagerMock = $this->getMock('\Magento\Store\Model\StoreManagerInterface', [], [], '', false);
69+
$paymentSpecMock = $this->getMock('\Magento\Payment\Model\Method\SpecificationInterface', [], [], '', false);
70+
$this->helperMock = $this->getMock('\Magento\Multishipping\Helper\Data', [], [], '', false);
71+
$orderSenderMock = $this->getMock('\Magento\Sales\Model\Order\Email\Sender\OrderSender', [], [], '', false);
72+
$priceMock = $this->getMock('\Magento\Framework\Pricing\PriceCurrencyInterface', [], [], '', false);
73+
$quoteRepositoryMock = $this->getMock('\Magento\Quote\Model\QuoteRepository', [], [], '', false);
74+
$this->filterBuilderMock = $this->getMock('\Magento\Framework\Api\FilterBuilder', [], [], '', false);
75+
$this->searchCriteriaBuilderMock = $this->getMock(
76+
'\Magento\Framework\Api\SearchCriteriaBuilder',
77+
[],
78+
[],
79+
'',
80+
false
81+
);
82+
$this->addressRepositoryMock = $this->getMock(
83+
'\Magento\Customer\Api\AddressRepositoryInterface',
84+
[],
85+
[],
86+
'',
87+
false
88+
);
89+
90+
/**
91+
* This is used to get past _init() which is called in construct.
92+
*/
93+
$data['checkout_session'] = $this->checkoutSessionMock;
94+
$this->quoteMock = $this->getMock('\Magento\Quote\Model\Quote', [], [], '', false);
95+
$this->customerMock = $this->getMock('\Magento\Customer\Api\Data\CustomerInterface', [], [], '', false);
96+
$this->customerMock->expects($this->atLeastOnce())->method('getId')->willReturn(null);
97+
$this->checkoutSessionMock->expects($this->atLeastOnce())->method('getQuote')->willReturn($this->quoteMock);
98+
$this->customerSessionMock->expects($this->atLeastOnce())->method('getCustomerDataObject')
99+
->willReturn($this->customerMock);
100+
101+
$this->model = new \Magento\Multishipping\Model\Checkout\Type\Multishipping(
102+
$this->checkoutSessionMock,
103+
$this->customerSessionMock,
104+
$orderFactoryMock,
105+
$this->addressRepositoryMock,
106+
$eventManagerMock,
107+
$scopeConfigMock,
108+
$sessionMock,
109+
$addressFactoryMock,
110+
$toOrderMock,
111+
$toOrderAddressMock,
112+
$toOrderPaymentMock,
113+
$toOrderItemMock,
114+
$storeManagerMock,
115+
$paymentSpecMock,
116+
$this->helperMock,
117+
$orderSenderMock,
118+
$priceMock,
119+
$quoteRepositoryMock,
120+
$this->searchCriteriaBuilderMock,
121+
$this->filterBuilderMock,
122+
$data
123+
);
124+
}
125+
126+
public function testSetShippingItemsInformation()
127+
{
128+
$info = [
129+
[
130+
1 => [
131+
'qty' => 2,
132+
'address' => 42
133+
]
134+
]
135+
];
136+
$customerAddressId = 42;
137+
138+
$customerAddressMock = $this->getMock('\Magento\Customer\Model\Data\Address', [], [], '', false);
139+
$customerAddressMock->expects($this->atLeastOnce())->method('getId')->willReturn($customerAddressId);
140+
$customerAddresses = [$customerAddressMock];
141+
142+
$this->quoteMock->expects($this->once())->method('getAllShippingAddresses')->willReturn([]);
143+
$this->checkoutSessionMock->expects($this->any())->method('getQuote')->willReturn($this->quoteMock);
144+
145+
$this->helperMock->expects($this->once())->method('getMaximumQty')->willReturn(500);
146+
147+
$this->customerMock->expects($this->once())->method('getAddresses')->willReturn($customerAddresses);
148+
$this->quoteMock->expects($this->once())->method('getItemById')->with(array_keys($info[0])[0])
149+
->willReturn(null);
150+
151+
$this->quoteMock->expects($this->atLeastOnce())->method('getAllItems')->willReturn([]);
152+
153+
$this->filterBuilderMock->expects($this->atLeastOnce())->method('setField')->willReturnSelf();
154+
$this->filterBuilderMock->expects($this->atLeastOnce())->method('setValue')->willReturnSelf();
155+
$this->filterBuilderMock->expects($this->atLeastOnce())->method('setConditionType')->willReturnSelf();
156+
$this->filterBuilderMock->expects($this->atLeastOnce())->method('create')->willReturnSelf();
157+
158+
$searchCriteriaMock = $this->getMock('\Magento\Framework\Api\SearchCriteria', [], [], '', false);
159+
$this->searchCriteriaBuilderMock->expects($this->atLeastOnce())->method('addFilter')->willReturnSelf();
160+
$this->searchCriteriaBuilderMock->expects($this->atLeastOnce())->method('create')
161+
->willReturn($searchCriteriaMock);
162+
163+
$resultMock = $this->getMock('\Magento\Customer\Api\Data\AddressSearchResultsInterface', [], [], '', false);
164+
$this->addressRepositoryMock->expects($this->atLeastOnce())->method('getList')->willReturn($resultMock);
165+
$addressItemMock = $this->getMock('\Magento\Customer\Api\Data\AddressInterface', [], [], '', false);
166+
$resultMock->expects($this->atLeastOnce())->method('getItems')->willReturn([$addressItemMock]);
167+
$addressItemMock->expects($this->atLeastOnce())->method('getId')->willReturn(null);
168+
169+
$this->assertEquals($this->model, $this->model->setShippingItemsInformation($info));
170+
}
171+
172+
/**
173+
* @expectedException \Magento\Framework\Exception\LocalizedException
174+
* @expectedExceptionMessage Please check shipping address information.
175+
*/
176+
public function testSetShippingItemsInformationForAddressLeak()
177+
{
178+
$info = [
179+
[
180+
1 => [
181+
'qty' => 2,
182+
'address' => 43
183+
]
184+
]
185+
];
186+
$customerAddressId = 42;
187+
188+
$customerAddressMock = $this->getMock('\Magento\Customer\Model\Data\Address', [], [], '', false);
189+
$customerAddressMock->expects($this->atLeastOnce())->method('getId')->willReturn($customerAddressId);
190+
$customerAddresses = [$customerAddressMock];
191+
192+
$this->quoteMock->expects($this->once())->method('getAllShippingAddresses')->willReturn([]);
193+
$this->checkoutSessionMock->expects($this->any())->method('getQuote')->willReturn($this->quoteMock);
194+
$this->helperMock->expects($this->once())->method('getMaximumQty')->willReturn(500);
195+
$this->customerMock->expects($this->once())->method('getAddresses')->willReturn($customerAddresses);
196+
197+
$this->assertEquals($this->model, $this->model->setShippingItemsInformation($info));
198+
}
199+
200+
public function testupdateQuoteCustomerShippingAddress()
201+
{
202+
$addressId = 42;
203+
$customerAddressId = 42;
204+
205+
$customerAddressMock = $this->getMock('\Magento\Customer\Model\Data\Address', [], [], '', false);
206+
$customerAddressMock->expects($this->atLeastOnce())->method('getId')->willReturn($customerAddressId);
207+
$customerAddresses = [$customerAddressMock];
208+
$this->customerMock->expects($this->once())->method('getAddresses')->willReturn($customerAddresses);
209+
210+
$this->addressRepositoryMock->expects($this->once())->method('getById')->willReturn(null);
211+
212+
$this->assertEquals($this->model, $this->model->updateQuoteCustomerShippingAddress($addressId));
213+
}
214+
215+
/**
216+
* @expectedException \Magento\Framework\Exception\LocalizedException
217+
* @expectedExceptionMessage Please check shipping address information.
218+
*/
219+
public function testupdateQuoteCustomerShippingAddressForAddressLeak()
220+
{
221+
$addressId = 43;
222+
$customerAddressId = 42;
223+
224+
$customerAddressMock = $this->getMock('\Magento\Customer\Model\Data\Address', [], [], '', false);
225+
$customerAddressMock->expects($this->atLeastOnce())->method('getId')->willReturn($customerAddressId);
226+
$customerAddresses = [$customerAddressMock];
227+
$this->customerMock->expects($this->once())->method('getAddresses')->willReturn($customerAddresses);
228+
229+
$this->assertEquals($this->model, $this->model->updateQuoteCustomerShippingAddress($addressId));
230+
}
231+
232+
public function testSetQuoteCustomerBillingAddress()
233+
{
234+
$addressId = 42;
235+
$customerAddressId = 42;
236+
237+
$customerAddressMock = $this->getMock('\Magento\Customer\Model\Data\Address', [], [], '', false);
238+
$customerAddressMock->expects($this->atLeastOnce())->method('getId')->willReturn($customerAddressId);
239+
$customerAddresses = [$customerAddressMock];
240+
$this->customerMock->expects($this->once())->method('getAddresses')->willReturn($customerAddresses);
241+
242+
$this->assertEquals($this->model, $this->model->setQuoteCustomerBillingAddress($addressId));
243+
}
244+
245+
/**
246+
* @expectedException \Magento\Framework\Exception\LocalizedException
247+
* @expectedExceptionMessage Please check billing address information.
248+
*/
249+
public function testSetQuoteCustomerBillingAddressForAddressLeak()
250+
{
251+
$addressId = 43;
252+
$customerAddressId = 42;
253+
254+
$customerAddressMock = $this->getMock('\Magento\Customer\Model\Data\Address', [], [], '', false);
255+
$customerAddressMock->expects($this->atLeastOnce())->method('getId')->willReturn($customerAddressId);
256+
$customerAddresses = [$customerAddressMock];
257+
$this->customerMock->expects($this->once())->method('getAddresses')->willReturn($customerAddresses);
258+
259+
$this->assertEquals($this->model, $this->model->setQuoteCustomerBillingAddress($addressId));
260+
}
261+
}

app/code/Magento/Multishipping/i18n/en_US.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ Change,Change
4444
"Please check shipping addresses information.","Please check shipping addresses information."
4545
"Please specify shipping methods for all addresses.","Please specify shipping methods for all addresses."
4646
"Please check billing address information.","Please check billing address information."
47+
"Please check shipping address information.","Please check shipping address information."
4748
"Select Addresses","Select Addresses"
4849
"Order Success","Order Success"
4950
"Default Billing","Default Billing"

0 commit comments

Comments
 (0)