weedkeeper changes 2

This commit is contained in:
flo 2025-01-04 02:11:41 +01:00
parent c1ba50d533
commit 9565270c19
137 changed files with 2104 additions and 1184 deletions

View File

@ -10,6 +10,19 @@ DB_NAME_LOG=log
# API Keys
TEMPLATE_API_KEY=
# Mail
MAIL_DEFAULT_SENDER=template@stack-up.de
MAIL_DEFAULT_SENDER_NAME=Template
SMTP_USERNAME=
SMTP_PASSWORD=
SMTP_HOST=
SMTP_PORT=
SMTP_ENCRYPTION=ssl
# Notification
NOTIFICATION_HOST=
NOTIFICATION_ID=
# Template Setup
INIT_USER_NAME=admin
INIT_USER_PASSWORD=password

View File

@ -15,11 +15,13 @@
"symfony/cache": "5.4.8",
"doctrine/dbal": "^3.6",
"teewurst/psr4-advanced-wildcard-composer-plugin": "^3.0",
"laminas/laminas-crypt": "^3.10",
"monolog/monolog": "^3.4",
"laminas/laminas-mail": "^2.23",
"teewurst/pipeline": "^3.0",
"guzzlehttp/guzzle": "^7.8"
"guzzlehttp/guzzle": "^7.8",
"nette/mail": "^4.0",
"latte/latte": "^3.0",
"league/openapi-psr7-validator": "^0.22.0",
"symfony/finder": "^6.4"
},
"autoload": {
"psr-4": {
@ -66,6 +68,7 @@
]
},
"config": {
"process-timeout": 0,
"allow-plugins": {
"teewurst/psr4-advanced-wildcard-composer-plugin": true
}

View File

@ -58,7 +58,7 @@ $aggregator = new ConfigAggregator([
// HandlingDomain
\Template\Handling\User\ConfigProvider::class,
\Template\Handling\UserSession\ConfigProvider::class,
\Template\Handling\Authentication\ConfigProvider::class,
\Template\Handling\Registration\ConfigProvider::class,
// API

View File

@ -1,5 +1,7 @@
<?php
use Template\API\Console\Command\ExportModelsCommand;
use Template\API\Console\Command\ExportSchemaCommand;
use Template\API\Console\Command\InitializeDataCommand;
use Template\API\Console\Command\RbacUpdateCommand;
@ -7,5 +9,7 @@ return [
'commands' => [
InitializeDataCommand::class,
RbacUpdateCommand::class,
ExportModelsCommand::class,
ExportSchemaCommand::class,
]
];

View File

@ -1,5 +1,7 @@
<?php
use Template\API\Console\Command\ExportModelsCommand;
use Template\API\Console\Command\ExportSchemaCommand;
use Template\API\Console\Command\InitializeDataCommand;
use Template\API\Console\Command\RbacUpdateCommand;
use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
@ -8,5 +10,7 @@ return [
'factories' => [
InitializeDataCommand::class => AutoWiringFactory::class,
RbacUpdateCommand::class => AutoWiringFactory::class,
ExportModelsCommand::class => AutoWiringFactory::class,
ExportSchemaCommand::class => AutoWiringFactory::class,
],
];

View File

@ -0,0 +1,51 @@
<?php
namespace Template\API\Console\Command;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Throwable;
use Template\Infrastructure\Logging\Logger\Logger;
use Template\Infrastructure\Schema\Enum\SchemaType;
use Template\Infrastructure\Schema\Exporter\BackendExporter;
use Template\Infrastructure\Schema\Exporter\FrontendExporter;
use Template\Infrastructure\Schema\Model\Api;
use Template\Infrastructure\Schema\Model\Type;
use Template\Infrastructure\Schema\Reader\ApiDefinitionReader;
#[AsCommand(name: 'export:models', description: 'Creates an export file for all the models in the current schema definition')]
class ExportModelsCommand extends Command
{
public function __construct(
private readonly BackendExporter $backendExporter,
private readonly FrontendExporter $frontendExporter,
private readonly Logger $logger,
) {
parent::__construct($this->getName());
}
protected function execute(
InputInterface $input,
OutputInterface $output
): int {
$io = new SymfonyStyle($input, $output);
try {
$this->backendExporter->export();
$this->frontendExporter->export();
$io->success("OK!");
} catch (Throwable $e) {
$io->error($e->getMessage());
$io->error($e->getTraceAsString());
$this->logger->error($e->getMessage(), ['exception' => $e]);
return Command::FAILURE;
}
return Command::SUCCESS;
}
}

View File

@ -0,0 +1,46 @@
<?php
namespace Template\API\Console\Command;
use cebe\openapi\spec\OpenApi;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Throwable;
use Template\Infrastructure\Logging\Logger\Logger;
#[AsCommand(name: 'export:schema', description: 'Creates an export file for the current schema definitions')]
class ExportSchemaCommand extends Command
{
public function __construct(
private readonly OpenApi $schema,
private readonly Logger $logger,
) {
parent::__construct($this->getName());
}
protected function execute(
InputInterface $input,
OutputInterface $output
): int {
$io = new SymfonyStyle($input, $output);
try {
file_put_contents(
APP_ROOT . '/var/export/schema/api.export.json',
json_encode($this->schema->getSerializableData(), JSON_PRETTY_PRINT)
);
$io->success("OK!");
} catch (Throwable $e) {
$io->error($e->getMessage());
$io->error($e->getTraceAsString());
$this->logger->error($e->getMessage(), ['exception' => $e]);
return Command::FAILURE;
}
return Command::SUCCESS;
}
}

View File

@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
namespace Template\API\External\Api;
use Template\Infrastructure\Rbac\Middleware\EnsureAuthorizationMiddleware;
use Template\Infrastructure\Schema\Middleware\SchemaValidationMiddleware;
use Template\Infrastructure\Session\Middleware\LoggedInUserMiddleware;
use Template\API\External\Api\Health\HealthRequestHandler;
use Template\API\External\Api\Schema\SchemaRequestHandler;
return [
[
'name' => 'api.health',
'path' => '/api/health',
'allowed_methods' => ['GET'],
'middleware' => [
SchemaValidationMiddleware::class,
LoggedInUserMiddleware::class,
EnsureAuthorizationMiddleware::class,
HealthRequestHandler::class,
],
],
[
'name' => 'api.schema',
'path' => '/api/schema',
'allowed_methods' => ['GET'],
'middleware' => [
SchemaValidationMiddleware::class,
LoggedInUserMiddleware::class,
EnsureAuthorizationMiddleware::class,
SchemaRequestHandler::class,
],
],
];

View File

@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
namespace Template\API\External\Api;
use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
use Template\API\External\Api\Health\HealthRequestHandler;
use Template\API\External\Api\Schema\SchemaRequestHandler;
return [
'factories' => [
/// Health
HealthRequestHandler::class => AutoWiringFactory::class,
/// Schema
SchemaRequestHandler::class => AutoWiringFactory::class,
]
];

View File

@ -0,0 +1,16 @@
<?php
declare(strict_types=1);
namespace Template\API\External\Api;
class ConfigProvider
{
public function __invoke(): array
{
return [
'dependencies' => require __DIR__ . '/./../config/service_manager.php',
'routes' => require __DIR__ . '/./../config/routes.php',
];
}
}

View File

@ -0,0 +1,23 @@
<?php
declare(strict_types=1);
namespace Template\API\External\Api\Health;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Template\Infrastructure\Response\SuccessResponse;
use Template\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
class HealthRequestHandler implements RequestHandlerInterface
{
public function __construct(
) {
}
public function handle(ServerRequestInterface $request): ResponseInterface
{
return new SuccessResponse("I'm fine. :)");
}
}

View File

@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
namespace Template\API\External\Api\Schema;
use cebe\openapi\spec\OpenApi;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Template\Infrastructure\Response\SuccessResponse;
class SchemaRequestHandler implements RequestHandlerInterface
{
public function __construct(
private readonly OpenApi $schema,
) {
}
public function handle(ServerRequestInterface $request): ResponseInterface
{
$response = json_decode(
json_encode($this->schema->getSerializableData()),
true
);
return new SuccessResponse($response);
}
}

View File

@ -1,10 +1,13 @@
<?php
use Template\API\External\Authentication\Handler\ConfirmRegistrationHandler;
use Template\API\External\Authentication\Handler\LoginUserHandler;
use Template\API\External\Authentication\Handler\LogoutUserHandler;
use Template\API\External\Authentication\Handler\RegisterUserHandler;
use Template\Infrastructure\Schema\Middleware\SchemaValidationMiddleware;
use Template\Infrastructure\Session\Middleware\LoggedInUserMiddleware;
use Template\API\External\Authentication\LoginUser\LoginUserRequestHandler;
use Template\API\External\Authentication\LogoutUser\LogoutUserRequestHandler;
use Template\API\External\Authentication\ConfirmRegistration\ConfirmRegistrationRequestHandler;
use Template\API\External\Authentication\RegisterUser\RegisterUserRequestHandler;
use Template\API\External\Authentication\ForgotPassword\ForgotPasswordRequestHandler;
use Template\API\External\Authentication\ResetPassword\ResetPasswordRequestHandler;
return [
[
@ -12,16 +15,18 @@ return [
'path' => '/api/auth/login-user',
'allowed_methods' => ['POST'],
'middleware' => [
LoginUserHandler::class
SchemaValidationMiddleware::class,
LoginUserRequestHandler::class,
],
],
[
'name' => 'auth.logout-user',
'path' => '/api/auth/logout-user',
'allowed_methods' => ['POST'],
'allowed_methods' => ['GET'],
'middleware' => [
SchemaValidationMiddleware::class,
LoggedInUserMiddleware::class,
LogoutUserHandler::class
LogoutUserRequestHandler::class,
],
],
[
@ -29,7 +34,8 @@ return [
'path' => '/api/auth/confirm-registration',
'allowed_methods' => ['POST'],
'middleware' => [
ConfirmRegistrationHandler::class
SchemaValidationMiddleware::class,
ConfirmRegistrationRequestHandler::class,
],
],
[
@ -37,7 +43,26 @@ return [
'path' => '/api/auth/register-user',
'allowed_methods' => ['POST'],
'middleware' => [
RegisterUserHandler::class
SchemaValidationMiddleware::class,
RegisterUserRequestHandler::class,
],
],
[
'name' => 'auth.forgot-password',
'path' => '/api/auth/forgot-password',
'allowed_methods' => ['POST'],
'middleware' => [
SchemaValidationMiddleware::class,
ForgotPasswordRequestHandler::class,
],
],
[
'name' => 'auth.reset-password',
'path' => '/api/auth/reset-password',
'allowed_methods' => ['POST'],
'middleware' => [
SchemaValidationMiddleware::class,
ResetPasswordRequestHandler::class,
],
],
];

View File

@ -1,17 +1,39 @@
<?php
use Template\API\External\Authentication\Handler\ConfirmRegistrationHandler;
use Template\API\External\Authentication\Handler\LoginUserHandler;
use Template\API\External\Authentication\Handler\LogoutUserHandler;
use Template\API\External\Authentication\Handler\RegisterUserHandler;
use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
use Reinfi\DependencyInjection\Factory\InjectionFactory;
use Template\API\External\Authentication\LoginUser\LoginUserResponseFormatter;
use Template\API\External\Authentication\LoginUser\LoginUserRequestHandler;
use Template\API\External\Authentication\LogoutUser\LogoutUserResponseFormatter;
use Template\API\External\Authentication\LogoutUser\LogoutUserRequestHandler;
use Template\API\External\Authentication\ConfirmRegistration\ConfirmRegistrationResponseFormatter;
use Template\API\External\Authentication\ConfirmRegistration\ConfirmRegistrationRequestHandler;
use Template\API\External\Authentication\RegisterUser\RegisterUserResponseFormatter;
use Template\API\External\Authentication\RegisterUser\RegisterUserRequestHandler;
use Template\API\External\Authentication\ForgotPassword\ForgotPasswordResponseFormatter;
use Template\API\External\Authentication\ForgotPassword\ForgotPasswordRequestHandler;
use Template\API\External\Authentication\ResetPassword\ResetPasswordResponseFormatter;
use Template\API\External\Authentication\ResetPassword\ResetPasswordRequestHandler;
return [
'factories' => [
// Handler
LoginUserHandler::class => AutoWiringFactory::class,
LogoutUserHandler::class => AutoWiringFactory::class,
ConfirmRegistrationHandler::class => AutoWiringFactory::class,
RegisterUserHandler::class => AutoWiringFactory::class
/// LoginUser
LoginUserResponseFormatter::class => AutoWiringFactory::class,
LoginUserRequestHandler::class => AutoWiringFactory::class,
/// LogoutUser
LogoutUserResponseFormatter::class => AutoWiringFactory::class,
LogoutUserRequestHandler::class => AutoWiringFactory::class,
/// ConfirmRegistration
ConfirmRegistrationResponseFormatter::class => AutoWiringFactory::class,
ConfirmRegistrationRequestHandler::class => AutoWiringFactory::class,
/// RegisterUser
RegisterUserResponseFormatter::class => AutoWiringFactory::class,
RegisterUserRequestHandler::class => AutoWiringFactory::class,
/// ForgotPassword
ForgotPasswordResponseFormatter::class => AutoWiringFactory::class,
ForgotPasswordRequestHandler::class => AutoWiringFactory::class,
/// ResetPassword
ResetPasswordResponseFormatter::class => AutoWiringFactory::class,
ResetPasswordRequestHandler::class => AutoWiringFactory::class,
],
];

View File

@ -0,0 +1,40 @@
<?php
declare(strict_types=1);
namespace Template\API\External\Authentication\ConfirmRegistration;
use Ramsey\Uuid\Uuid;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Template\Infrastructure\Response\SuccessResponse;
use Template\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
use Template\Handling\Registration\UseCase\ConfirmRegistration\ConfirmRegistrationUseCaseHandler;
use Template\Handling\Registration\UseCase\ConfirmRegistration\ConfirmRegistrationUseCaseBuilder;
use Template\API\External\Authentication\ConfirmRegistration\ConfirmRegistrationResponseFormatter;
class ConfirmRegistrationRequestHandler implements RequestHandlerInterface
{
public function __construct(
private readonly ConfirmRegistrationUseCaseBuilder $builder,
private readonly ConfirmRegistrationUseCaseHandler $handler,
private readonly ConfirmRegistrationResponseFormatter $responseFormatter,
) {
}
public function handle(ServerRequestInterface $request): ResponseInterface
{
$data = $request->getAttribute(AnalyzeBodyMiddleware::JSON_DATA);
$useCase = $this->builder->build(
Uuid::fromString($data['id']),
$data['password'],
$data['passwordConfirmation'],
);
$result = $this->handler->handle($useCase);
$response = $this->responseFormatter->format($result);
return new SuccessResponse($response);
}
}

View File

@ -0,0 +1,31 @@
<?php
declare(strict_types=1);
namespace Template\API\External\Authentication\ConfirmRegistration;
use DateTimeInterface;
use Ramsey\Uuid\Uuid;
use Template\Handling\Registration\UseCase\ConfirmRegistration\ConfirmRegistrationUseCaseResult;
class ConfirmRegistrationResponseFormatter
{
public function format(ConfirmRegistrationUseCaseResult $result): array
{
$user = $result->getUser();
$permissions = [];
foreach ($user->getRole()->getPermissions()->toArray() as $permission) {
$permissions[] = $permission->getIdentifier();
}
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)
];
}
}

View File

@ -0,0 +1,37 @@
<?php
declare(strict_types=1);
namespace Template\API\External\Authentication\ForgotPassword;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Template\Infrastructure\Response\SuccessResponse;
use Template\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
use Template\Handling\Authentication\UseCase\ForgotPassword\ForgotPasswordUseCaseHandler;
use Template\Handling\Authentication\UseCase\ForgotPassword\ForgotPasswordUseCaseBuilder;
use Template\API\External\Authentication\ForgotPassword\ForgotPasswordResponseFormatter;
class ForgotPasswordRequestHandler implements RequestHandlerInterface
{
public function __construct(
private readonly ForgotPasswordUseCaseBuilder $builder,
private readonly ForgotPasswordUseCaseHandler $handler,
private readonly ForgotPasswordResponseFormatter $responseFormatter,
) {
}
public function handle(ServerRequestInterface $request): ResponseInterface
{
$data = $request->getAttribute(AnalyzeBodyMiddleware::JSON_DATA);
$useCase = $this->builder->build(
$data['mail'],
);
$result = $this->handler->handle($useCase);
$response = $this->responseFormatter->format($result);
return new SuccessResponse($response);
}
}

View File

@ -0,0 +1,16 @@
<?php
declare(strict_types=1);
namespace Template\API\External\Authentication\ForgotPassword;
use Template\Handling\Authentication\UseCase\ForgotPassword\ForgotPasswordUseCaseResult;
class ForgotPasswordResponseFormatter
{
public function format(ForgotPasswordUseCaseResult $result): array
{
return [
];
}
}

View File

@ -1,44 +0,0 @@
<?php
declare(strict_types=1);
namespace Template\API\External\Authentication\Handler;
use Template\API\External\User\Formatter\UserFormatter;
use Template\Handling\Registration\Handler\Command\ConfirmRegistration\ConfirmRegistrationCommandBuilder;
use Template\Handling\Registration\Handler\Command\ConfirmRegistration\ConfirmRegistrationCommandHandler;
use Template\Infrastructure\Session\Middleware\SessionMiddleware;
use Laminas\Diactoros\Response\JsonResponse;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Ramsey\Uuid\Uuid;
class ConfirmRegistrationHandler implements RequestHandlerInterface
{
public function __construct(
private readonly ConfirmRegistrationCommandHandler $handler,
private readonly ConfirmRegistrationCommandBuilder $builder,
private readonly UserFormatter $userFormatter
) {
}
public function handle(ServerRequestInterface $request): ResponseInterface
{
$data = json_decode(
$request->getBody()->getContents(),
true
);
$query = $this->builder->build(
Uuid::fromString($data['id']),
$data['password'],
$data['passwordConfirmation'],
);
$result = $this->handler->execute($query);
return new JsonResponse(
$this->userFormatter->format($result)
);
}
}

View File

@ -1,42 +0,0 @@
<?php
declare(strict_types=1);
namespace Template\API\External\Authentication\Handler;
use Template\Handling\UserSession\Handler\Command\LoginUser\LoginUserCommandBuilder;
use Template\Handling\UserSession\Handler\Command\LoginUser\LoginUserCommandHandler;
use Template\Infrastructure\Session\Middleware\SessionMiddleware;
use Laminas\Diactoros\Response\JsonResponse;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
class LoginUserHandler implements RequestHandlerInterface
{
public function __construct(
private readonly LoginUserCommandHandler $handler,
private readonly LoginUserCommandBuilder $builder
) {
}
public function handle(ServerRequestInterface $request): ResponseInterface
{
$session = $request->getAttribute(SessionMiddleware::SESSION_ATTRIBUTE);
$data = json_decode(
$request->getBody()->getContents(),
true
);
$query = $this->builder->build(
$session,
$data['identifier'],
$data['password'],
);
$result = $this->handler->execute($query);
return new JsonResponse([
'sessionId' => $result->getId()->toString()
]);
}
}

View File

@ -1,35 +0,0 @@
<?php
declare(strict_types=1);
namespace Template\API\External\Authentication\Handler;
use Template\Handling\UserSession\Handler\Command\LogoutUser\LogoutUserCommandBuilder;
use Template\Handling\UserSession\Handler\Command\LogoutUser\LogoutUserCommandHandler;
use Template\Infrastructure\Response\SuccessResponse;
use Template\Infrastructure\Session\Middleware\SessionMiddleware;
use Laminas\Diactoros\Response\JsonResponse;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
class LogoutUserHandler implements RequestHandlerInterface
{
public function __construct(
private readonly LogoutUserCommandHandler $handler,
private readonly LogoutUserCommandBuilder $builder
) {
}
public function handle(ServerRequestInterface $request): ResponseInterface
{
$session = $request->getAttribute(SessionMiddleware::SESSION_ATTRIBUTE);
$query = $this->builder->build(
$session
);
$this->handler->execute($query);
return new JsonResponse('OK');
}
}

View File

@ -1,41 +0,0 @@
<?php
declare(strict_types=1);
namespace Template\API\External\Authentication\Handler;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Template\Handling\Registration\Handler\Command\RegisterUser\RegisterUserCommandBuilder;
use Template\Handling\Registration\Handler\Command\RegisterUser\RegisterUserCommandHandler;
use Template\Infrastructure\Logging\Logger\Logger;
use Template\Infrastructure\Request\Middleware\AnalyzeHeaderMiddleware;
use Template\Infrastructure\Response\SuccessResponse;
class RegisterUserHandler implements RequestHandlerInterface
{
public function __construct(
private readonly RegisterUserCommandHandler $handler,
private readonly RegisterUserCommandBuilder $builder
) {
}
public function handle(ServerRequestInterface $request): ResponseInterface
{
$host = $request->getAttribute(AnalyzeHeaderMiddleware::HOST_ATTRIBUTE);
$data = json_decode(
$request->getBody()->getContents(),
true
);
$query = $this->builder->build(
$data['username'],
$data['mail'],
$host
);
$this->handler->execute($query);
return new SuccessResponse();
}
}

View File

@ -0,0 +1,41 @@
<?php
declare(strict_types=1);
namespace Template\API\External\Authentication\LoginUser;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Template\Infrastructure\Response\SuccessResponse;
use Template\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
use Template\Handling\Authentication\UseCase\LoginUser\LoginUserUseCaseHandler;
use Template\Handling\Authentication\UseCase\LoginUser\LoginUserUseCaseBuilder;
use Template\API\External\Authentication\LoginUser\LoginUserResponseFormatter;
use Template\Infrastructure\Session\Middleware\SessionMiddleware;
class LoginUserRequestHandler implements RequestHandlerInterface
{
public function __construct(
private readonly LoginUserUseCaseBuilder $builder,
private readonly LoginUserUseCaseHandler $handler,
private readonly LoginUserResponseFormatter $responseFormatter,
) {
}
public function handle(ServerRequestInterface $request): ResponseInterface
{
$session = $request->getAttribute(SessionMiddleware::SESSION_ATTRIBUTE);
$data = $request->getAttribute(AnalyzeBodyMiddleware::JSON_DATA);
$useCase = $this->builder->build(
$session,
$data['identifier'],
$data['password'],
);
$result = $this->handler->handle($useCase);
$response = $this->responseFormatter->format($result);
return new SuccessResponse($response);
}
}

View File

@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
namespace Template\API\External\Authentication\LoginUser;
use Ramsey\Uuid\Uuid;
use Template\Handling\Authentication\UseCase\LoginUser\LoginUserUseCaseResult;
class LoginUserResponseFormatter
{
public function format(LoginUserUseCaseResult $result): array
{
return [
'sessionId' => $result->getSession()->getId()
];
}
}

View File

@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
namespace Template\API\External\Authentication\LogoutUser;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Template\Infrastructure\Response\SuccessResponse;
use Template\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
use Template\Handling\Authentication\UseCase\LogoutUser\LogoutUserUseCaseHandler;
use Template\Handling\Authentication\UseCase\LogoutUser\LogoutUserUseCaseBuilder;
use Template\API\External\Authentication\LogoutUser\LogoutUserResponseFormatter;
use Template\Infrastructure\Session\Middleware\SessionMiddleware;
class LogoutUserRequestHandler implements RequestHandlerInterface
{
public function __construct(
private readonly LogoutUserUseCaseBuilder $builder,
private readonly LogoutUserUseCaseHandler $handler,
private readonly LogoutUserResponseFormatter $responseFormatter,
) {
}
public function handle(ServerRequestInterface $request): ResponseInterface
{
$session = $request->getAttribute(SessionMiddleware::SESSION_ATTRIBUTE);
$data = $request->getAttribute(AnalyzeBodyMiddleware::JSON_DATA);
$useCase = $this->builder->build(
$session,
);
$result = $this->handler->handle($useCase);
$response = $this->responseFormatter->format($result);
return new SuccessResponse($response);
}
}

View File

@ -0,0 +1,16 @@
<?php
declare(strict_types=1);
namespace Template\API\External\Authentication\LogoutUser;
use Template\Handling\Authentication\UseCase\LogoutUser\LogoutUserUseCaseResult;
class LogoutUserResponseFormatter
{
public function format(LogoutUserUseCaseResult $result): array
{
return [
];
}
}

View File

@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
namespace Template\API\External\Authentication\RegisterUser;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Template\Infrastructure\Response\SuccessResponse;
use Template\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
use Template\Handling\Registration\UseCase\RegisterUser\RegisterUserUseCaseHandler;
use Template\Handling\Registration\UseCase\RegisterUser\RegisterUserUseCaseBuilder;
use Template\API\External\Authentication\RegisterUser\RegisterUserResponseFormatter;
class RegisterUserRequestHandler implements RequestHandlerInterface
{
public function __construct(
private readonly RegisterUserUseCaseBuilder $builder,
private readonly RegisterUserUseCaseHandler $handler,
private readonly RegisterUserResponseFormatter $responseFormatter,
) {
}
public function handle(ServerRequestInterface $request): ResponseInterface
{
$data = $request->getAttribute(AnalyzeBodyMiddleware::JSON_DATA);
$useCase = $this->builder->build(
$data['username'],
$data['mail'],
);
$result = $this->handler->handle($useCase);
$response = $this->responseFormatter->format($result);
return new SuccessResponse($response);
}
}

View File

@ -0,0 +1,16 @@
<?php
declare(strict_types=1);
namespace Template\API\External\Authentication\RegisterUser;
use Template\Handling\Registration\UseCase\RegisterUser\RegisterUserUseCaseResult;
class RegisterUserResponseFormatter
{
public function format(RegisterUserUseCaseResult $result): array
{
return [
];
}
}

View File

@ -0,0 +1,40 @@
<?php
declare(strict_types=1);
namespace Template\API\External\Authentication\ResetPassword;
use Ramsey\Uuid\Uuid;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Template\Infrastructure\Response\SuccessResponse;
use Template\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
use Template\Handling\Authentication\UseCase\ResetPassword\ResetPasswordUseCaseHandler;
use Template\Handling\Authentication\UseCase\ResetPassword\ResetPasswordUseCaseBuilder;
use Template\API\External\Authentication\ResetPassword\ResetPasswordResponseFormatter;
class ResetPasswordRequestHandler implements RequestHandlerInterface
{
public function __construct(
private readonly ResetPasswordUseCaseBuilder $builder,
private readonly ResetPasswordUseCaseHandler $handler,
private readonly ResetPasswordResponseFormatter $responseFormatter,
) {
}
public function handle(ServerRequestInterface $request): ResponseInterface
{
$data = $request->getAttribute(AnalyzeBodyMiddleware::JSON_DATA);
$useCase = $this->builder->build(
Uuid::fromString($data['passwordToken']),
$data['newPassword'],
$data['passwordConfirmation'],
);
$result = $this->handler->handle($useCase);
$response = $this->responseFormatter->format($result);
return new SuccessResponse($response);
}
}

View File

@ -0,0 +1,16 @@
<?php
declare(strict_types=1);
namespace Template\API\External\Authentication\ResetPassword;
use Template\Handling\Authentication\UseCase\ResetPassword\ResetPasswordUseCaseResult;
class ResetPasswordResponseFormatter
{
public function format(ResetPasswordUseCaseResult $result): array
{
return [
];
}
}

View File

@ -1,16 +0,0 @@
<?php
use Template\API\External\Health\Handler\HealthHandler;
return [
[
'name' => 'health',
'path' => '/api/health',
'allowed_methods' => ['GET'],
'middleware' => [
HealthHandler::class
],
],
];
?>

View File

@ -1,12 +0,0 @@
<?php
use Template\API\External\Health\Handler\HealthHandler;
use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
return [
'factories' => [
HealthHandler::class => AutoWiringFactory::class
],
]
?>

View File

@ -1,16 +0,0 @@
<?php
declare(strict_types=1);
namespace Template\API\External\Health;
class ConfigProvider
{
public function __invoke(): array
{
return [
'dependencies' => require __DIR__ . './../config/service_manager.php',
'routes' => require __DIR__ . '/./../config/routes.php',
];
}
}

View File

@ -1,23 +0,0 @@
<?php
declare(strict_types=1);
namespace Template\API\External\Health\Handler;
use Laminas\Diactoros\Response\JsonResponse;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
class HealthHandler implements RequestHandlerInterface
{
public function __construct() {
}
public function handle(ServerRequestInterface $request): ResponseInterface
{
return new JsonResponse("I'm fine. :)");
}
}
?>

View File

@ -1,21 +1,28 @@
<?php
use Template\API\External\User\Handler\ChangePasswordHandler;
use Template\API\External\User\Handler\ChangeUsernameHandler;
use Template\API\External\User\Handler\CreateUserHandler;
use Template\API\External\User\Handler\UserStateHandler;
declare(strict_types=1);
namespace Template\API\External\User;
use Template\Infrastructure\Rbac\Middleware\EnsureAuthorizationMiddleware;
use Template\Infrastructure\Schema\Middleware\SchemaValidationMiddleware;
use Template\Infrastructure\Session\Middleware\LoggedInUserMiddleware;
use Template\API\External\User\Create\CreateRequestHandler;
use Template\API\External\User\ChangePassword\ChangePasswordRequestHandler;
use Template\API\External\User\ChangeUsername\ChangeUsernameRequestHandler;
use Template\API\External\User\ReadList\ReadListRequestHandler;
use Template\API\External\User\State\StateRequestHandler;
return [
[
'name' => 'user.create-user',
'path' => '/api/user/create-user',
'name' => 'user.create',
'path' => '/api/user/create',
'allowed_methods' => ['POST'],
'middleware' => [
SchemaValidationMiddleware::class,
LoggedInUserMiddleware::class,
EnsureAuthorizationMiddleware::class,
CreateUserHandler::class
CreateRequestHandler::class,
],
],
[
@ -23,8 +30,10 @@ return [
'path' => '/api/user/change-password',
'allowed_methods' => ['POST'],
'middleware' => [
SchemaValidationMiddleware::class,
LoggedInUserMiddleware::class,
ChangePasswordHandler::class
EnsureAuthorizationMiddleware::class,
ChangePasswordRequestHandler::class,
],
],
[
@ -32,8 +41,21 @@ return [
'path' => '/api/user/change-username',
'allowed_methods' => ['POST'],
'middleware' => [
SchemaValidationMiddleware::class,
LoggedInUserMiddleware::class,
ChangeUsernameHandler::class
EnsureAuthorizationMiddleware::class,
ChangeUsernameRequestHandler::class,
],
],
[
'name' => 'user.read-list',
'path' => '/api/user/read-list',
'allowed_methods' => ['POST'],
'middleware' => [
SchemaValidationMiddleware::class,
LoggedInUserMiddleware::class,
EnsureAuthorizationMiddleware::class,
ReadListRequestHandler::class,
],
],
[
@ -41,8 +63,9 @@ return [
'path' => '/api/user/state',
'allowed_methods' => ['GET'],
'middleware' => [
SchemaValidationMiddleware::class,
LoggedInUserMiddleware::class,
UserStateHandler::class
StateRequestHandler::class,
],
],
];

View File

@ -1,21 +1,34 @@
<?php
use Template\API\External\User\Formatter\UserFormatter;
use Template\API\External\User\Handler\ChangePasswordHandler;
use Template\API\External\User\Handler\ChangeUsernameHandler;
use Template\API\External\User\Handler\CreateUserHandler;
use Template\API\External\User\Handler\UserStateHandler;
use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
use Reinfi\DependencyInjection\Factory\InjectionFactory;
use Template\API\External\User\Create\CreateResponseFormatter;
use Template\API\External\User\Create\CreateRequestHandler;
use Template\API\External\User\ChangePassword\ChangePasswordResponseFormatter;
use Template\API\External\User\ChangePassword\ChangePasswordRequestHandler;
use Template\API\External\User\ChangeUsername\ChangeUsernameResponseFormatter;
use Template\API\External\User\ChangeUsername\ChangeUsernameRequestHandler;
use Template\API\External\User\ReadList\ReadListResponseFormatter;
use Template\API\External\User\ReadList\ReadListRequestHandler;
use Template\API\External\User\State\StateResponseFormatter;
use Template\API\External\User\State\StateRequestHandler;
return [
'factories' => [
// Formatter
UserFormatter::class => AutoWiringFactory::class,
// Handler
CreateUserHandler::class => AutoWiringFactory::class,
UserStateHandler::class => AutoWiringFactory::class,
ChangePasswordHandler::class => AutoWiringFactory::class,
ChangeUsernameHandler::class => AutoWiringFactory::class,
/// Create
CreateResponseFormatter::class => AutoWiringFactory::class,
CreateRequestHandler::class => AutoWiringFactory::class,
/// ChangePassword
ChangePasswordResponseFormatter::class => AutoWiringFactory::class,
ChangePasswordRequestHandler::class => AutoWiringFactory::class,
/// ChangeUsername
ChangeUsernameResponseFormatter::class => AutoWiringFactory::class,
ChangeUsernameRequestHandler::class => AutoWiringFactory::class,
/// ReadList
ReadListResponseFormatter::class => AutoWiringFactory::class,
ReadListRequestHandler::class => AutoWiringFactory::class,
/// State
StateResponseFormatter::class => AutoWiringFactory::class,
StateRequestHandler::class => AutoWiringFactory::class,
],
];

View File

@ -0,0 +1,43 @@
<?php
declare(strict_types=1);
namespace Template\API\External\User\ChangePassword;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Template\Data\Business\Entity\User;
use Template\Infrastructure\Response\SuccessResponse;
use Template\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
use Template\Handling\User\UseCase\ChangePassword\ChangePasswordUseCaseHandler;
use Template\Handling\User\UseCase\ChangePassword\ChangePasswordUseCaseBuilder;
use Template\API\External\User\ChangePassword\ChangePasswordResponseFormatter;
use Template\Infrastructure\Session\Middleware\LoggedInUserMiddleware;
class ChangePasswordRequestHandler implements RequestHandlerInterface
{
public function __construct(
private readonly ChangePasswordUseCaseBuilder $builder,
private readonly ChangePasswordUseCaseHandler $handler,
private readonly ChangePasswordResponseFormatter $responseFormatter,
) {
}
public function handle(ServerRequestInterface $request): ResponseInterface
{
/** @var User $user */
$user = $request->getAttribute(LoggedInUserMiddleware::USER_KEY);
$data = $request->getAttribute(AnalyzeBodyMiddleware::JSON_DATA);
$useCase = $this->builder->build(
$user,
$data['password'],
$data['newPassword'],
);
$result = $this->handler->handle($useCase);
$response = $this->responseFormatter->format($result);
return new SuccessResponse($response);
}
}

View File

@ -0,0 +1,16 @@
<?php
declare(strict_types=1);
namespace Template\API\External\User\ChangePassword;
use Template\Handling\User\UseCase\ChangePassword\ChangePasswordUseCaseResult;
class ChangePasswordResponseFormatter
{
public function format(ChangePasswordUseCaseResult $result): array
{
return [
];
}
}

View File

@ -0,0 +1,43 @@
<?php
declare(strict_types=1);
namespace Template\API\External\User\ChangeUsername;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Template\Data\Business\Entity\User;
use Template\Infrastructure\Response\SuccessResponse;
use Template\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
use Template\Handling\User\UseCase\ChangeUsername\ChangeUsernameUseCaseHandler;
use Template\Handling\User\UseCase\ChangeUsername\ChangeUsernameUseCaseBuilder;
use Template\API\External\User\ChangeUsername\ChangeUsernameResponseFormatter;
use Template\Infrastructure\Session\Middleware\LoggedInUserMiddleware;
class ChangeUsernameRequestHandler implements RequestHandlerInterface
{
public function __construct(
private readonly ChangeUsernameUseCaseBuilder $builder,
private readonly ChangeUsernameUseCaseHandler $handler,
private readonly ChangeUsernameResponseFormatter $responseFormatter,
) {
}
public function handle(ServerRequestInterface $request): ResponseInterface
{
/** @var User $user */
$user = $request->getAttribute(LoggedInUserMiddleware::USER_KEY);
$data = $request->getAttribute(AnalyzeBodyMiddleware::JSON_DATA);
$useCase = $this->builder->build(
$user,
$data['password'],
$data['newUsername'],
);
$result = $this->handler->handle($useCase);
$response = $this->responseFormatter->format($result);
return new SuccessResponse($response);
}
}

View File

@ -0,0 +1,16 @@
<?php
declare(strict_types=1);
namespace Template\API\External\User\ChangeUsername;
use Template\Handling\User\UseCase\ChangeUsername\ChangeUsernameUseCaseResult;
class ChangeUsernameResponseFormatter
{
public function format(ChangeUsernameUseCaseResult $result): array
{
return [
];
}
}

View File

@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
namespace Template\API\External\User\Create;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Template\Infrastructure\Response\SuccessResponse;
use Template\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
use Template\Handling\User\UseCase\Create\CreateUseCaseHandler;
use Template\Handling\User\UseCase\Create\CreateUseCaseBuilder;
use Template\API\External\User\Create\CreateResponseFormatter;
class CreateRequestHandler implements RequestHandlerInterface
{
public function __construct(
private readonly CreateUseCaseBuilder $builder,
private readonly CreateUseCaseHandler $handler,
private readonly CreateResponseFormatter $responseFormatter,
) {
}
public function handle(ServerRequestInterface $request): ResponseInterface
{
$data = $request->getAttribute(AnalyzeBodyMiddleware::JSON_DATA);
$useCase = $this->builder->build(
$data['username'],
$data['mail'],
$data['password'],
);
$result = $this->handler->handle($useCase);
$response = $this->responseFormatter->format($result);
return new SuccessResponse($response);
}
}

View File

@ -0,0 +1,30 @@
<?php
declare(strict_types=1);
namespace Template\API\External\User\Create;
use DateTimeInterface;
use Template\Handling\User\UseCase\Create\CreateUseCaseResult;
class CreateResponseFormatter
{
public function format(CreateUseCaseResult $result): array
{
$user = $result->getUser();
$permissions = [];
foreach ($user->getRole()->getPermissions()->toArray() as $permission) {
$permissions[] = $permission->getIdentifier();
}
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)
];
}
}

View File

@ -1,27 +0,0 @@
<?php
namespace Template\API\External\User\Formatter;
use DateTime;
use Template\Data\Business\Entity\User;
class UserFormatter {
public function format(User $user): array {
$userArray = [
'id' => $user->getId()->toString(),
'username' => $user->getUsername(),
'role' => $user->getRole()->getIdentifier(),
'created' => $user->getCreatedAt()->format(DateTime::ATOM),
'updated' => $user->getUpdatedAt()->format(DateTime::ATOM)
];
$userArray['permissions'] = [];
foreach ($user->getRole()->getPermissions()->toArray() as $permission) {
$userArray['permissions'][] = $permission->getIdentifier();
}
return $userArray;
}
}

View File

@ -1,43 +0,0 @@
<?php
declare(strict_types=1);
namespace Template\API\External\User\Handler;
use Template\Data\Business\Entity\User;
use Template\Handling\User\Handler\Command\ChangePassword\ChangePasswordCommandBuilder;
use Template\Handling\User\Handler\Command\ChangePassword\ChangePasswordCommandHandler;
use Template\Infrastructure\Response\SuccessResponse;
use Template\Infrastructure\Session\Middleware\LoggedInUserMiddleware;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
class ChangePasswordHandler implements RequestHandlerInterface
{
public function __construct(
private readonly ChangePasswordCommandHandler $handler,
private readonly ChangePasswordCommandBuilder $builder,
) {
}
public function handle(ServerRequestInterface $request): ResponseInterface
{
/** @var User $user */
$user = $request->getAttribute(LoggedInUserMiddleware::USER_KEY);
$data = json_decode(
$request->getBody()->getContents(),
true
);
$query = $this->builder->build(
$user,
$data['password'],
$data['newPassword'],
);
$this->handler->execute($query);
return new SuccessResponse();
}
}

View File

@ -1,43 +0,0 @@
<?php
declare(strict_types=1);
namespace Template\API\External\User\Handler;
use Template\Data\Business\Entity\User;
use Template\Handling\User\Handler\Command\ChangeUsername\ChangeUsernameCommandBuilder;
use Template\Handling\User\Handler\Command\ChangeUsername\ChangeUsernameCommandHandler;
use Template\Infrastructure\Response\SuccessResponse;
use Template\Infrastructure\Session\Middleware\LoggedInUserMiddleware;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
class ChangeUsernameHandler implements RequestHandlerInterface
{
public function __construct(
private readonly ChangeUsernameCommandHandler $handler,
private readonly ChangeUsernameCommandBuilder $builder,
) {
}
public function handle(ServerRequestInterface $request): ResponseInterface
{
/** @var User $user */
$user = $request->getAttribute(LoggedInUserMiddleware::USER_KEY);
$data = json_decode(
$request->getBody()->getContents(),
true
);
$query = $this->builder->build(
$user,
$data['password'],
$data['newUsername'],
);
$this->handler->execute($query);
return new SuccessResponse();
}
}

View File

@ -1,44 +0,0 @@
<?php
declare(strict_types=1);
namespace Template\API\External\User\Handler;
use Template\API\External\User\Formatter\UserFormatter;
use Template\Handling\User\Handler\Command\CreateUser\CreateUserCommandBuilder;
use Template\Handling\User\Handler\Command\CreateUser\CreateUserCommandHandler;
use Laminas\Diactoros\Response\JsonResponse;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
class CreateUserHandler implements RequestHandlerInterface
{
public function __construct(
private readonly CreateUserCommandHandler $handler,
private readonly CreateUserCommandBuilder $builder,
private readonly UserFormatter $userFormatter,
) {
}
public function handle(ServerRequestInterface $request): ResponseInterface
{
$data = json_decode(
$request->getBody()->getContents(),
true
);
$query = $this->builder->build(
$data['username'],
$data['mail'],
$data['password'],
);
$result = $this->handler->execute($query);
return new JsonResponse(
$this->userFormatter->format($result)
);
}
}
?>

View File

@ -1,34 +0,0 @@
<?php
declare(strict_types=1);
namespace Template\API\External\User\Handler;
use Template\API\External\User\Formatter\UserFormatter;
use Template\Data\Business\Entity\User;
use Template\Handling\User\Handler\Command\CreateUser\CreateUserCommandBuilder;
use Template\Handling\User\Handler\Command\CreateUser\ChangePasswordCommandHandler;
use Template\Infrastructure\Session\Middleware\LoggedInUserMiddleware;
use Laminas\Diactoros\Response\JsonResponse;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
class UserStateHandler implements RequestHandlerInterface
{
public function __construct(
private readonly UserFormatter $userFormatter,
) {
}
public function handle(ServerRequestInterface $request): ResponseInterface
{
/** @var User $user */
$user = $request->getAttribute(LoggedInUserMiddleware::USER_KEY);
$response = $this->userFormatter->format($user);
$response['sessionId'] = $user->getSession()->getId()->toString();
return new JsonResponse($response);
}
}

View File

@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
namespace Template\API\External\User\ReadList;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Template\Infrastructure\Response\SuccessResponse;
use Template\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
use Template\Handling\User\UseCase\ReadList\ReadListUseCaseHandler;
use Template\Handling\User\UseCase\ReadList\ReadListUseCaseBuilder;
use Template\API\External\User\ReadList\ReadListResponseFormatter;
class ReadListRequestHandler implements RequestHandlerInterface
{
public function __construct(
private readonly ReadListUseCaseBuilder $builder,
private readonly ReadListUseCaseHandler $handler,
private readonly ReadListResponseFormatter $responseFormatter,
) {
}
public function handle(ServerRequestInterface $request): ResponseInterface
{
$data = $request->getAttribute(AnalyzeBodyMiddleware::JSON_DATA);
$useCase = $this->builder->build(
$data['page'],
$data['perPage'],
$data['query'],
);
$result = $this->handler->handle($useCase);
$response = $this->responseFormatter->format($result);
return new SuccessResponse($response);
}
}

View File

@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
namespace Template\API\External\User\ReadList;
use Template\Handling\User\UseCase\ReadList\ReadListUseCaseResult;
class ReadListResponseFormatter
{
public function format(ReadListUseCaseResult $result): array
{
return [
'total' => ,
'items' => ,
];
}
}

View File

@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
namespace Template\API\External\User\State;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Template\Data\Business\Entity\User;
use Template\Infrastructure\Response\SuccessResponse;
use Template\Infrastructure\Session\Middleware\LoggedInUserMiddleware;
class StateRequestHandler implements RequestHandlerInterface
{
public function __construct(
private readonly StateResponseFormatter $responseFormatter,
) {
}
public function handle(ServerRequestInterface $request): ResponseInterface
{
/** @var User $user */
$user = $request->getAttribute(LoggedInUserMiddleware::USER_KEY);
$response = $this->responseFormatter->format($user);
return new SuccessResponse($response);
}
}

View File

@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
namespace Template\API\External\User\State;
use DateTimeInterface;
use Template\Data\Business\Entity\User;
class StateResponseFormatter
{
public function format(User $user): array
{
$permissions = [];
foreach ($user->getRole()->getPermissions()->toArray() as $permission) {
$permissions[] = $permission->getIdentifier();
}
return [
'id' => $user->getId(),
'sessionId' => $user->getSession()->getId(),
'username' => $user->getUsername(),
'roleIdentifier' => $user->getRole()->getIdentifier(),
'permissions' => $permissions,
'createdAt' => $user->getCreatedAt()->format(DateTimeInterface::RFC3339),
'updatedAt' => $user->getUpdatedAt()->format(DateTimeInterface::RFC3339),
];
}
}

View File

@ -20,7 +20,7 @@
"username": {
"$ref": "../../Authentication/Partials/username.json"
},
"role": {
"roleIdentifier": {
"$ref": "../../Authentication/Partials/role-identifier.json"
},
"permissions": {

View File

@ -0,0 +1,41 @@
<?php
declare(strict_types=1);
namespace Template\Handling\Auth;
use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
use Reinfi\DependencyInjection\Factory\InjectionFactory;
use Template\Handling\Authentication\Builder\UserSessionBuilder;
use Template\Handling\Authentication\Rule\UserPasswordMatchesRule;
use Template\Handling\Authentication\UseCase\LoginUser\LoginUserUseCaseHandler;
use Template\Handling\Authentication\UseCase\LoginUser\LoginUserUseCaseBuilder;
use Template\Handling\Authentication\UseCase\LogoutUser\LogoutUserUseCaseHandler;
use Template\Handling\Authentication\UseCase\LogoutUser\LogoutUserUseCaseBuilder;
use Template\Handling\Authentication\UseCase\ForgotPassword\ForgotPasswordUseCaseHandler;
use Template\Handling\Authentication\UseCase\ForgotPassword\ForgotPasswordUseCaseBuilder;
use Template\Handling\Authentication\UseCase\ResetPassword\ResetPasswordUseCaseHandler;
use Template\Handling\Authentication\UseCase\ResetPassword\ResetPasswordUseCaseBuilder;
return [
'factories' => [
/// Builder
UserSessionBuilder::class => AutoWiringFactory::class,
/// Rule
UserPasswordMatchesRule::class => AutoWiringFactory::class,
/// LoginUser
LoginUserUseCaseHandler::class => InjectionFactory::class,
LoginUserUseCaseBuilder::class => AutoWiringFactory::class,
/// LogoutUser
LogoutUserUseCaseHandler::class => AutoWiringFactory::class,
LogoutUserUseCaseBuilder::class => AutoWiringFactory::class,
/// ForgotPassword
ForgotPasswordUseCaseHandler::class => AutoWiringFactory::class,
ForgotPasswordUseCaseBuilder::class => AutoWiringFactory::class,
/// ResetPassword
ResetPasswordUseCaseHandler::class => AutoWiringFactory::class,
ResetPasswordUseCaseBuilder::class => AutoWiringFactory::class,
]
];

View File

@ -1,6 +1,6 @@
<?php
namespace Template\Handling\UserSession\Builder;
namespace Template\Handling\Authentication\Builder;
use Template\Data\Business\Entity\UserSession;

View File

@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
namespace Template\Handling\Authentication;
class ConfigProvider
{
public function __invoke(): array
{
return [
'dependencies' => require __DIR__ . '/./../config/service_manager.php',
];
}
}

View File

@ -1,6 +1,6 @@
<?php
namespace Template\Handling\UserSession\Rule;
namespace Template\Handling\Authentication\Rule;
use Template\Data\Business\Entity\User;
use Template\Infrastructure\Encryption\Client\EncryptionClient;

View File

@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
namespace Template\Handling\Authentication\UseCase\ForgotPassword;
class ForgotPasswordUseCase
{
public function __construct(
private readonly string $mail,
) {
}
public function getMail(): string
{
return $this->mail;
}
}

View File

@ -0,0 +1,16 @@
<?php
declare(strict_types=1);
namespace Template\Handling\Authentication\UseCase\ForgotPassword;
class ForgotPasswordUseCaseBuilder
{
public function build(
string $mail,
): ForgotPasswordUseCase {
return new ForgotPasswordUseCase(
$mail,
);
}
}

View File

@ -0,0 +1,17 @@
<?php
declare(strict_types=1);
namespace Template\Handling\Authentication\UseCase\ForgotPassword;
class ForgotPasswordUseCaseHandler
{
public function __construct(
) {
}
public function handle(ForgotPasswordUseCase $useCase): ForgotPasswordUseCaseResult
{
return new ForgotPasswordUseCaseResult();
}
}

View File

@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Template\Handling\Authentication\UseCase\ForgotPassword;
class ForgotPasswordUseCaseResult
{
public function __construct(
) {
}
}

View File

@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
namespace Template\Handling\Authentication\UseCase\LoginUser;
use Template\Data\Business\Entity\UserSession;
class LoginUserUseCase
{
public function __construct(
private readonly UserSession $session,
private readonly string $identifier,
private readonly string $password,
) {
}
public function getSession(): UserSession
{
return $this->session;
}
public function getIdentifier(): string
{
return $this->identifier;
}
public function getPassword(): string
{
return $this->password;
}
}

View File

@ -0,0 +1,22 @@
<?php
declare(strict_types=1);
namespace Template\Handling\Authentication\UseCase\LoginUser;
use Template\Data\Business\Entity\UserSession;
class LoginUserUseCaseBuilder
{
public function build(
UserSession $session,
string $identifier,
string $password,
): LoginUserUseCase {
return new LoginUserUseCase(
$session,
$identifier,
$password,
);
}
}

View File

@ -1,19 +1,20 @@
<?php
namespace Template\Handling\UserSession\Handler\Command\LoginUser;
declare(strict_types=1);
namespace Template\Handling\Authentication\UseCase\LoginUser;
use DateTime;
use Template\Data\Business\Entity\UserSession;
use Template\Data\Business\Manager\EntityManager;
use Template\Data\Business\Repository\UserRepository;
use Template\Data\Business\Repository\UserSessionRepository;
use Template\Handling\User\Exception\UserNotFoundByIdentifierException;
use Template\Handling\User\Exception\UserWrongPasswordException;
use Template\Handling\UserSession\Rule\UserPasswordMatchesRule;
use Template\Data\Business\Manager\EntityManager;
use Reinfi\DependencyInjection\Annotation\Inject;
use Reinfi\DependencyInjection\Annotation\InjectDoctrineRepository;
use Template\Handling\Authentication\Rule\UserPasswordMatchesRule;
class LoginUserCommandHandler
class LoginUserUseCaseHandler
{
/**
* @Inject("Template\Data\Business\Manager\EntityManager")
@ -25,56 +26,45 @@ class LoginUserCommandHandler
* entityManager="Template\Data\Business\Manager\EntityManager",
* entity="Template\Data\Business\Entity\UserSession"
* )
* @Inject("Template\Handling\UserSession\Rule\UserPasswordMatchesRule")
* @Inject("Template\Handling\Authentication\Rule\UserPasswordMatchesRule")
*/
public function __construct(
public function __construct(
private readonly EntityManager $entityManager,
private readonly UserRepository $userRepository,
private readonly UserSessionRepository $userSessionRepository,
private readonly UserPasswordMatchesRule $passwordMatchesRule
) {
}
) {
}
/**
* @throws UserWrongPasswordException
* @throws UserNotFoundByIdentifierException
*/
public function execute(LoginUserCommand $command): UserSession
{
$user = $this->userRepository->findByIdentifier(
$command->getIdentifier()
);
public function handle(LoginUserUseCase $useCase): LoginUserUseCaseResult
{
$user = $this->userRepository->findByIdentifier($useCase->getIdentifier());
if ($user === null) {
throw new UserNotFoundByIdentifierException($command->getIdentifier());
throw new UserNotFoundByIdentifierException($useCase->getIdentifier());
}
if (
!$this->passwordMatchesRule->appliesTo(
$command->getPassword(),
$user
)
) {
if (!$this->passwordMatchesRule->appliesTo($useCase->getPassword(), $user)) {
throw new UserWrongPasswordException();
}
$oldUserSessions = $this->userSessionRepository->findBy([
'userId' => $user->getId()
]);
$oldUserSessions = $this->userSessionRepository->findBy(['userId' => $user->getId()]);
foreach ($oldUserSessions as $oldUserSession) {
$this->entityManager->remove($oldUserSession);
}
$session = $command->getSession();
$session = $useCase->getSession();
$session->setUser($user);
$user->setLastLoginAt(new DateTime('now'));
$this->entityManager->persist($session);
$this->entityManager->flush();
return $session;
}
return new LoginUserUseCaseResult($session);
}
}
?>

View File

@ -0,0 +1,20 @@
<?php
declare(strict_types=1);
namespace Template\Handling\Authentication\UseCase\LoginUser;
use Template\Data\Business\Entity\UserSession;
class LoginUserUseCaseResult
{
public function __construct(
private UserSession $userSession,
) {
}
public function getSession(): UserSession
{
return $this->userSession;
}
}

View File

@ -0,0 +1,20 @@
<?php
declare(strict_types=1);
namespace Template\Handling\Authentication\UseCase\LogoutUser;
use Template\Data\Business\Entity\UserSession;
class LogoutUserUseCase
{
public function __construct(
private readonly UserSession $userSession,
) {
}
public function getSession(): UserSession
{
return $this->userSession;
}
}

View File

@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
namespace Template\Handling\Authentication\UseCase\LogoutUser;
use Template\Data\Business\Entity\UserSession;
class LogoutUserUseCaseBuilder
{
public function build(
UserSession $userSession,
): LogoutUserUseCase {
return new LogoutUserUseCase(
$userSession,
);
}
}

View File

@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
namespace Template\Handling\Authentication\UseCase\LogoutUser;
use Template\Data\Business\Manager\EntityManager;
class LogoutUserUseCaseHandler
{
public function __construct(
private readonly EntityManager $entityManager,
) {
}
public function handle(LogoutUserUseCase $useCase): LogoutUserUseCaseResult
{
$session = $useCase->getSession();
$this->entityManager->remove($session);
$this->entityManager->flush();
return new LogoutUserUseCaseResult($session);
}
}

View File

@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Template\Handling\Authentication\UseCase\LogoutUser;
class LogoutUserUseCaseResult
{
public function __construct(
) {
}
}

View File

@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
namespace Template\Handling\Authentication\UseCase\ResetPassword;
use Ramsey\Uuid\UuidInterface;
class ResetPasswordUseCase
{
public function __construct(
private readonly UuidInterface $passwordToken,
private readonly string $newPassword,
private readonly string $passwordConfirmation,
) {
}
public function getPasswordToken(): UuidInterface
{
return $this->passwordToken;
}
public function getNewPassword(): string
{
return $this->newPassword;
}
public function getPasswordConfirmation(): string
{
return $this->passwordConfirmation;
}
}

View File

@ -0,0 +1,22 @@
<?php
declare(strict_types=1);
namespace Template\Handling\Authentication\UseCase\ResetPassword;
use Ramsey\Uuid\UuidInterface;
class ResetPasswordUseCaseBuilder
{
public function build(
UuidInterface $passwordToken,
string $newPassword,
string $passwordConfirmation,
): ResetPasswordUseCase {
return new ResetPasswordUseCase(
$passwordToken,
$newPassword,
$passwordConfirmation,
);
}
}

View File

@ -0,0 +1,17 @@
<?php
declare(strict_types=1);
namespace Template\Handling\Authentication\UseCase\ResetPassword;
class ResetPasswordUseCaseHandler
{
public function __construct(
) {
}
public function handle(ResetPasswordUseCase $useCase): ResetPasswordUseCaseResult
{
return new ResetPasswordUseCaseResult();
}
}

View File

@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Template\Handling\Authentication\UseCase\ResetPassword;
class ResetPasswordUseCaseResult
{
public function __construct(
) {
}
}

View File

@ -1,10 +1,10 @@
<?php
use Template\Handling\Registration\UseCase\ConfirmRegistration\ConfirmRegistrationUseCaseBuilder;
use Template\Handling\Registration\UseCase\ConfirmRegistration\ConfirmRegistrationUseCaseHandler;
use Template\Handling\Registration\UseCase\RegisterUser\RegisterUserUseCaseBuilder;
use Template\Handling\Registration\UseCase\RegisterUser\RegisterUserUseCaseHandler;
use Template\Handling\Registration\Builder\RegistrationBuilder;
use Template\Handling\Registration\Handler\Command\ConfirmRegistration\ConfirmRegistrationCommandBuilder;
use Template\Handling\Registration\Handler\Command\ConfirmRegistration\ConfirmRegistrationCommandHandler;
use Template\Handling\Registration\Handler\Command\RegisterUser\RegisterUserCommandBuilder;
use Template\Handling\Registration\Handler\Command\RegisterUser\RegisterUserCommandHandler;
use Template\Handling\Registration\Pipeline\ConfirmRegistration\ConfirmRegistrationPipeline;
use Template\Handling\Registration\Pipeline\ConfirmRegistration\Step\CreateUserStep;
use Template\Handling\Registration\Pipeline\ConfirmRegistration\Step\LoadRegistrationStep;
@ -42,12 +42,11 @@ return [
SaveRegistrationAndUserStep::class => AutoWiringFactory::class,
/// CQRS
// Register User
RegisterUserCommandHandler::class => AutoWiringFactory::class,
RegisterUserCommandBuilder::class => AutoWiringFactory::class,
// Confirm Registration
ConfirmRegistrationCommandHandler::class => AutoWiringFactory::class,
ConfirmRegistrationCommandBuilder::class => AutoWiringFactory::class,
/// ConfirmRegistration
ConfirmRegistrationUseCaseHandler::class => AutoWiringFactory::class,
ConfirmRegistrationUseCaseBuilder::class => AutoWiringFactory::class,
/// RegisterUser
RegisterUserUseCaseHandler::class => AutoWiringFactory::class,
RegisterUserUseCaseBuilder::class => AutoWiringFactory::class,
],
];

View File

@ -4,10 +4,10 @@ namespace Template\Handling\Registration\Exception;
use Template\Infrastructure\Exception\ErrorCode;
use Template\Infrastructure\Exception\ErrorDomain;
use Template\Infrastructure\Exception\Exception\Exception;
use Template\Infrastructure\Exception\Exception\TemplateException;
use Ramsey\Uuid\UuidInterface;
class RegistrationNotFoundByIdException extends Exception
class RegistrationNotFoundByIdException extends TemplateException
{
private const MESSAGE = 'A Registration with the id %s was not be found!';
public function __construct(

View File

@ -4,9 +4,9 @@ namespace Template\Handling\Registration\Exception;
use Template\Infrastructure\Exception\ErrorCode;
use Template\Infrastructure\Exception\ErrorDomain;
use Template\Infrastructure\Exception\Exception\Exception;
use Template\Infrastructure\Exception\Exception\TemplateException;
class RegistrationWithIdentifierAlreadyExistsException extends Exception
class RegistrationWithIdentifierAlreadyExistsException extends TemplateException
{
private const MESSAGE = 'A Registration with the identifier %s does already exist!';

View File

@ -1,28 +0,0 @@
<?php
namespace Template\Handling\Registration\Handler\Command\ConfirmRegistration;
use Ramsey\Uuid\UuidInterface;
class ConfirmRegistrationCommand
{
public function __construct(
private readonly UuidInterface $id,
private readonly string $password,
private readonly string $passwordConfirmation,
) {
}
public function getId(): UuidInterface {
return $this->id;
}
public function getPassword(): string {
return $this->password;
}
public function getPasswordConfirmation(): string {
return $this->passwordConfirmation;
}
}

View File

@ -1,21 +0,0 @@
<?php
namespace Template\Handling\Registration\Handler\Command\ConfirmRegistration;
use Ramsey\Uuid\UuidInterface;
class ConfirmRegistrationCommandBuilder
{
public function build(
UuidInterface $id,
string $password,
string $passwordConfirmation,
): ConfirmRegistrationCommand
{
return new ConfirmRegistrationCommand(
$id,
$password,
$passwordConfirmation
);
}
}

View File

@ -1,23 +0,0 @@
<?php
namespace Template\Handling\Registration\Handler\Command\ConfirmRegistration;
use Template\Data\Business\Entity\User;
use Template\Handling\Registration\Pipeline\ConfirmRegistration\ConfirmRegistrationPayload;
use Template\Handling\Registration\Pipeline\ConfirmRegistration\ConfirmRegistrationPipeline;
class ConfirmRegistrationCommandHandler
{
public function __construct(
private readonly ConfirmRegistrationPipeline $pipeline,
) {
}
public function execute(ConfirmRegistrationCommand $command): User
{
$payload = new ConfirmRegistrationPayload($command);
$this->pipeline->handle($payload);
return $payload->getUser();
}
}

View File

@ -1,25 +0,0 @@
<?php
namespace Template\Handling\Registration\Handler\Command\RegisterUser;
class RegisterUserCommand
{
public function __construct(
private readonly string $username,
private readonly string $mail,
private readonly string $host
) {
}
public function getUsername(): string {
return $this->username;
}
public function getMail(): string {
return $this->mail;
}
public function getHost(): string {
return $this->host;
}
}

View File

@ -1,19 +0,0 @@
<?php
namespace Template\Handling\Registration\Handler\Command\RegisterUser;
class RegisterUserCommandBuilder
{
public function build(
string $username,
string $mail,
string $host
): RegisterUserCommand
{
return new RegisterUserCommand(
$username,
$mail,
$host
);
}
}

View File

@ -1,23 +0,0 @@
<?php
namespace Template\Handling\Registration\Handler\Command\RegisterUser;
use Template\Data\Business\Entity\Registration;
use Template\Handling\Registration\Pipeline\RegisterUser\RegisterUserPayload;
use Template\Handling\Registration\Pipeline\RegisterUser\RegisterUserPipeline;
class RegisterUserCommandHandler
{
public function __construct(
private readonly RegisterUserPipeline $pipeline,
) {
}
public function execute(RegisterUserCommand $command): Registration
{
$payload = new RegisterUserPayload($command);
$this->pipeline->handle($payload);
return $payload->getRegistration();
}
}

View File

@ -8,6 +8,7 @@ use Template\Data\Business\Entity\Registration;
use Template\Data\Business\Entity\User;
use Template\Handling\Registration\Handler\Command\ConfirmRegistration\ConfirmRegistrationCommand;
use Template\Handling\Registration\Handler\Command\RegisterUser\RegisterUserCommand;
use Template\Handling\Registration\UseCase\ConfirmRegistration\ConfirmRegistrationUseCase;
class ConfirmRegistrationPayload
{
@ -15,11 +16,11 @@ class ConfirmRegistrationPayload
private readonly ?User $user;
public function __construct(
private readonly ConfirmRegistrationCommand $command
private readonly ConfirmRegistrationUseCase $command
) {
}
public function getCommand(): ConfirmRegistrationCommand
public function getUseCase(): ConfirmRegistrationUseCase
{
return $this->command;
}

View File

@ -33,14 +33,14 @@ class CreateUserStep implements TaskInterface
PipelineInterface $pipeline
): void
{
/** @var ConfirmRegistrationCommand $command */
$command = $payload->getCommand();
/** @var ConfirmRegistrationCommand $useCase */
$useCase = $payload->getUseCase();
$registration = $payload->getRegistration();
if (
!$this->passwordMatchRule->appliesTo(
$command->getPassword(),
$command->getPasswordConfirmation()
$useCase->getPassword(),
$useCase->getPasswordConfirmation()
)
) {
throw new UserPasswordMismatchException();
@ -49,7 +49,7 @@ class CreateUserStep implements TaskInterface
$createUserCommand = $this->createUserCommandBuilder->build(
username: $registration->getUsername(),
mail: $registration->getMail(),
password: $command->getPassword(),
password: $useCase->getPassword(),
);
$user = $this->createUserCommandHandler->execute($createUserCommand);

View File

@ -24,20 +24,23 @@ class LoadRegistrationStep implements TaskInterface
) {
}
/**
* @throws RegistrationNotFoundByIdException
*/
public function __invoke(
$payload,
PipelineInterface $pipeline
)
{
$command = $payload->getCommand();
$useCase = $payload->getUseCase();
/** @var Registration $registration */
$registration = $this->registrationRepository->findOneBy([
'id' => $command->getId()
'id' => $useCase->getId()
]) ?? null;
if ($registration === null) {
throw new RegistrationNotFoundByIdException($command->getId());
throw new RegistrationNotFoundByIdException($useCase->getId());
}
$payload->setRegistration($registration);

View File

@ -6,19 +6,20 @@ namespace Template\Handling\Registration\Pipeline\RegisterUser;
use Template\Data\Business\Entity\Registration;
use Template\Handling\Registration\Handler\Command\RegisterUser\RegisterUserCommand;
use Template\Handling\Registration\UseCase\RegisterUser\RegisterUserUseCase;
class RegisterUserPayload
{
private readonly ?Registration $registration;
public function __construct(
private readonly RegisterUserCommand $command
private readonly RegisterUserUseCase $useCase,
) {
}
public function getCommand(): RegisterUserCommand
public function getUseCase(): RegisterUserUseCase
{
return $this->command;
return $this->useCase;
}
public function getRegistration(): ?Registration

View File

@ -20,11 +20,11 @@ class BuildRegistrationStep implements TaskInterface
PipelineInterface $pipeline
)
{
$command = $payload->getCommand();
$useCase = $payload->getUseCase();
$registration = $this->builder->build(
username: $command->getUsername(),
mail: $command->getMail()
username: $useCase->getUsername(),
mail: $useCase->getMail()
);
$payload->setRegistration($registration);

View File

@ -28,13 +28,13 @@ class CheckIdentifierStep implements TaskInterface
PipelineInterface $pipeline
)
{
$command = $payload->getCommand();
$useCase = $payload->getUseCase();
$this->userWithIdentifierAlreadyExistsRule->appliesTo($command->getMail());
$this->userWithIdentifierAlreadyExistsRule->appliesTo($command->getUsername());
$this->userWithIdentifierAlreadyExistsRule->appliesTo($useCase->getMail());
$this->userWithIdentifierAlreadyExistsRule->appliesTo($useCase->getUsername());
$this->registrationWithIdentifierAlreadyExistsRule->appliesTo($command->getMail());
$this->registrationWithIdentifierAlreadyExistsRule->appliesTo($command->getUsername());
$this->registrationWithIdentifierAlreadyExistsRule->appliesTo($useCase->getMail());
$this->registrationWithIdentifierAlreadyExistsRule->appliesTo($useCase->getUsername());
$pipeline->next()($payload, $pipeline);
}

View File

@ -22,7 +22,7 @@ class SendMailStep implements TaskInterface
PipelineInterface $pipeline
)
{
$command = $payload->getCommand();
$useCase = $payload->getUseCase();
$registration = $payload->getRegistration();
$this->requestService->request(
@ -31,13 +31,13 @@ class SendMailStep implements TaskInterface
[
'template-identifier' => 'new-account',
'sender' => 'info@stack-up.de',
'recipient' => $command->getMail(),
'recipient' => $useCase->getMail(),
'data' => [
'username' => $command->getUsername(),
'username' => $useCase->getUsername(),
'confirmationLink' =>
sprintf(
self::CONFIRM_LINK,
$command->getHost(),
$useCase->getHost(),
$registration->getId()->toString()
)
]

View File

@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
namespace Template\Handling\Registration\UseCase\ConfirmRegistration;
use Ramsey\Uuid\UuidInterface;
class ConfirmRegistrationUseCase
{
public function __construct(
private readonly UuidInterface $id,
private readonly string $password,
private readonly string $passwordConfirmation,
) {
}
public function getId(): UuidInterface
{
return $this->id;
}
public function getPassword(): string
{
return $this->password;
}
public function getPasswordConfirmation(): string
{
return $this->passwordConfirmation;
}
}

View File

@ -0,0 +1,22 @@
<?php
declare(strict_types=1);
namespace Template\Handling\Registration\UseCase\ConfirmRegistration;
use Ramsey\Uuid\UuidInterface;
class ConfirmRegistrationUseCaseBuilder
{
public function build(
UuidInterface $id,
string $password,
string $passwordConfirmation,
): ConfirmRegistrationUseCase {
return new ConfirmRegistrationUseCase(
$id,
$password,
$passwordConfirmation,
);
}
}

View File

@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
namespace Template\Handling\Registration\UseCase\ConfirmRegistration;
use Template\Handling\Registration\Pipeline\ConfirmRegistration\ConfirmRegistrationPayload;
use Template\Handling\Registration\Pipeline\ConfirmRegistration\ConfirmRegistrationPipeline;
class ConfirmRegistrationUseCaseHandler
{
public function __construct(
private readonly ConfirmRegistrationPipeline $pipeline,
) {
}
public function handle(ConfirmRegistrationUseCase $useCase): ConfirmRegistrationUseCaseResult
{
$payload = new ConfirmRegistrationPayload($useCase);
$this->pipeline->handle($payload);
return new ConfirmRegistrationUseCaseResult($payload->getUser());
}
}

View File

@ -0,0 +1,20 @@
<?php
declare(strict_types=1);
namespace Template\Handling\Registration\UseCase\ConfirmRegistration;
use Template\Data\Business\Entity\User;
class ConfirmRegistrationUseCaseResult
{
public function __construct(
private User $user,
) {
}
public function getUser(): User
{
return $this->user;
}
}

View File

@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
namespace Template\Handling\Registration\UseCase\RegisterUser;
class RegisterUserUseCase
{
public function __construct(
private readonly string $username,
private readonly string $mail,
) {
}
public function getUsername(): string
{
return $this->username;
}
public function getMail(): string
{
return $this->mail;
}
}

View File

@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
namespace Template\Handling\Registration\UseCase\RegisterUser;
class RegisterUserUseCaseBuilder
{
public function build(
string $username,
string $mail,
): RegisterUserUseCase {
return new RegisterUserUseCase(
$username,
$mail,
);
}
}

View File

@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
namespace Template\Handling\Registration\UseCase\RegisterUser;
use Template\Handling\Registration\Pipeline\RegisterUser\RegisterUserPayload;
use Template\Handling\Registration\Pipeline\RegisterUser\RegisterUserPipeline;
class RegisterUserUseCaseHandler
{
public function __construct(
private readonly RegisterUserPipeline $pipeline,
) {
}
public function handle(RegisterUserUseCase $useCase): RegisterUserUseCaseResult
{
$payload = new RegisterUserPayload($useCase);
$this->pipeline->handle($payload);
return new RegisterUserUseCaseResult($payload->getRegistration());
}
}

View File

@ -0,0 +1,20 @@
<?php
declare(strict_types=1);
namespace Template\Handling\Registration\UseCase\RegisterUser;
use Template\Data\Business\Entity\Registration;
class RegisterUserUseCaseResult
{
public function __construct(
private Registration $registration,
) {
}
public function getRegistration(): Registration
{
return $this->registration;
}
}

View File

@ -1,12 +1,14 @@
<?php
use Template\Handling\User\Builder\UserBuilder;
use Template\Handling\User\Handler\Command\ChangePassword\ChangePasswordCommandBuilder;
use Template\Handling\User\Handler\Command\ChangePassword\ChangePasswordCommandHandler;
use Template\Handling\User\Handler\Command\ChangeUsername\ChangeUsernameCommandBuilder;
use Template\Handling\User\Handler\Command\ChangeUsername\ChangeUsernameCommandHandler;
use Template\Handling\User\Handler\Command\CreateUser\CreateUserCommandBuilder;
use Template\Handling\User\Handler\Command\CreateUser\CreateUserCommandHandler;
use Template\Handling\User\UseCase\Create\CreateUseCaseHandler;
use Template\Handling\User\UseCase\Create\CreateUseCaseBuilder;
use Template\Handling\User\UseCase\ChangePassword\ChangePasswordUseCaseHandler;
use Template\Handling\User\UseCase\ChangePassword\ChangePasswordUseCaseBuilder;
use Template\Handling\User\UseCase\ChangeUsername\ChangeUsernameUseCaseHandler;
use Template\Handling\User\UseCase\ChangeUsername\ChangeUsernameUseCaseBuilder;
use Template\Handling\User\UseCase\ReadList\ReadListUseCaseHandler;
use Template\Handling\User\UseCase\ReadList\ReadListUseCaseBuilder;
use Template\Handling\User\Rule\UserPasswordMatchRule;
use Template\Handling\User\Rule\UserWithIdentifierAlreadyExistsRule;
use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
@ -24,16 +26,17 @@ return [
UserPasswordMatchRule::class => AutoWiringFactory::class,
/// CQRS
// Create User
CreateUserCommandHandler::class => AutoWiringFactory::class,
CreateUserCommandBuilder::class => AutoWiringFactory::class,
// Change Password
ChangePasswordCommandHandler::class => AutoWiringFactory::class,
ChangePasswordCommandBuilder::class => AutoWiringFactory::class,
// Change Username
ChangeUsernameCommandHandler::class => AutoWiringFactory::class,
ChangeUsernameCommandBuilder::class => AutoWiringFactory::class,
/// Create
CreateUseCaseHandler::class => AutoWiringFactory::class,
CreateUseCaseBuilder::class => AutoWiringFactory::class,
/// ChangePassword
ChangePasswordUseCaseHandler::class => AutoWiringFactory::class,
ChangePasswordUseCaseBuilder::class => AutoWiringFactory::class,
/// ChangeUsername
ChangeUsernameUseCaseHandler::class => AutoWiringFactory::class,
ChangeUsernameUseCaseBuilder::class => AutoWiringFactory::class,
/// ReadList
ReadListUseCaseHandler::class => AutoWiringFactory::class,
ReadListUseCaseBuilder::class => AutoWiringFactory::class,
],
];

View File

@ -5,10 +5,10 @@ namespace Template\Handling\User\Builder;
use Template\Data\Business\Entity\Role;
use Template\Data\Business\Entity\User;
use Template\Data\Business\Repository\RoleRepository;
use Template\Handling\Role\Exception\RoleNotFoundByIdentifierException;
use Template\Infrastructure\Encryption\Client\EncryptionClient;
use Reinfi\DependencyInjection\Annotation\Inject;
use Reinfi\DependencyInjection\Annotation\InjectDoctrineRepository;
use Template\Infrastructure\Rbac\Exception\RoleNotFoundByIdentifierException;
class UserBuilder
{

View File

@ -4,9 +4,9 @@ namespace Template\Handling\User\Exception;
use Template\Infrastructure\Exception\ErrorCode;
use Template\Infrastructure\Exception\ErrorDomain;
use Template\Infrastructure\Exception\Exception\Exception;
use Template\Infrastructure\Exception\Exception\TemplateException;
class UserNotFoundByIdentifierException extends Exception {
class UserNotFoundByIdentifierException extends TemplateException {
private const MESSAGE = 'The user with the Identifier %s was not found!';
@ -22,5 +22,3 @@ class UserNotFoundByIdentifierException extends Exception {
);
}
}
?>

View File

@ -4,9 +4,9 @@ namespace Template\Handling\User\Exception;
use Template\Infrastructure\Exception\ErrorCode;
use Template\Infrastructure\Exception\ErrorDomain;
use Template\Infrastructure\Exception\Exception\Exception;
use Template\Infrastructure\Exception\Exception\TemplateException;
class UserPasswordMismatchException extends Exception {
class UserPasswordMismatchException extends TemplateException {
private const MESSAGE = 'The two passwords do not match!';

Some files were not shown because too many files have changed in this diff Show More