Skip to content

Commit 4dc993d

Browse files
author
Bomko, Alex(abomko)
committed
Merge pull request magento#1 from magento-mpi/MAGETWO-42955
MAGETWO-42955: Update Migration Tool with handler to migrate customer password after hashing alg changed
2 parents 8d858a7 + c21227a commit 4dc993d

2 files changed

Lines changed: 250 additions & 0 deletions

File tree

src/Migration/Step/Customer/Helper.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,10 @@ public function updateAttributeData($attributeType, $sourceDocName, $destination
156156
/** @var Record $record */
157157
foreach ($destinationRecords as $record) {
158158
if (isset($recordAttributesData[$record->getValue('entity_id')])) {
159+
$recordAttributesData = $this->upgradeCustomerHash(
160+
$recordAttributesData,
161+
$record->getValue('entity_id')
162+
);
159163
$data = $record->getData();
160164
$data = array_merge(
161165
array_fill_keys($attributeCodes, null),
@@ -310,4 +314,26 @@ public function updateEavAttributes()
310314
}
311315
}
312316
}
317+
318+
/**
319+
* Upgrade customer hash according M2 algorithm versions
320+
*
321+
* @param array $recordAttributesData
322+
* @param string $entityId
323+
* @return array
324+
*/
325+
private function upgradeCustomerHash($recordAttributesData, $entityId)
326+
{
327+
if (isset($recordAttributesData[$entityId]['password_hash'])) {
328+
list($hash, $salt) = explode(':', $recordAttributesData[$entityId]['password_hash'], 2);
329+
330+
if (strlen($hash) == 32) {
331+
$recordAttributesData[$entityId]['password_hash'] = implode(':', [$hash, $salt, '0']);
332+
} elseif (strlen($hash) == 64) {
333+
$recordAttributesData[$entityId]['password_hash'] = implode(':', [$hash, $salt, '1']);
334+
}
335+
}
336+
337+
return $recordAttributesData;
338+
}
313339
}
Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
<?php
2+
/**
3+
* Copyright © 2015 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace unit\testsuite\Migration\Step\Customer;
7+
8+
use Migration\Step\Customer\Helper;
9+
10+
class HelperTest extends \PHPUnit_Framework_TestCase
11+
{
12+
/**
13+
* Entity name
14+
*/
15+
const ENTITY = 'customer';
16+
17+
/**
18+
* Document name
19+
*/
20+
const DOCUMENT = 'customer_entity';
21+
22+
/**
23+
* Attribute name
24+
*/
25+
const ATTRIBUTE = 'password_hash';
26+
/**
27+
* @var Helper
28+
*/
29+
protected $helper;
30+
31+
/**
32+
* @var \Migration\Resource\Source|\PHPUnit_Framework_MockObject_MockObject
33+
*/
34+
protected $source;
35+
36+
/**
37+
* @var \Migration\Resource\Destination|\PHPUnit_Framework_MockObject_MockObject
38+
*/
39+
protected $destination;
40+
41+
/**
42+
* @var \Migration\Reader\Groups|\PHPUnit_Framework_MockObject_MockObject
43+
*/
44+
protected $readerAttributes;
45+
46+
/**
47+
* @var \Migration\Reader\Groups|\PHPUnit_Framework_MockObject_MockObject
48+
*/
49+
protected $readerGroups;
50+
51+
/**
52+
* @var \Migration\Resource\Adapter\Mysql|\PHPUnit_Framework_MockObject_MockObject
53+
*/
54+
protected $adapter;
55+
56+
/**
57+
* @var \Magento\Framework\DB\Select|\PHPUnit_Framework_MockObject_MockObject
58+
*/
59+
protected $select;
60+
61+
/**
62+
* @var array
63+
*/
64+
protected $sourceDocuments = [
65+
self::DOCUMENT => 'entity_id'
66+
];
67+
68+
/**
69+
* @var array
70+
*/
71+
protected $attribute = [
72+
[
73+
'attribute_id' => '12',
74+
'backend_type' => 'varchar',
75+
'attribute_code' => self::ATTRIBUTE,
76+
'entity_type_id' => '1'
77+
]
78+
];
79+
80+
public function setUp()
81+
{
82+
$this->adapter = $this->getMockBuilder('Migration\Resource\Adapter\Mysql')
83+
->setMethods(['fetchAll', 'getSelect'])
84+
->disableOriginalConstructor()
85+
->getMock();
86+
$this->select = $this->getMockBuilder('Magento\Framework\DB\Select')
87+
->setMethods(['from', 'join', 'where', 'getAdapter'])
88+
->disableOriginalConstructor()
89+
->getMock();
90+
$this->select->expects($this->any())->method('from')->willReturnSelf();
91+
$this->select->expects($this->any())->method('join')->willReturnSelf();
92+
$this->select->expects($this->any())->method('where')->willReturnSelf();
93+
$this->select->expects($this->any())->method('getAdapter')->willReturn($this->adapter);
94+
$this->adapter->expects($this->any())->method('getSelect')->willReturn($this->select);
95+
96+
$this->source = $this->getMockBuilder('Migration\Resource\Source')
97+
->disableOriginalConstructor()
98+
->getMock();
99+
$this->destination = $this->getMockBuilder('Migration\Resource\Destination')
100+
->disableOriginalConstructor()
101+
->getMock();
102+
103+
$this->readerAttributes = $this->getMockBuilder('Migration\Reader\Groups')
104+
->disableOriginalConstructor()
105+
->getMock();
106+
107+
$this->readerGroups = $this->getMockBuilder('Migration\Reader\Groups')
108+
->setMethods(['getGroup'])
109+
->disableOriginalConstructor()
110+
->getMock();
111+
$this->readerGroups->expects($this->at(0))
112+
->method('getGroup')
113+
->with('source_documents')
114+
->willReturn($this->sourceDocuments);
115+
116+
$groupsFactory = $this->getMockBuilder('Migration\Reader\GroupsFactory')
117+
->setMethods(['create'])
118+
->disableOriginalConstructor()
119+
->getMock();
120+
$groupsFactory->expects($this->at(0))
121+
->method('create')
122+
->with('customer_attribute_groups_file')
123+
->willReturn($this->readerAttributes);
124+
$groupsFactory->expects($this->at(1))
125+
->method('create')
126+
->with('customer_document_groups_file')
127+
->willReturn($this->readerGroups);
128+
129+
$this->helper = new Helper(
130+
$this->source,
131+
$this->destination,
132+
$groupsFactory
133+
);
134+
}
135+
136+
/**
137+
* @param array $attributeData
138+
* @param array $expected
139+
*
140+
* @dataProvider dataProviderUpdateAttributeData
141+
*/
142+
public function testUpdateAttributeData($attributeData, $expected)
143+
{
144+
$this->getAttributeType();
145+
146+
$this->readerAttributes->expects($this->any())
147+
->method('getGroup')
148+
->with(self::DOCUMENT)
149+
->willReturn($this->attribute);
150+
151+
$this->adapter->expects($this->at(2))->method('fetchAll')->with($this->select)->willReturn($attributeData);
152+
153+
$structure = $this->getMockBuilder('Migration\Resource\Structure')
154+
->disableOriginalConstructor()
155+
->getMock();
156+
$record = $this->getMockBuilder('Migration\Resource\Record')
157+
->disableOriginalConstructor()
158+
->getMock();
159+
$record->expects($this->any())->method('getValue')->with('entity_id')->willReturn('1');
160+
$record->expects($this->any())->method('getData')->willReturn([]);
161+
$record->expects($this->any())->method('setData')->with($expected);
162+
$destinationRecords = new \Migration\Resource\Record\Collection($structure, [$record]);
163+
164+
$this->helper->updateAttributeData(self::ENTITY, self::DOCUMENT, $destinationRecords);
165+
}
166+
167+
/**
168+
* Init EAV attributes
169+
*/
170+
protected function getAttributeType()
171+
{
172+
$entities = [self::ENTITY => ''];
173+
$documentGroups = [self::ATTRIBUTE => ''];
174+
175+
$this->readerGroups->expects($this->at(0))
176+
->method('getGroup')
177+
->with('eav_entities')
178+
->willReturn($entities);
179+
$this->readerGroups->expects($this->at(1))
180+
->method('getGroup')
181+
->with(self::ENTITY)
182+
->willReturn($this->sourceDocuments);
183+
184+
$this->source->expects($this->any())->method('getAdapter')->willReturn($this->adapter);
185+
$this->adapter->expects($this->at(1))->method('fetchAll')->with($this->select)->willReturn($this->attribute);
186+
187+
$this->readerAttributes->expects($this->any())->method('getGroup')->willReturn($documentGroups);
188+
189+
$this->helper->getAttributeType(self::DOCUMENT);
190+
}
191+
192+
/**
193+
* @return array
194+
*/
195+
public function dataProviderUpdateAttributeData()
196+
{
197+
return [
198+
[
199+
[
200+
[
201+
'entity_id' => '1',
202+
'attribute_id' => '12',
203+
'value' => '34356a3d028accfb3c2996827b706bf5:UmPvGtih25eQCjC5f6NMwqkds500x2Jd'
204+
]
205+
],
206+
[
207+
self::ATTRIBUTE => '34356a3d028accfb3c2996827b706bf5:UmPvGtih25eQCjC5f6NMwqkds500x2Jd:0'
208+
]
209+
],
210+
[
211+
[
212+
[
213+
'entity_id' => '1',
214+
'attribute_id' => '12',
215+
'value' => '123123q:UmPvGtih25eQCjC5f6NMwqkds500x2Jd'
216+
]
217+
],
218+
[
219+
self::ATTRIBUTE => '123123q:UmPvGtih25eQCjC5f6NMwqkds500x2Jd'
220+
]
221+
]
222+
];
223+
}
224+
}

0 commit comments

Comments
 (0)