From 5748c0cf2e76fdc1785a099b69080cd3d18ba631 Mon Sep 17 00:00:00 2001 From: Kamil Kokot Date: Tue, 27 Apr 2021 12:00:06 +0100 Subject: [PATCH] Add support for PHP 8 --- .github/workflows/build.yml | 29 ++-- behat.yml.dist | 2 +- composer.json | 13 +- easy-coding-standard.yml | 6 - ecs.php | 15 ++ phpstan.neon | 3 - psalm.xml | 3 +- .../Initiator/OnboardingInitiator.php | 5 +- .../Processor/BasicOnboardingProcessor.php | 3 - src/UrlUtils.php | 84 +++++++++ tests/Application/config/bundles.php | 2 - .../Application/config/packages/_sylius.yaml | 1 - .../config/sylius/1.10/bundles.php | 6 + .../config/sylius/1.10/packages/security.yaml | 148 ++++++++++++++++ .../Application/config/sylius/1.8/bundles.php | 2 + .../config/sylius/1.8/packages/_sylius.yaml | 2 + .../{ => sylius/1.8}/packages/security.yaml | 0 .../1.8}/routes/sylius_admin_api.yaml | 0 .../Application/config/sylius/1.9/bundles.php | 2 + .../config/sylius/1.9/packages/_sylius.yaml | 2 + .../config/sylius/1.9/packages/security.yaml | 159 ++++++++++++++++++ .../sylius/1.9/routes/sylius_admin_api.yaml | 3 + tests/Unit/UrlUtilsTest.php | 101 +++++++++++ 23 files changed, 555 insertions(+), 36 deletions(-) delete mode 100644 easy-coding-standard.yml create mode 100644 ecs.php create mode 100644 src/UrlUtils.php create mode 100644 tests/Application/config/sylius/1.10/bundles.php create mode 100644 tests/Application/config/sylius/1.10/packages/security.yaml create mode 100644 tests/Application/config/sylius/1.8/packages/_sylius.yaml rename tests/Application/config/{ => sylius/1.8}/packages/security.yaml (100%) rename tests/Application/config/{ => sylius/1.8}/routes/sylius_admin_api.yaml (100%) create mode 100644 tests/Application/config/sylius/1.9/packages/_sylius.yaml create mode 100644 tests/Application/config/sylius/1.9/packages/security.yaml create mode 100644 tests/Application/config/sylius/1.9/routes/sylius_admin_api.yaml create mode 100644 tests/Unit/UrlUtilsTest.php diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 318ccc8c..e8b72c43 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,24 +13,33 @@ jobs: tests: runs-on: ubuntu-latest - name: "PHP ${{ matrix.php }}, MySQL ${{ matrix.mysql }}, Sylius ${{ matrix.sylius }}" + name: "PHP ${{ matrix.php }}, Symfony ${{ matrix.symfony }}, Sylius ${{ matrix.sylius }}, MySQL ${{ matrix.mysql }}" strategy: fail-fast: false matrix: - php: [7.4, 7.3] - node: [10.x] - mysql: [5.7, 8.0] - symfony: [^4.4, ^5.2] - sylius: [~1.8.0, ~1.9.0] + php: ["8.0", "7.4", "7.3"] + node: ["10.x"] + mysql: ["5.7", "8.0"] + symfony: ["^4.4", "^5.2"] + sylius: ["~1.8.0", "~1.9.0", "~1.10@dev"] exclude: - - php: 7.3 - mysql: 8.0 + php: "7.3" + mysql: "8.0" - - sylius: ~1.8.0 - symfony: ^5.2 + sylius: "~1.8.0" + symfony: "^5.2" + - + php: "7.3" + sylius: "~1.10@dev" + - + php: "8.0" + sylius: "~1.8.0" + - + php: "8.0" + sylius: "~1.9.0" env: APP_ENV: test DATABASE_URL: "mysql://root:root@127.0.0.1/sylius?serverVersion=${{ matrix.mysql }}" diff --git a/behat.yml.dist b/behat.yml.dist index 5276e93d..c547e2e5 100644 --- a/behat.yml.dist +++ b/behat.yml.dist @@ -6,7 +6,7 @@ default: extensions: DMore\ChromeExtension\Behat\ServiceContainer\ChromeExtension: ~ - Lakion\Behat\MinkDebugExtension: + FriendsOfBehat\MinkDebugExtension: directory: etc/build clean_start: false screenshot: true diff --git a/composer.json b/composer.json index e3f8f471..37f9a5ef 100644 --- a/composer.json +++ b/composer.json @@ -5,10 +5,9 @@ "description": "PayPal plugin for Sylius.", "license": "MIT", "require": { - "php": "^7.3", + "php": "^7.3 || ^8.0", "sylius/sylius": "^1.8", - "nyholm/append-query-string": "^0.1.1", "phpseclib/phpseclib": "^2.0", "sylius-labs/doctrine-migrations-extra-bundle": "^0.1.3", "doctrine/doctrine-migrations-bundle": "^3.0" @@ -23,17 +22,17 @@ "friends-of-behat/mink-extension": "^2.4", "friends-of-behat/page-object-extension": "^0.3", "friends-of-behat/suite-settings-extension": "^1.0", + "friends-of-behat/mink-debug-extension": "^2.0", "friends-of-behat/symfony-extension": "^2.1", "friends-of-behat/variadic-extension": "^1.3", "friendsofsymfony/oauth-server-bundle": "^1.6 || >2.0.0-alpha.0 ^2.0@dev", - "lakion/mink-debug-extension": "^1.2.3", "phpspec/phpspec": "^6.1", - "phpstan/phpstan": "0.12.25", - "phpstan/phpstan-doctrine": "0.12.13", - "phpstan/phpstan-webmozart-assert": "0.12.4", + "phpstan/phpstan": "0.12.84", + "phpstan/phpstan-doctrine": "0.12.33", + "phpstan/phpstan-webmozart-assert": "0.12.12", "phpunit/phpunit": "^8.5", "sensiolabs/security-checker": "^6.0", - "sylius-labs/coding-standard": "^3.1", + "sylius-labs/coding-standard": "^4.0", "symfony/browser-kit": "^4.4 || ^5.2", "symfony/debug-bundle": "^4.4 || ^5.2", "symfony/dotenv": "^4.4 || ^5.2", diff --git a/easy-coding-standard.yml b/easy-coding-standard.yml deleted file mode 100644 index d1d90925..00000000 --- a/easy-coding-standard.yml +++ /dev/null @@ -1,6 +0,0 @@ -imports: - - { resource: 'vendor/sylius-labs/coding-standard/easy-coding-standard.yml' } - -parameters: - skip: - SlevomatCodingStandard\Sniffs\Commenting\InlineDocCommentDeclarationSniff.MissingVariable: ~ diff --git a/ecs.php b/ecs.php new file mode 100644 index 00000000..625ca542 --- /dev/null +++ b/ecs.php @@ -0,0 +1,15 @@ +import('vendor/sylius-labs/coding-standard/ecs.php'); + + $containerConfigurator->parameters()->set(Option::SKIP, [ + VisibilityRequiredFixer::class => ['*Spec.php'], + InlineDocCommentDeclarationSniff::class . '.MissingVariable', + ]); +}; diff --git a/phpstan.neon b/phpstan.neon index c4dd7445..46e93df9 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -14,6 +14,3 @@ parameters: # Test dependencies - 'tests/Application/app/**.php' - 'tests/Application/src/**.php' - - ignoreErrors: - - '/Parameter #1 $configuration of method Symfony\Component\DependencyInjection\Extension\Extension::processConfiguration() expects Symfony\Component\Config\Definition\ConfigurationInterface, Symfony\Component\Config\Definition\ConfigurationInterface|null given./' diff --git a/psalm.xml b/psalm.xml index 81e1a357..f38d221b 100644 --- a/psalm.xml +++ b/psalm.xml @@ -10,7 +10,8 @@ - + + diff --git a/src/Onboarding/Initiator/OnboardingInitiator.php b/src/Onboarding/Initiator/OnboardingInitiator.php index 51e37eac..f8bf261f 100644 --- a/src/Onboarding/Initiator/OnboardingInitiator.php +++ b/src/Onboarding/Initiator/OnboardingInitiator.php @@ -6,6 +6,7 @@ use Sylius\Component\Core\Model\AdminUserInterface; use Sylius\Component\Core\Model\PaymentMethodInterface; +use Sylius\PayPalPlugin\UrlUtils; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Security\Core\Security; @@ -36,7 +37,7 @@ public function initiate(PaymentMethodInterface $paymentMethod): string /** @var AdminUserInterface $user */ $user = $this->security->getUser(); - return append_query_string( + return UrlUtils::appendQueryString( $this->createPartnerReferralsUrl, http_build_query([ 'email' => $user->getEmail(), @@ -44,7 +45,7 @@ public function initiate(PaymentMethodInterface $paymentMethod): string 'factory' => 'sylius.pay_pal', ], UrlGeneratorInterface::ABSOLUTE_URL), ]), - APPEND_QUERY_STRING_REPLACE_DUPLICATE + UrlUtils::APPEND_QUERY_STRING_REPLACE_DUPLICATE ); } diff --git a/src/Onboarding/Processor/BasicOnboardingProcessor.php b/src/Onboarding/Processor/BasicOnboardingProcessor.php index 133f0f4b..a3046186 100644 --- a/src/Onboarding/Processor/BasicOnboardingProcessor.php +++ b/src/Onboarding/Processor/BasicOnboardingProcessor.php @@ -5,7 +5,6 @@ namespace Sylius\PayPalPlugin\Onboarding\Processor; use GuzzleHttp\ClientInterface; -use Sylius\Bundle\PayumBundle\Model\GatewayConfig; use Sylius\Component\Core\Model\PaymentMethodInterface; use Sylius\PayPalPlugin\Exception\PayPalPluginException; use Sylius\PayPalPlugin\Exception\PayPalWebhookAlreadyRegisteredException; @@ -44,8 +43,6 @@ public function process( } $gatewayConfig = $paymentMethod->getGatewayConfig(); - - /** @var GatewayConfig $gatewayConfig */ Assert::notNull($gatewayConfig); $onboardingId = (string) $request->query->get('onboarding_id'); diff --git a/src/UrlUtils.php b/src/UrlUtils.php new file mode 100644 index 00000000..dceb49fe --- /dev/null +++ b/src/UrlUtils.php @@ -0,0 +1,84 @@ + $paramName) { + $existing = str_replace($existingArray[0][$key], $queryStringArray[0][$keyMap[$paramName]], $existing); + $queryString = str_replace($queryStringArray[0][$keyMap[$paramName]], '', $queryString); + } + } elseif (self::APPEND_QUERY_STRING_SKIP_DUPLICATE === $mode) { + $intersect = array_intersect($queryStringArray[1], $existingArray[1]); + foreach ($intersect as $key => $paramName) { + $queryString = str_replace($queryStringArray[0][$key], '', $queryString); + } + } + $result .= trim((string) preg_replace('#&&+#i', '&', $existing . '&' . $queryString), '&'); + } + + // add fragment + return $result . $fragment; + } +} diff --git a/tests/Application/config/bundles.php b/tests/Application/config/bundles.php index 75357452..b958a8e0 100644 --- a/tests/Application/config/bundles.php +++ b/tests/Application/config/bundles.php @@ -45,8 +45,6 @@ Sylius\Bundle\ThemeBundle\SyliusThemeBundle::class => ['all' => true], Sylius\Bundle\AdminBundle\SyliusAdminBundle::class => ['all' => true], Sylius\Bundle\ShopBundle\SyliusShopBundle::class => ['all' => true], - FOS\OAuthServerBundle\FOSOAuthServerBundle::class => ['all' => true], - Sylius\Bundle\AdminApiBundle\SyliusAdminApiBundle::class => ['all' => true], Sylius\PayPalPlugin\SyliusPayPalPlugin::class => ['all' => true], Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true, 'test' => true, 'test_cached' => true], Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true, 'test_cached' => true], diff --git a/tests/Application/config/packages/_sylius.yaml b/tests/Application/config/packages/_sylius.yaml index 495f4694..c78547d1 100644 --- a/tests/Application/config/packages/_sylius.yaml +++ b/tests/Application/config/packages/_sylius.yaml @@ -2,7 +2,6 @@ imports: - { resource: "@SyliusCoreBundle/Resources/config/app/config.yml" } - { resource: "@SyliusAdminBundle/Resources/config/app/config.yml" } - - { resource: "@SyliusAdminApiBundle/Resources/config/app/config.yml" } - { resource: "@SyliusShopBundle/Resources/config/app/config.yml" } diff --git a/tests/Application/config/sylius/1.10/bundles.php b/tests/Application/config/sylius/1.10/bundles.php new file mode 100644 index 00000000..bd33f4ae --- /dev/null +++ b/tests/Application/config/sylius/1.10/bundles.php @@ -0,0 +1,6 @@ + ['all' => true], + SyliusLabs\Polyfill\Symfony\Security\Bundle\SyliusLabsPolyfillSymfonySecurityBundle::class => ['all' => true], +]; diff --git a/tests/Application/config/sylius/1.10/packages/security.yaml b/tests/Application/config/sylius/1.10/packages/security.yaml new file mode 100644 index 00000000..10628102 --- /dev/null +++ b/tests/Application/config/sylius/1.10/packages/security.yaml @@ -0,0 +1,148 @@ +parameters: + sylius.security.admin_regex: "^/%sylius_admin.path_name%" + sylius.security.api_regex: "^/api" + sylius.security.shop_regex: "^/(?!%sylius_admin.path_name%|new-api|api/.*|api$|media/.*)[^/]++" + sylius.security.new_api_route: "/new-api" + sylius.security.new_api_regex: "^%sylius.security.new_api_route%" + sylius.security.new_api_admin_route: "%sylius.security.new_api_route%/admin" + sylius.security.new_api_admin_regex: "^%sylius.security.new_api_admin_route%" + sylius.security.new_api_shop_route: "%sylius.security.new_api_route%/shop" + sylius.security.new_api_shop_regex: "^%sylius.security.new_api_shop_route%" + +security: + always_authenticate_before_granting: true + providers: + sylius_admin_user_provider: + id: sylius.admin_user_provider.email_or_name_based + sylius_api_admin_user_provider: + id: sylius.admin_user_provider.email_or_name_based + sylius_shop_user_provider: + id: sylius.shop_user_provider.email_or_name_based + sylius_api_shop_user_provider: + id: sylius.shop_user_provider.email_or_name_based + sylius_api_chain_provider: + chain: + providers: [sylius_api_shop_user_provider, sylius_api_admin_user_provider] + + encoders: + Sylius\Component\User\Model\UserInterface: argon2i + firewalls: + admin: + switch_user: true + context: admin + pattern: "%sylius.security.admin_regex%" + provider: sylius_admin_user_provider + form_login: + provider: sylius_admin_user_provider + login_path: sylius_admin_login + check_path: sylius_admin_login_check + failure_path: sylius_admin_login + default_target_path: sylius_admin_dashboard + use_forward: false + use_referer: true + csrf_token_generator: security.csrf.token_manager + csrf_parameter: _csrf_admin_security_token + csrf_token_id: admin_authenticate + remember_me: + secret: "%env(APP_SECRET)%" + path: "/%sylius_admin.path_name%" + name: APP_ADMIN_REMEMBER_ME + lifetime: 31536000 + remember_me_parameter: _remember_me + logout: + path: sylius_admin_logout + target: sylius_admin_login + anonymous: true + + new_api_admin_user: + pattern: "%sylius.security.new_api_route%/admin-user-authentication-token" + provider: sylius_admin_user_provider + stateless: true + anonymous: true + json_login: + check_path: "%sylius.security.new_api_route%/admin-user-authentication-token" + username_path: email + password_path: password + success_handler: lexik_jwt_authentication.handler.authentication_success + failure_handler: lexik_jwt_authentication.handler.authentication_failure + guard: + authenticators: + - lexik_jwt_authentication.jwt_token_authenticator + + new_api_shop_user: + pattern: "%sylius.security.new_api_route%/shop-user-authentication-token" + provider: sylius_shop_user_provider + stateless: true + anonymous: true + json_login: + check_path: "%sylius.security.new_api_route%/shop-user-authentication-token" + username_path: email + password_path: password + success_handler: lexik_jwt_authentication.handler.authentication_success + failure_handler: lexik_jwt_authentication.handler.authentication_failure + guard: + authenticators: + - lexik_jwt_authentication.jwt_token_authenticator + + new_api: + pattern: "%sylius.security.new_api_regex%/*" + provider: sylius_api_chain_provider + stateless: true + anonymous: lazy + guard: + authenticators: + - lexik_jwt_authentication.jwt_token_authenticator + + shop: + switch_user: { role: ROLE_ALLOWED_TO_SWITCH } + context: shop + pattern: "%sylius.security.shop_regex%" + provider: sylius_shop_user_provider + form_login: + success_handler: sylius.authentication.success_handler + failure_handler: sylius.authentication.failure_handler + provider: sylius_shop_user_provider + login_path: sylius_shop_login + check_path: sylius_shop_login_check + failure_path: sylius_shop_login + default_target_path: sylius_shop_homepage + use_forward: false + use_referer: true + csrf_token_generator: security.csrf.token_manager + csrf_parameter: _csrf_shop_security_token + csrf_token_id: shop_authenticate + remember_me: + secret: "%env(APP_SECRET)%" + name: APP_SHOP_REMEMBER_ME + lifetime: 31536000 + remember_me_parameter: _remember_me + logout: + path: sylius_shop_logout + target: sylius_shop_login + invalidate_session: false + success_handler: sylius.handler.shop_user_logout + anonymous: true + + dev: + pattern: ^/(_(profiler|wdt)|css|images|js)/ + security: false + + access_control: + - { path: "%sylius.security.admin_regex%/_partial", role: IS_AUTHENTICATED_ANONYMOUSLY, ips: [127.0.0.1, ::1] } + - { path: "%sylius.security.admin_regex%/_partial", role: ROLE_NO_ACCESS } + - { path: "%sylius.security.shop_regex%/_partial", role: IS_AUTHENTICATED_ANONYMOUSLY, ips: [127.0.0.1, ::1] } + - { path: "%sylius.security.shop_regex%/_partial", role: ROLE_NO_ACCESS } + + - { path: "%sylius.security.admin_regex%/login", role: IS_AUTHENTICATED_ANONYMOUSLY } + - { path: "%sylius.security.api_regex%/login", role: IS_AUTHENTICATED_ANONYMOUSLY } + - { path: "%sylius.security.shop_regex%/login", role: IS_AUTHENTICATED_ANONYMOUSLY } + + - { path: "%sylius.security.shop_regex%/register", role: IS_AUTHENTICATED_ANONYMOUSLY } + - { path: "%sylius.security.shop_regex%/verify", role: IS_AUTHENTICATED_ANONYMOUSLY } + + - { path: "%sylius.security.admin_regex%", role: ROLE_ADMINISTRATION_ACCESS } + - { path: "%sylius.security.api_regex%/.*", role: ROLE_API_ACCESS } + - { path: "%sylius.security.shop_regex%/account", role: ROLE_USER } + + - { path: "%sylius.security.new_api_admin_regex%/.*", role: ROLE_API_ACCESS } + - { path: "%sylius.security.new_api_shop_regex%/.*", role: IS_AUTHENTICATED_ANONYMOUSLY } diff --git a/tests/Application/config/sylius/1.8/bundles.php b/tests/Application/config/sylius/1.8/bundles.php index 74ee2bc0..1787cda9 100644 --- a/tests/Application/config/sylius/1.8/bundles.php +++ b/tests/Application/config/sylius/1.8/bundles.php @@ -1,6 +1,8 @@ ['all' => true], + Sylius\Bundle\AdminApiBundle\SyliusAdminApiBundle::class => ['all' => true], Doctrine\Bundle\DoctrineCacheBundle\DoctrineCacheBundle::class => ['all' => true], WhiteOctober\PagerfantaBundle\WhiteOctoberPagerfantaBundle::class => ['all' => true], ]; diff --git a/tests/Application/config/sylius/1.8/packages/_sylius.yaml b/tests/Application/config/sylius/1.8/packages/_sylius.yaml new file mode 100644 index 00000000..1674a972 --- /dev/null +++ b/tests/Application/config/sylius/1.8/packages/_sylius.yaml @@ -0,0 +1,2 @@ +imports: + - { resource: "@SyliusAdminApiBundle/Resources/config/app/config.yml" } diff --git a/tests/Application/config/packages/security.yaml b/tests/Application/config/sylius/1.8/packages/security.yaml similarity index 100% rename from tests/Application/config/packages/security.yaml rename to tests/Application/config/sylius/1.8/packages/security.yaml diff --git a/tests/Application/config/routes/sylius_admin_api.yaml b/tests/Application/config/sylius/1.8/routes/sylius_admin_api.yaml similarity index 100% rename from tests/Application/config/routes/sylius_admin_api.yaml rename to tests/Application/config/sylius/1.8/routes/sylius_admin_api.yaml diff --git a/tests/Application/config/sylius/1.9/bundles.php b/tests/Application/config/sylius/1.9/bundles.php index bd33f4ae..03dbd31e 100644 --- a/tests/Application/config/sylius/1.9/bundles.php +++ b/tests/Application/config/sylius/1.9/bundles.php @@ -1,6 +1,8 @@ ['all' => true], + Sylius\Bundle\AdminApiBundle\SyliusAdminApiBundle::class => ['all' => true], BabDev\PagerfantaBundle\BabDevPagerfantaBundle::class => ['all' => true], SyliusLabs\Polyfill\Symfony\Security\Bundle\SyliusLabsPolyfillSymfonySecurityBundle::class => ['all' => true], ]; diff --git a/tests/Application/config/sylius/1.9/packages/_sylius.yaml b/tests/Application/config/sylius/1.9/packages/_sylius.yaml new file mode 100644 index 00000000..1674a972 --- /dev/null +++ b/tests/Application/config/sylius/1.9/packages/_sylius.yaml @@ -0,0 +1,2 @@ +imports: + - { resource: "@SyliusAdminApiBundle/Resources/config/app/config.yml" } diff --git a/tests/Application/config/sylius/1.9/packages/security.yaml b/tests/Application/config/sylius/1.9/packages/security.yaml new file mode 100644 index 00000000..8161bdab --- /dev/null +++ b/tests/Application/config/sylius/1.9/packages/security.yaml @@ -0,0 +1,159 @@ +parameters: + sylius.security.admin_regex: "^/%sylius_admin.path_name%" + sylius.security.api_regex: "^/api" + sylius.security.shop_regex: "^/(?!%sylius_admin.path_name%|new-api|api/.*|api$|media/.*)[^/]++" + sylius.security.new_api_route: "/new-api" + sylius.security.new_api_regex: "^%sylius.security.new_api_route%" + sylius.security.new_api_admin_route: "%sylius.security.new_api_route%/admin" + sylius.security.new_api_admin_regex: "^%sylius.security.new_api_admin_route%" + sylius.security.new_api_shop_route: "%sylius.security.new_api_route%/shop" + sylius.security.new_api_shop_regex: "^%sylius.security.new_api_shop_route%" + +security: + always_authenticate_before_granting: true + providers: + sylius_admin_user_provider: + id: sylius.admin_user_provider.email_or_name_based + sylius_api_admin_user_provider: + id: sylius.admin_user_provider.email_or_name_based + sylius_shop_user_provider: + id: sylius.shop_user_provider.email_or_name_based + sylius_api_shop_user_provider: + id: sylius.shop_user_provider.email_or_name_based + sylius_api_chain_provider: + chain: + providers: [sylius_api_shop_user_provider, sylius_api_admin_user_provider] + + encoders: + Sylius\Component\User\Model\UserInterface: argon2i + firewalls: + admin: + switch_user: true + context: admin + pattern: "%sylius.security.admin_regex%" + provider: sylius_admin_user_provider + form_login: + provider: sylius_admin_user_provider + login_path: sylius_admin_login + check_path: sylius_admin_login_check + failure_path: sylius_admin_login + default_target_path: sylius_admin_dashboard + use_forward: false + use_referer: true + csrf_token_generator: security.csrf.token_manager + csrf_parameter: _csrf_admin_security_token + csrf_token_id: admin_authenticate + remember_me: + secret: "%env(APP_SECRET)%" + path: "/%sylius_admin.path_name%" + name: APP_ADMIN_REMEMBER_ME + lifetime: 31536000 + remember_me_parameter: _remember_me + logout: + path: sylius_admin_logout + target: sylius_admin_login + anonymous: true + + oauth_token: + pattern: "%sylius.security.api_regex%/oauth/v2/token" + security: false + + new_api_admin_user: + pattern: "%sylius.security.new_api_route%/admin-user-authentication-token" + provider: sylius_admin_user_provider + stateless: true + anonymous: true + json_login: + check_path: "%sylius.security.new_api_route%/admin-user-authentication-token" + username_path: email + password_path: password + success_handler: lexik_jwt_authentication.handler.authentication_success + failure_handler: lexik_jwt_authentication.handler.authentication_failure + guard: + authenticators: + - lexik_jwt_authentication.jwt_token_authenticator + + new_api_shop_user: + pattern: "%sylius.security.new_api_route%/shop-user-authentication-token" + provider: sylius_shop_user_provider + stateless: true + anonymous: true + json_login: + check_path: "%sylius.security.new_api_route%/shop-user-authentication-token" + username_path: email + password_path: password + success_handler: lexik_jwt_authentication.handler.authentication_success + failure_handler: lexik_jwt_authentication.handler.authentication_failure + guard: + authenticators: + - lexik_jwt_authentication.jwt_token_authenticator + + new_api: + pattern: "%sylius.security.new_api_regex%/*" + provider: sylius_api_chain_provider + stateless: true + anonymous: lazy + guard: + authenticators: + - lexik_jwt_authentication.jwt_token_authenticator + + api: + pattern: "%sylius.security.api_regex%/.*" + provider: sylius_admin_user_provider + fos_oauth: true + stateless: true + anonymous: true + + shop: + switch_user: { role: ROLE_ALLOWED_TO_SWITCH } + context: shop + pattern: "%sylius.security.shop_regex%" + provider: sylius_shop_user_provider + form_login: + success_handler: sylius.authentication.success_handler + failure_handler: sylius.authentication.failure_handler + provider: sylius_shop_user_provider + login_path: sylius_shop_login + check_path: sylius_shop_login_check + failure_path: sylius_shop_login + default_target_path: sylius_shop_homepage + use_forward: false + use_referer: true + csrf_token_generator: security.csrf.token_manager + csrf_parameter: _csrf_shop_security_token + csrf_token_id: shop_authenticate + remember_me: + secret: "%env(APP_SECRET)%" + name: APP_SHOP_REMEMBER_ME + lifetime: 31536000 + remember_me_parameter: _remember_me + logout: + path: sylius_shop_logout + target: sylius_shop_login + invalidate_session: false + success_handler: sylius.handler.shop_user_logout + anonymous: true + + dev: + pattern: ^/(_(profiler|wdt)|css|images|js)/ + security: false + + access_control: + - { path: "%sylius.security.admin_regex%/_partial", role: IS_AUTHENTICATED_ANONYMOUSLY, ips: [127.0.0.1, ::1] } + - { path: "%sylius.security.admin_regex%/_partial", role: ROLE_NO_ACCESS } + - { path: "%sylius.security.shop_regex%/_partial", role: IS_AUTHENTICATED_ANONYMOUSLY, ips: [127.0.0.1, ::1] } + - { path: "%sylius.security.shop_regex%/_partial", role: ROLE_NO_ACCESS } + + - { path: "%sylius.security.admin_regex%/login", role: IS_AUTHENTICATED_ANONYMOUSLY } + - { path: "%sylius.security.api_regex%/login", role: IS_AUTHENTICATED_ANONYMOUSLY } + - { path: "%sylius.security.shop_regex%/login", role: IS_AUTHENTICATED_ANONYMOUSLY } + + - { path: "%sylius.security.shop_regex%/register", role: IS_AUTHENTICATED_ANONYMOUSLY } + - { path: "%sylius.security.shop_regex%/verify", role: IS_AUTHENTICATED_ANONYMOUSLY } + + - { path: "%sylius.security.admin_regex%", role: ROLE_ADMINISTRATION_ACCESS } + - { path: "%sylius.security.api_regex%/.*", role: ROLE_API_ACCESS } + - { path: "%sylius.security.shop_regex%/account", role: ROLE_USER } + + - { path: "%sylius.security.new_api_admin_regex%/.*", role: ROLE_API_ACCESS } + - { path: "%sylius.security.new_api_shop_regex%/.*", role: IS_AUTHENTICATED_ANONYMOUSLY } diff --git a/tests/Application/config/sylius/1.9/routes/sylius_admin_api.yaml b/tests/Application/config/sylius/1.9/routes/sylius_admin_api.yaml new file mode 100644 index 00000000..80aed457 --- /dev/null +++ b/tests/Application/config/sylius/1.9/routes/sylius_admin_api.yaml @@ -0,0 +1,3 @@ +sylius_admin_api: + resource: "@SyliusAdminApiBundle/Resources/config/routing.yml" + prefix: /api diff --git a/tests/Unit/UrlUtilsTest.php b/tests/Unit/UrlUtilsTest.php new file mode 100644 index 00000000..aa8c00c1 --- /dev/null +++ b/tests/Unit/UrlUtilsTest.php @@ -0,0 +1,101 @@ +provideBaseUrls(); + + yield ['https://foo.com?a=b', 'foo=bar%20bar', 'https://foo.com?a=b&foo=bar%20bar']; + yield ['https://foo.com?a=b', 'foo=bar+bar', 'https://foo.com?a=b&foo=bar+bar']; + yield ['https://foo.com/page?aa=bb', 'foo=bar&biz=2', 'https://foo.com/page?aa=bb&foo=bar&biz=2']; + yield ['https://foo.com/page?aa=bb#link', 'foo=bar&biz=2', 'https://foo.com/page?aa=bb&foo=bar&biz=2#link']; + yield ['https://foo.com/page?aa=bb', 'foo=bar&aa=2', 'https://foo.com/page?aa=bb&foo=bar&aa=2']; + yield ['https://foo.com/page?aa=b+b', 'foo=bar&aa=2', 'https://foo.com/page?aa=b+b&foo=bar&aa=2']; + yield ['https://foo.com/page?aa=b%20b', 'foo=bar&aa=2', 'https://foo.com/page?aa=b%20b&foo=bar&aa=2']; + } + + public function provideModeReplace(): iterable + { + yield from $this->provideBaseUrls(); + + yield ['https://foo.com?a=b', 'foo=bar%20bar', 'https://foo.com?a=b&foo=bar%20bar']; + yield ['https://foo.com?a=b', 'foo=bar+bar', 'https://foo.com?a=b&foo=bar+bar']; + yield ['https://foo.com/page?aa=bb', 'foo=bar&biz=2', 'https://foo.com/page?aa=bb&foo=bar&biz=2']; + yield ['https://foo.com/page?aa=bb#link', 'foo=bar&biz=2', 'https://foo.com/page?aa=bb&foo=bar&biz=2#link']; + yield ['https://foo.com/page?aa=bb', 'foo=bar&aa=2', 'https://foo.com/page?aa=2&foo=bar']; + yield ['https://foo.com/page?aa=b+b', 'foo=bar&aa=2', 'https://foo.com/page?aa=2&foo=bar']; + yield ['https://foo.com/page?aa=b%20b', 'foo=bar&aa=2', 'https://foo.com/page?aa=2&foo=bar']; + yield ['https://foo.com/page?aa=b+b', 'foo=bar&aa=2+2', 'https://foo.com/page?aa=2+2&foo=bar']; + yield ['https://foo.com/page?aa=b%20b', 'foo=bar&aa=2%202', 'https://foo.com/page?aa=2%202&foo=bar']; + } + + public function provideModeSkip(): iterable + { + yield from $this->provideBaseUrls(); + + yield ['https://foo.com?a=b', 'foo=bar%20bar', 'https://foo.com?a=b&foo=bar%20bar']; + yield ['https://foo.com?a=b', 'foo=bar+bar', 'https://foo.com?a=b&foo=bar+bar']; + yield ['https://foo.com/page?aa=bb', 'foo=bar&biz=2', 'https://foo.com/page?aa=bb&foo=bar&biz=2']; + yield ['https://foo.com/page?aa=bb#link', 'foo=bar&biz=2', 'https://foo.com/page?aa=bb&foo=bar&biz=2#link']; + yield ['https://foo.com/page?aa=bb', 'foo=bar&aa=2', 'https://foo.com/page?aa=bb&foo=bar']; + yield ['https://foo.com/page?aa=b+b', 'foo=bar&aa=2', 'https://foo.com/page?aa=b+b&foo=bar']; + yield ['https://foo.com/page?aa=b%20b', 'foo=bar&aa=2', 'https://foo.com/page?aa=b%20b&foo=bar']; + yield ['https://foo.com/page?aa=b+b', 'foo=bar&cc=2+2', 'https://foo.com/page?aa=b+b&foo=bar&cc=2+2']; + yield ['https://foo.com/page?aa=b%20b', 'foo=bar&cc=2%202', 'https://foo.com/page?aa=b%20b&foo=bar&cc=2%202']; + } + + /** + * @dataProvider provideModeIgnore + */ + public function testModeIgnore(string $url, string $queryString, string $expected): void + { + $output = UrlUtils::appendQueryString($url, $queryString, UrlUtils::APPEND_QUERY_STRING_IGNORE_DUPLICATE); + $this->assertEquals($expected, $output); + } + + /** + * @dataProvider provideModeReplace + */ + public function testModeReplace(string $url, string $queryString, string $expected): void + { + $output = UrlUtils::appendQueryString($url, $queryString, UrlUtils::APPEND_QUERY_STRING_REPLACE_DUPLICATE); + $this->assertEquals($expected, $output); + } + + /** + * @dataProvider provideModeSkip + */ + public function testModeSkip(string $url, string $queryString, string $expected): void + { + $output = UrlUtils::appendQueryString($url, $queryString, UrlUtils::APPEND_QUERY_STRING_SKIP_DUPLICATE); + $this->assertEquals($expected, $output); + } +}