Compare commits
No commits in common. "a5dffa065a16fd5c93f23402f63ef55745af39a8" and "1df825db2a22717996c14d1a8ed3ab708dba1b44" have entirely different histories.
a5dffa065a
...
1df825db2a
@ -8,7 +8,11 @@ DB_NAME=template
|
|||||||
DB_NAME_LOG=log
|
DB_NAME_LOG=log
|
||||||
|
|
||||||
# API Keys
|
# API Keys
|
||||||
TEMPLATE_API_KEY=
|
AUTH_API_KEY=
|
||||||
|
NOTIFICATION_API_KEY=
|
||||||
|
FILE_API_KEY=
|
||||||
|
HOMEPAGE_API_KEY=
|
||||||
|
BEE_API_KEY=
|
||||||
|
|
||||||
# Template Setup
|
# Template Setup
|
||||||
INIT_USER_NAME=admin
|
INIT_USER_NAME=admin
|
||||||
|
|||||||
2
.gitignore
vendored
2
.gitignore
vendored
@ -11,8 +11,6 @@
|
|||||||
/var/
|
/var/
|
||||||
/vendor/
|
/vendor/
|
||||||
|
|
||||||
docker/docker-compose.yml
|
|
||||||
|
|
||||||
*.env
|
*.env
|
||||||
composer.lock
|
composer.lock
|
||||||
composer.development.json
|
composer.development.json
|
||||||
|
|||||||
@ -201,8 +201,8 @@ use Psr\\Http\\Server\\RequestHandlerInterface;
|
|||||||
class {$apiHandlerName} implements RequestHandlerInterface
|
class {$apiHandlerName} implements RequestHandlerInterface
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly {$cqrsHandlerName} \$handler,
|
private readonly {$cqrsHandlerName} \${$cqrsHandlerVariableName},
|
||||||
private readonly {$cqrsBuilderName} \$builder,
|
private readonly {$cqrsBuilderName} \${$cqrsBuilderVariableName},
|
||||||
private readonly {$apiResponseFormatterName} \$responseFormatter,
|
private readonly {$apiResponseFormatterName} \$responseFormatter,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
@ -211,10 +211,10 @@ class {$apiHandlerName} implements RequestHandlerInterface
|
|||||||
{
|
{
|
||||||
\$data = \$request->getAttribute(AnalyzeBodyMiddleware::JSON_DATA);
|
\$data = \$request->getAttribute(AnalyzeBodyMiddleware::JSON_DATA);
|
||||||
|
|
||||||
\${$cqrsVariableName} = \$this->builder->build(
|
\${$cqrsVariableName} = \$this->{$cqrsBuilderVariableName}->build(
|
||||||
\$data
|
\$data
|
||||||
);
|
);
|
||||||
\$result = \$this->handler->execute(\${$cqrsVariableName});
|
\$result = \$this->{$cqrsHandlerVariableName}->execute(\${$cqrsVariableName});
|
||||||
|
|
||||||
return new SuccessResponse(\$this->responseFormatter->format(\$result));
|
return new SuccessResponse(\$this->responseFormatter->format(\$result));
|
||||||
}
|
}
|
||||||
@ -251,10 +251,10 @@ namespace {$cqrsHandlerNamespace};
|
|||||||
class {$cqrsName}
|
class {$cqrsName}
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
#TODO
|
#TODO
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#TODO
|
#TODO
|
||||||
}
|
}
|
||||||
";
|
";
|
||||||
@ -270,12 +270,14 @@ class {$cqrsHandlerName}
|
|||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
#TODO
|
#TODO
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function execute({$cqrsName} \${$cqrsVariableName}): {$cqrsResultName}
|
public function execute({$cqrsName} \${$cqrsVariableName}): {$cqrsResultName}
|
||||||
{
|
{
|
||||||
return new {$cqrsResultName}();
|
return new {$cqrsResultName}(
|
||||||
|
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
";
|
";
|
||||||
|
|||||||
@ -1,30 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
|
||||||
PROJECT_DIR=$(realpath $SCRIPT_DIR/../../)
|
|
||||||
ENV_DIR=$(realpath $PROJECT_DIR/../../../)
|
|
||||||
|
|
||||||
source $ENV_DIR/bin/denv_msg
|
|
||||||
source $ENV_DIR/bin/drun
|
|
||||||
|
|
||||||
# Install PHP packages
|
|
||||||
denv_echo_msg "[backend]: Composer install"
|
|
||||||
drun backend composer install
|
|
||||||
denv_success_msg "[backend]: Composer install done"
|
|
||||||
|
|
||||||
# Dump autoload
|
|
||||||
denv_echo_msg "[backend]: Dump autoload"
|
|
||||||
drun backend composer da
|
|
||||||
denv_success_msg "[backend]: Dump autoload done"
|
|
||||||
|
|
||||||
# Migrate databases to current version
|
|
||||||
denv_echo_msg "[backend]: Migrate db"
|
|
||||||
drun backend composer dmm
|
|
||||||
drun backend composer dmlm
|
|
||||||
denv_success_msg "[backend]: Migrate db done"
|
|
||||||
|
|
||||||
# Insert setup for project after this line
|
|
||||||
denv_echo_msg "[backend]: Initialize data"
|
|
||||||
drun backend composer console rbac:update
|
|
||||||
drun backend composer console init:data
|
|
||||||
denv_success_msg "[backend]: Initialize data done"
|
|
||||||
@ -3,16 +3,54 @@
|
|||||||
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||||
PROJECT_DIR=$(realpath $SCRIPT_DIR/../../)
|
PROJECT_DIR=$(realpath $SCRIPT_DIR/../../)
|
||||||
ENV_DIR=$(realpath $PROJECT_DIR/../../../)
|
ENV_DIR=$(realpath $PROJECT_DIR/../../../)
|
||||||
source $ENV_DIR/bin/denv_msg
|
|
||||||
|
EXIT=0
|
||||||
|
|
||||||
# Check .env file
|
# Check .env file
|
||||||
if [ ! -f "$PROJECT_DIR/.env" ] ; then
|
if [ ! -f "$PROJECT_DIR/.env" ]
|
||||||
|
then
|
||||||
cp "$PROJECT_DIR/.env.example" "$PROJECT_DIR/.env"
|
cp "$PROJECT_DIR/.env.example" "$PROJECT_DIR/.env"
|
||||||
denv_info_msg "[backend] Created .env"
|
EXIT=1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check docker-compose.yml file
|
# Check docker-compose.yml file
|
||||||
if [ ! -f "$PROJECT_DIR/docker/docker-compose.yml" ] ; then
|
if [ ! -f "$PROJECT_DIR/docker/docker-compose.yml" ]
|
||||||
cp "$PROJECT_DIR/docker/docker-compose.yml.dist" "$PROJECT_DIR/docker/docker-compose.yml"
|
then
|
||||||
denv_info_msg "[backend] Created docker-compose.yml"
|
cp "$PROJECT_DIR/docker/docker-compose.yml.dist" "$PROJECT_DIR/docker/docker-compose.yml"
|
||||||
|
EXIT=1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Check docker-compose-mac.yml file
|
||||||
|
if [ ! -f "$PROJECT_DIR/docker/docker-compose-mac.yml" ]
|
||||||
|
then
|
||||||
|
cp "$PROJECT_DIR/docker/docker-compose-mac.yml.dist" "$PROJECT_DIR/docker/docker-compose-mac.yml"
|
||||||
|
EXIT=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $EXIT -eq 1 ]
|
||||||
|
then
|
||||||
|
echo "docker-compose or env files created, please change variables and call init again"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Source key-scripts
|
||||||
|
source $ENV_DIR/bin/drun
|
||||||
|
source $ENV_DIR/bin/dexec
|
||||||
|
|
||||||
|
# Build and start docker containers
|
||||||
|
dexec template-backend build
|
||||||
|
dexec template-backend up -d
|
||||||
|
|
||||||
|
# Install PHP packages
|
||||||
|
drun template-backend composer install
|
||||||
|
|
||||||
|
# Dump autoload
|
||||||
|
drun template-backend composer da
|
||||||
|
|
||||||
|
# Migrate databases to current version
|
||||||
|
drun template-backend composer dmm
|
||||||
|
drun template-backend composer dmlm
|
||||||
|
|
||||||
|
# Insert setup for project after this line
|
||||||
|
drun template-backend composer console rbac:update
|
||||||
|
drun template-backend composer console init:data
|
||||||
@ -1,39 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
|
||||||
PROJECT_DIR=$(realpath $SCRIPT_DIR/../../)
|
|
||||||
ENV_DIR=$(realpath $PROJECT_DIR/../../../)
|
|
||||||
SYSTEM_ENV_FILE="$PROJECT_DIR/.env"
|
|
||||||
CWD=$(pwd)
|
|
||||||
|
|
||||||
source $ENV_DIR/bin/denv_msg
|
|
||||||
source $ENV_DIR/bin/drun
|
|
||||||
|
|
||||||
# Pull branch in project directory
|
|
||||||
denv_echo_msg "[backend]: Git pull"
|
|
||||||
cd "$PROJECT_DIR"
|
|
||||||
git pull
|
|
||||||
denv_success_msg "[backend]: Git pull done"
|
|
||||||
|
|
||||||
# Install PHP packages
|
|
||||||
denv_echo_msg "[backend]: Composer install"
|
|
||||||
drun backend composer install
|
|
||||||
denv_success_msg "[backend]: Composer install done"
|
|
||||||
|
|
||||||
# Dump autoload
|
|
||||||
denv_echo_msg "[backend]: Dump autoload"
|
|
||||||
drun backend composer da
|
|
||||||
denv_success_msg "[backend]: Dump autoload done"
|
|
||||||
|
|
||||||
# Migrate databases to current version
|
|
||||||
denv_echo_msg "[backend]: Migrate db"
|
|
||||||
drun backend composer dmm
|
|
||||||
drun backend composer dmlm
|
|
||||||
denv_success_msg "[backend]: Migrate db done"
|
|
||||||
|
|
||||||
# Insert setup for project after this line
|
|
||||||
denv_echo_msg "[backend]: Update roles and permissions"
|
|
||||||
drun backend composer console rbac:update
|
|
||||||
denv_success_msg "[backend]: Update roles and permissions done"
|
|
||||||
|
|
||||||
# Switch back to current working directory
|
|
||||||
cd "$CWD"
|
|
||||||
@ -3,7 +3,26 @@
|
|||||||
return [
|
return [
|
||||||
'api' => [
|
'api' => [
|
||||||
'keys' => [
|
'keys' => [
|
||||||
'template' => $_ENV['TEMPLATE_API_KEY'],
|
'template' => $_ENV['HOMEPAGE_API_KEY'],
|
||||||
|
'notification' => $_ENV['NOTIFICATION_API_KEY'],
|
||||||
|
],
|
||||||
|
|
||||||
|
'services' => [
|
||||||
|
'template' => [
|
||||||
|
'host' => 'template-backend-nginx',
|
||||||
|
'apis' => [
|
||||||
|
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'notification' => [
|
||||||
|
'host' => 'notification-backend-nginx',
|
||||||
|
'apis' => [
|
||||||
|
'send-mail' => [
|
||||||
|
'path' => '/api/mail/send',
|
||||||
|
'method' => 'POST'
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|||||||
@ -10,8 +10,7 @@ return [
|
|||||||
'user' => [
|
'user' => [
|
||||||
],
|
],
|
||||||
'admin' => [
|
'admin' => [
|
||||||
'user.create',
|
'user.create-user',
|
||||||
'user.read-list',
|
|
||||||
],
|
],
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|||||||
@ -1,17 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
return [
|
|
||||||
'mail' => [
|
|
||||||
'default' => [
|
|
||||||
'sender' => $_ENV['MAIL_DEFAULT_SENDER'],
|
|
||||||
'senderName' => $_ENV['MAIL_DEFAULT_SENDER_NAME']
|
|
||||||
],
|
|
||||||
'smtp-server' => [
|
|
||||||
'host' => $_ENV['SMTP_HOST'],
|
|
||||||
'port' => (int)$_ENV['SMTP_PORT'] ?? 25,
|
|
||||||
'encryption' => $_ENV['SMTP_ENCRYPTION'],
|
|
||||||
'username' => $_ENV['SMTP_USERNAME'],
|
|
||||||
'password' => $_ENV['SMTP_PASSWORD'],
|
|
||||||
]
|
|
||||||
]
|
|
||||||
];
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
return [
|
|
||||||
'notification' => [
|
|
||||||
'defaultTitle' => $_ENV['NOTIFICATION_DEFAULT_TITLE'] ?? 'Template',
|
|
||||||
'host' => $_ENV['NOTIFICATION_HOST'],
|
|
||||||
'id' => $_ENV['NOTIFICATION_ID'],
|
|
||||||
]
|
|
||||||
];
|
|
||||||
@ -52,9 +52,6 @@ $aggregator = new ConfigAggregator([
|
|||||||
\Template\Infrastructure\Rbac\ConfigProvider::class,
|
\Template\Infrastructure\Rbac\ConfigProvider::class,
|
||||||
\Template\Infrastructure\Request\ConfigProvider::class,
|
\Template\Infrastructure\Request\ConfigProvider::class,
|
||||||
\Template\Infrastructure\Session\ConfigProvider::class,
|
\Template\Infrastructure\Session\ConfigProvider::class,
|
||||||
\Template\Infrastructure\Mail\ConfigProvider::class,
|
|
||||||
\Template\Infrastructure\Notification\ConfigProvider::class,
|
|
||||||
\Template\Infrastructure\Schema\ConfigProvider::class,
|
|
||||||
|
|
||||||
// HandlingDomain
|
// HandlingDomain
|
||||||
\Template\Handling\User\ConfigProvider::class,
|
\Template\Handling\User\ConfigProvider::class,
|
||||||
@ -66,7 +63,7 @@ $aggregator = new ConfigAggregator([
|
|||||||
\Template\API\Console\ConfigProvider::class,
|
\Template\API\Console\ConfigProvider::class,
|
||||||
|
|
||||||
/// External
|
/// External
|
||||||
\Template\API\External\Api\ConfigProvider::class,
|
\Template\API\External\Health\ConfigProvider::class,
|
||||||
\Template\API\External\User\ConfigProvider::class,
|
\Template\API\External\User\ConfigProvider::class,
|
||||||
\Template\API\External\Authentication\ConfigProvider::class,
|
\Template\API\External\Authentication\ConfigProvider::class,
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
use Template\Infrastructure\Exception\Middleware\TemplateExceptionHandlerMiddleware;
|
use Template\Infrastructure\Exception\Middleware\ExceptionHandlerMiddleware;
|
||||||
use Template\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
|
use Template\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
|
||||||
use Template\Infrastructure\Request\Middleware\AnalyzeHeaderMiddleware;
|
use Template\Infrastructure\Request\Middleware\AnalyzeHeaderMiddleware;
|
||||||
use Template\Infrastructure\Session\Middleware\SessionMiddleware;
|
use Template\Infrastructure\Session\Middleware\SessionMiddleware;
|
||||||
@ -68,7 +68,7 @@ return function (Application $app, MiddlewareFactory $factory, ContainerInterfac
|
|||||||
|
|
||||||
|
|
||||||
//// Pre Template Space
|
//// Pre Template Space
|
||||||
$app->pipe(TemplateExceptionHandlerMiddleware::class);
|
$app->pipe(ExceptionHandlerMiddleware::class);
|
||||||
$app->pipe(AnalyzeHeaderMiddleware::class);
|
$app->pipe(AnalyzeHeaderMiddleware::class);
|
||||||
$app->pipe(AnalyzeBodyMiddleware::class);
|
$app->pipe(AnalyzeBodyMiddleware::class);
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.7 KiB |
@ -1,66 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>Willkommen bei Template!</title>
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
}
|
|
||||||
.message-block {
|
|
||||||
font-family: Arial, sans-serif;
|
|
||||||
max-width: 600px;
|
|
||||||
margin: 0 auto;
|
|
||||||
margin-top: 20px;
|
|
||||||
padding: 20px;
|
|
||||||
}
|
|
||||||
.header {
|
|
||||||
background-color: rgb(21 128 61);
|
|
||||||
width: 100%;
|
|
||||||
height: 15%;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
.title {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
.wrapper {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
.quote {
|
|
||||||
font-style: italic;
|
|
||||||
font-size: x-small;
|
|
||||||
color: slategray;
|
|
||||||
}
|
|
||||||
img {
|
|
||||||
margin: 1rem;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
margin-top: auto;
|
|
||||||
margin-bottom: auto;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="header" class="header">
|
|
||||||
<div class="wrapper">
|
|
||||||
<div id="title" class="title">
|
|
||||||
<img src="assets/icon.png" />
|
|
||||||
<h1>Template</h1>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="message-block" class="message-block">
|
|
||||||
<p>Hallo {$username},</p>
|
|
||||||
<br />
|
|
||||||
<p>Herzlich willkommen beim Template!</p>
|
|
||||||
<br />
|
|
||||||
<p>Ich konnte deine Anmeldung nun bestätigen.</p>
|
|
||||||
<p>Bitte klicke auf <a href="{$confirmationLink}">diesen Link</a> um dein Passwort festzulegen.</p>
|
|
||||||
<p>Danach ist deine Registierung abgeschlossen und du kannst loslegen!</p>
|
|
||||||
<br />
|
|
||||||
<p>Mit grünen Grüßen,</p>
|
|
||||||
<p>{$growerName}</p>
|
|
||||||
<br />
|
|
||||||
<p class="quote">"Smoke weed everyday" - Snoop Dogg</p>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.7 KiB |
@ -1,63 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>Passwort zurücksetzen</title>
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
}
|
|
||||||
.message-block {
|
|
||||||
font-family: Arial, sans-serif;
|
|
||||||
max-width: 600px;
|
|
||||||
margin: 0 auto;
|
|
||||||
margin-top: 20px;
|
|
||||||
padding: 20px;
|
|
||||||
}
|
|
||||||
.header {
|
|
||||||
background-color: rgb(255, 199, 44);
|
|
||||||
width: 100%;
|
|
||||||
height: 15%;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
.title {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
.wrapper {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
.quote {
|
|
||||||
font-style: italic;
|
|
||||||
font-size: x-small;
|
|
||||||
color: slategray;
|
|
||||||
}
|
|
||||||
img {
|
|
||||||
margin: 1rem;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
margin-top: auto;
|
|
||||||
margin-bottom: auto;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="header" class="header">
|
|
||||||
<div class="wrapper">
|
|
||||||
<div id="title" class="title">
|
|
||||||
<img src="assets/icon.png" />
|
|
||||||
<h1>Template</h1>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="message-block" class="message-block">
|
|
||||||
<p>Hallo {$username},</p>
|
|
||||||
<br />
|
|
||||||
<p>Dein Passwort wurde zurückgesetzt.</p>
|
|
||||||
<p>Bitte klicke auf <a href="{$passwordResetLink}">diesen Link</a> um ein neues Passwort zu vergeben.</p>
|
|
||||||
<br />
|
|
||||||
<p>Wenn du dein Passwort nicht zurückgesetzt hast, kannst du diese Nachricht ignorieren!</p>
|
|
||||||
<br />
|
|
||||||
<p>Mit fleißigen Grüßen,</p>
|
|
||||||
<p>Der Template</p>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,37 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Template\Migrations\Bee;
|
|
||||||
|
|
||||||
use Doctrine\DBAL\Schema\Schema;
|
|
||||||
use Doctrine\Migrations\AbstractMigration;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Auto-generated Migration: Please modify to your needs!
|
|
||||||
*/
|
|
||||||
final class Version20240827155813 extends AbstractMigration
|
|
||||||
{
|
|
||||||
public function getDescription(): string
|
|
||||||
{
|
|
||||||
return "Create Table 'user_password_token'";
|
|
||||||
}
|
|
||||||
|
|
||||||
public function up(Schema $schema): void
|
|
||||||
{
|
|
||||||
$sql = "CREATE TABLE user_password_token (
|
|
||||||
id binary(16) NOT NULL,
|
|
||||||
user_id binary(16) NOT NULL,
|
|
||||||
updated_at datetime NOT NULL,
|
|
||||||
created_at datetime NOT NULL,
|
|
||||||
PRIMARY KEY (id)
|
|
||||||
);";
|
|
||||||
|
|
||||||
$this->addSql($sql);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function down(Schema $schema): void
|
|
||||||
{
|
|
||||||
$this->addSql("DROP TABLE user_password_token;");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Bee\Migrations\Bee;
|
|
||||||
|
|
||||||
use Doctrine\DBAL\Schema\Schema;
|
|
||||||
use Doctrine\Migrations\AbstractMigration;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Auto-generated Migration: Please modify to your needs!
|
|
||||||
*/
|
|
||||||
final class Version20240911191301 extends AbstractMigration
|
|
||||||
{
|
|
||||||
public function getDescription(): string
|
|
||||||
{
|
|
||||||
return "Create Table 'mail'";
|
|
||||||
}
|
|
||||||
|
|
||||||
public function up(Schema $schema): void
|
|
||||||
{
|
|
||||||
$sql = "CREATE TABLE mail (
|
|
||||||
id binary(16) NOT NULL,
|
|
||||||
template varchar(255) NOT NULL,
|
|
||||||
data json NOT NULL,
|
|
||||||
recipient varchar(255) NOT NULL,
|
|
||||||
sender varchar(255) NULL,
|
|
||||||
sender_name varchar(255) NULL,
|
|
||||||
failed_at datetime NULL,
|
|
||||||
created_at datetime NOT NULL,
|
|
||||||
PRIMARY KEY (id)
|
|
||||||
);";
|
|
||||||
|
|
||||||
$this->addSql($sql);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function down(Schema $schema): void
|
|
||||||
{
|
|
||||||
$this->addSql("DROP TABLE mail;");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
52
docker/docker-compose-mac.yml.dist
Normal file
52
docker/docker-compose-mac.yml.dist
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
networks:
|
||||||
|
template:
|
||||||
|
external: true
|
||||||
|
|
||||||
|
services:
|
||||||
|
template-backend-mysql:
|
||||||
|
image: template-backend-mysql
|
||||||
|
networks:
|
||||||
|
- template
|
||||||
|
build:
|
||||||
|
context: ./../
|
||||||
|
dockerfile: ./docker/mysql/dockerfile
|
||||||
|
volumes:
|
||||||
|
- /Users/flo/dev/backend/template/var/db:/var/lib/mysql:z
|
||||||
|
environment:
|
||||||
|
MYSQL_USER: ${DB_USER}
|
||||||
|
MYSQL_PASSWORD: ${DB_PASSWORD}
|
||||||
|
ports:
|
||||||
|
- 3306:3306
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"]
|
||||||
|
timeout: 20s
|
||||||
|
retries: 10
|
||||||
|
|
||||||
|
template-backend-app:
|
||||||
|
image: template-backend-app
|
||||||
|
networks:
|
||||||
|
- template
|
||||||
|
build:
|
||||||
|
context: ./../
|
||||||
|
dockerfile: ./docker/php/dockerfile
|
||||||
|
volumes:
|
||||||
|
- /Users/flo/dev/backend/template/:/var/www/html:z
|
||||||
|
ports:
|
||||||
|
- 9000:9000
|
||||||
|
depends_on:
|
||||||
|
template-backend-mysql:
|
||||||
|
condition: service_healthy
|
||||||
|
|
||||||
|
template-backend-nginx:
|
||||||
|
image: template-backend-nginx
|
||||||
|
networks:
|
||||||
|
- template
|
||||||
|
build:
|
||||||
|
context: ./../
|
||||||
|
dockerfile: ./docker/nginx/dockerfile
|
||||||
|
labels:
|
||||||
|
- "traefik.http.routers.backend.rule=Host(`template.local`) && PathPrefix(`/api`)"
|
||||||
|
- "traefik.http.routers.backend.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.backend.tls.certresolver=le"
|
||||||
|
depends_on:
|
||||||
|
- template-backend-app
|
||||||
@ -1,13 +0,0 @@
|
|||||||
{
|
|
||||||
"get": {
|
|
||||||
"description": "Checks the health of the API backend",
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"$ref": "./response.json"
|
|
||||||
},
|
|
||||||
"default": {
|
|
||||||
"$ref": "../../../Partials/Response/bad-request.json"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "Successfully checked the health of the API backend",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
{
|
|
||||||
"get": {
|
|
||||||
"description": "Reads the current schema definition",
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"$ref": "./response.json"
|
|
||||||
},
|
|
||||||
"default": {
|
|
||||||
"$ref": "../../../Partials/Response/bad-request.json"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "Successfully read the schema definition",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"openapi",
|
|
||||||
"info",
|
|
||||||
"paths",
|
|
||||||
"components"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,44 +0,0 @@
|
|||||||
{
|
|
||||||
"post": {
|
|
||||||
"description": "Confirms a registration and sets the initial password.",
|
|
||||||
"requestBody": {
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"id",
|
|
||||||
"password",
|
|
||||||
"passwordConfirmation"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"id": {
|
|
||||||
"$ref": "../../../Partials/uuid.json"
|
|
||||||
},
|
|
||||||
"password": {
|
|
||||||
"$ref": "../Partials/password.json"
|
|
||||||
},
|
|
||||||
"passwordConfirmation": {
|
|
||||||
"$ref": "../Partials/password.json"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"$ref": "./response.json"
|
|
||||||
},
|
|
||||||
"401": {
|
|
||||||
"$ref": "../../../Partials/Response/unauthorized.json"
|
|
||||||
},
|
|
||||||
"403": {
|
|
||||||
"$ref": "../../../Partials/Response/forbidden.json"
|
|
||||||
},
|
|
||||||
"default": {
|
|
||||||
"$ref": "../../../Partials/Response/bad-request.json"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,34 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "Successfully confirmed registration",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"id",
|
|
||||||
"username",
|
|
||||||
"roleIdentifier",
|
|
||||||
"permissions"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"id": {
|
|
||||||
"$ref": "../../../Partials/uuid.json"
|
|
||||||
},
|
|
||||||
"username": {
|
|
||||||
"$ref": "../Partials/username.json"
|
|
||||||
},
|
|
||||||
"roleIdentifier": {
|
|
||||||
"$ref": "../Partials/role-identifier.json"
|
|
||||||
},
|
|
||||||
"permissions": {
|
|
||||||
"description": "All permissions assigned to the user",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
{
|
|
||||||
"post": {
|
|
||||||
"description": "Requests a password reset mail, by providing a registered email address",
|
|
||||||
"requestBody": {
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"mail"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"mail": {
|
|
||||||
"$ref": "../Partials/mail.json"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"$ref": "./response.json"
|
|
||||||
},
|
|
||||||
"401": {
|
|
||||||
"$ref": "../../../Partials/Response/unauthorized.json"
|
|
||||||
},
|
|
||||||
"403": {
|
|
||||||
"$ref": "../../../Partials/Response/forbidden.json"
|
|
||||||
},
|
|
||||||
"default": {
|
|
||||||
"$ref": "../../../Partials/Response/bad-request.json"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "Password reset mail successfully sent",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,40 +0,0 @@
|
|||||||
{
|
|
||||||
"post": {
|
|
||||||
"description": "Login with user credentials.",
|
|
||||||
"requestBody": {
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"identifier",
|
|
||||||
"password"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"identifier": {
|
|
||||||
"$ref": "../Partials/identifier.json"
|
|
||||||
},
|
|
||||||
"password": {
|
|
||||||
"$ref": "../Partials/password.json"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"$ref": "./response.json"
|
|
||||||
},
|
|
||||||
"401": {
|
|
||||||
"$ref": "../../../Partials/Response/unauthorized.json"
|
|
||||||
},
|
|
||||||
"403": {
|
|
||||||
"$ref": "../../../Partials/Response/forbidden.json"
|
|
||||||
},
|
|
||||||
"default": {
|
|
||||||
"$ref": "../../../Partials/Response/bad-request.json"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "User successfully logged in",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"sessionId"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"sessionId": {
|
|
||||||
"$ref": "../../../Partials/uuid.json"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
{
|
|
||||||
"get": {
|
|
||||||
"description": "Logout the currently logged in user.",
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"$ref": "./response.json"
|
|
||||||
},
|
|
||||||
"401": {
|
|
||||||
"$ref": "../../../Partials/Response/unauthorized.json"
|
|
||||||
},
|
|
||||||
"403": {
|
|
||||||
"$ref": "../../../Partials/Response/forbidden.json"
|
|
||||||
},
|
|
||||||
"default": {
|
|
||||||
"$ref": "../../../Partials/Response/bad-request.json"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "User successfully logged out",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "The identifier for the user. May be a mail address or a username",
|
|
||||||
"example": "max.mustermann@example.com",
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "The mail address of a user",
|
|
||||||
"example": "max.mustermann@example.com",
|
|
||||||
"type": "string",
|
|
||||||
"format": "email"
|
|
||||||
}
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "The password for an account",
|
|
||||||
"example": "Password123!",
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "A role identifier",
|
|
||||||
"example": "admin",
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"admin",
|
|
||||||
"user"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "The username of a user",
|
|
||||||
"example": "max.mustermann",
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
@ -1,40 +0,0 @@
|
|||||||
{
|
|
||||||
"post": {
|
|
||||||
"description": "Creates a registration for a new user with their username and email address",
|
|
||||||
"requestBody": {
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"username",
|
|
||||||
"mail"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"username": {
|
|
||||||
"$ref": "../Partials/username.json"
|
|
||||||
},
|
|
||||||
"mail": {
|
|
||||||
"$ref": "../Partials/mail.json"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"$ref": "./response.json"
|
|
||||||
},
|
|
||||||
"401": {
|
|
||||||
"$ref": "../../../Partials/Response/unauthorized.json"
|
|
||||||
},
|
|
||||||
"403": {
|
|
||||||
"$ref": "../../../Partials/Response/forbidden.json"
|
|
||||||
},
|
|
||||||
"default": {
|
|
||||||
"$ref": "../../../Partials/Response/bad-request.json"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "Successfully created the registration",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,44 +0,0 @@
|
|||||||
{
|
|
||||||
"post": {
|
|
||||||
"description": "Sets a new Password by providing a password reset token and the new password",
|
|
||||||
"requestBody": {
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"passwordToken",
|
|
||||||
"newPassword",
|
|
||||||
"passwordConfirmation"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"passwordToken": {
|
|
||||||
"$ref": "../../../Partials/uuid.json"
|
|
||||||
},
|
|
||||||
"newPassword": {
|
|
||||||
"$ref": "../Partials/password.json"
|
|
||||||
},
|
|
||||||
"passwordConfirmation": {
|
|
||||||
"$ref": "../Partials/password.json"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"$ref": "./response.json"
|
|
||||||
},
|
|
||||||
"401": {
|
|
||||||
"$ref": "../../../Partials/Response/unauthorized.json"
|
|
||||||
},
|
|
||||||
"403": {
|
|
||||||
"$ref": "../../../Partials/Response/forbidden.json"
|
|
||||||
},
|
|
||||||
"default": {
|
|
||||||
"$ref": "../../../Partials/Response/bad-request.json"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "Successfully set new password",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,40 +0,0 @@
|
|||||||
{
|
|
||||||
"post": {
|
|
||||||
"description": "Changes the currently logged in users password",
|
|
||||||
"requestBody": {
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"password",
|
|
||||||
"newPassword"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"password": {
|
|
||||||
"$ref": "../../Authentication/Partials/password.json"
|
|
||||||
},
|
|
||||||
"newPassword": {
|
|
||||||
"$ref": "../../Authentication/Partials/password.json"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"$ref": "./response.json"
|
|
||||||
},
|
|
||||||
"401": {
|
|
||||||
"$ref": "../../../Partials/Response/unauthorized.json"
|
|
||||||
},
|
|
||||||
"403": {
|
|
||||||
"$ref": "../../../Partials/Response/forbidden.json"
|
|
||||||
},
|
|
||||||
"default": {
|
|
||||||
"$ref": "../../../Partials/Response/bad-request.json"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "Successfully changed the password",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,40 +0,0 @@
|
|||||||
{
|
|
||||||
"post": {
|
|
||||||
"description": "Changes the currently logged in users username",
|
|
||||||
"requestBody": {
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"password",
|
|
||||||
"newUsername"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"password": {
|
|
||||||
"$ref": "../../Authentication/Partials/password.json"
|
|
||||||
},
|
|
||||||
"newUsername": {
|
|
||||||
"$ref": "../../Authentication/Partials/username.json"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"$ref": "./response.json"
|
|
||||||
},
|
|
||||||
"401": {
|
|
||||||
"$ref": "../../../Partials/Response/unauthorized.json"
|
|
||||||
},
|
|
||||||
"403": {
|
|
||||||
"$ref": "../../../Partials/Response/forbidden.json"
|
|
||||||
},
|
|
||||||
"default": {
|
|
||||||
"$ref": "../../../Partials/Response/bad-request.json"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "Successfully changed the username",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,44 +0,0 @@
|
|||||||
{
|
|
||||||
"post": {
|
|
||||||
"description": "Creates a User",
|
|
||||||
"requestBody": {
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"username",
|
|
||||||
"mail",
|
|
||||||
"password"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"username": {
|
|
||||||
"$ref": "../../Authentication/Partials/username.json"
|
|
||||||
},
|
|
||||||
"mail": {
|
|
||||||
"$ref": "../../Authentication/Partials/mail.json"
|
|
||||||
},
|
|
||||||
"password": {
|
|
||||||
"$ref": "../../Authentication/Partials/password.json"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"$ref": "./response.json"
|
|
||||||
},
|
|
||||||
"401": {
|
|
||||||
"$ref": "../../../Partials/Response/unauthorized.json"
|
|
||||||
},
|
|
||||||
"403": {
|
|
||||||
"$ref": "../../../Partials/Response/forbidden.json"
|
|
||||||
},
|
|
||||||
"default": {
|
|
||||||
"$ref": "../../../Partials/Response/bad-request.json"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,42 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "Successfully created the user",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"id",
|
|
||||||
"username",
|
|
||||||
"role",
|
|
||||||
"permissions",
|
|
||||||
"createdAt",
|
|
||||||
"updatedAt"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"id": {
|
|
||||||
"$ref": "../../../Partials/uuid.json"
|
|
||||||
},
|
|
||||||
"username": {
|
|
||||||
"$ref": "../../Authentication/Partials/username.json"
|
|
||||||
},
|
|
||||||
"role": {
|
|
||||||
"$ref": "../../Authentication/Partials/role-identifier.json"
|
|
||||||
},
|
|
||||||
"permissions": {
|
|
||||||
"description": "All permissions assigned to the user",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"createdAt": {
|
|
||||||
"$ref": "../../../Partials/date-time.json"
|
|
||||||
},
|
|
||||||
"updatedAt": {
|
|
||||||
"$ref": "../../../Partials/date-time.json"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,44 +0,0 @@
|
|||||||
{
|
|
||||||
"post": {
|
|
||||||
"description": "Reads a paginated list of users",
|
|
||||||
"requestBody": {
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"page",
|
|
||||||
"perPage",
|
|
||||||
"query"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"page": {
|
|
||||||
"$ref": "../../../Partials/pagination-page.json"
|
|
||||||
},
|
|
||||||
"perPage": {
|
|
||||||
"$ref": "../../../Partials/pagination-per-page.json"
|
|
||||||
},
|
|
||||||
"query": {
|
|
||||||
"$ref": "../../../Partials/pagination-query.json"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"$ref": "./response.json"
|
|
||||||
},
|
|
||||||
"401": {
|
|
||||||
"$ref": "../../../Partials/Response/unauthorized.json"
|
|
||||||
},
|
|
||||||
"403": {
|
|
||||||
"$ref": "../../../Partials/Response/forbidden.json"
|
|
||||||
},
|
|
||||||
"default": {
|
|
||||||
"$ref": "../../../Partials/Response/bad-request.json"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,50 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "Successfully read a list of paginated users",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"total",
|
|
||||||
"items"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"total": {
|
|
||||||
"$ref": "../../../Partials/pagination-total.json"
|
|
||||||
},
|
|
||||||
"items": {
|
|
||||||
"description": "The resultset",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"id",
|
|
||||||
"role",
|
|
||||||
"username",
|
|
||||||
"mail",
|
|
||||||
"lastLoginAt"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"id": {
|
|
||||||
"$ref": "../../../Partials/uuid.json"
|
|
||||||
},
|
|
||||||
"role": {
|
|
||||||
"$ref": "../../Authentication/Partials/role-identifier.json"
|
|
||||||
},
|
|
||||||
"username": {
|
|
||||||
"$ref": "../../Authentication/Partials/username.json"
|
|
||||||
},
|
|
||||||
"mail": {
|
|
||||||
"$ref": "../../Authentication/Partials/mail.json"
|
|
||||||
},
|
|
||||||
"lastLoginAt": {
|
|
||||||
"$ref": "../../../Partials/nullable-date-time.json"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
{
|
|
||||||
"get": {
|
|
||||||
"description": "Reads the state of the currently logged in user",
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"$ref": "./response.json"
|
|
||||||
},
|
|
||||||
"401": {
|
|
||||||
"$ref": "../../../Partials/Response/unauthorized.json"
|
|
||||||
},
|
|
||||||
"403": {
|
|
||||||
"$ref": "../../../Partials/Response/forbidden.json"
|
|
||||||
},
|
|
||||||
"default": {
|
|
||||||
"$ref": "../../../Partials/Response/bad-request.json"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,46 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "Successfully read the currently logged in users state",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"id",
|
|
||||||
"username",
|
|
||||||
"roleIdentifier",
|
|
||||||
"permissions",
|
|
||||||
"createdAt",
|
|
||||||
"updatedAt",
|
|
||||||
"sessionId"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"id": {
|
|
||||||
"$ref": "../../../Partials/uuid.json"
|
|
||||||
},
|
|
||||||
"username": {
|
|
||||||
"$ref": "../../Authentication/Partials/username.json"
|
|
||||||
},
|
|
||||||
"role": {
|
|
||||||
"$ref": "../../Authentication/Partials/role-identifier.json"
|
|
||||||
},
|
|
||||||
"permissions": {
|
|
||||||
"description": "All permissions assigned to the user",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"createdAt": {
|
|
||||||
"$ref": "../../../Partials/date-time.json"
|
|
||||||
},
|
|
||||||
"updatedAt": {
|
|
||||||
"$ref": "../../../Partials/date-time.json"
|
|
||||||
},
|
|
||||||
"sessionId": {
|
|
||||||
"$ref": "../../../Partials/uuid.json"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "Bad Request",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"error"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"error": {
|
|
||||||
"description": "The error response object",
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"code"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"code": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"example": {
|
|
||||||
"error": {
|
|
||||||
"code": "Username.AlreadyExists"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "The user is forbidden to perform this action",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "Success",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "Invalid credentials or invalid user session",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "A string representing a timestamp",
|
|
||||||
"example": "2024-11-10T21:24:04+00:00",
|
|
||||||
"type": "string",
|
|
||||||
"format": "date-time"
|
|
||||||
}
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "A nullable string representing a timestamp",
|
|
||||||
"nullable": true,
|
|
||||||
"example": "2024-11-10T21:24:04+00:00",
|
|
||||||
"type": "string",
|
|
||||||
"format": "date-time"
|
|
||||||
}
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "A nullable string indicating the time of day in a 24h format (HH:MM)",
|
|
||||||
"nullable": true,
|
|
||||||
"example": "04:20",
|
|
||||||
"type": "string",
|
|
||||||
"pattern": "^([01]\\d|2[0-3]):([0-5]\\d)$"
|
|
||||||
}
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "The current page of a paginated list",
|
|
||||||
"type": "integer",
|
|
||||||
"example": 6,
|
|
||||||
"minimum": 1
|
|
||||||
}
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "The maximum amount of items displayed on a page of a paginated list",
|
|
||||||
"type": "integer",
|
|
||||||
"example": 4,
|
|
||||||
"minimum": 1
|
|
||||||
}
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "The nullable query to search for in a paginated list",
|
|
||||||
"example": "Growbox",
|
|
||||||
"type": "string",
|
|
||||||
"nullable": true
|
|
||||||
}
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "The total amount of elements in a paginated list",
|
|
||||||
"type": "integer",
|
|
||||||
"example": 3,
|
|
||||||
"minimum": 0
|
|
||||||
}
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "A string indicating the time of day in a 24h format (HH:MM)",
|
|
||||||
"example": "04:20",
|
|
||||||
"type": "string",
|
|
||||||
"pattern": "^([01]\\d|2[0-3]):([0-5]\\d)$"
|
|
||||||
}
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "A universally unique identifier",
|
|
||||||
"example": "071ac920-38dc-11ed-a009-0242ac130005",
|
|
||||||
"format": "uuid",
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
@ -1,60 +0,0 @@
|
|||||||
{
|
|
||||||
"openapi": "3.0.3",
|
|
||||||
"info": {
|
|
||||||
"title": "Template API",
|
|
||||||
"description": "The API powering the Template application",
|
|
||||||
"version": "1.0.0"
|
|
||||||
},
|
|
||||||
"components": {
|
|
||||||
"securitySchemes": {
|
|
||||||
"ApiKeyAuth": {
|
|
||||||
"type": "apiKey",
|
|
||||||
"in": "header",
|
|
||||||
"name": "X-API-Key"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"paths": {
|
|
||||||
"/api/health": {
|
|
||||||
"$ref": "External/Api/Health/request.json"
|
|
||||||
},
|
|
||||||
"/api/schema": {
|
|
||||||
"$ref": "External/Api/Schema/request.json"
|
|
||||||
},
|
|
||||||
|
|
||||||
"/api/auth/login-user": {
|
|
||||||
"$ref": "External/Authentication/Login/request.json"
|
|
||||||
},
|
|
||||||
"/api/auth/logout-user": {
|
|
||||||
"$ref": "External/Authentication/Logout/request.json"
|
|
||||||
},
|
|
||||||
"/api/auth/confirm-registration": {
|
|
||||||
"$ref": "External/Authentication/ConfirmRegistration/request.json"
|
|
||||||
},
|
|
||||||
"/api/auth/register-user": {
|
|
||||||
"$ref": "External/Authentication/RegisterUser/request.json"
|
|
||||||
},
|
|
||||||
"/api/auth/forgot-password": {
|
|
||||||
"$ref": "External/Authentication/ForgotPassword/request.json"
|
|
||||||
},
|
|
||||||
"/api/auth/reset-password": {
|
|
||||||
"$ref": "External/Authentication/ResetPassword/request.json"
|
|
||||||
},
|
|
||||||
|
|
||||||
"/api/user/create": {
|
|
||||||
"$ref": "External/User/Create/request.json"
|
|
||||||
},
|
|
||||||
"/api/user/change-password": {
|
|
||||||
"$ref": "External/User/ChangePassword/request.json"
|
|
||||||
},
|
|
||||||
"/api/user/change-username": {
|
|
||||||
"$ref": "External/User/ChangeUsername/request.json"
|
|
||||||
},
|
|
||||||
"/api/user/read-list": {
|
|
||||||
"$ref": "External/User/ReadList/request.json"
|
|
||||||
},
|
|
||||||
"/api/user/state": {
|
|
||||||
"$ref": "External/User/UserState/request.json"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -46,7 +46,7 @@ return [
|
|||||||
|
|
||||||
'migrations_configuration' => [
|
'migrations_configuration' => [
|
||||||
'orm_template' => [
|
'orm_template' => [
|
||||||
'directory' => 'data/migrations/template',
|
'directory' => 'data/migrations/business',
|
||||||
'name' => 'Doctrine Database Migrations for Template',
|
'name' => 'Doctrine Database Migrations for Template',
|
||||||
'namespace' => 'Template\Migrations\Template',
|
'namespace' => 'Template\Migrations\Template',
|
||||||
'table' => 'migrations',
|
'table' => 'migrations',
|
||||||
|
|||||||
@ -1,20 +1,20 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Template\Data\Business\Entity\User;
|
use Template\Data\Business\Entity\User;
|
||||||
use Template\Data\Business\Factory\EntityManagerFactory as TemplateEntityManagerFactory;
|
use Template\Data\Business\Factory\EntityManagerFactory;
|
||||||
use Template\Data\Business\Manager\EntityManager;
|
use Template\Data\Business\Manager\EntityManager;
|
||||||
use Template\Data\Business\Repository\UserRepository;
|
use Template\Data\Business\Repository\UserRepository;
|
||||||
use Template\Infrastructure\Database\AutowireRepositoryFactory;
|
use Template\Infrastructure\Database\AutowireRepositoryFactory;
|
||||||
use Roave\PsrContainerDoctrine\ConfigurationFactory;
|
use Roave\PsrContainerDoctrine\ConfigurationFactory;
|
||||||
use Roave\PsrContainerDoctrine\ConnectionFactory;
|
use Roave\PsrContainerDoctrine\ConnectionFactory;
|
||||||
use Roave\PsrContainerDoctrine\EntityManagerFactory;
|
use Roave\PsrContainerDoctrine\EntityManagerFactory as BaseEntityManagerFactory;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'factories' => [
|
'factories' => [
|
||||||
'doctrine.entity_manager.orm_template' => [EntityManagerFactory::class, 'orm_template'],
|
'doctrine.entity_manager.orm_template' => [BaseEntityManagerFactory::class, 'orm_template'],
|
||||||
'doctrine.configuration.orm_template' => [ConfigurationFactory::class, 'orm_template'],
|
'doctrine.configuration.orm_template' => [ConfigurationFactory::class, 'orm_template'],
|
||||||
'doctrine.connection.orm_template' => [ConnectionFactory::class, 'orm_template'],
|
'doctrine.connection.orm_template' => [ConnectionFactory::class, 'orm_template'],
|
||||||
EntityManager::class => TemplateEntityManagerFactory::class,
|
EntityManager::class => EntityManagerFactory::class,
|
||||||
|
|
||||||
UserRepository::class => [AutowireRepositoryFactory::class, EntityManager::class, User::class],
|
UserRepository::class => [AutowireRepositoryFactory::class, EntityManager::class, User::class],
|
||||||
],
|
],
|
||||||
|
|||||||
@ -1,125 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Template\Data\Business\Entity;
|
|
||||||
|
|
||||||
use DateTime;
|
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
|
||||||
use Template\Infrastructure\UuidGenerator\UuidGenerator;
|
|
||||||
use Ramsey\Uuid\UuidInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @ORM\Entity(repositoryClass="Template\Data\Business\Repository\MailRepository")
|
|
||||||
* @ORM\Table(name="mail")
|
|
||||||
*/
|
|
||||||
class Mail {
|
|
||||||
/**
|
|
||||||
* @ORM\Id
|
|
||||||
* @ORM\Column(name="id", type="uuid_binary_ordered_time")
|
|
||||||
*/
|
|
||||||
private UuidInterface $id;
|
|
||||||
|
|
||||||
/** @ORM\Column(name="template", type="string") */
|
|
||||||
private string $template;
|
|
||||||
|
|
||||||
/** @ORM\Column(name="data", type="json") */
|
|
||||||
private array $data;
|
|
||||||
|
|
||||||
/** @ORM\Column(name="recipient", type="string") */
|
|
||||||
private string $recipient;
|
|
||||||
|
|
||||||
/** @ORM\Column(name="sender", type="string", nullable="true") */
|
|
||||||
private ?string $sender;
|
|
||||||
|
|
||||||
/** @ORM\Column(name="sender_name", type="string", nullable="true") */
|
|
||||||
private ?string $senderName;
|
|
||||||
|
|
||||||
/** @ORM\Column(name="failed_at", type="datetime", nullable="true") */
|
|
||||||
private ?DateTime $failedAt;
|
|
||||||
|
|
||||||
/** @ORM\Column(name="created_at", type="datetime") */
|
|
||||||
private DateTime $createdAt;
|
|
||||||
|
|
||||||
public function __construct() {
|
|
||||||
$this->id = UuidGenerator::generate();
|
|
||||||
|
|
||||||
$now = new DateTime();
|
|
||||||
$this->setCreatedAt($now);
|
|
||||||
$this->setFailedAt(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @ORM\PrePersist
|
|
||||||
* @ORM\PreUpdate
|
|
||||||
*/
|
|
||||||
public function updateTimestamps(): void {
|
|
||||||
$now = new DateTime();
|
|
||||||
//$this->setUpdatedAt($now);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public function getId(): UuidInterface {
|
|
||||||
return $this->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getTemplate(): string
|
|
||||||
{
|
|
||||||
return $this->template;
|
|
||||||
}
|
|
||||||
public function setTemplate(string $template): void
|
|
||||||
{
|
|
||||||
$this->template = $template;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getData(): array
|
|
||||||
{
|
|
||||||
return $this->data;
|
|
||||||
}
|
|
||||||
public function setData(array $data): void
|
|
||||||
{
|
|
||||||
$this->data = $data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getRecipient(): string
|
|
||||||
{
|
|
||||||
return $this->recipient;
|
|
||||||
}
|
|
||||||
public function setRecipient(string $recipient): void
|
|
||||||
{
|
|
||||||
$this->recipient = $recipient;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getSender(): ?string
|
|
||||||
{
|
|
||||||
return $this->sender;
|
|
||||||
}
|
|
||||||
public function setSender(?string $sender): void
|
|
||||||
{
|
|
||||||
$this->sender = $sender;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getSenderName(): ?string
|
|
||||||
{
|
|
||||||
return $this->senderName;
|
|
||||||
}
|
|
||||||
public function setSenderName(?string $senderName): void
|
|
||||||
{
|
|
||||||
$this->senderName = $senderName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getFailedAt(): ?DateTime
|
|
||||||
{
|
|
||||||
return $this->failedAt;
|
|
||||||
}
|
|
||||||
public function setFailedAt(?DateTime $failedAt): void
|
|
||||||
{
|
|
||||||
$this->failedAt = $failedAt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getCreatedAt(): DateTime {
|
|
||||||
return $this->createdAt;
|
|
||||||
}
|
|
||||||
public function setCreatedAt(DateTime $createdAt): void {
|
|
||||||
$this->createdAt = $createdAt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -3,8 +3,6 @@
|
|||||||
namespace Template\Data\Business\Entity;
|
namespace Template\Data\Business\Entity;
|
||||||
|
|
||||||
use DateTime;
|
use DateTime;
|
||||||
use Doctrine\Common\Collections\ArrayCollection;
|
|
||||||
use Doctrine\Common\Collections\Collection;
|
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
use Template\Infrastructure\UuidGenerator\UuidGenerator;
|
use Template\Infrastructure\UuidGenerator\UuidGenerator;
|
||||||
use Ramsey\Uuid\UuidInterface;
|
use Ramsey\Uuid\UuidInterface;
|
||||||
@ -41,11 +39,8 @@ class User {
|
|||||||
/** @ORM\OneToOne(targetEntity="Template\Data\Business\Entity\UserSession", mappedBy="user") */
|
/** @ORM\OneToOne(targetEntity="Template\Data\Business\Entity\UserSession", mappedBy="user") */
|
||||||
private ?UserSession $session;
|
private ?UserSession $session;
|
||||||
|
|
||||||
/* @ORM\OneToMany(targetEntity="Bee\Data\Business\Entity\UserPasswordToken", mappedBy="user") */
|
|
||||||
private Collection $passwordTokens;
|
|
||||||
|
|
||||||
/** @ORM\Column(name="last_login_at", type="datetime", nullable=true) */
|
/** @ORM\Column(name="last_login_at", type="datetime", nullable=true) */
|
||||||
private ?DateTime $lastLoginAt;
|
private DateTime $lastLoginAt;
|
||||||
|
|
||||||
/** @ORM\Column(name="created_at", type="datetime") */
|
/** @ORM\Column(name="created_at", type="datetime") */
|
||||||
private DateTime $createdAt;
|
private DateTime $createdAt;
|
||||||
@ -56,9 +51,7 @@ class User {
|
|||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
$this->id = UuidGenerator::generate();
|
$this->id = UuidGenerator::generate();
|
||||||
|
|
||||||
$this->passwordTokens = new ArrayCollection();
|
|
||||||
|
|
||||||
$now = new DateTime();
|
$now = new DateTime();
|
||||||
$this->setCreatedAt($now);
|
$this->setCreatedAt($now);
|
||||||
$this->setUpdatedAt($now);
|
$this->setUpdatedAt($now);
|
||||||
@ -150,27 +143,6 @@ class User {
|
|||||||
public function setUpdatedAt(DateTime $updatedAt): void {
|
public function setUpdatedAt(DateTime $updatedAt): void {
|
||||||
$this->updatedAt = $updatedAt;
|
$this->updatedAt = $updatedAt;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPasswordTokens(): Collection
|
|
||||||
{
|
|
||||||
return $this->passwordTokens;
|
|
||||||
}
|
|
||||||
public function setPasswordTokens(Collection $passwordTokens): void
|
|
||||||
{
|
|
||||||
$this->passwordTokens = $passwordTokens;
|
|
||||||
}
|
|
||||||
public function addPasswordToken(UserPasswordToken $passwordToken): void
|
|
||||||
{
|
|
||||||
if (!$this->passwordTokens->contains($passwordToken)) {
|
|
||||||
$this->passwordTokens->add($passwordToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public function removePasswordToken(UserPasswordToken $passwordToken): void
|
|
||||||
{
|
|
||||||
if ($this->passwordTokens->contains($passwordToken)) {
|
|
||||||
$this->passwordTokens->removeElement($passwordToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
@ -1,91 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Template\Data\Business\Entity;
|
|
||||||
|
|
||||||
use DateTime;
|
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
|
||||||
use Template\Infrastructure\UuidGenerator\UuidGenerator;
|
|
||||||
use Ramsey\Uuid\UuidInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @ORM\Entity(repositoryClass="Template\Data\Business\Repository\UserPasswordTokenRepository")
|
|
||||||
* @ORM\Table(name="user_password_token")
|
|
||||||
*/
|
|
||||||
class UserPasswordToken {
|
|
||||||
/**
|
|
||||||
* @ORM\Id
|
|
||||||
* @ORM\Column(name="id", type="uuid_binary_ordered_time")
|
|
||||||
*/
|
|
||||||
private UuidInterface $id;
|
|
||||||
|
|
||||||
/** @ORM\Column(name="user_id", type="uuid_binary_ordered_time", nullable=false) */
|
|
||||||
private UuidInterface $userId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @ORM\ManyToOne(targetEntity="User", inversedBy="passwordTokens")
|
|
||||||
* @ORM\JoinColumn(name="user_id", referencedColumnName="id")
|
|
||||||
*/
|
|
||||||
private User $user;
|
|
||||||
|
|
||||||
/** @ORM\Column(name="created_at", type="datetime") */
|
|
||||||
private DateTime $createdAt;
|
|
||||||
|
|
||||||
/** @ORM\Column(name="updated_at", type="datetime") */
|
|
||||||
private DateTime $updatedAt;
|
|
||||||
|
|
||||||
|
|
||||||
public function __construct() {
|
|
||||||
$this->id = UuidGenerator::generate();
|
|
||||||
|
|
||||||
$now = new DateTime();
|
|
||||||
$this->setCreatedAt($now);
|
|
||||||
$this->setUpdatedAt($now);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @ORM\PrePersist
|
|
||||||
* @ORM\PreUpdate
|
|
||||||
*/
|
|
||||||
public function updateTimestamps(): void {
|
|
||||||
$now = new DateTime();
|
|
||||||
$this->setUpdatedAt($now);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public function getId(): UuidInterface {
|
|
||||||
return $this->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getUserId(): UuidInterface {
|
|
||||||
return $this->userId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setUserId(UuidInterface $userId): void {
|
|
||||||
$this->userId = $userId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getUser(): User {
|
|
||||||
return $this->user;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setUser(User $user): void {
|
|
||||||
$this->user = $user;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getCreatedAt(): DateTime {
|
|
||||||
return $this->createdAt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setCreatedAt(DateTime $createdAt): void {
|
|
||||||
$this->createdAt = $createdAt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getUpdatedAt(): DateTime {
|
|
||||||
return $this->updatedAt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setUpdatedAt(DateTime $updatedAt): void {
|
|
||||||
$this->updatedAt = $updatedAt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Template\Data\Business\Repository;
|
|
||||||
|
|
||||||
use Doctrine\ORM\EntityRepository;
|
|
||||||
|
|
||||||
class MailRepository extends EntityRepository {
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Template\Data\Business\Repository;
|
|
||||||
|
|
||||||
use Template\Data\Business\Entity\User;
|
|
||||||
use Doctrine\ORM\EntityRepository;
|
|
||||||
use Template\Data\Business\Entity\UserSession;
|
|
||||||
|
|
||||||
class UserPasswordTokenRepository extends EntityRepository {
|
|
||||||
}
|
|
||||||
@ -1,33 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Template\Infrastructure\Database;
|
|
||||||
|
|
||||||
use Doctrine\ORM\EntityManager;
|
|
||||||
use Doctrine\ORM\EntityRepository;
|
|
||||||
use Doctrine\Persistence\ObjectRepository;
|
|
||||||
use Laminas\ServiceManager\Factory\FactoryInterface;
|
|
||||||
use Psr\Container\ContainerInterface;
|
|
||||||
|
|
||||||
class AutowireRepositoryFactory implements FactoryInterface
|
|
||||||
{
|
|
||||||
public function __construct(
|
|
||||||
private readonly string $entityManagerClass,
|
|
||||||
private readonly string $entityClass,
|
|
||||||
) {
|
|
||||||
var_dump($this->entityClass, $this->entityClass);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function __invoke(
|
|
||||||
ContainerInterface $container,
|
|
||||||
$requestedName,
|
|
||||||
?array $options = null
|
|
||||||
): ObjectRepository|EntityRepository
|
|
||||||
{
|
|
||||||
/** @var EntityManager $em */
|
|
||||||
$em = $container->get($this->entityManagerClass);
|
|
||||||
|
|
||||||
return $em->getRepository($this->entityClass);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -4,15 +4,23 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Template\Infrastructure\Encryption\Client;
|
namespace Template\Infrastructure\Encryption\Client;
|
||||||
|
|
||||||
|
use Laminas\Crypt\Password\Bcrypt;
|
||||||
|
|
||||||
class EncryptionClient
|
class EncryptionClient
|
||||||
{
|
{
|
||||||
|
private readonly Bcrypt $bcrypt;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
) {
|
||||||
|
$this->bcrypt = new Bcrypt();
|
||||||
|
$this->bcrypt->setCost(10);
|
||||||
|
}
|
||||||
|
|
||||||
public function encrypt(string $value): string {
|
public function encrypt(string $value): string {
|
||||||
return password_hash($value, PASSWORD_BCRYPT, [
|
return $this->bcrypt->create($value);
|
||||||
'cost' => 10
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function verify(string $value, string $encryptedValue): bool {
|
public function verify(string $value, string $encryptedValue): bool {
|
||||||
return hash_equals($encryptedValue, crypt($value, $encryptedValue));
|
return $this->bcrypt->verify($value, $encryptedValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
use Template\Infrastructure\Exception\Middleware\TemplateExceptionHandlerMiddleware;
|
use Template\Infrastructure\Exception\Middleware\ExceptionHandlerMiddleware;
|
||||||
use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
|
use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'factories' => [
|
'factories' => [
|
||||||
TemplateExceptionHandlerMiddleware::class => AutoWiringFactory::class,
|
ExceptionHandlerMiddleware::class => AutoWiringFactory::class,
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|||||||
@ -3,13 +3,10 @@
|
|||||||
namespace Template\Infrastructure\Exception;
|
namespace Template\Infrastructure\Exception;
|
||||||
|
|
||||||
enum ErrorCode : string {
|
enum ErrorCode : string {
|
||||||
case AlreadyExists = 'AlreadyExists';
|
|
||||||
case Failed = 'Failed';
|
|
||||||
case Invalid = 'Invalid';
|
|
||||||
case Maintenance = 'Maintenance';
|
|
||||||
case Mismatch = 'Mismatch';
|
|
||||||
case NotFound = 'NotFound';
|
|
||||||
case SomethingWentWrong = 'SomethingWentWrong';
|
case SomethingWentWrong = 'SomethingWentWrong';
|
||||||
|
|
||||||
|
case NotFound = 'NotFound';
|
||||||
|
case AlreadyExists = 'AlreadyExists';
|
||||||
case WrongCredentials = 'WrongCredentials';
|
case WrongCredentials = 'WrongCredentials';
|
||||||
case ValidationFailed = 'ValidationFailed';
|
case Mismatch = 'Mismatch';
|
||||||
}
|
}
|
||||||
@ -3,12 +3,11 @@
|
|||||||
namespace Template\Infrastructure\Exception;
|
namespace Template\Infrastructure\Exception;
|
||||||
|
|
||||||
enum ErrorDomain : string {
|
enum ErrorDomain : string {
|
||||||
case Schema = 'Schema';
|
|
||||||
case Generic = 'Generic';
|
case Generic = 'Generic';
|
||||||
case Mail = 'Mail';
|
|
||||||
case Notification = 'Notification';
|
|
||||||
case Registration = 'Registration';
|
|
||||||
case Role = 'Role';
|
case Role = 'Role';
|
||||||
case User = 'User';
|
case User = 'User';
|
||||||
case UserPassword = 'UserPassword';
|
case UserPassword = 'UserPassword';
|
||||||
|
case Registration = 'Registration';
|
||||||
|
case Product = 'Product';
|
||||||
}
|
}
|
||||||
@ -2,11 +2,10 @@
|
|||||||
|
|
||||||
namespace Template\Infrastructure\Exception\Exception;
|
namespace Template\Infrastructure\Exception\Exception;
|
||||||
|
|
||||||
use Exception;
|
|
||||||
use Template\Infrastructure\Exception\ErrorCode;
|
use Template\Infrastructure\Exception\ErrorCode;
|
||||||
use Template\Infrastructure\Exception\ErrorDomain;
|
use Template\Infrastructure\Exception\ErrorDomain;
|
||||||
|
|
||||||
class TemplateException extends Exception {
|
class Exception extends \Exception {
|
||||||
|
|
||||||
private readonly ErrorDomain $errorDomain;
|
private readonly ErrorDomain $errorDomain;
|
||||||
private readonly ErrorCode $errorCode;
|
private readonly ErrorCode $errorCode;
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Template\Infrastructure\Exception\Middleware;
|
||||||
|
|
||||||
|
use Template\Infrastructure\Exception\Exception\Exception;
|
||||||
|
use Template\Infrastructure\Logging\Logger\Logger;
|
||||||
|
use Template\Infrastructure\Response\ErrorResponse;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Psr\Http\Server\MiddlewareInterface;
|
||||||
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
|
|
||||||
|
class ExceptionHandlerMiddleware implements MiddlewareInterface
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly Logger $logger
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function process(
|
||||||
|
ServerRequestInterface $request,
|
||||||
|
RequestHandlerInterface $handler
|
||||||
|
): ResponseInterface
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return $handler->handle($request);
|
||||||
|
} catch (Exception $exception) {
|
||||||
|
$this->logger->exception($exception);
|
||||||
|
|
||||||
|
return new ErrorResponse(
|
||||||
|
$exception->getErrorDomain(),
|
||||||
|
$exception->getErrorCode(),
|
||||||
|
$exception->getMessage()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,71 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Template\Infrastructure\Exception\Middleware;
|
|
||||||
|
|
||||||
use League\OpenAPIValidation\PSR15\Exception\InvalidResponseMessage;
|
|
||||||
use League\OpenAPIValidation\PSR15\Exception\InvalidServerRequestMessage;
|
|
||||||
use Template\Infrastructure\Exception\ErrorCode;
|
|
||||||
use Template\Infrastructure\Exception\ErrorDomain;
|
|
||||||
use Template\Infrastructure\Exception\Exception\TemplateException;
|
|
||||||
use Template\Infrastructure\Logging\Logger\Logger;
|
|
||||||
use Template\Infrastructure\Response\ErrorResponse;
|
|
||||||
use Psr\Http\Message\ResponseInterface;
|
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
|
||||||
use Psr\Http\Server\MiddlewareInterface;
|
|
||||||
use Psr\Http\Server\RequestHandlerInterface;
|
|
||||||
|
|
||||||
class TemplateExceptionHandlerMiddleware implements MiddlewareInterface
|
|
||||||
{
|
|
||||||
public function __construct(
|
|
||||||
private readonly Logger $logger
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public function process(
|
|
||||||
ServerRequestInterface $request,
|
|
||||||
RequestHandlerInterface $handler
|
|
||||||
): ResponseInterface
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
return $handler->handle($request);
|
|
||||||
} catch (TemplateException $exception) {
|
|
||||||
$this->logger->exception($exception);
|
|
||||||
|
|
||||||
return new ErrorResponse(
|
|
||||||
$exception->getErrorDomain(),
|
|
||||||
$exception->getErrorCode(),
|
|
||||||
$exception->getMessage()
|
|
||||||
);
|
|
||||||
} catch (InvalidResponseMessage $exception) {
|
|
||||||
$this->logger->exception($exception);
|
|
||||||
|
|
||||||
|
|
||||||
$lines = [];
|
|
||||||
do {
|
|
||||||
$lines[] = $exception->getMessage();
|
|
||||||
$exception = $exception->getPrevious();
|
|
||||||
} while ($exception->getPrevious() !== null);
|
|
||||||
|
|
||||||
return new ErrorResponse(
|
|
||||||
ErrorDomain::Schema,
|
|
||||||
ErrorCode::ValidationFailed,
|
|
||||||
implode(PHP_EOL, $lines)
|
|
||||||
);
|
|
||||||
} catch (InvalidServerRequestMessage $exception) {
|
|
||||||
$this->logger->exception($exception);
|
|
||||||
|
|
||||||
|
|
||||||
$lines = [];
|
|
||||||
do {
|
|
||||||
$lines[] = $exception->getMessage();
|
|
||||||
$exception = $exception->getPrevious();
|
|
||||||
} while ($exception->getPrevious() !== null);
|
|
||||||
|
|
||||||
return new ErrorResponse(
|
|
||||||
ErrorDomain::Schema,
|
|
||||||
ErrorCode::ValidationFailed,
|
|
||||||
implode(PHP_EOL, $lines)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -2,10 +2,8 @@
|
|||||||
|
|
||||||
namespace Template\Infrastructure\Logging\Logger;
|
namespace Template\Infrastructure\Logging\Logger;
|
||||||
|
|
||||||
use Template\Infrastructure\Exception\Exception\TemplateException;
|
use Template\Infrastructure\Exception\Exception\Exception;
|
||||||
use Template\Infrastructure\Logging\Handler\FileStreamHandler;
|
|
||||||
use Monolog\ErrorHandler;
|
use Monolog\ErrorHandler;
|
||||||
use Monolog\Handler\StreamHandler;
|
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
use Stringable;
|
use Stringable;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
@ -26,7 +24,7 @@ class Logger implements LoggerInterface
|
|||||||
'trace' => $exception->getTraceAsString()
|
'trace' => $exception->getTraceAsString()
|
||||||
]*/;
|
]*/;
|
||||||
|
|
||||||
if ($exception instanceof TemplateException) {
|
if ($exception instanceof Exception) {
|
||||||
$exceptionContext = array_merge([
|
$exceptionContext = array_merge([
|
||||||
'errorDomain' => $exception->getErrorDomain()->value,
|
'errorDomain' => $exception->getErrorDomain()->value,
|
||||||
'errorCode' => $exception->getErrorCode()->value,
|
'errorCode' => $exception->getErrorCode()->value,
|
||||||
|
|||||||
@ -1,12 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
|
|
||||||
use Template\Infrastructure\Mail\Service\MailService;
|
|
||||||
|
|
||||||
return [
|
|
||||||
'factories' => [
|
|
||||||
MailService::class => AutoWiringFactory::class,
|
|
||||||
],
|
|
||||||
];
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Template\Infrastructure\Mail;
|
|
||||||
|
|
||||||
class ConfigProvider
|
|
||||||
{
|
|
||||||
public function __invoke(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'dependencies' => require __DIR__ . './../config/service_manager.php',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Template\Infrastructure\Mail\Exception;
|
|
||||||
|
|
||||||
use Throwable;
|
|
||||||
use Template\Infrastructure\Exception\ErrorCode;
|
|
||||||
use Template\Infrastructure\Exception\ErrorDomain;
|
|
||||||
use Template\Infrastructure\Exception\Exception\TemplateException;
|
|
||||||
|
|
||||||
class SendMailFailedException extends TemplateException
|
|
||||||
{
|
|
||||||
private const MESSAGE = 'Das Mail template %s konnte mit den Daten {%s} nicht an %s gesendet werden. Grund: %s';
|
|
||||||
|
|
||||||
public function __construct(
|
|
||||||
string $templateIdentification,
|
|
||||||
array $templateData,
|
|
||||||
string $recipient,
|
|
||||||
Throwable $reason,
|
|
||||||
) {
|
|
||||||
parent::__construct(
|
|
||||||
sprintf(
|
|
||||||
self::MESSAGE,
|
|
||||||
$templateIdentification,
|
|
||||||
json_encode($templateData),
|
|
||||||
$recipient,
|
|
||||||
$reason->getMessage(),
|
|
||||||
),
|
|
||||||
ErrorDomain::Mail,
|
|
||||||
ErrorCode::Failed
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,176 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Template\Infrastructure\Mail\Service;
|
|
||||||
|
|
||||||
use Template\Data\Business\Entity\Mail;
|
|
||||||
use Template\Data\Business\Manager\EntityManager;
|
|
||||||
use Template\Data\Business\Repository\MailRepository;
|
|
||||||
use DateTime;
|
|
||||||
use Exception;
|
|
||||||
use Latte\Engine;
|
|
||||||
use Nette\Mail\Mailer;
|
|
||||||
use Nette\Mail\Message;
|
|
||||||
use Nette\Mail\SmtpMailer;
|
|
||||||
use Reinfi\DependencyInjection\Service\ConfigService;
|
|
||||||
use Throwable;
|
|
||||||
use Template\Infrastructure\Logging\Logger\Logger;
|
|
||||||
use Template\Infrastructure\Mail\Exception\SendMailFailedException;
|
|
||||||
|
|
||||||
class MailService
|
|
||||||
{
|
|
||||||
private const TEMPLATE_PATH = APP_ROOT . '/data/mails/';
|
|
||||||
private readonly Engine $engine;
|
|
||||||
private readonly MailRepository $mailRepository;
|
|
||||||
|
|
||||||
public function __construct(
|
|
||||||
private readonly EntityManager $entityManager,
|
|
||||||
private readonly ConfigService $configService,
|
|
||||||
private readonly Logger $logger,
|
|
||||||
) {
|
|
||||||
$this->engine = new Engine();
|
|
||||||
|
|
||||||
$this->mailRepository = $this->entityManager->getRepository(Mail::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function enqueue(
|
|
||||||
string $template,
|
|
||||||
array $templateData,
|
|
||||||
string $recipient,
|
|
||||||
?string $sender = null,
|
|
||||||
?string $senderName = null
|
|
||||||
): void {
|
|
||||||
$mail = new Mail();
|
|
||||||
$mail->setTemplate($template);
|
|
||||||
$mail->setData($templateData);
|
|
||||||
$mail->setRecipient($recipient);
|
|
||||||
$mail->setSender($sender);
|
|
||||||
$mail->setSenderName($senderName);
|
|
||||||
|
|
||||||
$this->entityManager->persist($mail);
|
|
||||||
$this->entityManager->flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function send(?int $count = null): void {
|
|
||||||
$qb = $this->mailRepository->createQueryBuilder('m');
|
|
||||||
$qb->orderBy('m.createdAt', 'asc');
|
|
||||||
|
|
||||||
if ($count !== null) {
|
|
||||||
$qb->setMaxResults($count);
|
|
||||||
}
|
|
||||||
|
|
||||||
$mailsToSend = $qb->getQuery()->execute();
|
|
||||||
|
|
||||||
/** @var Mail $mailToSend */
|
|
||||||
foreach ($mailsToSend as $mailToSend) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
$this->sendMail(
|
|
||||||
$mailToSend->getTemplate(),
|
|
||||||
$mailToSend->getData(),
|
|
||||||
$mailToSend->getRecipient(),
|
|
||||||
$mailToSend->getSender(),
|
|
||||||
$mailToSend->getSenderName(),
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->entityManager->remove($mailToSend);
|
|
||||||
} catch (SendMailFailedException $e) {
|
|
||||||
// log is done withing sendMail
|
|
||||||
$mailToSend->setFailedAt(new DateTime());
|
|
||||||
$this->entityManager->persist($mailToSend);
|
|
||||||
}
|
|
||||||
$this->entityManager->flush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws SendMailFailedException
|
|
||||||
*/
|
|
||||||
private function sendMail(
|
|
||||||
string $template,
|
|
||||||
array $templateData,
|
|
||||||
string $recipient,
|
|
||||||
?string $sender = null,
|
|
||||||
?string $senderName = null
|
|
||||||
): void {
|
|
||||||
try {
|
|
||||||
$mail = $this->getMail(
|
|
||||||
template: $template,
|
|
||||||
templateData: $templateData,
|
|
||||||
recipient: $recipient,
|
|
||||||
sender: $sender,
|
|
||||||
senderName: $senderName
|
|
||||||
);
|
|
||||||
|
|
||||||
$mailer = $this->getMailer();
|
|
||||||
|
|
||||||
$mailer->send($mail);
|
|
||||||
} catch (Throwable $e) {
|
|
||||||
$this->logger->exception($e);
|
|
||||||
|
|
||||||
throw new SendMailFailedException(
|
|
||||||
$template,
|
|
||||||
$templateData,
|
|
||||||
$recipient,
|
|
||||||
$e
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getMailer(): Mailer
|
|
||||||
{
|
|
||||||
$smtpConfig = $this->configService->resolve('mail.smtp-server');
|
|
||||||
|
|
||||||
return new SmtpMailer(
|
|
||||||
host: $smtpConfig['host'],
|
|
||||||
username: $smtpConfig['username'],
|
|
||||||
password: $smtpConfig['password'],
|
|
||||||
encryption: $smtpConfig['encryption'],
|
|
||||||
port: $smtpConfig['port'],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getMail(
|
|
||||||
string $template,
|
|
||||||
array $templateData,
|
|
||||||
string $recipient,
|
|
||||||
?string $sender = null,
|
|
||||||
?string $senderName = null
|
|
||||||
): Message {
|
|
||||||
$templatePath = self::TEMPLATE_PATH . $template . '/template.latte';
|
|
||||||
$assetsPath = self::TEMPLATE_PATH . $template . "/";
|
|
||||||
|
|
||||||
if (!file_exists($templatePath)) {
|
|
||||||
throw new Exception("Template File does not exist");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_dir($assetsPath)) {
|
|
||||||
$assetsPath = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$mail = new Message();
|
|
||||||
$mail->setFrom($this->getSenderName($sender, $senderName));
|
|
||||||
$mail->addTo($recipient);
|
|
||||||
$mail->setHtmlBody(
|
|
||||||
$this->engine->renderToString(
|
|
||||||
$templatePath,
|
|
||||||
$templateData,
|
|
||||||
),
|
|
||||||
$assetsPath
|
|
||||||
);
|
|
||||||
|
|
||||||
return $mail;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getSenderName(
|
|
||||||
?string $sender,
|
|
||||||
?string $senderName
|
|
||||||
): string {
|
|
||||||
$defaultConfig = $this->configService->resolve('mail.default');
|
|
||||||
|
|
||||||
$from = $sender ?? $defaultConfig['sender'] ?? throw new Exception('Could not determine Sender');
|
|
||||||
$name =$sender ?? $defaultConfig['senderName'] ?? throw new Exception('Could not determine Sender Name');
|
|
||||||
return sprintf('%s <%s>', $name, $from);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
|
|
||||||
use Template\Infrastructure\Notification\Service\NotificationService;
|
|
||||||
|
|
||||||
return [
|
|
||||||
'factories' => [
|
|
||||||
NotificationService::class => AutoWiringFactory::class,
|
|
||||||
],
|
|
||||||
];
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Template\Infrastructure\Notification;
|
|
||||||
|
|
||||||
class ConfigProvider
|
|
||||||
{
|
|
||||||
public function __invoke(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'dependencies' => require __DIR__ . './../config/service_manager.php',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,26 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Template\Infrastructure\Notification\Exception;
|
|
||||||
|
|
||||||
use Throwable;
|
|
||||||
use Template\Infrastructure\Exception\ErrorCode;
|
|
||||||
use Template\Infrastructure\Exception\ErrorDomain;
|
|
||||||
use Template\Infrastructure\Exception\Exception\TemplateException;
|
|
||||||
|
|
||||||
class SendNotificationFailed extends TemplateException
|
|
||||||
{
|
|
||||||
private const MESSAGE = 'Notification could not be sent. Reason: %s';
|
|
||||||
|
|
||||||
public function __construct(
|
|
||||||
Throwable $reason,
|
|
||||||
) {
|
|
||||||
parent::__construct(
|
|
||||||
sprintf(
|
|
||||||
self::MESSAGE,
|
|
||||||
$reason->getMessage(),
|
|
||||||
),
|
|
||||||
ErrorDomain::Notification,
|
|
||||||
ErrorCode::Failed
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,55 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Template\Infrastructure\Notification\Service;
|
|
||||||
|
|
||||||
use Exception;
|
|
||||||
use Reinfi\DependencyInjection\Service\ConfigService;
|
|
||||||
use Throwable;
|
|
||||||
use Template\Infrastructure\Notification\Exception\SendNotificationFailed;
|
|
||||||
|
|
||||||
class NotificationService
|
|
||||||
{
|
|
||||||
private string $defaultTitle;
|
|
||||||
private ?string $host;
|
|
||||||
private ?string $id;
|
|
||||||
|
|
||||||
public function __construct(
|
|
||||||
private readonly ConfigService $configService,
|
|
||||||
) {
|
|
||||||
$config = $this->configService->resolve('notification');
|
|
||||||
$this->defaultTitle = $config['defaultTitle'];
|
|
||||||
$this->host = $config['host'] ?? '';
|
|
||||||
$this->id = $config['id'] ?? '';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws SendNotificationFailed
|
|
||||||
*/
|
|
||||||
public function push(
|
|
||||||
string $message,
|
|
||||||
string $title = null,
|
|
||||||
): void {
|
|
||||||
try {
|
|
||||||
if (($this->id ?? '') === '') {
|
|
||||||
throw new Exception('Notification ID is not set.');
|
|
||||||
}
|
|
||||||
if (($this->host ?? '') === '') {
|
|
||||||
throw new Exception('Notification Host is not set.');
|
|
||||||
}
|
|
||||||
|
|
||||||
$command = sprintf(
|
|
||||||
'curl -H "Title: %s" -H "Tags: broccoli" -d "%s" %s/%s',
|
|
||||||
$title ?? $this->defaultTitle,
|
|
||||||
$message,
|
|
||||||
$this->host,
|
|
||||||
$this->id
|
|
||||||
);
|
|
||||||
|
|
||||||
shell_exec($command);
|
|
||||||
} catch (Throwable $e) {
|
|
||||||
throw new SendNotificationFailed($e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -56,8 +56,7 @@ class EnsureAuthorizationMiddleware implements MiddlewareInterface
|
|||||||
): bool {
|
): bool {
|
||||||
$role = $user->getRole();
|
$role = $user->getRole();
|
||||||
$permissions = $role->getPermissions();
|
$permissions = $role->getPermissions();
|
||||||
|
$targetApi = $this->routes[$targetPath];
|
||||||
$targetApi = $this->routes[$targetPath] ?? null;
|
|
||||||
|
|
||||||
/** @var Permission $permission */
|
/** @var Permission $permission */
|
||||||
foreach($permissions as $permission) {
|
foreach($permissions as $permission) {
|
||||||
|
|||||||
@ -2,14 +2,12 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
use Template\Infrastructure\Rbac\Middleware\EnsureAuthorizationMiddleware;
|
use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
|
||||||
use Template\Infrastructure\Request\Factory\RequestServiceFactory;
|
use Template\Infrastructure\Request\Factory\RequestServiceFactory;
|
||||||
use Template\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
|
use Template\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
|
||||||
use Template\Infrastructure\Request\Middleware\AnalyzeHeaderMiddleware;
|
use Template\Infrastructure\Request\Middleware\AnalyzeHeaderMiddleware;
|
||||||
use Template\Infrastructure\Request\Middleware\InternalRequestMiddleware;
|
use Template\Infrastructure\Request\Middleware\InternalRequestMiddleware;
|
||||||
use Template\Infrastructure\Request\Service\RequestService;
|
use Template\Infrastructure\Request\Service\RequestService;
|
||||||
use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
|
|
||||||
use Reinfi\DependencyInjection\Factory\InjectionFactory;
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'factories' => [
|
'factories' => [
|
||||||
|
|||||||
@ -2,10 +2,16 @@
|
|||||||
|
|
||||||
namespace Template\Infrastructure\Request\Middleware;
|
namespace Template\Infrastructure\Request\Middleware;
|
||||||
|
|
||||||
|
use Template\Data\Business\Entity\Permission;
|
||||||
|
use Template\Data\Business\Entity\User;
|
||||||
|
use Template\Infrastructure\Response\ForbiddenResponse;
|
||||||
|
use Template\Infrastructure\Session\Middleware\LoggedInUserMiddleware;
|
||||||
|
use Laminas\Config\Config;
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
use Psr\Http\Server\MiddlewareInterface;
|
use Psr\Http\Server\MiddlewareInterface;
|
||||||
use Psr\Http\Server\RequestHandlerInterface;
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
|
use Reinfi\DependencyInjection\Annotation\InjectConfig;
|
||||||
|
|
||||||
class AnalyzeBodyMiddleware implements MiddlewareInterface
|
class AnalyzeBodyMiddleware implements MiddlewareInterface
|
||||||
{
|
{
|
||||||
@ -27,8 +33,6 @@ class AnalyzeBodyMiddleware implements MiddlewareInterface
|
|||||||
$request->getBody()->getContents(),
|
$request->getBody()->getContents(),
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
|
||||||
$request->getBody()->rewind();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $handler->handle($request->withAttribute(
|
return $handler->handle($request->withAttribute(
|
||||||
|
|||||||
@ -2,47 +2,36 @@
|
|||||||
|
|
||||||
namespace Template\Infrastructure\Request\Middleware;
|
namespace Template\Infrastructure\Request\Middleware;
|
||||||
|
|
||||||
|
use Template\Data\Business\Entity\Permission;
|
||||||
|
use Template\Data\Business\Entity\User;
|
||||||
|
use Template\Infrastructure\Response\ForbiddenResponse;
|
||||||
|
use Template\Infrastructure\Session\Middleware\LoggedInUserMiddleware;
|
||||||
|
use Laminas\Config\Config;
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
use Psr\Http\Server\MiddlewareInterface;
|
use Psr\Http\Server\MiddlewareInterface;
|
||||||
use Psr\Http\Server\RequestHandlerInterface;
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
|
use Reinfi\DependencyInjection\Annotation\InjectConfig;
|
||||||
|
|
||||||
class AnalyzeHeaderMiddleware implements MiddlewareInterface
|
class AnalyzeHeaderMiddleware implements MiddlewareInterface
|
||||||
{
|
{
|
||||||
public const HOST_ATTRIBUTE = 'host_attribute';
|
const HOST_ATTRIBUTE = 'host_attribute';
|
||||||
public const CONTENT_TYPE_ATTRIBUTE = 'content_type_attribute';
|
|
||||||
|
|
||||||
private const CONTENT_TYPE_HEADER_KEY = 'Content-Type';
|
|
||||||
private const HOST_HEADER_KEY = 'host';
|
|
||||||
private const FORWARDED_HOST_HEADER_KEY = 'x-forwarded-host';
|
|
||||||
|
|
||||||
public function process(
|
public function process(
|
||||||
ServerRequestInterface $request,
|
ServerRequestInterface $request,
|
||||||
RequestHandlerInterface $handler
|
RequestHandlerInterface $handler
|
||||||
): ResponseInterface
|
): ResponseInterface
|
||||||
{
|
{
|
||||||
$headers = $request->getHeaders();
|
|
||||||
|
|
||||||
$contentType = $this->readHeader($headers, self::CONTENT_TYPE_HEADER_KEY) ?? null;
|
|
||||||
$host = explode(
|
$host = explode(
|
||||||
':',
|
':',
|
||||||
$this->readHeader($headers, self::HOST_HEADER_KEY) ??
|
$request->getHeaders()['host'][0]
|
||||||
$this->readHeader($headers, self::FORWARDED_HOST_HEADER_KEY) ??
|
?? $request->getHeaders()['x-forwarded-host'][0]
|
||||||
'UNKNOWN'
|
?? 'UNKNOWN'
|
||||||
)[0];
|
)[0];
|
||||||
|
|
||||||
return $handler->handle(
|
return $handler->handle($request->withAttribute(
|
||||||
$request
|
self::HOST_ATTRIBUTE,
|
||||||
->withAttribute(self::HOST_ATTRIBUTE, $host)
|
$host
|
||||||
->withAttribute(self::CONTENT_TYPE_ATTRIBUTE, $contentType)
|
));
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function readHeader(array $header, string $key): mixed
|
|
||||||
{
|
|
||||||
return
|
|
||||||
($header[$key] ??
|
|
||||||
$header[strtolower($key)] ??
|
|
||||||
$header[strtoupper($key)] ?? [])[0] ?? null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7,13 +7,9 @@ use Laminas\Diactoros\Response\JsonResponse;
|
|||||||
class SuccessResponse extends JsonResponse
|
class SuccessResponse extends JsonResponse
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
mixed $data = 'Success'
|
mixed $data = 'OK'
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if ($data === []) {
|
|
||||||
$data = 'Success';
|
|
||||||
}
|
|
||||||
|
|
||||||
parent::__construct(
|
parent::__construct(
|
||||||
$data
|
$data
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,41 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
use cebe\openapi\spec\OpenApi;
|
|
||||||
use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
|
|
||||||
use Template\Infrastructure\Schema\Exporter\Backend\Builder\ClassFileBuilder;
|
|
||||||
use Template\Infrastructure\Schema\Exporter\BackendExporter;
|
|
||||||
use Template\Infrastructure\Schema\Exporter\Frontend\Builder\PropertyBuilder as FrontendPropertyBuilder;
|
|
||||||
use Template\Infrastructure\Schema\Exporter\Backend\Builder\PropertyBuilder as BackendPropertyBuilder;
|
|
||||||
use Template\Infrastructure\Schema\Exporter\Frontend\Builder\ServiceBuilder;
|
|
||||||
use Template\Infrastructure\Schema\Exporter\Frontend\Builder\TypeBuilder as FrontendTypeBuilder;
|
|
||||||
use Template\Infrastructure\Schema\Exporter\Backend\Builder\TypeBuilder as BackendTypeBuilder;;
|
|
||||||
use Template\Infrastructure\Schema\Exporter\FrontendExporter;
|
|
||||||
use Template\Infrastructure\Schema\Factory\OpenApiFactory;
|
|
||||||
use Template\Infrastructure\Schema\Middleware\SchemaValidationMiddleware;
|
|
||||||
use Template\Infrastructure\Schema\Reader\ApiDefinitionReader;
|
|
||||||
|
|
||||||
return [
|
|
||||||
'factories' => [
|
|
||||||
OpenApi::class => OpenApiFactory::class,
|
|
||||||
|
|
||||||
/// Reader
|
|
||||||
ApiDefinitionReader::class => AutoWiringFactory::class,
|
|
||||||
|
|
||||||
/// Middleware
|
|
||||||
SchemaValidationMiddleware::class => AutoWiringFactory::class,
|
|
||||||
|
|
||||||
/// Exporter
|
|
||||||
// Backend
|
|
||||||
BackendExporter::class => AutoWiringFactory::class,
|
|
||||||
ClassFileBuilder::class => AutoWiringFactory::class,
|
|
||||||
BackendPropertyBuilder::class => AutoWiringFactory::class,
|
|
||||||
BackendTypeBuilder::class => AutoWiringFactory::class,
|
|
||||||
// Frontend
|
|
||||||
FrontendExporter::class => AutoWiringFactory::class,
|
|
||||||
ServiceBuilder::class => AutoWiringFactory::class,
|
|
||||||
FrontendTypeBuilder::class => AutoWiringFactory::class,
|
|
||||||
FrontendPropertyBuilder::class => AutoWiringFactory::class,
|
|
||||||
],
|
|
||||||
];
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user