diff --git a/.env b/.env index 6c8aa517..9adc5e48 100644 --- a/.env +++ b/.env @@ -50,5 +50,5 @@ MAILER_DELIVERY_ADDRESS="admin@example.org" # DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db" # DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=8&charset=utf8mb4" # DATABASE_URL="postgresql://app:!ChangeMe!@127.0.0.1:5432/app?serverVersion=14&charset=utf8" -DATABASE_URL="mysql://mail:password@127.0.0.1:3306/mail?serverVersion=mariadb-10.3.23&charset=utf8mb4" +DATABASE_URL="mysql://mail:password@127.0.0.1:3306/mail?charset=utf8mb4" ###< doctrine/doctrine-bundle ### diff --git a/CHANGELOG.md b/CHANGELOG.md index ed636c17..c128c39b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# 3.2.4 (unreleased) + +* Fix setting last_login_time on authentication through checkpassword command. + # 3.2.3 (2023.10.31) * Update dependencies diff --git a/src/Command/UsersRegistrationMailCommand.php b/src/Command/UsersRegistrationMailCommand.php index f3adc2e1..53d8c404 100644 --- a/src/Command/UsersRegistrationMailCommand.php +++ b/src/Command/UsersRegistrationMailCommand.php @@ -40,7 +40,7 @@ protected function configure(): void * * @throws \Exception */ - protected function execute(InputInterface $input, OutputInterface $output) + protected function execute(InputInterface $input, OutputInterface $output): int { $email = $input->getOption('user'); $locale = $input->getOption('locale'); @@ -50,5 +50,7 @@ protected function execute(InputInterface $input, OutputInterface $output) } $this->welcomeMessageSender->send($user, $locale); + + return 0; } } diff --git a/src/Event/RecoveryProcessEvent.php b/src/Event/RecoveryProcessEvent.php index b46b19da..5adb974f 100644 --- a/src/Event/RecoveryProcessEvent.php +++ b/src/Event/RecoveryProcessEvent.php @@ -7,7 +7,7 @@ use Symfony\Contracts\EventDispatcher\Event; /** - * Class LoginEvent. + * Class RecoveryProcessEvent. */ class RecoveryProcessEvent extends Event { diff --git a/src/EventListener/LoginListener.php b/src/EventListener/LoginListener.php index a82b073d..0366e903 100644 --- a/src/EventListener/LoginListener.php +++ b/src/EventListener/LoginListener.php @@ -62,7 +62,7 @@ public static function getSubscribedEvents(): array { return [ SecurityEvents::INTERACTIVE_LOGIN => 'onSecurityInteractiveLogin', - LoginEvent::class => 'onLogin', + LoginEvent::NAME => 'onLogin', ]; } } diff --git a/tests/Command/UsersCheckPasswordCommandTest.php b/tests/Command/UsersCheckPasswordCommandTest.php index 18ce04cf..dba80ca9 100644 --- a/tests/Command/UsersCheckPasswordCommandTest.php +++ b/tests/Command/UsersCheckPasswordCommandTest.php @@ -5,6 +5,8 @@ use App\Command\UsersCheckPasswordCommand; use App\Entity\User; use App\Enum\Roles; +use App\Event\LoginEvent; +use App\EventListener\LoginListener; use App\Handler\MailCryptKeyHandler; use App\Handler\UserAuthenticationHandler; use App\Helper\FileDescriptorReader; @@ -13,6 +15,10 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Exception\InvalidArgumentException; use Symfony\Component\Console\Tester\CommandTester; +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactoryInterface; +use Symfony\Component\PasswordHasher\PasswordHasherInterface; class UsersCheckPasswordCommandTest extends TestCase { @@ -21,16 +27,21 @@ class UsersCheckPasswordCommandTest extends TestCase protected $quotaUser; protected $mailCryptUser; protected $spamUser; + protected $loginListener; public function setUp(): void { $this->plainUser = new User(); + $this->plainUser->setPassword('passwordhash'); $this->quotaUser = new User(); + $this->quotaUser->setPassword('passwordhash'); $this->quotaUser->setQuota(1024); $this->mailCryptUser = new User(); + $this->mailCryptUser->setPassword('passwordhash'); $this->mailCryptUser->setMailCrypt(true); $this->mailCryptUser->setMailCryptPublicKey('somePublicKey'); $this->spamUser = new User(); + $this->spamUser->setPassword('passwordhash'); $this->spamUser->setRoles([Roles::SPAM]); } @@ -92,6 +103,35 @@ public function testExecuteFd3($inputStream, $returnCode): void $this->assertEquals($returnCode, $commandTester->getStatusCode()); } + public function testExecuteCallsLoginListener(): void + { + $inputStream = "user@example.org\x00password"; + $returnCode = 0; + + $manager = $this->getManager(); + $reader = $this->getReaderFd3($inputStream); + $handler = $this->getHandler(); + $mailCryptKeyHandler = $this->getMailCryptKeyHandler(); + $mailCrypt = 2; + $mailUID = 5000; + $mailGID = 5000; + $mailLocation = 'var/vmail'; + + $command = new UsersCheckPasswordCommand($manager, + $reader, + $handler, + $mailCryptKeyHandler, + $mailCrypt, + $mailUID, + $mailGID, + $mailLocation); + $commandTester = new CommandTester($command); + + $this->loginListener->expects(self::once())->method('onLogin'); + $commandTester->execute([]); + self::assertEquals($returnCode, $commandTester->getStatusCode()); + } + /** * @dataProvider validContentProvider */ @@ -239,19 +279,21 @@ public function getManager(): EntityManagerInterface public function getHandler(): UserAuthenticationHandler { - $handler = $this->getMockBuilder(UserAuthenticationHandler::class) - ->disableOriginalConstructor() - ->getMock(); - $handler->method('authenticate')->willReturnMap( + $passwordHasher = $this->createMock(PasswordHasherInterface::class); + $passwordHasher->method('verify')->willReturnMap( [ - [$this->plainUser, 'password', $this->plainUser], - [$this->quotaUser, 'password', $this->quotaUser], - [$this->mailCryptUser, 'password', $this->mailCryptUser], - [$this->spamUser, 'password', $this->spamUser], + ['passwordhash', 'password', true], + ['passwordhash', 'wrongpassword', false], + ['passwordhash', '', false], ] ); + $passwordHasherFactory = $this->createMock(PasswordHasherFactoryInterface::class); + $passwordHasherFactory->method('getPasswordHasher')->willReturn($passwordHasher); - return $handler; + $this->loginListener = $this->createMock(LoginListener::class); + $eventDispatcher = new EventDispatcher(); + $eventDispatcher->addListener(LoginEvent::NAME, [$this->loginListener, 'onLogin']); + return new UserAuthenticationHandler($passwordHasherFactory, $eventDispatcher); } public function getMailCryptKeyHandler(): MailCryptKeyHandler diff --git a/tests/EventListener/LoginListenerTest.php b/tests/EventListener/LoginListenerTest.php index bf32b226..4388124d 100644 --- a/tests/EventListener/LoginListenerTest.php +++ b/tests/EventListener/LoginListenerTest.php @@ -97,7 +97,7 @@ public function testGetSubscribedEvents(): void { $this->assertEquals([ SecurityEvents::INTERACTIVE_LOGIN => 'onSecurityInteractiveLogin', - LoginEvent::class => 'onLogin', + LoginEvent::NAME => 'onLogin', ], $this->listener::getSubscribedEvents()); }