214 lines
9.3 KiB
PHP
214 lines
9.3 KiB
PHP
<?php
|
|
namespace Stemcell\Customer\Model;
|
|
|
|
use Magento\Customer\Api\AddressRepositoryInterface;
|
|
use Magento\Customer\Api\CustomerMetadataInterface;
|
|
use Magento\Customer\Api\CustomerRepositoryInterface;
|
|
use Magento\Customer\Api\Data\AddressInterface;
|
|
use Magento\Customer\Api\Data\CustomerInterface;
|
|
use Magento\Customer\Api\Data\ValidationResultsInterfaceFactory;
|
|
use Magento\Customer\Api\SessionCleanerInterface;
|
|
use Magento\Customer\Helper\View as CustomerViewHelper;
|
|
use Magento\Customer\Model\AccountConfirmation;
|
|
use Magento\Customer\Model\AddressRegistry;
|
|
use Magento\Customer\Model\AuthenticationInterface;
|
|
use Magento\Customer\Model\Config\Share as ConfigShare;
|
|
use Magento\Customer\Model\Customer;
|
|
use Magento\Customer\Model\Customer as CustomerModel;
|
|
use Magento\Customer\Model\Customer\CredentialsValidator;
|
|
use Magento\Customer\Model\CustomerFactory;
|
|
use Magento\Customer\Model\CustomerRegistry;
|
|
use Magento\Customer\Model\EmailNotificationInterface;
|
|
use Magento\Customer\Model\ForgotPasswordToken\GetCustomerByToken;
|
|
use Magento\Customer\Model\Metadata\Validator;
|
|
use Magento\Customer\Model\ResourceModel\Visitor\CollectionFactory;
|
|
use Magento\Directory\Model\AllowedCountries;
|
|
use Magento\Framework\Api\ExtensibleDataObjectConverter;
|
|
use Magento\Framework\Api\SearchCriteriaBuilder;
|
|
use Magento\Framework\App\Config\ScopeConfigInterface;
|
|
use Magento\Framework\AuthorizationInterface;
|
|
use Magento\Framework\DataObjectFactory as ObjectFactory;
|
|
use Magento\Framework\Encryption\EncryptorInterface as Encryptor;
|
|
use Magento\Framework\Encryption\Helper\Security;
|
|
use Magento\Framework\Event\ManagerInterface;
|
|
use Magento\Framework\Exception\InputException;
|
|
use Magento\Framework\Exception\LocalizedException;
|
|
use Magento\Framework\Exception\NoSuchEntityException;
|
|
use Magento\Framework\Exception\State\ExpiredException;
|
|
use Magento\Framework\Exception\State\InputMismatchException;
|
|
use Magento\Framework\Intl\DateTimeFactory;
|
|
use Magento\Framework\Mail\Template\TransportBuilder;
|
|
use Magento\Framework\Math\Random;
|
|
use Magento\Framework\Reflection\DataObjectProcessor;
|
|
use Magento\Framework\Registry;
|
|
use Magento\Framework\Session\SaveHandlerInterface;
|
|
use Magento\Framework\Session\SessionManagerInterface;
|
|
use Magento\Framework\Stdlib\DateTime;
|
|
use Magento\Framework\Stdlib\StringUtils as StringHelper;
|
|
use Magento\Store\Model\ScopeInterface;
|
|
use Magento\Store\Model\StoreManagerInterface;
|
|
use Psr\Log\LoggerInterface as PsrLogger;
|
|
|
|
class AccountManagement extends \Magento\Customer\Model\AccountManagement
|
|
{
|
|
protected AddressRegistry $addressRegistry;
|
|
|
|
protected GetCustomerByToken $getByToken;
|
|
|
|
protected CustomerRegistry $customerRegistry;
|
|
protected CredentialsValidator $credentialsValidator;
|
|
protected CustomerRepositoryInterface $customerRepository;
|
|
protected SessionCleanerInterface $sessionCleaner;
|
|
|
|
public function __construct(
|
|
CustomerFactory $customerFactory,
|
|
ManagerInterface $eventManager,
|
|
StoreManagerInterface $storeManager,
|
|
Random $mathRandom,
|
|
Validator $validator,
|
|
ValidationResultsInterfaceFactory $validationResultsDataFactory,
|
|
AddressRepositoryInterface $addressRepository,
|
|
CustomerMetadataInterface $customerMetadataService,
|
|
CustomerRegistry $customerRegistry,
|
|
PsrLogger $logger,
|
|
Encryptor $encryptor,
|
|
ConfigShare $configShare,
|
|
StringHelper $stringHelper,
|
|
CustomerRepositoryInterface $customerRepository,
|
|
ScopeConfigInterface $scopeConfig,
|
|
TransportBuilder $transportBuilder,
|
|
DataObjectProcessor $dataProcessor,
|
|
Registry $registry,
|
|
CustomerViewHelper $customerViewHelper,
|
|
DateTime $dateTime,
|
|
Customer $customerModel,
|
|
ObjectFactory $objectFactory,
|
|
ExtensibleDataObjectConverter $extensibleDataObjectConverter,
|
|
CredentialsValidator $credentialsValidator,
|
|
DateTimeFactory $dateTimeFactory = null,
|
|
AccountConfirmation $accountConfirmation = null,
|
|
SessionManagerInterface $sessionManager = null,
|
|
SaveHandlerInterface $saveHandler = null,
|
|
CollectionFactory $visitorCollectionFactory = null,
|
|
SearchCriteriaBuilder $searchCriteriaBuilder = null,
|
|
AddressRegistry $addressRegistry,
|
|
GetCustomerByToken $getByToken,
|
|
AllowedCountries $allowedCountriesReader = null,
|
|
SessionCleanerInterface $sessionCleaner,
|
|
AuthorizationInterface $authorization = null
|
|
) {
|
|
parent::__construct($customerFactory, $eventManager, $storeManager, $mathRandom, $validator, $validationResultsDataFactory, $addressRepository, $customerMetadataService, $customerRegistry, $logger, $encryptor, $configShare, $stringHelper, $customerRepository, $scopeConfig, $transportBuilder, $dataProcessor, $registry, $customerViewHelper, $dateTime, $customerModel, $objectFactory, $extensibleDataObjectConverter, $credentialsValidator, $dateTimeFactory, $accountConfirmation, $sessionManager, $saveHandler, $visitorCollectionFactory, $searchCriteriaBuilder, $addressRegistry, $getByToken, $allowedCountriesReader, $sessionCleaner, $authorization);
|
|
$this->addressRegistry = $addressRegistry;
|
|
$this->getByToken = $getByToken;
|
|
$this->customerRegistry = $customerRegistry;
|
|
$this->credentialsValidator = $credentialsValidator;
|
|
$this->customerRepository = $customerRepository;
|
|
$this->sessionCleaner = $sessionCleaner;
|
|
}
|
|
|
|
/**
|
|
* Disable Customer Address Validation
|
|
*
|
|
* @param CustomerInterface $customer
|
|
* @throws NoSuchEntityException
|
|
*/
|
|
protected function disableAddressValidation($customer)
|
|
{
|
|
foreach ($customer->getAddresses() as $address) {
|
|
$addressModel = $this->addressRegistry->retrieve($address->getId());
|
|
$addressModel->setShouldIgnoreValidation(true);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set ignore_validation_flag for reset password flow to skip unnecessary address and customer validation
|
|
*
|
|
* @param Customer $customer
|
|
* @return void
|
|
*/
|
|
protected function setIgnoreValidationFlag($customer)
|
|
{
|
|
$customer->setData('ignore_validation_flag', true);
|
|
}
|
|
|
|
/**
|
|
* Validate the Reset Password Token for a customer.
|
|
*
|
|
* @param int $customerId
|
|
* @param string $resetPasswordLinkToken
|
|
*
|
|
* @return bool
|
|
* @throws ExpiredException If token is expired
|
|
* @throws InputException If token or customer id is invalid
|
|
* @throws InputMismatchException If token is mismatched
|
|
* @throws LocalizedException
|
|
* @throws NoSuchEntityException If customer doesn't exist
|
|
* @SuppressWarnings(PHPMD.LongVariable)
|
|
*/
|
|
protected function validateResetPasswordToken($customerId, $resetPasswordLinkToken)
|
|
{
|
|
if ($customerId !== null && $customerId <= 0) {
|
|
throw new InputException(
|
|
__(
|
|
'Invalid value of "%value" provided for the %fieldName field.',
|
|
['value' => $customerId, 'fieldName' => 'customerId']
|
|
)
|
|
);
|
|
}
|
|
|
|
if ($customerId === null) {
|
|
//Looking for the customer.
|
|
$customerId = $this->getByToken
|
|
->execute($resetPasswordLinkToken)
|
|
->getId();
|
|
}
|
|
if (!is_string($resetPasswordLinkToken) || empty($resetPasswordLinkToken)) {
|
|
$params = ['fieldName' => 'resetPasswordLinkToken'];
|
|
throw new InputException(__('"%fieldName" is required. Enter and try again.', $params));
|
|
}
|
|
$customerSecureData = $this->customerRegistry->retrieveSecureData($customerId);
|
|
$rpToken = $customerSecureData->getRpToken();
|
|
$rpTokenCreatedAt = $customerSecureData->getRpTokenCreatedAt();
|
|
if (!Security::compareStrings($rpToken, $resetPasswordLinkToken)) {
|
|
throw new InputMismatchException(__('The password token is mismatched. Reset and try again.'));
|
|
} elseif ($this->isResetPasswordLinkTokenExpired($rpToken, $rpTokenCreatedAt)) {
|
|
throw new ExpiredException(__('The password token is expired. Reset and try again.'));
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public function resetPassword($email, $resetToken, $newPassword)
|
|
{
|
|
if (!$email && $resetToken) {
|
|
$customer = $this->getByToken->execute($resetToken);
|
|
$email = $customer->getEmail();
|
|
} else {
|
|
$customer = $this->customerRepository->get($email);
|
|
}
|
|
|
|
// No need to validate customer and customer address while saving customer reset password token
|
|
$this->disableAddressValidation($customer);
|
|
$this->setIgnoreValidationFlag($customer);
|
|
|
|
//Validate Token and new password strength
|
|
if ($resetToken) {
|
|
$this->validateResetPasswordToken($customer->getId(), $resetToken);
|
|
}
|
|
|
|
$this->credentialsValidator->checkPasswordDifferentFromEmail(
|
|
$email,
|
|
$newPassword
|
|
);
|
|
$this->checkPasswordStrength($newPassword);
|
|
//Update secure data
|
|
$customerSecure = $this->customerRegistry->retrieveSecureData($customer->getId());
|
|
$customerSecure->setRpToken(null);
|
|
$customerSecure->setRpTokenCreatedAt(null);
|
|
$customerSecure->setPasswordHash($this->createPasswordHash($newPassword));
|
|
$this->sessionCleaner->clearFor((int)$customer->getId());
|
|
$this->customerRepository->save($customer);
|
|
|
|
return true;
|
|
}
|
|
}
|