123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 |
- <?php
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- namespace Magento\User\Observer\Backend;
- use Magento\Backend\Model\Auth\Session;
- use Magento\Backend\Model\UrlInterface;
- use Magento\Framework\Encryption\EncryptorInterface;
- use Magento\Framework\Event\Observer as EventObserver;
- use Magento\Framework\Exception\State\UserLockedException;
- use Magento\Framework\Message\ManagerInterface;
- use Magento\User\Model\Backend\Config\ObserverConfig;
- use Magento\User\Model\ResourceModel\User as ResourceUser;
- use Magento\User\Model\User;
- use Magento\Framework\Event\ObserverInterface;
- use Magento\User\Model\UserFactory;
- /**
- * User backend observer model for authentication
- * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
- */
- class AuthObserver implements ObserverInterface
- {
- /**
- * Backend configuration interface
- *
- * @var ObserverConfig
- */
- protected $observerConfig;
- /**
- * Admin user resource model
- *
- * @var ResourceUser
- */
- protected $userResource;
- /**
- * Backend url interface
- *
- * @var UrlInterface
- */
- protected $url;
- /**
- * Backend authorization session
- *
- * @var Session
- */
- protected $authSession;
- /**
- * Factory class for user model
- *
- * @var UserFactory
- */
- protected $userFactory;
- /**
- * Encryption model
- *
- * @var EncryptorInterface
- */
- protected $encryptor;
- /**
- * Message manager interface
- *
- * @var ManagerInterface
- */
- protected $messageManager;
- /**
- * @param ObserverConfig $observerConfig
- * @param ResourceUser $userResource
- * @param UrlInterface $url
- * @param Session $authSession
- * @param UserFactory $userFactory
- * @param EncryptorInterface $encryptor
- * @param ManagerInterface $messageManager
- */
- public function __construct(
- ObserverConfig $observerConfig,
- ResourceUser $userResource,
- UrlInterface $url,
- Session $authSession,
- UserFactory $userFactory,
- EncryptorInterface $encryptor,
- ManagerInterface $messageManager
- ) {
- $this->observerConfig = $observerConfig;
- $this->userResource = $userResource;
- $this->url = $url;
- $this->authSession = $authSession;
- $this->userFactory = $userFactory;
- $this->encryptor = $encryptor;
- $this->messageManager = $messageManager;
- }
- /**
- * Admin locking and password hashing upgrade logic implementation
- *
- * @param EventObserver $observer
- * @return void
- * @throws \Magento\Framework\Exception\LocalizedException
- */
- public function execute(EventObserver $observer)
- {
- $password = $observer->getEvent()->getPassword();
- /** @var User $user */
- $user = $observer->getEvent()->getUser();
- $authResult = $observer->getEvent()->getResult();
- if (!$authResult && $user->getId()) {
- // update locking information regardless whether user locked or not
- $this->_updateLockingInformation($user);
- }
- // check whether user is locked
- $lockExpires = $user->getLockExpires();
- if ($lockExpires) {
- $lockExpires = new \DateTime($lockExpires);
- if ($lockExpires > new \DateTime()) {
- throw new UserLockedException(
- __(
- 'The account sign-in was incorrect or your account is disabled temporarily. '
- . 'Please wait and try again later.'
- )
- );
- }
- }
- if (!$authResult) {
- return;
- }
- $this->userResource->unlock($user->getId());
- $latestPassword = $this->userResource->getLatestPassword($user->getId());
- $this->_checkExpiredPassword($latestPassword);
- if (!$this->encryptor->validateHashVersion($user->getPassword(), true)) {
- $user->setPassword($password)
- ->setData('force_new_password', true)
- ->save();
- }
- }
- /**
- * Update locking information for the user
- *
- * @param User $user
- * @return void
- */
- private function _updateLockingInformation($user)
- {
- $now = new \DateTime();
- $lockThreshold = $this->observerConfig->getAdminLockThreshold();
- $maxFailures = $this->observerConfig->getMaxFailures();
- if (!($lockThreshold && $maxFailures)) {
- return;
- }
- $failuresNum = (int)$user->getFailuresNum() + 1;
- /** @noinspection PhpAssignmentInConditionInspection */
- if ($firstFailureDate = $user->getFirstFailure()) {
- $firstFailureDate = new \DateTime($firstFailureDate);
- }
- $newFirstFailureDate = false;
- $updateLockExpires = false;
- $lockThreshInterval = new \DateInterval('PT' . $lockThreshold.'S');
- // set first failure date when this is first failure or last first failure expired
- if (1 === $failuresNum || !$firstFailureDate || $now->diff($firstFailureDate) > $lockThreshInterval) {
- $newFirstFailureDate = $now;
- // otherwise lock user
- } elseif ($failuresNum >= $maxFailures) {
- $updateLockExpires = $now->add($lockThreshInterval);
- }
- $this->userResource->updateFailure($user, $updateLockExpires, $newFirstFailureDate);
- }
- /**
- * Check whether the latest password is expired
- * Side-effect can be when passwords were changed with different lifetime configuration settings
- *
- * @param array $latestPassword
- * @return void
- */
- private function _checkExpiredPassword($latestPassword)
- {
- if ($latestPassword && $this->observerConfig->_isLatestPasswordExpired($latestPassword)) {
- if ($this->observerConfig->isPasswordChangeForced()) {
- $message = __('It\'s time to change your password.');
- } else {
- $myAccountUrl = $this->url->getUrl('adminhtml/system_account/');
- $message = __('It\'s time to <a href="%1">change your password</a>.', $myAccountUrl);
- }
- $messages = $this->messageManager->getMessages();
- // Remove existing messages with same ID to avoid duplication
- $messages->deleteMessageByIdentifier(User::MESSAGE_ID_PASSWORD_EXPIRED);
- $this->messageManager->addNoticeMessage($message);
- $message = $messages->getLastAddedMessage();
- if ($message) {
- $message->setIdentifier(User::MESSAGE_ID_PASSWORD_EXPIRED)->setIsSticky(true);
- $this->authSession->setPciAdminUserIsPasswordExpired(true);
- }
- }
- }
- }
|