Compare commits
6 Commits
1df825db2a
...
a5dffa065a
| Author | SHA1 | Date | |
|---|---|---|---|
| a5dffa065a | |||
| 8ca2d350e8 | |||
| cfa750aff2 | |||
| 7a96e5175d | |||
| 56fa3c512e | |||
| cc989e96f7 |
@ -8,11 +8,7 @@ DB_NAME=template
|
||||
DB_NAME_LOG=log
|
||||
|
||||
# API Keys
|
||||
AUTH_API_KEY=
|
||||
NOTIFICATION_API_KEY=
|
||||
FILE_API_KEY=
|
||||
HOMEPAGE_API_KEY=
|
||||
BEE_API_KEY=
|
||||
TEMPLATE_API_KEY=
|
||||
|
||||
# Template Setup
|
||||
INIT_USER_NAME=admin
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@ -11,6 +11,8 @@
|
||||
/var/
|
||||
/vendor/
|
||||
|
||||
docker/docker-compose.yml
|
||||
|
||||
*.env
|
||||
composer.lock
|
||||
composer.development.json
|
||||
|
||||
@ -201,8 +201,8 @@ use Psr\\Http\\Server\\RequestHandlerInterface;
|
||||
class {$apiHandlerName} implements RequestHandlerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private readonly {$cqrsHandlerName} \${$cqrsHandlerVariableName},
|
||||
private readonly {$cqrsBuilderName} \${$cqrsBuilderVariableName},
|
||||
private readonly {$cqrsHandlerName} \$handler,
|
||||
private readonly {$cqrsBuilderName} \$builder,
|
||||
private readonly {$apiResponseFormatterName} \$responseFormatter,
|
||||
) {
|
||||
}
|
||||
@ -211,10 +211,10 @@ class {$apiHandlerName} implements RequestHandlerInterface
|
||||
{
|
||||
\$data = \$request->getAttribute(AnalyzeBodyMiddleware::JSON_DATA);
|
||||
|
||||
\${$cqrsVariableName} = \$this->{$cqrsBuilderVariableName}->build(
|
||||
\${$cqrsVariableName} = \$this->builder->build(
|
||||
\$data
|
||||
);
|
||||
\$result = \$this->{$cqrsHandlerVariableName}->execute(\${$cqrsVariableName});
|
||||
\$result = \$this->handler->execute(\${$cqrsVariableName});
|
||||
|
||||
return new SuccessResponse(\$this->responseFormatter->format(\$result));
|
||||
}
|
||||
@ -275,9 +275,7 @@ class {$cqrsHandlerName}
|
||||
|
||||
public function execute({$cqrsName} \${$cqrsVariableName}): {$cqrsResultName}
|
||||
{
|
||||
return new {$cqrsResultName}(
|
||||
|
||||
);
|
||||
return new {$cqrsResultName}();
|
||||
}
|
||||
}
|
||||
";
|
||||
|
||||
30
bin/script/firstRun
Executable file
30
bin/script/firstRun
Executable file
@ -0,0 +1,30 @@
|
||||
#!/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,54 +3,16 @@
|
||||
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||
PROJECT_DIR=$(realpath $SCRIPT_DIR/../../)
|
||||
ENV_DIR=$(realpath $PROJECT_DIR/../../../)
|
||||
|
||||
EXIT=0
|
||||
source $ENV_DIR/bin/denv_msg
|
||||
|
||||
# Check .env file
|
||||
if [ ! -f "$PROJECT_DIR/.env" ]
|
||||
then
|
||||
if [ ! -f "$PROJECT_DIR/.env" ] ; then
|
||||
cp "$PROJECT_DIR/.env.example" "$PROJECT_DIR/.env"
|
||||
EXIT=1
|
||||
denv_info_msg "[backend] Created .env"
|
||||
fi
|
||||
|
||||
# Check docker-compose.yml file
|
||||
if [ ! -f "$PROJECT_DIR/docker/docker-compose.yml" ]
|
||||
then
|
||||
if [ ! -f "$PROJECT_DIR/docker/docker-compose.yml" ] ; then
|
||||
cp "$PROJECT_DIR/docker/docker-compose.yml.dist" "$PROJECT_DIR/docker/docker-compose.yml"
|
||||
EXIT=1
|
||||
denv_info_msg "[backend] Created docker-compose.yml"
|
||||
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
|
||||
39
bin/script/update
Executable file
39
bin/script/update
Executable file
@ -0,0 +1,39 @@
|
||||
#!/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,26 +3,7 @@
|
||||
return [
|
||||
'api' => [
|
||||
'keys' => [
|
||||
'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'
|
||||
],
|
||||
],
|
||||
],
|
||||
'template' => $_ENV['TEMPLATE_API_KEY'],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
@ -10,7 +10,8 @@ return [
|
||||
'user' => [
|
||||
],
|
||||
'admin' => [
|
||||
'user.create-user',
|
||||
'user.create',
|
||||
'user.read-list',
|
||||
],
|
||||
]
|
||||
]
|
||||
|
||||
17
config/autoload/mail.global.php
Normal file
17
config/autoload/mail.global.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?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'],
|
||||
]
|
||||
]
|
||||
];
|
||||
9
config/autoload/notification.global.php
Normal file
9
config/autoload/notification.global.php
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'notification' => [
|
||||
'defaultTitle' => $_ENV['NOTIFICATION_DEFAULT_TITLE'] ?? 'Template',
|
||||
'host' => $_ENV['NOTIFICATION_HOST'],
|
||||
'id' => $_ENV['NOTIFICATION_ID'],
|
||||
]
|
||||
];
|
||||
@ -52,6 +52,9 @@ $aggregator = new ConfigAggregator([
|
||||
\Template\Infrastructure\Rbac\ConfigProvider::class,
|
||||
\Template\Infrastructure\Request\ConfigProvider::class,
|
||||
\Template\Infrastructure\Session\ConfigProvider::class,
|
||||
\Template\Infrastructure\Mail\ConfigProvider::class,
|
||||
\Template\Infrastructure\Notification\ConfigProvider::class,
|
||||
\Template\Infrastructure\Schema\ConfigProvider::class,
|
||||
|
||||
// HandlingDomain
|
||||
\Template\Handling\User\ConfigProvider::class,
|
||||
@ -63,7 +66,7 @@ $aggregator = new ConfigAggregator([
|
||||
\Template\API\Console\ConfigProvider::class,
|
||||
|
||||
/// External
|
||||
\Template\API\External\Health\ConfigProvider::class,
|
||||
\Template\API\External\Api\ConfigProvider::class,
|
||||
\Template\API\External\User\ConfigProvider::class,
|
||||
\Template\API\External\Authentication\ConfigProvider::class,
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Template\Infrastructure\Exception\Middleware\ExceptionHandlerMiddleware;
|
||||
use Template\Infrastructure\Exception\Middleware\TemplateExceptionHandlerMiddleware;
|
||||
use Template\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
|
||||
use Template\Infrastructure\Request\Middleware\AnalyzeHeaderMiddleware;
|
||||
use Template\Infrastructure\Session\Middleware\SessionMiddleware;
|
||||
@ -68,7 +68,7 @@ return function (Application $app, MiddlewareFactory $factory, ContainerInterfac
|
||||
|
||||
|
||||
//// Pre Template Space
|
||||
$app->pipe(ExceptionHandlerMiddleware::class);
|
||||
$app->pipe(TemplateExceptionHandlerMiddleware::class);
|
||||
$app->pipe(AnalyzeHeaderMiddleware::class);
|
||||
$app->pipe(AnalyzeBodyMiddleware::class);
|
||||
|
||||
|
||||
BIN
data/mails/registration/assets/icon.png
Normal file
BIN
data/mails/registration/assets/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
66
data/mails/registration/template.latte
Normal file
66
data/mails/registration/template.latte
Normal file
@ -0,0 +1,66 @@
|
||||
<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>
|
||||
BIN
data/mails/reset-password/assets/icon.png
Normal file
BIN
data/mails/reset-password/assets/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
63
data/mails/reset-password/template.latte
Normal file
63
data/mails/reset-password/template.latte
Normal file
@ -0,0 +1,63 @@
|
||||
<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>
|
||||
37
data/migrations/template/Version20240827155813.php
Normal file
37
data/migrations/template/Version20240827155813.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?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;");
|
||||
}
|
||||
}
|
||||
41
data/migrations/template/Version20240911191301.php
Normal file
41
data/migrations/template/Version20240911191301.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?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;");
|
||||
}
|
||||
}
|
||||
@ -1,52 +0,0 @@
|
||||
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
|
||||
13
src/ApiDomain/Schema/External/Api/Health/request.json
vendored
Normal file
13
src/ApiDomain/Schema/External/Api/Health/request.json
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"get": {
|
||||
"description": "Checks the health of the API backend",
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "./response.json"
|
||||
},
|
||||
"default": {
|
||||
"$ref": "../../../Partials/Response/bad-request.json"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
10
src/ApiDomain/Schema/External/Api/Health/response.json
vendored
Normal file
10
src/ApiDomain/Schema/External/Api/Health/response.json
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"description": "Successfully checked the health of the API backend",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
13
src/ApiDomain/Schema/External/Api/Schema/request.json
vendored
Normal file
13
src/ApiDomain/Schema/External/Api/Schema/request.json
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"get": {
|
||||
"description": "Reads the current schema definition",
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "./response.json"
|
||||
},
|
||||
"default": {
|
||||
"$ref": "../../../Partials/Response/bad-request.json"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
16
src/ApiDomain/Schema/External/Api/Schema/response.json
vendored
Normal file
16
src/ApiDomain/Schema/External/Api/Schema/response.json
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"description": "Successfully read the schema definition",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"openapi",
|
||||
"info",
|
||||
"paths",
|
||||
"components"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
44
src/ApiDomain/Schema/External/Authentication/ConfirmRegistration/request.json
vendored
Normal file
44
src/ApiDomain/Schema/External/Authentication/ConfirmRegistration/request.json
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
34
src/ApiDomain/Schema/External/Authentication/ConfirmRegistration/response.json
vendored
Normal file
34
src/ApiDomain/Schema/External/Authentication/ConfirmRegistration/response.json
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
36
src/ApiDomain/Schema/External/Authentication/ForgotPassword/request.json
vendored
Normal file
36
src/ApiDomain/Schema/External/Authentication/ForgotPassword/request.json
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
9
src/ApiDomain/Schema/External/Authentication/ForgotPassword/response.json
vendored
Normal file
9
src/ApiDomain/Schema/External/Authentication/ForgotPassword/response.json
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"description": "Password reset mail successfully sent",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
40
src/ApiDomain/Schema/External/Authentication/Login/request.json
vendored
Normal file
40
src/ApiDomain/Schema/External/Authentication/Login/request.json
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
18
src/ApiDomain/Schema/External/Authentication/Login/response.json
vendored
Normal file
18
src/ApiDomain/Schema/External/Authentication/Login/response.json
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"description": "User successfully logged in",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"sessionId"
|
||||
],
|
||||
"properties": {
|
||||
"sessionId": {
|
||||
"$ref": "../../../Partials/uuid.json"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
19
src/ApiDomain/Schema/External/Authentication/Logout/request.json
vendored
Normal file
19
src/ApiDomain/Schema/External/Authentication/Logout/request.json
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
10
src/ApiDomain/Schema/External/Authentication/Logout/response.json
vendored
Normal file
10
src/ApiDomain/Schema/External/Authentication/Logout/response.json
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"description": "User successfully logged out",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
5
src/ApiDomain/Schema/External/Authentication/Partials/identifier.json
vendored
Normal file
5
src/ApiDomain/Schema/External/Authentication/Partials/identifier.json
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"description": "The identifier for the user. May be a mail address or a username",
|
||||
"example": "max.mustermann@example.com",
|
||||
"type": "string"
|
||||
}
|
||||
6
src/ApiDomain/Schema/External/Authentication/Partials/mail.json
vendored
Normal file
6
src/ApiDomain/Schema/External/Authentication/Partials/mail.json
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"description": "The mail address of a user",
|
||||
"example": "max.mustermann@example.com",
|
||||
"type": "string",
|
||||
"format": "email"
|
||||
}
|
||||
5
src/ApiDomain/Schema/External/Authentication/Partials/password.json
vendored
Normal file
5
src/ApiDomain/Schema/External/Authentication/Partials/password.json
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"description": "The password for an account",
|
||||
"example": "Password123!",
|
||||
"type": "string"
|
||||
}
|
||||
9
src/ApiDomain/Schema/External/Authentication/Partials/role-identifier.json
vendored
Normal file
9
src/ApiDomain/Schema/External/Authentication/Partials/role-identifier.json
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"description": "A role identifier",
|
||||
"example": "admin",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"admin",
|
||||
"user"
|
||||
]
|
||||
}
|
||||
5
src/ApiDomain/Schema/External/Authentication/Partials/username.json
vendored
Normal file
5
src/ApiDomain/Schema/External/Authentication/Partials/username.json
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"description": "The username of a user",
|
||||
"example": "max.mustermann",
|
||||
"type": "string"
|
||||
}
|
||||
40
src/ApiDomain/Schema/External/Authentication/RegisterUser/request.json
vendored
Normal file
40
src/ApiDomain/Schema/External/Authentication/RegisterUser/request.json
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
10
src/ApiDomain/Schema/External/Authentication/RegisterUser/response.json
vendored
Normal file
10
src/ApiDomain/Schema/External/Authentication/RegisterUser/response.json
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"description": "Successfully created the registration",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
44
src/ApiDomain/Schema/External/Authentication/ResetPassword/request.json
vendored
Normal file
44
src/ApiDomain/Schema/External/Authentication/ResetPassword/request.json
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
9
src/ApiDomain/Schema/External/Authentication/ResetPassword/response.json
vendored
Normal file
9
src/ApiDomain/Schema/External/Authentication/ResetPassword/response.json
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"description": "Successfully set new password",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
40
src/ApiDomain/Schema/External/User/ChangePassword/request.json
vendored
Normal file
40
src/ApiDomain/Schema/External/User/ChangePassword/request.json
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
9
src/ApiDomain/Schema/External/User/ChangePassword/response.json
vendored
Normal file
9
src/ApiDomain/Schema/External/User/ChangePassword/response.json
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"description": "Successfully changed the password",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
40
src/ApiDomain/Schema/External/User/ChangeUsername/request.json
vendored
Normal file
40
src/ApiDomain/Schema/External/User/ChangeUsername/request.json
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
9
src/ApiDomain/Schema/External/User/ChangeUsername/response.json
vendored
Normal file
9
src/ApiDomain/Schema/External/User/ChangeUsername/response.json
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"description": "Successfully changed the username",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
44
src/ApiDomain/Schema/External/User/Create/request.json
vendored
Normal file
44
src/ApiDomain/Schema/External/User/Create/request.json
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
42
src/ApiDomain/Schema/External/User/Create/response.json
vendored
Normal file
42
src/ApiDomain/Schema/External/User/Create/response.json
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
44
src/ApiDomain/Schema/External/User/ReadList/request.json
vendored
Normal file
44
src/ApiDomain/Schema/External/User/ReadList/request.json
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
50
src/ApiDomain/Schema/External/User/ReadList/response.json
vendored
Normal file
50
src/ApiDomain/Schema/External/User/ReadList/response.json
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
19
src/ApiDomain/Schema/External/User/UserState/request.json
vendored
Normal file
19
src/ApiDomain/Schema/External/User/UserState/request.json
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
46
src/ApiDomain/Schema/External/User/UserState/response.json
vendored
Normal file
46
src/ApiDomain/Schema/External/User/UserState/response.json
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
32
src/ApiDomain/Schema/Partials/Response/bad-request.json
Normal file
32
src/ApiDomain/Schema/Partials/Response/bad-request.json
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
10
src/ApiDomain/Schema/Partials/Response/forbidden.json
Normal file
10
src/ApiDomain/Schema/Partials/Response/forbidden.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"description": "The user is forbidden to perform this action",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
10
src/ApiDomain/Schema/Partials/Response/success.json
Normal file
10
src/ApiDomain/Schema/Partials/Response/success.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"description": "Success",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
10
src/ApiDomain/Schema/Partials/Response/unauthorized.json
Normal file
10
src/ApiDomain/Schema/Partials/Response/unauthorized.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"description": "Invalid credentials or invalid user session",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
6
src/ApiDomain/Schema/Partials/date-time.json
Normal file
6
src/ApiDomain/Schema/Partials/date-time.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"description": "A string representing a timestamp",
|
||||
"example": "2024-11-10T21:24:04+00:00",
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
}
|
||||
7
src/ApiDomain/Schema/Partials/nullable-date-time.json
Normal file
7
src/ApiDomain/Schema/Partials/nullable-date-time.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"description": "A nullable string representing a timestamp",
|
||||
"nullable": true,
|
||||
"example": "2024-11-10T21:24:04+00:00",
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
}
|
||||
7
src/ApiDomain/Schema/Partials/nullable-time.json
Normal file
7
src/ApiDomain/Schema/Partials/nullable-time.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"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)$"
|
||||
}
|
||||
6
src/ApiDomain/Schema/Partials/pagination-page.json
Normal file
6
src/ApiDomain/Schema/Partials/pagination-page.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"description": "The current page of a paginated list",
|
||||
"type": "integer",
|
||||
"example": 6,
|
||||
"minimum": 1
|
||||
}
|
||||
6
src/ApiDomain/Schema/Partials/pagination-per-page.json
Normal file
6
src/ApiDomain/Schema/Partials/pagination-per-page.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"description": "The maximum amount of items displayed on a page of a paginated list",
|
||||
"type": "integer",
|
||||
"example": 4,
|
||||
"minimum": 1
|
||||
}
|
||||
6
src/ApiDomain/Schema/Partials/pagination-query.json
Normal file
6
src/ApiDomain/Schema/Partials/pagination-query.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"description": "The nullable query to search for in a paginated list",
|
||||
"example": "Growbox",
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
}
|
||||
6
src/ApiDomain/Schema/Partials/pagination-total.json
Normal file
6
src/ApiDomain/Schema/Partials/pagination-total.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"description": "The total amount of elements in a paginated list",
|
||||
"type": "integer",
|
||||
"example": 3,
|
||||
"minimum": 0
|
||||
}
|
||||
6
src/ApiDomain/Schema/Partials/time.json
Normal file
6
src/ApiDomain/Schema/Partials/time.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"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)$"
|
||||
}
|
||||
6
src/ApiDomain/Schema/Partials/uuid.json
Normal file
6
src/ApiDomain/Schema/Partials/uuid.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"description": "A universally unique identifier",
|
||||
"example": "071ac920-38dc-11ed-a009-0242ac130005",
|
||||
"format": "uuid",
|
||||
"type": "string"
|
||||
}
|
||||
60
src/ApiDomain/Schema/api.schema.json
Normal file
60
src/ApiDomain/Schema/api.schema.json
Normal file
@ -0,0 +1,60 @@
|
||||
{
|
||||
"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' => [
|
||||
'orm_template' => [
|
||||
'directory' => 'data/migrations/business',
|
||||
'directory' => 'data/migrations/template',
|
||||
'name' => 'Doctrine Database Migrations for Template',
|
||||
'namespace' => 'Template\Migrations\Template',
|
||||
'table' => 'migrations',
|
||||
|
||||
@ -1,20 +1,20 @@
|
||||
<?php
|
||||
|
||||
use Template\Data\Business\Entity\User;
|
||||
use Template\Data\Business\Factory\EntityManagerFactory;
|
||||
use Template\Data\Business\Factory\EntityManagerFactory as TemplateEntityManagerFactory;
|
||||
use Template\Data\Business\Manager\EntityManager;
|
||||
use Template\Data\Business\Repository\UserRepository;
|
||||
use Template\Infrastructure\Database\AutowireRepositoryFactory;
|
||||
use Roave\PsrContainerDoctrine\ConfigurationFactory;
|
||||
use Roave\PsrContainerDoctrine\ConnectionFactory;
|
||||
use Roave\PsrContainerDoctrine\EntityManagerFactory as BaseEntityManagerFactory;
|
||||
use Roave\PsrContainerDoctrine\EntityManagerFactory;
|
||||
|
||||
return [
|
||||
'factories' => [
|
||||
'doctrine.entity_manager.orm_template' => [BaseEntityManagerFactory::class, 'orm_template'],
|
||||
'doctrine.entity_manager.orm_template' => [EntityManagerFactory::class, 'orm_template'],
|
||||
'doctrine.configuration.orm_template' => [ConfigurationFactory::class, 'orm_template'],
|
||||
'doctrine.connection.orm_template' => [ConnectionFactory::class, 'orm_template'],
|
||||
EntityManager::class => EntityManagerFactory::class,
|
||||
EntityManager::class => TemplateEntityManagerFactory::class,
|
||||
|
||||
UserRepository::class => [AutowireRepositoryFactory::class, EntityManager::class, User::class],
|
||||
],
|
||||
|
||||
125
src/DataDomain/Business/src/Entity/Mail.php
Normal file
125
src/DataDomain/Business/src/Entity/Mail.php
Normal file
@ -0,0 +1,125 @@
|
||||
<?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,6 +3,8 @@
|
||||
namespace Template\Data\Business\Entity;
|
||||
|
||||
use DateTime;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Template\Infrastructure\UuidGenerator\UuidGenerator;
|
||||
use Ramsey\Uuid\UuidInterface;
|
||||
@ -39,8 +41,11 @@ class User {
|
||||
/** @ORM\OneToOne(targetEntity="Template\Data\Business\Entity\UserSession", mappedBy="user") */
|
||||
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) */
|
||||
private DateTime $lastLoginAt;
|
||||
private ?DateTime $lastLoginAt;
|
||||
|
||||
/** @ORM\Column(name="created_at", type="datetime") */
|
||||
private DateTime $createdAt;
|
||||
@ -52,6 +57,8 @@ class User {
|
||||
public function __construct() {
|
||||
$this->id = UuidGenerator::generate();
|
||||
|
||||
$this->passwordTokens = new ArrayCollection();
|
||||
|
||||
$now = new DateTime();
|
||||
$this->setCreatedAt($now);
|
||||
$this->setUpdatedAt($now);
|
||||
@ -143,6 +150,27 @@ class User {
|
||||
public function setUpdatedAt(DateTime $updatedAt): void {
|
||||
$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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
91
src/DataDomain/Business/src/Entity/UserPasswordToken.php
Normal file
91
src/DataDomain/Business/src/Entity/UserPasswordToken.php
Normal file
@ -0,0 +1,91 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Template\Data\Business\Repository;
|
||||
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
|
||||
class MailRepository extends EntityRepository {
|
||||
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
<?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 {
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
<?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,23 +4,15 @@ declare(strict_types=1);
|
||||
|
||||
namespace Template\Infrastructure\Encryption\Client;
|
||||
|
||||
use Laminas\Crypt\Password\Bcrypt;
|
||||
|
||||
class EncryptionClient
|
||||
{
|
||||
private readonly Bcrypt $bcrypt;
|
||||
|
||||
public function __construct(
|
||||
) {
|
||||
$this->bcrypt = new Bcrypt();
|
||||
$this->bcrypt->setCost(10);
|
||||
}
|
||||
|
||||
public function encrypt(string $value): string {
|
||||
return $this->bcrypt->create($value);
|
||||
return password_hash($value, PASSWORD_BCRYPT, [
|
||||
'cost' => 10
|
||||
]);
|
||||
}
|
||||
|
||||
public function verify(string $value, string $encryptedValue): bool {
|
||||
return $this->bcrypt->verify($value, $encryptedValue);
|
||||
return hash_equals($encryptedValue, crypt($value, $encryptedValue));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,11 +2,11 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Template\Infrastructure\Exception\Middleware\ExceptionHandlerMiddleware;
|
||||
use Template\Infrastructure\Exception\Middleware\TemplateExceptionHandlerMiddleware;
|
||||
use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
|
||||
|
||||
return [
|
||||
'factories' => [
|
||||
ExceptionHandlerMiddleware::class => AutoWiringFactory::class,
|
||||
TemplateExceptionHandlerMiddleware::class => AutoWiringFactory::class,
|
||||
],
|
||||
];
|
||||
|
||||
@ -3,10 +3,13 @@
|
||||
namespace Template\Infrastructure\Exception;
|
||||
|
||||
enum ErrorCode : string {
|
||||
case SomethingWentWrong = 'SomethingWentWrong';
|
||||
|
||||
case NotFound = 'NotFound';
|
||||
case AlreadyExists = 'AlreadyExists';
|
||||
case WrongCredentials = 'WrongCredentials';
|
||||
case Failed = 'Failed';
|
||||
case Invalid = 'Invalid';
|
||||
case Maintenance = 'Maintenance';
|
||||
case Mismatch = 'Mismatch';
|
||||
case NotFound = 'NotFound';
|
||||
case SomethingWentWrong = 'SomethingWentWrong';
|
||||
case WrongCredentials = 'WrongCredentials';
|
||||
case ValidationFailed = 'ValidationFailed';
|
||||
}
|
||||
@ -3,11 +3,12 @@
|
||||
namespace Template\Infrastructure\Exception;
|
||||
|
||||
enum ErrorDomain : string {
|
||||
case Schema = 'Schema';
|
||||
case Generic = 'Generic';
|
||||
|
||||
case Mail = 'Mail';
|
||||
case Notification = 'Notification';
|
||||
case Registration = 'Registration';
|
||||
case Role = 'Role';
|
||||
case User = 'User';
|
||||
case UserPassword = 'UserPassword';
|
||||
case Registration = 'Registration';
|
||||
case Product = 'Product';
|
||||
}
|
||||
@ -2,10 +2,11 @@
|
||||
|
||||
namespace Template\Infrastructure\Exception\Exception;
|
||||
|
||||
use Exception;
|
||||
use Template\Infrastructure\Exception\ErrorCode;
|
||||
use Template\Infrastructure\Exception\ErrorDomain;
|
||||
|
||||
class Exception extends \Exception {
|
||||
class TemplateException extends Exception {
|
||||
|
||||
private readonly ErrorDomain $errorDomain;
|
||||
private readonly ErrorCode $errorCode;
|
||||
@ -1,37 +0,0 @@
|
||||
<?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()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,71 @@
|
||||
<?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,8 +2,10 @@
|
||||
|
||||
namespace Template\Infrastructure\Logging\Logger;
|
||||
|
||||
use Template\Infrastructure\Exception\Exception\Exception;
|
||||
use Template\Infrastructure\Exception\Exception\TemplateException;
|
||||
use Template\Infrastructure\Logging\Handler\FileStreamHandler;
|
||||
use Monolog\ErrorHandler;
|
||||
use Monolog\Handler\StreamHandler;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Stringable;
|
||||
use Throwable;
|
||||
@ -24,7 +26,7 @@ class Logger implements LoggerInterface
|
||||
'trace' => $exception->getTraceAsString()
|
||||
]*/;
|
||||
|
||||
if ($exception instanceof Exception) {
|
||||
if ($exception instanceof TemplateException) {
|
||||
$exceptionContext = array_merge([
|
||||
'errorDomain' => $exception->getErrorDomain()->value,
|
||||
'errorCode' => $exception->getErrorCode()->value,
|
||||
|
||||
12
src/Infrastructure/Mail/config/service_manager.php
Normal file
12
src/Infrastructure/Mail/config/service_manager.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
|
||||
use Template\Infrastructure\Mail\Service\MailService;
|
||||
|
||||
return [
|
||||
'factories' => [
|
||||
MailService::class => AutoWiringFactory::class,
|
||||
],
|
||||
];
|
||||
15
src/Infrastructure/Mail/src/ConfigProvider.php
Normal file
15
src/Infrastructure/Mail/src/ConfigProvider.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Template\Infrastructure\Mail;
|
||||
|
||||
class ConfigProvider
|
||||
{
|
||||
public function __invoke(): array
|
||||
{
|
||||
return [
|
||||
'dependencies' => require __DIR__ . './../config/service_manager.php',
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
<?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
|
||||
);
|
||||
}
|
||||
}
|
||||
176
src/Infrastructure/Mail/src/Service/MailService.php
Normal file
176
src/Infrastructure/Mail/src/Service/MailService.php
Normal file
@ -0,0 +1,176 @@
|
||||
<?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);
|
||||
}
|
||||
}
|
||||
12
src/Infrastructure/Notification/config/service_manager.php
Normal file
12
src/Infrastructure/Notification/config/service_manager.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
|
||||
use Template\Infrastructure\Notification\Service\NotificationService;
|
||||
|
||||
return [
|
||||
'factories' => [
|
||||
NotificationService::class => AutoWiringFactory::class,
|
||||
],
|
||||
];
|
||||
15
src/Infrastructure/Notification/src/ConfigProvider.php
Normal file
15
src/Infrastructure/Notification/src/ConfigProvider.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Template\Infrastructure\Notification;
|
||||
|
||||
class ConfigProvider
|
||||
{
|
||||
public function __invoke(): array
|
||||
{
|
||||
return [
|
||||
'dependencies' => require __DIR__ . './../config/service_manager.php',
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
<?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
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
<?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,7 +56,8 @@ class EnsureAuthorizationMiddleware implements MiddlewareInterface
|
||||
): bool {
|
||||
$role = $user->getRole();
|
||||
$permissions = $role->getPermissions();
|
||||
$targetApi = $this->routes[$targetPath];
|
||||
|
||||
$targetApi = $this->routes[$targetPath] ?? null;
|
||||
|
||||
/** @var Permission $permission */
|
||||
foreach($permissions as $permission) {
|
||||
|
||||
@ -2,12 +2,14 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
|
||||
use Template\Infrastructure\Rbac\Middleware\EnsureAuthorizationMiddleware;
|
||||
use Template\Infrastructure\Request\Factory\RequestServiceFactory;
|
||||
use Template\Infrastructure\Request\Middleware\AnalyzeBodyMiddleware;
|
||||
use Template\Infrastructure\Request\Middleware\AnalyzeHeaderMiddleware;
|
||||
use Template\Infrastructure\Request\Middleware\InternalRequestMiddleware;
|
||||
use Template\Infrastructure\Request\Service\RequestService;
|
||||
use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
|
||||
use Reinfi\DependencyInjection\Factory\InjectionFactory;
|
||||
|
||||
return [
|
||||
'factories' => [
|
||||
|
||||
@ -2,16 +2,10 @@
|
||||
|
||||
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\ServerRequestInterface;
|
||||
use Psr\Http\Server\MiddlewareInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
use Reinfi\DependencyInjection\Annotation\InjectConfig;
|
||||
|
||||
class AnalyzeBodyMiddleware implements MiddlewareInterface
|
||||
{
|
||||
@ -33,6 +27,8 @@ class AnalyzeBodyMiddleware implements MiddlewareInterface
|
||||
$request->getBody()->getContents(),
|
||||
true
|
||||
);
|
||||
|
||||
$request->getBody()->rewind();
|
||||
}
|
||||
|
||||
return $handler->handle($request->withAttribute(
|
||||
|
||||
@ -2,36 +2,47 @@
|
||||
|
||||
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\ServerRequestInterface;
|
||||
use Psr\Http\Server\MiddlewareInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
use Reinfi\DependencyInjection\Annotation\InjectConfig;
|
||||
|
||||
class AnalyzeHeaderMiddleware implements MiddlewareInterface
|
||||
{
|
||||
const HOST_ATTRIBUTE = 'host_attribute';
|
||||
public 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(
|
||||
ServerRequestInterface $request,
|
||||
RequestHandlerInterface $handler
|
||||
): ResponseInterface
|
||||
{
|
||||
$headers = $request->getHeaders();
|
||||
|
||||
$contentType = $this->readHeader($headers, self::CONTENT_TYPE_HEADER_KEY) ?? null;
|
||||
$host = explode(
|
||||
':',
|
||||
$request->getHeaders()['host'][0]
|
||||
?? $request->getHeaders()['x-forwarded-host'][0]
|
||||
?? 'UNKNOWN'
|
||||
$this->readHeader($headers, self::HOST_HEADER_KEY) ??
|
||||
$this->readHeader($headers, self::FORWARDED_HOST_HEADER_KEY) ??
|
||||
'UNKNOWN'
|
||||
)[0];
|
||||
|
||||
return $handler->handle($request->withAttribute(
|
||||
self::HOST_ATTRIBUTE,
|
||||
$host
|
||||
));
|
||||
return $handler->handle(
|
||||
$request
|
||||
->withAttribute(self::HOST_ATTRIBUTE, $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,9 +7,13 @@ use Laminas\Diactoros\Response\JsonResponse;
|
||||
class SuccessResponse extends JsonResponse
|
||||
{
|
||||
public function __construct(
|
||||
mixed $data = 'OK'
|
||||
mixed $data = 'Success'
|
||||
)
|
||||
{
|
||||
if ($data === []) {
|
||||
$data = 'Success';
|
||||
}
|
||||
|
||||
parent::__construct(
|
||||
$data
|
||||
);
|
||||
|
||||
41
src/Infrastructure/Schema/config/service_manager.php
Normal file
41
src/Infrastructure/Schema/config/service_manager.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?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