text: <?php
  /**
   * Copyright © Magento, Inc. All rights reserved.
   * See COPYING.txt for license details.
   */
  declare(strict_types=1);
  
  namespace Magento\Security\Model;
  
  /**
   * Tests for \Magento\Security\Model\UserExpirationManager
   * @magentoAppArea adminhtml
   * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
   */
  class UserExpirationManagerTest extends \PHPUnit\Framework\TestCase
  {
      /**
       * @var \Magento\Framework\ObjectManagerInterface
       */
      private $objectManager;
  
      /**
       * @var \Magento\Backend\Model\Auth
       */
      private $auth;
  
      /**
       * @var \Magento\Backend\Model\Auth\Session
       */
      private $authSession;
  
      /**
       * @var \Magento\Security\Model\AdminSessionInfo
       */
      private $adminSessionInfo;
  
      /**
       * @var \Magento\Security\Model\UserExpirationManager
       */
      private $userExpirationManager;
  
      protected function setUp(): void
      {
          $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
          $this->auth = $this->objectManager->create(\Magento\Backend\Model\Auth::class);
          $this->authSession = $this->objectManager->create(\Magento\Backend\Model\Auth\Session::class);
          $this->adminSessionInfo = $this->objectManager->create(\Magento\Security\Model\AdminSessionInfo::class);
          $this->auth->setAuthStorage($this->authSession);
          $this->userExpirationManager =
              $this->objectManager->create(\Magento\Security\Model\UserExpirationManager::class);
      }
  
      /**
       * @magentoDataFixture Magento/Security/_files/expired_users.php
       */
      public function testUserIsExpired()
      {
          $adminUserNameFromFixture = 'adminUserExpired';
          $user = $this->loadUserByUsername($adminUserNameFromFixture);
          static::assertTrue($this->userExpirationManager->isUserExpired($user->getId()));
      }
  
      /**
       * @magentoDataFixture Magento/Security/_files/expired_users.php
       * @magentoAppIsolation enabled
       */
      public function testDeactivateExpiredUsersWithExpiredUser()
      {
          $adminUsernameFromFixture = 'adminUserNotExpired';
          $this->loginUser($adminUsernameFromFixture);
          $user = $this->loadUserByUsername($adminUsernameFromFixture);
          $sessionId = $this->authSession->getSessionId();
          $this->expireUser($user);
          $this->userExpirationManager->deactivateExpiredUsersById([$user->getId()]);
          $this->adminSessionInfo->load($sessionId, 'session_id');
          $user->reload();
          $userExpirationModel = $this->loadExpiredUserModelByUser($user);
          static::assertEquals(0, $user->getIsActive());
          static::assertNull($userExpirationModel->getId());
          static::assertEquals(AdminSessionInfo::LOGGED_OUT, (int)$this->adminSessionInfo->getStatus());
      }
  
      /**
       * @magentoDataFixture Magento/Security/_files/expired_users.php
       * @magentoAppIsolation enabled
       */
      public function testDeactivateExpiredUsersWithNonExpiredUser()
      {
          $adminUsernameFromFixture = 'adminUserNotExpired';
          $this->loginUser($adminUsernameFromFixture);
          $user = $this->loadUserByUsername($adminUsernameFromFixture);
          $sessionId = $this->authSession->getSessionId();
          $this->userExpirationManager->deactivateExpiredUsersById([$user->getId()]);
          $user->reload();
          $userExpirationModel = $this->loadExpiredUserModelByUser($user);
          $this->adminSessionInfo->load($sessionId, 'session_id');
          static::assertEquals(1, $user->getIsActive());
          static::assertEquals($user->getId(), $userExpirationModel->getId());
          static::assertEquals(AdminSessionInfo::LOGGED_IN, (int)$this->adminSessionInfo->getStatus());
      }
  
      /**
       * Test deactivating without inputting a user.
       *
       * @magentoDataFixture Magento/Security/_files/expired_users.php
       */
      public function testDeactivateExpiredUsers()
      {
          $notExpiredUser = $this->loadUserByUsername('adminUserNotExpired');
          $expiredUser = $this->loadUserByUsername('adminUserExpired');
          $this->userExpirationManager->deactivateExpiredUsers();
          $notExpiredUserExpirationModel = $this->loadExpiredUserModelByUser($notExpiredUser);
          $expiredUserExpirationModel = $this->loadExpiredUserModelByUser($expiredUser);
  
          static::assertNotNull($notExpiredUserExpirationModel->getId());
          static::assertNull($expiredUserExpirationModel->getId());
          $notExpiredUser->reload();
          $expiredUser->reload();
          static::assertEquals($notExpiredUser->getIsActive(), 1);
          static::assertEquals($expiredUser->getIsActive(), 0);
      }
  
      /**
       * Login the given user and return a user model.
       *
       * @param string $username
       * @throws \Magento\Framework\Exception\AuthenticationException
       */
      private function loginUser(string $username)
      {
          $this->auth->login(
              $username,
              \Magento\TestFramework\Bootstrap::ADMIN_PASSWORD
          );
      }
  
      /**
       * @param $username
       * @return \Magento\User\Model\User
       */
      private function loadUserByUsername(string $username): \Magento\User\Model\User
      {
          /** @var \Magento\User\Model\User $user */
          $user = $this->objectManager->create(\Magento\User\Model\User::class);
          $user->loadByUsername($username);
          return $user;
      }
  
      /**
       * Expire the given user and return the UserExpiration model.
       *
       * @param \Magento\User\Model\User $user
       * @throws \Exception
       */
      private function expireUser(\Magento\User\Model\User $user)
      {
          $expireDate = new \DateTime();
          $expireDate->modify('-10 days');
          /** @var \Magento\Security\Api\Data\UserExpirationInterface $userExpiration */
          $userExpiration = $this->objectManager->create(\Magento\Security\Api\Data\UserExpirationInterface::class);
          $userExpiration->setId($user->getId())
              ->setExpiresAt($expireDate->format('Y-m-d H:i:s'))
              ->save();
      }
  
      /**
       * @param \Magento\User\Model\User $user
       * @return \Magento\Security\Model\UserExpiration
       */
      private function loadExpiredUserModelByUser(\Magento\User\Model\User $user): \Magento\Security\Model\UserExpiration
      {
          /** @var \Magento\Security\Model\UserExpiration $expiredUserModel */
          $expiredUserModel = $this->objectManager->create(\Magento\Security\Model\UserExpiration::class);
          $expiredUserModel->load($user->getId());
          return $expiredUserModel;
      }
  }
  