Initial commit
This commit is contained in:
commit
c0c461a844
20
.env.example
Normal file
20
.env.example
Normal file
@ -0,0 +1,20 @@
|
||||
# DB Configuration
|
||||
DB_DRIVER=pdo_mysql
|
||||
DB_HOST=homepage-backend-mysql
|
||||
DB_PORT=3306
|
||||
DB_USER=homepage
|
||||
DB_PASSWORD=pass
|
||||
DB_NAME=homepage
|
||||
DB_NAME_LOG=log
|
||||
|
||||
# API Keys
|
||||
AUTH_API_KEY=
|
||||
NOTIFICATION_API_KEY=
|
||||
FILE_API_KEY=
|
||||
HOMEPAGE_API_KEY=
|
||||
BEE_API_KEY=
|
||||
|
||||
# Homepage Setup
|
||||
INIT_USER_NAME=admin
|
||||
INIT_USER_PASSWORD=password
|
||||
INIT_USER_MAIL=admin@test.com
|
||||
7
.gitattributes
vendored
Normal file
7
.gitattributes
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
/.gitattributes export-ignore
|
||||
/.github/ export-ignore
|
||||
/.laminas-ci.json export-ignore
|
||||
/phpcs.xml.dist export-ignore
|
||||
/psalm.xml.dist export-ignore
|
||||
/psalm-baseline.xml export-ignore
|
||||
/renovate.json export-ignore
|
||||
40
.github/workflows/create branch on issue.yml
vendored
Normal file
40
.github/workflows/create branch on issue.yml
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
name: Create Branch on Issue Transition to In Progress
|
||||
|
||||
on:
|
||||
issues:
|
||||
types:
|
||||
- edited
|
||||
|
||||
jobs:
|
||||
create-branch:
|
||||
if: github.event.changes.issue.labels
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Get issue details
|
||||
run: |
|
||||
issue_title=$(jq -r ".issue.number" "$GITHUB_EVENT_PATH")
|
||||
previous_labels=$(jq -r ".changes.labels.from" "$GITHUB_EVENT_PATH")
|
||||
current_labels=$(jq -r ".issue.labels | map(.name) | join(\", \")" "$GITHUB_EVENT_PATH")
|
||||
branch_name=""
|
||||
|
||||
# Check if the issue transitioned from 'Todo' to 'In Progress'
|
||||
if [[ "$previous_labels" == *"Todo"* && "$current_labels" == *"In Progress"* ]]; then
|
||||
project_name="hp-be" # Verwende "hp-be" als Projektnamen
|
||||
branch_name="${project_name}-${issue_title}"
|
||||
echo "Branch name: $branch_name"
|
||||
fi
|
||||
|
||||
echo "::set-output name=branch_name::$branch_name"
|
||||
shell: bash
|
||||
|
||||
- name: Create and switch to new branch
|
||||
run: |
|
||||
branch_name="${{ steps.create-branch.outputs.branch_name }}"
|
||||
if [ -n "$branch_name" ]; then
|
||||
git checkout -b "$branch_name"
|
||||
git push origin "$branch_name"
|
||||
fi
|
||||
working-directory: ${{ github.workspace }}
|
||||
39
.github/workflows/php.yml
vendored
Normal file
39
.github/workflows/php.yml
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
name: PHP Composer
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Validate composer.json and composer.lock
|
||||
run: composer validate --strict
|
||||
|
||||
- name: Cache Composer packages
|
||||
id: composer-cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: vendor
|
||||
key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-php-
|
||||
|
||||
- name: Install dependencies
|
||||
run: composer install --prefer-dist --no-progress
|
||||
|
||||
# Add a test script to composer.json, for instance: "test": "vendor/bin/phpunit"
|
||||
# Docs: https://getcomposer.org/doc/articles/scripts.md
|
||||
|
||||
# - name: Run test suite
|
||||
# run: composer run-script test
|
||||
15
.gitignore
vendored
Normal file
15
.gitignore
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
/.phpcs-cache
|
||||
/.phpunit.result.cache
|
||||
/.idea
|
||||
/clover.xml
|
||||
/coveralls-upload.json
|
||||
/phpunit.xml
|
||||
|
||||
/data/cache/
|
||||
/data/db/
|
||||
/public/data/
|
||||
/var/
|
||||
/vendor/
|
||||
|
||||
*.env
|
||||
composer.lock
|
||||
3
.htaccess
Normal file
3
.htaccess
Normal file
@ -0,0 +1,3 @@
|
||||
RewriteEngine On
|
||||
RewriteBase /
|
||||
RewriteRule ^pages/([^/]*)/(.*)$ pages.php?$1=$2
|
||||
1
COPYRIGHT.md
Normal file
1
COPYRIGHT.md
Normal file
@ -0,0 +1 @@
|
||||
Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC. (https://getlaminas.org/)
|
||||
26
LICENSE.md
Normal file
26
LICENSE.md
Normal file
@ -0,0 +1,26 @@
|
||||
Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
- Neither the name of Laminas Foundation nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
39
bin/clear-config-cache.php
Normal file
39
bin/clear-config-cache.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
chdir(__DIR__ . '/../');
|
||||
|
||||
require 'vendor/autoload.php';
|
||||
|
||||
$config = include 'config/config.php';
|
||||
|
||||
if (! isset($config['config_cache_path'])) {
|
||||
echo "No configuration cache path found" . PHP_EOL;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (! file_exists($config['config_cache_path'])) {
|
||||
printf(
|
||||
"Configured config cache file '%s' not found%s",
|
||||
$config['config_cache_path'],
|
||||
PHP_EOL
|
||||
);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (false === unlink($config['config_cache_path'])) {
|
||||
printf(
|
||||
"Error removing config cache file '%s'%s",
|
||||
$config['config_cache_path'],
|
||||
PHP_EOL
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf(
|
||||
"Removed configured config cache file '%s'%s",
|
||||
$config['config_cache_path'],
|
||||
PHP_EOL
|
||||
);
|
||||
exit(0);
|
||||
30
bin/console.php
Normal file
30
bin/console.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
use Homepage\Infrastructure\Logging\Logger\Logger;
|
||||
use Symfony\Component\Console\Application;
|
||||
|
||||
require_once __DIR__ . '/../config/autoload/defines.php';
|
||||
require APP_ROOT . '/vendor/autoload.php';
|
||||
|
||||
call_user_func(function() {
|
||||
$container = require APP_ROOT . '/config/container.php';
|
||||
|
||||
$config = $container->get('config');
|
||||
$commands = $config['console']['commands'];
|
||||
|
||||
$app = new Application();
|
||||
foreach ($commands as $command) {
|
||||
$app->add($container->get($command));
|
||||
}
|
||||
|
||||
try {
|
||||
$app->setCatchExceptions(false);
|
||||
$app->run();
|
||||
} catch (Throwable $e) {
|
||||
$logger = new Logger();
|
||||
$logger->error(
|
||||
$e->getMessage(),
|
||||
['exception' => $e]
|
||||
);
|
||||
}
|
||||
});
|
||||
91
bin/doctrine-migrations-log.php
Normal file
91
bin/doctrine-migrations-log.php
Normal file
@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . '/../config/autoload/defines.php';
|
||||
require APP_ROOT . '/vendor/autoload.php';
|
||||
|
||||
use Homepage\Data\Business\Manager\HomepageEntityManager;
|
||||
use Doctrine\Common\Annotations\AnnotationReader;
|
||||
use Doctrine\DBAL\DriverManager;
|
||||
use Doctrine\Migrations\Configuration\Configuration;
|
||||
use Doctrine\Migrations\Configuration\Connection\ExistingConnection;
|
||||
use Doctrine\Migrations\Configuration\Migration\ExistingConfiguration;
|
||||
use Doctrine\Migrations\DependencyFactory;
|
||||
use Doctrine\Migrations\Metadata\Storage\TableMetadataStorageConfiguration;
|
||||
use Doctrine\Migrations\Tools\Console\Command\DumpSchemaCommand;
|
||||
use Doctrine\Migrations\Tools\Console\Command\ExecuteCommand;
|
||||
use Doctrine\Migrations\Tools\Console\Command\GenerateCommand;
|
||||
use Doctrine\Migrations\Tools\Console\Command\LatestCommand;
|
||||
use Doctrine\Migrations\Tools\Console\Command\ListCommand;
|
||||
use Doctrine\Migrations\Tools\Console\Command\MigrateCommand;
|
||||
use Doctrine\Migrations\Tools\Console\Command\RollupCommand;
|
||||
use Doctrine\Migrations\Tools\Console\Command\StatusCommand;
|
||||
use Doctrine\Migrations\Tools\Console\Command\SyncMetadataCommand;
|
||||
use Doctrine\Migrations\Tools\Console\Command\VersionCommand;
|
||||
use Doctrine\ORM\Mapping\Driver\AnnotationDriver;
|
||||
use Doctrine\ORM\Tools\Setup;
|
||||
use Symfony\Component\Console\Application;
|
||||
|
||||
$isDevMode = true;
|
||||
|
||||
$container = require APP_ROOT . '/config/container.php';
|
||||
$config = $container->get('config');
|
||||
$doctrineConfig = $config['doctrine'];
|
||||
$paths = $doctrineConfig['driver']['orm_log_annotation_driver']['paths'];
|
||||
|
||||
$dbParams = $doctrineConfig['connection']['orm_log']['params'];
|
||||
$migrationsConf = $doctrineConfig['migrations_configuration']['orm_log'];
|
||||
|
||||
$reader = new AnnotationReader();
|
||||
$driver = new AnnotationDriver($reader, $paths);
|
||||
|
||||
$config = Setup::createAnnotationMetadataConfiguration($paths, $isDevMode);
|
||||
$config->setMetadataDriverImpl($driver);
|
||||
$entityManager = $container->get(HomepageEntityManager::class);
|
||||
|
||||
try {
|
||||
$connection = DriverManager::getConnection($dbParams);
|
||||
} catch (\Doctrine\DBAL\Exception $e) {
|
||||
echo $e->getMessage();
|
||||
exit;
|
||||
}
|
||||
|
||||
$configuration = new Configuration($connection);
|
||||
|
||||
$configuration->addMigrationsDirectory(
|
||||
$migrationsConf['namespace'],
|
||||
$migrationsConf['directory']
|
||||
);
|
||||
$configuration->setAllOrNothing(true);
|
||||
$configuration->setCheckDatabasePlatform(false);
|
||||
|
||||
$storageConfiguration = new TableMetadataStorageConfiguration();
|
||||
$storageConfiguration->setTableName($migrationsConf['table']);
|
||||
|
||||
$configuration->setMetadataStorageConfiguration($storageConfiguration);
|
||||
|
||||
$dependencyFactory = DependencyFactory::fromConnection(
|
||||
new ExistingConfiguration($configuration),
|
||||
new ExistingConnection($connection)
|
||||
);
|
||||
|
||||
$cli = new Application('Doctrine Migrations');
|
||||
$cli->setCatchExceptions(true);
|
||||
|
||||
$cli->addCommands([
|
||||
new DumpSchemaCommand($dependencyFactory),
|
||||
new ExecuteCommand($dependencyFactory),
|
||||
new GenerateCommand($dependencyFactory),
|
||||
new LatestCommand($dependencyFactory),
|
||||
new ListCommand($dependencyFactory),
|
||||
new MigrateCommand($dependencyFactory),
|
||||
new RollupCommand($dependencyFactory),
|
||||
new StatusCommand($dependencyFactory),
|
||||
new SyncMetadataCommand($dependencyFactory),
|
||||
new VersionCommand($dependencyFactory),
|
||||
]);
|
||||
|
||||
try {
|
||||
$cli->run();
|
||||
} catch (Exception $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
91
bin/doctrine-migrations.php
Normal file
91
bin/doctrine-migrations.php
Normal file
@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . '/../config/autoload/defines.php';
|
||||
require APP_ROOT . '/vendor/autoload.php';
|
||||
|
||||
use Homepage\Data\Business\Manager\HomepageEntityManager;
|
||||
use Doctrine\Common\Annotations\AnnotationReader;
|
||||
use Doctrine\DBAL\DriverManager;
|
||||
use Doctrine\Migrations\Configuration\Configuration;
|
||||
use Doctrine\Migrations\Configuration\Connection\ExistingConnection;
|
||||
use Doctrine\Migrations\Configuration\Migration\ExistingConfiguration;
|
||||
use Doctrine\Migrations\DependencyFactory;
|
||||
use Doctrine\Migrations\Metadata\Storage\TableMetadataStorageConfiguration;
|
||||
use Doctrine\Migrations\Tools\Console\Command\DumpSchemaCommand;
|
||||
use Doctrine\Migrations\Tools\Console\Command\ExecuteCommand;
|
||||
use Doctrine\Migrations\Tools\Console\Command\GenerateCommand;
|
||||
use Doctrine\Migrations\Tools\Console\Command\LatestCommand;
|
||||
use Doctrine\Migrations\Tools\Console\Command\ListCommand;
|
||||
use Doctrine\Migrations\Tools\Console\Command\MigrateCommand;
|
||||
use Doctrine\Migrations\Tools\Console\Command\RollupCommand;
|
||||
use Doctrine\Migrations\Tools\Console\Command\StatusCommand;
|
||||
use Doctrine\Migrations\Tools\Console\Command\SyncMetadataCommand;
|
||||
use Doctrine\Migrations\Tools\Console\Command\VersionCommand;
|
||||
use Doctrine\ORM\Mapping\Driver\AnnotationDriver;
|
||||
use Doctrine\ORM\Tools\Setup;
|
||||
use Symfony\Component\Console\Application;
|
||||
|
||||
$isDevMode = true;
|
||||
|
||||
$container = require APP_ROOT . '/config/container.php';
|
||||
$config = $container->get('config');
|
||||
$doctrineConfig = $config['doctrine'];
|
||||
$paths = $doctrineConfig['driver']['orm_homepage_annotation_driver']['paths'];
|
||||
|
||||
$dbParams = $doctrineConfig['connection']['orm_homepage']['params'];
|
||||
$migrationsConf = $doctrineConfig['migrations_configuration']['orm_homepage'];
|
||||
|
||||
$reader = new AnnotationReader();
|
||||
$driver = new AnnotationDriver($reader, $paths);
|
||||
|
||||
$config = Setup::createAnnotationMetadataConfiguration($paths, $isDevMode);
|
||||
$config->setMetadataDriverImpl($driver);
|
||||
$entityManager = $container->get(HomepageEntityManager::class);
|
||||
|
||||
try {
|
||||
$connection = DriverManager::getConnection($dbParams);
|
||||
} catch (\Doctrine\DBAL\Exception $e) {
|
||||
echo $e->getMessage();
|
||||
exit;
|
||||
}
|
||||
|
||||
$configuration = new Configuration($connection);
|
||||
|
||||
$configuration->addMigrationsDirectory(
|
||||
$migrationsConf['namespace'],
|
||||
$migrationsConf['directory']
|
||||
);
|
||||
$configuration->setAllOrNothing(true);
|
||||
$configuration->setCheckDatabasePlatform(false);
|
||||
|
||||
$storageConfiguration = new TableMetadataStorageConfiguration();
|
||||
$storageConfiguration->setTableName($migrationsConf['table']);
|
||||
|
||||
$configuration->setMetadataStorageConfiguration($storageConfiguration);
|
||||
|
||||
$dependencyFactory = DependencyFactory::fromConnection(
|
||||
new ExistingConfiguration($configuration),
|
||||
new ExistingConnection($connection)
|
||||
);
|
||||
|
||||
$cli = new Application('Doctrine Migrations');
|
||||
$cli->setCatchExceptions(true);
|
||||
|
||||
$cli->addCommands([
|
||||
new DumpSchemaCommand($dependencyFactory),
|
||||
new ExecuteCommand($dependencyFactory),
|
||||
new GenerateCommand($dependencyFactory),
|
||||
new LatestCommand($dependencyFactory),
|
||||
new ListCommand($dependencyFactory),
|
||||
new MigrateCommand($dependencyFactory),
|
||||
new RollupCommand($dependencyFactory),
|
||||
new StatusCommand($dependencyFactory),
|
||||
new SyncMetadataCommand($dependencyFactory),
|
||||
new VersionCommand($dependencyFactory),
|
||||
]);
|
||||
|
||||
try {
|
||||
$cli->run();
|
||||
} catch (Exception $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
3
bin/script/build
Executable file
3
bin/script/build
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||
$SCRIPT_DIR/exec build
|
||||
3
bin/script/down
Executable file
3
bin/script/down
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||
$SCRIPT_DIR/exec down
|
||||
23
bin/script/exec
Executable file
23
bin/script/exec
Executable file
@ -0,0 +1,23 @@
|
||||
#!/bin/bash
|
||||
|
||||
COMMAND="$@"
|
||||
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||
|
||||
#LOAD ENV VARIABLES FROM .ENV
|
||||
export $(grep -v '^#' "${SCRIPT_DIR}/../../.env" | xargs)
|
||||
|
||||
#MAC
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
docker-compose -f "${SCRIPT_DIR}/../../docker/docker-compose-mac.yml" $COMMAND
|
||||
|
||||
#LINUX
|
||||
elif [[ "$OSTYPE" == "linux-gnu" ]]; then
|
||||
docker-compose -f "${SCRIPT_DIR}/../../docker/docker-compose.yml" $COMMAND
|
||||
|
||||
else
|
||||
echo "Dieses Skript wird auf deinem Gerät nicht unterstützt"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#UNSET ENV VARIABLES FROM .ENV
|
||||
unset $(grep -v '^#' "${SCRIPT_DIR}/../../.env" | sed -E 's/(.*)=.*/\1/' | xargs)
|
||||
32
bin/script/init
Executable file
32
bin/script/init
Executable file
@ -0,0 +1,32 @@
|
||||
#!/bin/bash
|
||||
|
||||
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||
PROJECT_DIR=$(realpath $SCRIPT_DIR/../../)
|
||||
ENV_DIR=$(realpath $PROJECT_DIR/../../)
|
||||
|
||||
# Check .env file
|
||||
if [ ! -f "$PROJECT_DIR/.env" ]
|
||||
then
|
||||
echo "Create .env file from example..."
|
||||
cp "$PROJECT_DIR/.env.example" "$PROJECT_DIR/.env"
|
||||
echo ".env file created, please change variables and call me again"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Build and start docker containers
|
||||
$SCRIPT_DIR/exec build
|
||||
$SCRIPT_DIR/exec up -d
|
||||
|
||||
# Source drun
|
||||
source $ENV_DIR/bin/script/drun
|
||||
|
||||
# Install PHP packages
|
||||
drun homepage-backend composer install
|
||||
|
||||
# Migrate databases to current version
|
||||
drun homepage-backend composer dmm
|
||||
drun homepage-backend composer dmlm
|
||||
|
||||
# Insert setup for project after this line
|
||||
drun homepage-backend composer console rbac:update
|
||||
drun homepage-backend composer console init:data
|
||||
3
bin/script/stop
Executable file
3
bin/script/stop
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||
$SCRIPT_DIR/exec stop
|
||||
3
bin/script/up
Executable file
3
bin/script/up
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||
$SCRIPT_DIR/exec up -d
|
||||
122
composer.development.json
Normal file
122
composer.development.json
Normal file
@ -0,0 +1,122 @@
|
||||
{
|
||||
"require": {
|
||||
"laminas\/laminas-servicemanager": "^3.21",
|
||||
"mezzio\/mezzio-laminasrouter": "^3.8",
|
||||
"reinfi\/zf-dependency-injection": "^5.4",
|
||||
"laminas\/laminas-config-aggregator": "^1.13",
|
||||
"doctrine\/doctrine-orm-module": "5.0.*",
|
||||
"doctrine\/migrations": "^3.5",
|
||||
"doctrine\/orm": "2.11.3",
|
||||
"doctrine\/persistence": "2.2.*",
|
||||
"ramsey\/uuid-doctrine": "^1.8",
|
||||
"roave\/psr-container-doctrine": "^3.1",
|
||||
"mezzio\/mezzio": "^3.17",
|
||||
"mezzio\/mezzio-helpers": "^5.15",
|
||||
"symfony\/cache": "5.4.8",
|
||||
"doctrine\/dbal": "^3.6",
|
||||
"teewurst\/psr4-advanced-wildcard-composer-plugin": "^3.0",
|
||||
"laminas\/laminas-crypt": "^3.10",
|
||||
"monolog\/monolog": "^3.4",
|
||||
"laminas\/laminas-mail": "^2.23",
|
||||
"teewurst\/pipeline": "^3.0",
|
||||
"guzzlehttp\/guzzle": "^7.8"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Homepage\\API\\Console\\": "src\/ApiDomain\/Console\/src",
|
||||
"Homepage\\API\\External\\Authentication\\": "src\/ApiDomain\/External\/Authentication\/src",
|
||||
"Homepage\\API\\External\\Health\\": "src\/ApiDomain\/External\/Health\/src",
|
||||
"Homepage\\API\\External\\Product\\": "src\/ApiDomain\/External\/Product\/src",
|
||||
"Homepage\\API\\External\\User\\": "src\/ApiDomain\/External\/User\/src",
|
||||
"Homepage\\Data\\Business\\": "src\/DataDomain\/Business\/src",
|
||||
"Homepage\\Data\\Log\\": "src\/DataDomain\/Log\/src",
|
||||
"Homepage\\Handling\\Product\\": "src\/HandlingDomain\/Product\/src",
|
||||
"Homepage\\Handling\\Registration\\": "src\/HandlingDomain\/Registration\/src",
|
||||
"Homepage\\Handling\\Role\\": "src\/HandlingDomain\/Role\/src",
|
||||
"Homepage\\Handling\\User\\": "src\/HandlingDomain\/User\/src",
|
||||
"Homepage\\Handling\\UserSession\\": "src\/HandlingDomain\/UserSession\/src",
|
||||
"Homepage\\Infrastructure\\Database\\": "src\/Infrastructure\/Database\/src",
|
||||
"Homepage\\Infrastructure\\DependencyInjection\\": "src\/Infrastructure\/DependencyInjection\/src",
|
||||
"Homepage\\Infrastructure\\Encryption\\": "src\/Infrastructure\/Encryption\/src",
|
||||
"Homepage\\Infrastructure\\Exception\\": "src\/Infrastructure\/Exception\/src",
|
||||
"Homepage\\Infrastructure\\Logging\\": "src\/Infrastructure\/Logging\/src",
|
||||
"Homepage\\Infrastructure\\Rbac\\": "src\/Infrastructure\/Rbac\/src",
|
||||
"Homepage\\Infrastructure\\Request\\": "src\/Infrastructure\/Request\/src",
|
||||
"Homepage\\Infrastructure\\Response\\": "src\/Infrastructure\/Response\/src",
|
||||
"Homepage\\Infrastructure\\Session\\": "src\/Infrastructure\/Session\/src",
|
||||
"Homepage\\Infrastructure\\UuidGenerator\\": "src\/Infrastructure\/UuidGenerator\/src"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"teewurst\/psr4-advanced-wildcard-composer-plugin": {
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Homepage\\API\\%s\\%s\\": "src\/ApiDomain\/{*}\/{*}\/src\/",
|
||||
"Homepage\\Data\\%s\\": "src\/DataDomain\/{*}\/src\/",
|
||||
"Homepage\\Handling\\%s\\": "src\/HandlingDomain\/{*}\/src\/",
|
||||
"Homepage\\Infrastructure\\%s\\": "src\/Infrastructure\/{*}\/src\/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Homepage\\API\\%s\\%s\\": "src\/ApiDomain\/{*}\/{*}\/src\/",
|
||||
"Homepage\\Data\\%s\\": "src\/DataDomain\/{*}\/src\/",
|
||||
"Homepage\\Handling\\%s\\": "src\/HandlingDomain\/{*}\/src\/",
|
||||
"Homepage\\Infrastructure\\%s\\": "src\/Infrastructure\/{*}\/src\/"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"dmg": "php bin\/doctrine-migrations.php migrations:generate --no-interaction",
|
||||
"dmm": "php bin\/doctrine-migrations.php migrations:migrate --no-interaction",
|
||||
"dmlg": "php bin\/doctrine-migrations-log.php migrations:generate --no-interaction",
|
||||
"dmlm": "php bin\/doctrine-migrations-log.php migrations:migrate --no-interaction",
|
||||
"console": "php bin\/console.php",
|
||||
"serve": "php -S 0.0.0.0:8080 -t public\/",
|
||||
"unserve": "killall -9 php",
|
||||
"da": [
|
||||
"composer dump-autoload",
|
||||
"composer dump-autoload --dev"
|
||||
],
|
||||
"initdb": [
|
||||
"@composer dmm",
|
||||
"@composer dmlm",
|
||||
"@composer console rbac:update",
|
||||
"@composer console init:data"
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"teewurst\/psr4-advanced-wildcard-composer-plugin": true
|
||||
}
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony\/dotenv": "^6.3"
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Homepage\\API\\External\\Authentication\\": "src\/ApiDomain\/External\/Authentication\/src",
|
||||
"Homepage\\API\\External\\Health\\": "src\/ApiDomain\/External\/Health\/src",
|
||||
"Homepage\\API\\External\\Product\\": "src\/ApiDomain\/External\/Product\/src",
|
||||
"Homepage\\API\\External\\User\\": "src\/ApiDomain\/External\/User\/src",
|
||||
"Homepage\\Data\\Business\\": "src\/DataDomain\/Business\/src",
|
||||
"Homepage\\Data\\Log\\": "src\/DataDomain\/Log\/src",
|
||||
"Homepage\\Handling\\Product\\": "src\/HandlingDomain\/Product\/src",
|
||||
"Homepage\\Handling\\Registration\\": "src\/HandlingDomain\/Registration\/src",
|
||||
"Homepage\\Handling\\Role\\": "src\/HandlingDomain\/Role\/src",
|
||||
"Homepage\\Handling\\User\\": "src\/HandlingDomain\/User\/src",
|
||||
"Homepage\\Handling\\UserSession\\": "src\/HandlingDomain\/UserSession\/src",
|
||||
"Homepage\\Infrastructure\\Database\\": "src\/Infrastructure\/Database\/src",
|
||||
"Homepage\\Infrastructure\\DependencyInjection\\": "src\/Infrastructure\/DependencyInjection\/src",
|
||||
"Homepage\\Infrastructure\\Encryption\\": "src\/Infrastructure\/Encryption\/src",
|
||||
"Homepage\\Infrastructure\\Exception\\": "src\/Infrastructure\/Exception\/src",
|
||||
"Homepage\\Infrastructure\\Logging\\": "src\/Infrastructure\/Logging\/src",
|
||||
"Homepage\\Infrastructure\\Rbac\\": "src\/Infrastructure\/Rbac\/src",
|
||||
"Homepage\\Infrastructure\\Request\\": "src\/Infrastructure\/Request\/src",
|
||||
"Homepage\\Infrastructure\\Response\\": "src\/Infrastructure\/Response\/src",
|
||||
"Homepage\\Infrastructure\\Session\\": "src\/Infrastructure\/Session\/src",
|
||||
"Homepage\\Infrastructure\\UuidGenerator\\": "src\/Infrastructure\/UuidGenerator\/src"
|
||||
}
|
||||
}
|
||||
}
|
||||
76
composer.json
Normal file
76
composer.json
Normal file
@ -0,0 +1,76 @@
|
||||
{
|
||||
"require": {
|
||||
"laminas/laminas-servicemanager": "^3.21",
|
||||
"mezzio/mezzio-laminasrouter": "^3.8",
|
||||
"reinfi/zf-dependency-injection": "^5.4",
|
||||
"laminas/laminas-config-aggregator": "^1.13",
|
||||
"doctrine/doctrine-orm-module": "5.0.*",
|
||||
"doctrine/migrations": "^3.5",
|
||||
"doctrine/orm": "2.11.3",
|
||||
"doctrine/persistence": "2.2.*",
|
||||
"ramsey/uuid-doctrine": "^1.8",
|
||||
"roave/psr-container-doctrine": "^3.1",
|
||||
"mezzio/mezzio": "^3.17",
|
||||
"mezzio/mezzio-helpers": "^5.15",
|
||||
"symfony/cache": "5.4.8",
|
||||
"doctrine/dbal": "^3.6",
|
||||
"teewurst/psr4-advanced-wildcard-composer-plugin": "^3.0",
|
||||
"laminas/laminas-crypt": "^3.10",
|
||||
"monolog/monolog": "^3.4",
|
||||
"laminas/laminas-mail": "^2.23",
|
||||
"teewurst/pipeline": "^3.0",
|
||||
"guzzlehttp/guzzle": "^7.8"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Homepage\\API\\Console\\": "src/ApiDomain/Console/src/"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"teewurst/psr4-advanced-wildcard-composer-plugin": {
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Homepage\\API\\%s\\%s\\": "src/ApiDomain/{*}/{*}/src/",
|
||||
"Homepage\\Data\\%s\\": "src/DataDomain/{*}/src/",
|
||||
"Homepage\\Handling\\%s\\": "src/HandlingDomain/{*}/src/",
|
||||
"Homepage\\Infrastructure\\%s\\": "src/Infrastructure/{*}/src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Homepage\\API\\%s\\%s\\": "src/ApiDomain/{*}/{*}/src/",
|
||||
"Homepage\\Data\\%s\\": "src/DataDomain/{*}/src/",
|
||||
"Homepage\\Handling\\%s\\": "src/HandlingDomain/{*}/src/",
|
||||
"Homepage\\Infrastructure\\%s\\": "src/Infrastructure/{*}/src/"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"dmg": "php bin/doctrine-migrations.php migrations:generate --no-interaction",
|
||||
"dmm": "php bin/doctrine-migrations.php migrations:migrate --no-interaction",
|
||||
"dmlg": "php bin/doctrine-migrations-log.php migrations:generate --no-interaction",
|
||||
"dmlm": "php bin/doctrine-migrations-log.php migrations:migrate --no-interaction",
|
||||
"console": "php bin/console.php",
|
||||
"serve": "php -S 0.0.0.0:8080 -t public/",
|
||||
"unserve": "killall -9 php",
|
||||
"da": [
|
||||
"composer dump-autoload",
|
||||
"composer dump-autoload --dev"
|
||||
],
|
||||
"initdb": [
|
||||
"@composer dmm",
|
||||
"@composer dmlm",
|
||||
"@composer console rbac:update",
|
||||
"@composer console init:data"
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"teewurst/psr4-advanced-wildcard-composer-plugin": true
|
||||
}
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/dotenv": "^6.3"
|
||||
}
|
||||
}
|
||||
2
config/autoload/.gitignore
vendored
Normal file
2
config/autoload/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
local.php
|
||||
*.local.php
|
||||
29
config/autoload/api.global.php
Normal file
29
config/autoload/api.global.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'api' => [
|
||||
'keys' => [
|
||||
'homepage' => $_ENV['HOMEPAGE_API_KEY'],
|
||||
'notification' => $_ENV['NOTIFICATION_API_KEY'],
|
||||
],
|
||||
|
||||
'services' => [
|
||||
'homepage' => [
|
||||
'host' => 'homepage-backend-nginx',
|
||||
'apis' => [
|
||||
|
||||
]
|
||||
],
|
||||
'notification' => [
|
||||
'host' => 'notification-backend-nginx',
|
||||
'apis' => [
|
||||
'send-mail' => [
|
||||
'path' => '/api/mail/send',
|
||||
'method' => 'POST'
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
22
config/autoload/authorization.global.php
Normal file
22
config/autoload/authorization.global.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'homepage-rbac' => [
|
||||
'roles' => [
|
||||
'admin',
|
||||
'user',
|
||||
],
|
||||
'permissions' => [
|
||||
'user' => [
|
||||
'product.product-list',
|
||||
],
|
||||
'admin' => [
|
||||
'product.create-product',
|
||||
'product.delete-product',
|
||||
'product.product-list',
|
||||
'product.update-product',
|
||||
'user.create-user',
|
||||
],
|
||||
]
|
||||
]
|
||||
];
|
||||
6
config/autoload/defines.php
Normal file
6
config/autoload/defines.php
Normal file
@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
|
||||
if (! defined('APP_ROOT')) {
|
||||
define('APP_ROOT', realpath(__DIR__ . '/../../'));
|
||||
}
|
||||
26
config/autoload/dependencies.global.php
Normal file
26
config/autoload/dependencies.global.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
return [
|
||||
// Provides application-wide services.
|
||||
// We recommend using fully-qualified class names whenever possible as
|
||||
// service names.
|
||||
'dependencies' => [
|
||||
// Use 'aliases' to alias a service name to another service. The
|
||||
// key is the alias name, the value is the service to which it points.
|
||||
'aliases' => [
|
||||
// Fully\Qualified\ClassOrInterfaceName::class => Fully\Qualified\ClassName::class,
|
||||
],
|
||||
// Use 'invokables' for constructor-less services, or services that do
|
||||
// not require arguments to the constructor. Map a service name to the
|
||||
// class name.
|
||||
'invokables' => [
|
||||
// Fully\Qualified\InterfaceName::class => Fully\Qualified\ClassName::class,
|
||||
],
|
||||
// Use 'factories' for services provided by callbacks/factory classes.
|
||||
'factories' => [
|
||||
// Fully\Qualified\ClassName::class => Fully\Qualified\FactoryName::class,
|
||||
],
|
||||
],
|
||||
];
|
||||
14
config/autoload/doctrine.global.php
Normal file
14
config/autoload/doctrine.global.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
use Doctrine\DBAL\Driver\PDO\MySQL\Driver;
|
||||
use Doctrine\ORM\Mapping\Driver\AnnotationDriver;
|
||||
use Doctrine\Persistence\Mapping\Driver\MappingDriverChain;
|
||||
use Ramsey\Uuid\Doctrine\UuidBinaryOrderedTimeType;
|
||||
|
||||
return [
|
||||
'doctrine' => [
|
||||
'types' => [
|
||||
UuidBinaryOrderedTimeType::NAME => UuidBinaryOrderedTimeType::class,
|
||||
],
|
||||
],
|
||||
];
|
||||
14
config/autoload/logger.global.php
Normal file
14
config/autoload/logger.global.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Monolog\Level;
|
||||
|
||||
return [
|
||||
'logger' => [
|
||||
'name' => 'homepage.backend',
|
||||
'path' => APP_ROOT . '/var/log/homepage.backend.log',
|
||||
'level' => Level::Debug,
|
||||
'pretty' => true,
|
||||
]
|
||||
];
|
||||
24
config/autoload/mezzio.global.php
Normal file
24
config/autoload/mezzio.global.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Laminas\ConfigAggregator\ConfigAggregator;
|
||||
|
||||
return [
|
||||
// Toggle the configuration cache. Set this to boolean false, or remove the
|
||||
// directive, to disable configuration caching. Toggling development mode
|
||||
// will also disable it by default; clear the configuration cache using
|
||||
// `composer clear-config-cache`.
|
||||
ConfigAggregator::ENABLE_CACHE => false,
|
||||
|
||||
// Enable debugging; typically used to provide debugging information within templates.
|
||||
'debug' => false,
|
||||
'mezzio' => [
|
||||
// Provide templates for the error handling middleware to use when
|
||||
// generating responses.
|
||||
'error_handler' => [
|
||||
'template_404' => 'error::404',
|
||||
'template_error' => 'error::error',
|
||||
],
|
||||
],
|
||||
];
|
||||
91
config/config.php
Normal file
91
config/config.php
Normal file
@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Laminas\ConfigAggregator\ArrayProvider;
|
||||
use Laminas\ConfigAggregator\ConfigAggregator;
|
||||
use Laminas\ConfigAggregator\PhpFileProvider;
|
||||
|
||||
// To enable or disable caching, set the `ConfigAggregator::ENABLE_CACHE` boolean in
|
||||
// `config/autoload/local.php`.
|
||||
$cacheConfig = [
|
||||
'config_cache_path' => 'data/cache/config-cache.php',
|
||||
];
|
||||
|
||||
$aggregator = new ConfigAggregator([
|
||||
// Include cache configuration
|
||||
new ArrayProvider($cacheConfig),
|
||||
\Mezzio\Helper\ConfigProvider::class,
|
||||
\Mezzio\ConfigProvider::class,
|
||||
\Mezzio\Router\ConfigProvider::class,
|
||||
\Mezzio\Router\LaminasRouter\ConfigProvider::class,
|
||||
|
||||
\Laminas\Diactoros\ConfigProvider::class,
|
||||
\Laminas\HttpHandlerRunner\ConfigProvider::class,
|
||||
\Laminas\Validator\ConfigProvider::class,
|
||||
\Laminas\Router\ConfigProvider::class,
|
||||
|
||||
\Reinfi\DependencyInjection\ConfigProvider::class,
|
||||
|
||||
\DoctrineORMModule\ConfigProvider::class,
|
||||
\DoctrineModule\ConfigProvider::class,
|
||||
|
||||
|
||||
// Swoole config to overwrite some services (if installed)
|
||||
class_exists(\Mezzio\Swoole\ConfigProvider::class)
|
||||
? \Mezzio\Swoole\ConfigProvider::class
|
||||
: function (): array {
|
||||
return [];
|
||||
},
|
||||
|
||||
|
||||
// Data
|
||||
\Homepage\Data\Business\ConfigProvider::class,
|
||||
\Homepage\Data\Log\ConfigProvider::class,
|
||||
|
||||
// Infrastructure
|
||||
\Homepage\Infrastructure\Database\ConfigProvider::class,
|
||||
\Homepage\Infrastructure\DependencyInjection\ConfigProvider::class,
|
||||
\Homepage\Infrastructure\Encryption\ConfigProvider::class,
|
||||
\Homepage\Infrastructure\Exception\ConfigProvider::class,
|
||||
\Homepage\Infrastructure\Logging\ConfigProvider::class,
|
||||
\Homepage\Infrastructure\Rbac\ConfigProvider::class,
|
||||
\Homepage\Infrastructure\Request\ConfigProvider::class,
|
||||
\Homepage\Infrastructure\Session\ConfigProvider::class,
|
||||
|
||||
// HandlingDomain
|
||||
\Homepage\Handling\Product\ConfigProvider::class,
|
||||
\Homepage\Handling\User\ConfigProvider::class,
|
||||
\Homepage\Handling\UserSession\ConfigProvider::class,
|
||||
\Homepage\Handling\Registration\ConfigProvider::class,
|
||||
|
||||
// API
|
||||
/// Command
|
||||
\Homepage\API\Console\ConfigProvider::class,
|
||||
|
||||
/// External
|
||||
\Homepage\API\External\Health\ConfigProvider::class,
|
||||
\Homepage\API\External\Product\ConfigProvider::class,
|
||||
\Homepage\API\External\User\ConfigProvider::class,
|
||||
\Homepage\API\External\Authentication\ConfigProvider::class,
|
||||
|
||||
/// Internal
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Load application config in a pre-defined order in such a way that local settings
|
||||
// overwrite global settings. (Loaded as first to last):
|
||||
// - `global.php`
|
||||
// - `*.global.php`
|
||||
// - `local.php`
|
||||
// - `*.local.php`
|
||||
new PhpFileProvider(realpath(__DIR__) . '/autoload/{{,*.}global,{,*.}local}.php'),
|
||||
|
||||
// Load development config if it exists
|
||||
new PhpFileProvider(realpath(__DIR__) . '/development.config.php'),
|
||||
], $cacheConfig['config_cache_path']);
|
||||
|
||||
return $aggregator->getMergedConfig();
|
||||
21
config/container.php
Normal file
21
config/container.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Laminas\ServiceManager\ServiceManager;
|
||||
use Symfony\Component\Dotenv\Dotenv;
|
||||
|
||||
$dotenv = new Dotenv();
|
||||
|
||||
if (file_exists(__DIR__ . '/../.env')) {
|
||||
$dotenv->load(__DIR__ . '/../.env');
|
||||
}
|
||||
|
||||
// Load configuration
|
||||
$config = require __DIR__ . '/config.php';
|
||||
|
||||
$dependencies = $config['dependencies'];
|
||||
$dependencies['services']['config'] = $config;
|
||||
|
||||
// Build container
|
||||
return new ServiceManager($dependencies);
|
||||
31
config/development.config.php
Normal file
31
config/development.config.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* File required to allow enablement of development mode.
|
||||
*
|
||||
* For use with the laminas-development-mode tool.
|
||||
*
|
||||
* Usage:
|
||||
* $ composer development-disable
|
||||
* $ composer development-enable
|
||||
* $ composer development-status
|
||||
*
|
||||
* DO NOT MODIFY THIS FILE.
|
||||
*
|
||||
* Provide your own development-mode settings by editing the file
|
||||
* `config/autoload/development.local.php.dist`.
|
||||
*
|
||||
* Because this file is aggregated last, it simply ensures:
|
||||
*
|
||||
* - The `debug` flag is _enabled_.
|
||||
* - Configuration caching is _disabled_.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Laminas\ConfigAggregator\ConfigAggregator;
|
||||
|
||||
return [
|
||||
'debug' => true,
|
||||
ConfigAggregator::ENABLE_CACHE => false,
|
||||
];
|
||||
92
config/pipeline.php
Normal file
92
config/pipeline.php
Normal file
@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Homepage\Infrastructure\Exception\Middleware\HomepageExceptionHandlerMiddleware;
|
||||
use Homepage\Infrastructure\Request\Middleware\AnalyzeHeaderMiddleware;
|
||||
use Homepage\Infrastructure\Session\Middleware\SessionMiddleware;
|
||||
use Laminas\Stratigility\Middleware\ErrorHandler;
|
||||
use Mezzio\Application;
|
||||
use Mezzio\Handler\NotFoundHandler;
|
||||
use Mezzio\Helper\ServerUrlMiddleware;
|
||||
use Mezzio\Helper\UrlHelperMiddleware;
|
||||
use Mezzio\MiddlewareFactory;
|
||||
use Mezzio\Router\Middleware\DispatchMiddleware;
|
||||
use Mezzio\Router\Middleware\ImplicitHeadMiddleware;
|
||||
use Mezzio\Router\Middleware\ImplicitOptionsMiddleware;
|
||||
use Mezzio\Router\Middleware\MethodNotAllowedMiddleware;
|
||||
use Mezzio\Router\Middleware\RouteMiddleware;
|
||||
use Psr\Container\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Setup middleware pipeline:
|
||||
*/
|
||||
|
||||
return function (Application $app, MiddlewareFactory $factory, ContainerInterface $container): void {
|
||||
// The error handler should be the first (most outer) middleware to catch
|
||||
// all Exceptions.
|
||||
$app->pipe(ErrorHandler::class);
|
||||
$app->pipe(ServerUrlMiddleware::class);
|
||||
|
||||
// Pipe more middleware here that you want to execute on every request:
|
||||
// - bootstrapping
|
||||
// - pre-conditions
|
||||
// - modifications to outgoing responses
|
||||
//
|
||||
// Piped Middleware may be either callables or service names. Middleware may
|
||||
// also be passed as an array; each item in the array must resolve to
|
||||
// middleware eventually (i.e., callable or service name).
|
||||
//
|
||||
// Middleware can be attached to specific paths, allowing you to mix and match
|
||||
// applications under a common domain. The handlers in each middleware
|
||||
// attached this way will see a URI with the matched path segment removed.
|
||||
//
|
||||
// i.e., path of "/api/member/profile" only passes "/member/profile" to $apiMiddleware
|
||||
// - $app->pipe('/api', $apiMiddleware);
|
||||
// - $app->pipe('/docs', $apiDocMiddleware);
|
||||
// - $app->pipe('/files', $filesMiddleware);
|
||||
|
||||
// Register the routing middleware in the middleware pipeline.
|
||||
// This middleware registers the Mezzio\Router\RouteResult request attribute.
|
||||
$app->pipe(RouteMiddleware::class);
|
||||
|
||||
// The following handle routing failures for common conditions:
|
||||
// - HEAD request but no routes answer that method
|
||||
// - OPTIONS request but no routes answer that method
|
||||
// - method not allowed
|
||||
// Order here matters; the MethodNotAllowedMiddleware should be placed
|
||||
// after the Implicit*Middleware.
|
||||
$app->pipe(ImplicitHeadMiddleware::class);
|
||||
$app->pipe(ImplicitOptionsMiddleware::class);
|
||||
$app->pipe(MethodNotAllowedMiddleware::class);
|
||||
|
||||
// Seed the UrlHelper with the routing results:
|
||||
$app->pipe(UrlHelperMiddleware::class);
|
||||
|
||||
|
||||
|
||||
|
||||
//// Pre Homepage Space
|
||||
$app->pipe(HomepageExceptionHandlerMiddleware::class);
|
||||
$app->pipe(AnalyzeHeaderMiddleware::class);
|
||||
|
||||
//// Homepage Space
|
||||
$app->pipe(SessionMiddleware::class);
|
||||
|
||||
|
||||
|
||||
// Add more middleware here that needs to introspect the routing results; this
|
||||
// might include:
|
||||
//
|
||||
// - route-based authentication
|
||||
// - route-based validation
|
||||
// - etc.
|
||||
|
||||
// Register the dispatch middleware in the middleware pipeline
|
||||
$app->pipe(DispatchMiddleware::class);
|
||||
|
||||
// At this point, if no Response is returned by any middleware, the
|
||||
// NotFoundHandler kicks in; alternately, you can provide other fallback
|
||||
// middleware to execute.
|
||||
$app->pipe(NotFoundHandler::class);
|
||||
};
|
||||
52
config/routes.php
Normal file
52
config/routes.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Mezzio\Application;
|
||||
use Mezzio\MiddlewareFactory;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Homepage\Infrastructure\Session\Middleware\LoggedInUserMiddleware;
|
||||
|
||||
/**
|
||||
* laminas-router route configuration
|
||||
*
|
||||
* @see https://docs.laminas.dev/laminas-router/
|
||||
*
|
||||
* Setup routes with a single request method:
|
||||
*
|
||||
* $app->get('/', App\Handler\HomePageHandler::class, 'home');
|
||||
* $app->post('/album', App\Handler\AlbumCreateHandler::class, 'album.create');
|
||||
* $app->put('/album/:id', App\Handler\AlbumUpdateHandler::class, 'album.put');
|
||||
* $app->patch('/album/:id', App\Handler\AlbumUpdateHandler::class, 'album.patch');
|
||||
* $app->delete('/album/:id', App\Handler\AlbumDeleteHandler::class, 'album.delete');
|
||||
*
|
||||
* Or with multiple request methods:
|
||||
*
|
||||
* $app->route('/contact', App\Handler\ContactHandler::class, ['GET', 'POST', ...], 'contact');
|
||||
*
|
||||
* Or handling all request methods:
|
||||
*
|
||||
* $app->route('/contact', App\Handler\ContactHandler::class)->setName('contact');
|
||||
*
|
||||
* or:
|
||||
*
|
||||
* $app->route(
|
||||
* '/contact',
|
||||
* App\Handler\ContactHandler::class,
|
||||
* Mezzio\Router\Route::HTTP_METHOD_ANY,
|
||||
* 'contact'
|
||||
* );
|
||||
*/
|
||||
|
||||
return static function (Application $app, MiddlewareFactory $factory, ContainerInterface $container): void {
|
||||
$config = $container->get('config');
|
||||
|
||||
foreach ($config['routes'] as $routeConfig) {
|
||||
$app->route(
|
||||
name: $routeConfig['name'],
|
||||
path: $routeConfig['path'],
|
||||
middleware: $routeConfig['middleware'],
|
||||
methods: $routeConfig['allowed_methods']
|
||||
);
|
||||
}
|
||||
};
|
||||
33
data/migrations/homepage/Version20230922085011.php
Normal file
33
data/migrations/homepage/Version20230922085011.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Homepage\Migrations\Homepage;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
final class Version20230922085011 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return "Create Table 'role'";
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$sql = "CREATE TABLE role (
|
||||
id binary(16) NOT NULL,
|
||||
product_id binary(16) DEFAULT NULL,
|
||||
identifier varchar(255) UNIQUE NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);";
|
||||
|
||||
$this->addSql($sql);
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql("DROP TABLE role;");
|
||||
}
|
||||
}
|
||||
36
data/migrations/homepage/Version20230922092351.php
Normal file
36
data/migrations/homepage/Version20230922092351.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Homepage\Migrations\Homepage;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20230922092351 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return "Create Table 'permission'";
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$sql = "CREATE TABLE permission (
|
||||
id binary(16) NOT NULL,
|
||||
product_id binary(16) DEFAULT NULL,
|
||||
identifier varchar(255) UNIQUE NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);";
|
||||
|
||||
$this->addSql($sql);
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql("DROP TABLE permission;");
|
||||
}
|
||||
}
|
||||
36
data/migrations/homepage/Version20230922092754.php
Normal file
36
data/migrations/homepage/Version20230922092754.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Homepage\Migrations\Homepage;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20230922092754 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return "Create Table 'role_permission'";
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$sql = "CREATE TABLE role_permission (
|
||||
id binary(16) NOT NULL DEFAULT (uuid_to_bin(uuid())),
|
||||
role_id binary(16) NOT NULL,
|
||||
permission_id binary(16) NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);";
|
||||
|
||||
$this->addSql($sql);
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql("DROP TABLE role_permission;");
|
||||
}
|
||||
}
|
||||
38
data/migrations/homepage/Version20230922101352.php
Normal file
38
data/migrations/homepage/Version20230922101352.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Homepage\Migrations\Homepage;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20230922101352 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return "Create Table 'product'";
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$sql = "CREATE TABLE product (
|
||||
id binary(16) NOT NULL,
|
||||
identifier varchar(255) UNIQUE NOT NULL,
|
||||
name varchar(255) DEFAULT 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 product;");
|
||||
}
|
||||
}
|
||||
41
data/migrations/homepage/Version20230922101354.php
Normal file
41
data/migrations/homepage/Version20230922101354.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Homepage\Migrations\Homepage;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20230922101354 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return "Create Table 'user'";
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$sql = "CREATE TABLE user (
|
||||
id binary(16) NOT NULL,
|
||||
role_id binary(16) NOT NULL,
|
||||
username varchar(255) UNIQUE NOT NULL,
|
||||
mail varchar(255) UNIQUE NOT NULL,
|
||||
password varchar(255) UNIQUE NOT NULL,
|
||||
last_login_at datetime DEFAULT 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;");
|
||||
}
|
||||
}
|
||||
38
data/migrations/homepage/Version20230922101355.php
Normal file
38
data/migrations/homepage/Version20230922101355.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Homepage\Migrations\Homepage;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20230922101355 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return "Create Table 'user_session'";
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$sql = "CREATE TABLE user_session (
|
||||
id binary(16) NOT NULL,
|
||||
user_id binary(16) DEFAULT NULL,
|
||||
csrf binary(16) DEFAULT 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 role_permission;");
|
||||
}
|
||||
}
|
||||
38
data/migrations/homepage/Version20230924113403.php
Normal file
38
data/migrations/homepage/Version20230924113403.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Homepage\Migrations\Homepage;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20230924113403 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return "Create Table 'registration'";
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$sql = "CREATE TABLE registration (
|
||||
id binary(16) NOT NULL,
|
||||
mail varchar(255) NOT NULL,
|
||||
username varchar(255) NOT NULL,
|
||||
password varchar(255) NOT NULL,
|
||||
created_at datetime NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);";
|
||||
|
||||
$this->addSql($sql);
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql("DROP TABLE registration;");
|
||||
}
|
||||
}
|
||||
33
data/migrations/homepage/Version20231021103120.php
Normal file
33
data/migrations/homepage/Version20231021103120.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Homepage\Migrations\Homepage;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20231021103120 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'drop password from registration';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$sql = "ALTER TABLE registration DROP COLUMN password;";
|
||||
|
||||
$this->addSql($sql);
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$sql = "ALTER TABLE registration ADD COLUMN password varchar(255) NOT NULL after username";
|
||||
|
||||
$this->addSql($sql);
|
||||
}
|
||||
}
|
||||
33
data/migrations/homepage/Version20231021112654.php
Normal file
33
data/migrations/homepage/Version20231021112654.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Homepage\Migrations\Homepage;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20231021112654 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Add url to product';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$sql = "ALTER TABLE product ADD COLUMN url varchar(255) NULL after name";
|
||||
|
||||
$this->addSql($sql);
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$sql = "ALTER TABLE product DROP COLUMN url;";
|
||||
|
||||
$this->addSql($sql);
|
||||
}
|
||||
}
|
||||
40
data/migrations/log/Version20230922150649.php
Normal file
40
data/migrations/log/Version20230922150649.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Homepage\Migrations\Log;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20230922150649 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return "Create Table 'log'";
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$query = 'CREATE TABLE log (
|
||||
id BINARY(16) NOT NULL,
|
||||
message TEXT NOT NULL,
|
||||
context JSON DEFAULT NULL,
|
||||
level INT NOT NULL ,
|
||||
level_name VARCHAR(50) NOT NULL,
|
||||
extra JSON DEFAULT NULL,
|
||||
created_at datetime NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
)';
|
||||
|
||||
$this->addSql($query);
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('DROP TABLE log');
|
||||
}
|
||||
}
|
||||
51
docker/docker-compose-mac.yml
Normal file
51
docker/docker-compose-mac.yml
Normal file
@ -0,0 +1,51 @@
|
||||
version: '3'
|
||||
networks:
|
||||
homepage:
|
||||
external: true
|
||||
|
||||
services:
|
||||
homepage-backend-mysql:
|
||||
image: homepage-backend-mysql
|
||||
networks:
|
||||
- homepage
|
||||
build:
|
||||
context: ./../
|
||||
dockerfile: ./docker/mysql/dockerfile
|
||||
volumes:
|
||||
- /Users/flo/dev/backend/homepage/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
|
||||
|
||||
homepage-backend-app:
|
||||
image: homepage-backend-app
|
||||
networks:
|
||||
- homepage
|
||||
build:
|
||||
context: ./../
|
||||
dockerfile: ./docker/php/dockerfile
|
||||
volumes:
|
||||
- /Users/flo/dev/backend/homepage/:/var/www/html:z
|
||||
ports:
|
||||
- 9000:9000
|
||||
depends_on:
|
||||
homepage-backend-mysql:
|
||||
condition: service_healthy
|
||||
|
||||
homepage-backend-nginx:
|
||||
image: homepage-backend-nginx
|
||||
networks:
|
||||
- homepage
|
||||
build:
|
||||
context: ./../
|
||||
dockerfile: ./docker/nginx/dockerfile
|
||||
ports:
|
||||
- 8080:80
|
||||
depends_on:
|
||||
- homepage-backend-app
|
||||
51
docker/docker-compose.yml
Normal file
51
docker/docker-compose.yml
Normal file
@ -0,0 +1,51 @@
|
||||
version: '3'
|
||||
networks:
|
||||
homepage:
|
||||
external: true
|
||||
|
||||
services:
|
||||
homepage-backend-mysql:
|
||||
image: homepage-backend-mysql
|
||||
networks:
|
||||
- homepage
|
||||
build:
|
||||
context: ./../
|
||||
dockerfile: ./docker/mysql/dockerfile
|
||||
volumes:
|
||||
- ./../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
|
||||
|
||||
homepage-backend-app:
|
||||
image: homepage-backend-app
|
||||
networks:
|
||||
- homepage
|
||||
build:
|
||||
context: ./../
|
||||
dockerfile: ./docker/php/dockerfile
|
||||
volumes:
|
||||
- ./../:/var/www/html:z
|
||||
ports:
|
||||
- 9000:9000
|
||||
depends_on:
|
||||
homepage-backend-mysql:
|
||||
condition: service_healthy
|
||||
|
||||
homepage-backend-nginx:
|
||||
image: homepage-backend-nginx
|
||||
networks:
|
||||
- homepage
|
||||
build:
|
||||
context: ./../
|
||||
dockerfile: ./docker/nginx/dockerfile
|
||||
ports:
|
||||
- 8080:80
|
||||
depends_on:
|
||||
- homepage-backend-app
|
||||
7
docker/mysql/dockerfile
Normal file
7
docker/mysql/dockerfile
Normal file
@ -0,0 +1,7 @@
|
||||
FROM mysql:latest
|
||||
|
||||
ENV MYSQL_RANDOM_ROOT_PASSWORD=1
|
||||
|
||||
COPY docker/mysql/scripts /docker-entrypoint-initdb.d/
|
||||
|
||||
CMD ["mysqld"]
|
||||
4
docker/mysql/scripts/initdb.sql
Normal file
4
docker/mysql/scripts/initdb.sql
Normal file
@ -0,0 +1,4 @@
|
||||
CREATE DATABASE IF NOT EXISTS `log`;
|
||||
CREATE DATABASE IF NOT EXISTS `homepage`;
|
||||
|
||||
GRANT ALL PRIVILEGES on *.* to 'homepage'@'%';
|
||||
15
docker/nginx/config/nginx.conf
Normal file
15
docker/nginx/config/nginx.conf
Normal file
@ -0,0 +1,15 @@
|
||||
upstream host-backend-app {
|
||||
server homepage-backend-app:9000;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80 default_server;
|
||||
|
||||
location / {
|
||||
fastcgi_pass host-backend-app;
|
||||
fastcgi_index index.php;
|
||||
|
||||
include fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME /var/www/html/public/index.php;
|
||||
}
|
||||
}
|
||||
3
docker/nginx/config/upstream.conf
Normal file
3
docker/nginx/config/upstream.conf
Normal file
@ -0,0 +1,3 @@
|
||||
upstream backend-dev {
|
||||
server backend-app:9000;
|
||||
}
|
||||
5
docker/nginx/dockerfile
Normal file
5
docker/nginx/dockerfile
Normal file
@ -0,0 +1,5 @@
|
||||
FROM nginx:alpine
|
||||
|
||||
COPY docker/nginx/config/nginx.conf /etc/nginx/conf.d/default.conf
|
||||
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
15
docker/php/dockerfile
Normal file
15
docker/php/dockerfile
Normal file
@ -0,0 +1,15 @@
|
||||
FROM php:8.1-fpm
|
||||
|
||||
RUN apt-get -y update
|
||||
RUN apt-get -y install git
|
||||
|
||||
RUN chown -R www-data:www-data /var/www/html
|
||||
WORKDIR /var/www/html
|
||||
|
||||
RUN docker-php-ext-install pdo pdo_mysql
|
||||
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
|
||||
|
||||
RUN useradd -m docker && echo "docker:docker" | chpasswd && adduser docker sudo
|
||||
USER docker
|
||||
|
||||
CMD ["php-fpm"]
|
||||
26
phpunit.xml.dist
Normal file
26
phpunit.xml.dist
Normal file
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
|
||||
beStrictAboutCoversAnnotation="true"
|
||||
beStrictAboutOutputDuringTests="true"
|
||||
beStrictAboutTodoAnnotatedTests="true"
|
||||
bootstrap="vendor/autoload.php"
|
||||
convertDeprecationsToExceptions="true"
|
||||
executionOrder="depends,defects"
|
||||
failOnRisky="true"
|
||||
failOnWarning="true"
|
||||
verbose="true"
|
||||
colors="true">
|
||||
<testsuites>
|
||||
<testsuite name="default">
|
||||
<directory suffix="Test.php">test</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<coverage processUncoveredFiles="true">
|
||||
<include>
|
||||
<directory suffix=".php">src</directory>
|
||||
</include>
|
||||
</coverage>
|
||||
</phpunit>
|
||||
19
public/.htaccess
Normal file
19
public/.htaccess
Normal file
@ -0,0 +1,19 @@
|
||||
RewriteEngine On
|
||||
# The following rule allows authentication to work with fast-cgi
|
||||
RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
|
||||
# The following rule tells Apache that if the requested filename
|
||||
# exists, simply serve it.
|
||||
RewriteCond %{REQUEST_FILENAME} -f [OR]
|
||||
RewriteCond %{REQUEST_FILENAME} -l [OR]
|
||||
RewriteCond %{REQUEST_FILENAME} -d
|
||||
RewriteRule ^ - [NC,L]
|
||||
|
||||
# The following rewrites all other queries to index.php. The
|
||||
# condition ensures that if you are using Apache aliases to do
|
||||
# mass virtual hosting, the base path will be prepended to
|
||||
# allow proper resolution of the index.php file; it will work
|
||||
# in non-aliased environments as well, providing a safe, one-size
|
||||
# fits all solution.
|
||||
RewriteCond $0::%{REQUEST_URI} ^([^:]*+(?::[^:]*+)*?)::(/.+?)\1$
|
||||
RewriteRule .+ - [E=BASE:%2]
|
||||
RewriteRule .* %{ENV:BASE}index.php [NC,L]
|
||||
48
public/index.php
Normal file
48
public/index.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Mezzio\Application;
|
||||
use Mezzio\MiddlewareFactory;
|
||||
|
||||
if (PHP_SAPI === 'cli-server' && $_SERVER['SCRIPT_FILENAME'] !== __FILE__) {
|
||||
return false;
|
||||
}
|
||||
|
||||
require './../vendor/autoload.php';
|
||||
|
||||
require './../config/autoload/defines.php';
|
||||
|
||||
function throwableToMessageArray(Throwable $e): array {
|
||||
$messageArray = [];
|
||||
while($e !== null) {
|
||||
$messageArray[] = $e->getMessage();
|
||||
$e = $e->getPrevious();
|
||||
}
|
||||
return $messageArray;
|
||||
}
|
||||
|
||||
function throwableToMessageArrayString(Throwable $e): string {
|
||||
return implode( PHP_EOL, throwableToMessageArray($e) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Self-called anonymous function that creates its own scope and keeps the global namespace clean.
|
||||
*/
|
||||
(function () {
|
||||
|
||||
/** @var \Psr\Container\ContainerInterface $container */
|
||||
$container = require './../config/container.php';
|
||||
|
||||
/** @var Application $app */
|
||||
$app = $container->get(Application::class);
|
||||
$factory = $container->get(MiddlewareFactory::class);
|
||||
|
||||
// Execute programmatic/declarative middleware pipeline and routing
|
||||
// configuration statements
|
||||
(require './../config/pipeline.php')($app, $factory, $container);
|
||||
(require './../config/routes.php')($app, $factory, $container);
|
||||
|
||||
$app->run();
|
||||
|
||||
})();
|
||||
11
src/ApiDomain/Console/config/console.php
Normal file
11
src/ApiDomain/Console/config/console.php
Normal file
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
use Homepage\API\Console\Command\InitializeDataCommand;
|
||||
use Homepage\API\Console\Command\RbacUpdateCommand;
|
||||
|
||||
return [
|
||||
'commands' => [
|
||||
InitializeDataCommand::class,
|
||||
RbacUpdateCommand::class,
|
||||
]
|
||||
];
|
||||
12
src/ApiDomain/Console/config/service_manager.php
Normal file
12
src/ApiDomain/Console/config/service_manager.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
use Homepage\API\Console\Command\InitializeDataCommand;
|
||||
use Homepage\API\Console\Command\RbacUpdateCommand;
|
||||
use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
|
||||
|
||||
return [
|
||||
'factories' => [
|
||||
InitializeDataCommand::class => AutoWiringFactory::class,
|
||||
RbacUpdateCommand::class => AutoWiringFactory::class,
|
||||
],
|
||||
];
|
||||
80
src/ApiDomain/Console/src/Command/InitializeDataCommand.php
Normal file
80
src/ApiDomain/Console/src/Command/InitializeDataCommand.php
Normal file
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace Homepage\API\Console\Command;
|
||||
|
||||
use Homepage\Data\Business\Entity\Role;
|
||||
use Homepage\Data\Business\Entity\User;
|
||||
use Homepage\Data\Business\Repository\RoleRepository;
|
||||
use Homepage\Data\Business\Repository\UserRepository;
|
||||
use Homepage\Data\Business\Manager\HomepageEntityManager;
|
||||
use Homepage\Infrastructure\Encryption\Client\EncryptionClient;
|
||||
use Homepage\Infrastructure\Logging\Logger\Logger;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
#[AsCommand(name: 'init:data', description: 'Initializes the applications data')]
|
||||
class InitializeDataCommand extends Command
|
||||
{
|
||||
private readonly RoleRepository $roleRepository;
|
||||
private readonly UserRepository $userRepository;
|
||||
|
||||
public function __construct(
|
||||
private readonly EncryptionClient $encryptionClient,
|
||||
private readonly HomepageEntityManager $entityManager,
|
||||
private readonly Logger $logger,
|
||||
) {
|
||||
parent::__construct($this->getName());
|
||||
|
||||
$this->roleRepository = $this->entityManager->getRepository(Role::class);
|
||||
$this->userRepository = $this->entityManager->getRepository(User::class);
|
||||
}
|
||||
|
||||
protected function execute(
|
||||
InputInterface $input,
|
||||
OutputInterface $output
|
||||
): int {
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
|
||||
try {
|
||||
$admin = $this->roleRepository->findOneBy([
|
||||
'identifier' => 'admin'
|
||||
]) ?? null;
|
||||
if ($admin === null) {
|
||||
throw new \Exception('Admin role does not exist!');
|
||||
}
|
||||
|
||||
$adminUser = $this->userRepository->findOneBy([
|
||||
'roleId' => $admin->getId()
|
||||
]) ?? null;
|
||||
|
||||
if ($adminUser === null) {
|
||||
$io->info('Create admin');
|
||||
|
||||
$adminUser = new User();
|
||||
$adminUser->setRole($admin);
|
||||
$adminUser->setUsername($_ENV['INIT_USER_NAME']);
|
||||
$adminUser->setMail($_ENV['INIT_USER_MAIL']);
|
||||
$adminUser->setPassword(
|
||||
$this->encryptionClient->encrypt(
|
||||
$_ENV['INIT_USER_PASSWORD']
|
||||
)
|
||||
);
|
||||
|
||||
$this->entityManager->persist($adminUser);
|
||||
$this->entityManager->flush();
|
||||
}
|
||||
|
||||
$io->success('OK!');
|
||||
} catch (\Throwable $e) {
|
||||
$io->error($e->getMessage());
|
||||
$io->error($e->getTraceAsString());
|
||||
$this->logger->error($e->getMessage(), ['exception' => $e]);
|
||||
return Command::FAILURE;
|
||||
}
|
||||
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
}
|
||||
98
src/ApiDomain/Console/src/Command/RbacUpdateCommand.php
Normal file
98
src/ApiDomain/Console/src/Command/RbacUpdateCommand.php
Normal file
@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace Homepage\API\Console\Command;
|
||||
|
||||
use Homepage\Data\Business\Entity\Permission;
|
||||
use Homepage\Data\Business\Entity\Role;
|
||||
use Homepage\Data\Business\Repository\PermissionRepository;
|
||||
use Homepage\Data\Business\Repository\RoleRepository;
|
||||
use Homepage\Data\Business\Manager\HomepageEntityManager;
|
||||
use Homepage\Infrastructure\Logging\Logger\Logger;
|
||||
use Reinfi\DependencyInjection\Service\ConfigService;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
#[AsCommand(name: 'rbac:update', description: 'Updates RBAC entries in DB')]
|
||||
class RbacUpdateCommand extends Command
|
||||
{
|
||||
private array $rbacConfig;
|
||||
private RoleRepository $roleRepository;
|
||||
private PermissionRepository $permissionRepository;
|
||||
|
||||
public function __construct(
|
||||
private readonly ConfigService $configService,
|
||||
private readonly HomepageEntityManager $entityManager,
|
||||
private readonly Logger $logger,
|
||||
) {
|
||||
parent::__construct($this->getName());
|
||||
|
||||
$this->roleRepository = $this->entityManager->getRepository(Role::class);
|
||||
$this->permissionRepository = $this->entityManager->getRepository(Permission::class);
|
||||
|
||||
$this->rbacConfig = $this->configService->resolve('homepage-rbac')->toArray();
|
||||
}
|
||||
|
||||
protected function execute(
|
||||
InputInterface $input,
|
||||
OutputInterface $output
|
||||
): int {
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
|
||||
try {
|
||||
|
||||
$roles = [];
|
||||
|
||||
foreach ($this->rbacConfig['roles'] as $roleIdentifier) {
|
||||
$role = $this->roleRepository->findOneBy([
|
||||
'identifier' => $roleIdentifier
|
||||
]) ?? null;
|
||||
|
||||
if ($role === null) {
|
||||
$role = new Role();
|
||||
$role->setIdentifier($roleIdentifier);
|
||||
|
||||
$this->entityManager->persist($role);
|
||||
$this->entityManager->flush();
|
||||
}
|
||||
|
||||
$roles[$roleIdentifier] = $role;
|
||||
}
|
||||
|
||||
foreach ($roles as $role) {
|
||||
$roleIdentifier = $role->getIdentifier();
|
||||
|
||||
foreach ($this->rbacConfig['permissions'][$roleIdentifier] as $permissionIdentifier) {
|
||||
$io->info($role->getIdentifier() . '.' . $permissionIdentifier);
|
||||
|
||||
$permission = $this->permissionRepository->findOneBy([
|
||||
'identifier' => $permissionIdentifier
|
||||
]) ?? null;
|
||||
|
||||
if ($permission === null) {
|
||||
$permission = new Permission();
|
||||
$permission->setIdentifier($permissionIdentifier);
|
||||
|
||||
$this->entityManager->persist($permission);
|
||||
$this->entityManager->flush();
|
||||
}
|
||||
|
||||
$role->addPermission($permission);
|
||||
$this->entityManager->persist($role);
|
||||
$this->entityManager->flush();
|
||||
}
|
||||
}
|
||||
|
||||
$io->success('OK!');
|
||||
} catch (\Throwable $e) {
|
||||
$io->error($e->getMessage());
|
||||
$io->error($e->getTraceAsString());
|
||||
$this->logger->error($e->getMessage(), ['exception' => $e]);
|
||||
return Command::FAILURE;
|
||||
}
|
||||
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
}
|
||||
16
src/ApiDomain/Console/src/ConfigProvider.php
Normal file
16
src/ApiDomain/Console/src/ConfigProvider.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Homepage\API\Console;
|
||||
|
||||
class ConfigProvider
|
||||
{
|
||||
public function __invoke(): array
|
||||
{
|
||||
return [
|
||||
'dependencies' => require __DIR__ . './../config/service_manager.php',
|
||||
'console' => require __DIR__ . '/./../config/console.php',
|
||||
];
|
||||
}
|
||||
}
|
||||
43
src/ApiDomain/External/Authentication/config/routes.php
vendored
Normal file
43
src/ApiDomain/External/Authentication/config/routes.php
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
use Homepage\API\External\Authentication\Handler\ConfirmRegistrationHandler;
|
||||
use Homepage\API\External\Authentication\Handler\LoginUserHandler;
|
||||
use Homepage\API\External\Authentication\Handler\LogoutUserHandler;
|
||||
use Homepage\API\External\Authentication\Handler\RegisterUserHandler;
|
||||
use Homepage\Infrastructure\Session\Middleware\LoggedInUserMiddleware;
|
||||
|
||||
return [
|
||||
[
|
||||
'name' => 'auth.login-user',
|
||||
'path' => '/api/auth/login-user',
|
||||
'allowed_methods' => ['POST'],
|
||||
'middleware' => [
|
||||
LoginUserHandler::class
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'auth.logout-user',
|
||||
'path' => '/api/auth/logout-user',
|
||||
'allowed_methods' => ['POST'],
|
||||
'middleware' => [
|
||||
LoggedInUserMiddleware::class,
|
||||
LogoutUserHandler::class
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'auth.confirm-registration',
|
||||
'path' => '/api/auth/confirm-registration',
|
||||
'allowed_methods' => ['POST'],
|
||||
'middleware' => [
|
||||
ConfirmRegistrationHandler::class
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'auth.register-user',
|
||||
'path' => '/api/auth/register-user',
|
||||
'allowed_methods' => ['POST'],
|
||||
'middleware' => [
|
||||
RegisterUserHandler::class
|
||||
],
|
||||
],
|
||||
];
|
||||
17
src/ApiDomain/External/Authentication/config/service_manager.php
vendored
Normal file
17
src/ApiDomain/External/Authentication/config/service_manager.php
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
use Homepage\API\External\Authentication\Handler\ConfirmRegistrationHandler;
|
||||
use Homepage\API\External\Authentication\Handler\LoginUserHandler;
|
||||
use Homepage\API\External\Authentication\Handler\LogoutUserHandler;
|
||||
use Homepage\API\External\Authentication\Handler\RegisterUserHandler;
|
||||
use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
|
||||
|
||||
return [
|
||||
'factories' => [
|
||||
// Handler
|
||||
LoginUserHandler::class => AutoWiringFactory::class,
|
||||
LogoutUserHandler::class => AutoWiringFactory::class,
|
||||
ConfirmRegistrationHandler::class => AutoWiringFactory::class,
|
||||
RegisterUserHandler::class => AutoWiringFactory::class
|
||||
],
|
||||
];
|
||||
16
src/ApiDomain/External/Authentication/src/ConfigProvider.php
vendored
Normal file
16
src/ApiDomain/External/Authentication/src/ConfigProvider.php
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Homepage\API\External\Authentication;
|
||||
|
||||
class ConfigProvider
|
||||
{
|
||||
public function __invoke(): array
|
||||
{
|
||||
return [
|
||||
'dependencies' => require __DIR__ . '/./../config/service_manager.php',
|
||||
'routes' => require __DIR__ . '/./../config/routes.php',
|
||||
];
|
||||
}
|
||||
}
|
||||
44
src/ApiDomain/External/Authentication/src/Handler/ConfirmRegistrationHandler.php
vendored
Normal file
44
src/ApiDomain/External/Authentication/src/Handler/ConfirmRegistrationHandler.php
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Homepage\API\External\Authentication\Handler;
|
||||
|
||||
use Homepage\API\External\User\Formatter\UserFormatter;
|
||||
use Homepage\Handling\Registration\Handler\Command\ConfirmRegistration\ConfirmRegistrationCommandBuilder;
|
||||
use Homepage\Handling\Registration\Handler\Command\ConfirmRegistration\ConfirmRegistrationCommandHandler;
|
||||
use Homepage\Infrastructure\Session\Middleware\SessionMiddleware;
|
||||
use Laminas\Diactoros\Response\JsonResponse;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
|
||||
class ConfirmRegistrationHandler implements RequestHandlerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private readonly ConfirmRegistrationCommandHandler $handler,
|
||||
private readonly ConfirmRegistrationCommandBuilder $builder,
|
||||
private readonly UserFormatter $userFormatter
|
||||
) {
|
||||
}
|
||||
|
||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
$data = json_decode(
|
||||
$request->getBody()->getContents(),
|
||||
true
|
||||
);
|
||||
|
||||
$query = $this->builder->build(
|
||||
Uuid::fromString($data['id']),
|
||||
$data['password'],
|
||||
$data['passwordConfirmation'],
|
||||
);
|
||||
|
||||
$result = $this->handler->execute($query);
|
||||
return new JsonResponse(
|
||||
$this->userFormatter->format($result)
|
||||
);
|
||||
}
|
||||
}
|
||||
42
src/ApiDomain/External/Authentication/src/Handler/LoginUserHandler.php
vendored
Normal file
42
src/ApiDomain/External/Authentication/src/Handler/LoginUserHandler.php
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Homepage\API\External\Authentication\Handler;
|
||||
|
||||
use Homepage\Handling\UserSession\Handler\Command\LoginUser\LoginUserCommandBuilder;
|
||||
use Homepage\Handling\UserSession\Handler\Command\LoginUser\LoginUserCommandHandler;
|
||||
use Homepage\Infrastructure\Session\Middleware\SessionMiddleware;
|
||||
use Laminas\Diactoros\Response\JsonResponse;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
|
||||
class LoginUserHandler implements RequestHandlerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private readonly LoginUserCommandHandler $handler,
|
||||
private readonly LoginUserCommandBuilder $builder
|
||||
) {
|
||||
}
|
||||
|
||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
$session = $request->getAttribute(SessionMiddleware::SESSION_ATTRIBUTE);
|
||||
$data = json_decode(
|
||||
$request->getBody()->getContents(),
|
||||
true
|
||||
);
|
||||
|
||||
$query = $this->builder->build(
|
||||
$session,
|
||||
$data['identifier'],
|
||||
$data['password'],
|
||||
);
|
||||
|
||||
$result = $this->handler->execute($query);
|
||||
return new JsonResponse([
|
||||
'sessionId' => $result->getId()->toString()
|
||||
]);
|
||||
}
|
||||
}
|
||||
35
src/ApiDomain/External/Authentication/src/Handler/LogoutUserHandler.php
vendored
Normal file
35
src/ApiDomain/External/Authentication/src/Handler/LogoutUserHandler.php
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Homepage\API\External\Authentication\Handler;
|
||||
|
||||
use Homepage\Handling\UserSession\Handler\Command\LogoutUser\LogoutUserCommandBuilder;
|
||||
use Homepage\Handling\UserSession\Handler\Command\LogoutUser\LogoutUserCommandHandler;
|
||||
use Homepage\Infrastructure\Response\SuccessResponse;
|
||||
use Homepage\Infrastructure\Session\Middleware\SessionMiddleware;
|
||||
use Laminas\Diactoros\Response\JsonResponse;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
|
||||
class LogoutUserHandler implements RequestHandlerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private readonly LogoutUserCommandHandler $handler,
|
||||
private readonly LogoutUserCommandBuilder $builder
|
||||
) {
|
||||
}
|
||||
|
||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
$session = $request->getAttribute(SessionMiddleware::SESSION_ATTRIBUTE);
|
||||
|
||||
$query = $this->builder->build(
|
||||
$session
|
||||
);
|
||||
$this->handler->execute($query);
|
||||
|
||||
return new JsonResponse('OK');
|
||||
}
|
||||
}
|
||||
45
src/ApiDomain/External/Authentication/src/Handler/RegisterUserHandler.php
vendored
Normal file
45
src/ApiDomain/External/Authentication/src/Handler/RegisterUserHandler.php
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Homepage\API\External\Authentication\Handler;
|
||||
|
||||
use Homepage\Handling\Registration\Handler\Command\RegisterUser\RegisterUserCommandBuilder;
|
||||
use Homepage\Handling\Registration\Handler\Command\RegisterUser\RegisterUserCommandHandler;
|
||||
use Homepage\Infrastructure\Exception\Middleware\HomepageExceptionHandlerMiddleware;
|
||||
use Homepage\Infrastructure\Logging\Logger\Logger;
|
||||
use Homepage\Infrastructure\Request\Middleware\AnalyzeHeaderMiddleware;
|
||||
use Homepage\Infrastructure\Response\SuccessResponse;
|
||||
use Homepage\Infrastructure\Session\Middleware\SessionMiddleware;
|
||||
use Laminas\Diactoros\Response\JsonResponse;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
|
||||
class RegisterUserHandler implements RequestHandlerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private readonly RegisterUserCommandHandler $handler,
|
||||
private readonly RegisterUserCommandBuilder $builder,
|
||||
private readonly Logger $logger
|
||||
) {
|
||||
}
|
||||
|
||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
$host = $request->getAttribute(AnalyzeHeaderMiddleware::HOST_ATTRIBUTE);
|
||||
$data = json_decode(
|
||||
$request->getBody()->getContents(),
|
||||
true
|
||||
);
|
||||
|
||||
$query = $this->builder->build(
|
||||
$data['username'],
|
||||
$data['mail'],
|
||||
$host
|
||||
);
|
||||
|
||||
$this->handler->execute($query);
|
||||
return new SuccessResponse();
|
||||
}
|
||||
}
|
||||
16
src/ApiDomain/External/Health/config/routes.php
vendored
Normal file
16
src/ApiDomain/External/Health/config/routes.php
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
use Homepage\API\External\Health\Handler\HealthHandler;
|
||||
|
||||
return [
|
||||
[
|
||||
'name' => 'health',
|
||||
'path' => '/api/health',
|
||||
'allowed_methods' => ['GET'],
|
||||
'middleware' => [
|
||||
HealthHandler::class
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
?>
|
||||
12
src/ApiDomain/External/Health/config/service_manager.php
vendored
Normal file
12
src/ApiDomain/External/Health/config/service_manager.php
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
use Homepage\API\External\Health\Handler\HealthHandler;
|
||||
use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
|
||||
|
||||
return [
|
||||
'factories' => [
|
||||
HealthHandler::class => AutoWiringFactory::class
|
||||
],
|
||||
]
|
||||
|
||||
?>
|
||||
16
src/ApiDomain/External/Health/src/ConfigProvider.php
vendored
Normal file
16
src/ApiDomain/External/Health/src/ConfigProvider.php
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Homepage\API\External\Health;
|
||||
|
||||
class ConfigProvider
|
||||
{
|
||||
public function __invoke(): array
|
||||
{
|
||||
return [
|
||||
'dependencies' => require __DIR__ . './../config/service_manager.php',
|
||||
'routes' => require __DIR__ . '/./../config/routes.php',
|
||||
];
|
||||
}
|
||||
}
|
||||
23
src/ApiDomain/External/Health/src/Handler/HealthHandler.php
vendored
Normal file
23
src/ApiDomain/External/Health/src/Handler/HealthHandler.php
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Homepage\API\External\Health\Handler;
|
||||
|
||||
use Laminas\Diactoros\Response\JsonResponse;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
|
||||
class HealthHandler implements RequestHandlerInterface
|
||||
{
|
||||
public function __construct() {
|
||||
}
|
||||
|
||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
return new JsonResponse("I'm fine. :)");
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
51
src/ApiDomain/External/Product/config/routes.php
vendored
Normal file
51
src/ApiDomain/External/Product/config/routes.php
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
use Homepage\API\External\Product\Handler\CreateProductHandler;
|
||||
use Homepage\API\External\Product\Handler\DeleteProductHandler;
|
||||
use Homepage\API\External\Product\Handler\ProductListHandler;
|
||||
use Homepage\API\External\Product\Handler\UpdateProductHandler;
|
||||
use Homepage\Infrastructure\Rbac\Middleware\EnsureAuthorizationMiddleware;
|
||||
use Homepage\Infrastructure\Session\Middleware\LoggedInUserMiddleware;
|
||||
|
||||
return [
|
||||
[
|
||||
'name' => 'product.product-list',
|
||||
'path' => '/api/product/product-list',
|
||||
'allowed_methods' => ['GET'],
|
||||
'middleware' => [
|
||||
LoggedInUserMiddleware::class,
|
||||
EnsureAuthorizationMiddleware::class,
|
||||
ProductListHandler::class
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'product.create-product',
|
||||
'path' => '/api/product/create-product',
|
||||
'allowed_methods' => ['POST'],
|
||||
'middleware' => [
|
||||
LoggedInUserMiddleware::class,
|
||||
EnsureAuthorizationMiddleware::class,
|
||||
CreateProductHandler::class
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'product.delete-product',
|
||||
'path' => '/api/product/delete-product',
|
||||
'allowed_methods' => ['POST'],
|
||||
'middleware' => [
|
||||
LoggedInUserMiddleware::class,
|
||||
EnsureAuthorizationMiddleware::class,
|
||||
DeleteProductHandler::class
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'product.update-product',
|
||||
'path' => '/api/product/update-product',
|
||||
'allowed_methods' => ['POST'],
|
||||
'middleware' => [
|
||||
LoggedInUserMiddleware::class,
|
||||
EnsureAuthorizationMiddleware::class,
|
||||
UpdateProductHandler::class
|
||||
],
|
||||
],
|
||||
];
|
||||
25
src/ApiDomain/External/Product/config/service_manager.php
vendored
Normal file
25
src/ApiDomain/External/Product/config/service_manager.php
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
use Homepage\API\External\Product\Formatter\ProductFormatter;
|
||||
use Homepage\API\External\Product\Formatter\ProductListFormatter;
|
||||
use Homepage\API\External\Product\Handler\CreateProductHandler;
|
||||
use Homepage\API\External\Product\Handler\DeleteProductHandler;
|
||||
use Homepage\API\External\Product\Handler\ProductListHandler;
|
||||
use Homepage\API\External\Product\Handler\UpdateProductHandler;
|
||||
use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
|
||||
|
||||
return [
|
||||
'factories' => [
|
||||
// Formatter
|
||||
ProductFormatter::class => AutoWiringFactory::class,
|
||||
ProductListFormatter::class => AutoWiringFactory::class,
|
||||
|
||||
// Handler
|
||||
ProductListHandler::class => AutoWiringFactory::class,
|
||||
CreateProductHandler::class => AutoWiringFactory::class,
|
||||
DeleteProductHandler::class => AutoWiringFactory::class,
|
||||
UpdateProductHandler::class => AutoWiringFactory::class,
|
||||
],
|
||||
]
|
||||
|
||||
?>
|
||||
16
src/ApiDomain/External/Product/src/ConfigProvider.php
vendored
Normal file
16
src/ApiDomain/External/Product/src/ConfigProvider.php
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Homepage\API\External\Product;
|
||||
|
||||
class ConfigProvider
|
||||
{
|
||||
public function __invoke(): array
|
||||
{
|
||||
return [
|
||||
'dependencies' => require __DIR__ . '/./../config/service_manager.php',
|
||||
'routes' => require __DIR__ . '/./../config/routes.php',
|
||||
];
|
||||
}
|
||||
}
|
||||
20
src/ApiDomain/External/Product/src/Formatter/ProductFormatter.php
vendored
Normal file
20
src/ApiDomain/External/Product/src/Formatter/ProductFormatter.php
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Homepage\API\External\Product\Formatter;
|
||||
|
||||
use DateTime;
|
||||
use Homepage\Data\Business\Entity\Product;
|
||||
|
||||
class ProductFormatter {
|
||||
|
||||
public function format(Product $product): array {
|
||||
return [
|
||||
'id' => $product->getId()->toString(),
|
||||
'identifier' => $product->getIdentifier(),
|
||||
'name' => $product->getName(),
|
||||
'url' => $product->getUrl(),
|
||||
'created' => $product->getCreatedAt()->format(DateTime::ATOM),
|
||||
'updated' => $product->getUpdatedAt()->format(DateTime::ATOM)
|
||||
];
|
||||
}
|
||||
}
|
||||
28
src/ApiDomain/External/Product/src/Formatter/ProductListFormatter.php
vendored
Normal file
28
src/ApiDomain/External/Product/src/Formatter/ProductListFormatter.php
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Homepage\API\External\Product\Formatter;
|
||||
|
||||
use Homepage\Data\Business\Entity\Product;
|
||||
|
||||
class ProductListFormatter {
|
||||
|
||||
public function __construct(
|
||||
private readonly ProductFormatter $productFormatter
|
||||
) {
|
||||
}
|
||||
|
||||
public function format(array $products): array {
|
||||
$list = [];
|
||||
|
||||
/** @var Product $product */
|
||||
foreach ($products as $product) {
|
||||
$list[] = $this->productFormatter->format(
|
||||
$product
|
||||
);
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
41
src/ApiDomain/External/Product/src/Handler/CreateProductHandler.php
vendored
Normal file
41
src/ApiDomain/External/Product/src/Handler/CreateProductHandler.php
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Homepage\API\External\Product\Handler;
|
||||
|
||||
use Homepage\API\External\Product\Formatter\ProductFormatter;
|
||||
use Homepage\Handling\Product\Handler\Command\CreateProduct\CreateProductCommandBuilder;
|
||||
use Homepage\Handling\Product\Handler\Command\CreateProduct\CreateProductCommandHandler;
|
||||
use Laminas\Diactoros\Response\JsonResponse;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
|
||||
class CreateProductHandler implements RequestHandlerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private readonly CreateProductCommandHandler $handler,
|
||||
private readonly CreateProductCommandBuilder $builder,
|
||||
private readonly ProductFormatter $productFormatter,
|
||||
) {
|
||||
}
|
||||
|
||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
$data = json_decode(
|
||||
$request->getBody()->getContents(),
|
||||
true
|
||||
);
|
||||
|
||||
$query = $this->builder->build(
|
||||
$data['identifier'],
|
||||
$data['name'] ?? null
|
||||
);
|
||||
$result = $this->handler->execute($query);
|
||||
|
||||
return new JsonResponse(
|
||||
$this->productFormatter->format($result)
|
||||
);
|
||||
}
|
||||
}
|
||||
38
src/ApiDomain/External/Product/src/Handler/DeleteProductHandler.php
vendored
Normal file
38
src/ApiDomain/External/Product/src/Handler/DeleteProductHandler.php
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Homepage\API\External\Product\Handler;
|
||||
|
||||
use Homepage\Handling\Product\Handler\Command\DeleteProduct\DeleteProductCommandBuilder;
|
||||
use Homepage\Handling\Product\Handler\Command\DeleteProduct\DeleteProductCommandHandler;
|
||||
use Laminas\Diactoros\Response\JsonResponse;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
|
||||
class DeleteProductHandler implements RequestHandlerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private readonly DeleteProductCommandHandler $handler,
|
||||
private readonly DeleteProductCommandBuilder $builder,
|
||||
) {
|
||||
}
|
||||
|
||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
$data = json_decode(
|
||||
$request->getBody()->getContents(),
|
||||
true
|
||||
);
|
||||
|
||||
$query = $this->builder->build(
|
||||
$data['id']
|
||||
);
|
||||
$result = $this->handler->execute($query);
|
||||
|
||||
return new JsonResponse("OK");
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
35
src/ApiDomain/External/Product/src/Handler/ProductListHandler.php
vendored
Normal file
35
src/ApiDomain/External/Product/src/Handler/ProductListHandler.php
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Homepage\API\External\Product\Handler;
|
||||
|
||||
use Homepage\API\External\Product\Formatter\ProductListFormatter;
|
||||
use Homepage\Handling\Product\Handler\Query\ProductList\ProductListQueryBuilder;
|
||||
use Homepage\Handling\Product\Handler\Query\ProductList\ProductListQueryHandler;
|
||||
use Laminas\Diactoros\Response\JsonResponse;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
|
||||
class ProductListHandler implements RequestHandlerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private readonly ProductListQueryHandler $handler,
|
||||
private readonly ProductListQueryBuilder $builder,
|
||||
private readonly ProductListFormatter $productListFormatter
|
||||
) {
|
||||
}
|
||||
|
||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
$query = $this->builder->build( '*' );
|
||||
$result = $this->handler->execute($query);
|
||||
|
||||
return new JsonResponse(
|
||||
$this->productListFormatter->format($result)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
43
src/ApiDomain/External/Product/src/Handler/UpdateProductHandler.php
vendored
Normal file
43
src/ApiDomain/External/Product/src/Handler/UpdateProductHandler.php
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Homepage\API\External\Product\Handler;
|
||||
|
||||
use Homepage\API\External\Product\Formatter\ProductFormatter;
|
||||
use Homepage\Handling\Product\Handler\Command\UpdateProduct\UpdateProductCommandBuilder;
|
||||
use Homepage\Handling\Product\Handler\Command\UpdateProduct\UpdateProductCommandHandler;
|
||||
use Laminas\Diactoros\Response\JsonResponse;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
|
||||
class UpdateProductHandler implements RequestHandlerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private readonly UpdateProductCommandHandler $handler,
|
||||
private readonly UpdateProductCommandBuilder $builder,
|
||||
private readonly ProductFormatter $productFormatter,
|
||||
) {
|
||||
}
|
||||
|
||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
$data = json_decode(
|
||||
$request->getBody()->getContents(),
|
||||
true
|
||||
);
|
||||
|
||||
$query = $this->builder->build(
|
||||
$data['id'],
|
||||
$data['identifier'],
|
||||
$data['name'] ?? null,
|
||||
$data['url'] ?? null
|
||||
);
|
||||
$result = $this->handler->execute($query);
|
||||
|
||||
return new JsonResponse(
|
||||
$this->productFormatter->format($result)
|
||||
);
|
||||
}
|
||||
}
|
||||
48
src/ApiDomain/External/User/config/routes.php
vendored
Normal file
48
src/ApiDomain/External/User/config/routes.php
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
use Homepage\API\External\User\Handler\ChangePasswordHandler;
|
||||
use Homepage\API\External\User\Handler\ChangeUsernameHandler;
|
||||
use Homepage\API\External\User\Handler\CreateUserHandler;
|
||||
use Homepage\API\External\User\Handler\UserStateHandler;
|
||||
use Homepage\Infrastructure\Rbac\Middleware\EnsureAuthorizationMiddleware;
|
||||
use Homepage\Infrastructure\Session\Middleware\LoggedInUserMiddleware;
|
||||
|
||||
return [
|
||||
[
|
||||
'name' => 'user.create-user',
|
||||
'path' => '/api/user/create-user',
|
||||
'allowed_methods' => ['POST'],
|
||||
'middleware' => [
|
||||
LoggedInUserMiddleware::class,
|
||||
EnsureAuthorizationMiddleware::class,
|
||||
CreateUserHandler::class
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'user.change-password',
|
||||
'path' => '/api/user/change-password',
|
||||
'allowed_methods' => ['POST'],
|
||||
'middleware' => [
|
||||
LoggedInUserMiddleware::class,
|
||||
ChangePasswordHandler::class
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'user.change-username',
|
||||
'path' => '/api/user/change-username',
|
||||
'allowed_methods' => ['POST'],
|
||||
'middleware' => [
|
||||
LoggedInUserMiddleware::class,
|
||||
ChangeUsernameHandler::class
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'user.state',
|
||||
'path' => '/api/user/state',
|
||||
'allowed_methods' => ['GET'],
|
||||
'middleware' => [
|
||||
LoggedInUserMiddleware::class,
|
||||
UserStateHandler::class
|
||||
],
|
||||
],
|
||||
];
|
||||
21
src/ApiDomain/External/User/config/service_manager.php
vendored
Normal file
21
src/ApiDomain/External/User/config/service_manager.php
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
use Homepage\API\External\User\Formatter\UserFormatter;
|
||||
use Homepage\API\External\User\Handler\ChangePasswordHandler;
|
||||
use Homepage\API\External\User\Handler\ChangeUsernameHandler;
|
||||
use Homepage\API\External\User\Handler\CreateUserHandler;
|
||||
use Homepage\API\External\User\Handler\UserStateHandler;
|
||||
use Reinfi\DependencyInjection\Factory\AutoWiringFactory;
|
||||
|
||||
return [
|
||||
'factories' => [
|
||||
// Formatter
|
||||
UserFormatter::class => AutoWiringFactory::class,
|
||||
|
||||
// Handler
|
||||
CreateUserHandler::class => AutoWiringFactory::class,
|
||||
UserStateHandler::class => AutoWiringFactory::class,
|
||||
ChangePasswordHandler::class => AutoWiringFactory::class,
|
||||
ChangeUsernameHandler::class => AutoWiringFactory::class,
|
||||
],
|
||||
];
|
||||
16
src/ApiDomain/External/User/src/ConfigProvider.php
vendored
Normal file
16
src/ApiDomain/External/User/src/ConfigProvider.php
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Homepage\API\External\User;
|
||||
|
||||
class ConfigProvider
|
||||
{
|
||||
public function __invoke(): array
|
||||
{
|
||||
return [
|
||||
'dependencies' => require __DIR__ . '/./../config/service_manager.php',
|
||||
'routes' => require __DIR__ . '/./../config/routes.php',
|
||||
];
|
||||
}
|
||||
}
|
||||
27
src/ApiDomain/External/User/src/Formatter/UserFormatter.php
vendored
Normal file
27
src/ApiDomain/External/User/src/Formatter/UserFormatter.php
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Homepage\API\External\User\Formatter;
|
||||
|
||||
use DateTime;
|
||||
use Homepage\Data\Business\Entity\User;
|
||||
|
||||
class UserFormatter {
|
||||
|
||||
public function format(User $user): array {
|
||||
$userArray = [
|
||||
'id' => $user->getId()->toString(),
|
||||
'username' => $user->getUsername(),
|
||||
'role' => $user->getRole()->getIdentifier(),
|
||||
'created' => $user->getCreatedAt()->format(DateTime::ATOM),
|
||||
'updated' => $user->getUpdatedAt()->format(DateTime::ATOM)
|
||||
];
|
||||
|
||||
$userArray['permissions'] = [];
|
||||
|
||||
foreach ($user->getRole()->getPermissions()->toArray() as $permission) {
|
||||
$userArray['permissions'][] = $permission->getIdentifier();
|
||||
}
|
||||
|
||||
return $userArray;
|
||||
}
|
||||
}
|
||||
43
src/ApiDomain/External/User/src/Handler/ChangePasswordHandler.php
vendored
Normal file
43
src/ApiDomain/External/User/src/Handler/ChangePasswordHandler.php
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Homepage\API\External\User\Handler;
|
||||
|
||||
use Homepage\Data\Business\Entity\User;
|
||||
use Homepage\Handling\User\Handler\Command\ChangePassword\ChangePasswordCommandBuilder;
|
||||
use Homepage\Handling\User\Handler\Command\ChangePassword\ChangePasswordCommandHandler;
|
||||
use Homepage\Infrastructure\Response\SuccessResponse;
|
||||
use Homepage\Infrastructure\Session\Middleware\LoggedInUserMiddleware;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
|
||||
class ChangePasswordHandler implements RequestHandlerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private readonly ChangePasswordCommandHandler $handler,
|
||||
private readonly ChangePasswordCommandBuilder $builder,
|
||||
) {
|
||||
}
|
||||
|
||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = $request->getAttribute(LoggedInUserMiddleware::USER_KEY);
|
||||
|
||||
$data = json_decode(
|
||||
$request->getBody()->getContents(),
|
||||
true
|
||||
);
|
||||
|
||||
$query = $this->builder->build(
|
||||
$user,
|
||||
$data['password'],
|
||||
$data['newPassword'],
|
||||
);
|
||||
$this->handler->execute($query);
|
||||
|
||||
return new SuccessResponse();
|
||||
}
|
||||
}
|
||||
43
src/ApiDomain/External/User/src/Handler/ChangeUsernameHandler.php
vendored
Normal file
43
src/ApiDomain/External/User/src/Handler/ChangeUsernameHandler.php
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Homepage\API\External\User\Handler;
|
||||
|
||||
use Homepage\Data\Business\Entity\User;
|
||||
use Homepage\Handling\User\Handler\Command\ChangeUsername\ChangeUsernameCommandBuilder;
|
||||
use Homepage\Handling\User\Handler\Command\ChangeUsername\ChangeUsernameCommandHandler;
|
||||
use Homepage\Infrastructure\Response\SuccessResponse;
|
||||
use Homepage\Infrastructure\Session\Middleware\LoggedInUserMiddleware;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
|
||||
class ChangeUsernameHandler implements RequestHandlerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private readonly ChangeUsernameCommandHandler $handler,
|
||||
private readonly ChangeUsernameCommandBuilder $builder,
|
||||
) {
|
||||
}
|
||||
|
||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = $request->getAttribute(LoggedInUserMiddleware::USER_KEY);
|
||||
|
||||
$data = json_decode(
|
||||
$request->getBody()->getContents(),
|
||||
true
|
||||
);
|
||||
|
||||
$query = $this->builder->build(
|
||||
$user,
|
||||
$data['password'],
|
||||
$data['newUsername'],
|
||||
);
|
||||
$this->handler->execute($query);
|
||||
|
||||
return new SuccessResponse();
|
||||
}
|
||||
}
|
||||
44
src/ApiDomain/External/User/src/Handler/CreateUserHandler.php
vendored
Normal file
44
src/ApiDomain/External/User/src/Handler/CreateUserHandler.php
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Homepage\API\External\User\Handler;
|
||||
|
||||
use Homepage\API\External\User\Formatter\UserFormatter;
|
||||
use Homepage\Handling\User\Handler\Command\CreateUser\CreateUserCommandBuilder;
|
||||
use Homepage\Handling\User\Handler\Command\CreateUser\CreateUserCommandHandler;
|
||||
use Laminas\Diactoros\Response\JsonResponse;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
|
||||
class CreateUserHandler implements RequestHandlerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private readonly CreateUserCommandHandler $handler,
|
||||
private readonly CreateUserCommandBuilder $builder,
|
||||
private readonly UserFormatter $userFormatter,
|
||||
) {
|
||||
}
|
||||
|
||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
$data = json_decode(
|
||||
$request->getBody()->getContents(),
|
||||
true
|
||||
);
|
||||
|
||||
$query = $this->builder->build(
|
||||
$data['username'],
|
||||
$data['mail'],
|
||||
$data['password'],
|
||||
);
|
||||
$result = $this->handler->execute($query);
|
||||
|
||||
return new JsonResponse(
|
||||
$this->userFormatter->format($result)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
34
src/ApiDomain/External/User/src/Handler/UserStateHandler.php
vendored
Normal file
34
src/ApiDomain/External/User/src/Handler/UserStateHandler.php
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Homepage\API\External\User\Handler;
|
||||
|
||||
use Homepage\API\External\User\Formatter\UserFormatter;
|
||||
use Homepage\Data\Business\Entity\User;
|
||||
use Homepage\Handling\User\Handler\Command\CreateUser\CreateUserCommandBuilder;
|
||||
use Homepage\Handling\User\Handler\Command\CreateUser\ChangePasswordCommandHandler;
|
||||
use Homepage\Infrastructure\Session\Middleware\LoggedInUserMiddleware;
|
||||
use Laminas\Diactoros\Response\JsonResponse;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
|
||||
class UserStateHandler implements RequestHandlerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private readonly UserFormatter $userFormatter,
|
||||
) {
|
||||
}
|
||||
|
||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = $request->getAttribute(LoggedInUserMiddleware::USER_KEY);
|
||||
|
||||
$response = $this->userFormatter->format($user);
|
||||
$response['sessionId'] = $user->getSession()->getId()->toString();
|
||||
|
||||
return new JsonResponse($response);
|
||||
}
|
||||
}
|
||||
55
src/DataDomain/Business/config/doctrine.php
Normal file
55
src/DataDomain/Business/config/doctrine.php
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
use Doctrine\DBAL\Driver\PDO\MySQL\Driver;
|
||||
use Doctrine\ORM\Mapping\Driver\AnnotationDriver;
|
||||
use Doctrine\Persistence\Mapping\Driver\MappingDriverChain;
|
||||
|
||||
return [
|
||||
'configuration' => [
|
||||
'orm_homepage' => [
|
||||
'second_level_cache' => [
|
||||
'enabled' => false,
|
||||
]
|
||||
],
|
||||
],
|
||||
|
||||
'driver' => [
|
||||
'orm_homepage_annotation_driver' => [
|
||||
'class' => AnnotationDriver::class,
|
||||
'cache' => 'array',
|
||||
'paths' => [
|
||||
realpath(APP_ROOT . '/src/DataDomain/Business/Entity/')
|
||||
],
|
||||
],
|
||||
|
||||
'orm_homepage' => [
|
||||
'class' => MappingDriverChain::class,
|
||||
'drivers' => [
|
||||
'Homepage\Data\Business\Entity' => 'orm_homepage_annotation_driver',
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
'connection' => [
|
||||
'orm_homepage' => [
|
||||
'driverClass' => Driver::class,
|
||||
'params' => [
|
||||
'driver' => $_ENV['DB_DRIVER'],
|
||||
'host' => $_ENV['DB_HOST'],
|
||||
'port' => $_ENV['DB_PORT'],
|
||||
'user' => $_ENV['DB_USER'],
|
||||
'password' => $_ENV['DB_PASSWORD'],
|
||||
'dbname' => $_ENV['DB_NAME'],
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
'migrations_configuration' => [
|
||||
'orm_homepage' => [
|
||||
'directory' => 'data/migrations/homepage',
|
||||
'name' => 'Doctrine Database Migrations for Homepage',
|
||||
'namespace' => 'Homepage\Migrations\Homepage',
|
||||
'table' => 'migrations',
|
||||
],
|
||||
],
|
||||
];
|
||||
21
src/DataDomain/Business/config/service_manager.php
Normal file
21
src/DataDomain/Business/config/service_manager.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
use Homepage\Data\Business\Entity\User;
|
||||
use Homepage\Data\Business\Factory\HomepageEntityManagerFactory;
|
||||
use Homepage\Data\Business\Manager\HomepageEntityManager;
|
||||
use Homepage\Data\Business\Repository\UserRepository;
|
||||
use Homepage\Infrastructure\Database\AutowireRepositoryFactory;
|
||||
use Roave\PsrContainerDoctrine\ConfigurationFactory;
|
||||
use Roave\PsrContainerDoctrine\ConnectionFactory;
|
||||
use Roave\PsrContainerDoctrine\EntityManagerFactory;
|
||||
|
||||
return [
|
||||
'factories' => [
|
||||
'doctrine.entity_manager.orm_homepage' => [EntityManagerFactory::class, 'orm_homepage'],
|
||||
'doctrine.configuration.orm_homepage' => [ConfigurationFactory::class, 'orm_homepage'],
|
||||
'doctrine.connection.orm_homepage' => [ConnectionFactory::class, 'orm_homepage'],
|
||||
HomepageEntityManager::class => HomepageEntityManagerFactory::class,
|
||||
|
||||
UserRepository::class => [AutowireRepositoryFactory::class, HomepageEntityManager::class, User::class],
|
||||
],
|
||||
];
|
||||
16
src/DataDomain/Business/src/ConfigProvider.php
Normal file
16
src/DataDomain/Business/src/ConfigProvider.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Homepage\Data\Business;
|
||||
|
||||
class ConfigProvider
|
||||
{
|
||||
public function __invoke(): array
|
||||
{
|
||||
return [
|
||||
'dependencies' => require __DIR__ . './../config/service_manager.php',
|
||||
'doctrine' => require __DIR__ . './../config/doctrine.php',
|
||||
];
|
||||
}
|
||||
}
|
||||
100
src/DataDomain/Business/src/Entity/Permission.php
Normal file
100
src/DataDomain/Business/src/Entity/Permission.php
Normal file
@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
namespace Homepage\Data\Business\Entity;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Homepage\Infrastructure\UuidGenerator\UuidGenerator;
|
||||
use Ramsey\Uuid\UuidInterface;
|
||||
|
||||
/**
|
||||
* @ORM\Entity(repositoryClass="Homepage\Data\Business\Repository\PermissionRepository")
|
||||
* @ORM\Table(name="permission")
|
||||
*/
|
||||
class Permission {
|
||||
/**
|
||||
* @ORM\Id
|
||||
* @ORM\Column(name="id", type="uuid_binary_ordered_time")
|
||||
*/
|
||||
private UuidInterface $id;
|
||||
|
||||
/** @ORM\Column(name="product_id", type="uuid_binary_ordered_time", nullable=true) */
|
||||
private ?UuidInterface $productId;
|
||||
|
||||
/**
|
||||
* @ORM\OneToOne(targetEntity="Homepage\Data\Business\Entity\Product")
|
||||
* @ORM\JoinColumn(name="product_id", referencedColumnName="id", nullable=true)
|
||||
*/
|
||||
private ?Product $product;
|
||||
|
||||
/** @ORM\Column(name="identifier", type="string") */
|
||||
private string $identifier;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToMany(targetEntity="Homepage\Data\Business\Entity\Role", inversedBy="permissions")
|
||||
* @ORM\JoinTable(
|
||||
* name="role_permission",
|
||||
* joinColumns={@ORM\JoinColumn(name="permission_id", referencedColumnName="id")},
|
||||
* inverseJoinColumns={@ORM\JoinColumn(name="role_id", referencedColumnName="id")}
|
||||
* )
|
||||
*/
|
||||
private Collection $roles;
|
||||
|
||||
|
||||
public function __construct() {
|
||||
$this->id = UuidGenerator::generate();
|
||||
$this->roles = new ArrayCollection();
|
||||
}
|
||||
|
||||
|
||||
public function getId(): UuidInterface {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getProductId(): ?UuidInterface {
|
||||
return $this->productId;
|
||||
}
|
||||
|
||||
public function setProductId(?UuidInterface $productId): void {
|
||||
$this->productId = $productId;
|
||||
}
|
||||
|
||||
public function getProduct(): ?Product {
|
||||
return $this->product;
|
||||
}
|
||||
|
||||
public function setProduct(?Product $product): void {
|
||||
$this->product = $product;
|
||||
}
|
||||
|
||||
public function getIdentifier(): string {
|
||||
return $this->identifier;
|
||||
}
|
||||
|
||||
public function setIdentifier(string $identifier): void {
|
||||
$this->identifier = $identifier;
|
||||
}
|
||||
|
||||
public function getRoles(): Collection {
|
||||
return $this->roles;
|
||||
}
|
||||
|
||||
public function setRoles(Collection $roles): void {
|
||||
$this->roles = $roles;
|
||||
}
|
||||
|
||||
public function addRole(Role $role): void {
|
||||
if (!$this->roles->contains($role)) {
|
||||
$this->roles->add($role);
|
||||
$role->addPermission($this);
|
||||
}
|
||||
}
|
||||
|
||||
public function removeRole(Role $role): void {
|
||||
if ($this->roles->contains($role)) {
|
||||
$this->roles->remove($role);
|
||||
$role->removePermission($this);
|
||||
}
|
||||
}
|
||||
}
|
||||
99
src/DataDomain/Business/src/Entity/Product.php
Normal file
99
src/DataDomain/Business/src/Entity/Product.php
Normal file
@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
namespace Homepage\Data\Business\Entity;
|
||||
|
||||
use DateTime;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Homepage\Infrastructure\UuidGenerator\UuidGenerator;
|
||||
use Ramsey\Uuid\UuidInterface;
|
||||
|
||||
/**
|
||||
* @ORM\Entity(repositoryClass="Homepage\Data\Business\Repository\ProductRepository")
|
||||
* @ORM\Table(name="product")
|
||||
*/
|
||||
class Product {
|
||||
/**
|
||||
* @ORM\Id
|
||||
* @ORM\Column(name="id", type="uuid_binary_ordered_time")
|
||||
*/
|
||||
private UuidInterface $id;
|
||||
|
||||
/** @ORM\Column(name="identifier", type="string") */
|
||||
private string $identifier;
|
||||
|
||||
/** @ORM\Column(name="name", type="string", nullable="true") */
|
||||
private ?string $name;
|
||||
|
||||
/** @ORM\Column(name="url", type="string", nullable="true") */
|
||||
private ?string $url;
|
||||
|
||||
/** @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 getIdentifier(): string {
|
||||
return $this->identifier;
|
||||
}
|
||||
|
||||
public function setIdentifier(string $identifier): void {
|
||||
$this->identifier = $identifier;
|
||||
}
|
||||
|
||||
public function getName(): ?string {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName(?string $name): void {
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
public function getUrl(): ?string {
|
||||
return $this->url;
|
||||
}
|
||||
|
||||
public function setUrl(?string $url): void {
|
||||
$this->url = $url;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
66
src/DataDomain/Business/src/Entity/Registration.php
Normal file
66
src/DataDomain/Business/src/Entity/Registration.php
Normal file
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace Homepage\Data\Business\Entity;
|
||||
|
||||
use DateTime;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Homepage\Infrastructure\UuidGenerator\UuidGenerator;
|
||||
use Ramsey\Uuid\UuidInterface;
|
||||
|
||||
/**
|
||||
* @ORM\Entity(repositoryClass="Homepage\Data\Business\Repository\RegistrationRepository")
|
||||
* @ORM\Table(name="registration")
|
||||
*/
|
||||
class Registration {
|
||||
/**
|
||||
* @ORM\Id
|
||||
* @ORM\Column(name="id", type="uuid_binary_ordered_time")
|
||||
*/
|
||||
private UuidInterface $id;
|
||||
|
||||
/** @ORM\Column(name="username", type="string") */
|
||||
private string $username;
|
||||
|
||||
/** @ORM\Column(name="mail", type="string") */
|
||||
private string $mail;
|
||||
|
||||
/** @ORM\Column(name="created_at", type="datetime") */
|
||||
private DateTime $createdAt;
|
||||
|
||||
|
||||
public function __construct() {
|
||||
$this->id = UuidGenerator::generate();
|
||||
|
||||
$now = new DateTime();
|
||||
$this->setCreatedAt($now);
|
||||
}
|
||||
|
||||
|
||||
public function getId(): UuidInterface {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getUsername(): string {
|
||||
return $this->username;
|
||||
}
|
||||
|
||||
public function setUsername(string $username): void {
|
||||
$this->username = $username;
|
||||
}
|
||||
|
||||
public function getMail(): ?string {
|
||||
return $this->mail;
|
||||
}
|
||||
|
||||
public function setMail(?string $mail): void {
|
||||
$this->mail = $mail;
|
||||
}
|
||||
|
||||
public function getCreatedAt(): DateTime {
|
||||
return $this->createdAt;
|
||||
}
|
||||
|
||||
public function setCreatedAt(DateTime $createdAt): void {
|
||||
$this->createdAt = $createdAt;
|
||||
}
|
||||
}
|
||||
101
src/DataDomain/Business/src/Entity/Role.php
Normal file
101
src/DataDomain/Business/src/Entity/Role.php
Normal file
@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
namespace Homepage\Data\Business\Entity;
|
||||
|
||||
use DateTime;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Homepage\Infrastructure\UuidGenerator\UuidGenerator;
|
||||
use Ramsey\Uuid\UuidInterface;
|
||||
|
||||
/**
|
||||
* @ORM\Entity(repositoryClass="Homepage\Data\Business\Repository\RoleRepository")
|
||||
* @ORM\Table(name="role")
|
||||
*/
|
||||
class Role {
|
||||
/**
|
||||
* @ORM\Id
|
||||
* @ORM\Column(name="id", type="uuid_binary_ordered_time")
|
||||
*/
|
||||
private UuidInterface $id;
|
||||
|
||||
/** @ORM\Column(name="product_id", type="uuid_binary_ordered_time", nullable=true) */
|
||||
private ?UuidInterface $productId;
|
||||
|
||||
/**
|
||||
* @ORM\OneToOne(targetEntity="Homepage\Data\Business\Entity\Product")
|
||||
* @ORM\JoinColumn(name="product_id", referencedColumnName="id", nullable=true)
|
||||
*/
|
||||
private ?Product $product;
|
||||
|
||||
/** @ORM\Column(name="identifier", type="string") */
|
||||
private string $identifier;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToMany(targetEntity="Homepage\Data\Business\Entity\Permission", mappedBy="roles")
|
||||
* @ORM\JoinTable(
|
||||
* name="role_permission",
|
||||
* joinColumns={@ORM\JoinColumn(name="role_id", referencedColumnName="id")},
|
||||
* inverseJoinColumns={@ORM\JoinColumn(name="permission_id", referencedColumnName="id")}
|
||||
* )
|
||||
*/
|
||||
private Collection $permissions;
|
||||
|
||||
|
||||
public function __construct() {
|
||||
$this->id = UuidGenerator::generate();
|
||||
$this->permissions = new ArrayCollection();
|
||||
}
|
||||
|
||||
|
||||
public function getId(): UuidInterface {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getProductId(): ?UuidInterface {
|
||||
return $this->productId;
|
||||
}
|
||||
|
||||
public function setProductId(?UuidInterface $productId): void {
|
||||
$this->productId = $productId;
|
||||
}
|
||||
|
||||
public function getProduct(): ?Product {
|
||||
return $this->product;
|
||||
}
|
||||
|
||||
public function setProduct(?Product $product): void {
|
||||
$this->product = $product;
|
||||
}
|
||||
|
||||
public function getIdentifier(): string {
|
||||
return $this->identifier;
|
||||
}
|
||||
|
||||
public function setIdentifier(string $identifier): void {
|
||||
$this->identifier = $identifier;
|
||||
}
|
||||
|
||||
public function getPermissions(): Collection {
|
||||
return $this->permissions;
|
||||
}
|
||||
|
||||
public function setPermissions(Collection $permissions): void {
|
||||
$this->permissions = $permissions;
|
||||
}
|
||||
|
||||
public function addPermission(Permission $permission): void {
|
||||
if (!$this->permissions->contains($permission)) {
|
||||
$this->permissions->add($permission);
|
||||
$permission->addRole($this);
|
||||
}
|
||||
}
|
||||
|
||||
public function removePermission(Permission $permission): void {
|
||||
if ($this->permissions->contains($permission)) {
|
||||
$this->permissions->remove($permission);
|
||||
$permission->removeRole($this);
|
||||
}
|
||||
}
|
||||
}
|
||||
148
src/DataDomain/Business/src/Entity/User.php
Normal file
148
src/DataDomain/Business/src/Entity/User.php
Normal file
@ -0,0 +1,148 @@
|
||||
<?php
|
||||
|
||||
namespace Homepage\Data\Business\Entity;
|
||||
|
||||
use DateTime;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Homepage\Infrastructure\UuidGenerator\UuidGenerator;
|
||||
use Ramsey\Uuid\UuidInterface;
|
||||
|
||||
/**
|
||||
* @ORM\Entity(repositoryClass="Homepage\Data\Business\Repository\UserRepository")
|
||||
* @ORM\Table(name="user")
|
||||
*/
|
||||
class User {
|
||||
/**
|
||||
* @ORM\Id
|
||||
* @ORM\Column(name="id", type="uuid_binary_ordered_time")
|
||||
*/
|
||||
private UuidInterface $id;
|
||||
|
||||
/** @ORM\Column(name="role_id", type="uuid_binary_ordered_time") */
|
||||
private UuidInterface $roleId;
|
||||
|
||||
/**
|
||||
* @ORM\OneToOne(targetEntity="Homepage\Data\Business\Entity\Role")
|
||||
* @ORM\JoinColumn(name="role_id", referencedColumnName="id")
|
||||
*/
|
||||
private Role $role;
|
||||
|
||||
/** @ORM\Column(name="username", type="string") */
|
||||
private string $username;
|
||||
|
||||
/** @ORM\Column(name="mail", type="string") */
|
||||
private string $mail;
|
||||
|
||||
/** @ORM\Column(name="password", type="string") */
|
||||
private string $password;
|
||||
|
||||
/** @ORM\OneToOne(targetEntity="Homepage\Data\Business\Entity\UserSession", mappedBy="user") */
|
||||
private ?UserSession $session;
|
||||
|
||||
/** @ORM\Column(name="last_login_at", type="datetime", nullable=true) */
|
||||
private DateTime $lastLoginAt;
|
||||
|
||||
/** @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 getRoleId(): UuidInterface {
|
||||
return $this->roleId;
|
||||
}
|
||||
|
||||
public function setRoleId(UuidInterface $roleId): void {
|
||||
$this->roleId = $roleId;
|
||||
}
|
||||
|
||||
public function getRole(): Role {
|
||||
return $this->role;
|
||||
}
|
||||
|
||||
public function setRole(Role $role): void {
|
||||
$this->role = $role;
|
||||
}
|
||||
|
||||
public function getUsername(): string {
|
||||
return $this->username;
|
||||
}
|
||||
|
||||
public function setUsername(string $username): void {
|
||||
$this->username = $username;
|
||||
}
|
||||
|
||||
public function getMail(): ?string {
|
||||
return $this->mail;
|
||||
}
|
||||
|
||||
public function setMail(?string $mail): void {
|
||||
$this->mail = $mail;
|
||||
}
|
||||
|
||||
public function getPassword(): ?string {
|
||||
return $this->password;
|
||||
}
|
||||
|
||||
public function setPassword(?string $password): void {
|
||||
$this->password = $password;
|
||||
}
|
||||
|
||||
public function getSession(): ?UserSession {
|
||||
return $this->session;
|
||||
}
|
||||
|
||||
public function setSession(?UserSession $session): void {
|
||||
$this->session = $session;
|
||||
}
|
||||
|
||||
public function getLastLoginAt(): ?DateTime {
|
||||
return $this->lastLoginAt;
|
||||
}
|
||||
|
||||
public function setLastLoginAt(?DateTime $lastLoginAt): void {
|
||||
$this->lastLoginAt = $lastLoginAt;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
105
src/DataDomain/Business/src/Entity/UserSession.php
Normal file
105
src/DataDomain/Business/src/Entity/UserSession.php
Normal file
@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
namespace Homepage\Data\Business\Entity;
|
||||
|
||||
use DateTime;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Homepage\Infrastructure\UuidGenerator\UuidGenerator;
|
||||
use Ramsey\Uuid\UuidInterface;
|
||||
|
||||
/**
|
||||
* @ORM\Entity(repositoryClass="Homepage\Data\Business\Repository\UserSessionRepository")
|
||||
* @ORM\Table(name="user_session")
|
||||
*/
|
||||
class UserSession {
|
||||
/**
|
||||
* @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=true) */
|
||||
private ?UuidInterface $userId;
|
||||
|
||||
/**
|
||||
* @ORM\OneToOne(targetEntity="Homepage\Data\Business\Entity\User", mappedBy="session")
|
||||
* @ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=true)
|
||||
*/
|
||||
private ?User $user;
|
||||
|
||||
/** @ORM\Column(name="csrf", type="uuid_binary_ordered_time", nullable=true) */
|
||||
private ?UuidInterface $csrf;
|
||||
|
||||
/** @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 getCsrf(): ?UuidInterface {
|
||||
return $this->csrf;
|
||||
}
|
||||
|
||||
public function setCsrf(?UuidInterface $csrf): void {
|
||||
$this->csrf = $csrf;
|
||||
}
|
||||
|
||||
|
||||
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,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Homepage\Data\Business\Factory;
|
||||
|
||||
use Homepage\Data\Business\Manager\HomepageEntityManager;
|
||||
use Laminas\ServiceManager\Factory\FactoryInterface;
|
||||
use Psr\Container\ContainerInterface;
|
||||
|
||||
class HomepageEntityManagerFactory implements FactoryInterface
|
||||
{
|
||||
public function __invoke(ContainerInterface $container, $requestedName, ?array $options = null): HomepageEntityManager
|
||||
{
|
||||
return new HomepageEntityManager(
|
||||
$container->get('doctrine.entity_manager.orm_homepage')
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Homepage\Data\Business\Manager;
|
||||
|
||||
use Doctrine\ORM\Decorator\EntityManagerDecorator;
|
||||
|
||||
class HomepageEntityManager extends EntityManagerDecorator
|
||||
{
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Homepage\Data\Business\Repository;
|
||||
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
|
||||
class PermissionRepository extends EntityRepository {
|
||||
}
|
||||
|
||||
?>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user