diff --git a/CHANGELOG.md b/CHANGELOG.md index f9f6481..0998feb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## v0.11.1 + +### Features + +- Support for Pimcore 11. + ## v0.11.0 ### Breaking Changes: diff --git a/README.md b/README.md index 72ec91c..042c393 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,8 @@ Pimcore also expects some configuration (e.g., for the [`security`](https://github.com/pimcore/skeleton/blob/10.2/config/packages/security.yaml)) to be present. You can use the `\Neusta\Pimcore\TestingFramework\Kernel\TestKernel` as a base, -which already provides all necessary configurations with default values (see: `dist/config`). +which already provides all necessary configurations with default values +(see: `dist/config` and `dist/pimcore10/config` or `dist/pimcore11/config`, depending on your Pimcore version). For a basic setup, you can use the `TestKernel` directly: ```php @@ -65,6 +66,13 @@ BootstrapPimcore::bootstrap( > echo '/var' > tests/app/.gitignore > ``` +> **Note**: +> Since the kernels of Pimcore 10 and 11 are not compatible (the signature of the method `configureContainer()` differs), +> we have extended our `TestKernel` with the ability to load separate configuration files depending on the version. +> Configuration that is compatible with both Pimcore versions belongs to the `config/` folder of the test app as before. +> Version specific configuration can be placed inside the `config/pimcore10/` +> or `config/pimcore11/` folder and will be loaded last. + ### Switch Common Behavior on/off in Test Cases We provide traits to switch common behavior on/off in whole test case classes. diff --git a/composer.json b/composer.json index cf1d16a..7099e1e 100644 --- a/composer.json +++ b/composer.json @@ -19,22 +19,25 @@ } ], "require": { - "php": "~8.1.0", - "doctrine/persistence": "^2.1.0", - "pimcore/pimcore": "^10.5", + "php": "~8.1.0 || ~8.2.0", + "doctrine/persistence": "^2.1 || ^3.0", + "pimcore/pimcore": "^10.5 || ^11.0", "psr/log": "^1.0 || ^2.0 || ^3.0", - "symfony/console": "^5.4", - "symfony/filesystem": "^5.4", - "symfony/framework-bundle": "^5.4" + "symfony/console": "^5.4 || ^6.2", + "symfony/filesystem": "^5.4 || ^6.2", + "symfony/framework-bundle": "^5.4 || ^6.2" }, "require-dev": { - "dama/doctrine-test-bundle": "^6.0", + "dama/doctrine-test-bundle": "^6.0 || ^7.0", "doctrine/orm": "^2.7", "ergebnis/composer-normalize": "^2.6.1", "friendsofphp/php-cs-fixer": "^3.0", "phpunit/phpunit": "^9.3", "vimeo/psalm": "^4.3" }, + "suggest": { + "pimcore/admin-ui-classic-bundle": "Required when used with Pimcore 11" + }, "autoload": { "psr-4": { "Neusta\\Pimcore\\TestingFramework\\": "src/" diff --git a/dist/config/doctrine.yaml b/dist/config/doctrine.yaml index 2357886..eb61acb 100644 --- a/dist/config/doctrine.yaml +++ b/dist/config/doctrine.yaml @@ -1,18 +1,18 @@ parameters: - env(MYSQL_HOST): 'database' - env(MYSQL_PORT): '3306' - env(MYSQL_USER): 'pimcore' - env(MYSQL_PASSWORD): 'pimcore' - env(MYSQL_DATABASE): 'pimcore' + env(MYSQL_HOST): 'database' + env(MYSQL_PORT): '3306' + env(MYSQL_USER): 'pimcore' + env(MYSQL_PASSWORD): 'pimcore' + env(MYSQL_DATABASE): 'pimcore' doctrine: - dbal: - server_version: '%env(MYSQL_SERVER_VERSION)%' - host: '%env(MYSQL_HOST)%' - port: '%env(int:MYSQL_PORT)%' - user: '%env(MYSQL_USER)%' - password: '%env(MYSQL_PASSWORD)%' - dbname: '%env(MYSQL_DATABASE)%' - mapping_types: - enum: string - bit: boolean + dbal: + server_version: '%env(MYSQL_SERVER_VERSION)%' + host: '%env(MYSQL_HOST)%' + port: '%env(int:MYSQL_PORT)%' + user: '%env(MYSQL_USER)%' + password: '%env(MYSQL_PASSWORD)%' + dbname: '%env(MYSQL_DATABASE)%' + mapping_types: + enum: string + bit: boolean diff --git a/dist/config/framework.yaml b/dist/config/framework.yaml new file mode 100644 index 0000000..0c9c03c --- /dev/null +++ b/dist/config/framework.yaml @@ -0,0 +1,3 @@ +framework: + session: + storage_factory_id: session.storage.factory.mock_file diff --git a/dist/config/secret.yaml b/dist/config/secret.yaml new file mode 100644 index 0000000..aac50ad --- /dev/null +++ b/dist/config/secret.yaml @@ -0,0 +1,2 @@ +parameters: + secret: ThisTokenIsNotSoSecretChangeIt diff --git a/dist/config/security.yaml b/dist/config/security.yaml deleted file mode 100644 index 9675d5a..0000000 --- a/dist/config/security.yaml +++ /dev/null @@ -1,54 +0,0 @@ -security: - providers: - pimcore_admin: - id: Pimcore\Bundle\AdminBundle\Security\User\UserProvider - - firewalls: - dev: - pattern: ^/(_(profiler|wdt)|css|images|js)/ - security: false - - # Pimcore WebDAV HTTP basic // DO NOT CHANGE! - pimcore_admin_webdav: - pattern: ^/admin/asset/webdav - provider: pimcore_admin - http_basic: ~ - - # Pimcore admin form login // DO NOT CHANGE! - pimcore_admin: - anonymous: ~ - pattern: ^/admin(/.*)?$ - # admin firewall is stateless as we open the admin - # session on demand for non-blocking parallel requests - stateless: true - provider: pimcore_admin - logout: - path: /admin/logout - target: /admin/login - success_handler: Pimcore\Bundle\AdminBundle\Security\LogoutSuccessHandler - guard: - entry_point: Pimcore\Bundle\AdminBundle\Security\Guard\AdminAuthenticator - authenticators: - - Pimcore\Bundle\AdminBundle\Security\Guard\AdminAuthenticator - two_factor: - auth_form_path: /admin/login/2fa # Path or route name of the two-factor form - check_path: /admin/login/2fa-verify # Path or route name of the two-factor code check - default_target_path: /admin # Where to redirect by default after successful authentication - always_use_default_target_path: false # If it should always redirect to default_target_path - auth_code_parameter_name: _auth_code # Name of the parameter for the two-factor authentication code - trusted_parameter_name: _trusted # Name of the parameter for the trusted device option - multi_factor: false # If ALL active two-factor methods need to be fulfilled (multi-factor authentication) - - - access_control: - # Pimcore admin ACl // DO NOT CHANGE! - - { path: ^/admin/settings/display-custom-logo, roles: IS_AUTHENTICATED_ANONYMOUSLY } - - { path: ^/admin/login/2fa-verify, roles: IS_AUTHENTICATED_2FA_IN_PROGRESS} - - { path: ^/admin/login/2fa, roles: IS_AUTHENTICATED_2FA_IN_PROGRESS} - - { path: ^/admin/login$, roles: IS_AUTHENTICATED_ANONYMOUSLY } - - { path: ^/admin/login/(login|lostpassword|deeplink|csrf-token)$, roles: IS_AUTHENTICATED_ANONYMOUSLY } - - { path: ^/admin, roles: ROLE_PIMCORE_USER } - - role_hierarchy: - # Pimcore admin // DO NOT CHANGE! - ROLE_PIMCORE_ADMIN: [ROLE_PIMCORE_USER] diff --git a/dist/pimcore10/config/security.yaml b/dist/pimcore10/config/security.yaml new file mode 100644 index 0000000..86ded92 --- /dev/null +++ b/dist/pimcore10/config/security.yaml @@ -0,0 +1,57 @@ +security: + enable_authenticator_manager: true + + providers: + pimcore_admin: + id: Pimcore\Bundle\AdminBundle\Security\User\UserProvider + + firewalls: + dev: + pattern: ^/(_(profiler|wdt)|css|images|js)/ + security: false + + # Pimcore WebDAV HTTP basic // DO NOT CHANGE! + pimcore_admin_webdav: + pattern: ^/admin/asset/webdav + provider: pimcore_admin + http_basic: ~ + + # Pimcore admin form login // DO NOT CHANGE! + pimcore_admin: + pattern: ^/admin(/.*)?$ + # admin firewall is stateless as we open the admin + # session on demand for non-blocking parallel requests + stateless: true + provider: pimcore_admin + login_throttling: + max_attempts: 3 + interval: '5 minutes' + + logout: + path: pimcore_admin_logout + target: pimcore_admin_login + custom_authenticators: + - Pimcore\Bundle\AdminBundle\Security\Authenticator\AdminLoginAuthenticator + - Pimcore\Bundle\AdminBundle\Security\Authenticator\AdminTokenAuthenticator + - Pimcore\Bundle\AdminBundle\Security\Authenticator\AdminSessionAuthenticator + two_factor: + auth_form_path: /admin/login/2fa # Path or route name of the two-factor form + check_path: /admin/login/2fa-verify # Path or route name of the two-factor code check + default_target_path: /admin # Where to redirect by default after successful authentication + always_use_default_target_path: false # If it should always redirect to default_target_path + auth_code_parameter_name: _auth_code # Name of the parameter for the two-factor authentication code + trusted_parameter_name: _trusted # Name of the parameter for the trusted device option + multi_factor: false # If ALL active two-factor methods need to be fulfilled (multi-factor authentication) + + access_control: + # Pimcore admin ACl // DO NOT CHANGE! + - { path: ^/admin/settings/display-custom-logo, roles: PUBLIC_ACCESS } + - { path: ^/admin/login/2fa-verify, roles: IS_AUTHENTICATED_2FA_IN_PROGRESS} + - { path: ^/admin/login/2fa, roles: IS_AUTHENTICATED_2FA_IN_PROGRESS} + - { path: ^/admin/login$, roles: PUBLIC_ACCESS } + - { path: ^/admin/login/(login|lostpassword|deeplink|csrf-token)$, roles: PUBLIC_ACCESS } + - { path: ^/admin, roles: ROLE_PIMCORE_USER } + + role_hierarchy: + # Pimcore admin // DO NOT CHANGE! + ROLE_PIMCORE_ADMIN: [ROLE_PIMCORE_USER] diff --git a/dist/pimcore11/config/security.yaml b/dist/pimcore11/config/security.yaml new file mode 100644 index 0000000..bd9360d --- /dev/null +++ b/dist/pimcore11/config/security.yaml @@ -0,0 +1,35 @@ +security: + enable_authenticator_manager: true + + providers: + pimcore_admin: + id: Pimcore\Security\User\UserProvider + + firewalls: + dev: + pattern: ^/(_(profiler|wdt)|css|images|js)/ + security: false + + # Pimcore WebDAV HTTP basic // DO NOT CHANGE! + pimcore_webdav: + pattern: ^/asset/webdav + provider: pimcore_admin + http_basic: ~ + + # Pimcore Admin Bundle firewall + pimcore_admin: '%pimcore_admin_bundle.firewall_settings%' + + access_control: + # Pimcore admin ACl // DO NOT CHANGE! + - { path: ^/admin/settings/display-custom-logo, roles: PUBLIC_ACCESS } + - { path: ^/admin/login/2fa-verify, roles: IS_AUTHENTICATED_2FA_IN_PROGRESS } + - { path: ^/admin/login/2fa-setup, roles: ROLE_PIMCORE_USER } + - { path: ^/admin/login/2fa, roles: IS_AUTHENTICATED_2FA_IN_PROGRESS } + - { path: ^/admin/login$, roles: PUBLIC_ACCESS } + - { path: ^/admin/login/(login|lostpassword|deeplink|csrf-token)$, roles: PUBLIC_ACCESS } + - { path: ^/admin, roles: ROLE_PIMCORE_USER } + - { path: ^/asset/webdav, roles: ROLE_PIMCORE_USER } + + role_hierarchy: + # Pimcore admin // DO NOT CHANGE! + ROLE_PIMCORE_ADMIN: [ROLE_PIMCORE_USER] diff --git a/src/Kernel/TestKernel.php b/src/Kernel/TestKernel.php index d3e3e84..0ef66ab 100644 --- a/src/Kernel/TestKernel.php +++ b/src/Kernel/TestKernel.php @@ -4,24 +4,57 @@ namespace Neusta\Pimcore\TestingFramework\Kernel; +use Pimcore\Bundle\AdminBundle\PimcoreAdminBundle; +use Pimcore\HttpKernel\BundleCollection\BundleCollection; use Pimcore\Kernel; +use Pimcore\Version; +use Symfony\Component\Config\Loader\LoaderInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; -class TestKernel extends Kernel -{ - protected function configureContainer(ContainerConfigurator $container): void +if (!method_exists(Version::class, 'getMajorVersion') || 10 === Version::getMajorVersion()) { + class TestKernel extends Kernel { - $container->extension('framework', [ - 'session' => [ - 'storage_factory_id' => 'session.storage.factory.mock_file', - ], - ]); + protected function configureContainer(ContainerConfigurator $container): void + { + $container->import(__DIR__.'/../../dist/config/*.yaml'); + $container->import(__DIR__.'/../../dist/pimcore10/config/*.yaml'); - $container->parameters()->set('secret', 'ThisTokenIsNotSoSecretChangeIt'); + parent::configureContainer($container); - $container->import(__DIR__.'/../../dist/config/doctrine.yaml'); - $container->import(__DIR__.'/../../dist/config/security.yaml'); + if (file_exists($pimcore10Config = $this->getProjectDir().'/config/pimcore10')) { + $container->import($pimcore10Config.'/*.{php,yaml}'); + } + } + } +} else { + class TestKernel extends Kernel + { + protected function configureContainer( + ContainerConfigurator $container, + LoaderInterface $loader, + ContainerBuilder $builder, + ): void { + + $container->import(__DIR__.'/../../dist/config/*.yaml'); + $container->import(__DIR__.'/../../dist/pimcore11/config/*.yaml'); + + parent::configureContainer($container, $loader, $builder); + + if (file_exists($pimcore11Config = $this->getProjectDir().'/config/pimcore11')) { + $container->import($pimcore11Config.'/*.{php,yaml}'); + } + } + + protected function registerCoreBundlesToCollection(BundleCollection $collection): void + { + if (!class_exists(PimcoreAdminBundle::class)) { + throw new \LogicException('Pimcore 11 requires the "pimcore/admin-ui-classic-bundle" dependency.'); + } + + parent::registerCoreBundlesToCollection($collection); - parent::configureContainer($container); + $collection->addBundle(new PimcoreAdminBundle(), 60); + } } }