diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml new file mode 100644 index 0000000..8134005 --- /dev/null +++ b/.github/workflows/unit-tests.yml @@ -0,0 +1,29 @@ +name: Unit Tests + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + unit-tests: + name: Unit Tests + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v6 + + - uses: shivammathur/setup-php@v2 + with: + # no matrix across 8.2-8.4 here: these are plain PHP unit tests with no + # version-sensitive logic, so one version is enough signal for the added CI cost + php-version: '8.4' + coverage: none + + - name: Install dependencies + run: composer install --no-plugins --prefer-dist + + - name: Run unit tests + run: vendor/bin/phpunit Tests/Unit diff --git a/.gitignore b/.gitignore index e6abe13..fe5d8fe 100644 --- a/.gitignore +++ b/.gitignore @@ -5,5 +5,9 @@ vendor/ # composer composer.lock +# phpunit +.phpunit.result.cache +phpunit.xml.dist + # IDEs .idea/ diff --git a/Classes/Controller/ResetPasswordController.php b/Classes/Controller/ResetPasswordController.php index 8d3ae16..5e71c0b 100644 --- a/Classes/Controller/ResetPasswordController.php +++ b/Classes/Controller/ResetPasswordController.php @@ -5,6 +5,7 @@ use Neos\Flow\Property\TypeConverter\PersistentObjectConverter; use Sandstorm\UserManagement\Domain\Model\ResetPasswordFlow; use Sandstorm\UserManagement\Domain\Repository\ResetPasswordFlowRepository; +use Sandstorm\UserManagement\Domain\Service\FindEmailAddressForUserServiceInterface; use Sandstorm\UserManagement\Domain\Service\UserCreationServiceInterface; use Neos\Flow\Annotations as Flow; use Neos\Flow\Mvc\Controller\ActionController; @@ -40,6 +41,12 @@ class ResetPasswordController extends ActionController */ protected $emailService; + /** + * @Flow\Inject + * @var FindEmailAddressForUserServiceInterface + */ + protected $findEmailAddressForUserService; + /** * @Flow\Inject * @var Translator @@ -104,28 +111,32 @@ public function requestTokenAction(ResetPasswordFlow $resetPasswordFlow) } } - // Send out a confirmation mail - $resetPasswordLink = $this->uriBuilder->reset()->setCreateAbsoluteUri(true)->uriFor( - 'insertNewPassword', - ['token' => $resetPasswordFlow->getResetPasswordToken()], - 'ResetPassword'); - - $this->emailService->sendTemplateEmail( - 'ResetPasswordToken', - $this->getSubjectResetPassword(), - [$resetPasswordFlow->getEmail()], - [ - 'resetPasswordLink' => $resetPasswordLink, - 'resetPasswordFlow' => $resetPasswordFlow - ], - 'sandstorm_usermanagement_sender_email', - [], // cc - [], // bcc - [], // attachments - 'sandstorm_usermanagement_replyTo_email' - ); - - $this->resetPasswordFlowRepository->add($resetPasswordFlow); + $receiverMail = $this->findEmailAddressForUserService->getEmailAddressByAccount($account); + + if ($receiverMail !== null) { + // Send out a confirmation mail + $resetPasswordLink = $this->uriBuilder->reset()->setCreateAbsoluteUri(true)->uriFor( + 'insertNewPassword', + ['token' => $resetPasswordFlow->getResetPasswordToken()], + 'ResetPassword'); + + $this->emailService->sendTemplateEmail( + 'ResetPasswordToken', + $this->getSubjectResetPassword(), + [$receiverMail], + [ + 'resetPasswordLink' => $resetPasswordLink, + 'resetPasswordFlow' => $resetPasswordFlow + ], + 'sandstorm_usermanagement_sender_email', + [], // cc + [], // bcc + [], // attachments + 'sandstorm_usermanagement_replyTo_email' + ); + + $this->resetPasswordFlowRepository->add($resetPasswordFlow); + } } diff --git a/Classes/Domain/Model/ResetPasswordFlow.php b/Classes/Domain/Model/ResetPasswordFlow.php index cb9123c..101a9a4 100644 --- a/Classes/Domain/Model/ResetPasswordFlow.php +++ b/Classes/Domain/Model/ResetPasswordFlow.php @@ -16,7 +16,6 @@ class ResetPasswordFlow /** * @var string * @Flow\Validate(type="NotEmpty") - * @Flow\Validate(type="EmailAddress") */ protected $email; diff --git a/Classes/Domain/Service/FindEmailAddressForUserByAccountIdentifierService.php b/Classes/Domain/Service/FindEmailAddressForUserByAccountIdentifierService.php new file mode 100644 index 0000000..467a04c --- /dev/null +++ b/Classes/Domain/Service/FindEmailAddressForUserByAccountIdentifierService.php @@ -0,0 +1,23 @@ +getAccountIdentifier(); + } +} diff --git a/Classes/Domain/Service/FindEmailAddressForUserServiceInterface.php b/Classes/Domain/Service/FindEmailAddressForUserServiceInterface.php new file mode 100644 index 0000000..3e9f852 --- /dev/null +++ b/Classes/Domain/Service/FindEmailAddressForUserServiceInterface.php @@ -0,0 +1,20 @@ +setPassword('foobar'); @@ -26,10 +23,7 @@ public function equalPasswordsAreEqual() $this->assertTrue($passwordDto->arePasswordsEqual()); } - /** - * @test - */ - public function inequalPasswordsAreNotEqual() + public function testInequalPasswordsAreNotEqual() { $passwordDto = new PasswordDto(); $passwordDto->setPassword('FOOBAR'); @@ -38,10 +32,7 @@ public function inequalPasswordsAreNotEqual() $this->assertFalse($passwordDto->arePasswordsEqual()); } - /** - * @test - */ - public function passwordMinLength() + public function testPasswordMinLength() { $passwordDto = new PasswordDto(); $passwordDto->setPassword('6chars'); @@ -51,10 +42,7 @@ public function passwordMinLength() $this->assertFalse($passwordDto->isPasswordMinLength(7)); } - /** - * @test - */ - public function passwordMaxLength() + public function testPasswordMaxLength() { $passwordDto = new PasswordDto(); $passwordDto->setPassword('6chars'); @@ -64,10 +52,7 @@ public function passwordMaxLength() $this->assertFalse($passwordDto->isPasswordMaxLength(5)); } - /** - * @test - */ - public function passwordContainsLowercaseLetters() + public function testPasswordContainsLowercaseLetters() { $passwordDto = new PasswordDto(); $passwordDto->setPassword('4loweRCASELETTERS'); @@ -78,10 +63,7 @@ public function passwordContainsLowercaseLetters() $this->assertFalse($passwordDto->doesPasswordContainLowercaseLetters(5)); } - /** - * @test - */ - public function passwordContainsUppercaseLetters() + public function testPasswordContainsUppercaseLetters() { $passwordDto = new PasswordDto(); $passwordDto->setPassword('4UPPErcaseletters'); @@ -92,10 +74,7 @@ public function passwordContainsUppercaseLetters() $this->assertFalse($passwordDto->doesPasswordContainUppercaseLetters(5)); } - /** - * @test - */ - public function passwordContainsNumbers() + public function testPasswordContainsNumbers() { $passwordDto = new PasswordDto(); $passwordDto->setPassword('fournumbers1234'); @@ -106,10 +85,7 @@ public function passwordContainsNumbers() $this->assertFalse($passwordDto->doesPasswordContainNumbers(5)); } - /** - * @test - */ - public function passwordContainsSpecialCharacters() + public function testPasswordContainsSpecialCharacters() { $passwordDto = new PasswordDto(); $passwordDto->setPassword('4specialCHARS!"%$'); diff --git a/Tests/Unit/Domain/Service/FindEmailAddressForUserByAccountIdentifierServiceTest.php b/Tests/Unit/Domain/Service/FindEmailAddressForUserByAccountIdentifierServiceTest.php new file mode 100644 index 0000000..26c6210 --- /dev/null +++ b/Tests/Unit/Domain/Service/FindEmailAddressForUserByAccountIdentifierServiceTest.php @@ -0,0 +1,33 @@ +setAccountIdentifier('user@example.com'); + + $service = new FindEmailAddressForUserByAccountIdentifierService(); + + $this->assertSame('user@example.com', $service->getEmailAddressByAccount($account)); + } + + public function testReturnsTheAccountIdentifierUnchangedWhenItIsAPlainUsername() + { + $account = new Account(); + $account->setAccountIdentifier('someuser'); + + $service = new FindEmailAddressForUserByAccountIdentifierService(); + + $this->assertSame('someuser', $service->getEmailAddressByAccount($account)); + } +} diff --git a/composer.json b/composer.json index 0f80e8f..4d890e7 100644 --- a/composer.json +++ b/composer.json @@ -26,9 +26,18 @@ "neos/flow": "^8.3 || ^9.0", "sandstorm/templatemailer": "^3.0.1 || dev-master" }, + "require-dev": { + "phpunit/phpunit": "^13.0" + }, "autoload": { "psr-4": { "Sandstorm\\UserManagement\\": "Classes" } + }, + "autoload-dev": { + "psr-4": { + "Sandstorm\\UserManagement\\Tests\\": "Tests", + "Neos\\Flow\\Tests\\": "vendor/neos/flow/Tests" + } } }