From 9e493dcc33bd0cd30593b88b856c3e89a59a8fb0 Mon Sep 17 00:00:00 2001 From: flo Date: Sat, 4 Jan 2025 04:01:24 +0100 Subject: [PATCH] full working version --- config/autoload/authorization.global.php | 4 ++ data/mails/registration/assets/icon.png | Bin 1766 -> 946 bytes data/mails/registration/template.latte | 8 +-- data/mails/reset-password/assets/icon.png | Bin 1766 -> 946 bytes data/mails/reset-password/template.latte | 3 - ...27155813.php => Version20250104024640.php} | 4 +- ...11191301.php => Version20250104024641.php} | 4 +- .../ConfirmRegistrationResponseFormatter.php | 6 +- .../ForgotPasswordRequestHandler.php | 9 ++- .../RegisterUserRequestHandler.php | 3 + .../ResetPasswordRequestHandler.php | 8 ++- .../ChangePasswordRequestHandler.php | 6 +- .../Authentication/config/service_manager.php | 4 +- .../ForgotPassword/ForgotPasswordUseCase.php | 6 ++ .../ForgotPasswordUseCaseBuilder.php | 2 + .../ForgotPasswordUseCaseHandler.php | 58 +++++++++++++++++- .../ResetPasswordUseCaseHandler.php | 52 +++++++++++++++- .../ConfirmRegistrationPipeline.php | 2 +- .../Step/CreateUserStep.php | 15 +++-- .../RegisterUser/Step/SendMailStep.php | 32 ++++------ .../RegisterUser/RegisterUserUseCase.php | 6 ++ .../RegisterUserUseCaseBuilder.php | 2 + .../User/config/service_manager.php | 2 + .../src/Builder/UserPasswordTokenBuilder.php | 19 ++++++ .../Exception/UserNotFoundByMailException.php | 24 ++++++++ ...rPasswordConfirmationMismatchException.php | 22 +++++++ ...UserPasswordTokenNotFoundByIdException.php | 27 ++++++++ 27 files changed, 276 insertions(+), 52 deletions(-) rename data/migrations/template/{Version20240827155813.php => Version20250104024640.php} (88%) rename data/migrations/template/{Version20240911191301.php => Version20250104024641.php} (90%) create mode 100644 src/HandlingDomain/User/src/Builder/UserPasswordTokenBuilder.php create mode 100644 src/HandlingDomain/User/src/Exception/UserNotFoundByMailException.php create mode 100644 src/HandlingDomain/User/src/Exception/UserPasswordConfirmationMismatchException.php create mode 100644 src/HandlingDomain/User/src/Exception/UserPasswordTokenNotFoundByIdException.php diff --git a/config/autoload/authorization.global.php b/config/autoload/authorization.global.php index 0c6dfa8..040a22c 100644 --- a/config/autoload/authorization.global.php +++ b/config/autoload/authorization.global.php @@ -8,8 +8,12 @@ return [ ], 'permissions' => [ 'user' => [ + 'user.change-password', + 'user.change-username', ], 'admin' => [ + 'user.change-password', + 'user.change-username', 'user.create', 'user.read-list', ], diff --git a/data/mails/registration/assets/icon.png b/data/mails/registration/assets/icon.png index 07e8b9d9cba7a4dc27cd800357a7ca8e4b45ec2c..723547311eb7bb5e405cae5118724234bed35b37 100644 GIT binary patch literal 946 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7Ro>V6OCZaSW-5dpmc3wn(5z>;2iR zj!H>JyEkvXvHFP98{egKmv(h5XwA?J`zIW>l2!E2&4?S^N-9gmk_1?+6*s^3krLf_ zqt@=|Auo%3zoMCUCmYSNEPwa??QP##k?+4GdmWhVcfCNJ@t8gn=LCjirelvwnN$wU zX!uw$mx0qjEx{&E-GQlxQ=c@}!eD8d1 z=FeL_J=LGR`RVmsHnsT;Cskx-?3&BI@j=XN=@);tD%!}2{VaX|w|`3PB$gI|Z{hK? zeBb{$Ic4GJGT(xSzLqDh2dSuVt~hpfas`k6S?LpIzmJGNJ$!LPJ?q;B){xTLTW9}x zmt0VKV*LDiS5hkTO;K@!%y~x{#V0CqPuUwT_R}=wz6j&|#|?*1OmIDU?0i%I;zji$ zH^s#^*yhz8vp4;&=q#o#y>FW9e}zr@Ityl*JgjGaB-mm-QF`0CP2bxSH|8IZ(y*Gp zcRx!5n+gNVu|98x*%~+085Io5Vwi5Y9JJ$PXx#W%=ztp6H%|tR9@*&(W`P_0nH&<{ z>|oi@*;FgUz?6JkwZT{9&141v32QyZoJ9%qSsD)9DCA5KX8k?Xjr_)R?5p|nze3d; zf4;cg%)b4Y`t!V_>d)7mV>kFDc5ttD`%lg#rcZY+d|i0JH|4~ll;-ksx8^@)z@Sdp zof-D`%HDqG2iX&)Uni73bAErKpyGva(R)vU)rEgG>iA;Z*v{6P?b!YC?Q^zW>9ZQN zbav*X8}l{adw*f}YcD&yZU1ura7_-b{wAun|KOj$Li2xLeDHH!!>!)mJ^hpF-=%AZ zpT1P@|I*)z@ju_M&!%C<_1gd5<(%Rz`8G=+u4T=3J1L$0S(}}+8FSlSNBvbz{wH;T z(;!TNQ7FOZK*b)v1{Min1G)9W3XI2CdXB$l@n|q)eEiXh@fcGbqxLGNdTr&{tH8X- N;OXk;vd$@?2>|4QmSq3{ literal 1766 zcmVPx#1ZP1_K>z@;j|==^1poj532;bRa{vHNyZ``ByaAytitqpc02y>eSaefwW^{L9 za%BK_cXuvnZfkR6VQ^(GZ*pgw?mQX*00ve`L_t(|UhSM`sPse>hOc7p4SW0S3Mwd8 z1jXJfqJk)*_`@G|YzT^q3N}Ph5qm+z&w{;yU@!PbR8;KPd++Ui*aULpNivg}l)IY; z9vYtO4wiiYuG4rCfk7;422iKP>zKGze+2PtMU(d zqolwmh8^XL(khTTQivDHMdjGCq`XyH1rWmz6rd0kCmOU zygW+M>3&~k+oLb#Bl38;mULxr`J2ps$)-J5w#K^hCi%OxK8)on@+7&EEaDK!-C(`H zX-}7pLUlYkEM_vGSw@x8RJLf$K7Q|u>yl-7BDB!tRF0>Fdh8ENgG zm+I}sThcmE-cKY$eKA>EUL$=HtyLZ^v(V66`&k|)y`UOd2eKri96De=kK_wIDx1jb zy)08W7mdBOpXKh-i({m9pdufTWHNl1SMDn5Lw+HxMk=XL3G zM-k!QC7+dySCAh1K>}Bshrz0nFTs!>@gXDqZE>+A3-g+EO;geKFD@xWFYb}~t1y%O zOx~CKTb1;*YC#Zd9dMFlkg7Ix_^pFZf;2-*$l8#8j}dFlMCm#PLmJyU_&7_ihpB5( zI7eD1>5H*z$AvN~N6MH{e=NC6_R0M%#J6QSQ8FrLO6!DOnhw+uTU!73kqhCIpY)<{ zLy>gl)|9|hF>4=JIaXtHRlq01+=k=;Q^=ff=UDqyN%Ge_0pJ7efOX<7-B)I*Q!|*c z746Ad1cS`h$-9#7RzAhPleG3N@-i7^6+l%IV7X-57f3=d5i-kTk^ym780)1FgQ+S! z?{sv-khsXhAovZVmrjtY3!Ojh#MUx@+jk|YuA)&fQeQp^)oo=kRd*hfwfh3oI`UOE zg=+iw=%o`(AP=Uh@ZL?feSpE6GOkOuF3>xP^3bT_Q)%7$ZOh178Dy?~CL1xaDF~O8 zdv+kDOIY(!2D3w1J><$>$+l6*tXfyDZI_l+tS_ziTGB6W9J)YVEi%dKy6Dbl!5=>< zQX7|Q`;{a$-!;r>apBrz>%!*AwozDG(8R#BkFK-xSvg7IY#k%-39>dWcOEdFd&}r$ zXSfcqe=SLFx)3ym>{@tmoMfI#S8SMUU2vVrMR-#ipTc9(Ad{%M-MheNk+JK;rIkQA z%ZW1IcC;Y_J}y<4C#Y-t%>10zxl~#orfKh&WwnKB_@K1jYk7cd9lpR7()vJ6%hCas z<>w*n@Lettv{W>-&YzLkcH2Ql`CiEbjGo6fl5olgrtx

Hallo {$username},


-

Herzlich willkommen beim Template!

+

Herzlich willkommen bei Template!


-

Ich konnte deine Anmeldung nun bestätigen.

Bitte klicke auf diesen Link um dein Passwort festzulegen.

Danach ist deine Registierung abgeschlossen und du kannst loslegen!

-
-

Mit grünen Grüßen,

-

{$growerName}

-
-

"Smoke weed everyday" - Snoop Dogg

diff --git a/data/mails/reset-password/assets/icon.png b/data/mails/reset-password/assets/icon.png index 07e8b9d9cba7a4dc27cd800357a7ca8e4b45ec2c..723547311eb7bb5e405cae5118724234bed35b37 100644 GIT binary patch literal 946 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7Ro>V6OCZaSW-5dpmc3wn(5z>;2iR zj!H>JyEkvXvHFP98{egKmv(h5XwA?J`zIW>l2!E2&4?S^N-9gmk_1?+6*s^3krLf_ zqt@=|Auo%3zoMCUCmYSNEPwa??QP##k?+4GdmWhVcfCNJ@t8gn=LCjirelvwnN$wU zX!uw$mx0qjEx{&E-GQlxQ=c@}!eD8d1 z=FeL_J=LGR`RVmsHnsT;Cskx-?3&BI@j=XN=@);tD%!}2{VaX|w|`3PB$gI|Z{hK? zeBb{$Ic4GJGT(xSzLqDh2dSuVt~hpfas`k6S?LpIzmJGNJ$!LPJ?q;B){xTLTW9}x zmt0VKV*LDiS5hkTO;K@!%y~x{#V0CqPuUwT_R}=wz6j&|#|?*1OmIDU?0i%I;zji$ zH^s#^*yhz8vp4;&=q#o#y>FW9e}zr@Ityl*JgjGaB-mm-QF`0CP2bxSH|8IZ(y*Gp zcRx!5n+gNVu|98x*%~+085Io5Vwi5Y9JJ$PXx#W%=ztp6H%|tR9@*&(W`P_0nH&<{ z>|oi@*;FgUz?6JkwZT{9&141v32QyZoJ9%qSsD)9DCA5KX8k?Xjr_)R?5p|nze3d; zf4;cg%)b4Y`t!V_>d)7mV>kFDc5ttD`%lg#rcZY+d|i0JH|4~ll;-ksx8^@)z@Sdp zof-D`%HDqG2iX&)Uni73bAErKpyGva(R)vU)rEgG>iA;Z*v{6P?b!YC?Q^zW>9ZQN zbav*X8}l{adw*f}YcD&yZU1ura7_-b{wAun|KOj$Li2xLeDHH!!>!)mJ^hpF-=%AZ zpT1P@|I*)z@ju_M&!%C<_1gd5<(%Rz`8G=+u4T=3J1L$0S(}}+8FSlSNBvbz{wH;T z(;!TNQ7FOZK*b)v1{Min1G)9W3XI2CdXB$l@n|q)eEiXh@fcGbqxLGNdTr&{tH8X- N;OXk;vd$@?2>|4QmSq3{ literal 1766 zcmVPx#1ZP1_K>z@;j|==^1poj532;bRa{vHNyZ``ByaAytitqpc02y>eSaefwW^{L9 za%BK_cXuvnZfkR6VQ^(GZ*pgw?mQX*00ve`L_t(|UhSM`sPse>hOc7p4SW0S3Mwd8 z1jXJfqJk)*_`@G|YzT^q3N}Ph5qm+z&w{;yU@!PbR8;KPd++Ui*aULpNivg}l)IY; z9vYtO4wiiYuG4rCfk7;422iKP>zKGze+2PtMU(d zqolwmh8^XL(khTTQivDHMdjGCq`XyH1rWmz6rd0kCmOU zygW+M>3&~k+oLb#Bl38;mULxr`J2ps$)-J5w#K^hCi%OxK8)on@+7&EEaDK!-C(`H zX-}7pLUlYkEM_vGSw@x8RJLf$K7Q|u>yl-7BDB!tRF0>Fdh8ENgG zm+I}sThcmE-cKY$eKA>EUL$=HtyLZ^v(V66`&k|)y`UOd2eKri96De=kK_wIDx1jb zy)08W7mdBOpXKh-i({m9pdufTWHNl1SMDn5Lw+HxMk=XL3G zM-k!QC7+dySCAh1K>}Bshrz0nFTs!>@gXDqZE>+A3-g+EO;geKFD@xWFYb}~t1y%O zOx~CKTb1;*YC#Zd9dMFlkg7Ix_^pFZf;2-*$l8#8j}dFlMCm#PLmJyU_&7_ihpB5( zI7eD1>5H*z$AvN~N6MH{e=NC6_R0M%#J6QSQ8FrLO6!DOnhw+uTU!73kqhCIpY)<{ zLy>gl)|9|hF>4=JIaXtHRlq01+=k=;Q^=ff=UDqyN%Ge_0pJ7efOX<7-B)I*Q!|*c z746Ad1cS`h$-9#7RzAhPleG3N@-i7^6+l%IV7X-57f3=d5i-kTk^ym780)1FgQ+S! z?{sv-khsXhAovZVmrjtY3!Ojh#MUx@+jk|YuA)&fQeQp^)oo=kRd*hfwfh3oI`UOE zg=+iw=%o`(AP=Uh@ZL?feSpE6GOkOuF3>xP^3bT_Q)%7$ZOh178Dy?~CL1xaDF~O8 zdv+kDOIY(!2D3w1J><$>$+l6*tXfyDZI_l+tS_ziTGB6W9J)YVEi%dKy6Dbl!5=>< zQX7|Q`;{a$-!;r>apBrz>%!*AwozDG(8R#BkFK-xSvg7IY#k%-39>dWcOEdFd&}r$ zXSfcqe=SLFx)3ym>{@tmoMfI#S8SMUU2vVrMR-#ipTc9(Ad{%M-MheNk+JK;rIkQA z%ZW1IcC;Y_J}y<4C#Y-t%>10zxl~#orfKh&WwnKB_@K1jYk7cd9lpR7()vJ6%hCas z<>w*n@Lettv{W>-&YzLkcH2Ql`CiEbjGo6fl5olgrtxBitte klicke auf diesen Link um ein neues Passwort zu vergeben.


Wenn du dein Passwort nicht zurückgesetzt hast, kannst du diese Nachricht ignorieren!

-
-

Mit fleißigen Grüßen,

-

Der Template

diff --git a/data/migrations/template/Version20240827155813.php b/data/migrations/template/Version20250104024640.php similarity index 88% rename from data/migrations/template/Version20240827155813.php rename to data/migrations/template/Version20250104024640.php index 98c287b..2230c22 100644 --- a/data/migrations/template/Version20240827155813.php +++ b/data/migrations/template/Version20250104024640.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Template\Migrations\Bee; +namespace Template\Migrations\Template; use Doctrine\DBAL\Schema\Schema; use Doctrine\Migrations\AbstractMigration; @@ -10,7 +10,7 @@ use Doctrine\Migrations\AbstractMigration; /** * Auto-generated Migration: Please modify to your needs! */ -final class Version20240827155813 extends AbstractMigration +final class Version20250104024640 extends AbstractMigration { public function getDescription(): string { diff --git a/data/migrations/template/Version20240911191301.php b/data/migrations/template/Version20250104024641.php similarity index 90% rename from data/migrations/template/Version20240911191301.php rename to data/migrations/template/Version20250104024641.php index 98f0102..e6590a1 100644 --- a/data/migrations/template/Version20240911191301.php +++ b/data/migrations/template/Version20250104024641.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Bee\Migrations\Bee; +namespace Template\Migrations\Template; use Doctrine\DBAL\Schema\Schema; use Doctrine\Migrations\AbstractMigration; @@ -10,7 +10,7 @@ use Doctrine\Migrations\AbstractMigration; /** * Auto-generated Migration: Please modify to your needs! */ -final class Version20240911191301 extends AbstractMigration +final class Version20250104024641 extends AbstractMigration { public function getDescription(): string { diff --git a/src/ApiDomain/External/Authentication/src/ConfirmRegistration/ConfirmRegistrationResponseFormatter.php b/src/ApiDomain/External/Authentication/src/ConfirmRegistration/ConfirmRegistrationResponseFormatter.php index ac5c6fe..c3e29cd 100644 --- a/src/ApiDomain/External/Authentication/src/ConfirmRegistration/ConfirmRegistrationResponseFormatter.php +++ b/src/ApiDomain/External/Authentication/src/ConfirmRegistration/ConfirmRegistrationResponseFormatter.php @@ -22,10 +22,8 @@ class ConfirmRegistrationResponseFormatter return [ 'id' => $user->getId()->toString(), 'username' => $user->getUsername(), - 'role' => $user->getRole()->getIdentifier(), - 'permissions' => $permissions, - 'created' => $user->getCreatedAt()->format(DateTimeInterface::RFC3339), - 'updated' => $user->getUpdatedAt()->format(DateTimeInterface::RFC3339) + 'roleIdentifier' => $user->getRole()->getIdentifier(), + 'permissions' => $permissions ]; } } \ No newline at end of file diff --git a/src/ApiDomain/External/Authentication/src/ForgotPassword/ForgotPasswordRequestHandler.php b/src/ApiDomain/External/Authentication/src/ForgotPassword/ForgotPasswordRequestHandler.php index f7d066f..c70640b 100644 --- a/src/ApiDomain/External/Authentication/src/ForgotPassword/ForgotPasswordRequestHandler.php +++ b/src/ApiDomain/External/Authentication/src/ForgotPassword/ForgotPasswordRequestHandler.php @@ -7,6 +7,8 @@ namespace Template\API\External\Authentication\ForgotPassword; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; +use Template\Handling\User\Exception\UserNotFoundByMailException; +use Template\Infrastructure\Request\Middleware\AnalyzeHeaderMiddleware; use Template\Infrastructure\Response\SuccessResponse; use Template\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware; use Template\Handling\Authentication\UseCase\ForgotPassword\ForgotPasswordUseCaseHandler; @@ -22,11 +24,16 @@ class ForgotPasswordRequestHandler implements RequestHandlerInterface ) { } - public function handle(ServerRequestInterface $request): ResponseInterface + /** + * @throws UserNotFoundByMailException + */ + public function handle(ServerRequestInterface $request): ResponseInterface { + $host = $request->getAttribute(AnalyzeHeaderMiddleware::HOST_ATTRIBUTE); $data = $request->getAttribute(AnalyzeBodyMiddleware::JSON_DATA); $useCase = $this->builder->build( + $host, $data['mail'], ); $result = $this->handler->handle($useCase); diff --git a/src/ApiDomain/External/Authentication/src/RegisterUser/RegisterUserRequestHandler.php b/src/ApiDomain/External/Authentication/src/RegisterUser/RegisterUserRequestHandler.php index bd45ff2..ecfd5aa 100644 --- a/src/ApiDomain/External/Authentication/src/RegisterUser/RegisterUserRequestHandler.php +++ b/src/ApiDomain/External/Authentication/src/RegisterUser/RegisterUserRequestHandler.php @@ -7,6 +7,7 @@ namespace Template\API\External\Authentication\RegisterUser; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; +use Template\Infrastructure\Request\Middleware\AnalyzeHeaderMiddleware; use Template\Infrastructure\Response\SuccessResponse; use Template\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware; use Template\Handling\Registration\UseCase\RegisterUser\RegisterUserUseCaseHandler; @@ -24,9 +25,11 @@ class RegisterUserRequestHandler implements RequestHandlerInterface public function handle(ServerRequestInterface $request): ResponseInterface { + $host = $request->getAttribute(AnalyzeHeaderMiddleware::HOST_ATTRIBUTE); $data = $request->getAttribute(AnalyzeBodyMiddleware::JSON_DATA); $useCase = $this->builder->build( + $host, $data['username'], $data['mail'], ); diff --git a/src/ApiDomain/External/Authentication/src/ResetPassword/ResetPasswordRequestHandler.php b/src/ApiDomain/External/Authentication/src/ResetPassword/ResetPasswordRequestHandler.php index 18d1b64..1a7776d 100644 --- a/src/ApiDomain/External/Authentication/src/ResetPassword/ResetPasswordRequestHandler.php +++ b/src/ApiDomain/External/Authentication/src/ResetPassword/ResetPasswordRequestHandler.php @@ -8,6 +8,8 @@ use Ramsey\Uuid\Uuid; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; +use Template\Handling\User\Exception\UserPasswordConfirmationMismatchException; +use Template\Handling\User\Exception\UserPasswordTokenNotFoundByIdException; use Template\Infrastructure\Response\SuccessResponse; use Template\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware; use Template\Handling\Authentication\UseCase\ResetPassword\ResetPasswordUseCaseHandler; @@ -23,7 +25,11 @@ class ResetPasswordRequestHandler implements RequestHandlerInterface ) { } - public function handle(ServerRequestInterface $request): ResponseInterface + /** + * @throws UserPasswordTokenNotFoundByIdException + * @throws UserPasswordConfirmationMismatchException + */ + public function handle(ServerRequestInterface $request): ResponseInterface { $data = $request->getAttribute(AnalyzeBodyMiddleware::JSON_DATA); diff --git a/src/ApiDomain/External/User/src/ChangePassword/ChangePasswordRequestHandler.php b/src/ApiDomain/External/User/src/ChangePassword/ChangePasswordRequestHandler.php index aad95f8..cbfea5d 100644 --- a/src/ApiDomain/External/User/src/ChangePassword/ChangePasswordRequestHandler.php +++ b/src/ApiDomain/External/User/src/ChangePassword/ChangePasswordRequestHandler.php @@ -8,6 +8,7 @@ use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; use Template\Data\Business\Entity\User; +use Template\Handling\User\Exception\UserWrongPasswordException; use Template\Infrastructure\Response\SuccessResponse; use Template\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware; use Template\Handling\User\UseCase\ChangePassword\ChangePasswordUseCaseHandler; @@ -24,7 +25,10 @@ class ChangePasswordRequestHandler implements RequestHandlerInterface ) { } - public function handle(ServerRequestInterface $request): ResponseInterface + /** + * @throws UserWrongPasswordException + */ + public function handle(ServerRequestInterface $request): ResponseInterface { /** @var User $user */ $user = $request->getAttribute(LoggedInUserMiddleware::USER_KEY); diff --git a/src/HandlingDomain/Authentication/config/service_manager.php b/src/HandlingDomain/Authentication/config/service_manager.php index 8497975..5422b4d 100644 --- a/src/HandlingDomain/Authentication/config/service_manager.php +++ b/src/HandlingDomain/Authentication/config/service_manager.php @@ -32,10 +32,10 @@ return [ LogoutUserUseCaseHandler::class => AutoWiringFactory::class, LogoutUserUseCaseBuilder::class => AutoWiringFactory::class, /// ForgotPassword - ForgotPasswordUseCaseHandler::class => AutoWiringFactory::class, + ForgotPasswordUseCaseHandler::class => InjectionFactory::class, ForgotPasswordUseCaseBuilder::class => AutoWiringFactory::class, /// ResetPassword - ResetPasswordUseCaseHandler::class => AutoWiringFactory::class, + ResetPasswordUseCaseHandler::class => InjectionFactory::class, ResetPasswordUseCaseBuilder::class => AutoWiringFactory::class, ] ]; diff --git a/src/HandlingDomain/Authentication/src/UseCase/ForgotPassword/ForgotPasswordUseCase.php b/src/HandlingDomain/Authentication/src/UseCase/ForgotPassword/ForgotPasswordUseCase.php index 16ff010..d3c599c 100644 --- a/src/HandlingDomain/Authentication/src/UseCase/ForgotPassword/ForgotPasswordUseCase.php +++ b/src/HandlingDomain/Authentication/src/UseCase/ForgotPassword/ForgotPasswordUseCase.php @@ -7,10 +7,16 @@ namespace Template\Handling\Authentication\UseCase\ForgotPassword; class ForgotPasswordUseCase { public function __construct( + private readonly string $domain, private readonly string $mail, ) { } + public function getDomain(): string + { + return $this->domain; + } + public function getMail(): string { return $this->mail; diff --git a/src/HandlingDomain/Authentication/src/UseCase/ForgotPassword/ForgotPasswordUseCaseBuilder.php b/src/HandlingDomain/Authentication/src/UseCase/ForgotPassword/ForgotPasswordUseCaseBuilder.php index eaff05a..0206f35 100644 --- a/src/HandlingDomain/Authentication/src/UseCase/ForgotPassword/ForgotPasswordUseCaseBuilder.php +++ b/src/HandlingDomain/Authentication/src/UseCase/ForgotPassword/ForgotPasswordUseCaseBuilder.php @@ -7,9 +7,11 @@ namespace Template\Handling\Authentication\UseCase\ForgotPassword; class ForgotPasswordUseCaseBuilder { public function build( + string $domain, string $mail, ): ForgotPasswordUseCase { return new ForgotPasswordUseCase( + $domain, $mail, ); } diff --git a/src/HandlingDomain/Authentication/src/UseCase/ForgotPassword/ForgotPasswordUseCaseHandler.php b/src/HandlingDomain/Authentication/src/UseCase/ForgotPassword/ForgotPasswordUseCaseHandler.php index 348e40a..a3ba055 100644 --- a/src/HandlingDomain/Authentication/src/UseCase/ForgotPassword/ForgotPasswordUseCaseHandler.php +++ b/src/HandlingDomain/Authentication/src/UseCase/ForgotPassword/ForgotPasswordUseCaseHandler.php @@ -4,14 +4,68 @@ declare(strict_types=1); namespace Template\Handling\Authentication\UseCase\ForgotPassword; +use Reinfi\DependencyInjection\Annotation\Inject; +use Reinfi\DependencyInjection\Annotation\InjectDoctrineRepository; +use Template\Data\Business\Entity\User; +use Template\Data\Business\Manager\EntityManager; +use Template\Data\Business\Repository\UserRepository; +use Template\Handling\User\Builder\UserPasswordTokenBuilder; +use Template\Handling\User\Exception\UserNotFoundByMailException; +use Template\Infrastructure\Mail\Service\MailService; + class ForgotPasswordUseCaseHandler { + private const RESET_PASSWORD_LINK = "https://%s/auth/reset-password/%s"; + + /** + * @InjectDoctrineRepository( + * entityManager="Template\Data\Business\Manager\EntityManager", + * entity="Template\Data\Business\Entity\User" + * ) + * @Inject("Template\Handling\User\Builder\UserPasswordTokenBuilder") + * @Inject("Template\Infrastructure\Mail\Service\MailService") + * @Inject("Template\Data\Business\Manager\EntityManager") + */ public function __construct( + private readonly UserRepository $userRepository, + private readonly UserPasswordTokenBuilder $passwordTokenBuilder, + private readonly MailService $mailService, + private readonly EntityManager $entityManager, ) { } - public function handle(ForgotPasswordUseCase $useCase): ForgotPasswordUseCaseResult + /** + * @throws UserNotFoundByMailException + */ + public function handle(ForgotPasswordUseCase $useCase): ForgotPasswordUseCaseResult { - return new ForgotPasswordUseCaseResult(); + $mail = $useCase->getMail(); + + /** @var User $user */ + $user = $this->userRepository->findOneBy(['mail' => $mail]); + + if ($user === null) { + throw new UserNotFoundByMailException($mail); + } + + $passwordToken = $this->passwordTokenBuilder->build($user); + + $this->entityManager->persist($passwordToken); + $this->entityManager->flush(); + + $this->mailService->enqueue( + 'reset-password', + templateData: [ + 'username' => $user->getUsername(), + 'passwordResetLink' => sprintf( + self::RESET_PASSWORD_LINK, + $useCase->getDomain(), + $passwordToken->getId()->toString() + ) + ], + recipient: $mail, + ); + + return new ForgotPasswordUseCaseResult(); } } \ No newline at end of file diff --git a/src/HandlingDomain/Authentication/src/UseCase/ResetPassword/ResetPasswordUseCaseHandler.php b/src/HandlingDomain/Authentication/src/UseCase/ResetPassword/ResetPasswordUseCaseHandler.php index 89d2ad9..2adf951 100644 --- a/src/HandlingDomain/Authentication/src/UseCase/ResetPassword/ResetPasswordUseCaseHandler.php +++ b/src/HandlingDomain/Authentication/src/UseCase/ResetPassword/ResetPasswordUseCaseHandler.php @@ -4,14 +4,64 @@ declare(strict_types=1); namespace Template\Handling\Authentication\UseCase\ResetPassword; +use Reinfi\DependencyInjection\Annotation\Inject; +use Reinfi\DependencyInjection\Annotation\InjectDoctrineRepository; +use Template\Data\Business\Entity\UserPasswordToken; +use Template\Data\Business\Manager\EntityManager; +use Template\Data\Business\Repository\UserPasswordTokenRepository; +use Template\Handling\User\Exception\UserPasswordConfirmationMismatchException; +use Template\Handling\User\Exception\UserPasswordTokenNotFoundByIdException; +use Template\Infrastructure\Encryption\Client\EncryptionClient; + class ResetPasswordUseCaseHandler { + /** + * @InjectDoctrineRepository( + * entityManager="Template\Data\Business\Manager\EntityManager", + * entity="Template\Data\Business\Entity\UserPasswordToken" + * ) + * @Inject("Template\Infrastructure\Encryption\Client\EncryptionClient") + * @Inject("Template\Data\Business\Manager\EntityManager") + */ public function __construct( + private readonly UserPasswordTokenRepository $repository, + private readonly EncryptionClient $encryptionClient, + private readonly EntityManager $entityManager, ) { } - public function handle(ResetPasswordUseCase $useCase): ResetPasswordUseCaseResult + /** + * @throws UserPasswordTokenNotFoundByIdException + * @throws UserPasswordConfirmationMismatchException + */ + public function handle(ResetPasswordUseCase $useCase): ResetPasswordUseCaseResult { + $passwordTokenId = $useCase->getPasswordToken(); + + // Load and check password token + /** @var ?UserPasswordToken $passwordToken */ + $passwordToken = $this->repository->findOneBy(['id' => $passwordTokenId]); + if ($passwordToken === null) { + throw new UserPasswordTokenNotFoundByIdException($passwordTokenId->toString()); + } + + if ($useCase->getNewPassword() !== $useCase->getPasswordConfirmation()) { + throw new UserPasswordConfirmationMismatchException(); + } + + // Update Password + $user = $passwordToken->getUser(); + $user->setPassword($this->encryptionClient->encrypt($useCase->getNewPassword())); + + // Save to DB + $this->entityManager->remove($passwordToken); + $this->entityManager->persist($user); + if ($user->getSession() !== null) { + $this->entityManager->remove($user->getSession()); + } + + $this->entityManager->flush(); + return new ResetPasswordUseCaseResult(); } } \ No newline at end of file diff --git a/src/HandlingDomain/Registration/src/Pipeline/ConfirmRegistration/ConfirmRegistrationPipeline.php b/src/HandlingDomain/Registration/src/Pipeline/ConfirmRegistration/ConfirmRegistrationPipeline.php index 0da093d..2c8c2bf 100644 --- a/src/HandlingDomain/Registration/src/Pipeline/ConfirmRegistration/ConfirmRegistrationPipeline.php +++ b/src/HandlingDomain/Registration/src/Pipeline/ConfirmRegistration/ConfirmRegistrationPipeline.php @@ -13,7 +13,7 @@ class ConfirmRegistrationPipeline extends Pipeline { public function __construct( private readonly LoadRegistrationStep $loadRegistrationStep, - private readonly CreateUserStep $createUserStep, + private readonly CreateUserStep $createUserStep, private readonly SaveRegistrationAndUserStep $saveRegistrationStep ) { diff --git a/src/HandlingDomain/Registration/src/Pipeline/ConfirmRegistration/Step/CreateUserStep.php b/src/HandlingDomain/Registration/src/Pipeline/ConfirmRegistration/Step/CreateUserStep.php index 11f988a..d1d5712 100644 --- a/src/HandlingDomain/Registration/src/Pipeline/ConfirmRegistration/Step/CreateUserStep.php +++ b/src/HandlingDomain/Registration/src/Pipeline/ConfirmRegistration/Step/CreateUserStep.php @@ -7,6 +7,8 @@ namespace Template\Handling\Registration\Pipeline\ConfirmRegistration\Step; use Template\Handling\Registration\Exception\RegistrationWithIdentifierAlreadyExistsException; use Template\Handling\Registration\Handler\Command\ConfirmRegistration\ConfirmRegistrationCommand; use Template\Handling\Registration\Rule\RegistrationWithIdentifierAlreadyExistsRule; +use Template\Handling\Registration\UseCase\ConfirmRegistration\ConfirmRegistrationUseCase; +use Template\Handling\User\Builder\UserBuilder; use Template\Handling\User\Exception\UserPasswordMismatchException; use Template\Handling\User\Exception\UserWithIdentifierAlreadyExistsException; use Template\Handling\User\Handler\Command\CreateUser\CreateUserCommandBuilder; @@ -15,25 +17,26 @@ use Template\Handling\User\Rule\UserPasswordMatchRule; use Template\Handling\User\Rule\UserWithIdentifierAlreadyExistsRule; use teewurst\Pipeline\PipelineInterface; use teewurst\Pipeline\TaskInterface; +use Template\Infrastructure\Rbac\Exception\RoleNotFoundByIdentifierException; class CreateUserStep implements TaskInterface { public function __construct( - private readonly CreateUserCommandBuilder $createUserCommandBuilder, - private readonly CreateUserCommandHandler $createUserCommandHandler, + private readonly UserBuilder $builder, private readonly UserPasswordMatchRule $passwordMatchRule, ) { } /** * @throws UserPasswordMismatchException + * @throws RoleNotFoundByIdentifierException */ public function __invoke( $payload, PipelineInterface $pipeline ): void { - /** @var ConfirmRegistrationCommand $useCase */ + /** @var ConfirmRegistrationUseCase $useCase */ $useCase = $payload->getUseCase(); $registration = $payload->getRegistration(); @@ -46,12 +49,12 @@ class CreateUserStep implements TaskInterface throw new UserPasswordMismatchException(); } - $createUserCommand = $this->createUserCommandBuilder->build( + $user = $this->builder->build( username: $registration->getUsername(), + roleIdentifier: 'user', mail: $registration->getMail(), - password: $useCase->getPassword(), + password: $useCase->getPassword() ); - $user = $this->createUserCommandHandler->execute($createUserCommand); $payload->setUser($user); diff --git a/src/HandlingDomain/Registration/src/Pipeline/RegisterUser/Step/SendMailStep.php b/src/HandlingDomain/Registration/src/Pipeline/RegisterUser/Step/SendMailStep.php index fa14759..4be94fd 100644 --- a/src/HandlingDomain/Registration/src/Pipeline/RegisterUser/Step/SendMailStep.php +++ b/src/HandlingDomain/Registration/src/Pipeline/RegisterUser/Step/SendMailStep.php @@ -4,7 +4,7 @@ declare(strict_types=1); namespace Template\Handling\Registration\Pipeline\RegisterUser\Step; -use Template\Infrastructure\Request\Service\RequestService; +use Template\Infrastructure\Mail\Service\MailService; use teewurst\Pipeline\PipelineInterface; use teewurst\Pipeline\TaskInterface; @@ -13,7 +13,7 @@ class SendMailStep implements TaskInterface private const CONFIRM_LINK = 'https://%s/auth/registration/%s'; public function __construct( - private RequestService $requestService + private readonly MailService $mailService, ) { } @@ -25,23 +25,17 @@ class SendMailStep implements TaskInterface $useCase = $payload->getUseCase(); $registration = $payload->getRegistration(); - $this->requestService->request( - 'notification', - 'send-mail', - [ - 'template-identifier' => 'new-account', - 'sender' => 'info@stack-up.de', - 'recipient' => $useCase->getMail(), - 'data' => [ - 'username' => $useCase->getUsername(), - 'confirmationLink' => - sprintf( - self::CONFIRM_LINK, - $useCase->getHost(), - $registration->getId()->toString() - ) - ] - ] + $this->mailService->enqueue( + 'registration', + templateData: [ + 'username' => $useCase->getUsername(), + 'confirmationLink' => sprintf( + self::CONFIRM_LINK, + $useCase->getHost(), + $registration->getId()->toString() + ) + ], + recipient: $useCase->getMail(), ); $pipeline->next()($payload, $pipeline); diff --git a/src/HandlingDomain/Registration/src/UseCase/RegisterUser/RegisterUserUseCase.php b/src/HandlingDomain/Registration/src/UseCase/RegisterUser/RegisterUserUseCase.php index 93d4a10..13a90a5 100644 --- a/src/HandlingDomain/Registration/src/UseCase/RegisterUser/RegisterUserUseCase.php +++ b/src/HandlingDomain/Registration/src/UseCase/RegisterUser/RegisterUserUseCase.php @@ -7,11 +7,17 @@ namespace Template\Handling\Registration\UseCase\RegisterUser; class RegisterUserUseCase { public function __construct( + private readonly string $host, private readonly string $username, private readonly string $mail, ) { } + public function getHost(): string + { + return $this->host; + } + public function getUsername(): string { return $this->username; diff --git a/src/HandlingDomain/Registration/src/UseCase/RegisterUser/RegisterUserUseCaseBuilder.php b/src/HandlingDomain/Registration/src/UseCase/RegisterUser/RegisterUserUseCaseBuilder.php index aa0c787..e2c13b4 100644 --- a/src/HandlingDomain/Registration/src/UseCase/RegisterUser/RegisterUserUseCaseBuilder.php +++ b/src/HandlingDomain/Registration/src/UseCase/RegisterUser/RegisterUserUseCaseBuilder.php @@ -7,10 +7,12 @@ namespace Template\Handling\Registration\UseCase\RegisterUser; class RegisterUserUseCaseBuilder { public function build( + string $host, string $username, string $mail, ): RegisterUserUseCase { return new RegisterUserUseCase( + $host, $username, $mail, ); diff --git a/src/HandlingDomain/User/config/service_manager.php b/src/HandlingDomain/User/config/service_manager.php index 73950b4..2b30017 100644 --- a/src/HandlingDomain/User/config/service_manager.php +++ b/src/HandlingDomain/User/config/service_manager.php @@ -1,6 +1,7 @@ InjectionFactory::class, + UserPasswordTokenBuilder::class => InjectionFactory::class, /// Rule UserWithIdentifierAlreadyExistsRule::class => InjectionFactory::class, diff --git a/src/HandlingDomain/User/src/Builder/UserPasswordTokenBuilder.php b/src/HandlingDomain/User/src/Builder/UserPasswordTokenBuilder.php new file mode 100644 index 0000000..daa66fe --- /dev/null +++ b/src/HandlingDomain/User/src/Builder/UserPasswordTokenBuilder.php @@ -0,0 +1,19 @@ +setUser($user); + + return $userPasswordToken; + } +} diff --git a/src/HandlingDomain/User/src/Exception/UserNotFoundByMailException.php b/src/HandlingDomain/User/src/Exception/UserNotFoundByMailException.php new file mode 100644 index 0000000..6bbe398 --- /dev/null +++ b/src/HandlingDomain/User/src/Exception/UserNotFoundByMailException.php @@ -0,0 +1,24 @@ +