From 6b2842534bf750b97153405bac2b896611f64db8 Mon Sep 17 00:00:00 2001 From: Claudiu Pintiuta Date: Fri, 28 Jun 2024 15:43:23 +0300 Subject: [PATCH 01/15] update doctrine to orm 3 and dbal 4, code refactoring Signed-off-by: Claudiu Pintiuta --- .github/workflows/continuous-integration.yml | 11 ++++ .github/workflows/cs-tests.yml | 47 -------------- .github/workflows/run-tests.yml | 55 ---------------- .github/workflows/static-analysis.yml | 46 ------------- README.md | 4 +- composer.json | 5 +- config/autoload/doctrine.global.php | 10 ++- .../migrations/Version20240110104118.php | 45 ------------- .../migrations/Version20240627134952.php | 45 +++++++++++++ .../src/Adapter/AuthenticationAdapter.php | 2 +- src/Admin/src/Controller/AdminController.php | 8 +-- src/Admin/src/Entity/Admin.php | 4 ++ src/Admin/src/Entity/AdminLogin.php | 4 ++ src/Admin/src/Entity/AdminRole.php | 4 ++ src/Admin/src/Repository/AdminRepository.php | 39 +---------- .../src/Repository/AdminRoleRepository.php | 2 +- src/Admin/src/Service/AdminService.php | 9 +-- .../src/Service/AdminServiceInterface.php | 2 - .../src/Common/TimestampAwareInterface.php | 22 ------- src/App/src/Common/TimestampAwareTrait.php | 64 ------------------- src/App/src/Common/UuidAwareInterface.php | 12 ---- src/App/src/Common/UuidAwareTrait.php | 27 -------- .../src/Common/UuidOrderedTimeGenerator.php | 29 --------- src/App/src/Entity/AbstractEntity.php | 26 ++++---- src/App/src/Entity/TimestampsTrait.php | 54 ++++++++++++++++ src/App/src/Exception/ORMException.php | 11 ++++ src/App/src/Repository/AbstractRepository.php | 26 -------- .../src/Controller/SettingController.php | 10 +-- src/Setting/src/Entity/Setting.php | 4 ++ .../Adapter/AuthenticationAdapterTest.php | 12 +++- test/Unit/Admin/Entity/AdminLoginTest.php | 9 +-- test/Unit/Admin/Entity/AdminRoleTest.php | 11 +--- test/Unit/Admin/Entity/AdminTest.php | 11 +--- test/Unit/App/Common/TimestampAwareTest.php | 47 -------------- test/Unit/App/Common/UuidAwareTest.php | 24 ------- .../Common/UuidOrderedTimeGeneratorTest.php | 23 ------- test/Unit/App/Entity/AbstractEntityTest.php | 3 - 37 files changed, 192 insertions(+), 575 deletions(-) create mode 100644 .github/workflows/continuous-integration.yml delete mode 100644 .github/workflows/cs-tests.yml delete mode 100644 .github/workflows/run-tests.yml delete mode 100644 .github/workflows/static-analysis.yml delete mode 100644 data/doctrine/migrations/Version20240110104118.php create mode 100644 data/doctrine/migrations/Version20240627134952.php delete mode 100644 src/App/src/Common/TimestampAwareInterface.php delete mode 100644 src/App/src/Common/TimestampAwareTrait.php delete mode 100644 src/App/src/Common/UuidAwareInterface.php delete mode 100644 src/App/src/Common/UuidAwareTrait.php delete mode 100644 src/App/src/Common/UuidOrderedTimeGenerator.php create mode 100644 src/App/src/Entity/TimestampsTrait.php create mode 100644 src/App/src/Exception/ORMException.php delete mode 100644 test/Unit/App/Common/TimestampAwareTest.php delete mode 100644 test/Unit/App/Common/UuidAwareTest.php delete mode 100644 test/Unit/App/Common/UuidOrderedTimeGeneratorTest.php diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml new file mode 100644 index 00000000..26c58025 --- /dev/null +++ b/.github/workflows/continuous-integration.yml @@ -0,0 +1,11 @@ +name: "Continuous Integration" + +on: + pull_request: + push: + branches: + tags: + +jobs: + ci: + uses: laminas/workflow-continuous-integration/.github/workflows/continuous-integration.yml@1.x diff --git a/.github/workflows/cs-tests.yml b/.github/workflows/cs-tests.yml deleted file mode 100644 index 55806c6b..00000000 --- a/.github/workflows/cs-tests.yml +++ /dev/null @@ -1,47 +0,0 @@ -on: - - push - -name: Run phpcs checks - -jobs: - mutation: - name: PHP ${{ matrix.php }}-${{ matrix.os }} - - runs-on: ${{ matrix.os }} - - strategy: - matrix: - os: - - ubuntu-latest - - php: - - "8.2" - - "8.3" - - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Install PHP - uses: shivammathur/setup-php@v2 - with: - php-version: "${{ matrix.php }}" - tools: composer:v2, cs2pr - coverage: none - - - name: Determine composer cache directory - run: echo "COMPOSER_CACHE_DIR=$(composer config cache-dir)" >> $GITHUB_ENV - - - name: Cache dependencies installed with composer - uses: actions/cache@v4 - with: - path: ${{ env.COMPOSER_CACHE_DIR }} - key: php${{ matrix.php }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: | - php${{ matrix.php }}-composer- - - - name: Install dependencies with composer - run: composer install --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi - - - name: Run phpcs checks - run: vendor/bin/phpcs diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml deleted file mode 100644 index 0460fee6..00000000 --- a/.github/workflows/run-tests.yml +++ /dev/null @@ -1,55 +0,0 @@ -on: - - push - -name: Run PHPUnit tests - -jobs: - mutation: - name: PHP ${{ matrix.php }}-${{ matrix.os }} - - runs-on: ${{ matrix.os }} - - strategy: - matrix: - os: - - ubuntu-latest - - php: - - "8.2" - - "8.3" - - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Install PHP - uses: shivammathur/setup-php@v2 - with: - php-version: "${{ matrix.php }}" - tools: composer:v2, cs2pr - coverage: none - - - name: Determine composer cache directory - run: echo "COMPOSER_CACHE_DIR=$(composer config cache-dir)" >> $GITHUB_ENV - - - name: Cache dependencies installed with composer - uses: actions/cache@v4 - with: - path: ${{ env.COMPOSER_CACHE_DIR }} - key: php${{ matrix.php }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: | - php${{ matrix.php }}-composer- - - - name: Install dependencies with composer - run: composer install --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi - - - name: Setup project - run: | - mv config/autoload/local.php.dist config/autoload/local.php - mv config/autoload/mail.local.php.dist config/autoload/mail.local.php - mv config/autoload/local.test.php.dist config/autoload/local.test.php - - - name: Run unit tests - run: vendor/bin/phpunit --testsuite=UnitTests --testdox --colors=always - - name: Run functional tests - run: vendor/bin/phpunit --testsuite=FunctionalTests --testdox --colors=always diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml deleted file mode 100644 index 16d3bfce..00000000 --- a/.github/workflows/static-analysis.yml +++ /dev/null @@ -1,46 +0,0 @@ -on: - - push - -name: static analysis - -jobs: - mutation: - name: PHP ${{ matrix.php }}-${{ matrix.os }} - - runs-on: ${{ matrix.os }} - - strategy: - matrix: - os: - - ubuntu-latest - - php: - - "8.2" - - "8.3" - - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Install PHP - uses: shivammathur/setup-php@v2 - with: - php-version: "${{ matrix.php }}" - tools: composer:v2, cs2pr - coverage: none - - - name: Determine composer cache directory - run: echo "COMPOSER_CACHE_DIR=$(composer config cache-dir)" >> $GITHUB_ENV - - - name: Cache dependencies installed with composer - uses: actions/cache@v4 - with: - path: ${{ env.COMPOSER_CACHE_DIR }} - key: php${{ matrix.php }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: | - php${{ matrix.php }}-composer- - - name: Install dependencies with composer - run: composer install --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi - - - name: Static analysis - run: vendor/bin/psalm --no-cache --output-format=github --show-info=false --threads=4 --php-version="${{ matrix.php }}" diff --git a/README.md b/README.md index 564ddbeb..7c1ffc8b 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,9 @@ DotKernel web starter package suitable for admin applications. [![GitHub stars](https://img.shields.io/github/stars/dotkernel/admin)](https://github.com/dotkernel/admin/stargazers) [![GitHub license](https://img.shields.io/github/license/dotkernel/admin)](https://github.com/dotkernel/admin/blob/3.0/LICENSE.md) -[![Build Static](https://github.com/dotkernel/admin/actions/workflows/static-analysis.yml/badge.svg?branch=4.0)](https://github.com/dotkernel/admin/actions/workflows/static-analysis.yml) -[![Build Static](https://github.com/dotkernel/admin/actions/workflows/run-tests.yml/badge.svg?branch=4.0)](https://github.com/dotkernel/admin/actions/workflows/run-tests.yml) +[![Build Static](https://github.com/dotkernel/admin/actions/workflows/continuous-integration.yml/badge.svg?branch=5.0)](https://github.com/dotkernel/admin/actions/workflows/continuous-integration.yml) [![codecov](https://codecov.io/gh/dotkernel/admin/graph/badge.svg?token=BQS43UWAM4)](https://codecov.io/gh/dotkernel/admin) +[![Qodana](https://github.com/dotkernel/admin/actions/workflows/qodana_code_quality.yml/badge.svg?branch=5.0)](https://github.com/dotkernel/admin/actions/workflows/qodana_code_quality.yml) [![SymfonyInsight](https://insight.symfony.com/projects/6a7ecfc1-a0ed-4901-96ac-d0ff61f7b55f/big.svg)](https://insight.symfony.com/projects/6a7ecfc1-a0ed-4901-96ac-d0ff61f7b55f) diff --git a/composer.json b/composer.json index c5123146..9f80e96c 100644 --- a/composer.json +++ b/composer.json @@ -52,8 +52,9 @@ "mezzio/mezzio-authorization-rbac": "^1.7.0", "mezzio/mezzio-cors": "^1.11.1", "mezzio/mezzio-fastroute": "^3.11.0", - "ramsey/uuid-doctrine": "^2.0.0", - "roave/psr-container-doctrine": "^4.1.0" + "ramsey/uuid-doctrine": "^2.1.0", + "roave/psr-container-doctrine": "^5.1.0", + "doctrine/orm": "^3.2" }, "require-dev": { "filp/whoops": "^2.15.4", diff --git a/config/autoload/doctrine.global.php b/config/autoload/doctrine.global.php index fc6c37b8..00d76767 100644 --- a/config/autoload/doctrine.global.php +++ b/config/autoload/doctrine.global.php @@ -4,6 +4,7 @@ use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\Mapping\Driver\AttributeDriver; use Doctrine\Persistence\Mapping\Driver\MappingDriverChain; use Dot\Cache\Adapter\ArrayAdapter; use Dot\Cache\Adapter\FilesystemAdapter; @@ -54,7 +55,14 @@ // Override `orm_default` only if you know what you're doing 'orm_default' => [ 'class' => MappingDriverChain::class, - 'drivers' => [], + 'drivers' => [ + 'Frontend\\App\\Entity' => 'AppEntities', + ], + ], + 'AppEntities' => [ + 'class' => AttributeDriver::class, + 'cache' => 'array', + 'paths' => __DIR__ . '/../../src/App/src/Entity', ], ], 'types' => [ diff --git a/data/doctrine/migrations/Version20240110104118.php b/data/doctrine/migrations/Version20240110104118.php deleted file mode 100644 index 4dae5afd..00000000 --- a/data/doctrine/migrations/Version20240110104118.php +++ /dev/null @@ -1,45 +0,0 @@ -addSql('CREATE TABLE admin (uuid BINARY(16) NOT NULL COMMENT \'(DC2Type:uuid_binary_ordered_time)\', identity VARCHAR(100) NOT NULL, firstName VARCHAR(255) DEFAULT NULL, lastName VARCHAR(255) DEFAULT NULL, password VARCHAR(100) NOT NULL, status ENUM(\'pending\', \'active\'), created DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', updated DATETIME DEFAULT NULL COMMENT \'(DC2Type:datetime_immutable)\', UNIQUE INDEX UNIQ_880E0D766A95E9C4 (identity), PRIMARY KEY(uuid)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); - $this->addSql('CREATE TABLE admin_roles (userUuid BINARY(16) NOT NULL COMMENT \'(DC2Type:uuid_binary_ordered_time)\', roleUuid BINARY(16) NOT NULL COMMENT \'(DC2Type:uuid_binary_ordered_time)\', INDEX IDX_1614D53DD73087E9 (userUuid), INDEX IDX_1614D53D88446210 (roleUuid), PRIMARY KEY(userUuid, roleUuid)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); - $this->addSql('CREATE TABLE admin_login (uuid BINARY(16) NOT NULL COMMENT \'(DC2Type:uuid_binary_ordered_time)\', adminIp VARCHAR(50) DEFAULT NULL, country VARCHAR(50) DEFAULT NULL, continent VARCHAR(50) DEFAULT NULL, organization VARCHAR(50) DEFAULT NULL, deviceType VARCHAR(20) DEFAULT NULL, deviceBrand VARCHAR(20) DEFAULT NULL, deviceModel VARCHAR(40) DEFAULT NULL, isMobile ENUM(\'yes\', \'no\'), osName VARCHAR(20) DEFAULT NULL, osVersion VARCHAR(20) DEFAULT NULL, osPlatform VARCHAR(20) DEFAULT NULL, clientType VARCHAR(20) DEFAULT NULL, clientName VARCHAR(40) DEFAULT NULL, clientEngine VARCHAR(20) DEFAULT NULL, clientVersion VARCHAR(20) DEFAULT NULL, loginStatus ENUM(\'success\', \'fail\'), identity VARCHAR(100) DEFAULT NULL, created DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', updated DATETIME DEFAULT NULL COMMENT \'(DC2Type:datetime_immutable)\', PRIMARY KEY(uuid)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); - $this->addSql('CREATE TABLE admin_role (uuid BINARY(16) NOT NULL COMMENT \'(DC2Type:uuid_binary_ordered_time)\', name VARCHAR(30) NOT NULL, created DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', updated DATETIME DEFAULT NULL COMMENT \'(DC2Type:datetime_immutable)\', UNIQUE INDEX UNIQ_7770088A5E237E06 (name), PRIMARY KEY(uuid)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); - $this->addSql('CREATE TABLE settings (uuid BINARY(16) NOT NULL COMMENT \'(DC2Type:uuid_binary_ordered_time)\', admin_uuid BINARY(16) DEFAULT NULL COMMENT \'(DC2Type:uuid_binary_ordered_time)\', identifier VARCHAR(50) NOT NULL, value LONGTEXT NOT NULL, created DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', updated DATETIME DEFAULT NULL COMMENT \'(DC2Type:datetime_immutable)\', INDEX IDX_E545A0C5F166D246 (admin_uuid), PRIMARY KEY(uuid)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); - $this->addSql('ALTER TABLE admin_roles ADD CONSTRAINT FK_1614D53DD73087E9 FOREIGN KEY (userUuid) REFERENCES admin (uuid)'); - $this->addSql('ALTER TABLE admin_roles ADD CONSTRAINT FK_1614D53D88446210 FOREIGN KEY (roleUuid) REFERENCES admin_role (uuid)'); - $this->addSql('ALTER TABLE settings ADD CONSTRAINT FK_E545A0C5F166D246 FOREIGN KEY (admin_uuid) REFERENCES admin (uuid)'); - } - - public function down(Schema $schema): void - { - // this down() migration is auto-generated, please modify it to your needs - $this->addSql('ALTER TABLE admin_roles DROP FOREIGN KEY FK_1614D53DD73087E9'); - $this->addSql('ALTER TABLE admin_roles DROP FOREIGN KEY FK_1614D53D88446210'); - $this->addSql('ALTER TABLE settings DROP FOREIGN KEY FK_E545A0C5F166D246'); - $this->addSql('DROP TABLE admin'); - $this->addSql('DROP TABLE admin_roles'); - $this->addSql('DROP TABLE admin_login'); - $this->addSql('DROP TABLE admin_role'); - $this->addSql('DROP TABLE settings'); - } -} diff --git a/data/doctrine/migrations/Version20240627134952.php b/data/doctrine/migrations/Version20240627134952.php new file mode 100644 index 00000000..243eed9d --- /dev/null +++ b/data/doctrine/migrations/Version20240627134952.php @@ -0,0 +1,45 @@ +addSql('CREATE TABLE admin (uuid BINARY(16) NOT NULL, identity VARCHAR(100) NOT NULL, firstName VARCHAR(255) DEFAULT NULL, lastName VARCHAR(255) DEFAULT NULL, password VARCHAR(100) NOT NULL, status ENUM(\'pending\', \'active\'), created DATETIME NOT NULL, updated DATETIME DEFAULT NULL, UNIQUE INDEX UNIQ_880E0D766A95E9C4 (identity), PRIMARY KEY(uuid)) DEFAULT CHARACTER SET utf8mb4'); + $this->addSql('CREATE TABLE admin_roles (userUuid BINARY(16) NOT NULL, roleUuid BINARY(16) NOT NULL, INDEX IDX_1614D53DD73087E9 (userUuid), INDEX IDX_1614D53D88446210 (roleUuid), PRIMARY KEY(userUuid, roleUuid)) DEFAULT CHARACTER SET utf8mb4'); + $this->addSql('CREATE TABLE admin_login (uuid BINARY(16) NOT NULL, adminIp VARCHAR(50) DEFAULT NULL, country VARCHAR(50) DEFAULT NULL, continent VARCHAR(50) DEFAULT NULL, organization VARCHAR(50) DEFAULT NULL, deviceType VARCHAR(20) DEFAULT NULL, deviceBrand VARCHAR(20) DEFAULT NULL, deviceModel VARCHAR(40) DEFAULT NULL, isMobile ENUM(\'yes\', \'no\'), osName VARCHAR(20) DEFAULT NULL, osVersion VARCHAR(20) DEFAULT NULL, osPlatform VARCHAR(20) DEFAULT NULL, clientType VARCHAR(20) DEFAULT NULL, clientName VARCHAR(40) DEFAULT NULL, clientEngine VARCHAR(20) DEFAULT NULL, clientVersion VARCHAR(20) DEFAULT NULL, loginStatus ENUM(\'success\', \'fail\'), identity VARCHAR(100) DEFAULT NULL, created DATETIME NOT NULL, updated DATETIME DEFAULT NULL, PRIMARY KEY(uuid)) DEFAULT CHARACTER SET utf8mb4'); + $this->addSql('CREATE TABLE admin_role (uuid BINARY(16) NOT NULL, name VARCHAR(30) NOT NULL, created DATETIME NOT NULL, updated DATETIME DEFAULT NULL, UNIQUE INDEX UNIQ_7770088A5E237E06 (name), PRIMARY KEY(uuid)) DEFAULT CHARACTER SET utf8mb4'); + $this->addSql('CREATE TABLE settings (uuid BINARY(16) NOT NULL, identifier VARCHAR(50) NOT NULL, value LONGTEXT NOT NULL, created DATETIME NOT NULL, updated DATETIME DEFAULT NULL, admin_uuid BINARY(16) DEFAULT NULL, INDEX IDX_E545A0C5F166D246 (admin_uuid), PRIMARY KEY(uuid)) DEFAULT CHARACTER SET utf8mb4'); + $this->addSql('ALTER TABLE admin_roles ADD CONSTRAINT FK_1614D53DD73087E9 FOREIGN KEY (userUuid) REFERENCES admin (uuid)'); + $this->addSql('ALTER TABLE admin_roles ADD CONSTRAINT FK_1614D53D88446210 FOREIGN KEY (roleUuid) REFERENCES admin_role (uuid)'); + $this->addSql('ALTER TABLE settings ADD CONSTRAINT FK_E545A0C5F166D246 FOREIGN KEY (admin_uuid) REFERENCES admin (uuid)'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE admin_roles DROP FOREIGN KEY FK_1614D53DD73087E9'); + $this->addSql('ALTER TABLE admin_roles DROP FOREIGN KEY FK_1614D53D88446210'); + $this->addSql('ALTER TABLE settings DROP FOREIGN KEY FK_E545A0C5F166D246'); + $this->addSql('DROP TABLE admin'); + $this->addSql('DROP TABLE admin_roles'); + $this->addSql('DROP TABLE admin_login'); + $this->addSql('DROP TABLE admin_role'); + $this->addSql('DROP TABLE settings'); + } +} diff --git a/src/Admin/src/Adapter/AuthenticationAdapter.php b/src/Admin/src/Adapter/AuthenticationAdapter.php index cd73732a..274fdb9f 100644 --- a/src/Admin/src/Adapter/AuthenticationAdapter.php +++ b/src/Admin/src/Adapter/AuthenticationAdapter.php @@ -34,7 +34,7 @@ class AuthenticationAdapter implements AdapterInterface "config.doctrine.authentication" )] public function __construct( - private EntityManager $entityManager, + private readonly EntityManager $entityManager, array $config ) { $this->config = $config; diff --git a/src/Admin/src/Controller/AdminController.php b/src/Admin/src/Controller/AdminController.php index 5d919a07..7afff01a 100644 --- a/src/Admin/src/Controller/AdminController.php +++ b/src/Admin/src/Controller/AdminController.php @@ -116,7 +116,7 @@ public function editAction(): ResponseInterface $uuid = $this->getAttribute('uuid'); /** @var Admin $admin */ - $admin = $this->adminService->getAdminRepository()->find($uuid); + $admin = $this->adminService->getAdminRepository()->findOneBy(['uuid' => $uuid]); $adminFormData = (new AdminFormData())->fromEntity($admin); @@ -179,7 +179,7 @@ public function deleteAction(): ResponseInterface } /** @var Admin $admin */ - $admin = $this->adminService->getAdminRepository()->find($uuid); + $admin = $this->adminService->getAdminRepository()->findOneBy(['uuid' => $uuid]); try { $this->adminService->getAdminRepository()->deleteAdmin($admin); @@ -295,7 +295,7 @@ public function accountAction(): ResponseInterface $form = new AccountForm(); $changePasswordForm = new ChangePasswordForm(); $identity = $this->authenticationService->getIdentity(); - $admin = $this->adminService->findAdminBy(['uuid' => $identity->getUuid()]); + $admin = $this->adminService->getAdminRepository()->findOneBy(['uuid' => $identity->getUuid()]); if ($this->isPost()) { $form->setData($this->getPostParams()); @@ -333,7 +333,7 @@ public function changePasswordAction(): ResponseInterface $changePasswordForm = new ChangePasswordForm(); /** @var AdminIdentity $adminIdentity */ $adminIdentity = $this->authenticationService->getIdentity(); - $admin = $this->adminService->getAdminRepository()->findAdminBy([ + $admin = $this->adminService->getAdminRepository()->findOneBy([ 'identity' => $adminIdentity->getIdentity(), ]); diff --git a/src/Admin/src/Entity/Admin.php b/src/Admin/src/Entity/Admin.php index e028ca8a..dac3e1ab 100644 --- a/src/Admin/src/Entity/Admin.php +++ b/src/Admin/src/Entity/Admin.php @@ -9,15 +9,19 @@ use Doctrine\ORM\Mapping as ORM; use Frontend\Admin\Repository\AdminRepository; use Frontend\App\Entity\AbstractEntity; +use Frontend\App\Entity\TimestampsTrait; use Frontend\Setting\Entity\Setting; use function array_map; #[ORM\Entity(repositoryClass: AdminRepository::class)] #[ORM\Table(name: "admin")] +#[ORM\HasLifecycleCallbacks] #[ORM\Cache(usage: "NONSTRICT_READ_WRITE")] class Admin extends AbstractEntity implements AdminInterface { + use TimestampsTrait; + public const STATUS_ACTIVE = 'active'; public const STATUS_INACTIVE = 'pending'; public const STATUSES = [ diff --git a/src/Admin/src/Entity/AdminLogin.php b/src/Admin/src/Entity/AdminLogin.php index 759de685..37b2b523 100644 --- a/src/Admin/src/Entity/AdminLogin.php +++ b/src/Admin/src/Entity/AdminLogin.php @@ -7,12 +7,16 @@ use Doctrine\ORM\Mapping as ORM; use Frontend\Admin\Repository\AdminLoginRepository; use Frontend\App\Entity\AbstractEntity; +use Frontend\App\Entity\TimestampsTrait; #[ORM\Entity(repositoryClass: AdminLoginRepository::class)] #[ORM\Table(name: 'admin_login')] +#[ORM\HasLifecycleCallbacks] #[ORM\Cache(usage: "NONSTRICT_READ_WRITE")] class AdminLogin extends AbstractEntity { + use TimestampsTrait; + public const IS_MOBILE_YES = 'yes'; public const IS_MOBILE_NO = 'no'; public const LOGIN_SUCCESS = 'success'; diff --git a/src/Admin/src/Entity/AdminRole.php b/src/Admin/src/Entity/AdminRole.php index 4ce1024e..aba70015 100644 --- a/src/Admin/src/Entity/AdminRole.php +++ b/src/Admin/src/Entity/AdminRole.php @@ -7,12 +7,16 @@ use Doctrine\ORM\Mapping as ORM; use Frontend\Admin\Repository\AdminRoleRepository; use Frontend\App\Entity\AbstractEntity; +use Frontend\App\Entity\TimestampsTrait; #[ORM\Entity(repositoryClass: AdminRoleRepository::class)] #[ORM\Table(name: 'admin_role')] +#[ORM\HasLifecycleCallbacks] #[ORM\Cache(usage: "NONSTRICT_READ_WRITE")] class AdminRole extends AbstractEntity { + use TimestampsTrait; + public const ROLE_ADMIN = 'admin'; public const ROLE_SUPERUSER = 'superuser'; public const ROLES = [ diff --git a/src/Admin/src/Repository/AdminRepository.php b/src/Admin/src/Repository/AdminRepository.php index fc360345..5b5fd4bf 100644 --- a/src/Admin/src/Repository/AdminRepository.php +++ b/src/Admin/src/Repository/AdminRepository.php @@ -5,12 +5,10 @@ namespace Frontend\Admin\Repository; use Doctrine\ORM\NonUniqueResultException; -use Doctrine\ORM\QueryBuilder; use Dot\DependencyInjection\Attribute\Entity; use Frontend\Admin\Entity\Admin; use Frontend\Admin\Entity\AdminLogin; use Frontend\App\Repository\AbstractRepository; -use Ramsey\Uuid\Doctrine\UuidBinaryOrderedTimeType; use Throwable; #[Entity(Admin::class)] @@ -47,10 +45,7 @@ public function exists(string $identity): bool } try { - $result = $this->getQueryBuilder()->select('admin') - ->from(Admin::class, 'admin') - ->andWhere('admin.identity = :identity') - ->setParameter('identity', $identity)->getQuery()->getSingleResult(); + $result = $this->findOneBy(['identity' => $identity]); } catch (Throwable) { $result = null; } @@ -154,36 +149,4 @@ public function setCacheLifetime(int $cacheLifetime): self return $this; } - - public function findAdminBy(array $params): ?Admin - { - if (empty($params)) { - return null; - } - - try { - $qb = $this->getQueryBuilder()->select('admin')->from(Admin::class, 'admin'); - $this->addUuidFilter($qb, $params['uuid'] ?? null); - $this->addIdentityFilter($qb, $params['identity'] ?? null); - - return $qb->getQuery()->getSingleResult(); - } catch (Throwable) { - return null; - } - } - - public function addUuidFilter(QueryBuilder $qb, ?string $uuid): void - { - if (! empty($uuid)) { - $qb->andWhere('admin.uuid = :admin_uuid') - ->setParameter('admin_uuid', $uuid, UuidBinaryOrderedTimeType::NAME); - } - } - - public function addIdentityFilter(QueryBuilder $qb, ?string $identity): void - { - if (! empty($identity)) { - $qb->andWhere('admin.identity = :admin_identity')->setParameter('admin_identity', $identity); - } - } } diff --git a/src/Admin/src/Repository/AdminRoleRepository.php b/src/Admin/src/Repository/AdminRoleRepository.php index 33a980b8..952b4cfd 100644 --- a/src/Admin/src/Repository/AdminRoleRepository.php +++ b/src/Admin/src/Repository/AdminRoleRepository.php @@ -18,7 +18,7 @@ class AdminRoleRepository extends AbstractRepository public function getRole(string $uuid): ?AdminRole { /** @var AdminRole $role */ - $role = $this->find($uuid); + $role = $this->findOneBy(['uuid' => $uuid]); return $role; } diff --git a/src/Admin/src/Service/AdminService.php b/src/Admin/src/Service/AdminService.php index dd506cc1..9f35e633 100644 --- a/src/Admin/src/Service/AdminService.php +++ b/src/Admin/src/Service/AdminService.php @@ -40,11 +40,6 @@ public function __construct( $this->adminRepository->setCacheLifetime($cacheLifetime); } - public function findAdminBy(array $params): ?Admin - { - return $this->adminRepository->findAdminBy($params); - } - public function getAdminRepository(): AdminRepository|EntityRepository { return $this->adminRepository; @@ -142,7 +137,7 @@ public function getAdminLogins( public function createAdmin(array $data): Admin { if ($this->exists($data['identity'])) { - throw new ORMException('An account with this identity already exists.'); + throw new \Frontend\App\Exception\ORMException('An account with this identity already exists.'); } $admin = (new Admin()) @@ -170,7 +165,7 @@ public function updateAdmin(Admin $admin, array $data): Admin if (! $this->exists($data['identity'])) { $admin->setIdentity($data['identity']); } elseif ($admin->getIdentity() !== $data['identity']) { - throw new ORMException('An account with this identity already exists'); + throw new \Frontend\App\Exception\ORMException('An account with this identity already exists'); } } if (! empty($data['password'])) { diff --git a/src/Admin/src/Service/AdminServiceInterface.php b/src/Admin/src/Service/AdminServiceInterface.php index b11ef782..4dbbe6b4 100644 --- a/src/Admin/src/Service/AdminServiceInterface.php +++ b/src/Admin/src/Service/AdminServiceInterface.php @@ -52,7 +52,5 @@ public function updateAdmin(Admin $admin, array $data): Admin; public function logAdminVisit(array $serverParams, string $name): AdminLogin; - public function findAdminBy(array $params): ?Admin; - public function getAdminFormProcessedRoles(): array; } diff --git a/src/App/src/Common/TimestampAwareInterface.php b/src/App/src/Common/TimestampAwareInterface.php deleted file mode 100644 index 23874eb3..00000000 --- a/src/App/src/Common/TimestampAwareInterface.php +++ /dev/null @@ -1,22 +0,0 @@ -touch(); - } - - public function getCreated(): ?DateTimeImmutable - { - return $this->created; - } - - public function getCreatedFormatted(?string $dateFormat = null): string - { - return $this->created->format($dateFormat ?? $this->dateFormat); - } - - public function getUpdated(): ?DateTimeImmutable - { - return $this->updated; - } - - public function getUpdatedFormatted(?string $dateFormat = null): ?string - { - return $this->updated?->format($dateFormat ?? $this->dateFormat); - } - - public function setDateFormat(string $dateFormat): void - { - $this->dateFormat = $dateFormat; - } - - public function touch(): void - { - try { - $this->created = new DateTimeImmutable(); - $this->updated = new DateTimeImmutable(); - } catch (Exception $exception) { - error_log($exception->getMessage()); - } - } -} diff --git a/src/App/src/Common/UuidAwareInterface.php b/src/App/src/Common/UuidAwareInterface.php deleted file mode 100644 index 74ed760b..00000000 --- a/src/App/src/Common/UuidAwareInterface.php +++ /dev/null @@ -1,12 +0,0 @@ -uuid) { - $this->uuid = UuidOrderedTimeGenerator::generateUuid(); - } - - return $this->uuid; - } -} diff --git a/src/App/src/Common/UuidOrderedTimeGenerator.php b/src/App/src/Common/UuidOrderedTimeGenerator.php deleted file mode 100644 index eea324e7..00000000 --- a/src/App/src/Common/UuidOrderedTimeGenerator.php +++ /dev/null @@ -1,29 +0,0 @@ -uuid1(); - } - - private static function getFactory(): UuidFactoryInterface - { - self::$factory = clone Uuid::getFactory(); - $codec = new OrderedTimeCodec(self::$factory->getUuidBuilder()); - self::$factory->setCodec($codec); - - return self::$factory; - } -} diff --git a/src/App/src/Entity/AbstractEntity.php b/src/App/src/Entity/AbstractEntity.php index 815d47b2..268dc03f 100644 --- a/src/App/src/Entity/AbstractEntity.php +++ b/src/App/src/Entity/AbstractEntity.php @@ -4,22 +4,24 @@ namespace Frontend\App\Entity; -use DateTimeImmutable; -use Frontend\App\Common\TimestampAwareInterface; -use Frontend\App\Common\TimestampAwareTrait; -use Frontend\App\Common\UuidAwareInterface; -use Frontend\App\Common\UuidAwareTrait; -use Frontend\App\Common\UuidOrderedTimeGenerator; +use Doctrine\ORM\Mapping as ORM; +use Ramsey\Uuid\Uuid; +use Ramsey\Uuid\UuidInterface; -abstract class AbstractEntity implements UuidAwareInterface, TimestampAwareInterface +#[ORM\MappedSuperclass] +abstract class AbstractEntity { - use TimestampAwareTrait; - use UuidAwareTrait; + #[ORM\Id] + #[ORM\Column(name: 'uuid', type: "uuid_binary", unique: true)] + protected UuidInterface $uuid; public function __construct() { - $this->uuid = UuidOrderedTimeGenerator::generateUuid(); - $this->created = new DateTimeImmutable(); - $this->updated = new DateTimeImmutable(); + $this->uuid = Uuid::uuid4(); + } + + public function getUuid(): UuidInterface + { + return $this->uuid; } } diff --git a/src/App/src/Entity/TimestampsTrait.php b/src/App/src/Entity/TimestampsTrait.php new file mode 100644 index 00000000..04e4c246 --- /dev/null +++ b/src/App/src/Entity/TimestampsTrait.php @@ -0,0 +1,54 @@ +created; + } + + public function getCreatedFormatted(string $dateFormat = 'Y-m-d H:i:s'): string + { + return $this->created->format($dateFormat); + } + + public function getUpdated(): ?DateTimeImmutable + { + return $this->updated; + } + + public function getUpdatedFormatted(string $dateFormat = 'Y-m-d H:i:s'): ?string + { + if ($this->updated instanceof DateTimeImmutable) { + return $this->updated->format($dateFormat); + } + + return null; + } + + #[ORM\PrePersist] + public function created(): void + { + $this->created = new DateTimeImmutable(); + } + + #[ORM\PreUpdate] + public function touch(): void + { + $this->updated = new DateTimeImmutable(); + } +} diff --git a/src/App/src/Exception/ORMException.php b/src/App/src/Exception/ORMException.php new file mode 100644 index 00000000..ba855ba0 --- /dev/null +++ b/src/App/src/Exception/ORMException.php @@ -0,0 +1,11 @@ + @@ -20,26 +16,4 @@ public function getQueryBuilder(): QueryBuilder { return $this->getEntityManager()->createQueryBuilder(); } - - /** - * @param mixed $id - * @param int|null $lockMode - * @param int|null $lockVersion - * @throws NonUniqueResultException - */ - public function find($id, $lockMode = null, $lockVersion = null): ?object - { - $qb = $this->getEntityManager()->createQueryBuilder(); - $qb->select('entity') - ->from($this->getEntityName(), 'entity') - ->where('entity.uuid = :uuid'); - - if (is_array($id)) { - $qb->setParameter('uuid', $id['uuid']->getBytes()); - } else { - $qb->setParameter('uuid', $id, UuidBinaryOrderedTimeType::NAME); - } - - return $qb->getQuery()->getOneOrNullResult(); - } } diff --git a/src/Setting/src/Controller/SettingController.php b/src/Setting/src/Controller/SettingController.php index 21dc5134..510769b3 100644 --- a/src/Setting/src/Controller/SettingController.php +++ b/src/Setting/src/Controller/SettingController.php @@ -72,7 +72,7 @@ public function storeSettingAction(): JsonResponse ], StatusCodeInterface::STATUS_BAD_REQUEST); } - $admin = $this->adminService->findAdminBy([ + $admin = $this->adminService->getAdminRepository()->findOneBy([ 'uuid' => $this->authenticationService->getIdentity()->getUuid(), ]); @@ -125,9 +125,11 @@ public function getSettingAction(): JsonResponse ], StatusCodeInterface::STATUS_BAD_REQUEST); } - $admin = $this->adminService->findAdminBy([ - 'uuid' => $this->authenticationService->getIdentity()->getUuid(), - ]); + $admin = $this->adminService->getAdminRepository()->findOneBy( + [ + 'uuid' => $this->authenticationService->getIdentity()->getUuid(), + ] + ); if (! $admin instanceof Admin) { return new JsonResponse([ diff --git a/src/Setting/src/Entity/Setting.php b/src/Setting/src/Entity/Setting.php index 2b646bb8..182d110f 100644 --- a/src/Setting/src/Entity/Setting.php +++ b/src/Setting/src/Entity/Setting.php @@ -7,6 +7,7 @@ use Doctrine\ORM\Mapping as ORM; use Frontend\Admin\Entity\Admin; use Frontend\App\Entity\AbstractEntity; +use Frontend\App\Entity\TimestampsTrait; use Frontend\Setting\Repository\SettingRepository; use function array_unique; @@ -15,8 +16,11 @@ #[ORM\Entity(repositoryClass: SettingRepository::class)] #[ORM\Table(name: 'settings')] +#[ORM\HasLifecycleCallbacks] class Setting extends AbstractEntity { + use TimestampsTrait; + public const IDENTIFIER_TABLE_ADMIN_LIST_SELECTED_COLUMNS = 'table_admin_list_selected_columns'; public const IDENTIFIER_TABLE_ADMIN_LIST_LOGINS_SELECTED_COLUMNS = 'table_admin_list_logins_selected_columns'; public const IDENTIFIERS = [ diff --git a/test/Unit/Admin/Adapter/AuthenticationAdapterTest.php b/test/Unit/Admin/Adapter/AuthenticationAdapterTest.php index 3a5c72ff..9dfc203c 100644 --- a/test/Unit/Admin/Adapter/AuthenticationAdapterTest.php +++ b/test/Unit/Admin/Adapter/AuthenticationAdapterTest.php @@ -6,7 +6,6 @@ use Doctrine\ORM\EntityManager; use Doctrine\ORM\Persisters\Exception\UnrecognizedField; -use Error; use Frontend\Admin\Adapter\AuthenticationAdapter; use Frontend\Admin\Entity\Admin; use Frontend\Admin\Repository\AdminRepository; @@ -101,6 +100,7 @@ public function testWillNotAuthenticateWithoutValidConfig(): void /** * @throws Exception * @throws \Exception + * @group testing */ public function testWillNotAuthenticateWithInvalidIdentityClassConfig(): void { @@ -111,14 +111,20 @@ public function testWillNotAuthenticateWithInvalidIdentityClassConfig(): void 'identity_class' => \Exception::class, 'identity_property' => 'identity', 'credential_property' => 'password', + 'messages' => [ + 'success' => 'Authenticated successfully.', + 'not_found' => 'Identity not found.', + 'invalid_credential' => 'Invalid credentials.', + ], ], ], ); $adapter->setCredential('test'); $adapter->setIdentity('test@example.com'); - $this->expectException(Error::class); - $adapter->authenticate(); + $auth = $adapter->authenticate(); + + $this->assertSame(-1, $auth->getCode()); } /** diff --git a/test/Unit/Admin/Entity/AdminLoginTest.php b/test/Unit/Admin/Entity/AdminLoginTest.php index e57ed126..d3871b26 100644 --- a/test/Unit/Admin/Entity/AdminLoginTest.php +++ b/test/Unit/Admin/Entity/AdminLoginTest.php @@ -4,13 +4,12 @@ namespace FrontendTest\Unit\Admin\Entity; -use DateTimeInterface; use Doctrine\ORM\Mapping\Entity; use Doctrine\ORM\Mapping\Table; use Frontend\Admin\Entity\AdminLogin; use Frontend\Admin\Repository\AdminLoginRepository; use FrontendTest\Unit\UnitTest; -use Ramsey\Uuid\Rfc4122\UuidInterface; +use Ramsey\Uuid\UuidInterface; use ReflectionAttribute; use ReflectionClass; @@ -129,11 +128,5 @@ public function testAccessors(): void $adminLogin = $adminLogin->setIdentity('test'); $this->assertInstanceOf(AdminLogin::class, $adminLogin); $this->assertSame('test', $adminLogin->getIdentity()); - - $this->assertInstanceOf(DateTimeInterface::class, $adminLogin->getCreated()); - $this->assertIsString($adminLogin->getCreatedFormatted()); - - $this->assertInstanceOf(DateTimeInterface::class, $adminLogin->getUpdated()); - $this->assertIsString($adminLogin->getUpdatedFormatted()); } } diff --git a/test/Unit/Admin/Entity/AdminRoleTest.php b/test/Unit/Admin/Entity/AdminRoleTest.php index 2b6525b3..a83e3cce 100644 --- a/test/Unit/Admin/Entity/AdminRoleTest.php +++ b/test/Unit/Admin/Entity/AdminRoleTest.php @@ -4,13 +4,12 @@ namespace FrontendTest\Unit\Admin\Entity; -use DateTimeInterface; use Doctrine\ORM\Mapping\Entity; use Doctrine\ORM\Mapping\Table; use Frontend\Admin\Entity\AdminRole; use Frontend\Admin\Repository\AdminRoleRepository; use FrontendTest\Unit\UnitTest; -use Ramsey\Uuid\Rfc4122\UuidInterface; +use Ramsey\Uuid\UuidInterface; use ReflectionAttribute; use ReflectionClass; @@ -49,12 +48,6 @@ public function testAccessors(): void $adminRole = $adminRole->setName(AdminRole::ROLE_ADMIN); $this->assertInstanceOf(AdminRole::class, $adminRole); $this->assertSame(AdminRole::ROLE_ADMIN, $adminRole->getName()); - - $this->assertInstanceOf(DateTimeInterface::class, $adminRole->getCreated()); - $this->assertIsString($adminRole->getCreatedFormatted()); - - $this->assertInstanceOf(DateTimeInterface::class, $adminRole->getUpdated()); - $this->assertIsString($adminRole->getUpdatedFormatted()); } public function testWillGetArrayCopy(): void @@ -72,9 +65,7 @@ public function testWillGetArrayCopy(): void $this->assertSame(AdminRole::ROLE_ADMIN, $copy['name']); $this->assertArrayHasKey('created', $copy); - $this->assertInstanceOf(DateTimeInterface::class, $copy['created']); $this->assertArrayHasKey('updated', $copy); - $this->assertInstanceOf(DateTimeInterface::class, $copy['updated']); } } diff --git a/test/Unit/Admin/Entity/AdminTest.php b/test/Unit/Admin/Entity/AdminTest.php index 0b86cbc1..72464dfe 100644 --- a/test/Unit/Admin/Entity/AdminTest.php +++ b/test/Unit/Admin/Entity/AdminTest.php @@ -4,7 +4,6 @@ namespace FrontendTest\Unit\Admin\Entity; -use DateTimeInterface; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping\Entity; use Doctrine\ORM\Mapping\Table; @@ -12,7 +11,7 @@ use Frontend\Admin\Entity\AdminRole; use Frontend\Admin\Repository\AdminRepository; use FrontendTest\Unit\UnitTest; -use Ramsey\Uuid\Rfc4122\UuidInterface; +use Ramsey\Uuid\UuidInterface; use ReflectionAttribute; use ReflectionClass; @@ -104,12 +103,6 @@ public function testAccessors(): void $this->assertInstanceOf(Admin::class, $admin); $this->assertIsArray($admin->getRoles()); $this->assertCount(1, $admin->getRoles()); - - $this->assertInstanceOf(DateTimeInterface::class, $admin->getCreated()); - $this->assertIsString($admin->getCreatedFormatted()); - - $this->assertInstanceOf(DateTimeInterface::class, $admin->getUpdated()); - $this->assertIsString($admin->getUpdatedFormatted()); } public function testWillGetArrayCopy(): void @@ -149,9 +142,7 @@ public function testWillGetArrayCopy(): void $this->assertSame($this->default['roles'][0]->getName(), $copy['roles'][0]['name']); $this->assertArrayHasKey('created', $copy); - $this->assertInstanceOf(DateTimeInterface::class, $copy['created']); $this->assertArrayHasKey('updated', $copy); - $this->assertInstanceOf(DateTimeInterface::class, $copy['updated']); } } diff --git a/test/Unit/App/Common/TimestampAwareTest.php b/test/Unit/App/Common/TimestampAwareTest.php deleted file mode 100644 index dd114fa4..00000000 --- a/test/Unit/App/Common/TimestampAwareTest.php +++ /dev/null @@ -1,47 +0,0 @@ -assertNull($entity->getCreated()); - $this->assertNull($entity->getUpdated()); - - $entity->updateTimestamps(); - - $this->assertInstanceOf(DateTimeInterface::class, $entity->getCreated()); - $this->assertIsString($entity->getCreatedFormatted()); - $this->assertSame(date('Y-m-d H:i:s'), $entity->getCreatedFormatted()); - $this->assertSame(date('d-m-Y H:i:s'), $entity->getCreatedFormatted('d-m-Y H:i:s')); - - $this->assertInstanceOf(DateTimeInterface::class, $entity->getUpdated()); - $this->assertIsString($entity->getUpdatedFormatted()); - $this->assertSame(date('Y-m-d H:i:s'), $entity->getUpdatedFormatted()); - $this->assertSame(date('d-m-Y H:i:s'), $entity->getUpdatedFormatted('d-m-Y H:i:s')); - - $entity->setDateFormat('d-m-Y H:i:s'); - - $this->assertIsString($entity->getCreatedFormatted()); - $this->assertSame(date('d-m-Y H:i:s'), $entity->getCreatedFormatted()); - $this->assertSame(date('Y-m-d H:i:s'), $entity->getCreatedFormatted('Y-m-d H:i:s')); - - $this->assertIsString($entity->getUpdatedFormatted()); - $this->assertSame(date('d-m-Y H:i:s'), $entity->getUpdatedFormatted()); - $this->assertSame(date('Y-m-d H:i:s'), $entity->getUpdatedFormatted('Y-m-d H:i:s')); - } -} diff --git a/test/Unit/App/Common/UuidAwareTest.php b/test/Unit/App/Common/UuidAwareTest.php deleted file mode 100644 index 5e9d7ee2..00000000 --- a/test/Unit/App/Common/UuidAwareTest.php +++ /dev/null @@ -1,24 +0,0 @@ -getUuid(); - $this->assertInstanceOf(UuidInterface::class, $uuid); - $this->assertSame($uuid, $entity->getUuid()); - } -} diff --git a/test/Unit/App/Common/UuidOrderedTimeGeneratorTest.php b/test/Unit/App/Common/UuidOrderedTimeGeneratorTest.php deleted file mode 100644 index 3f6923c9..00000000 --- a/test/Unit/App/Common/UuidOrderedTimeGeneratorTest.php +++ /dev/null @@ -1,23 +0,0 @@ -assertInstanceOf(UuidInterface::class, $firstUuid); - - $secondUuid = UuidOrderedTimeGenerator::generateUuid(); - $this->assertInstanceOf(UuidInterface::class, $secondUuid); - - $this->assertNotSame($firstUuid, $secondUuid); - } -} diff --git a/test/Unit/App/Entity/AbstractEntityTest.php b/test/Unit/App/Entity/AbstractEntityTest.php index b61a0146..482adf60 100644 --- a/test/Unit/App/Entity/AbstractEntityTest.php +++ b/test/Unit/App/Entity/AbstractEntityTest.php @@ -4,7 +4,6 @@ namespace FrontendTest\Unit\App\Entity; -use DateTimeInterface; use Frontend\App\Entity\AbstractEntity; use FrontendTest\Unit\UnitTest; use Ramsey\Uuid\UuidInterface; @@ -18,7 +17,5 @@ public function testWillInstantiate(): void $this->assertInstanceOf(AbstractEntity::class, $entity); $this->assertInstanceOf(UuidInterface::class, $entity->getUuid()); - $this->assertInstanceOf(DateTimeInterface::class, $entity->getCreated()); - $this->assertInstanceOf(DateTimeInterface::class, $entity->getUpdated()); } } From 1413c868641c649f85e725604a8b3c502f50896b Mon Sep 17 00:00:00 2001 From: Claudiu Pintiuta Date: Fri, 28 Jun 2024 15:56:20 +0300 Subject: [PATCH 02/15] changes from github ci Signed-off-by: Claudiu Pintiuta --- README.md | 53 +++++++++-------------------- config/autoload/local.test.php.dist | 2 +- 2 files changed, 18 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index 7c1ffc8b..6c3f21a9 100644 --- a/README.md +++ b/README.md @@ -16,24 +16,12 @@ DotKernel web starter package suitable for admin applications. [![SymfonyInsight](https://insight.symfony.com/projects/6a7ecfc1-a0ed-4901-96ac-d0ff61f7b55f/big.svg)](https://insight.symfony.com/projects/6a7ecfc1-a0ed-4901-96ac-d0ff61f7b55f) - -# Installing DotKernel `admin` - -- [Installing DotKernel `admin`](#installing-dotkernel-admin) - - [Installation](#installation) - - [Composer](#composer) - - [Choose a destination path for DotKernel `admin` installation](#choose-a-destination-path-for-dotkernel-admin-installation) - - [Installing the `admin` Composer package](#installing-the-admin-composer-package) - - [Installing DotKernel admin](#installing-dotkernel-admin) - - [Configuration - First Run](#configuration---first-run) - - [Manage GeoLite2 database](#manage-geolite2-database) - - [Testing (Running)](#testing-running) +## Installing DotKernel `admin` ## Tools DotKernel can be installed through a single command that utilizes [Composer](https://getcomposer.org/). Because of that, Composer is required to install DotKernel `admin`. - ### Composer Installation instructions: @@ -41,32 +29,27 @@ Installation instructions: - [Composer Installation - Linux/Unix/OSX](https://getcomposer.org/doc/00-intro.md#installation-linux-unix-osx) - [Composer Installation - Windows](https://getcomposer.org/doc/00-intro.md#installation-windows) -> If you have never used composer before make sure you read the [`Composer Basic Usage`](https://getcomposer.org/doc/01-basic-usage.md) section in Composer's documentation +>If you have never used composer before make sure you read the [`Composer Basic Usage`](https://getcomposer.org/doc/01-basic-usage.md) section in Composer's documentation - -## Choosing an installation path for DotKernel `admin` +## Choosing an installation path for DotKernel `admin` Example: - absolute path `/var/www/dk-admin` - or relative path `dk-admin` (equivalent with `./dk-admin`) - ## Installing DotKernel `admin` -After choosing the path for DotKernel (`dk-admin` will be used for the remainder of this example) it must be installed. There are two installation methods. - +After choosing the path for DotKernel (`dk-admin` will be used for the remainder of this example) it must be installed. There are two installation methods. -#### I. Installing DotKernel `admin` using composer +### I. Installing DotKernel `admin` using composer -#### NOTE -> please use the below CLI commands in terminal, do NOT use the PhpStorm buttons +>please use the below CLI commands in terminal, do NOT use the PhpStorm buttons The advantage of using this command is that it runs through the whole installation process. Run the following command: composer create-project dotkernel/admin -s dev dk - The above command downloads the `admin` package, then downloads and installs the `dependencies`. The setup script prompts for some configuration settings, for example the lines below: @@ -88,30 +71,29 @@ The next question is: Type `y` here, and hit `enter` -#### II. Installing DotKernel `admin` using git clone +### II. Installing DotKernel `admin` using git clone This method requires more manual input, but it ensures that the default branch is installed, even if it is not released. Run the following command: git clone https://github.com/dotkernel/admin.git . - The dependencies have to be installed separately, by running this command composer install - Just like for `II Installing DotKernel admin using composer` (see above), the setup asks for configuration settings regarding injections (type `0` and hit `enter`) and a confirmation to use this setting for other packages (type `y` and hit `enter`) - ## Configuration - First Run - Remove the `.dist` extension from the files `config/autoload/local.php.dist` - Edit `config/autoload/local.php` according to your dev machine and fill in the `database` configuration Run the migrations and seeds with these commands: + ```shell php bin/doctrine-migrations migrate ``` + ```shell php bin/doctrine fixtures:execute ``` @@ -120,9 +102,11 @@ Run the migrations and seeds with these commands: ```shell composer development-status ``` + ```shell composer development-enable ``` + ```shell composer development-disable ``` @@ -138,14 +122,12 @@ You can download/update a specific GeoLite2 database, by running the following c php bin/cli.php geoip:synchronize -d {DATABASE} - Where _{DATABASE}_ takes one of the following values: `asn`, `city`, `country`. You can download/update all GeoLite2 databases at once, by running the following command: php bin/cli.php geoip:synchronize - The output should be similar to the below, displaying per row: `database identifier`: `previous build datetime` -> `current build datetime`. > asn: n/a -> 2021-07-01 02:09:34 @@ -158,30 +140,26 @@ Get help for this command by running: php bin/cli.php help geoip:synchronize - **Tip**: If you setup the synchronizer command as a cronjob, you can add the `-q|--quiet` option, and it will output data only if an error has occurred. - ## NPM Commands To install dependencies into the `node_modules` directory run this command. npm install - If `npm install` fails, this could be caused by user permissions of npm. Recommendation is to install npm through `Node Version Manager`. The watch command compiles the components then watches the files and recompiles when one of them changes. npm run watch - After all updates are done, this command compiles the assets locally, minifies them and makes them ready for production. npm run prod - ## Authorization Guards + The packages responsible for restricting access to certain parts of the application are [dot-rbac-guard](https://github.com/dotkernel/dot-rbac-guard) and [dot-rbac](https://github.com/dotkernel/dot-rbac). These packages work together to create an infrastructure that is customizable and diversified to manage user access to the platform by specifying the type of role the user has. The `authorization.global.php` file provides multiple configurations specifying multiple roles as well as the types of permissions to which these roles have access. @@ -239,11 +217,12 @@ The `authorization-guards.global.php` file provides configuration to restrict ac Note: **Do not enable dev mode in production** - Run the following command in your project's directory to start PHPs built-in server: +- ```shell php -S 0.0.0.0:8080 -t public ``` -> Running command `composer serve` will do the exact same, but the above is faster. +>Running command `composer serve` will do the exact same, but the above is faster. `0.0.0.0` means that the server is open to all incoming connections `127.0.0.1` means that the server can only be accessed locally (localhost only) @@ -255,7 +234,7 @@ If you are still getting exceptions or errors regarding some missing services, t php bin/clear-config-cache.php -> If `config-cache.php` is present that config will be loaded regardless of the `ConfigAggregator::ENABLE_CACHE` in `config/autoload/mezzio.global.php` +>If `config-cache.php` is present that config will be loaded regardless of the `ConfigAggregator::ENABLE_CACHE` in `config/autoload/mezzio.global.php` - Open a web browser and visit `http://localhost:8080/` @@ -269,6 +248,7 @@ If you ran the migrations you will have an admin user in the database with the f **NOTE:** - **Production only**: Make sure you modify the default admin credentials. - **Development only**: `session.cookie_secure` does not work locally so make sure you modify your `local.php`, as per the following: + ```php # other code @@ -279,4 +259,5 @@ return [ ], ]; ``` + Do not change this in `local.php.dist` as well because this value should remain `true` on production. diff --git a/config/autoload/local.test.php.dist b/config/autoload/local.test.php.dist index 6f577379..b7de6fd5 100644 --- a/config/autoload/local.test.php.dist +++ b/config/autoload/local.test.php.dist @@ -13,7 +13,7 @@ return [ 'connection' => [ 'orm_default' => [ 'params' => [ - 'url' => 'sqlite:///:memory:', + 'url' => 'sqlite3:///:memory:', ], ], ], From 0de5e23aa964ecddeebfc20eb27fe6112210557a Mon Sep 17 00:00:00 2001 From: Claudiu Pintiuta Date: Fri, 28 Jun 2024 16:49:41 +0300 Subject: [PATCH 03/15] changes from github ci Signed-off-by: Claudiu Pintiuta --- .github/workflows/qodana_code_quality.yml | 2 +- README.md | 84 ++++++++++++------- .../Adapter/AuthenticationAdapterTest.php | 14 +++- 3 files changed, 63 insertions(+), 37 deletions(-) diff --git a/.github/workflows/qodana_code_quality.yml b/.github/workflows/qodana_code_quality.yml index a9ea9b79..2e492b72 100644 --- a/.github/workflows/qodana_code_quality.yml +++ b/.github/workflows/qodana_code_quality.yml @@ -4,7 +4,7 @@ on: pull_request: push: branches: - - 4.0 + - 5.0 - 'releases/*' jobs: diff --git a/README.md b/README.md index 6c3f21a9..b9212c3e 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,8 @@ DotKernel web starter package suitable for admin applications. ## Tools -DotKernel can be installed through a single command that utilizes [Composer](https://getcomposer.org/). Because of that, Composer is required to install DotKernel `admin`. +DotKernel can be installed through a single command that utilizes [Composer](https://getcomposer.org/). Because of that, +Composer is required to install DotKernel `admin`. ### Composer @@ -29,7 +30,8 @@ Installation instructions: - [Composer Installation - Linux/Unix/OSX](https://getcomposer.org/doc/00-intro.md#installation-linux-unix-osx) - [Composer Installation - Windows](https://getcomposer.org/doc/00-intro.md#installation-windows) ->If you have never used composer before make sure you read the [`Composer Basic Usage`](https://getcomposer.org/doc/01-basic-usage.md) section in Composer's documentation +>If you have never used composer before make sure you read +>the [`Composer Basic Usage`](https://getcomposer.org/doc/01-basic-usage.md) section in Composer's documentation ## Choosing an installation path for DotKernel `admin` @@ -40,11 +42,12 @@ Example: ## Installing DotKernel `admin` -After choosing the path for DotKernel (`dk-admin` will be used for the remainder of this example) it must be installed. There are two installation methods. +After choosing the path for DotKernel (`dk-admin` will be used for the remainder of this example) it must be installed. +There are two installation methods. -### I. Installing DotKernel `admin` using composer +### I. Installing DotKernel `admin` using composer ->please use the below CLI commands in terminal, do NOT use the PhpStorm buttons +>please use the below CLI commands in terminal, do NOT use the PhpStorm buttons The advantage of using this command is that it runs through the whole installation process. Run the following command: @@ -59,8 +62,8 @@ The setup script prompts for some configuration settings, for example the lines [1] config/config.php Make your selection (default is 1): - -Simply select `[0] Do not inject`, because DotKernel includes its own configProvider which already contains the prompted configurations. +Simply select `[0] Do not inject`, because DotKernel includes its own configProvider which already contains the prompted +configurations. If you choose `[1] config/config.php` Laminas's `ConfigProvider` from `session` will be injected. @@ -70,10 +73,10 @@ The next question is: Type `y` here, and hit `enter` - ### II. Installing DotKernel `admin` using git clone -This method requires more manual input, but it ensures that the default branch is installed, even if it is not released. Run the following command: +This method requires more manual input, but it ensures that the default branch is installed, even if it is not released. +Run the following command: git clone https://github.com/dotkernel/admin.git . @@ -81,7 +84,9 @@ The dependencies have to be installed separately, by running this command composer install -Just like for `II Installing DotKernel admin using composer` (see above), the setup asks for configuration settings regarding injections (type `0` and hit `enter`) and a confirmation to use this setting for other packages (type `y` and hit `enter`) +Just like for `II Installing DotKernel admin using composer` (see above), the setup asks for configuration settings +regarding injections (type `0` and hit `enter`) and a confirmation to use this setting for other packages (type `y` and +hit `enter`) ## Configuration - First Run @@ -91,28 +96,31 @@ Just like for `II Installing DotKernel admin using composer` (see above), the se Run the migrations and seeds with these commands: ```shell - php bin/doctrine-migrations migrate +php bin/doctrine-migrations migrate ``` ```shell - php bin/doctrine fixtures:execute +php bin/doctrine fixtures:execute ``` -- If you use `composer create-project`, the project will go into development mode automatically after installing. The development mode status can be checked and toggled by using these composer commands: +- If you use `composer create-project`, the project will go into development mode automatically after installing. The + development mode status can be checked and toggled by using these composer commands: + ```shell - composer development-status +composer development-status ``` ```shell - composer development-enable +composer development-enable ``` ```shell - composer development-disable +composer development-disable ``` - If not already done on installation, remove the `.dist` extension from `config/autoload/development.global.php.dist`. -This will enable dev mode by turning debug flag to `true` and turning configuration caching to `off`. It will also make sure that any existing config cache is cleared. +This will enable dev mode by turning debug flag to `true` and turning configuration caching to `off`. It will also +make sure that any existing config cache is cleared. > Charset recommendation: utf8mb4_general_ci @@ -128,19 +136,21 @@ You can download/update all GeoLite2 databases at once, by running the following php bin/cli.php geoip:synchronize -The output should be similar to the below, displaying per row: `database identifier`: `previous build datetime` -> `current build datetime`. +The output should be similar to the below, displaying per +row: `database identifier`: `previous build datetime` -> `current build datetime`. > asn: n/a -> 2021-07-01 02:09:34 -> +> > city: n/a -> 2021-07-01 02:09:20 -> +> > country: n/a -> 2021-07-01 02:05:12 Get help for this command by running: php bin/cli.php help geoip:synchronize -**Tip**: If you setup the synchronizer command as a cronjob, you can add the `-q|--quiet` option, and it will output data only if an error has occurred. +**Tip**: If you setup the synchronizer command as a cronjob, you can add the `-q|--quiet` option, and it will output +data only if an error has occurred. ## NPM Commands @@ -148,21 +158,26 @@ To install dependencies into the `node_modules` directory run this command. npm install -If `npm install` fails, this could be caused by user permissions of npm. Recommendation is to install npm through `Node Version Manager`. +If `npm install` fails, this could be caused by user permissions of npm. Recommendation is to install npm +through `Node Version Manager`. The watch command compiles the components then watches the files and recompiles when one of them changes. npm run watch -After all updates are done, this command compiles the assets locally, minifies them and makes them ready for production. +After all updates are done, this command compiles the assets locally, minifies them and makes them ready for production. npm run prod ## Authorization Guards -The packages responsible for restricting access to certain parts of the application are [dot-rbac-guard](https://github.com/dotkernel/dot-rbac-guard) and [dot-rbac](https://github.com/dotkernel/dot-rbac). These packages work together to create an infrastructure that is customizable and diversified to manage user access to the platform by specifying the type of role the user has. +The packages responsible for restricting access to certain parts of the application +are [dot-rbac-guard](https://github.com/dotkernel/dot-rbac-guard) and [dot-rbac](https://github.com/dotkernel/dot-rbac). +These packages work together to create an infrastructure that is customizable and diversified to manage user access to +the platform by specifying the type of role the user has. -The `authorization.global.php` file provides multiple configurations specifying multiple roles as well as the types of permissions to which these roles have access. +The `authorization.global.php` file provides multiple configurations specifying multiple roles as well as the types of +permissions to which these roles have access. ```php //example of a flat RBAC model that specifies two types of roles as well as their permission @@ -184,7 +199,9 @@ The `authorization.global.php` file provides multiple configurations specifying ] ``` -The `authorization-guards.global.php` file provides configuration to restrict access to certain actions based on the permissions defined in `authorization.global.php` so basically we have to add the permissions in the dot-rbac configuration file first to specify the action restriction permissions. +The `authorization-guards.global.php` file provides configuration to restrict access to certain actions based on the +permissions defined in `authorization.global.php` so basically we have to add the permissions in the dot-rbac +configuration file first to specify the action restriction permissions. ```php //example of configuration example to restrict certain actions of some routes based on the permissions specified in the dot-rbac configuration file @@ -217,12 +234,13 @@ The `authorization-guards.global.php` file provides configuration to restrict ac Note: **Do not enable dev mode in production** - Run the following command in your project's directory to start PHPs built-in server: -- +- + ```shell - php -S 0.0.0.0:8080 -t public +php -S 0.0.0.0:8080 -t public ``` ->Running command `composer serve` will do the exact same, but the above is faster. +> Running command `composer serve` will do the exact same, but the above is faster. `0.0.0.0` means that the server is open to all incoming connections `127.0.0.1` means that the server can only be accessed locally (localhost only) @@ -233,8 +251,8 @@ If you are still getting exceptions or errors regarding some missing services, t php bin/clear-config-cache.php - ->If `config-cache.php` is present that config will be loaded regardless of the `ConfigAggregator::ENABLE_CACHE` in `config/autoload/mezzio.global.php` +> If `config-cache.php` is present that config will be loaded regardless of the `ConfigAggregator::ENABLE_CACHE` +> in `config/autoload/mezzio.global.php` - Open a web browser and visit `http://localhost:8080/` @@ -246,8 +264,10 @@ If you ran the migrations you will have an admin user in the database with the f - **Password**: `dotadmin` **NOTE:** + - **Production only**: Make sure you modify the default admin credentials. -- **Development only**: `session.cookie_secure` does not work locally so make sure you modify your `local.php`, as per the following: +- **Development only**: `session.cookie_secure` does not work locally so make sure you modify your `local.php`, as per + the following: ```php # other code diff --git a/test/Unit/Admin/Adapter/AuthenticationAdapterTest.php b/test/Unit/Admin/Adapter/AuthenticationAdapterTest.php index 9dfc203c..acfc51d7 100644 --- a/test/Unit/Admin/Adapter/AuthenticationAdapterTest.php +++ b/test/Unit/Admin/Adapter/AuthenticationAdapterTest.php @@ -135,20 +135,26 @@ public function testWillNotAuthenticateWithInvalidIdentityClassConfig(): void public function testWillNotAuthenticateWithInvalidIdentityPropertyConfig(): void { $adapter = new AuthenticationAdapter( - $this->getContainer()->get(EntityManager::class), + $this->createMock(EntityManager::class), [ 'orm_default' => [ 'identity_class' => Admin::class, - 'identity_property' => 'test', + 'identity_property' => 'identity', 'credential_property' => 'password', + 'messages' => [ + 'success' => 'Authenticated successfully.', + 'not_found' => 'Identity not found.', + 'invalid_credential' => 'Invalid credentials.', + ], ], ], ); $adapter->setCredential('test'); $adapter->setIdentity('test@example.com'); - $this->expectException(UnrecognizedField::class); - $adapter->authenticate(); + $auth = $adapter->authenticate(); + + $this->assertSame(-1, $auth->getCode()); } /** From 2ce227ef2ee877702de1380e7d51167923ffc037 Mon Sep 17 00:00:00 2001 From: Claudiu Pintiuta Date: Fri, 28 Jun 2024 18:17:33 +0300 Subject: [PATCH 04/15] changes from github ci Signed-off-by: Claudiu Pintiuta --- README.md | 27 +++++++-------------------- test/Common/TestCase.php | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index b9212c3e..2952ceaf 100644 --- a/README.md +++ b/README.md @@ -95,28 +95,18 @@ hit `enter`) Run the migrations and seeds with these commands: -```shell -php bin/doctrine-migrations migrate -``` + php bin/doctrine-migrations migrate -```shell -php bin/doctrine fixtures:execute -``` + php bin/doctrine fixtures:execute - If you use `composer create-project`, the project will go into development mode automatically after installing. The development mode status can be checked and toggled by using these composer commands: -```shell -composer development-status -``` + composer development-status + + composer development-enable -```shell -composer development-enable -``` - -```shell -composer development-disable -``` + composer development-disable - If not already done on installation, remove the `.dist` extension from `config/autoload/development.global.php.dist`. This will enable dev mode by turning debug flag to `true` and turning configuration caching to `off`. It will also @@ -234,11 +224,8 @@ configuration file first to specify the action restriction permissions. Note: **Do not enable dev mode in production** - Run the following command in your project's directory to start PHPs built-in server: -- -```shell -php -S 0.0.0.0:8080 -t public -``` + php -S 0.0.0.0:8080 -t public > Running command `composer serve` will do the exact same, but the above is faster. diff --git a/test/Common/TestCase.php b/test/Common/TestCase.php index c029de97..f060d95b 100644 --- a/test/Common/TestCase.php +++ b/test/Common/TestCase.php @@ -10,6 +10,8 @@ use Psr\Container\ContainerInterface; use Psr\Container\NotFoundExceptionInterface; +use RuntimeException; + use function realpath; class TestCase extends \PHPUnit\Framework\TestCase @@ -20,6 +22,23 @@ class TestCase extends \PHPUnit\Framework\TestCase protected function setUp(): void { TestMode::enable(); + $this->ensureTestMode(); + + } + + private function ensureTestMode(): void + { + if (! TestMode::isEnabled()) { + throw new RuntimeException( + 'You are running tests, but test mode is NOT enabled. Did you forget to create local.test.php?' + ); + } + + if (! $this->getEntityManager()->getConnection()->getParams()['memory'] ?? false) { + throw new RuntimeException( + 'You are running tests in a non in-memory database. Did you forget to create local.test.php?' + ); + } } protected function tearDown(): void From 9a4d21853678b695f73af8b8da89a49be081c1f1 Mon Sep 17 00:00:00 2001 From: Claudiu Pintiuta Date: Fri, 28 Jun 2024 18:26:26 +0300 Subject: [PATCH 05/15] changes from github ci Signed-off-by: Claudiu Pintiuta --- README.md | 28 ++++++++++++++-------------- config/autoload/doctrine.global.php | 10 ---------- psalm-baseline.xml | 6 ------ src/App/src/ConfigProvider.php | 2 ++ 4 files changed, 16 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 2952ceaf..bef1c432 100644 --- a/README.md +++ b/README.md @@ -171,22 +171,22 @@ permissions to which these roles have access. ```php //example of a flat RBAC model that specifies two types of roles as well as their permission - 'roles' => [ - 'superuser' => [ - 'permissions' => [ - 'authenticated', - 'edit', - 'delete', - //etc.. - ] - ], - 'admin' => [ - 'permissions' => [ - 'authenticated', - //etc.. - ] +'roles' => [ + 'superuser' => [ + 'permissions' => [ + 'authenticated', + 'edit', + 'delete', + //etc.. + ] + ], + 'admin' => [ + 'permissions' => [ + 'authenticated', + //etc.. ] ] +] ``` The `authorization-guards.global.php` file provides configuration to restrict access to certain actions based on the diff --git a/config/autoload/doctrine.global.php b/config/autoload/doctrine.global.php index 00d76767..26f331ee 100644 --- a/config/autoload/doctrine.global.php +++ b/config/autoload/doctrine.global.php @@ -15,16 +15,6 @@ use Roave\PsrContainerDoctrine\EntityManagerFactory; return [ - 'dependencies' => [ - 'factories' => [ - 'doctrine.entity_manager.orm_default' => EntityManagerFactory::class, - ], - 'aliases' => [ - EntityManager::class => 'doctrine.entity_manager.orm_default', - EntityManagerInterface::class => 'doctrine.entity_manager.orm_default', - 'doctrine.entitymanager.orm_default' => 'doctrine.entity_manager.orm_default', - ], - ], 'doctrine' => [ 'configuration' => [ 'orm_default' => [ diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 6d463172..35fe0e50 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -6,12 +6,6 @@ getStorage - - - getUuidBuilder - setCodec - - iterable diff --git a/src/App/src/ConfigProvider.php b/src/App/src/ConfigProvider.php index 68148d08..11c9e6cc 100644 --- a/src/App/src/ConfigProvider.php +++ b/src/App/src/ConfigProvider.php @@ -16,6 +16,7 @@ use Frontend\App\Plugin\FormsPlugin; use Frontend\App\Resolver\EntityListenerResolver; use Mezzio\Application; +use Roave\PsrContainerDoctrine\EntityManagerFactory; class ConfigProvider { @@ -38,6 +39,7 @@ public function getDependencies(): array ], ], 'factories' => [ + 'doctrine.entity_manager.orm_default' => EntityManagerFactory::class, EntityListenerResolver::class => EntityListenerResolverFactory::class, DashboardController::class => AttributedServiceFactory::class, PageController::class => AttributedServiceFactory::class, From 5038944447e411b8d1370def1167666dc95756dd Mon Sep 17 00:00:00 2001 From: Claudiu Pintiuta Date: Fri, 28 Jun 2024 18:32:28 +0300 Subject: [PATCH 06/15] changes from github ci Signed-off-by: Claudiu Pintiuta --- README.md | 94 ++++++++----------- config/autoload/doctrine.global.php | 3 - src/App/src/ConfigProvider.php | 10 +- test/Common/TestCase.php | 2 - .../Adapter/AuthenticationAdapterTest.php | 1 - 5 files changed, 46 insertions(+), 64 deletions(-) diff --git a/README.md b/README.md index bef1c432..2049dfa4 100644 --- a/README.md +++ b/README.md @@ -169,55 +169,49 @@ the platform by specifying the type of role the user has. The `authorization.global.php` file provides multiple configurations specifying multiple roles as well as the types of permissions to which these roles have access. -```php -//example of a flat RBAC model that specifies two types of roles as well as their permission -'roles' => [ - 'superuser' => [ - 'permissions' => [ - 'authenticated', - 'edit', - 'delete', - //etc.. - ] - ], - 'admin' => [ - 'permissions' => [ - 'authenticated', - //etc.. + 'roles' => [ + 'superuser' => [ + 'permissions' => [ + 'authenticated', + 'edit', + 'delete', + //etc.. + ] + ], + 'admin' => [ + 'permissions' => [ + 'authenticated', + //etc.. + ] ] ] -] -``` The `authorization-guards.global.php` file provides configuration to restrict access to certain actions based on the permissions defined in `authorization.global.php` so basically we have to add the permissions in the dot-rbac configuration file first to specify the action restriction permissions. -```php -//example of configuration example to restrict certain actions of some routes based on the permissions specified in the dot-rbac configuration file 'rules' => [ - [ - 'route' => 'account', - 'actions' => [//list of actions to apply , or empty array for all actions - 'unregister', - 'avatar', - 'details', - 'changePassword' - ], - 'permissions' => ['authenticated'] - ], - [ - 'route' => 'admin', - 'actions' => [ - 'deleteAccount' - ], - 'permissions' => [ - 'delete' - //list of roles to allow - ] - ] + [ + 'route' => 'account', + 'actions' => [//list of actions to apply , or empty array for all actions + 'unregister', + 'avatar', + 'details', + 'changePassword' + ], + 'permissions' => ['authenticated'] + ], + [ + 'route' => 'admin', + 'actions' => [ + 'deleteAccount' + ], + 'permissions' => [ + 'delete' + //list of roles to allow + ] + ] ] -``` ## Testing (Running) @@ -253,18 +247,12 @@ If you ran the migrations you will have an admin user in the database with the f **NOTE:** - **Production only**: Make sure you modify the default admin credentials. -- **Development only**: `session.cookie_secure` does not work locally so make sure you modify your `local.php`, as per - the following: - -```php -# other code - -return [ - # other configurations... - 'session_config' => [ - 'cookie_secure' => false, - ], -]; -``` +- **Development only**: `session.cookie_secure` does not work locally so make sure you modify your `local.php`, as per the following: + + return [ + 'session_config' => [ + 'cookie_secure' => false, + ] + ]; Do not change this in `local.php.dist` as well because this value should remain `true` on production. diff --git a/config/autoload/doctrine.global.php b/config/autoload/doctrine.global.php index 26f331ee..53534e57 100644 --- a/config/autoload/doctrine.global.php +++ b/config/autoload/doctrine.global.php @@ -2,8 +2,6 @@ declare(strict_types=1); -use Doctrine\ORM\EntityManager; -use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Mapping\Driver\AttributeDriver; use Doctrine\Persistence\Mapping\Driver\MappingDriverChain; use Dot\Cache\Adapter\ArrayAdapter; @@ -12,7 +10,6 @@ use Ramsey\Uuid\Doctrine\UuidBinaryOrderedTimeType; use Ramsey\Uuid\Doctrine\UuidBinaryType; use Ramsey\Uuid\Doctrine\UuidType; -use Roave\PsrContainerDoctrine\EntityManagerFactory; return [ 'doctrine' => [ diff --git a/src/App/src/ConfigProvider.php b/src/App/src/ConfigProvider.php index 11c9e6cc..532008dd 100644 --- a/src/App/src/ConfigProvider.php +++ b/src/App/src/ConfigProvider.php @@ -40,11 +40,11 @@ public function getDependencies(): array ], 'factories' => [ 'doctrine.entity_manager.orm_default' => EntityManagerFactory::class, - EntityListenerResolver::class => EntityListenerResolverFactory::class, - DashboardController::class => AttributedServiceFactory::class, - PageController::class => AttributedServiceFactory::class, - PluginManager::class => PluginManagerFactory::class, - FormsPlugin::class => FormsPluginFactory::class, + EntityListenerResolver::class => EntityListenerResolverFactory::class, + DashboardController::class => AttributedServiceFactory::class, + PageController::class => AttributedServiceFactory::class, + PluginManager::class => PluginManagerFactory::class, + FormsPlugin::class => FormsPluginFactory::class, ], 'aliases' => [ EntityManager::class => 'doctrine.entity_manager.orm_default', diff --git a/test/Common/TestCase.php b/test/Common/TestCase.php index f060d95b..33f3814c 100644 --- a/test/Common/TestCase.php +++ b/test/Common/TestCase.php @@ -9,7 +9,6 @@ use Psr\Container\ContainerExceptionInterface; use Psr\Container\ContainerInterface; use Psr\Container\NotFoundExceptionInterface; - use RuntimeException; use function realpath; @@ -23,7 +22,6 @@ protected function setUp(): void { TestMode::enable(); $this->ensureTestMode(); - } private function ensureTestMode(): void diff --git a/test/Unit/Admin/Adapter/AuthenticationAdapterTest.php b/test/Unit/Admin/Adapter/AuthenticationAdapterTest.php index acfc51d7..48b1afd4 100644 --- a/test/Unit/Admin/Adapter/AuthenticationAdapterTest.php +++ b/test/Unit/Admin/Adapter/AuthenticationAdapterTest.php @@ -5,7 +5,6 @@ namespace FrontendTest\Unit\Admin\Adapter; use Doctrine\ORM\EntityManager; -use Doctrine\ORM\Persisters\Exception\UnrecognizedField; use Frontend\Admin\Adapter\AuthenticationAdapter; use Frontend\Admin\Entity\Admin; use Frontend\Admin\Repository\AdminRepository; From b26e992fdac9ff4a6f5dab55c713fcc8047a17bd Mon Sep 17 00:00:00 2001 From: arhimede Date: Wed, 26 Jun 2024 21:35:32 +0300 Subject: [PATCH 07/15] Update qodana_code_quality.yml to include composer install Signed-off-by: arhimede Signed-off-by: Claudiu Pintiuta --- .github/workflows/qodana_code_quality.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/.github/workflows/qodana_code_quality.yml b/.github/workflows/qodana_code_quality.yml index 2e492b72..633fbbe7 100644 --- a/.github/workflows/qodana_code_quality.yml +++ b/.github/workflows/qodana_code_quality.yml @@ -19,6 +19,26 @@ jobs: with: ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit fetch-depth: 0 # a full history is required for pull request analysis + - name: Install PHP + uses: shivammathur/setup-php@v2 + with: + php-version: "${{ matrix.php }}" + coverage: pcov + ini-values: assert.exception=1, zend.assertions=1, error_reporting=-1, log_errors_max_len=0, display_errors=On + tools: composer:v2, cs2pr + + - name: Determine composer cache directory + run: echo "COMPOSER_CACHE_DIR=$(composer config cache-dir)" >> $GITHUB_ENV + + - name: Cache dependencies installed with composer + uses: actions/cache@v4 + with: + path: ${{ env.COMPOSER_CACHE_DIR }} + key: php${{ matrix.php }}-composer-${{ hashFiles('**/composer.json') }} + restore-keys: | + php${{ matrix.php }}-composer- + - name: Install dependencies with composer + run: composer install --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi - name: 'Qodana Scan' uses: JetBrains/qodana-action@v2024.1 env: From 9b1bb14cad93d6e376ca6f6520d24d1579876616 Mon Sep 17 00:00:00 2001 From: arhimede Date: Wed, 26 Jun 2024 21:50:13 +0300 Subject: [PATCH 08/15] Update README.md Signed-off-by: arhimede --- README.md | 197 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 111 insertions(+), 86 deletions(-) diff --git a/README.md b/README.md index 2049dfa4..095c3f8a 100644 --- a/README.md +++ b/README.md @@ -10,18 +10,30 @@ DotKernel web starter package suitable for admin applications. [![GitHub stars](https://img.shields.io/github/stars/dotkernel/admin)](https://github.com/dotkernel/admin/stargazers) [![GitHub license](https://img.shields.io/github/license/dotkernel/admin)](https://github.com/dotkernel/admin/blob/3.0/LICENSE.md) -[![Build Static](https://github.com/dotkernel/admin/actions/workflows/continuous-integration.yml/badge.svg?branch=5.0)](https://github.com/dotkernel/admin/actions/workflows/continuous-integration.yml) +[![Build Static](https://github.com/dotkernel/admin/actions/workflows/static-analysis.yml/badge.svg?branch=4.0)](https://github.com/dotkernel/admin/actions/workflows/static-analysis.yml) +[![Build Static](https://github.com/dotkernel/admin/actions/workflows/run-tests.yml/badge.svg?branch=4.0)](https://github.com/dotkernel/admin/actions/workflows/run-tests.yml) [![codecov](https://codecov.io/gh/dotkernel/admin/graph/badge.svg?token=BQS43UWAM4)](https://codecov.io/gh/dotkernel/admin) -[![Qodana](https://github.com/dotkernel/admin/actions/workflows/qodana_code_quality.yml/badge.svg?branch=5.0)](https://github.com/dotkernel/admin/actions/workflows/qodana_code_quality.yml) +[![Qodana](https://github.com/dotkernel/admin/actions/workflows/qodana_code_quality.yml/badge.svg)](https://github.com/dotkernel/admin/actions/workflows/qodana_code_quality.yml) [![SymfonyInsight](https://insight.symfony.com/projects/6a7ecfc1-a0ed-4901-96ac-d0ff61f7b55f/big.svg)](https://insight.symfony.com/projects/6a7ecfc1-a0ed-4901-96ac-d0ff61f7b55f) -## Installing DotKernel `admin` + +# Installing DotKernel `admin` + +- [Installing DotKernel `admin`](#installing-dotkernel-admin) + - [Installation](#installation) + - [Composer](#composer) + - [Choose a destination path for DotKernel `admin` installation](#choose-a-destination-path-for-dotkernel-admin-installation) + - [Installing the `admin` Composer package](#installing-the-admin-composer-package) + - [Installing DotKernel admin](#installing-dotkernel-admin) + - [Configuration - First Run](#configuration---first-run) + - [Manage GeoLite2 database](#manage-geolite2-database) + - [Testing (Running)](#testing-running) ## Tools -DotKernel can be installed through a single command that utilizes [Composer](https://getcomposer.org/). Because of that, -Composer is required to install DotKernel `admin`. +DotKernel can be installed through a single command that utilizes [Composer](https://getcomposer.org/). Because of that, Composer is required to install DotKernel `admin`. + ### Composer @@ -30,29 +42,32 @@ Installation instructions: - [Composer Installation - Linux/Unix/OSX](https://getcomposer.org/doc/00-intro.md#installation-linux-unix-osx) - [Composer Installation - Windows](https://getcomposer.org/doc/00-intro.md#installation-windows) ->If you have never used composer before make sure you read ->the [`Composer Basic Usage`](https://getcomposer.org/doc/01-basic-usage.md) section in Composer's documentation +> If you have never used composer before make sure you read the [`Composer Basic Usage`](https://getcomposer.org/doc/01-basic-usage.md) section in Composer's documentation + -## Choosing an installation path for DotKernel `admin` +## Choosing an installation path for DotKernel `admin` Example: - absolute path `/var/www/dk-admin` - or relative path `dk-admin` (equivalent with `./dk-admin`) + ## Installing DotKernel `admin` -After choosing the path for DotKernel (`dk-admin` will be used for the remainder of this example) it must be installed. -There are two installation methods. +After choosing the path for DotKernel (`dk-admin` will be used for the remainder of this example) it must be installed. There are two installation methods. + -### I. Installing DotKernel `admin` using composer +#### I. Installing DotKernel `admin` using composer ->please use the below CLI commands in terminal, do NOT use the PhpStorm buttons +#### NOTE +> please use the below CLI commands in terminal, do NOT use the PhpStorm buttons The advantage of using this command is that it runs through the whole installation process. Run the following command: composer create-project dotkernel/admin -s dev dk + The above command downloads the `admin` package, then downloads and installs the `dependencies`. The setup script prompts for some configuration settings, for example the lines below: @@ -62,8 +77,8 @@ The setup script prompts for some configuration settings, for example the lines [1] config/config.php Make your selection (default is 1): -Simply select `[0] Do not inject`, because DotKernel includes its own configProvider which already contains the prompted -configurations. + +Simply select `[0] Do not inject`, because DotKernel includes its own configProvider which already contains the prompted configurations. If you choose `[1] config/config.php` Laminas's `ConfigProvider` from `session` will be injected. @@ -73,20 +88,21 @@ The next question is: Type `y` here, and hit `enter` -### II. Installing DotKernel `admin` using git clone -This method requires more manual input, but it ensures that the default branch is installed, even if it is not released. -Run the following command: +#### II. Installing DotKernel `admin` using git clone + +This method requires more manual input, but it ensures that the default branch is installed, even if it is not released. Run the following command: git clone https://github.com/dotkernel/admin.git . + The dependencies have to be installed separately, by running this command composer install -Just like for `II Installing DotKernel admin using composer` (see above), the setup asks for configuration settings -regarding injections (type `0` and hit `enter`) and a confirmation to use this setting for other packages (type `y` and -hit `enter`) + +Just like for `II Installing DotKernel admin using composer` (see above), the setup asks for configuration settings regarding injections (type `0` and hit `enter`) and a confirmation to use this setting for other packages (type `y` and hit `enter`) + ## Configuration - First Run @@ -94,23 +110,26 @@ hit `enter`) - Edit `config/autoload/local.php` according to your dev machine and fill in the `database` configuration Run the migrations and seeds with these commands: - - php bin/doctrine-migrations migrate - - php bin/doctrine fixtures:execute - -- If you use `composer create-project`, the project will go into development mode automatically after installing. The - development mode status can be checked and toggled by using these composer commands: - - composer development-status - - composer development-enable - - composer development-disable +```shell + php bin/doctrine-migrations migrate +``` +```shell + php bin/doctrine fixtures:execute +``` + +- If you use `composer create-project`, the project will go into development mode automatically after installing. The development mode status can be checked and toggled by using these composer commands: +```shell + composer development-status +``` +```shell + composer development-enable +``` +```shell + composer development-disable +``` - If not already done on installation, remove the `.dist` extension from `config/autoload/development.global.php.dist`. -This will enable dev mode by turning debug flag to `true` and turning configuration caching to `off`. It will also -make sure that any existing config cache is cleared. +This will enable dev mode by turning debug flag to `true` and turning configuration caching to `off`. It will also make sure that any existing config cache is cleared. > Charset recommendation: utf8mb4_general_ci @@ -120,27 +139,29 @@ You can download/update a specific GeoLite2 database, by running the following c php bin/cli.php geoip:synchronize -d {DATABASE} + Where _{DATABASE}_ takes one of the following values: `asn`, `city`, `country`. You can download/update all GeoLite2 databases at once, by running the following command: php bin/cli.php geoip:synchronize -The output should be similar to the below, displaying per -row: `database identifier`: `previous build datetime` -> `current build datetime`. + +The output should be similar to the below, displaying per row: `database identifier`: `previous build datetime` -> `current build datetime`. > asn: n/a -> 2021-07-01 02:09:34 -> +> > city: n/a -> 2021-07-01 02:09:20 -> +> > country: n/a -> 2021-07-01 02:05:12 Get help for this command by running: php bin/cli.php help geoip:synchronize -**Tip**: If you setup the synchronizer command as a cronjob, you can add the `-q|--quiet` option, and it will output -data only if an error has occurred. + +**Tip**: If you setup the synchronizer command as a cronjob, you can add the `-q|--quiet` option, and it will output data only if an error has occurred. + ## NPM Commands @@ -148,27 +169,26 @@ To install dependencies into the `node_modules` directory run this command. npm install -If `npm install` fails, this could be caused by user permissions of npm. Recommendation is to install npm -through `Node Version Manager`. + +If `npm install` fails, this could be caused by user permissions of npm. Recommendation is to install npm through `Node Version Manager`. The watch command compiles the components then watches the files and recompiles when one of them changes. npm run watch -After all updates are done, this command compiles the assets locally, minifies them and makes them ready for production. + +After all updates are done, this command compiles the assets locally, minifies them and makes them ready for production. npm run prod -## Authorization Guards -The packages responsible for restricting access to certain parts of the application -are [dot-rbac-guard](https://github.com/dotkernel/dot-rbac-guard) and [dot-rbac](https://github.com/dotkernel/dot-rbac). -These packages work together to create an infrastructure that is customizable and diversified to manage user access to -the platform by specifying the type of role the user has. +## Authorization Guards +The packages responsible for restricting access to certain parts of the application are [dot-rbac-guard](https://github.com/dotkernel/dot-rbac-guard) and [dot-rbac](https://github.com/dotkernel/dot-rbac). These packages work together to create an infrastructure that is customizable and diversified to manage user access to the platform by specifying the type of role the user has. -The `authorization.global.php` file provides multiple configurations specifying multiple roles as well as the types of -permissions to which these roles have access. +The `authorization.global.php` file provides multiple configurations specifying multiple roles as well as the types of permissions to which these roles have access. +```php +//example of a flat RBAC model that specifies two types of roles as well as their permission 'roles' => [ 'superuser' => [ 'permissions' => [ @@ -185,41 +205,44 @@ permissions to which these roles have access. ] ] ] +``` -The `authorization-guards.global.php` file provides configuration to restrict access to certain actions based on the -permissions defined in `authorization.global.php` so basically we have to add the permissions in the dot-rbac -configuration file first to specify the action restriction permissions. +The `authorization-guards.global.php` file provides configuration to restrict access to certain actions based on the permissions defined in `authorization.global.php` so basically we have to add the permissions in the dot-rbac configuration file first to specify the action restriction permissions. +```php +//example of configuration example to restrict certain actions of some routes based on the permissions specified in the dot-rbac configuration file 'rules' => [ - [ - 'route' => 'account', - 'actions' => [//list of actions to apply , or empty array for all actions - 'unregister', - 'avatar', - 'details', - 'changePassword' - ], - 'permissions' => ['authenticated'] - ], - [ - 'route' => 'admin', - 'actions' => [ - 'deleteAccount' - ], - 'permissions' => [ - 'delete' - //list of roles to allow - ] - ] + [ + 'route' => 'account', + 'actions' => [//list of actions to apply , or empty array for all actions + 'unregister', + 'avatar', + 'details', + 'changePassword' + ], + 'permissions' => ['authenticated'] + ], + [ + 'route' => 'admin', + 'actions' => [ + 'deleteAccount' + ], + 'permissions' => [ + 'delete' + //list of roles to allow + ] + ] ] +``` ## Testing (Running) Note: **Do not enable dev mode in production** - Run the following command in your project's directory to start PHPs built-in server: - - php -S 0.0.0.0:8080 -t public +```shell + php -S 0.0.0.0:8080 -t public +``` > Running command `composer serve` will do the exact same, but the above is faster. @@ -232,8 +255,8 @@ If you are still getting exceptions or errors regarding some missing services, t php bin/clear-config-cache.php -> If `config-cache.php` is present that config will be loaded regardless of the `ConfigAggregator::ENABLE_CACHE` -> in `config/autoload/mezzio.global.php` + +> If `config-cache.php` is present that config will be loaded regardless of the `ConfigAggregator::ENABLE_CACHE` in `config/autoload/mezzio.global.php` - Open a web browser and visit `http://localhost:8080/` @@ -245,14 +268,16 @@ If you ran the migrations you will have an admin user in the database with the f - **Password**: `dotadmin` **NOTE:** - - **Production only**: Make sure you modify the default admin credentials. - **Development only**: `session.cookie_secure` does not work locally so make sure you modify your `local.php`, as per the following: - - return [ - 'session_config' => [ - 'cookie_secure' => false, - ] - ]; - +```php +# other code + +return [ + # other configurations... + 'session_config' => [ + 'cookie_secure' => false, + ], +]; +``` Do not change this in `local.php.dist` as well because this value should remain `true` on production. From fb36a8cff70057bc5f3adc55a3c80ae31f8d644e Mon Sep 17 00:00:00 2001 From: Claudiu Pintiuta Date: Mon, 1 Jul 2024 15:36:43 +0300 Subject: [PATCH 09/15] laminas ci pre-run command Signed-off-by: Claudiu Pintiuta --- .laminas-ci/pre-run.sh | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .laminas-ci/pre-run.sh diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh new file mode 100644 index 00000000..f6351b84 --- /dev/null +++ b/.laminas-ci/pre-run.sh @@ -0,0 +1,15 @@ +JOB=$3 +PHP_VERSION=$4 +COMMAND=$(echo "${JOB}" | jq -r '.command') + +echo "Running $COMMAND" + +if [[ ${COMMAND} =~ phpunit ]];then + + apt-get install php"${PHP_VERSION}"-sqlite3 + + cp config/autoload/local.php.dist config/autoload/local.php + cp config/autoload/mail.local.php.dist config/autoload/mail.local.php + cp config/autoload/local.test.php.dist config/autoload/local.test.php + +fi From fb163aac875272f8635869577427a81df4d2ea07 Mon Sep 17 00:00:00 2001 From: Claudiu Pintiuta Date: Mon, 1 Jul 2024 16:02:35 +0300 Subject: [PATCH 10/15] laminas ci pre-run Signed-off-by: Claudiu Pintiuta --- .laminas-ci/pre-run.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh index f6351b84..1e32ee3d 100644 --- a/.laminas-ci/pre-run.sh +++ b/.laminas-ci/pre-run.sh @@ -6,6 +6,7 @@ echo "Running $COMMAND" if [[ ${COMMAND} =~ phpunit ]];then + apt-get update apt-get install php"${PHP_VERSION}"-sqlite3 cp config/autoload/local.php.dist config/autoload/local.php From 54c997461ed1e019c2dea3119b5129b72327d1b1 Mon Sep 17 00:00:00 2001 From: Claudiu Pintiuta Date: Mon, 1 Jul 2024 16:10:48 +0300 Subject: [PATCH 11/15] laminas ci pre-run Signed-off-by: Claudiu Pintiuta --- .laminas-ci/pre-run.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh index 1e32ee3d..f6351b84 100644 --- a/.laminas-ci/pre-run.sh +++ b/.laminas-ci/pre-run.sh @@ -6,7 +6,6 @@ echo "Running $COMMAND" if [[ ${COMMAND} =~ phpunit ]];then - apt-get update apt-get install php"${PHP_VERSION}"-sqlite3 cp config/autoload/local.php.dist config/autoload/local.php From 112a8ba420423aa0de7b5d6a038fad97d80bd21e Mon Sep 17 00:00:00 2001 From: Claudiu Pintiuta Date: Mon, 1 Jul 2024 16:15:47 +0300 Subject: [PATCH 12/15] laminas ci pre-run Signed-off-by: Claudiu Pintiuta --- .laminas-ci/pre-run.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh index f6351b84..346124a2 100644 --- a/.laminas-ci/pre-run.sh +++ b/.laminas-ci/pre-run.sh @@ -2,7 +2,7 @@ JOB=$3 PHP_VERSION=$4 COMMAND=$(echo "${JOB}" | jq -r '.command') -echo "Running $COMMAND" +echo "Running pre-run $COMMAND" if [[ ${COMMAND} =~ phpunit ]];then @@ -12,4 +12,6 @@ if [[ ${COMMAND} =~ phpunit ]];then cp config/autoload/mail.local.php.dist config/autoload/mail.local.php cp config/autoload/local.test.php.dist config/autoload/local.test.php + echo 'running if' + fi From 7410e3a91e55cad8fa59da3ee63364b72f4119ff Mon Sep 17 00:00:00 2001 From: Claudiu Pintiuta Date: Mon, 1 Jul 2024 16:26:19 +0300 Subject: [PATCH 13/15] laminas ci pre-run Signed-off-by: Claudiu Pintiuta --- .laminas-ci/pre-run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh index 346124a2..c24f8f1d 100644 --- a/.laminas-ci/pre-run.sh +++ b/.laminas-ci/pre-run.sh @@ -2,7 +2,7 @@ JOB=$3 PHP_VERSION=$4 COMMAND=$(echo "${JOB}" | jq -r '.command') -echo "Running pre-run $COMMAND" +echo "Running pre-run $COMMAND" if [[ ${COMMAND} =~ phpunit ]];then From 6fd52d385f724948e5630b9325c667dd991e014a Mon Sep 17 00:00:00 2001 From: alexmerlin Date: Tue, 2 Jul 2024 07:11:01 +0300 Subject: [PATCH 14/15] Made .laminas-ci/pre-run.sh executable Signed-off-by: alexmerlin --- .laminas-ci/pre-run.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 .laminas-ci/pre-run.sh diff --git a/.laminas-ci/pre-run.sh b/.laminas-ci/pre-run.sh old mode 100644 new mode 100755 From a9cd7bc52670564a8ebe9ab9600eaa4bf1d33662 Mon Sep 17 00:00:00 2001 From: Claudiu Pintiuta Date: Tue, 2 Jul 2024 13:05:10 +0300 Subject: [PATCH 15/15] updated readme and changes for quodana Signed-off-by: Claudiu Pintiuta --- README.md | 201 +++++++++------------ src/Setting/src/Service/SettingService.php | 2 +- 2 files changed, 89 insertions(+), 114 deletions(-) diff --git a/README.md b/README.md index 095c3f8a..bbff9e9c 100644 --- a/README.md +++ b/README.md @@ -3,37 +3,25 @@ DotKernel web starter package suitable for admin applications. ![OSS Lifecycle](https://img.shields.io/osslifecycle/dotkernel/admin) -![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/admin/4.3.1) +![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/admin/5.0.0) [![GitHub issues](https://img.shields.io/github/issues/dotkernel/admin)](https://github.com/dotkernel/admin/issues) [![GitHub forks](https://img.shields.io/github/forks/dotkernel/admin)](https://github.com/dotkernel/admin/network) [![GitHub stars](https://img.shields.io/github/stars/dotkernel/admin)](https://github.com/dotkernel/admin/stargazers) -[![GitHub license](https://img.shields.io/github/license/dotkernel/admin)](https://github.com/dotkernel/admin/blob/3.0/LICENSE.md) +[![GitHub license](https://img.shields.io/github/license/dotkernel/admin)](https://github.com/dotkernel/admin/blob/5.0/LICENSE.md) -[![Build Static](https://github.com/dotkernel/admin/actions/workflows/static-analysis.yml/badge.svg?branch=4.0)](https://github.com/dotkernel/admin/actions/workflows/static-analysis.yml) -[![Build Static](https://github.com/dotkernel/admin/actions/workflows/run-tests.yml/badge.svg?branch=4.0)](https://github.com/dotkernel/admin/actions/workflows/run-tests.yml) +[![Build Static](https://github.com/dotkernel/admin/actions/workflows/continuous-integration.yml/badge.svg?branch=5.0)](https://github.com/dotkernel/admin/actions/workflows/continuous-integration.yml) [![codecov](https://codecov.io/gh/dotkernel/admin/graph/badge.svg?token=BQS43UWAM4)](https://codecov.io/gh/dotkernel/admin) -[![Qodana](https://github.com/dotkernel/admin/actions/workflows/qodana_code_quality.yml/badge.svg)](https://github.com/dotkernel/admin/actions/workflows/qodana_code_quality.yml) +[![Qodana](https://github.com/dotkernel/admin/actions/workflows/qodana_code_quality.yml/badge.svg?branch=5.0)](https://github.com/dotkernel/admin/actions/workflows/qodana_code_quality.yml) [![SymfonyInsight](https://insight.symfony.com/projects/6a7ecfc1-a0ed-4901-96ac-d0ff61f7b55f/big.svg)](https://insight.symfony.com/projects/6a7ecfc1-a0ed-4901-96ac-d0ff61f7b55f) - -# Installing DotKernel `admin` - -- [Installing DotKernel `admin`](#installing-dotkernel-admin) - - [Installation](#installation) - - [Composer](#composer) - - [Choose a destination path for DotKernel `admin` installation](#choose-a-destination-path-for-dotkernel-admin-installation) - - [Installing the `admin` Composer package](#installing-the-admin-composer-package) - - [Installing DotKernel admin](#installing-dotkernel-admin) - - [Configuration - First Run](#configuration---first-run) - - [Manage GeoLite2 database](#manage-geolite2-database) - - [Testing (Running)](#testing-running) +## Installing DotKernel `admin` ## Tools -DotKernel can be installed through a single command that utilizes [Composer](https://getcomposer.org/). Because of that, Composer is required to install DotKernel `admin`. - +DotKernel can be installed through a single command that utilizes [Composer](https://getcomposer.org/). Because of that, +Composer is required to install DotKernel `admin`. ### Composer @@ -42,32 +30,29 @@ Installation instructions: - [Composer Installation - Linux/Unix/OSX](https://getcomposer.org/doc/00-intro.md#installation-linux-unix-osx) - [Composer Installation - Windows](https://getcomposer.org/doc/00-intro.md#installation-windows) -> If you have never used composer before make sure you read the [`Composer Basic Usage`](https://getcomposer.org/doc/01-basic-usage.md) section in Composer's documentation - +>If you have never used composer before make sure you read +>the [`Composer Basic Usage`](https://getcomposer.org/doc/01-basic-usage.md) section in Composer's documentation -## Choosing an installation path for DotKernel `admin` +## Choosing an installation path for DotKernel `admin` Example: - absolute path `/var/www/dk-admin` - or relative path `dk-admin` (equivalent with `./dk-admin`) - ## Installing DotKernel `admin` -After choosing the path for DotKernel (`dk-admin` will be used for the remainder of this example) it must be installed. There are two installation methods. - +After choosing the path for DotKernel (`dk-admin` will be used for the remainder of this example) it must be installed. +There are two installation methods. -#### I. Installing DotKernel `admin` using composer +### I. Installing DotKernel `admin` using composer -#### NOTE -> please use the below CLI commands in terminal, do NOT use the PhpStorm buttons +>please use the below CLI commands in terminal, do NOT use the PhpStorm buttons The advantage of using this command is that it runs through the whole installation process. Run the following command: composer create-project dotkernel/admin -s dev dk - The above command downloads the `admin` package, then downloads and installs the `dependencies`. The setup script prompts for some configuration settings, for example the lines below: @@ -77,8 +62,8 @@ The setup script prompts for some configuration settings, for example the lines [1] config/config.php Make your selection (default is 1): - -Simply select `[0] Do not inject`, because DotKernel includes its own configProvider which already contains the prompted configurations. +Simply select `[0] Do not inject`, because DotKernel includes its own configProvider which already contains the prompted +configurations. If you choose `[1] config/config.php` Laminas's `ConfigProvider` from `session` will be injected. @@ -88,21 +73,20 @@ The next question is: Type `y` here, and hit `enter` +### II. Installing DotKernel `admin` using git clone -#### II. Installing DotKernel `admin` using git clone - -This method requires more manual input, but it ensures that the default branch is installed, even if it is not released. Run the following command: +This method requires more manual input, but it ensures that the default branch is installed, even if it is not released. +Run the following command: git clone https://github.com/dotkernel/admin.git . - The dependencies have to be installed separately, by running this command composer install - -Just like for `II Installing DotKernel admin using composer` (see above), the setup asks for configuration settings regarding injections (type `0` and hit `enter`) and a confirmation to use this setting for other packages (type `y` and hit `enter`) - +Just like for `II Installing DotKernel admin using composer` (see above), the setup asks for configuration settings +regarding injections (type `0` and hit `enter`) and a confirmation to use this setting for other packages (type `y` and +hit `enter`) ## Configuration - First Run @@ -110,26 +94,23 @@ Just like for `II Installing DotKernel admin using composer` (see above), the se - Edit `config/autoload/local.php` according to your dev machine and fill in the `database` configuration Run the migrations and seeds with these commands: -```shell - php bin/doctrine-migrations migrate -``` -```shell - php bin/doctrine fixtures:execute -``` - -- If you use `composer create-project`, the project will go into development mode automatically after installing. The development mode status can be checked and toggled by using these composer commands: -```shell - composer development-status -``` -```shell - composer development-enable -``` -```shell - composer development-disable -``` + + php bin/doctrine-migrations migrate + + php bin/doctrine fixtures:execute + +- If you use `composer create-project`, the project will go into development mode automatically after installing. The + development mode status can be checked and toggled by using these composer commands: + + composer development-status + + composer development-enable + + composer development-disable - If not already done on installation, remove the `.dist` extension from `config/autoload/development.global.php.dist`. -This will enable dev mode by turning debug flag to `true` and turning configuration caching to `off`. It will also make sure that any existing config cache is cleared. + This will enable dev mode by turning debug flag to `true` and turning configuration caching to `off`. It will also + make sure that any existing config cache is cleared. > Charset recommendation: utf8mb4_general_ci @@ -139,29 +120,27 @@ You can download/update a specific GeoLite2 database, by running the following c php bin/cli.php geoip:synchronize -d {DATABASE} - Where _{DATABASE}_ takes one of the following values: `asn`, `city`, `country`. You can download/update all GeoLite2 databases at once, by running the following command: php bin/cli.php geoip:synchronize - -The output should be similar to the below, displaying per row: `database identifier`: `previous build datetime` -> `current build datetime`. +The output should be similar to the below, displaying per +row: `database identifier`: `previous build datetime` -> `current build datetime`. > asn: n/a -> 2021-07-01 02:09:34 -> +> > city: n/a -> 2021-07-01 02:09:20 -> +> > country: n/a -> 2021-07-01 02:05:12 Get help for this command by running: php bin/cli.php help geoip:synchronize - -**Tip**: If you setup the synchronizer command as a cronjob, you can add the `-q|--quiet` option, and it will output data only if an error has occurred. - +**Tip**: If you setup the synchronizer command as a cronjob, you can add the `-q|--quiet` option, and it will output +data only if an error has occurred. ## NPM Commands @@ -169,26 +148,27 @@ To install dependencies into the `node_modules` directory run this command. npm install - -If `npm install` fails, this could be caused by user permissions of npm. Recommendation is to install npm through `Node Version Manager`. +If `npm install` fails, this could be caused by user permissions of npm. Recommendation is to install npm +through `Node Version Manager`. The watch command compiles the components then watches the files and recompiles when one of them changes. npm run watch - -After all updates are done, this command compiles the assets locally, minifies them and makes them ready for production. +After all updates are done, this command compiles the assets locally, minifies them and makes them ready for production. npm run prod - ## Authorization Guards -The packages responsible for restricting access to certain parts of the application are [dot-rbac-guard](https://github.com/dotkernel/dot-rbac-guard) and [dot-rbac](https://github.com/dotkernel/dot-rbac). These packages work together to create an infrastructure that is customizable and diversified to manage user access to the platform by specifying the type of role the user has. -The `authorization.global.php` file provides multiple configurations specifying multiple roles as well as the types of permissions to which these roles have access. +The packages responsible for restricting access to certain parts of the application +are [dot-rbac-guard](https://github.com/dotkernel/dot-rbac-guard) and [dot-rbac](https://github.com/dotkernel/dot-rbac). +These packages work together to create an infrastructure that is customizable and diversified to manage user access to +the platform by specifying the type of role the user has. + +The `authorization.global.php` file provides multiple configurations specifying multiple roles as well as the types of +permissions to which these roles have access. -```php -//example of a flat RBAC model that specifies two types of roles as well as their permission 'roles' => [ 'superuser' => [ 'permissions' => [ @@ -205,44 +185,41 @@ The `authorization.global.php` file provides multiple configurations specifying ] ] ] -``` -The `authorization-guards.global.php` file provides configuration to restrict access to certain actions based on the permissions defined in `authorization.global.php` so basically we have to add the permissions in the dot-rbac configuration file first to specify the action restriction permissions. +The `authorization-guards.global.php` file provides configuration to restrict access to certain actions based on the +permissions defined in `authorization.global.php` so basically we have to add the permissions in the dot-rbac +configuration file first to specify the action restriction permissions. -```php -//example of configuration example to restrict certain actions of some routes based on the permissions specified in the dot-rbac configuration file 'rules' => [ - [ - 'route' => 'account', - 'actions' => [//list of actions to apply , or empty array for all actions - 'unregister', - 'avatar', - 'details', - 'changePassword' - ], - 'permissions' => ['authenticated'] - ], - [ - 'route' => 'admin', - 'actions' => [ - 'deleteAccount' - ], - 'permissions' => [ - 'delete' - //list of roles to allow - ] - ] + [ + 'route' => 'account', + 'actions' => [//list of actions to apply , or empty array for all actions + 'unregister', + 'avatar', + 'details', + 'changePassword' + ], + 'permissions' => ['authenticated'] + ], + [ + 'route' => 'admin', + 'actions' => [ + 'deleteAccount' + ], + 'permissions' => [ + 'delete' + //list of roles to allow + ] + ] ] -``` ## Testing (Running) Note: **Do not enable dev mode in production** - Run the following command in your project's directory to start PHPs built-in server: -```shell - php -S 0.0.0.0:8080 -t public -``` + + php -S 0.0.0.0:8080 -t public > Running command `composer serve` will do the exact same, but the above is faster. @@ -255,8 +232,8 @@ If you are still getting exceptions or errors regarding some missing services, t php bin/clear-config-cache.php - -> If `config-cache.php` is present that config will be loaded regardless of the `ConfigAggregator::ENABLE_CACHE` in `config/autoload/mezzio.global.php` +> If `config-cache.php` is present that config will be loaded regardless of the `ConfigAggregator::ENABLE_CACHE` +> in `config/autoload/mezzio.global.php` - Open a web browser and visit `http://localhost:8080/` @@ -268,16 +245,14 @@ If you ran the migrations you will have an admin user in the database with the f - **Password**: `dotadmin` **NOTE:** + - **Production only**: Make sure you modify the default admin credentials. - **Development only**: `session.cookie_secure` does not work locally so make sure you modify your `local.php`, as per the following: -```php -# other code - -return [ - # other configurations... - 'session_config' => [ - 'cookie_secure' => false, - ], -]; -``` + + return [ + 'session_config' => [ + 'cookie_secure' => false, + ] + ]; + Do not change this in `local.php.dist` as well because this value should remain `true` on production. diff --git a/src/Setting/src/Service/SettingService.php b/src/Setting/src/Service/SettingService.php index 46e2c809..a9df2bc8 100644 --- a/src/Setting/src/Service/SettingService.php +++ b/src/Setting/src/Service/SettingService.php @@ -9,7 +9,7 @@ use Frontend\Setting\Entity\Setting; use Frontend\Setting\Repository\SettingRepository; -class SettingService +readonly class SettingService { #[Inject( SettingRepository::class,