diff --git a/.github/workflows/qodana_code_quality.yml b/.github/workflows/qodana_code_quality.yml index aa8b0b27..188c5513 100644 --- a/.github/workflows/qodana_code_quality.yml +++ b/.github/workflows/qodana_code_quality.yml @@ -4,7 +4,7 @@ on: pull_request: push: branches: - - 5.0 + - '6.0' - 'releases/*' jobs: diff --git a/config/pipeline.php b/config/pipeline.php index f5373937..da98ec75 100644 --- a/config/pipeline.php +++ b/config/pipeline.php @@ -2,11 +2,12 @@ declare(strict_types=1); -use Api\App\Handler\GetNotFoundViewHandler; +use Api\App\Handler\GetNotFoundResourceHandler; use Api\App\Middleware\AuthenticationMiddleware; use Api\App\Middleware\AuthorizationMiddleware; use Api\App\Middleware\ContentNegotiationMiddleware; use Api\App\Middleware\DeprecationMiddleware; +use Api\App\Middleware\ResourceProviderMiddleware; use Dot\ResponseHeader\Middleware\ResponseHeaderMiddleware; use Mezzio\Application; use Mezzio\Cors\Middleware\CorsMiddleware; @@ -80,11 +81,13 @@ // - route-based validation // - etc. + $app->pipe(ResourceProviderMiddleware::class); + // Register the dispatch middleware in the middleware pipeline $app->pipe(DispatchMiddleware::class); // At this point, if no Response is returned by any middleware, the // NotFoundHandler kicks in; alternately, you can provide other fallback // middleware to execute. $app->pipe(ProblemDetailsNotFoundHandler::class); - $app->pipe(GetNotFoundViewHandler::class); + $app->pipe(GetNotFoundResourceHandler::class); }; diff --git a/src/Admin/src/Handler/Account/GetAdminAccountResourceHandler.php b/src/Admin/src/Handler/Account/GetAdminAccountResourceHandler.php index 306c6baa..68463ece 100644 --- a/src/Admin/src/Handler/Account/GetAdminAccountResourceHandler.php +++ b/src/Admin/src/Handler/Account/GetAdminAccountResourceHandler.php @@ -5,7 +5,7 @@ namespace Api\Admin\Handler\Account; use Api\App\Handler\AbstractHandler; -use Core\Admin\Entity\Admin; +use Api\App\IdentityInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; @@ -13,6 +13,6 @@ class GetAdminAccountResourceHandler extends AbstractHandler { public function handle(ServerRequestInterface $request): ResponseInterface { - return $this->createResponse($request, $request->getAttribute(Admin::class)); + return $this->createResponse($request, $request->getAttribute(IdentityInterface::class)); } } diff --git a/src/Admin/src/Handler/Account/PatchAdminAccountResourceHandler.php b/src/Admin/src/Handler/Account/PatchAdminAccountResourceHandler.php index a6e39811..253f06d6 100644 --- a/src/Admin/src/Handler/Account/PatchAdminAccountResourceHandler.php +++ b/src/Admin/src/Handler/Account/PatchAdminAccountResourceHandler.php @@ -10,7 +10,7 @@ use Api\App\Exception\ConflictException; use Api\App\Exception\NotFoundException; use Api\App\Handler\AbstractHandler; -use Core\Admin\Entity\Admin; +use Api\App\IdentityInterface; use Core\App\Message; use Dot\DependencyInjection\Attribute\Inject; use Psr\Http\Message\ResponseInterface; @@ -47,7 +47,7 @@ public function handle(ServerRequestInterface $request): ResponseInterface $request, $this->adminService->saveAdmin( (array) $this->inputFilter->getValues(), - $request->getAttribute(Admin::class) + $request->getAttribute(IdentityInterface::class) ) ); } diff --git a/src/Admin/src/Handler/Admin/DeleteAdminResourceHandler.php b/src/Admin/src/Handler/Admin/DeleteAdminResourceHandler.php index bedddafd..2f43d9f2 100644 --- a/src/Admin/src/Handler/Admin/DeleteAdminResourceHandler.php +++ b/src/Admin/src/Handler/Admin/DeleteAdminResourceHandler.php @@ -5,8 +5,9 @@ namespace Api\Admin\Handler\Admin; use Api\Admin\Service\AdminServiceInterface; -use Api\App\Exception\NotFoundException; +use Api\App\Attribute\Resource; use Api\App\Handler\AbstractHandler; +use Core\Admin\Entity\Admin; use Dot\DependencyInjection\Attribute\Inject; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; @@ -21,12 +22,12 @@ public function __construct( ) { } - /** - * @throws NotFoundException - */ + #[Resource(entity: Admin::class)] public function handle(ServerRequestInterface $request): ResponseInterface { - $this->adminService->deleteAdmin($this->adminService->findAdmin($request->getAttribute('uuid'))); + $this->adminService->deleteAdmin( + $request->getAttribute(Admin::class) + ); return $this->noContentResponse(); } diff --git a/src/Admin/src/Handler/Admin/GetAdminResourceHandler.php b/src/Admin/src/Handler/Admin/GetAdminResourceHandler.php index 53693ccc..ab5ac4ae 100644 --- a/src/Admin/src/Handler/Admin/GetAdminResourceHandler.php +++ b/src/Admin/src/Handler/Admin/GetAdminResourceHandler.php @@ -4,31 +4,20 @@ namespace Api\Admin\Handler\Admin; -use Api\Admin\Service\AdminServiceInterface; -use Api\App\Exception\NotFoundException; +use Api\App\Attribute\Resource; use Api\App\Handler\AbstractHandler; -use Dot\DependencyInjection\Attribute\Inject; +use Core\Admin\Entity\Admin; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; class GetAdminResourceHandler extends AbstractHandler { - #[Inject( - AdminServiceInterface::class, - )] - public function __construct( - protected AdminServiceInterface $adminService, - ) { - } - - /** - * @throws NotFoundException - */ + #[Resource(entity: Admin::class)] public function handle(ServerRequestInterface $request): ResponseInterface { return $this->createResponse( $request, - $this->adminService->findAdmin($request->getAttribute('uuid')) + $request->getAttribute(Admin::class) ); } } diff --git a/src/Admin/src/Handler/Admin/PatchAdminResourceHandler.php b/src/Admin/src/Handler/Admin/PatchAdminResourceHandler.php index e19faeb3..f0e13ccd 100644 --- a/src/Admin/src/Handler/Admin/PatchAdminResourceHandler.php +++ b/src/Admin/src/Handler/Admin/PatchAdminResourceHandler.php @@ -6,10 +6,12 @@ use Api\Admin\InputFilter\UpdateAdminInputFilter; use Api\Admin\Service\AdminServiceInterface; +use Api\App\Attribute\Resource; use Api\App\Exception\BadRequestException; use Api\App\Exception\ConflictException; use Api\App\Exception\NotFoundException; use Api\App\Handler\AbstractHandler; +use Core\Admin\Entity\Admin; use Core\App\Message; use Dot\DependencyInjection\Attribute\Inject; use Psr\Http\Message\ResponseInterface; @@ -32,6 +34,7 @@ public function __construct( * @throws ConflictException * @throws NotFoundException */ + #[Resource(entity: Admin::class)] public function handle(ServerRequestInterface $request): ResponseInterface { $this->inputFilter->setData((array) $request->getParsedBody()); @@ -46,7 +49,7 @@ public function handle(ServerRequestInterface $request): ResponseInterface $request, $this->adminService->saveAdmin( (array) $this->inputFilter->getValues(), - $this->adminService->findAdmin($request->getAttribute('uuid')) + $request->getAttribute(Admin::class) ) ); } diff --git a/src/Admin/src/Handler/Admin/Role/GetAdminRoleResourceHandler.php b/src/Admin/src/Handler/Admin/Role/GetAdminRoleResourceHandler.php index 3c1f2c1d..88215553 100644 --- a/src/Admin/src/Handler/Admin/Role/GetAdminRoleResourceHandler.php +++ b/src/Admin/src/Handler/Admin/Role/GetAdminRoleResourceHandler.php @@ -4,31 +4,20 @@ namespace Api\Admin\Handler\Admin\Role; -use Api\Admin\Service\AdminRoleServiceInterface; -use Api\App\Exception\NotFoundException; +use Api\App\Attribute\Resource; use Api\App\Handler\AbstractHandler; -use Dot\DependencyInjection\Attribute\Inject; +use Core\Admin\Entity\AdminRole; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; class GetAdminRoleResourceHandler extends AbstractHandler { - #[Inject( - AdminRoleServiceInterface::class, - )] - public function __construct( - protected AdminRoleServiceInterface $adminRoleService, - ) { - } - - /** - * @throws NotFoundException - */ + #[Resource(entity: AdminRole::class)] public function handle(ServerRequestInterface $request): ResponseInterface { return $this->createResponse( $request, - $this->adminRoleService->findAdminRole($request->getAttribute('uuid')) + $request->getAttribute(AdminRole::class) ); } } diff --git a/src/App/src/Attribute/Resource.php b/src/App/src/Attribute/Resource.php new file mode 100644 index 00000000..7fef438c --- /dev/null +++ b/src/App/src/Attribute/Resource.php @@ -0,0 +1,31 @@ +guard !== null; + } +} diff --git a/src/App/src/Attribute/ResourceInterface.php b/src/App/src/Attribute/ResourceInterface.php new file mode 100644 index 00000000..5fc52a65 --- /dev/null +++ b/src/App/src/Attribute/ResourceInterface.php @@ -0,0 +1,10 @@ + AttributedServiceFactory::class, DeprecationMiddleware::class => AttributedServiceFactory::class, ErrorReportPermissionMiddleware::class => AttributedServiceFactory::class, + ResourceProviderMiddleware::class => AttributedServiceFactory::class, GetIndexResourceHandler::class => AttributedServiceFactory::class, PostErrorReportResourceHandler::class => AttributedServiceFactory::class, ErrorReportService::class => AttributedServiceFactory::class, diff --git a/src/App/src/Guard/ResourceGuardInterface.php b/src/App/src/Guard/ResourceGuardInterface.php new file mode 100644 index 00000000..c39018c6 --- /dev/null +++ b/src/App/src/Guard/ResourceGuardInterface.php @@ -0,0 +1,18 @@ +isActive()) { return $this->unauthorizedResponse(Message::ADMIN_INACTIVE); } - $request = $request->withAttribute(Admin::class, $user); + $request = $request->withAttribute(IdentityInterface::class, $user); break; case 'frontend': $user = $this->userRepository->findOneBy(['identity' => $defaultUser->getIdentity()]); @@ -63,11 +64,11 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface if (! $user->isActive()) { return $this->unauthorizedResponse(Message::USER_NOT_ACTIVATED); } - $request = $request->withAttribute(User::class, $user); + $request = $request->withAttribute(IdentityInterface::class, $user); break; case 'guest': $user = new Guest(); - $request = $request->withAttribute(Guest::class, $user); + $request = $request->withAttribute(IdentityInterface::class, $user); break; default: return $this->unauthorizedResponse(Message::INVALID_CLIENT_ID); diff --git a/src/App/src/Middleware/DeprecationMiddleware.php b/src/App/src/Middleware/DeprecationMiddleware.php index 50c47d44..72efad95 100644 --- a/src/App/src/Middleware/DeprecationMiddleware.php +++ b/src/App/src/Middleware/DeprecationMiddleware.php @@ -8,12 +8,9 @@ use Api\App\Attribute\ResourceDeprecation; use Api\App\Exception\ConflictException; use Api\App\Exception\RuntimeException; +use Api\App\Service\HandlerService; use Core\App\Message; use Dot\DependencyInjection\Attribute\Inject; -use Dot\Router\Middleware\LazyLoadingMiddleware; -use Laminas\Stratigility\MiddlewarePipe; -use Mezzio\Middleware\LazyLoadingMiddleware as MezzioLazyLoadingMiddleware; -use Mezzio\Router\RouteResult; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\MiddlewareInterface; @@ -59,19 +56,10 @@ public function process( ServerRequestInterface $request, RequestHandlerInterface $handler ): ResponseInterface { - $response = $handler->handle($request); - $routeResult = $request->getAttribute(RouteResult::class); - if (! $routeResult instanceof RouteResult || $routeResult->isFailure()) { - return $response; - } - - $matchedRoute = $routeResult->getMatchedRoute(); - if (! $matchedRoute) { - return $response; - } + $response = $handler->handle($request); - $reflectionHandler = $this->getHandler($matchedRoute->getMiddleware()); - if (empty($reflectionHandler)) { + $reflectionHandler = HandlerService::getReflectionHandler($request); + if (! $reflectionHandler instanceof ReflectionClass) { return $response; } @@ -138,39 +126,6 @@ private function getReflectionAttributes(ReflectionClass $reflectionObject): arr return $attributes; } - /** - * @throws ReflectionException - * @throws RuntimeException - */ - private function getHandler(MiddlewareInterface $routeMiddleware): ?ReflectionClass - { - $reflectionHandler = null; - if ( - $routeMiddleware instanceof MezzioLazyLoadingMiddleware - || $routeMiddleware instanceof LazyLoadingMiddleware - ) { - /** @var class-string $routeMiddlewareName */ - $routeMiddlewareName = $routeMiddleware->middlewareName; - $reflectionMiddlewareClass = new ReflectionClass($routeMiddlewareName); - if ($reflectionMiddlewareClass->implementsInterface(RequestHandlerInterface::class)) { - $reflectionHandler = $reflectionMiddlewareClass; - } - } elseif ($routeMiddleware instanceof MiddlewarePipe) { - $reflectionClass = new ReflectionClass($routeMiddleware); - $middlewarePipeline = $reflectionClass->getProperty('pipeline')->getValue($routeMiddleware); - for ($middlewarePipeline->rewind(); $middlewarePipeline->valid(); $middlewarePipeline->next()) { - $reflectionMiddlewareClass = new ReflectionClass($middlewarePipeline->current()->middlewareName); - if ($reflectionMiddlewareClass->implementsInterface(RequestHandlerInterface::class)) { - $reflectionHandler = $reflectionMiddlewareClass; - } - } - } else { - throw RuntimeException::create('Invalid route middleware provided.'); - } - - return $reflectionHandler; - } - /** * @throws ConflictException */ diff --git a/src/App/src/Middleware/ResourceProviderMiddleware.php b/src/App/src/Middleware/ResourceProviderMiddleware.php new file mode 100644 index 00000000..50eb614b --- /dev/null +++ b/src/App/src/Middleware/ResourceProviderMiddleware.php @@ -0,0 +1,96 @@ +handle($request); + } + + $reflectionAttributes = $reflectionHandler->getMethod('handle')->getAttributes(Resource::class); + if (count($reflectionAttributes) === 0) { + return $handler->handle($request); + } + + /** @var Resource $resource */ + $resource = $reflectionAttributes[0]->newInstance(); + + if ($resource->identifier === 'uuid' || $resource->identifier === 'id') { + $entity = $this->entityManager->getRepository($resource->entity)->find( + $request->getAttribute($resource->placeholder) + ); + } else { + $entity = $this->entityManager->getRepository($resource->entity)->findOneBy([ + $resource->identifier => $request->getAttribute($resource->placeholder), + ]); + } + + if ($entity === null) { + $entity = explode('\\', $resource->entity); + throw NotFoundException::create( + Message::resourceNotFound(array_pop($entity)) + ); + } + assert($entity instanceof EntityInterface); + + if ($entity->isDeleted()) { + $entity = explode('\\', $resource->entity); + throw NotFoundException::create( + Message::resourceNotFound(array_pop($entity)) + ); + } + + if ($resource->hasGuard()) { + (new $resource->guard())($request, $this->entityManager, $entity); + } + + if ($request->getAttribute($entity::class) !== null) { + throw ConflictException::create( + Message::resourceAlreadyRegistered($entity::class) + ); + } + + return $handler->handle( + $request->withAttribute($entity::class, $entity) + ); + } +} diff --git a/src/App/src/Service/HandlerService.php b/src/App/src/Service/HandlerService.php new file mode 100644 index 00000000..e3bbde78 --- /dev/null +++ b/src/App/src/Service/HandlerService.php @@ -0,0 +1,62 @@ +getAttribute(RouteResult::class); + if (! $routeResult instanceof RouteResult || $routeResult->isFailure()) { + return null; + } + + $matchedRoute = $routeResult->getMatchedRoute(); + if (! $matchedRoute instanceof Route) { + return null; + } + + $routeMiddleware = $matchedRoute->getMiddleware(); + if ( + $routeMiddleware instanceof MezzioLazyLoadingMiddleware + || $routeMiddleware instanceof LazyLoadingMiddleware + ) { + /** @var class-string $routeMiddlewareName */ + $routeMiddlewareName = $routeMiddleware->middlewareName; + $reflectionMiddlewareClass = new ReflectionClass($routeMiddlewareName); + if ($reflectionMiddlewareClass->implementsInterface(RequestHandlerInterface::class)) { + return $reflectionMiddlewareClass; + } + } elseif ($routeMiddleware instanceof MiddlewarePipe) { + $reflectionClass = new ReflectionClass($routeMiddleware); + $middlewarePipeline = $reflectionClass->getProperty('pipeline')->getValue($routeMiddleware); + for ($middlewarePipeline->rewind(); $middlewarePipeline->valid(); $middlewarePipeline->next()) { + $reflectionMiddlewareClass = new ReflectionClass($middlewarePipeline->current()->middlewareName); + if ($reflectionMiddlewareClass->implementsInterface(RequestHandlerInterface::class)) { + return $reflectionMiddlewareClass; + } + } + } else { + throw RuntimeException::create('Invalid route middleware provided.'); + } + + return null; + } +} diff --git a/src/Core/src/App/src/Entity/AbstractEntity.php b/src/Core/src/App/src/Entity/AbstractEntity.php index 82e1dea0..f2848a50 100644 --- a/src/Core/src/App/src/Entity/AbstractEntity.php +++ b/src/Core/src/App/src/Entity/AbstractEntity.php @@ -30,6 +30,14 @@ public function getUuid(): UuidInterface return $this->uuid; } + /** + * Override this method in soft-deletable entities + */ + public function isDeleted(): bool + { + return false; + } + public function exchangeArray(array $array): void { foreach ($array as $property => $values) { diff --git a/src/Core/src/App/src/Entity/EntityInterface.php b/src/Core/src/App/src/Entity/EntityInterface.php index 418e0fd8..80ce6095 100644 --- a/src/Core/src/App/src/Entity/EntityInterface.php +++ b/src/Core/src/App/src/Entity/EntityInterface.php @@ -4,6 +4,20 @@ namespace Core\App\Entity; +use DateTimeImmutable; +use Ramsey\Uuid\UuidInterface; + interface EntityInterface { + public function getUuid(): UuidInterface; + + public function getCreated(): ?DateTimeImmutable; + + public function getCreatedFormatted(string $dateFormat = 'Y-m-d H:i:s'): string; + + public function getUpdated(): ?DateTimeImmutable; + + public function getUpdatedFormatted(string $dateFormat = 'Y-m-d H:i:s'): ?string; + + public function isDeleted(): bool; } diff --git a/src/Core/src/App/src/Entity/RoleInterface.php b/src/Core/src/App/src/Entity/RoleInterface.php index b1893e38..0c2b80b3 100644 --- a/src/Core/src/App/src/Entity/RoleInterface.php +++ b/src/Core/src/App/src/Entity/RoleInterface.php @@ -5,12 +5,9 @@ namespace Core\App\Entity; use BackedEnum; -use Ramsey\Uuid\UuidInterface; -interface RoleInterface +interface RoleInterface extends EntityInterface { - public function getUuid(): UuidInterface; - public function getName(): ?BackedEnum; public function setName(BackedEnum $name): RoleInterface; diff --git a/src/Core/src/App/src/Message.php b/src/Core/src/App/src/Message.php index c65460de..1ab64299 100644 --- a/src/Core/src/App/src/Message.php +++ b/src/Core/src/App/src/Message.php @@ -39,7 +39,9 @@ class Message public const RESET_PASSWORD_OK = 'Password successfully modified.'; public const RESET_PASSWORD_USED = 'Reset password hash is invalid (used).'; public const RESET_PASSWORD_VALID = 'Reset password hash is valid.'; + public const RESOURCE_ALREADY_REGISTERED = 'Resource "%s" is already registered.'; public const RESOURCE_NOT_ALLOWED = 'You are not allowed to access this resource.'; + public const RESOURCE_NOT_FOUND = '%s not found.'; public const RESTRICTION_DEPRECATION = 'Cannot use both "%s" and "%s" attributes on the same object.'; public const RESTRICTION_IMAGE = 'File must be an image> Accepted mim type(s): %s'; public const RESTRICTION_ROLES = 'At least one role is required.'; @@ -93,6 +95,16 @@ public static function mailSentUserActivation(string $email): string return sprintf(self::MAIL_SENT_USER_ACTIVATION, $email); } + public static function resourceAlreadyRegistered(string $resource): string + { + return sprintf(self::RESOURCE_ALREADY_REGISTERED, $resource); + } + + public static function resourceNotFound(string $resource = 'Resource'): string + { + return sprintf(self::RESOURCE_NOT_FOUND, $resource); + } + public static function restrictionDeprecation(string $first, string $second): string { return sprintf(self::RESTRICTION_DEPRECATION, $first, $second); diff --git a/src/Core/src/Setting/src/ConfigProvider.php b/src/Core/src/Setting/src/ConfigProvider.php index c82dea1b..9cfda078 100644 --- a/src/Core/src/Setting/src/ConfigProvider.php +++ b/src/Core/src/Setting/src/ConfigProvider.php @@ -19,7 +19,7 @@ public function __invoke(): array ]; } - public function getDependencies(): array + private function getDependencies(): array { return [ 'factories' => [ @@ -28,7 +28,7 @@ public function getDependencies(): array ]; } - public function getDoctrineConfig(): array + private function getDoctrineConfig(): array { return [ 'driver' => [ diff --git a/src/User/src/ConfigProvider.php b/src/User/src/ConfigProvider.php index a0efa60f..eb291fbc 100644 --- a/src/User/src/ConfigProvider.php +++ b/src/User/src/ConfigProvider.php @@ -8,9 +8,9 @@ use Api\App\Factory\HandlerDelegatorFactory; use Api\User\Collection\UserCollection; use Api\User\Collection\UserRoleCollection; -use Api\User\Handler\Account\Avatar\DeleteUserAccountAvatarHandler; -use Api\User\Handler\Account\Avatar\GetUserAccountAvatarHandler; -use Api\User\Handler\Account\Avatar\PostUserAccountAvatarHandler; +use Api\User\Handler\Account\Avatar\DeleteUserAccountAvatarResourceHandler; +use Api\User\Handler\Account\Avatar\GetUserAccountAvatarResourceHandler; +use Api\User\Handler\Account\Avatar\PostUserAccountAvatarResourceHandler; use Api\User\Handler\Account\DeleteUserAccountResourceHandler; use Api\User\Handler\Account\GetUserAccountResourceHandler; use Api\User\Handler\Account\PatchUserAccountActivateHandler; @@ -18,9 +18,9 @@ use Api\User\Handler\Account\PostUserAccountActivateHandler; use Api\User\Handler\Account\PostUserAccountRecoverHandler; use Api\User\Handler\Account\PostUserAccountResourceHandler; -use Api\User\Handler\Account\ResetPassword\GetUserAccountResetPasswordHandler; -use Api\User\Handler\Account\ResetPassword\PatchUserAccountResetPasswordHandler; -use Api\User\Handler\Account\ResetPassword\PostUserAccountResetPasswordHandler; +use Api\User\Handler\Account\ResetPassword\GetUserAccountResetPasswordResourceHandler; +use Api\User\Handler\Account\ResetPassword\PatchUserAccountResetPasswordResourceHandler; +use Api\User\Handler\Account\ResetPassword\PostUserAccountResetPasswordResourceHandler; use Api\User\Handler\User\Avatar\DeleteUserAvatarResourceHandler; use Api\User\Handler\User\Avatar\GetUserAvatarResourceHandler; use Api\User\Handler\User\Avatar\PostUserAvatarResourceHandler; @@ -63,63 +63,63 @@ private function getDependencies(): array { return [ 'delegators' => [ - Application::class => [RoutesDelegator::class], - DeleteUserAccountAvatarHandler::class => [HandlerDelegatorFactory::class], - DeleteUserAccountResourceHandler::class => [HandlerDelegatorFactory::class], - DeleteUserAvatarResourceHandler::class => [HandlerDelegatorFactory::class], - DeleteUserResourceHandler::class => [HandlerDelegatorFactory::class], - GetUserAccountAvatarHandler::class => [HandlerDelegatorFactory::class], - GetUserAccountResetPasswordHandler::class => [HandlerDelegatorFactory::class], - GetUserAccountResourceHandler::class => [HandlerDelegatorFactory::class], - GetUserAvatarResourceHandler::class => [HandlerDelegatorFactory::class], - GetUserCollectionHandler::class => [HandlerDelegatorFactory::class], - GetUserResourceHandler::class => [HandlerDelegatorFactory::class], - GetUserRoleCollectionHandler::class => [HandlerDelegatorFactory::class], - GetUserRoleResourceHandler::class => [HandlerDelegatorFactory::class], - PatchUserAccountActivateHandler::class => [HandlerDelegatorFactory::class], - PatchUserAccountResetPasswordHandler::class => [HandlerDelegatorFactory::class], - PatchUserAccountResourceHandler::class => [HandlerDelegatorFactory::class], - PatchUserActivateHandler::class => [HandlerDelegatorFactory::class], - PatchUserDeactivateHandler::class => [HandlerDelegatorFactory::class], - PatchUserResourceHandler::class => [HandlerDelegatorFactory::class], - PostUserAccountActivateHandler::class => [HandlerDelegatorFactory::class], - PostUserAccountAvatarHandler::class => [HandlerDelegatorFactory::class], - PostUserAccountRecoverHandler::class => [HandlerDelegatorFactory::class], - PostUserAccountResetPasswordHandler::class => [HandlerDelegatorFactory::class], - PostUserAccountResourceHandler::class => [HandlerDelegatorFactory::class], - PostUserAvatarResourceHandler::class => [HandlerDelegatorFactory::class], - PostUserResourceHandler::class => [HandlerDelegatorFactory::class], + Application::class => [RoutesDelegator::class], + DeleteUserAccountAvatarResourceHandler::class => [HandlerDelegatorFactory::class], + DeleteUserAccountResourceHandler::class => [HandlerDelegatorFactory::class], + DeleteUserAvatarResourceHandler::class => [HandlerDelegatorFactory::class], + DeleteUserResourceHandler::class => [HandlerDelegatorFactory::class], + GetUserAccountAvatarResourceHandler::class => [HandlerDelegatorFactory::class], + GetUserAccountResetPasswordResourceHandler::class => [HandlerDelegatorFactory::class], + GetUserAccountResourceHandler::class => [HandlerDelegatorFactory::class], + GetUserAvatarResourceHandler::class => [HandlerDelegatorFactory::class], + GetUserCollectionHandler::class => [HandlerDelegatorFactory::class], + GetUserResourceHandler::class => [HandlerDelegatorFactory::class], + GetUserRoleCollectionHandler::class => [HandlerDelegatorFactory::class], + GetUserRoleResourceHandler::class => [HandlerDelegatorFactory::class], + PatchUserAccountActivateHandler::class => [HandlerDelegatorFactory::class], + PatchUserAccountResetPasswordResourceHandler::class => [HandlerDelegatorFactory::class], + PatchUserAccountResourceHandler::class => [HandlerDelegatorFactory::class], + PatchUserActivateHandler::class => [HandlerDelegatorFactory::class], + PatchUserDeactivateHandler::class => [HandlerDelegatorFactory::class], + PatchUserResourceHandler::class => [HandlerDelegatorFactory::class], + PostUserAccountActivateHandler::class => [HandlerDelegatorFactory::class], + PostUserAccountAvatarResourceHandler::class => [HandlerDelegatorFactory::class], + PostUserAccountRecoverHandler::class => [HandlerDelegatorFactory::class], + PostUserAccountResetPasswordResourceHandler::class => [HandlerDelegatorFactory::class], + PostUserAccountResourceHandler::class => [HandlerDelegatorFactory::class], + PostUserAvatarResourceHandler::class => [HandlerDelegatorFactory::class], + PostUserResourceHandler::class => [HandlerDelegatorFactory::class], ], 'factories' => [ - DeleteUserAccountAvatarHandler::class => AttributedServiceFactory::class, - DeleteUserAccountResourceHandler::class => AttributedServiceFactory::class, - DeleteUserAvatarResourceHandler::class => AttributedServiceFactory::class, - DeleteUserResourceHandler::class => AttributedServiceFactory::class, - GetUserAccountAvatarHandler::class => AttributedServiceFactory::class, - GetUserAccountResetPasswordHandler::class => AttributedServiceFactory::class, - GetUserAccountResourceHandler::class => AttributedServiceFactory::class, - GetUserAvatarResourceHandler::class => AttributedServiceFactory::class, - GetUserCollectionHandler::class => AttributedServiceFactory::class, - GetUserResourceHandler::class => AttributedServiceFactory::class, - GetUserRoleCollectionHandler::class => AttributedServiceFactory::class, - GetUserRoleResourceHandler::class => AttributedServiceFactory::class, - PatchUserAccountActivateHandler::class => AttributedServiceFactory::class, - PatchUserAccountResetPasswordHandler::class => AttributedServiceFactory::class, - PatchUserAccountResourceHandler::class => AttributedServiceFactory::class, - PatchUserActivateHandler::class => AttributedServiceFactory::class, - PatchUserDeactivateHandler::class => AttributedServiceFactory::class, - PatchUserResourceHandler::class => AttributedServiceFactory::class, - PostUserAccountActivateHandler::class => AttributedServiceFactory::class, - PostUserAccountAvatarHandler::class => AttributedServiceFactory::class, - PostUserAccountRecoverHandler::class => AttributedServiceFactory::class, - PostUserAccountResetPasswordHandler::class => AttributedServiceFactory::class, - PostUserAccountResourceHandler::class => AttributedServiceFactory::class, - PostUserAvatarResourceHandler::class => AttributedServiceFactory::class, - PostUserResourceHandler::class => AttributedServiceFactory::class, - UserAvatarService::class => AttributedServiceFactory::class, - UserResetPasswordService::class => AttributedServiceFactory::class, - UserRoleService::class => AttributedServiceFactory::class, - UserService::class => AttributedServiceFactory::class, + DeleteUserAccountAvatarResourceHandler::class => AttributedServiceFactory::class, + DeleteUserAccountResourceHandler::class => AttributedServiceFactory::class, + DeleteUserAvatarResourceHandler::class => AttributedServiceFactory::class, + DeleteUserResourceHandler::class => AttributedServiceFactory::class, + GetUserAccountAvatarResourceHandler::class => AttributedServiceFactory::class, + GetUserAccountResetPasswordResourceHandler::class => AttributedServiceFactory::class, + GetUserAccountResourceHandler::class => AttributedServiceFactory::class, + GetUserAvatarResourceHandler::class => AttributedServiceFactory::class, + GetUserCollectionHandler::class => AttributedServiceFactory::class, + GetUserResourceHandler::class => AttributedServiceFactory::class, + GetUserRoleCollectionHandler::class => AttributedServiceFactory::class, + GetUserRoleResourceHandler::class => AttributedServiceFactory::class, + PatchUserAccountActivateHandler::class => AttributedServiceFactory::class, + PatchUserAccountResetPasswordResourceHandler::class => AttributedServiceFactory::class, + PatchUserAccountResourceHandler::class => AttributedServiceFactory::class, + PatchUserActivateHandler::class => AttributedServiceFactory::class, + PatchUserDeactivateHandler::class => AttributedServiceFactory::class, + PatchUserResourceHandler::class => AttributedServiceFactory::class, + PostUserAccountActivateHandler::class => AttributedServiceFactory::class, + PostUserAccountAvatarResourceHandler::class => AttributedServiceFactory::class, + PostUserAccountRecoverHandler::class => AttributedServiceFactory::class, + PostUserAccountResetPasswordResourceHandler::class => AttributedServiceFactory::class, + PostUserAccountResourceHandler::class => AttributedServiceFactory::class, + PostUserAvatarResourceHandler::class => AttributedServiceFactory::class, + PostUserResourceHandler::class => AttributedServiceFactory::class, + UserAvatarService::class => AttributedServiceFactory::class, + UserResetPasswordService::class => AttributedServiceFactory::class, + UserRoleService::class => AttributedServiceFactory::class, + UserService::class => AttributedServiceFactory::class, ], 'aliases' => [ UserAvatarServiceInterface::class => UserAvatarService::class, diff --git a/src/User/src/Handler/Account/Avatar/DeleteUserAccountAvatarHandler.php b/src/User/src/Handler/Account/Avatar/DeleteUserAccountAvatarResourceHandler.php similarity index 84% rename from src/User/src/Handler/Account/Avatar/DeleteUserAccountAvatarHandler.php rename to src/User/src/Handler/Account/Avatar/DeleteUserAccountAvatarResourceHandler.php index 4e3d96d3..1b9445db 100644 --- a/src/User/src/Handler/Account/Avatar/DeleteUserAccountAvatarHandler.php +++ b/src/User/src/Handler/Account/Avatar/DeleteUserAccountAvatarResourceHandler.php @@ -6,14 +6,14 @@ use Api\App\Exception\NotFoundException; use Api\App\Handler\AbstractHandler; +use Api\App\IdentityInterface; use Api\User\Service\UserAvatarServiceInterface; use Core\App\Message; -use Core\User\Entity\User; use Dot\DependencyInjection\Attribute\Inject; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; -class DeleteUserAccountAvatarHandler extends AbstractHandler +class DeleteUserAccountAvatarResourceHandler extends AbstractHandler { #[Inject( UserAvatarServiceInterface::class, @@ -28,7 +28,7 @@ public function __construct( */ public function handle(ServerRequestInterface $request): ResponseInterface { - $user = $request->getAttribute(User::class); + $user = $request->getAttribute(IdentityInterface::class); if (! $user->hasAvatar()) { throw NotFoundException::create(Message::USER_AVATAR_MISSING); } diff --git a/src/User/src/Handler/Account/Avatar/GetUserAccountAvatarHandler.php b/src/User/src/Handler/Account/Avatar/GetUserAccountAvatarResourceHandler.php similarity index 84% rename from src/User/src/Handler/Account/Avatar/GetUserAccountAvatarHandler.php rename to src/User/src/Handler/Account/Avatar/GetUserAccountAvatarResourceHandler.php index a1c81a04..529b0d04 100644 --- a/src/User/src/Handler/Account/Avatar/GetUserAccountAvatarHandler.php +++ b/src/User/src/Handler/Account/Avatar/GetUserAccountAvatarResourceHandler.php @@ -6,14 +6,14 @@ use Api\App\Exception\NotFoundException; use Api\App\Handler\AbstractHandler; +use Api\App\IdentityInterface; use Api\User\Service\UserAvatarServiceInterface; use Core\App\Message; -use Core\User\Entity\User; use Dot\DependencyInjection\Attribute\Inject; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; -class GetUserAccountAvatarHandler extends AbstractHandler +class GetUserAccountAvatarResourceHandler extends AbstractHandler { #[Inject( UserAvatarServiceInterface::class, @@ -28,7 +28,7 @@ public function __construct( */ public function handle(ServerRequestInterface $request): ResponseInterface { - $user = $request->getAttribute(User::class); + $user = $request->getAttribute(IdentityInterface::class); if (! $user->hasAvatar()) { throw NotFoundException::create(Message::USER_AVATAR_MISSING); } diff --git a/src/User/src/Handler/Account/Avatar/PostUserAccountAvatarHandler.php b/src/User/src/Handler/Account/Avatar/PostUserAccountAvatarResourceHandler.php similarity index 89% rename from src/User/src/Handler/Account/Avatar/PostUserAccountAvatarHandler.php rename to src/User/src/Handler/Account/Avatar/PostUserAccountAvatarResourceHandler.php index 78589945..415fd539 100644 --- a/src/User/src/Handler/Account/Avatar/PostUserAccountAvatarHandler.php +++ b/src/User/src/Handler/Account/Avatar/PostUserAccountAvatarResourceHandler.php @@ -6,15 +6,15 @@ use Api\App\Exception\BadRequestException; use Api\App\Handler\AbstractHandler; +use Api\App\IdentityInterface; use Api\User\InputFilter\UpdateAvatarInputFilter; use Api\User\Service\UserAvatarServiceInterface; use Core\App\Message; -use Core\User\Entity\User; use Dot\DependencyInjection\Attribute\Inject; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; -class PostUserAccountAvatarHandler extends AbstractHandler +class PostUserAccountAvatarResourceHandler extends AbstractHandler { #[Inject( UserAvatarServiceInterface::class, @@ -42,7 +42,7 @@ public function handle(ServerRequestInterface $request): ResponseInterface return $this->createdResponse( $request, $this->userAvatarService->saveAvatar( - $request->getAttribute(User::class), + $request->getAttribute(IdentityInterface::class), $this->inputFilter->getValue('avatar') ) ); diff --git a/src/User/src/Handler/Account/DeleteUserAccountResourceHandler.php b/src/User/src/Handler/Account/DeleteUserAccountResourceHandler.php index da551707..68f8f953 100644 --- a/src/User/src/Handler/Account/DeleteUserAccountResourceHandler.php +++ b/src/User/src/Handler/Account/DeleteUserAccountResourceHandler.php @@ -5,8 +5,8 @@ namespace Api\User\Handler\Account; use Api\App\Handler\AbstractHandler; +use Api\App\IdentityInterface; use Api\User\Service\UserServiceInterface; -use Core\User\Entity\User; use Dot\DependencyInjection\Attribute\Inject; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; @@ -23,7 +23,9 @@ public function __construct( public function handle(ServerRequestInterface $request): ResponseInterface { - $this->userService->deleteUser($request->getAttribute(User::class)); + $this->userService->deleteUser( + $request->getAttribute(IdentityInterface::class) + ); return $this->noContentResponse(); } diff --git a/src/User/src/Handler/Account/GetUserAccountResourceHandler.php b/src/User/src/Handler/Account/GetUserAccountResourceHandler.php index 6f547bdd..1d2c9649 100644 --- a/src/User/src/Handler/Account/GetUserAccountResourceHandler.php +++ b/src/User/src/Handler/Account/GetUserAccountResourceHandler.php @@ -5,24 +5,14 @@ namespace Api\User\Handler\Account; use Api\App\Handler\AbstractHandler; -use Api\User\Service\UserServiceInterface; -use Core\User\Entity\User; -use Dot\DependencyInjection\Attribute\Inject; +use Api\App\IdentityInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; class GetUserAccountResourceHandler extends AbstractHandler { - #[Inject( - UserServiceInterface::class, - )] - public function __construct( - protected UserServiceInterface $userService, - ) { - } - public function handle(ServerRequestInterface $request): ResponseInterface { - return $this->createResponse($request, $request->getAttribute(User::class)); + return $this->createResponse($request, $request->getAttribute(IdentityInterface::class)); } } diff --git a/src/User/src/Handler/Account/PatchUserAccountActivateHandler.php b/src/User/src/Handler/Account/PatchUserAccountActivateHandler.php index 81269954..feaffccd 100644 --- a/src/User/src/Handler/Account/PatchUserAccountActivateHandler.php +++ b/src/User/src/Handler/Account/PatchUserAccountActivateHandler.php @@ -4,11 +4,12 @@ namespace Api\User\Handler\Account; +use Api\App\Attribute\Resource; use Api\App\Exception\ConflictException; -use Api\App\Exception\NotFoundException; use Api\App\Handler\AbstractHandler; use Api\User\Service\UserServiceInterface; use Core\App\Message; +use Core\User\Entity\User; use Dot\DependencyInjection\Attribute\Inject; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; @@ -25,11 +26,11 @@ public function __construct( /** * @throws ConflictException - * @throws NotFoundException */ + #[Resource(entity: User::class, identifier: 'hash', placeholder: 'hash')] public function handle(ServerRequestInterface $request): ResponseInterface { - $user = $this->userService->findOneBy(['hash' => $request->getAttribute('hash')]); + $user = $request->getAttribute(User::class); if ($user->isActive()) { throw ConflictException::create(Message::USER_ALREADY_ACTIVATED); } diff --git a/src/User/src/Handler/Account/PatchUserAccountResourceHandler.php b/src/User/src/Handler/Account/PatchUserAccountResourceHandler.php index c49f9564..1f232b8b 100644 --- a/src/User/src/Handler/Account/PatchUserAccountResourceHandler.php +++ b/src/User/src/Handler/Account/PatchUserAccountResourceHandler.php @@ -8,10 +8,10 @@ use Api\App\Exception\ConflictException; use Api\App\Exception\NotFoundException; use Api\App\Handler\AbstractHandler; +use Api\App\IdentityInterface; use Api\User\InputFilter\UpdateUserInputFilter; use Api\User\Service\UserServiceInterface; use Core\App\Message; -use Core\User\Entity\User; use Dot\DependencyInjection\Attribute\Inject; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; @@ -49,7 +49,7 @@ public function handle(ServerRequestInterface $request): ResponseInterface $request, $this->userService->saveUser( (array) $this->inputFilter->getValues(), - $request->getAttribute(User::class) + $request->getAttribute(IdentityInterface::class) ) ); } diff --git a/src/User/src/Handler/Account/ResetPassword/GetUserAccountResetPasswordHandler.php b/src/User/src/Handler/Account/ResetPassword/GetUserAccountResetPasswordResourceHandler.php similarity index 56% rename from src/User/src/Handler/Account/ResetPassword/GetUserAccountResetPasswordHandler.php rename to src/User/src/Handler/Account/ResetPassword/GetUserAccountResetPasswordResourceHandler.php index c010fe40..3e032573 100644 --- a/src/User/src/Handler/Account/ResetPassword/GetUserAccountResetPasswordHandler.php +++ b/src/User/src/Handler/Account/ResetPassword/GetUserAccountResetPasswordResourceHandler.php @@ -4,34 +4,23 @@ namespace Api\User\Handler\Account\ResetPassword; +use Api\App\Attribute\Resource; use Api\App\Exception\ExpiredException; -use Api\App\Exception\NotFoundException; use Api\App\Handler\AbstractHandler; -use Api\User\Service\UserResetPasswordServiceInterface; use Core\App\Message; -use Dot\DependencyInjection\Attribute\Inject; +use Core\User\Entity\UserResetPassword; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; -class GetUserAccountResetPasswordHandler extends AbstractHandler +class GetUserAccountResetPasswordResourceHandler extends AbstractHandler { - #[Inject( - UserResetPasswordServiceInterface::class, - )] - public function __construct( - protected UserResetPasswordServiceInterface $userResetPasswordService, - ) { - } - /** * @throws ExpiredException - * @throws NotFoundException */ + #[Resource(entity: UserResetPassword::class, identifier: 'hash', placeholder: 'hash')] public function handle(ServerRequestInterface $request): ResponseInterface { - $hash = $request->getAttribute('hash'); - - $userResetPassword = $this->userResetPasswordService->findOneBy(['hash' => $hash]); + $userResetPassword = $request->getAttribute(UserResetPassword::class); if (! $userResetPassword->isValid()) { throw ExpiredException::create(Message::RESET_PASSWORD_EXPIRED); } diff --git a/src/User/src/Handler/Account/ResetPassword/PatchUserAccountResetPasswordHandler.php b/src/User/src/Handler/Account/ResetPassword/PatchUserAccountResetPasswordResourceHandler.php similarity index 84% rename from src/User/src/Handler/Account/ResetPassword/PatchUserAccountResetPasswordHandler.php rename to src/User/src/Handler/Account/ResetPassword/PatchUserAccountResetPasswordResourceHandler.php index ea151e72..8498dcce 100644 --- a/src/User/src/Handler/Account/ResetPassword/PatchUserAccountResetPasswordHandler.php +++ b/src/User/src/Handler/Account/ResetPassword/PatchUserAccountResetPasswordResourceHandler.php @@ -4,33 +4,32 @@ namespace Api\User\Handler\Account\ResetPassword; +use Api\App\Attribute\Resource; use Api\App\Exception\BadRequestException; use Api\App\Exception\ConflictException; use Api\App\Exception\ExpiredException; use Api\App\Exception\NotFoundException; use Api\App\Handler\AbstractHandler; use Api\User\InputFilter\UpdatePasswordInputFilter; -use Api\User\Service\UserResetPasswordServiceInterface; use Api\User\Service\UserServiceInterface; use Core\App\Message; use Core\App\Service\MailService; +use Core\User\Entity\UserResetPassword; use Dot\DependencyInjection\Attribute\Inject; use Dot\Mail\Exception\MailException; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; -class PatchUserAccountResetPasswordHandler extends AbstractHandler +class PatchUserAccountResetPasswordResourceHandler extends AbstractHandler { #[Inject( MailService::class, UserServiceInterface::class, - UserResetPasswordServiceInterface::class, UpdatePasswordInputFilter::class, )] public function __construct( protected MailService $mailService, protected UserServiceInterface $userService, - protected UserResetPasswordServiceInterface $userResetPasswordService, protected UpdatePasswordInputFilter $inputFilter, ) { } @@ -42,6 +41,7 @@ public function __construct( * @throws MailException * @throws NotFoundException */ + #[Resource(entity: UserResetPassword::class, identifier: 'hash', placeholder: 'hash')] public function handle(ServerRequestInterface $request): ResponseInterface { $this->inputFilter->setData((array) $request->getParsedBody()); @@ -52,9 +52,7 @@ public function handle(ServerRequestInterface $request): ResponseInterface ); } - $hash = $request->getAttribute('hash'); - - $userResetPassword = $this->userResetPasswordService->findOneBy(['hash' => $hash]); + $userResetPassword = $request->getAttribute(UserResetPassword::class); if (! $userResetPassword->isValid()) { throw ExpiredException::create(Message::RESET_PASSWORD_EXPIRED); } diff --git a/src/User/src/Handler/Account/ResetPassword/PostUserAccountResetPasswordHandler.php b/src/User/src/Handler/Account/ResetPassword/PostUserAccountResetPasswordResourceHandler.php similarity index 96% rename from src/User/src/Handler/Account/ResetPassword/PostUserAccountResetPasswordHandler.php rename to src/User/src/Handler/Account/ResetPassword/PostUserAccountResetPasswordResourceHandler.php index 2455379c..5e17e51e 100644 --- a/src/User/src/Handler/Account/ResetPassword/PostUserAccountResetPasswordHandler.php +++ b/src/User/src/Handler/Account/ResetPassword/PostUserAccountResetPasswordResourceHandler.php @@ -18,7 +18,7 @@ use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; -class PostUserAccountResetPasswordHandler extends AbstractHandler +class PostUserAccountResetPasswordResourceHandler extends AbstractHandler { #[Inject( MailService::class, diff --git a/src/User/src/Handler/User/Avatar/DeleteUserAvatarResourceHandler.php b/src/User/src/Handler/User/Avatar/DeleteUserAvatarResourceHandler.php index 7a345b59..29be3e36 100644 --- a/src/User/src/Handler/User/Avatar/DeleteUserAvatarResourceHandler.php +++ b/src/User/src/Handler/User/Avatar/DeleteUserAvatarResourceHandler.php @@ -4,11 +4,12 @@ namespace Api\User\Handler\User\Avatar; +use Api\App\Attribute\Resource; use Api\App\Exception\NotFoundException; use Api\App\Handler\AbstractHandler; use Api\User\Service\UserAvatarServiceInterface; -use Api\User\Service\UserServiceInterface; use Core\App\Message; +use Core\User\Entity\User; use Dot\DependencyInjection\Attribute\Inject; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; @@ -16,11 +17,9 @@ class DeleteUserAvatarResourceHandler extends AbstractHandler { #[Inject( - UserServiceInterface::class, UserAvatarServiceInterface::class, )] public function __construct( - protected UserServiceInterface $userService, protected UserAvatarServiceInterface $userAvatarService, ) { } @@ -28,9 +27,10 @@ public function __construct( /** * @throws NotFoundException */ + #[Resource(entity: User::class)] public function handle(ServerRequestInterface $request): ResponseInterface { - $user = $this->userService->findUser($request->getAttribute('uuid')); + $user = $request->getAttribute(User::class); if (! $user->hasAvatar()) { throw NotFoundException::create(Message::USER_AVATAR_MISSING); } diff --git a/src/User/src/Handler/User/Avatar/GetUserAvatarResourceHandler.php b/src/User/src/Handler/User/Avatar/GetUserAvatarResourceHandler.php index c7006ca2..2ed5218f 100644 --- a/src/User/src/Handler/User/Avatar/GetUserAvatarResourceHandler.php +++ b/src/User/src/Handler/User/Avatar/GetUserAvatarResourceHandler.php @@ -4,30 +4,23 @@ namespace Api\User\Handler\User\Avatar; +use Api\App\Attribute\Resource; use Api\App\Exception\NotFoundException; use Api\App\Handler\AbstractHandler; -use Api\User\Service\UserServiceInterface; use Core\App\Message; -use Dot\DependencyInjection\Attribute\Inject; +use Core\User\Entity\User; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; class GetUserAvatarResourceHandler extends AbstractHandler { - #[Inject( - UserServiceInterface::class, - )] - public function __construct( - protected UserServiceInterface $userService, - ) { - } - /** * @throws NotFoundException */ + #[Resource(entity: User::class)] public function handle(ServerRequestInterface $request): ResponseInterface { - $user = $this->userService->findUser($request->getAttribute('uuid')); + $user = $request->getAttribute(User::class); if (! $user->hasAvatar()) { throw NotFoundException::create(Message::USER_AVATAR_MISSING); } diff --git a/src/User/src/Handler/User/Avatar/PostUserAvatarResourceHandler.php b/src/User/src/Handler/User/Avatar/PostUserAvatarResourceHandler.php index c7cfcc52..4da05572 100644 --- a/src/User/src/Handler/User/Avatar/PostUserAvatarResourceHandler.php +++ b/src/User/src/Handler/User/Avatar/PostUserAvatarResourceHandler.php @@ -4,13 +4,13 @@ namespace Api\User\Handler\User\Avatar; +use Api\App\Attribute\Resource; use Api\App\Exception\BadRequestException; -use Api\App\Exception\NotFoundException; use Api\App\Handler\AbstractHandler; use Api\User\InputFilter\UpdateAvatarInputFilter; use Api\User\Service\UserAvatarServiceInterface; -use Api\User\Service\UserServiceInterface; use Core\App\Message; +use Core\User\Entity\User; use Dot\DependencyInjection\Attribute\Inject; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; @@ -18,12 +18,10 @@ class PostUserAvatarResourceHandler extends AbstractHandler { #[Inject( - UserServiceInterface::class, UserAvatarServiceInterface::class, UpdateAvatarInputFilter::class, )] public function __construct( - protected UserServiceInterface $userService, protected UserAvatarServiceInterface $userAvatarService, protected UpdateAvatarInputFilter $inputFilter, ) { @@ -31,8 +29,8 @@ public function __construct( /** * @throws BadRequestException - * @throws NotFoundException */ + #[Resource(entity: User::class)] public function handle(ServerRequestInterface $request): ResponseInterface { $this->inputFilter->setData($request->getUploadedFiles()); @@ -46,7 +44,7 @@ public function handle(ServerRequestInterface $request): ResponseInterface return $this->createdResponse( $request, $this->userAvatarService->saveAvatar( - $this->userService->findUser($request->getAttribute('uuid')), + $request->getAttribute(User::class), $this->inputFilter->getValue('avatar') ) ); diff --git a/src/User/src/Handler/User/DeleteUserResourceHandler.php b/src/User/src/Handler/User/DeleteUserResourceHandler.php index cf3dd4bc..b3572483 100644 --- a/src/User/src/Handler/User/DeleteUserResourceHandler.php +++ b/src/User/src/Handler/User/DeleteUserResourceHandler.php @@ -4,10 +4,10 @@ namespace Api\User\Handler\User; -use Api\App\Exception\NotFoundException; -use Api\App\Exception\RuntimeException; +use Api\App\Attribute\Resource; use Api\App\Handler\AbstractHandler; use Api\User\Service\UserServiceInterface; +use Core\User\Entity\User; use Dot\DependencyInjection\Attribute\Inject; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; @@ -22,14 +22,11 @@ public function __construct( ) { } - /** - * @throws NotFoundException - * @throws RuntimeException - */ + #[Resource(entity: User::class)] public function handle(ServerRequestInterface $request): ResponseInterface { $this->userService->deleteUser( - $this->userService->findUser($request->getAttribute('uuid')) + $request->getAttribute(User::class) ); return $this->noContentResponse(); diff --git a/src/User/src/Handler/User/GetUserResourceHandler.php b/src/User/src/Handler/User/GetUserResourceHandler.php index 4bd381e3..787f302d 100644 --- a/src/User/src/Handler/User/GetUserResourceHandler.php +++ b/src/User/src/Handler/User/GetUserResourceHandler.php @@ -4,31 +4,20 @@ namespace Api\User\Handler\User; -use Api\App\Exception\NotFoundException; +use Api\App\Attribute\Resource; use Api\App\Handler\AbstractHandler; -use Api\User\Service\UserServiceInterface; -use Dot\DependencyInjection\Attribute\Inject; +use Core\User\Entity\User; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; class GetUserResourceHandler extends AbstractHandler { - #[Inject( - UserServiceInterface::class, - )] - public function __construct( - protected UserServiceInterface $userService, - ) { - } - - /** - * @throws NotFoundException - */ + #[Resource(entity: User::class)] public function handle(ServerRequestInterface $request): ResponseInterface { return $this->createResponse( $request, - $this->userService->findUser($request->getAttribute('uuid')) + $request->getAttribute(User::class) ); } } diff --git a/src/User/src/Handler/User/PatchUserActivateHandler.php b/src/User/src/Handler/User/PatchUserActivateHandler.php index 8c70db1d..7725a0ee 100644 --- a/src/User/src/Handler/User/PatchUserActivateHandler.php +++ b/src/User/src/Handler/User/PatchUserActivateHandler.php @@ -4,12 +4,14 @@ namespace Api\User\Handler\User; +use Api\App\Attribute\Resource; use Api\App\Exception\ConflictException; use Api\App\Exception\NotFoundException; use Api\App\Handler\AbstractHandler; use Api\User\Service\UserServiceInterface; use Core\App\Message; use Core\App\Service\MailService; +use Core\User\Entity\User; use Dot\DependencyInjection\Attribute\Inject; use Dot\Mail\Exception\MailException; use Psr\Http\Message\ResponseInterface; @@ -32,9 +34,10 @@ public function __construct( * @throws MailException * @throws NotFoundException */ + #[Resource(entity: User::class)] public function handle(ServerRequestInterface $request): ResponseInterface { - $user = $this->userService->findUser($request->getAttribute('uuid')); + $user = $request->getAttribute(User::class); if ($user->isActive()) { throw ConflictException::create(Message::USER_ALREADY_ACTIVATED); } diff --git a/src/User/src/Handler/User/PatchUserDeactivateHandler.php b/src/User/src/Handler/User/PatchUserDeactivateHandler.php index 836c6c50..8ff4ee8c 100644 --- a/src/User/src/Handler/User/PatchUserDeactivateHandler.php +++ b/src/User/src/Handler/User/PatchUserDeactivateHandler.php @@ -4,11 +4,13 @@ namespace Api\User\Handler\User; +use Api\App\Attribute\Resource; use Api\App\Exception\ConflictException; use Api\App\Exception\NotFoundException; use Api\App\Handler\AbstractHandler; use Api\User\Service\UserServiceInterface; use Core\App\Message; +use Core\User\Entity\User; use Dot\DependencyInjection\Attribute\Inject; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; @@ -27,9 +29,10 @@ public function __construct( * @throws ConflictException * @throws NotFoundException */ + #[Resource(entity: User::class)] public function handle(ServerRequestInterface $request): ResponseInterface { - $user = $this->userService->findUser($request->getAttribute('uuid')); + $user = $request->getAttribute(User::class); if ($user->isPending()) { throw ConflictException::create(Message::USER_ALREADY_DEACTIVATED); } diff --git a/src/User/src/Handler/User/PatchUserResourceHandler.php b/src/User/src/Handler/User/PatchUserResourceHandler.php index 6961d9fe..641c101e 100644 --- a/src/User/src/Handler/User/PatchUserResourceHandler.php +++ b/src/User/src/Handler/User/PatchUserResourceHandler.php @@ -4,6 +4,7 @@ namespace Api\User\Handler\User; +use Api\App\Attribute\Resource; use Api\App\Exception\BadRequestException; use Api\App\Exception\ConflictException; use Api\App\Exception\NotFoundException; @@ -11,6 +12,7 @@ use Api\User\InputFilter\UpdateUserInputFilter; use Api\User\Service\UserServiceInterface; use Core\App\Message; +use Core\User\Entity\User; use Dot\DependencyInjection\Attribute\Inject; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; @@ -32,6 +34,7 @@ public function __construct( * @throws ConflictException * @throws NotFoundException */ + #[Resource(entity: User::class)] public function handle(ServerRequestInterface $request): ResponseInterface { $this->inputFilter->setData((array) $request->getParsedBody()); @@ -46,7 +49,7 @@ public function handle(ServerRequestInterface $request): ResponseInterface $request, $this->userService->saveUser( (array) $this->inputFilter->getValues(), - $this->userService->findUser($request->getAttribute('uuid')) + $request->getAttribute(User::class) ) ); } diff --git a/src/User/src/Handler/User/Role/GetUserRoleResourceHandler.php b/src/User/src/Handler/User/Role/GetUserRoleResourceHandler.php index 2b01af24..0b847895 100644 --- a/src/User/src/Handler/User/Role/GetUserRoleResourceHandler.php +++ b/src/User/src/Handler/User/Role/GetUserRoleResourceHandler.php @@ -4,31 +4,20 @@ namespace Api\User\Handler\User\Role; -use Api\App\Exception\NotFoundException; +use Api\App\Attribute\Resource; use Api\App\Handler\AbstractHandler; -use Api\User\Service\UserRoleServiceInterface; -use Dot\DependencyInjection\Attribute\Inject; +use Core\User\Entity\UserRole; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; class GetUserRoleResourceHandler extends AbstractHandler { - #[Inject( - UserRoleServiceInterface::class, - )] - public function __construct( - protected UserRoleServiceInterface $userRoleService, - ) { - } - - /** - * @throws NotFoundException - */ + #[Resource(entity: UserRole::class)] public function handle(ServerRequestInterface $request): ResponseInterface { return $this->createResponse( $request, - $this->userRoleService->findUserRole($request->getAttribute('uuid')) + $request->getAttribute(UserRole::class) ); } } diff --git a/src/User/src/OpenAPI.php b/src/User/src/OpenAPI.php index 3a8c9bb3..ce9b6a3c 100644 --- a/src/User/src/OpenAPI.php +++ b/src/User/src/OpenAPI.php @@ -5,9 +5,9 @@ namespace Api\User; use Api\User\Collection\UserCollection; -use Api\User\Handler\Account\Avatar\DeleteUserAccountAvatarHandler; -use Api\User\Handler\Account\Avatar\GetUserAccountAvatarHandler; -use Api\User\Handler\Account\Avatar\PostUserAccountAvatarHandler; +use Api\User\Handler\Account\Avatar\DeleteUserAccountAvatarResourceHandler; +use Api\User\Handler\Account\Avatar\GetUserAccountAvatarResourceHandler; +use Api\User\Handler\Account\Avatar\PostUserAccountAvatarResourceHandler; use Api\User\Handler\Account\DeleteUserAccountResourceHandler; use Api\User\Handler\Account\GetUserAccountResourceHandler; use Api\User\Handler\Account\PatchUserAccountActivateHandler; @@ -15,9 +15,9 @@ use Api\User\Handler\Account\PostUserAccountActivateHandler; use Api\User\Handler\Account\PostUserAccountRecoverHandler; use Api\User\Handler\Account\PostUserAccountResourceHandler; -use Api\User\Handler\Account\ResetPassword\GetUserAccountResetPasswordHandler; -use Api\User\Handler\Account\ResetPassword\PatchUserAccountResetPasswordHandler; -use Api\User\Handler\Account\ResetPassword\PostUserAccountResetPasswordHandler; +use Api\User\Handler\Account\ResetPassword\GetUserAccountResetPasswordResourceHandler; +use Api\User\Handler\Account\ResetPassword\PatchUserAccountResetPasswordResourceHandler; +use Api\User\Handler\Account\ResetPassword\PostUserAccountResetPasswordResourceHandler; use Api\User\Handler\User\Avatar\DeleteUserAvatarResourceHandler; use Api\User\Handler\User\Avatar\GetUserAvatarResourceHandler; use Api\User\Handler\User\Avatar\PostUserAvatarResourceHandler; @@ -761,7 +761,7 @@ )] /** - * @see DeleteUserAccountAvatarHandler::handle() + * @see DeleteUserAccountAvatarResourceHandler::handle() */ #[OA\Delete( path: '/user/account/avatar', @@ -782,7 +782,7 @@ )] /** - * @see GetUserAccountAvatarHandler::handle() + * @see GetUserAccountAvatarResourceHandler::handle() */ #[OA\Get( path: '/user/account/avatar', @@ -804,7 +804,7 @@ )] /** - * @see PostUserAccountAvatarHandler::handle() + * @see PostUserAccountAvatarResourceHandler::handle() */ #[OA\Post( path: '/user/account/avatar', @@ -963,7 +963,7 @@ )] /** - * @see GetUserAccountResetPasswordHandler::handle() + * @see GetUserAccountResetPasswordResourceHandler::handle() */ #[OA\Get( path: '/user/account/reset-password/{hash}', @@ -997,7 +997,7 @@ )] /** - * @see PatchUserAccountResetPasswordHandler::handle() + * @see PatchUserAccountResetPasswordResourceHandler::handle() */ #[OA\Patch( path: '/user/account/reset-password/{hash}', @@ -1058,7 +1058,7 @@ )] /** - * @see PostUserAccountResetPasswordHandler::handle() + * @see PostUserAccountResetPasswordResourceHandler::handle() */ #[OA\Post( path: '/user/account/reset-password', diff --git a/src/User/src/RoutesDelegator.php b/src/User/src/RoutesDelegator.php index 69ea11c5..d52dd583 100644 --- a/src/User/src/RoutesDelegator.php +++ b/src/User/src/RoutesDelegator.php @@ -4,9 +4,9 @@ namespace Api\User; -use Api\User\Handler\Account\Avatar\DeleteUserAccountAvatarHandler; -use Api\User\Handler\Account\Avatar\GetUserAccountAvatarHandler; -use Api\User\Handler\Account\Avatar\PostUserAccountAvatarHandler; +use Api\User\Handler\Account\Avatar\DeleteUserAccountAvatarResourceHandler; +use Api\User\Handler\Account\Avatar\GetUserAccountAvatarResourceHandler; +use Api\User\Handler\Account\Avatar\PostUserAccountAvatarResourceHandler; use Api\User\Handler\Account\DeleteUserAccountResourceHandler; use Api\User\Handler\Account\GetUserAccountResourceHandler; use Api\User\Handler\Account\PatchUserAccountActivateHandler; @@ -14,9 +14,9 @@ use Api\User\Handler\Account\PostUserAccountActivateHandler; use Api\User\Handler\Account\PostUserAccountRecoverHandler; use Api\User\Handler\Account\PostUserAccountResourceHandler; -use Api\User\Handler\Account\ResetPassword\GetUserAccountResetPasswordHandler; -use Api\User\Handler\Account\ResetPassword\PatchUserAccountResetPasswordHandler; -use Api\User\Handler\Account\ResetPassword\PostUserAccountResetPasswordHandler; +use Api\User\Handler\Account\ResetPassword\GetUserAccountResetPasswordResourceHandler; +use Api\User\Handler\Account\ResetPassword\PatchUserAccountResetPasswordResourceHandler; +use Api\User\Handler\Account\ResetPassword\PostUserAccountResetPasswordResourceHandler; use Api\User\Handler\User\Avatar\DeleteUserAvatarResourceHandler; use Api\User\Handler\User\Avatar\GetUserAvatarResourceHandler; use Api\User\Handler\User\Avatar\PostUserAvatarResourceHandler; @@ -84,14 +84,26 @@ public function __invoke(ContainerInterface $container, string $serviceName, cal $routeCollector->post('/user/account/recover', PostUserAccountRecoverHandler::class, 'user::recover-account'); $routeCollector->group('/user/account/avatar') - ->delete('', DeleteUserAccountAvatarHandler::class, 'user::delete-account-avatar') - ->get('', GetUserAccountAvatarHandler::class, 'user::view-account-avatar') - ->post('', PostUserAccountAvatarHandler::class, 'user::create-account-avatar'); - - $routeCollector->group('/user/account/reset-password') - ->get('/{hash}', GetUserAccountResetPasswordHandler::class, 'user::check-account-reset-password') - ->patch('/{hash}', PatchUserAccountResetPasswordHandler::class, 'user::update-account-reset-password') - ->post('', PostUserAccountResetPasswordHandler::class, 'user::create-account-reset-password'); + ->delete('', DeleteUserAccountAvatarResourceHandler::class, 'user::delete-account-avatar') + ->get('', GetUserAccountAvatarResourceHandler::class, 'user::view-account-avatar') + ->post('', PostUserAccountAvatarResourceHandler::class, 'user::create-account-avatar'); + + $routeCollector + ->get( + '/user/account/reset-password/{hash}', + GetUserAccountResetPasswordResourceHandler::class, + 'user::check-account-reset-password' + ) + ->patch( + '/user/account/reset-password/{hash}', + PatchUserAccountResetPasswordResourceHandler::class, + 'user::update-account-reset-password' + ) + ->post( + '/user/account/reset-password', + PostUserAccountResetPasswordResourceHandler::class, + 'user::create-account-reset-password' + ); return $callback(); } diff --git a/test/Functional/UserTest.php b/test/Functional/UserTest.php index 864b5335..93f522fa 100644 --- a/test/Functional/UserTest.php +++ b/test/Functional/UserTest.php @@ -296,12 +296,6 @@ public function testDeleteMyAccount(): void $this->assertTrue($deletedUser?->isDeleted()); } - public function testRequestResetPasswordBadRequest(): void - { - $response = $this->patch('/user/account/reset-password/invalid_hash'); - $this->assertResponseBadRequest($response); - } - public function testRequestResetPasswordInvalidHash(): void { $response = $this->patch('/user/account/reset-password/invalid_hash', [