Skip to content

Commit e80efd8

Browse files
Merge pull request #7302 from magento-cia/AC-1323-updated
Bugfixes
2 parents ae15acb + d261568 commit e80efd8

File tree

16 files changed

+253
-80
lines changed

16 files changed

+253
-80
lines changed

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

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use Magento\Framework\Controller\Result\Redirect;
1818
use Magento\Framework\View\Result\Page;
1919
use Magento\Framework\View\Result\PageFactory;
20+
use Magento\Customer\Api\CustomerRepositoryInterface;
2021

2122
/**
2223
* Controller for front-end customer password reset form
@@ -48,21 +49,28 @@ class CreatePassword extends \Magento\Customer\Controller\AbstractAccount implem
4849
*/
4950
private $getByToken;
5051

52+
/**
53+
* @var CustomerRepositoryInterface
54+
*/
55+
private $customerRepository;
56+
5157
/**
5258
* @param Context $context
5359
* @param Session $customerSession
5460
* @param PageFactory $resultPageFactory
5561
* @param AccountManagementInterface $accountManagement
5662
* @param ConfirmCustomerByToken|null $confirmByToken
5763
* @param GetCustomerByToken|null $getByToken
64+
* @param CustomerRepositoryInterface|null $customerRepository
5865
*/
5966
public function __construct(
6067
Context $context,
6168
Session $customerSession,
6269
PageFactory $resultPageFactory,
6370
AccountManagementInterface $accountManagement,
6471
ConfirmCustomerByToken $confirmByToken = null,
65-
GetCustomerByToken $getByToken = null
72+
GetCustomerByToken $getByToken = null,
73+
CustomerRepositoryInterface $customerRepository = null
6674
) {
6775
$this->session = $customerSession;
6876
$this->resultPageFactory = $resultPageFactory;
@@ -71,6 +79,8 @@ public function __construct(
7179
?? ObjectManager::getInstance()->get(ConfirmCustomerByToken::class);
7280
$this->getByToken = $getByToken
7381
?? ObjectManager::getInstance()->get(GetCustomerByToken::class);
82+
$this->customerRepository = $customerRepository
83+
?? ObjectManager::getInstance()->get(CustomerRepositoryInterface::class);
7484

7585
parent::__construct($context);
7686
}
@@ -83,23 +93,25 @@ public function __construct(
8393
public function execute()
8494
{
8595
$resetPasswordToken = (string)$this->getRequest()->getParam('token');
96+
$customerId = (int)$this->getRequest()->getParam('id');
8697
$isDirectLink = $resetPasswordToken != '';
8798
if (!$isDirectLink) {
8899
$resetPasswordToken = (string)$this->session->getRpToken();
100+
$customerId = (int)$this->session->getRpCustomerId();
89101
}
90102

91103
try {
92-
$this->accountManagement->validateResetPasswordLinkToken(null, $resetPasswordToken);
93-
94-
$this->confirmByToken->execute($resetPasswordToken);
104+
$this->accountManagement->validateResetPasswordLinkToken($customerId, $resetPasswordToken);
105+
$this->confirmByToken->resetCustomerConfirmation($customerId);
95106

96107
// Extend token validity to avoid expiration while this form is
97108
// being completed by the user.
98-
$customer = $this->getByToken->execute($resetPasswordToken);
109+
$customer = $this->customerRepository->getById($customerId);
99110
$this->accountManagement->changeResetPasswordLinkToken($customer, $resetPasswordToken);
100111

101112
if ($isDirectLink) {
102113
$this->session->setRpToken($resetPasswordToken);
114+
$this->session->setRpCustomerId($customerId);
103115
$resultRedirect = $this->resultRedirectFactory->create();
104116
$resultRedirect->setPath('*/*/createpassword');
105117

@@ -109,7 +121,8 @@ public function execute()
109121
$resultPage = $this->resultPageFactory->create();
110122
$resultPage->getLayout()
111123
->getBlock('resetPassword')
112-
->setResetPasswordLinkToken($resetPasswordToken);
124+
->setResetPasswordLinkToken($resetPasswordToken)
125+
->setRpCustomerId($customerId);
113126

114127
return $resultPage;
115128
}

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,10 @@ public function execute()
6767
/** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */
6868
$resultRedirect = $this->resultRedirectFactory->create();
6969
$resetPasswordToken = (string)$this->getRequest()->getQuery('token');
70+
$customerId = (string)$this->getRequest()->getQuery('id');
7071
$password = (string)$this->getRequest()->getPost('password');
7172
$passwordConfirmation = (string)$this->getRequest()->getPost('password_confirmation');
73+
$email = null;
7274

7375
if ($password !== $passwordConfirmation) {
7476
$this->messageManager->addErrorMessage(__("New Password and Confirm New Password values didn't match."));
@@ -83,9 +85,13 @@ public function execute()
8385
return $resultRedirect;
8486
}
8587

88+
if ($customerId && $this->customerRepository->getById($customerId)) {
89+
$email = $this->customerRepository->getById($customerId)->getEmail();
90+
}
91+
8692
try {
8793
$this->accountManagement->resetPassword(
88-
null,
94+
$email,
8995
$resetPasswordToken,
9096
$password
9197
);
@@ -95,6 +101,7 @@ public function execute()
95101
$this->session->start();
96102
}
97103
$this->session->unsRpToken();
104+
$this->session->unsRpCustomerId();
98105
$this->messageManager->addSuccessMessage(__('You updated your password.'));
99106
$resultRedirect->setPath('*/*/login');
100107

app/code/Magento/Customer/Model/AccountManagement.php

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -704,8 +704,8 @@ private function handleUnknownTemplate($template)
704704
public function resetPassword($email, $resetToken, $newPassword)
705705
{
706706
if (!$email) {
707-
$customer = $this->getByToken->execute($resetToken);
708-
$email = $customer->getEmail();
707+
$params = ['fieldName' => 'email'];
708+
throw new InputException(__('"%fieldName" is required. Enter and try again.', $params));
709709
} else {
710710
$customer = $this->customerRepository->get($email);
711711
}
@@ -1163,24 +1163,17 @@ public function validateCustomerStoreIdByWebsiteId(CustomerInterface $customer)
11631163
* @throws NoSuchEntityException If customer doesn't exist
11641164
* @SuppressWarnings(PHPMD.LongVariable)
11651165
*/
1166-
private function validateResetPasswordToken($customerId, $resetPasswordLinkToken)
1166+
private function validateResetPasswordToken(int $customerId, string $resetPasswordLinkToken): bool
11671167
{
1168-
if ($customerId !== null && $customerId <= 0) {
1168+
if (!$customerId) {
11691169
throw new InputException(
11701170
__(
11711171
'Invalid value of "%value" provided for the %fieldName field.',
11721172
['value' => $customerId, 'fieldName' => 'customerId']
11731173
)
11741174
);
11751175
}
1176-
1177-
if ($customerId === null) {
1178-
//Looking for the customer.
1179-
$customerId = $this->getByToken
1180-
->execute($resetPasswordLinkToken)
1181-
->getId();
1182-
}
1183-
if (!is_string($resetPasswordLinkToken) || empty($resetPasswordLinkToken)) {
1176+
if (!$resetPasswordLinkToken) {
11841177
$params = ['fieldName' => 'resetPasswordLinkToken'];
11851178
throw new InputException(__('"%fieldName" is required. Enter and try again.', $params));
11861179
}
@@ -1451,7 +1444,7 @@ public function isResetPasswordLinkTokenExpired($rpToken, $rpTokenCreatedAt)
14511444
* @throws LocalizedException
14521445
* @throws NoSuchEntityException
14531446
*/
1454-
public function changeResetPasswordLinkToken($customer, $passwordLinkToken)
1447+
public function changeResetPasswordLinkToken(CustomerInterface $customer, string $passwordLinkToken): bool
14551448
{
14561449
if (!is_string($passwordLinkToken) || empty($passwordLinkToken)) {
14571450
throw new InputException(
@@ -1460,15 +1453,15 @@ public function changeResetPasswordLinkToken($customer, $passwordLinkToken)
14601453
['value' => $passwordLinkToken, 'fieldName' => 'password reset token']
14611454
)
14621455
);
1456+
} else {
1457+
$customerSecure = $this->customerRegistry->retrieveSecureData($customer->getId());
1458+
$customerSecure->setRpToken($passwordLinkToken);
1459+
$customerSecure->setRpTokenCreatedAt(
1460+
$this->dateTimeFactory->create()->format(DateTime::DATETIME_PHP_FORMAT)
1461+
);
1462+
$this->setIgnoreValidationFlag($customer);
1463+
$this->customerRepository->save($customer);
14631464
}
1464-
$customerSecure = $this->customerRegistry->retrieveSecureData($customer->getId());
1465-
$customerSecure->setRpToken($passwordLinkToken);
1466-
$customerSecure->setRpTokenCreatedAt(
1467-
$this->dateTimeFactory->create()->format(DateTime::DATETIME_PHP_FORMAT)
1468-
);
1469-
$this->setIgnoreValidationFlag($customer);
1470-
$this->customerRepository->save($customer);
1471-
14721465
return true;
14731466
}
14741467

app/code/Magento/Customer/Model/ForgotPasswordToken/ConfirmCustomerByToken.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,19 @@ private function resetConfirmation(CustomerInterface $customer): void
6565

6666
$this->customerRepository->save($customer);
6767
}
68+
69+
/**
70+
* Check if customer confirmation needs to be reset
71+
*
72+
* @param int $customerId
73+
* @return void
74+
*/
75+
public function resetCustomerConfirmation(int $customerId): void
76+
{
77+
$customer = $this->customerRepository->getById($customerId);
78+
79+
if ($customer) {
80+
$this->resetConfirmation($customer);
81+
}
82+
}
6883
}

app/code/Magento/Customer/Model/ForgotPasswordToken/GetCustomerByToken.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
/**
1818
* Get Customer By reset password token
1919
* @SuppressWarnings(PHPMD.LongVariable)
20+
* @deprecated Rp Tokens cannot be looked up directly
2021
*/
2122
class GetCustomerByToken
2223
{

app/code/Magento/Customer/Model/ResourceModel/Customer.php

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use Magento\Framework\App\ObjectManager;
1313
use Magento\Framework\Exception\AlreadyExistsException;
1414
use Magento\Framework\Validator\Exception as ValidatorException;
15+
use Magento\Framework\Encryption\EncryptorInterface;
1516

1617
/**
1718
* Customer entity resource model
@@ -54,6 +55,11 @@ class Customer extends \Magento\Eav\Model\Entity\VersionControl\AbstractEntity
5455
*/
5556
private $notificationStorage;
5657

58+
/**
59+
* @var EncryptorInterface
60+
*/
61+
private $encryptor;
62+
5763
/**
5864
* Customer constructor.
5965
*
@@ -66,6 +72,8 @@ class Customer extends \Magento\Eav\Model\Entity\VersionControl\AbstractEntity
6672
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
6773
* @param array $data
6874
* @param AccountConfirmation $accountConfirmation
75+
* @param EncryptorInterface|null $encryptor
76+
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
6977
*/
7078
public function __construct(
7179
\Magento\Eav\Model\Entity\Context $context,
@@ -76,7 +84,8 @@ public function __construct(
7684
\Magento\Framework\Stdlib\DateTime $dateTime,
7785
\Magento\Store\Model\StoreManagerInterface $storeManager,
7886
$data = [],
79-
AccountConfirmation $accountConfirmation = null
87+
AccountConfirmation $accountConfirmation = null,
88+
EncryptorInterface $encryptor = null
8089
) {
8190
parent::__construct($context, $entitySnapshot, $entityRelationComposite, $data);
8291

@@ -88,6 +97,8 @@ public function __construct(
8897
$this->setType('customer');
8998
$this->setConnection('customer_read');
9099
$this->storeManager = $storeManager;
100+
$this->encryptor = $encryptor ?? ObjectManager::getInstance()
101+
->get(EncryptorInterface::class);
91102
}
92103

93104
/**
@@ -176,6 +187,11 @@ protected function _beforeSave(\Magento\Framework\DataObject $customer)
176187
$this->_validate($customer);
177188
}
178189

190+
if ($customer->getData('rp_token')) {
191+
$rpToken = $customer->getData('rp_token');
192+
$customer->setRpToken($this->encryptor->encrypt($rpToken));
193+
}
194+
179195
return $this;
180196
}
181197

@@ -224,6 +240,10 @@ protected function _afterSave(\Magento\Framework\DataObject $customer)
224240
NotificationStorage::UPDATE_CUSTOMER_SESSION,
225241
$customer->getId()
226242
);
243+
if ($customer->getData('rp_token')) {
244+
$rpToken = $customer->getData('rp_token');
245+
$customer->setRpToken($this->encryptor->decrypt($rpToken));
246+
}
227247
return parent::_afterSave($customer);
228248
}
229249

@@ -445,4 +465,16 @@ public function updateSessionCutOff(int $customerId, int $timestamp): void
445465
$this->getConnection()->quoteInto('entity_id = ?', $customerId)
446466
);
447467
}
468+
469+
/**
470+
* @inheritDoc
471+
*/
472+
protected function _afterLoad(\Magento\Framework\DataObject $customer)
473+
{
474+
if ($customer->getData('rp_token')) {
475+
$rpToken = $customer->getData('rp_token');
476+
$customer->setRpToken($this->encryptor->decrypt($rpToken));
477+
}
478+
return parent::_afterLoad($customer); //
479+
}
448480
}

app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1751,7 +1751,7 @@ public function testValidateResetPasswordTokenBadResetPasswordLinkToken(): void
17511751
$this->expectException(InputException::class);
17521752
$this->expectExceptionMessage('"resetPasswordLinkToken" is required. Enter and try again.');
17531753

1754-
$this->accountManagement->validateResetPasswordLinkToken(22, null);
1754+
$this->accountManagement->validateResetPasswordLinkToken(22, '');
17551755
}
17561756

17571757
/**

app/code/Magento/Customer/view/frontend/email/password_reset_confirmation.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<!--@vars {
99
"var store.frontend_name":"Store Name",
1010
"var customer.name":"Customer Name",
11-
"var this.getUrl($store,'customer/account/createPassword/',[_query:[token:$customer.rp_token],_nosid:1])":"Reset Password URL"
11+
"var this.getUrl($store,'customer/account/createPassword/',[_query:[id:$customer.id,token:$customer.rp_token],_nosid:1])":"Reset Password URL"
1212
} @-->
1313
{{template config_path="design/email/header_template"}}
1414

@@ -22,7 +22,7 @@
2222
<table class="inner-wrapper" border="0" cellspacing="0" cellpadding="0" align="center">
2323
<tr>
2424
<td align="center">
25-
<a href="{{var this.getUrl($store,'customer/account/createPassword/',[_query:[token:$customer.rp_token],_nosid:1])}}" target="_blank">{{trans "Set a New Password"}}</a>
25+
<a href="{{var this.getUrl($store,'customer/account/createPassword/',[_query:[id:$customer.id,token:$customer.rp_token],_nosid:1])}}" target="_blank">{{trans "Set a New Password"}}</a>
2626
</td>
2727
</tr>
2828
</table>

app/code/Magento/Customer/view/frontend/templates/form/resetforgottenpassword.phtml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6-
6+
// phpcs:disable Generic.Files.LineLength.TooLong
7+
//phpcs:disable Magento2.Legacy.PhtmlTemplate
78
/** @var \Magento\Customer\Block\Account\Resetpassword $block */
89
?>
9-
<form action="<?= $block->escapeUrl($block->getUrl('*/*/resetpasswordpost', ['_query' => ['token' => $block->getResetPasswordLinkToken()]])) ?>"
10+
<form action="<?= $block->escapeUrl($block->getUrl('*/*/resetpasswordpost', ['_query' => ['id'=>$block->getRpCustomerId(),'token' => $block->getResetPasswordLinkToken()]])) ?>"
1011
method="post"
11-
<?php if ($block->isAutocompleteDisabled()) : ?> autocomplete="off"<?php endif; ?>
12+
<?php if ($block->isAutocompleteDisabled()): ?> autocomplete="off"<?php endif; ?>
1213
id="form-validate"
1314
class="form password reset"
1415
data-mage-init='{"validation":{}}'>

0 commit comments

Comments
 (0)