diff --git a/app/code/Magento/User/Cron/DisableExpiredUsers.php b/app/code/Magento/User/Cron/DisableExpiredUsers.php new file mode 100644 index 0000000000000..08b35bd45433a --- /dev/null +++ b/app/code/Magento/User/Cron/DisableExpiredUsers.php @@ -0,0 +1,45 @@ +collectionFactory = $collectionFactory; + } + + /** + * Disable all expired user accounts. + */ + public function execute() + { + $users = $this->collectionFactory->create() + ->addExpiresAtFilter() + ->addFieldToFilter('is_active', 1) + ; + /** @var \Magento\User\Model\User $user */ + foreach ($users as $user) { + $user->setIsActive(0) + ->setExpiresAt(null) + ->save(); + } + } +} diff --git a/app/code/Magento/User/Model/ResourceModel/User/Collection.php b/app/code/Magento/User/Model/ResourceModel/User/Collection.php index 7683adae84365..133c253c28574 100644 --- a/app/code/Magento/User/Model/ResourceModel/User/Collection.php +++ b/app/code/Magento/User/Model/ResourceModel/User/Collection.php @@ -13,9 +13,9 @@ */ class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection { + /** * Define resource model - * * @return void */ protected function _construct() @@ -41,4 +41,21 @@ protected function _initSelect() ['role_name'] ); } + + /** + * Filter users by expires_at. + * @param string|null $now + * @return $this + */ + public function addExpiresAtFilter($now = null) + { + if ($now === null) { + $now = new \DateTime(); + $now->format('Y-m-d H:i:s'); + } + + $this->addFieldToFilter('expires_at', ['lt' => $now]); + + return $this; + } } diff --git a/app/code/Magento/User/Test/Unit/Model/UserValidationRulesTest.php b/app/code/Magento/User/Test/Unit/Model/UserValidationRulesTest.php index 9eb3ee203f0aa..be23fde541eb2 100644 --- a/app/code/Magento/User/Test/Unit/Model/UserValidationRulesTest.php +++ b/app/code/Magento/User/Test/Unit/Model/UserValidationRulesTest.php @@ -45,7 +45,7 @@ public function testAddPasswordConfirmationRule() public function testAddExpiresAtRule() { - $this->validator->expects($this->once())->method('addRule')->willReturn($this->validator); + $this->validator->expects($this->atMost(2))->method('addRule')->willReturn($this->validator); $this->assertSame($this->validator, $this->rules->addExpiresAtRule($this->validator)); } } diff --git a/app/code/Magento/User/etc/crontab.xml b/app/code/Magento/User/etc/crontab.xml new file mode 100644 index 0000000000000..a58379f00e952 --- /dev/null +++ b/app/code/Magento/User/etc/crontab.xml @@ -0,0 +1,11 @@ + + + + + + 0 * * * * + + + + diff --git a/dev/tests/integration/testsuite/Magento/User/Cron/DisableExpiredUsersTest.php b/dev/tests/integration/testsuite/Magento/User/Cron/DisableExpiredUsersTest.php new file mode 100644 index 0000000000000..2adac918ae29c --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/User/Cron/DisableExpiredUsersTest.php @@ -0,0 +1,32 @@ +create(\Magento\User\Cron\DisableExpiredUsers::class); + $job->execute(); + + /** @var \Magento\User\Model\User $user */ + $user = Bootstrap::getObjectManager()->create(\Magento\User\Model\User::class); + $user->loadByUsername('adminUser3'); + static::assertEquals(0, $user->getIsActive()); + static::assertNull($user->getExpiresAt()); + } + +} diff --git a/dev/tests/integration/testsuite/Magento/User/Model/ResourceModel/User/CollectionTest.php b/dev/tests/integration/testsuite/Magento/User/Model/ResourceModel/User/CollectionTest.php new file mode 100644 index 0000000000000..0a81814c982a8 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/User/Model/ResourceModel/User/CollectionTest.php @@ -0,0 +1,43 @@ +collection = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + \Magento\User\Model\ResourceModel\User\Collection::class + ); + } + + public function testSelectQueryInitialized() + { + static::assertContains( + 'main_table.user_id = user_role.user_id AND user_role.parent_id != 0', + $this->collection->getSelect()->__toString() + ); + } + + /** + * @magentoDataFixture Magento/User/_files/expired_users.php + */ + public function testExpiresAtFilter() + { + $this->collection->addExpiresAtFilter(); + static::assertCount(1, $this->collection); + } +} diff --git a/dev/tests/integration/testsuite/Magento/User/Model/UserTest.php b/dev/tests/integration/testsuite/Magento/User/Model/UserTest.php index 8b85339afd789..eb5a3a0d11f53 100644 --- a/dev/tests/integration/testsuite/Magento/User/Model/UserTest.php +++ b/dev/tests/integration/testsuite/Magento/User/Model/UserTest.php @@ -387,6 +387,17 @@ public function testBeforeSavePasswordTooShort() $this->_model->save(); } + /** + * @expectedException \Magento\Framework\Exception\LocalizedException + * @expectedExceptionMessage The expiration date must be later than the current date. + * @magentoDbIsolation enabled + */ + public function testBeforeSaveExpireDateBeforeNow() + { + $this->_model->setExpiresAt('2010-01-01 00:00:00'); + $this->_model->save(); + } + /** * @dataProvider beforeSavePasswordInsecureDataProvider * @expectedException \Magento\Framework\Exception\LocalizedException diff --git a/dev/tests/integration/testsuite/Magento/User/_files/expired_users.php b/dev/tests/integration/testsuite/Magento/User/_files/expired_users.php new file mode 100644 index 0000000000000..f6c562e4e03a5 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/User/_files/expired_users.php @@ -0,0 +1,57 @@ +create(\Magento\User\Model\User::class); +$model->setFirstname("John") + ->setLastname("Doe") + ->setUsername('adminUser3') + ->setPassword(\Magento\TestFramework\Bootstrap::ADMIN_PASSWORD) + ->setEmail('adminUser3@example.com') + ->setRoleType('G') + ->setResourceId('Magento_Adminhtml::all') + ->setPrivileges("") + ->setAssertId(0) + ->setRoleId(1) + ->setPermission('allow'); +$model->save(); +$userIds[] = $model->getDataByKey('user_id'); + +/** @var $model \Magento\User\Model\User */ +$futureDate = new \DateTime(); +$futureDate->modify('+10 days'); +$model = $objectManager->create(\Magento\User\Model\User::class); +$model->setFirstname("John") + ->setLastname("Doe") + ->setUsername('adminUser4') + ->setPassword(\Magento\TestFramework\Bootstrap::ADMIN_PASSWORD) + ->setEmail('adminUser4@example.com') + ->setExpiresAt($futureDate->format('Y-m-d H:i:s')) + ->setRoleType('G') + ->setResourceId('Magento_Adminhtml::all') + ->setPrivileges("") + ->setAssertId(0) + ->setRoleId(1) + ->setPermission('allow'); +$model->save(); +$userIds[] = $model->getDataByKey('user_id'); + +// need to bypass model validation to set expired date +$resource = $objectManager->get(\Magento\Framework\App\ResourceConnection::class); +$conn = $resource->getConnection(\Magento\Framework\App\ResourceConnection::DEFAULT_CONNECTION); +$tableName = $resource->getTableName('admin_user'); +$sql = "UPDATE " . $tableName . " SET expires_at = '2010-01-01 00:00:00' WHERE user_id=" . + $userIds[0] . ";"; +$result = $conn->query($sql); + +