diff --git a/.github/workflows/split_packages.yml b/.github/workflows/split_packages.yml index 86f8f5b5a..25ddec9d0 100644 --- a/.github/workflows/split_packages.yml +++ b/.github/workflows/split_packages.yml @@ -4,6 +4,7 @@ on: push: branches: - master + - 3.x jobs: split_packages: @@ -45,11 +46,15 @@ jobs: - id: previous_tag uses: eonx-com/github-action-get-previous-tag@master + - id: branch_name + run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})" + - name: Split ${{ matrix.mapping.dir }} uses: eonx-com/github-action-monorepo-split@master env: GITHUB_TOKEN: ${{ secrets.REPO_GITHUB_TOKEN }} with: + branch: ${{ steps.branch_name.outputs.branch }} package-directory: 'packages/${{ matrix.mapping.dir }}' split-repository-organization: 'eonx-com' split-repository-name: '${{ matrix.mapping.repo }}' diff --git a/composer.json b/composer.json index a6d3c97ca..1c125b803 100644 --- a/composer.json +++ b/composer.json @@ -11,7 +11,6 @@ "php": "^7.2", "ext-json": "*", "doctrine/orm": "^2.6", - "eonx-com/externals": "^1.0 || ^2.0", "nesbot/carbon": "^2.22", "dragonmantank/cron-expression": "^2.3", "ramsey/uuid": "^3.9", diff --git a/packages/EasyApiToken/composer.json b/packages/EasyApiToken/composer.json index fe530dd56..88bd5609c 100644 --- a/packages/EasyApiToken/composer.json +++ b/packages/EasyApiToken/composer.json @@ -11,8 +11,8 @@ "phpunit/phpunit": "^8.4 || ^9.5", "ext-openssl": "^7.1", "firebase/php-jwt": "^5.0", - "eonx-com/easy-psr7-factory": "^2.6", - "eonx-com/easy-utils": "^2.6", + "eonx-com/easy-psr7-factory": "^3.0", + "eonx-com/easy-utils": "^3.0", "auth0/auth0-php": "^5.4", "psr/container": "^1.0", "laravel/lumen-framework": "^5.5", @@ -36,7 +36,7 @@ }, "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "3.0-dev" } } } diff --git a/packages/EasyApiToken/src/Bridge/Laravel/EasyApiTokenServiceProvider.php b/packages/EasyApiToken/src/Bridge/Laravel/EasyApiTokenServiceProvider.php index 47a81dc97..23d4b8b9e 100644 --- a/packages/EasyApiToken/src/Bridge/Laravel/EasyApiTokenServiceProvider.php +++ b/packages/EasyApiToken/src/Bridge/Laravel/EasyApiTokenServiceProvider.php @@ -7,9 +7,7 @@ use EonX\EasyApiToken\Bridge\BridgeConstantsInterface; use EonX\EasyApiToken\Factories\ApiTokenDecoderFactory; use EonX\EasyApiToken\Interfaces\ApiTokenDecoderInterface; -use EonX\EasyApiToken\Interfaces\ApiTokenDecoderProviderInterface; use EonX\EasyApiToken\Interfaces\Factories\ApiTokenDecoderFactoryInterface as DecoderFactoryInterface; -use EonX\EasyApiToken\Providers\FromConfigDecoderProvider; use Illuminate\Support\ServiceProvider; final class EasyApiTokenServiceProvider extends ServiceProvider @@ -25,24 +23,6 @@ public function register(): void { $this->mergeConfigFrom(__DIR__ . '/config/easy-api-token.php', 'easy-api-token'); - // TODO - Remove in 3.0. - if (empty(\config('easy-api-token.decoders', [])) === false) { - @\trigger_error(\sprintf( - 'Defining ApiTokenDecoders using a config file is deprecated since 2.4 and will be removed in 3.0. - Use %s instead.', - ApiTokenDecoderProviderInterface::class - ), \E_USER_NOTICE); - - $this->app->singleton(FromConfigDecoderProvider::class, function (): FromConfigDecoderProvider { - return new FromConfigDecoderProvider( - \config('easy-api-token.decoders', []), - \config('easy-api-token.factories'), - \config('easy-api-token.default_decoder') - ); - }); - $this->app->tag(FromConfigDecoderProvider::class, [BridgeConstantsInterface::TAG_DECODER_PROVIDER]); - } - $this->app->singleton(ApiTokenDecoderInterface::class, function (): ApiTokenDecoderInterface { return $this->app->make(DecoderFactoryInterface::class)->buildDefault(); }); diff --git a/packages/EasyApiToken/src/Bridge/Symfony/DependencyInjection/EasyApiTokenExtension.php b/packages/EasyApiToken/src/Bridge/Symfony/DependencyInjection/EasyApiTokenExtension.php index bf24e63ae..210075971 100644 --- a/packages/EasyApiToken/src/Bridge/Symfony/DependencyInjection/EasyApiTokenExtension.php +++ b/packages/EasyApiToken/src/Bridge/Symfony/DependencyInjection/EasyApiTokenExtension.php @@ -23,40 +23,8 @@ public function load(array $configs, ContainerBuilder $container): void $loader = new PhpFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')); $loader->load('services.php'); - $container->registerForAutoconfiguration(ApiTokenDecoderProviderInterface::class) + $container + ->registerForAutoconfiguration(ApiTokenDecoderProviderInterface::class) ->addTag(BridgeConstantsInterface::TAG_DECODER_PROVIDER); - - // Resolve config - $decoders = []; - $defaultFactories = null; - $defaultDecoder = null; - - foreach ($configs as $config) { - if (isset($config['decoders'])) { - $decoders = $config['decoders']; - } - - if (isset($config['default_decoder'])) { - $defaultDecoder = $config['default_decoder']; - } - - if (isset($config['default_factories'])) { - $defaultFactories = $config['default_factories']; - } - } - - if (empty($decoders) === false) { - @\trigger_error(\sprintf( - 'Defining ApiTokenDecoders using a config file is deprecated since 2.4 and will be removed in 3.0. - Use %s instead.', - ApiTokenDecoderProviderInterface::class - ), \E_USER_NOTICE); - - $container->setParameter(BridgeConstantsInterface::PARAM_DECODERS, $decoders); - $container->setParameter(BridgeConstantsInterface::PARAM_DEFAULT_FACTORIES, $defaultFactories); - $container->setParameter(BridgeConstantsInterface::PARAM_DEFAULT_DECODER, $defaultDecoder); - - $loader->load('from_config_provider.php'); - } } } diff --git a/packages/EasyApiToken/src/Bridge/Symfony/Resources/config/from_config_provider.php b/packages/EasyApiToken/src/Bridge/Symfony/Resources/config/from_config_provider.php deleted file mode 100644 index e27dc3dec..000000000 --- a/packages/EasyApiToken/src/Bridge/Symfony/Resources/config/from_config_provider.php +++ /dev/null @@ -1,21 +0,0 @@ -services(); - $services->defaults() - ->autowire() - ->autoconfigure(); - - $services - ->set(FromConfigDecoderProvider::class) - ->arg('$config', '%' . BridgeConstantsInterface::PARAM_DECODERS . '%') - ->arg('$defaultFactories', '%' . BridgeConstantsInterface::PARAM_DEFAULT_FACTORIES . '%') - ->arg('$defaultDecoder', '%' . BridgeConstantsInterface::PARAM_DEFAULT_DECODER . '%'); -}; diff --git a/packages/EasyApiToken/src/Bridge/Symfony/Resources/config/services.php b/packages/EasyApiToken/src/Bridge/Symfony/Resources/config/services.php index 07ea080cd..8897557c6 100644 --- a/packages/EasyApiToken/src/Bridge/Symfony/Resources/config/services.php +++ b/packages/EasyApiToken/src/Bridge/Symfony/Resources/config/services.php @@ -8,7 +8,6 @@ use EonX\EasyApiToken\Factories\ApiTokenDecoderFactory; use EonX\EasyApiToken\Interfaces\ApiTokenDecoderInterface; use EonX\EasyApiToken\Interfaces\Factories\ApiTokenDecoderFactoryInterface; -use EonX\EasyApiToken\Interfaces\Factories\EasyApiTokenDecoderFactoryInterface; return static function (ContainerConfigurator $container): void { $services = $container->services(); @@ -20,8 +19,6 @@ ->set(ApiTokenDecoderFactoryInterface::class, ApiTokenDecoderFactory::class) ->arg('$decoderProviders', tagged_iterator(BridgeConstantsInterface::TAG_DECODER_PROVIDER)); - $services->alias(EasyApiTokenDecoderFactoryInterface::class, ApiTokenDecoderFactoryInterface::class); - $services ->set(ApiTokenDecoderInterface::class) ->factory([ref(ApiTokenDecoderFactoryInterface::class), 'buildDefault']); diff --git a/packages/EasyApiToken/src/Bridge/Symfony/Resources/config/services.xml b/packages/EasyApiToken/src/Bridge/Symfony/Resources/config/services.xml deleted file mode 100644 index 4746aebc6..000000000 --- a/packages/EasyApiToken/src/Bridge/Symfony/Resources/config/services.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - diff --git a/packages/EasyApiToken/src/Decoders/AbstractApiTokenDecoder.php b/packages/EasyApiToken/src/Decoders/AbstractApiTokenDecoder.php index bce029009..d202942b6 100644 --- a/packages/EasyApiToken/src/Decoders/AbstractApiTokenDecoder.php +++ b/packages/EasyApiToken/src/Decoders/AbstractApiTokenDecoder.php @@ -23,24 +23,11 @@ public function __construct(?string $name = null) public function getName(): string { - return $this->name ?? self::class; + return $this->name ?? static::class; } - /** - * @param \Symfony\Component\HttpFoundation\Request|\Psr\Http\Message\ServerRequestInterface $request - */ - protected function getHeaderWithoutPrefix(string $header, string $prefix, $request): ?string + protected function getHeaderWithoutPrefix(string $header, string $prefix, Request $request): ?string { - if ($request instanceof ServerRequestInterface) { - @\trigger_error(\sprintf( - 'Passing $request as %s is deprecated since 2.4 and removed in 3.0. Use %s instead.', - ServerRequestInterface::class, - Request::class - ), \E_USER_DEPRECATED); - - return $this->getHeaderWithoutPrefixForServerRequest($header, $prefix, $request); - } - $header = $request->headers->get($header, ''); if (Strings::startsWith($header ?? '', $prefix) === false) { @@ -63,26 +50,4 @@ protected function getQueryParam(string $param, ServerRequestInterface $request) return $request->getQueryParams()[$param] ?? null; } - - private function getFirstHeaderValue(string $header, ServerRequestInterface $request): ?string - { - return $request->getHeader(\strtolower($header))[0] ?? null; - } - - private function getHeaderWithoutPrefixForServerRequest( - string $header, - string $prefix, - ServerRequestInterface $request - ): ?string { - if ($this->headerStartsWith($header, $prefix, $request) === false) { - return null; - } - - return \substr((string)$this->getFirstHeaderValue($header, $request), \strlen($prefix)); - } - - private function headerStartsWith(string $header, string $prefix, ServerRequestInterface $request): bool - { - return Strings::startsWith($this->getFirstHeaderValue($header, $request) ?? '', $prefix); - } } diff --git a/packages/EasyApiToken/src/Decoders/ApiKeyAsBasicAuthUsernameDecoder.php b/packages/EasyApiToken/src/Decoders/ApiKeyAsBasicAuthUsernameDecoder.php deleted file mode 100644 index 5db75d124..000000000 --- a/packages/EasyApiToken/src/Decoders/ApiKeyAsBasicAuthUsernameDecoder.php +++ /dev/null @@ -1,50 +0,0 @@ -getHeaderWithoutPrefix('Authorization', 'Basic', $request); - - if ($authorization === null) { - // If Authorization doesn't start with Basic, return null - return null; - } - - $authorization = \explode(':', (string)\base64_decode($authorization, true)); - - if (empty(\trim($authorization[0] ?? '')) === true || empty(\trim($authorization[1] ?? '')) === false) { - // If Authorization doesn't contain ONLY a username, return null - return null; - } - - return new ApiKey(\trim($authorization[0])); - } -} diff --git a/packages/EasyApiToken/src/Decoders/ApiKeyDecoder.php b/packages/EasyApiToken/src/Decoders/ApiKeyDecoder.php index d1cf19abe..2c464e30e 100644 --- a/packages/EasyApiToken/src/Decoders/ApiKeyDecoder.php +++ b/packages/EasyApiToken/src/Decoders/ApiKeyDecoder.php @@ -6,13 +6,11 @@ use EonX\EasyApiToken\Interfaces\ApiTokenInterface; use EonX\EasyApiToken\Tokens\ApiKey; +use Symfony\Component\HttpFoundation\Request; final class ApiKeyDecoder extends AbstractApiTokenDecoder { - /** - * @param \Symfony\Component\HttpFoundation\Request|\Psr\Http\Message\ServerRequestInterface $request - */ - public function decode($request): ?ApiTokenInterface + public function decode(Request $request): ?ApiTokenInterface { $authorization = $this->getHeaderWithoutPrefix('Authorization', 'Basic', $request); diff --git a/packages/EasyApiToken/src/Decoders/BasicAuthDecoder.php b/packages/EasyApiToken/src/Decoders/BasicAuthDecoder.php index d1c780a05..207316288 100644 --- a/packages/EasyApiToken/src/Decoders/BasicAuthDecoder.php +++ b/packages/EasyApiToken/src/Decoders/BasicAuthDecoder.php @@ -6,18 +6,11 @@ use EonX\EasyApiToken\Interfaces\ApiTokenInterface; use EonX\EasyApiToken\Tokens\BasicAuth; +use Symfony\Component\HttpFoundation\Request; final class BasicAuthDecoder extends AbstractApiTokenDecoder { - public function __construct(?string $name = null) - { - parent::__construct($name ?? self::NAME_BASIC); - } - - /** - * @param \Symfony\Component\HttpFoundation\Request|\Psr\Http\Message\ServerRequestInterface $request - */ - public function decode($request): ?ApiTokenInterface + public function decode(Request $request): ?ApiTokenInterface { $authorization = $this->getHeaderWithoutPrefix('Authorization', 'Basic', $request); diff --git a/packages/EasyApiToken/src/Decoders/BearerTokenDecoder.php b/packages/EasyApiToken/src/Decoders/BearerTokenDecoder.php index 3ea8d9571..83e1b894b 100644 --- a/packages/EasyApiToken/src/Decoders/BearerTokenDecoder.php +++ b/packages/EasyApiToken/src/Decoders/BearerTokenDecoder.php @@ -9,6 +9,7 @@ use EonX\EasyApiToken\Tokens\Jwt; use Psr\Log\LoggerInterface; use Psr\Log\NullLogger; +use Symfony\Component\HttpFoundation\Request; final class BearerTokenDecoder extends AbstractApiTokenDecoder { @@ -30,10 +31,7 @@ public function __construct(JwtDriverInterface $jwtDriver, ?string $name = null, parent::__construct($name); } - /** - * @param \Symfony\Component\HttpFoundation\Request|\Psr\Http\Message\ServerRequestInterface $request - */ - public function decode($request): ?ApiTokenInterface + public function decode(Request $request): ?ApiTokenInterface { $authorization = $this->getHeaderWithoutPrefix('Authorization', 'Bearer', $request); diff --git a/packages/EasyApiToken/src/Decoders/ChainDecoder.php b/packages/EasyApiToken/src/Decoders/ChainDecoder.php index ec20f54a7..e7b404973 100644 --- a/packages/EasyApiToken/src/Decoders/ChainDecoder.php +++ b/packages/EasyApiToken/src/Decoders/ChainDecoder.php @@ -7,6 +7,7 @@ use EonX\EasyApiToken\Interfaces\ApiTokenDecoderInterface; use EonX\EasyApiToken\Interfaces\ApiTokenInterface; use EonX\EasyUtils\CollectorHelper; +use Symfony\Component\HttpFoundation\Request; final class ChainDecoder extends AbstractApiTokenDecoder { @@ -25,10 +26,7 @@ public function __construct(array $decoders, ?string $name = null) parent::__construct($name ?? self::NAME_CHAIN); } - /** - * @param \Symfony\Component\HttpFoundation\Request|\Psr\Http\Message\ServerRequestInterface $request - */ - public function decode($request): ?ApiTokenInterface + public function decode(Request $request): ?ApiTokenInterface { foreach ($this->decoders as $decoder) { $token = $decoder->decode($request); @@ -41,5 +39,3 @@ public function decode($request): ?ApiTokenInterface return null; } } - -\class_alias(ChainDecoder::class, ChainReturnFirstTokenDecoder::class); diff --git a/packages/EasyApiToken/src/Decoders/JwtTokenDecoder.php b/packages/EasyApiToken/src/Decoders/JwtTokenDecoder.php deleted file mode 100644 index bbdd75c81..000000000 --- a/packages/EasyApiToken/src/Decoders/JwtTokenDecoder.php +++ /dev/null @@ -1,68 +0,0 @@ -jwtApiTokenFactory = $jwtApiTokenFactory; - $this->logger = $logger ?? new NullLogger(); - - parent::__construct($name ?? self::NAME_JWT_HEADER); - } - - /** - * @param \Symfony\Component\HttpFoundation\Request|\Psr\Http\Message\ServerRequestInterface $request - */ - public function decode($request): ?ApiTokenInterface - { - $authorization = $this->getHeaderWithoutPrefix('Authorization', 'Bearer', $request); - - if ($authorization === null) { - // If Authorization doesn't start with Basic, return null - return null; - } - - try { - return $this->jwtApiTokenFactory->createFromString($authorization); - } catch (InvalidEasyApiTokenFromRequestException $exception) { - $this->logger->info(\sprintf('Invalid JWT token from request: "%s"', $exception->getMessage())); - - return null; - } - } -} diff --git a/packages/EasyApiToken/src/Decoders/JwtTokenInQueryDecoder.php b/packages/EasyApiToken/src/Decoders/JwtTokenInQueryDecoder.php deleted file mode 100644 index 60c51a5f8..000000000 --- a/packages/EasyApiToken/src/Decoders/JwtTokenInQueryDecoder.php +++ /dev/null @@ -1,49 +0,0 @@ -jwtApiTokenFactory = $jwtApiTokenFactory; - $this->queryParam = $queryParam; - - parent::__construct($name ?? self::NAME_JWT_PARAM); - } - - /** - * @param \Symfony\Component\HttpFoundation\Request|\Psr\Http\Message\ServerRequestInterface $request - */ - public function decode($request): ?ApiTokenInterface - { - $jwtToken = $request instanceof ServerRequestInterface - ? $this->getQueryParam($this->queryParam, $request) - : $request->query->get($this->queryParam); - - if (empty($jwtToken)) { - return null; - } - - return $this->jwtApiTokenFactory->createFromString((string)$jwtToken); - } -} diff --git a/packages/EasyApiToken/src/Factories/ApiTokenDecoderFactory.php b/packages/EasyApiToken/src/Factories/ApiTokenDecoderFactory.php index 64f19be18..3abf7fbed 100644 --- a/packages/EasyApiToken/src/Factories/ApiTokenDecoderFactory.php +++ b/packages/EasyApiToken/src/Factories/ApiTokenDecoderFactory.php @@ -83,5 +83,3 @@ private function setDecoders(iterable $providers): void $this->decoders = $decoders; } } - -\class_alias(ApiTokenDecoderFactory::class, EasyApiTokenDecoderFactory::class); diff --git a/packages/EasyApiToken/src/Factories/Decoders/AbstractJwtTokenDecoderFactory.php b/packages/EasyApiToken/src/Factories/Decoders/AbstractJwtTokenDecoderFactory.php deleted file mode 100644 index c1af620b4..000000000 --- a/packages/EasyApiToken/src/Factories/Decoders/AbstractJwtTokenDecoderFactory.php +++ /dev/null @@ -1,116 +0,0 @@ -decoderName - )); - } - - if (empty($config['options'] ?? []) || \is_array($config['options']) === false) { - throw new InvalidConfigurationException(\sprintf( - '"options" is required and must be an array for decoder "%s".', - $this->decoderName - )); - } - - return $this->doBuild($this->createJwtDriver($config['driver'], $config['options']), $config, $name); - } - - /** - * @param mixed[] $config - */ - abstract protected function doBuild( - JwtDriverInterface $jwtDriver, - array $config, - ?string $name = null - ): ApiTokenDecoderInterface; - - /** - * @param mixed[] $options List of options to use to create Driver. - * - * @throws \EonX\EasyApiToken\Exceptions\InvalidConfigurationException - */ - protected function createJwtDriver(string $driver, array $options): JwtDriverInterface - { - switch ($driver) { - case 'auth0': - return $this->createAuth0Driver($options); - case 'firebase': - return $this->createFirebaseDriver($options); - } - - throw new InvalidConfigurationException(\sprintf( - '"driver" value "%s" is invalid. Valid drivers: ["%s"].', - $driver, - \implode('", "', static::$jwtDrivers) - )); - } - - /** - * @param mixed[] $options List of options to pass to Auth0JwtDriver. Keys match constructor parameters. - */ - private function createAuth0Driver(array $options): Auth0JwtDriver - { - $cache = empty($options['cache_path']) === false ? new FileSystemCacheHandler($options['cache_path']) : null; - - return new Auth0JwtDriver( - $options['valid_audiences'], - $options['authorized_iss'], - // Required only for HS256 - $options['private_key'] ?? null, - $options['audience_for_encode'] ?? null, - $options['allowed_algos'] ?? null, - $cache - ); - } - - /** - * @param mixed[] $options List of options to pass to FirebaseJwtDriver. Keys match constructor parameters. - */ - private function createFirebaseDriver(array $options): FirebaseJwtDriver - { - return new FirebaseJwtDriver( - $options['algo'], - $options['public_key'], - $options['private_key'], - $options['allowed_algos'] ?? null, - $options['leeway'] ?? null - ); - } -} diff --git a/packages/EasyApiToken/src/Factories/Decoders/ApiKeyAsBasicAuthUsernameDecoderFactory.php b/packages/EasyApiToken/src/Factories/Decoders/ApiKeyAsBasicAuthUsernameDecoderFactory.php deleted file mode 100644 index 7311caa9c..000000000 --- a/packages/EasyApiToken/src/Factories/Decoders/ApiKeyAsBasicAuthUsernameDecoderFactory.php +++ /dev/null @@ -1,23 +0,0 @@ -decoderName - )); - } - - $decoders = []; - foreach ($config['list'] as $decoder) { - $decoders[] = $this->factory->build($decoder); - } - - return new ChainDecoder($decoders, $name); - } -} diff --git a/packages/EasyApiToken/src/Factories/Decoders/JwtTokenDecoderFactory.php b/packages/EasyApiToken/src/Factories/Decoders/JwtTokenDecoderFactory.php deleted file mode 100644 index ff674507b..000000000 --- a/packages/EasyApiToken/src/Factories/Decoders/JwtTokenDecoderFactory.php +++ /dev/null @@ -1,27 +0,0 @@ -decoderName - )); - } - - return new JwtTokenInQueryDecoder(new JwtFactory($jwtDriver), $param, $name); - } -} diff --git a/packages/EasyApiToken/src/Interfaces/ApiTokenDecoderInterface.php b/packages/EasyApiToken/src/Interfaces/ApiTokenDecoderInterface.php index 2a7c11a8c..fae24e5d2 100644 --- a/packages/EasyApiToken/src/Interfaces/ApiTokenDecoderInterface.php +++ b/packages/EasyApiToken/src/Interfaces/ApiTokenDecoderInterface.php @@ -4,6 +4,8 @@ namespace EonX\EasyApiToken\Interfaces; +use Symfony\Component\HttpFoundation\Request; + interface ApiTokenDecoderInterface { public const NAME_BASIC = 'basic'; @@ -16,10 +18,7 @@ interface ApiTokenDecoderInterface public const NAME_USER_APIKEY = 'user-apikey'; - /** - * @param \Symfony\Component\HttpFoundation\Request|\Psr\Http\Message\ServerRequestInterface $request - */ - public function decode($request): ?ApiTokenInterface; + public function decode(Request $request): ?ApiTokenInterface; public function getName(): string; } diff --git a/packages/EasyApiToken/src/Interfaces/ApiTokenInterface.php b/packages/EasyApiToken/src/Interfaces/ApiTokenInterface.php index f4dc38e0d..b929bc868 100644 --- a/packages/EasyApiToken/src/Interfaces/ApiTokenInterface.php +++ b/packages/EasyApiToken/src/Interfaces/ApiTokenInterface.php @@ -13,5 +13,3 @@ public function getOriginalToken(): string; */ public function getPayload(): array; } - -\class_alias(ApiTokenInterface::class, EasyApiTokenInterface::class); diff --git a/packages/EasyApiToken/src/Interfaces/Factories/ApiTokenDecoderFactoryInterface.php b/packages/EasyApiToken/src/Interfaces/Factories/ApiTokenDecoderFactoryInterface.php index 51eb7cc94..970907394 100644 --- a/packages/EasyApiToken/src/Interfaces/Factories/ApiTokenDecoderFactoryInterface.php +++ b/packages/EasyApiToken/src/Interfaces/Factories/ApiTokenDecoderFactoryInterface.php @@ -12,5 +12,3 @@ public function build(?string $decoder = null): ApiTokenDecoderInterface; public function buildDefault(): ApiTokenDecoderInterface; } - -\class_alias(ApiTokenDecoderFactoryInterface::class, EasyApiTokenDecoderFactoryInterface::class); diff --git a/packages/EasyApiToken/src/Interfaces/Factories/ApiTokenDecoderSubFactoryInterface.php b/packages/EasyApiToken/src/Interfaces/Factories/ApiTokenDecoderSubFactoryInterface.php deleted file mode 100644 index 9a7b66c5b..000000000 --- a/packages/EasyApiToken/src/Interfaces/Factories/ApiTokenDecoderSubFactoryInterface.php +++ /dev/null @@ -1,22 +0,0 @@ -priority = $priority ?? 0; - } - - public function getPriority(): int - { - return $this->priority; - } -} diff --git a/packages/EasyApiToken/src/Providers/FromConfigDecoderProvider.php b/packages/EasyApiToken/src/Providers/FromConfigDecoderProvider.php deleted file mode 100644 index 8e1fec300..000000000 --- a/packages/EasyApiToken/src/Providers/FromConfigDecoderProvider.php +++ /dev/null @@ -1,180 +0,0 @@ -config = $config; - $this->defaultFactories = $defaultFactories ?? $this->getDefaultDecoderFactories(); - $this->defaultDecoder = $defaultDecoder; - - parent::__construct($priority); - } - - public function build(?string $decoder = null): ApiTokenDecoderInterface - { - if ($decoder === null) { - return $this->buildDefault(); - } - - if (isset($this->resolved[$decoder])) { - return $this->resolved[$decoder]; - } - - if (empty($this->config) || \array_key_exists($decoder, $this->config) === false) { - throw new InvalidConfigurationException(\sprintf('No decoder configured for key: "%s".', $decoder)); - } - - $config = $this->config[$decoder] ?? []; - $subFactory = $this->instantiateSubFactory($decoder, $config); - - if ($subFactory instanceof DecoderNameAwareInterface) { - $subFactory->setDecoderName($decoder); - } - if ($subFactory instanceof MasterDecoderFactoryAwareInterface) { - $subFactory->setMasterFactory($this); - } - - return $this->resolved[$decoder] = $subFactory->build($config, $decoder); - } - - public function buildDefault(): ApiTokenDecoderInterface - { - return $this->build($this->defaultDecoder); - } - - /** - * @return iterable<\EonX\EasyApiToken\Interfaces\ApiTokenDecoderInterface> - * - * @throws \EonX\EasyApiToken\Exceptions\InvalidConfigurationException - */ - public function getDecoders(): iterable - { - foreach (\array_keys($this->config) as $decoder) { - yield $this->build($decoder); - } - } - - public function getDefaultDecoder(): ?string - { - return $this->defaultDecoder; - } - - public function setContainer(ContainerInterface $container): void - { - $this->container = $container; - } - - /** - * @param mixed[] $config - * - * @throws \EonX\EasyApiToken\Exceptions\InvalidConfigurationException - */ - private function getSubFactoryClass(string $decoder, array $config): string - { - // If explicit type is set, use it - if (empty($config['type']) === false && \is_string($config['type'])) { - $type = $config['type']; - - // Allow type to be alias of default factory - return empty($this->defaultFactories[$type]) === false ? $this->defaultFactories[$type] : $type; - } - - // Default to factory for decoder - if (empty($this->defaultFactories[$decoder]) === false) { - return $this->defaultFactories[$decoder]; - } - - throw new InvalidConfigurationException(\sprintf( - 'No "type" or default factory configured for decoder "%s".', - $decoder - )); - } - - /** - * @param mixed[] $config - * - * @throws \EonX\EasyApiToken\Exceptions\InvalidConfigurationException - */ - private function instantiateSubFactory(string $decoder, array $config): ApiTokenDecoderSubFactoryInterface - { - $factoryClass = $this->getSubFactoryClass($decoder, $config); - - try { - if ($this->container !== null && $this->container->has($factoryClass)) { - return $this->container->get($factoryClass); - } - - if (\class_exists($factoryClass)) { - return new $factoryClass(); - } - } catch (\Throwable $exception) { - throw new InvalidConfigurationException(\sprintf( - 'Unable to instantiate the factory "%s" for decoder "%s": %s', - $factoryClass, - $decoder, - $exception->getMessage() - ), $exception->getCode(), $exception); - } - - throw new InvalidConfigurationException(\sprintf( - 'Unable to instantiate the factory "%s" for decoder "%s".', - $factoryClass, - $decoder - )); - } -} diff --git a/packages/EasyApiToken/src/Tokens/ApiKey.php b/packages/EasyApiToken/src/Tokens/ApiKey.php index a1635c2d8..15e8914fa 100644 --- a/packages/EasyApiToken/src/Tokens/ApiKey.php +++ b/packages/EasyApiToken/src/Tokens/ApiKey.php @@ -38,5 +38,3 @@ public function getPayload(): array ]; } } - -\class_alias(ApiKey::class, ApiKeyEasyApiToken::class); diff --git a/packages/EasyApiToken/src/Tokens/BasicAuth.php b/packages/EasyApiToken/src/Tokens/BasicAuth.php index bce29320a..c09d8e2fc 100644 --- a/packages/EasyApiToken/src/Tokens/BasicAuth.php +++ b/packages/EasyApiToken/src/Tokens/BasicAuth.php @@ -56,5 +56,3 @@ public function getUsername(): string return $this->username; } } - -\class_alias(BasicAuth::class, BasicAuthEasyApiToken::class); diff --git a/packages/EasyApiToken/src/Tokens/Factories/JwtFactory.php b/packages/EasyApiToken/src/Tokens/Factories/JwtFactory.php deleted file mode 100644 index a60fb5ebb..000000000 --- a/packages/EasyApiToken/src/Tokens/Factories/JwtFactory.php +++ /dev/null @@ -1,46 +0,0 @@ -jwtDriver = $jwtDriver; - } - - public function createFromString(string $token): JwtInterface - { - try { - return new Jwt((array)$this->jwtDriver->decode(\trim($token)), $token); - } catch (\Throwable $exception) { - throw new InvalidEasyApiTokenFromRequestException( - \sprintf( - 'Decoder "%s" unable to decode token. Message: %s', - static::class, - $exception->getMessage() - ), - $exception->getCode(), - $exception - ); - } - } -} - -\class_alias(JwtFactory::class, JwtEasyApiTokenFactory::class); diff --git a/packages/EasyApiToken/src/Tokens/Jwt.php b/packages/EasyApiToken/src/Tokens/Jwt.php index 220668610..22606f31f 100644 --- a/packages/EasyApiToken/src/Tokens/Jwt.php +++ b/packages/EasyApiToken/src/Tokens/Jwt.php @@ -81,5 +81,3 @@ public function hasClaim(string $claim): bool return isset($this->payload[$claim]); } } - -\class_alias(Jwt::class, JwtEasyApiToken::class); diff --git a/packages/EasyApiToken/src/Traits/DecoderNameAwareTrait.php b/packages/EasyApiToken/src/Traits/DecoderNameAwareTrait.php deleted file mode 100644 index 69a07ef19..000000000 --- a/packages/EasyApiToken/src/Traits/DecoderNameAwareTrait.php +++ /dev/null @@ -1,18 +0,0 @@ -decoderName = $decoderName; - } -} diff --git a/packages/EasyApiToken/src/Traits/DefaultDecoderFactoriesTrait.php b/packages/EasyApiToken/src/Traits/DefaultDecoderFactoriesTrait.php deleted file mode 100644 index b05e7e6d1..000000000 --- a/packages/EasyApiToken/src/Traits/DefaultDecoderFactoriesTrait.php +++ /dev/null @@ -1,28 +0,0 @@ - BasicAuthDecoderFactory::class, - 'chain' => ChainReturnFirstTokenDecoderFactory::class, - 'jwt-header' => JwtTokenDecoderFactory::class, - 'jwt-param' => JwtTokenInQueryDecoderFactory::class, - 'user-apikey' => ApiKeyAsBasicAuthUsernameDecoderFactory::class, - ]; - } -} diff --git a/packages/EasyApiToken/src/Traits/MasterDecoderFactoryAwareTrait.php b/packages/EasyApiToken/src/Traits/MasterDecoderFactoryAwareTrait.php deleted file mode 100644 index 3b3347cc8..000000000 --- a/packages/EasyApiToken/src/Traits/MasterDecoderFactoryAwareTrait.php +++ /dev/null @@ -1,20 +0,0 @@ -factory = $factory; - } -} diff --git a/packages/EasyApiToken/tests/AbstractJwtTokenTestCase.php b/packages/EasyApiToken/tests/AbstractJwtTokenTestCase.php index 9055541ef..216e7ef38 100644 --- a/packages/EasyApiToken/tests/AbstractJwtTokenTestCase.php +++ b/packages/EasyApiToken/tests/AbstractJwtTokenTestCase.php @@ -4,18 +4,10 @@ namespace EonX\EasyApiToken\Tests; -use EonX\EasyApiToken\External\Interfaces\JwtDriverInterface; -use EonX\EasyApiToken\Interfaces\Tokens\Factories\JwtFactoryInterface; -use EonX\EasyApiToken\Tokens\Factories\JwtFactory; use Nette\Utils\Strings; abstract class AbstractJwtTokenTestCase extends AbstractTestCase { - protected function createJwtEasyApiTokenFactory(JwtDriverInterface $jwtDriver): JwtFactoryInterface - { - return new JwtFactory($jwtDriver); - } - /** * @return false|resource */ diff --git a/packages/EasyApiToken/tests/Bridge/Laravel/EasyApiTokenServiceProviderTest.php b/packages/EasyApiToken/tests/Bridge/Laravel/EasyApiTokenServiceProviderTest.php index 2cdf7fe7e..e8220e4e0 100644 --- a/packages/EasyApiToken/tests/Bridge/Laravel/EasyApiTokenServiceProviderTest.php +++ b/packages/EasyApiToken/tests/Bridge/Laravel/EasyApiTokenServiceProviderTest.php @@ -4,11 +4,13 @@ namespace EonX\EasyApiToken\Tests\Bridge\Laravel; +use EonX\EasyApiToken\Bridge\BridgeConstantsInterface; use EonX\EasyApiToken\Bridge\Laravel\EasyApiTokenServiceProvider; use EonX\EasyApiToken\Decoders\BasicAuthDecoder; use EonX\EasyApiToken\Interfaces\ApiTokenDecoderInterface; use EonX\EasyApiToken\Interfaces\Factories\ApiTokenDecoderFactoryInterface as DecoderFactoryInterface; use EonX\EasyApiToken\Tests\AbstractLumenTestCase; +use EonX\EasyApiToken\Tests\Stubs\DecoderProviderStub; final class EasyApiTokenServiceProviderTest extends AbstractLumenTestCase { @@ -16,15 +18,8 @@ public function testRegister(): void { $app = $this->getApplication(); - \config([ - 'easy-api-token' => [ - 'decoders' => [ - 'basic' => null, - ], - 'default_decoder' => 'basic', - ], - ]); - + $app->singleton(DecoderProviderStub::class); + $app->tag(DecoderProviderStub::class, [BridgeConstantsInterface::TAG_DECODER_PROVIDER]); $app->register(EasyApiTokenServiceProvider::class); self::assertInstanceOf(DecoderFactoryInterface::class, $app->get(DecoderFactoryInterface::class)); diff --git a/packages/EasyApiToken/tests/Bridge/Symfony/EasyApiTokenBundleTest.php b/packages/EasyApiToken/tests/Bridge/Symfony/EasyApiTokenBundleTest.php index 9c5cf632a..0bf4c579a 100644 --- a/packages/EasyApiToken/tests/Bridge/Symfony/EasyApiTokenBundleTest.php +++ b/packages/EasyApiToken/tests/Bridge/Symfony/EasyApiTokenBundleTest.php @@ -5,12 +5,11 @@ namespace EonX\EasyApiToken\Tests\Bridge\Symfony; use EonX\EasyApiToken\Decoders\BasicAuthDecoder; -use EonX\EasyApiToken\Decoders\ChainDecoder; use EonX\EasyApiToken\Exceptions\InvalidConfigurationException; use EonX\EasyApiToken\Interfaces\ApiTokenDecoderInterface; +use EonX\EasyApiToken\Interfaces\Factories\ApiTokenDecoderFactoryInterface; use EonX\EasyApiToken\Tests\AbstractTestCase; use EonX\EasyApiToken\Tests\Bridge\Symfony\Stubs\KernelStub; -use EonX\EasyApiToken\Tests\Bridge\Symfony\Stubs\ServiceStub; final class EasyApiTokenBundleTest extends AbstractTestCase { @@ -20,13 +19,9 @@ public function testDecoderFactoryIsRegisteredAsService(): void $kernel->boot(); $container = $kernel->getContainer(); + $decoderFactory = $container->get(ApiTokenDecoderFactoryInterface::class); - /** @var \EonX\EasyApiToken\Tests\Bridge\Symfony\Stubs\ServiceStub $stub */ - $stub = $container->get(ServiceStub::class); - $decoderFactory = $stub->getDecoderFactory(); - - self::assertInstanceOf(ChainDecoder::class, $decoderFactory->build('chain')); - self::assertInstanceOf(BasicAuthDecoder::class, $decoderFactory->build('basic')); + self::assertInstanceOf(BasicAuthDecoder::class, $decoderFactory->build(BasicAuthDecoder::class)); self::assertInstanceOf(BasicAuthDecoder::class, $container->get(ApiTokenDecoderInterface::class)); self::expectException(InvalidConfigurationException::class); diff --git a/packages/EasyApiToken/tests/Bridge/Symfony/Stubs/KernelStub.php b/packages/EasyApiToken/tests/Bridge/Symfony/Stubs/KernelStub.php index ebf2b9df1..c060c3612 100644 --- a/packages/EasyApiToken/tests/Bridge/Symfony/Stubs/KernelStub.php +++ b/packages/EasyApiToken/tests/Bridge/Symfony/Stubs/KernelStub.php @@ -4,8 +4,9 @@ namespace EonX\EasyApiToken\Tests\Bridge\Symfony\Stubs; +use EonX\EasyApiToken\Bridge\BridgeConstantsInterface; use EonX\EasyApiToken\Bridge\Symfony\EasyApiTokenBundle; -use EonX\EasyApiToken\Interfaces\ApiTokenDecoderInterface; +use EonX\EasyApiToken\Tests\Stubs\DecoderProviderStub; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -21,12 +22,20 @@ public function __construct() public function process(ContainerBuilder $container): void { - $container->getDefinition(ApiTokenDecoderInterface::class)->setPublic(true); + foreach ($container->getDefinitions() as $definition) { + $definition->setPublic(true); + } + + foreach ($container->getAliases() as $alias) { + $alias->setPublic(true); + } $container - ->setDefinition(ServiceStub::class, new Definition(ServiceStub::class)) + ->setDefinition(DecoderProviderStub::class, new Definition(DecoderProviderStub::class)) ->setAutowired(true) - ->setPublic(true); + ->setAutoconfigured(true) + ->setPublic(true) + ->addTag(BridgeConstantsInterface::TAG_DECODER_PROVIDER); } /** @@ -39,7 +48,6 @@ public function registerBundles(): iterable public function registerContainerConfiguration(LoaderInterface $loader): void { - $loader->load(__DIR__ . '/config.yaml'); - $loader->load(__DIR__ . '/config_test.yaml'); + // No body needed. } } diff --git a/packages/EasyApiToken/tests/Bridge/Symfony/Stubs/ServiceStub.php b/packages/EasyApiToken/tests/Bridge/Symfony/Stubs/ServiceStub.php deleted file mode 100644 index e7f7ca4d5..000000000 --- a/packages/EasyApiToken/tests/Bridge/Symfony/Stubs/ServiceStub.php +++ /dev/null @@ -1,25 +0,0 @@ -decoderFactory = $decoderFactory; - } - - public function getDecoderFactory(): EasyApiTokenDecoderFactoryInterface - { - return $this->decoderFactory; - } -} diff --git a/packages/EasyApiToken/tests/Bridge/Symfony/Stubs/config.yaml b/packages/EasyApiToken/tests/Bridge/Symfony/Stubs/config.yaml deleted file mode 100644 index 45d780d3b..000000000 --- a/packages/EasyApiToken/tests/Bridge/Symfony/Stubs/config.yaml +++ /dev/null @@ -1,6 +0,0 @@ -easy_api_token: - decoders: - user-apikey: ~ - chain: - list: - - user-apikey diff --git a/packages/EasyApiToken/tests/Bridge/Symfony/Stubs/config_test.yaml b/packages/EasyApiToken/tests/Bridge/Symfony/Stubs/config_test.yaml deleted file mode 100644 index b815984a5..000000000 --- a/packages/EasyApiToken/tests/Bridge/Symfony/Stubs/config_test.yaml +++ /dev/null @@ -1,7 +0,0 @@ -easy_api_token: - default_decoder: 'basic' - decoders: - basic: ~ - chain: - list: - - basic diff --git a/packages/EasyApiToken/tests/Decoders/ApiKeyAsBasicAuthUsernameDecoderTest.php b/packages/EasyApiToken/tests/Decoders/ApiKeyAsBasicAuthUsernameDecoderTest.php deleted file mode 100644 index 3a18bb859..000000000 --- a/packages/EasyApiToken/tests/Decoders/ApiKeyAsBasicAuthUsernameDecoderTest.php +++ /dev/null @@ -1,56 +0,0 @@ -decode($this->createServerRequest())); - } - - public function testApiKeyAsBasicAuthUsernameNullIfDoesntStartWithBasic(): void - { - self::assertNull((new ApiKeyAsBasicAuthUsernameDecoder())->decode($this->createServerRequest([ - 'HTTP_AUTHORIZATION' => 'SomethingElse', - ]))); - } - - public function testApiKeyAsBasicAuthUsernameNullIfNotOnlyApiKeyProvided(): void - { - $tests = ['', ':', ':password', 'api-key:password']; - - foreach ($tests as $test) { - self::assertNull((new ApiKeyAsBasicAuthUsernameDecoder())->decode($this->createServerRequest([ - 'HTTP_AUTHORIZATION' => 'Basic ' . \base64_encode($test), - ]))); - } - } - - public function testApiKeyAsBasicAuthUsernameReturnEasyApiTokenSuccessfully(): void - { - // Value in header => [expectedUsername, expectedPassword] - $tests = [ - 'api-key' => ['api-key'], - 'api-key:' => ['api-key'], - 'api-key: ' => ['api-key'], - 'api-key: ' => ['api-key'], - ]; - - foreach ($tests as $test => $expected) { - /** @var \EonX\EasyApiToken\Interfaces\Tokens\ApiKeyInterface $token */ - $token = (new ApiKeyAsBasicAuthUsernameDecoder())->decode($this->createServerRequest([ - 'HTTP_AUTHORIZATION' => \sprintf('Basic %s', \base64_encode($test)), - ])); - - self::assertInstanceOf(ApiKeyInterface::class, $token); - self::assertEquals($expected[0], $token->getPayload()['api_key']); - } - } -} diff --git a/packages/EasyApiToken/tests/Decoders/Auth0JwtTokenDecoderTest.php b/packages/EasyApiToken/tests/Decoders/Auth0JwtTokenDecoderTest.php deleted file mode 100644 index e0abdaa2f..000000000 --- a/packages/EasyApiToken/tests/Decoders/Auth0JwtTokenDecoderTest.php +++ /dev/null @@ -1,58 +0,0 @@ -createJwtEasyApiTokenFactory($this->createAuth0JwtDriver()); - - /** @var \EonX\EasyApiToken\Interfaces\Tokens\JwtInterface $token */ - $token = (new JwtTokenDecoder($jwtEasyApiTokenFactory))->decode($this->createRequest([ - 'HTTP_AUTHORIZATION' => 'Bearer ' . $this->createToken(), - ])); - - $payload = $token->getPayload(); - - self::assertInstanceOf(Jwt::class, $token); - - foreach (static::$tokenPayload as $key => $value) { - self::assertArrayHasKey($key, $payload); - self::assertEquals($value, $payload[$key]); - } - } - - public function testJwtTokenNullIfAuthorizationHeaderNotSet(): void - { - $decoder = new JwtTokenDecoder($this->createJwtEasyApiTokenFactory($this->createAuth0JwtDriver())); - - self::assertNull($decoder->decode($this->createRequest())); - } - - public function testJwtTokenNullIfDoesntStartWithBearer(): void - { - $decoder = new JwtTokenDecoder($this->createJwtEasyApiTokenFactory($this->createAuth0JwtDriver())); - - self::assertNull($decoder->decode($this->createRequest([ - 'HTTP_AUTHORIZATION' => 'SomethingElse', - ]))); - } - - public function testJwtTokenReturnNullIfUnableToDecodeToken(): void - { - $jwtEasyApiTokenFactory = $this->createJwtEasyApiTokenFactory($this->createAuth0JwtDriver()); - - $token = (new JwtTokenDecoder($jwtEasyApiTokenFactory))->decode($this->createRequest([ - 'HTTP_AUTHORIZATION' => 'Bearer WeirdTokenHere', - ])); - - self::assertNull($token); - } -} diff --git a/packages/EasyApiToken/tests/Decoders/Auth0JwtTokenInQueryDecoderTest.php b/packages/EasyApiToken/tests/Decoders/Auth0JwtTokenInQueryDecoderTest.php deleted file mode 100644 index 9b1d8f88c..000000000 --- a/packages/EasyApiToken/tests/Decoders/Auth0JwtTokenInQueryDecoderTest.php +++ /dev/null @@ -1,45 +0,0 @@ -createJwtEasyApiTokenFactory($this->createAuth0JwtDriver()); - - $decoder = new JwtTokenInQueryDecoder($jwtEasyApiTokenFactory, 'param'); - - $request = $this->createRequest(null, [ - 'param' => $this->createToken(), - ]); - - /** @var \EonX\EasyApiToken\Interfaces\Tokens\JwtInterface $token */ - $token = $decoder->decode($request); - - $payload = $token->getPayload(); - - self::assertInstanceOf(Jwt::class, $token); - - foreach (static::$tokenPayload as $key => $value) { - self::assertArrayHasKey($key, $payload); - self::assertEquals($value, $payload[$key]); - } - } - - public function testNullWhenQueryParamNotSet(): void - { - $decoder = new JwtTokenInQueryDecoder( - $this->createJwtEasyApiTokenFactory($this->createAuth0JwtDriver()), - 'param' - ); - - self::assertNull($decoder->decode($this->createRequest())); - } -} diff --git a/packages/EasyApiToken/tests/Decoders/ChainReturnFirstTokenDecoderTest.php b/packages/EasyApiToken/tests/Decoders/ChainReturnFirstTokenDecoderTest.php index 8a7730352..c31f6b4e6 100644 --- a/packages/EasyApiToken/tests/Decoders/ChainReturnFirstTokenDecoderTest.php +++ b/packages/EasyApiToken/tests/Decoders/ChainReturnFirstTokenDecoderTest.php @@ -4,7 +4,7 @@ namespace EonX\EasyApiToken\Tests\Decoders; -use EonX\EasyApiToken\Decoders\ApiKeyAsBasicAuthUsernameDecoder; +use EonX\EasyApiToken\Decoders\ApiKeyDecoder; use EonX\EasyApiToken\Decoders\BasicAuthDecoder; use EonX\EasyApiToken\Decoders\ChainDecoder; use EonX\EasyApiToken\Interfaces\Tokens\ApiKeyInterface; @@ -45,6 +45,6 @@ public function testChainFirstNullIfNoDecoderCouldDecoderToken(): void private function createChainReturnFirstTokenDecoder(): ChainDecoder { - return new ChainDecoder([new BasicAuthDecoder(), new ApiKeyAsBasicAuthUsernameDecoder()]); + return new ChainDecoder([new BasicAuthDecoder(), new ApiKeyDecoder()]); } } diff --git a/packages/EasyApiToken/tests/Decoders/FirebaseJwtTokenDecoderTest.php b/packages/EasyApiToken/tests/Decoders/FirebaseJwtTokenDecoderTest.php deleted file mode 100644 index 10009d133..000000000 --- a/packages/EasyApiToken/tests/Decoders/FirebaseJwtTokenDecoderTest.php +++ /dev/null @@ -1,77 +0,0 @@ -isAlgoRs($algo)) { - $key = $this->getOpenSslPublicKey(); - } - - $jwtEasyApiTokenFactory = $this->createJwtEasyApiTokenFactory($this->createFirebaseJwtDriver( - null, - $key, - null, - [$algo] - )); - - /** @var \EonX\EasyApiToken\Interfaces\Tokens\JwtInterface $token */ - $token = (new JwtTokenDecoder($jwtEasyApiTokenFactory))->decode($this->createRequest([ - 'HTTP_AUTHORIZATION' => 'Bearer ' . $this->createToken($algo), - ])); - - $payload = $token->getPayload(); - - self::assertInstanceOf(Jwt::class, $token); - - foreach (static::$tokenPayload as $key => $value) { - self::assertArrayHasKey($key, $payload); - self::assertEquals($value, $payload[$key]); - } - } - } - - public function testJwtTokenNullIfAuthorizationHeaderNotSet(): void - { - $decoder = new JwtTokenDecoder($this->createJwtEasyApiTokenFactory($this->createFirebaseJwtDriver())); - - self::assertNull($decoder->decode($this->createRequest())); - } - - public function testJwtTokenNullIfDoesntStartWithBearer(): void - { - $decoder = new JwtTokenDecoder($this->createJwtEasyApiTokenFactory($this->createFirebaseJwtDriver())); - - self::assertNull($decoder->decode($this->createRequest([ - 'HTTP_AUTHORIZATION' => 'SomethingElse', - ]))); - } - - public function testJwtTokenReturnNullIfUnableToDecodeToken(): void - { - $jwtEasyApiTokenFactory = $this->createJwtEasyApiTokenFactory($this->createFirebaseJwtDriver( - null, - 'different-key', - null, - ['HS256'], - 2 - )); - - $token = (new JwtTokenDecoder($jwtEasyApiTokenFactory))->decode($this->createRequest([ - 'HTTP_AUTHORIZATION' => 'Bearer ' . $this->createToken(), - ])); - - self::assertNull($token); - } -} diff --git a/packages/EasyApiToken/tests/Decoders/FirebaseJwtTokenInQueryDecoderTest.php b/packages/EasyApiToken/tests/Decoders/FirebaseJwtTokenInQueryDecoderTest.php deleted file mode 100644 index 08111817e..000000000 --- a/packages/EasyApiToken/tests/Decoders/FirebaseJwtTokenInQueryDecoderTest.php +++ /dev/null @@ -1,56 +0,0 @@ -isAlgoRs($algo)) { - $key = $this->getOpenSslPublicKey(); - } - - $jwtEasyApiTokenFactory = $this->createJwtEasyApiTokenFactory($this->createFirebaseJwtDriver( - null, - $key, - null, - [$algo] - )); - $decoder = new JwtTokenInQueryDecoder($jwtEasyApiTokenFactory, 'param'); - $request = $this->createRequest(null, [ - 'param' => $this->createToken($algo), - ]); - - /** @var \EonX\EasyApiToken\Interfaces\Tokens\JwtInterface $token */ - $token = $decoder->decode($request); - - $payload = $token->getPayload(); - - self::assertInstanceOf(Jwt::class, $token); - - foreach (static::$tokenPayload as $key => $value) { - self::assertArrayHasKey($key, $payload); - self::assertEquals($value, $payload[$key]); - } - } - } - - public function testNullWhenQueryParamNotSet(): void - { - $decoder = new JwtTokenInQueryDecoder( - $this->createJwtEasyApiTokenFactory($this->createFirebaseJwtDriver()), - 'param' - ); - - self::assertNull($decoder->decode($this->createRequest())); - } -} diff --git a/packages/EasyApiToken/tests/Factories/EasyApiDecoderFactoryTest.php b/packages/EasyApiToken/tests/Factories/EasyApiDecoderFactoryTest.php deleted file mode 100644 index 1c6854f24..000000000 --- a/packages/EasyApiToken/tests/Factories/EasyApiDecoderFactoryTest.php +++ /dev/null @@ -1,456 +0,0 @@ - - * - * @see testInvalidConfigurationErrors - */ - public function getBrokenConfigurations(): iterable - { - yield 'Empty configuration' => [[], 'nothing', 'No decoders configured']; - - yield 'Error is thrown when a non-existent key is requested.' => [ - [ - 'onething' => [ - 'type' => 'basic', - ], - ], - 'some_other_thing', - 'No decoder configured for key: "some_other_thing".', - ]; - - yield 'Error because no type set and no default factories for decoder' => [ - [ - 'fake-basic' => [], - ], - 'fake-basic', - 'No "type" or default factory configured for decoder "fake-basic".', - ]; - - yield 'Test that an error is thrown when a non-existent decoder type is configured.' => [ - [ - 'xxx' => [ - 'type' => 'yyy', - 'driver' => 'auth0', - 'options' => [], - ], - ], - 'xxx', - 'Unable to instantiate the factory "yyy" for decoder "xxx".', - ]; - - yield 'Expect chain driver with no list to return error.' => [ - [ - 'chain-thing' => [ - 'type' => 'chain', - ], - ], - 'chain-thing', - '"list" is required and must be an array for decoder "chain-thing".', - ]; - - yield 'Expect error for missing options supplied for JWT driver.' => [ - [ - 'rad' => [ - 'type' => 'jwt-header', - 'driver' => 'auth0', - ], - ], - 'rad', - '"options" is required and must be an array for decoder "rad".', - ]; - - yield 'Expect error for invalid jwt driver.' => [ - [ - 'foobar' => [ - 'type' => 'jwt-header', - 'driver' => 'GOOGLE', - 'options' => ['not-empty'], - ], - ], - 'foobar', - '"driver" value "GOOGLE" is invalid. Valid drivers: ["auth0", "firebase"].', - ]; - - yield 'Expect error for missing jwt driver' => [ - [ - 'something' => [ - 'type' => 'jwt-header', - 'options' => [], - ], - ], - 'something', - '"driver" is required and must be a string for decoder "something".', - ]; - - yield 'Expect error for missing param' => [ - [ - 'foobar' => [ - 'type' => 'jwt-param', - 'driver' => 'auth0', - 'options' => [ - 'valid_audiences' => ['id1', 'id2'], - 'authorized_iss' => ['xyz.auth0', 'abc.goog'], - 'private_key' => 'someprivatekeystring', - 'allowed_algos' => ['HS256', 'RS256'], - ], - ], - ], - 'foobar', - '"param" is required and must be an string for decoder "foobar".', - ]; - } - - /** - * @return iterable - * - * @throws \EonX\EasyApiToken\Exceptions\InvalidArgumentException - * - * @see testBuild - * @see testBuildWithContainer - */ - public function getChainBuilds(): iterable - { - $config = [ - 'chain-key' => [ - 'type' => 'chain', - 'list' => ['api', 'pass'], - ], - 'api' => [ - 'type' => 'user-apikey', - ], - 'pass' => [ - 'type' => 'basic', - ], - ]; - - yield 'Build API Chain' => [ - $config, - 'chain-key', - new ChainDecoder([ - new ApiKeyAsBasicAuthUsernameDecoder('api'), - new BasicAuthDecoder('pass'), - ], 'chain-key'), - ]; - } - - /** - * @return iterable - * - * @see testBuild - * @see testBuildWithContainer - */ - public function getJwtBuilds(): iterable - { - $config = [ - 'jwt-by-header' => [ - 'type' => 'jwt-header', - 'driver' => 'auth0', - 'options' => [ - 'valid_audiences' => ['id1', 'id2'], - 'authorized_iss' => ['xyz.auth0', 'abc.goog'], - 'private_key' => 'someprivatekeystring', - 'allowed_algos' => ['HS256', 'RS256'], - ], - ], - 'jwt-by-parameter' => [ - 'type' => 'jwt-param', - 'driver' => 'firebase', - 'options' => [ - 'algo' => 'HS256', - 'allowed_algos' => ['HS256', 'RS256'], - 'leeway' => 15, - 'param' => 'authParam', - 'private_key' => 'someprivatekeystring', - 'public_key' => 'somepublickeystring', - ], - ], - 'jwt-by-header-firebase' => [ - 'type' => 'jwt-header', - 'driver' => 'firebase', - 'options' => [ - 'algo' => 'HS256', - 'allowed_algos' => ['HS256', 'RS256'], - 'leeway' => 15, - 'private_key' => 'someprivatekeystring', - 'public_key' => 'somepublickeystring', - ], - ], - 'jwt-by-parameter-auth0' => [ - 'type' => 'jwt-param', - 'driver' => 'auth0', - 'options' => [ - 'allowed_algos' => ['HS256', 'RS256'], - 'authorized_iss' => ['xyz.auth0', 'abc.goog'], - 'param' => 'authParam', - 'private_key' => 'someprivatekeystring', - 'valid_audiences' => ['id1', 'id2'], - ], - ], - 'jwt-by-parameter-auth0-with-cache' => [ - 'type' => 'jwt-param', - 'driver' => 'auth0', - 'options' => [ - 'allowed_algos' => ['HS256', 'RS256'], - 'authorized_iss' => ['xyz.auth0', 'abc.goog'], - 'cache_path' => 'test/path', - 'param' => 'authParam', - 'private_key' => 'someprivatekeystring', - 'valid_audiences' => ['id1', 'id2'], - ], - ], - ]; - - yield 'Jwt Header' => [ - $config, - 'jwt-by-header', - new JwtTokenDecoder( - new JwtFactory( - new Auth0JwtDriver( - ['id1', 'id2'], - ['xyz.auth0', 'abc.goog'], - 'someprivatekeystring', - 'id1', - ['HS256', 'RS256'] - ) - ), - null, - 'jwt-by-header' - ), - ]; - - yield 'Jwt Parameter' => [ - $config, - 'jwt-by-parameter', - new JwtTokenInQueryDecoder( - new JwtFactory( - new FirebaseJwtDriver( - 'HS256', - 'somepublickeystring', - 'someprivatekeystring', - ['HS256', 'RS256'], - 15 - ) - ), - 'authParam', - 'jwt-by-parameter' - ), - ]; - - yield 'Jwt Header with Firebase' => [ - $config, - 'jwt-by-header-firebase', - new JwtTokenDecoder( - new JwtFactory( - new FirebaseJwtDriver( - 'HS256', - 'somepublickeystring', - 'someprivatekeystring', - ['HS256', 'RS256'], - 15 - ) - ), - null, - 'jwt-by-header-firebase' - ), - ]; - - yield 'Jwt Parameter with Auth0' => [ - $config, - 'jwt-by-parameter-auth0', - new JwtTokenInQueryDecoder( - new JwtFactory( - new Auth0JwtDriver( - ['id1', 'id2'], - ['xyz.auth0', 'abc.goog'], - 'someprivatekeystring', - 'id1', - ['HS256', 'RS256'] - ) - ), - 'authParam', - 'jwt-by-parameter-auth0' - ), - ]; - - yield 'Jwt Parameter with Auth0, with cache' => [ - $config, - 'jwt-by-parameter-auth0-with-cache', - new JwtTokenInQueryDecoder( - new JwtFactory( - new Auth0JwtDriver( - ['id1', 'id2'], - ['xyz.auth0', 'abc.goog'], - 'someprivatekeystring', - 'id1', - ['HS256', 'RS256'], - new FileSystemCacheHandler('test/path') - ) - ), - 'authParam', - 'jwt-by-parameter-auth0-with-cache' - ), - ]; - } - - /** - * @return iterable - * - * @see testBuild - * @see testBuildWithContainer - */ - public function getSimpleBuilds(): iterable - { - yield 'Simple API Key' => [ - [ - 'apiconfig' => [ - 'type' => 'user-apikey', - ], - ], - 'apiconfig', - new ApiKeyAsBasicAuthUsernameDecoder('apiconfig'), - ]; - - yield 'Simple Basic Auth decoder' => [ - [ - 'something' => [ - 'type' => 'basic', - ], - ], - 'something', - new BasicAuthDecoder('something'), - ]; - - yield 'Simple Basic Auth decoder using default factory' => [ - [ - 'basic' => null, - ], - 'basic', - new BasicAuthDecoder(), - ]; - } - - /** - * @param mixed[] $config Config array to build factory with. - * - * @throws \EonX\EasyApiToken\Exceptions\InvalidConfigurationException - * - * @dataProvider getSimpleBuilds - * @dataProvider getJwtBuilds - * @dataProvider getChainBuilds - */ - public function testBuild(array $config, string $key, ApiTokenDecoderInterface $expected): void - { - $factory = new ApiTokenDecoderFactory([new FromConfigDecoderProvider($config)]); - - $actual = $factory->build($key); - $second = $factory->build($key); - - $this->assertEquals($expected, $actual); - $this->assertEquals(\spl_object_hash($actual), \spl_object_hash($second)); - } - - public function testBuildContainerThrows(): void - { - $container = new class() extends Application { - public function has($id): bool - { - throw new \RuntimeException('runtime problems'); - } - }; - - $this->expectException(InvalidConfigurationException::class); - $this->expectExceptionMessage('runtime problems'); - - $provider = new FromConfigDecoderProvider([ - 'basic' => [], - ]); - $provider->setContainer($container); - - $factory = new ApiTokenDecoderFactory([$provider]); - - $factory->build('basic'); - } - - /** - * @param mixed[] $config Config array to build factory with. - * - * @throws \EonX\EasyApiToken\Exceptions\InvalidConfigurationException - * - * @dataProvider getSimpleBuilds - * @dataProvider getJwtBuilds - * @dataProvider getChainBuilds - */ - public function testBuildWithContainer(array $config, string $key, ApiTokenDecoderInterface $expected): void - { - $container = new Application(); - $container->bind(BasicAuthDecoderFactory::class, BasicAuthDecoderFactory::class); - - $provider = new FromConfigDecoderProvider($config); - $provider->setContainer($container); - - $factory = new ApiTokenDecoderFactory([$provider]); - - $actual = $factory->build($key); - $second = $factory->build($key); - - $this->assertEquals($expected, $actual); - $this->assertEquals(\spl_object_hash($actual), \spl_object_hash($second)); - } - - /** - * @param mixed[] $config Config array to build factory with. - * - * @throws \EonX\EasyApiToken\Exceptions\InvalidConfigurationException - * - * @dataProvider getBrokenConfigurations - */ - public function testInvalidConfigurationErrors(array $config, string $key, string $expectedError): void - { - $this->expectException(InvalidConfigurationException::class); - $this->expectExceptionMessage($expectedError); - - (new ApiTokenDecoderFactory([new FromConfigDecoderProvider($config)]))->build($key); - } - - public function testNoDefaultDecoderSetException(): void - { - $this->expectException(InvalidDefaultDecoderException::class); - $this->expectExceptionMessage('No default decoder set'); - - (new ApiTokenDecoderFactory([]))->buildDefault(); - } -} diff --git a/packages/EasyApiToken/tests/Stubs/DecoderProviderStub.php b/packages/EasyApiToken/tests/Stubs/DecoderProviderStub.php new file mode 100644 index 000000000..ed76cca23 --- /dev/null +++ b/packages/EasyApiToken/tests/Stubs/DecoderProviderStub.php @@ -0,0 +1,27 @@ + + */ + public function getDecoders(): iterable + { + yield new BasicAuthDecoder(); + } + + public function getDefaultDecoder(): ?string + { + return BasicAuthDecoder::class; + } +} diff --git a/packages/EasyAsync/composer.json b/packages/EasyAsync/composer.json index cf2de1590..5a2215071 100644 --- a/packages/EasyAsync/composer.json +++ b/packages/EasyAsync/composer.json @@ -5,9 +5,9 @@ "license": "MIT", "require": { "php": "^7.2", - "eonx-com/easy-event-dispatcher": "^2.6", - "eonx-com/easy-pagination": "^2.6", - "eonx-com/easy-random": "^2.6", + "eonx-com/easy-event-dispatcher": "^3.0", + "eonx-com/easy-pagination": "^3.0", + "eonx-com/easy-random": "^3.0", "nette/utils": "^3.1" }, "require-dev": { @@ -30,7 +30,7 @@ }, "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "3.0-dev" } } } diff --git a/packages/EasyAwsCredentialsFinder/composer.json b/packages/EasyAwsCredentialsFinder/composer.json index 1a3daf4f5..567545c08 100644 --- a/packages/EasyAwsCredentialsFinder/composer.json +++ b/packages/EasyAwsCredentialsFinder/composer.json @@ -5,7 +5,7 @@ "license": "MIT", "require": { "php": "^7.2", - "eonx-com/easy-utils": "^2.6", + "eonx-com/easy-utils": "^3.0", "symfony/process": "^4.4 || ^5.1.5", "symplify/package-builder": "^8.3.41", "symplify/autowire-array-parameter": "^8.3.41", @@ -28,7 +28,7 @@ }, "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "3.0-dev" } } } diff --git a/packages/EasyBankFiles/composer.json b/packages/EasyBankFiles/composer.json index 53109b54e..897f5fc22 100644 --- a/packages/EasyBankFiles/composer.json +++ b/packages/EasyBankFiles/composer.json @@ -6,7 +6,7 @@ "require": { "php": "^7.2", "nette/utils": "^3.1", - "eonx-com/easy-error-handler": "^2.6", + "eonx-com/easy-error-handler": "^3.0", "monolog/monolog": "^2.1" }, "require-dev": { @@ -25,7 +25,7 @@ }, "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "3.0-dev" } } } diff --git a/packages/EasyBugsnag/composer.json b/packages/EasyBugsnag/composer.json index 4af3330b4..28b8e9b56 100644 --- a/packages/EasyBugsnag/composer.json +++ b/packages/EasyBugsnag/composer.json @@ -6,7 +6,7 @@ "require": { "php": "^7.2", "bugsnag/bugsnag": "^3.19", - "eonx-com/easy-utils": "^2.6", + "eonx-com/easy-utils": "^3.0", "nette/utils": "^3.1" }, "require-dev": { @@ -27,7 +27,7 @@ }, "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "3.0-dev" } } } diff --git a/packages/EasyCore/composer.json b/packages/EasyCore/composer.json index cfb07bf0f..b9cf05556 100644 --- a/packages/EasyCore/composer.json +++ b/packages/EasyCore/composer.json @@ -30,7 +30,7 @@ }, "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "3.0-dev" } } } diff --git a/packages/EasyCore/src/Bridge/Symfony/ApiPlatform/Metadata/NoPropertiesPropertyNameCollectionFactory.php b/packages/EasyCore/src/Bridge/Symfony/ApiPlatform/Metadata/NoPropertiesPropertyNameCollectionFactory.php deleted file mode 100644 index 6fc8b4875..000000000 --- a/packages/EasyCore/src/Bridge/Symfony/ApiPlatform/Metadata/NoPropertiesPropertyNameCollectionFactory.php +++ /dev/null @@ -1,46 +0,0 @@ -decorated = $decorated; - - @\trigger_error(\sprintf( - '%s is deprecated since 2.4.26 and will be removed in 3.0, This is now supported by api-platform itself.', - static::class, - ), \E_USER_DEPRECATED); - } - - /** - * @param null|mixed[] $options - * - * @return \ApiPlatform\Core\Metadata\Property\PropertyNameCollection - * - * @throws \ApiPlatform\Core\Exception\ResourceClassNotFoundException - */ - public function create(string $resourceClass, ?array $options = null): PropertyNameCollection - { - if (\is_a($resourceClass, NoPropertiesApiResourceInterface::class, true)) { - return new PropertyNameCollection([]); - } - - return $this->decorated->create($resourceClass, $options ?? []); - } -} diff --git a/packages/EasyCore/src/Bridge/Symfony/Messenger/ProcessWithLockMiddleware.php b/packages/EasyCore/src/Bridge/Symfony/Messenger/ProcessWithLockMiddleware.php deleted file mode 100644 index 10802053a..000000000 --- a/packages/EasyCore/src/Bridge/Symfony/Messenger/ProcessWithLockMiddleware.php +++ /dev/null @@ -1,56 +0,0 @@ -shouldSkip($envelope)) { - return $stack->next() - ->handle($envelope, $stack); - } - - /** @var \EonX\EasyCore\Lock\WithLockDataInterface $message */ - $message = $envelope->getMessage(); - - $newEnvelope = $this->processWithLock($message, static function () use ($envelope, $stack): Envelope { - return $stack->next() - ->handle($envelope, $stack); - }); - - return $newEnvelope ?? $envelope; - } - - private function shouldSkip(Envelope $envelope): bool - { - if ($envelope->last(ConsumedByWorkerStamp::class) === null) { - return true; - } - - if ($envelope->getMessage() instanceof WithLockDataInterface === false) { - return true; - } - - return false; - } -} diff --git a/packages/EasyCore/src/Bridge/Symfony/Messenger/SafeHandlerTrait.php b/packages/EasyCore/src/Bridge/Symfony/Messenger/SafeHandlerTrait.php deleted file mode 100644 index 07c2d447b..000000000 --- a/packages/EasyCore/src/Bridge/Symfony/Messenger/SafeHandlerTrait.php +++ /dev/null @@ -1,51 +0,0 @@ -lockService = $lockService; - } - - /** - * @return void|mixed - */ - protected function handleSafely(string $resource, Closure $func, ?float $ttl = null) - { - @\trigger_error(\sprintf( - '%s::%s() is deprecated since 2.3.3 and will be removed in 3.0, use %s::%s() instead', - SafeHandlerTrait::class, - __METHOD__, - ProcessWithLockTrait::class, - 'processWithLock' - ), \E_USER_DEPRECATED); - - $lock = $this->lockService->createLock($resource, $ttl); - - if ($lock->acquire() === false) { - return; - } - - try { - return $func(); - } finally { - $lock->release(); - } - } -} diff --git a/packages/EasyCore/src/Bridge/Symfony/Resources/config/services.php b/packages/EasyCore/src/Bridge/Symfony/Resources/config/services.php index a61b055db..c7715da96 100644 --- a/packages/EasyCore/src/Bridge/Symfony/Resources/config/services.php +++ b/packages/EasyCore/src/Bridge/Symfony/Resources/config/services.php @@ -3,9 +3,6 @@ declare(strict_types=1); use EonX\EasyCore\Bridge\Symfony\Env\ForBuildEnvVarProcessor; -use EonX\EasyCore\Bridge\Symfony\Messenger\ProcessWithLockMiddleware; -use EonX\EasyCore\Lock\LockService; -use EonX\EasyCore\Lock\LockServiceInterface; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; return static function (ContainerConfigurator $containerConfigurator): void { @@ -16,8 +13,4 @@ ->autoconfigure(); $services->set(ForBuildEnvVarProcessor::class); - - $services->set(LockServiceInterface::class, LockService::class); - - $services->set(ProcessWithLockMiddleware::class); }; diff --git a/packages/EasyCore/src/Http/Middleware/SetContentLength.php b/packages/EasyCore/src/Http/Middleware/SetContentLength.php deleted file mode 100644 index 4d4cf450a..000000000 --- a/packages/EasyCore/src/Http/Middleware/SetContentLength.php +++ /dev/null @@ -1,33 +0,0 @@ -headers->set('Content-Length', \strlen($response->getContent())); - - return $response; - } -} diff --git a/packages/EasyCore/src/Lock/LockData.php b/packages/EasyCore/src/Lock/LockData.php deleted file mode 100644 index 9f704e5f9..000000000 --- a/packages/EasyCore/src/Lock/LockData.php +++ /dev/null @@ -1,42 +0,0 @@ -resource = $resource; - $this->ttl = $ttl; - } - - public function getResource(): string - { - return $this->resource; - } - - public function getTtl(): ?float - { - return $this->ttl; - } -} diff --git a/packages/EasyCore/src/Lock/LockDataInterface.php b/packages/EasyCore/src/Lock/LockDataInterface.php deleted file mode 100644 index 36c865120..000000000 --- a/packages/EasyCore/src/Lock/LockDataInterface.php +++ /dev/null @@ -1,15 +0,0 @@ -registry = $registry; - $this->logger = $logger ?? new NullLogger(); - } - - public function createLock(string $resource, ?float $ttl = null): LockInterface - { - return $this->getFactory() - ->createLock($resource, $ttl ?? 300.0); - } - - public function setStore(PersistingStoreInterface $store): LockServiceInterface - { - $this->store = $store; - - return $this; - } - - private function getFactory(): LockFactory - { - if ($this->factory !== null) { - return $this->factory; - } - - $factory = new LockFactory($this->store ?? new PdoStore($this->registry->getConnection())); - $factory->setLogger($this->logger); - - return $this->factory = $factory; - } -} diff --git a/packages/EasyCore/src/Lock/LockServiceInterface.php b/packages/EasyCore/src/Lock/LockServiceInterface.php deleted file mode 100644 index e1dcac070..000000000 --- a/packages/EasyCore/src/Lock/LockServiceInterface.php +++ /dev/null @@ -1,18 +0,0 @@ -lockService = $lockService; - } - - /** - * @return null|mixed - */ - protected function processWithLock(WithLockDataInterface $withLockData, Closure $func) - { - @\trigger_error(\sprintf( - '%s is deprecated since 2.4.31 and will be removed in 3.0, Use eonx-com/easy-lock package instead.', - static::class - ), \E_USER_DEPRECATED); - - $data = $withLockData->getLockData(); - $lock = $this->lockService->createLock($data->getResource(), $data->getTtl()); - - if ($lock->acquire() === false) { - return null; - } - - try { - return $func(); - } finally { - $lock->release(); - } - } -} diff --git a/packages/EasyCore/src/Lock/WithLockDataInterface.php b/packages/EasyCore/src/Lock/WithLockDataInterface.php deleted file mode 100644 index a4d8a2cd6..000000000 --- a/packages/EasyCore/src/Lock/WithLockDataInterface.php +++ /dev/null @@ -1,17 +0,0 @@ -resource, $this->ttl); - } - - public function setResource(string $resource): void - { - $this->resource = $resource; - } - - public function setTtl(?float $ttl = null): void - { - $this->ttl = $ttl; - } -} diff --git a/packages/EasyCore/tests/Bridge/Symfony/Messenger/ProcessWithLockMiddlewareTest.php b/packages/EasyCore/tests/Bridge/Symfony/Messenger/ProcessWithLockMiddlewareTest.php deleted file mode 100644 index 05f1993c1..000000000 --- a/packages/EasyCore/tests/Bridge/Symfony/Messenger/ProcessWithLockMiddlewareTest.php +++ /dev/null @@ -1,75 +0,0 @@ - - * - * @see testProcessWithJobLog - */ - public function providerHandle(): iterable - { - $withData = new WithLockDataStub(); - $withData->setResource('resource'); - $withData->setTtl(60.0); - - yield 'Acquire lock' => [ - new Envelope($withData, [new ConsumedByWorkerStamp()]), - new LockStub(true), - false, - ]; - - yield 'Do Not Acquire lock' => [ - new Envelope($withData, [new ConsumedByWorkerStamp()]), - new LockStub(false), - true, - ]; - - yield 'Skipped because envelope does not have worker stamp' => [ - new Envelope($withData), - new LockStub(false), - false, - ]; - - yield 'Skipped because message does not implement interface' => [ - new Envelope(new \stdClass(), [new ConsumedByWorkerStamp()]), - new LockStub(false), - false, - ]; - } - - /** - * @dataProvider providerHandle - */ - public function testProcessWithJobLog(Envelope $envelope, LockStub $lock, bool $sameEnvelope): void - { - $middleware = new ProcessWithLockMiddleware(); - $middleware->setLockService(new LockServiceStub($lock)); - - $iterator = new \ArrayIterator([ - $middleware, - new MessengerMiddlewareStub(static function (): Envelope { - return new Envelope(new \stdClass()); - }), - ]); - - $newEnvelope = $iterator->current() - ->handle($envelope, new StackMiddleware($iterator)); - - self::assertEquals($sameEnvelope, \spl_object_hash($envelope) === \spl_object_hash($newEnvelope)); - } -} diff --git a/packages/EasyCore/tests/Http/Middleware/SetContentLengthTest.php b/packages/EasyCore/tests/Http/Middleware/SetContentLengthTest.php deleted file mode 100644 index 9b3ed3009..000000000 --- a/packages/EasyCore/tests/Http/Middleware/SetContentLengthTest.php +++ /dev/null @@ -1,50 +0,0 @@ -prophesize(Request::class); - /** @var \Illuminate\Http\Request $request */ - $request = $requestProphecy->reveal(); - $responseProphecy = $this->prophesize(Response::class); - $responseProphecy->getContent() - ->willReturn('content'); - $response = $responseProphecy->reveal(); - $headersProphecy = $this->prophesize(ResponseHeaderBag::class); - // 'content' string's length is 7 - $headersProphecy->set('Content-Length', 7) - ->willReturn(); - $response->headers = $headersProphecy->reveal(); - $next = static function ($request) use ($response) { - $response->forRequest = $request; - - return $response; - }; - - $actualResult = $middleware->handle($request, $next); - - self::assertEquals($actualResult, $response); - self::assertEquals($response->forRequest, $request); - $responseProphecy->getContent() - ->shouldHaveBeenCalledOnce(); - $headersProphecy->set('Content-Length', 7) - ->shouldHaveBeenCalledOnce(); - } -} diff --git a/packages/EasyCore/tests/Stubs/LockServiceStub.php b/packages/EasyCore/tests/Stubs/LockServiceStub.php deleted file mode 100644 index d5903385e..000000000 --- a/packages/EasyCore/tests/Stubs/LockServiceStub.php +++ /dev/null @@ -1,32 +0,0 @@ -lock = $lock; - } - - public function createLock(string $resource, ?float $ttl = null): LockInterface - { - return $this->lock; - } - - public function setStore(PersistingStoreInterface $store): LockServiceInterface - { - return $this; - } -} diff --git a/packages/EasyCore/tests/Stubs/LockStub.php b/packages/EasyCore/tests/Stubs/LockStub.php deleted file mode 100644 index 83ce49a14..000000000 --- a/packages/EasyCore/tests/Stubs/LockStub.php +++ /dev/null @@ -1,51 +0,0 @@ -acquire = $acquire; - } - - /** - * @param bool $blocking - */ - public function acquire($blocking = false): bool - { - return $this->acquire; - } - - public function getRemainingLifetime(): ?float - { - return null; - } - - public function isAcquired(): bool - { - return $this->acquire; - } - - public function isExpired(): bool - { - return false; - } - - public function refresh(): void - { - } - - public function release(): void - { - } -} diff --git a/packages/EasyCore/tests/Stubs/WithLockDataStub.php b/packages/EasyCore/tests/Stubs/WithLockDataStub.php deleted file mode 100644 index 94fe20656..000000000 --- a/packages/EasyCore/tests/Stubs/WithLockDataStub.php +++ /dev/null @@ -1,13 +0,0 @@ -getName(), $expressionFunction->getEvaluator()); - } - - if (\is_array($expressionFunction) === false) { - throw new InvalidArgumentException(\sprintf( - '%s::create expects either %s or array, %s given', - self::class, - ExpressionFunctionInterface::class, - \gettype($expressionFunction) - )); - } - - // ['name' => 'myFunction', 'evaluator' => function () {}, 'description' => 'Optional text'] - if (\is_string($expressionFunction['name'] ?? null) && \is_callable($expressionFunction['evaluator'] ?? null)) { - return new ExpressionFunction( - $expressionFunction['name'], - $expressionFunction['evaluator'], - $expressionFunction['description'] ?? null - ); - } - - // ['myFunction', function () {}, 'Optional text'] - if (\is_string($expressionFunction[0] ?? null) && \is_callable($expressionFunction[1] ?? null)) { - return new ExpressionFunction( - $expressionFunction[0], - $expressionFunction[1], - $expressionFunction[2] ?? null - ); - } - - throw new InvalidArgumentException(\sprintf( - '%s::create called with array expects either "[\'name\' => \'myFunction\', - \'evaluator\' => function () {}]" or "[\'myFunction\', function () {}]"', - self::class - )); - } -} diff --git a/packages/EasyDecision/packages/expressions/src/ExpressionLanguage.php b/packages/EasyDecision/packages/expressions/src/ExpressionLanguage.php index aaab7771f..e1c9fddaf 100644 --- a/packages/EasyDecision/packages/expressions/src/ExpressionLanguage.php +++ b/packages/EasyDecision/packages/expressions/src/ExpressionLanguage.php @@ -7,7 +7,6 @@ use EonX\EasyDecision\Exceptions\InvalidExpressionException; use EonX\EasyDecision\Expressions\Exceptions\ExpressionLanguageLockedException; use EonX\EasyDecision\Expressions\Interfaces\ExpressionFunctionInterface; -use EonX\EasyDecision\Expressions\Interfaces\ExpressionLanguageFactoryInterface; use EonX\EasyDecision\Expressions\Interfaces\ExpressionLanguageInterface; use EonX\EasyUtils\CollectorHelper; use Psr\Cache\CacheItemPoolInterface; @@ -31,29 +30,11 @@ final class ExpressionLanguage implements ExpressionLanguageInterface */ private $functions = []; - /** - * @var null|\Symfony\Component\ExpressionLanguage\ExpressionLanguage - */ - private $legacyExpressionLanguage; - /** * @var bool */ private $locked = false; - public function __construct(?BaseExpressionLanguage $expressionLanguage = null) - { - if ($expressionLanguage !== null) { - @\trigger_error(\sprintf( - 'Passing %s in %s constructor is deprecated since 2.3.7 and will be removed in 3.0.', - ExpressionLanguageFactoryInterface::class, - static::class - ), \E_USER_DEPRECATED); - } - - $this->legacyExpressionLanguage = $expressionLanguage; - } - public function addFunction(ExpressionFunctionInterface $function): ExpressionLanguageInterface { $this->isLocked(__METHOD__); @@ -170,7 +151,7 @@ private function getExpressionLanguage(): BaseExpressionLanguage $this->locked = true; // Legacy to be removed in 3.0 - $expressionLanguage = $this->legacyExpressionLanguage ?? new BaseExpressionLanguage($this->cache); + $expressionLanguage = new BaseExpressionLanguage($this->cache); foreach ($this->functions as $function) { $expressionLanguage->register( diff --git a/packages/EasyDecision/packages/expressions/src/ExpressionLanguageConfig.php b/packages/EasyDecision/packages/expressions/src/ExpressionLanguageConfig.php deleted file mode 100644 index 2beeda0ae..000000000 --- a/packages/EasyDecision/packages/expressions/src/ExpressionLanguageConfig.php +++ /dev/null @@ -1,64 +0,0 @@ -expressionLanguage = $expressionLanguage; - $this->providers = $providers; - $this->functions = $functions; - } - - public function getBaseExpressionLanguage(): ?BaseExpressionLanguage - { - return $this->expressionLanguage; - } - - /** - * @return null|mixed[] - */ - public function getFunctionProviders(): ?array - { - return $this->providers; - } - - /** - * @return null|mixed[] - */ - public function getFunctions(): ?array - { - return $this->functions; - } -} diff --git a/packages/EasyDecision/packages/expressions/src/ExpressionLanguageFactory.php b/packages/EasyDecision/packages/expressions/src/ExpressionLanguageFactory.php index 76705e865..3f7096b50 100644 --- a/packages/EasyDecision/packages/expressions/src/ExpressionLanguageFactory.php +++ b/packages/EasyDecision/packages/expressions/src/ExpressionLanguageFactory.php @@ -4,60 +4,13 @@ namespace EonX\EasyDecision\Expressions; -use EonX\EasyDecision\Expressions\Interfaces\ExpressionFunctionFactoryInterface; -use EonX\EasyDecision\Expressions\Interfaces\ExpressionLanguageConfigInterface; use EonX\EasyDecision\Expressions\Interfaces\ExpressionLanguageFactoryInterface; use EonX\EasyDecision\Expressions\Interfaces\ExpressionLanguageInterface; -use EonX\EasyDecision\Interfaces\DecisionConfiguratorInterface; final class ExpressionLanguageFactory implements ExpressionLanguageFactoryInterface { - /** - * @var null|\EonX\EasyDecision\Expressions\Interfaces\ExpressionFunctionFactoryInterface - */ - private $functionFactory; - - public function __construct(?ExpressionFunctionFactoryInterface $functionFactory = null) - { - if ($functionFactory !== null) { - @\trigger_error(\sprintf( - 'Passing %s in %s constructor is deprecated since 2.3.7 and will be removed in 3.0. Use a %s instead', - ExpressionFunctionFactoryInterface::class, - static::class, - DecisionConfiguratorInterface::class - ), \E_USER_DEPRECATED); - } - - $this->functionFactory = $functionFactory; - } - - public function create(?ExpressionLanguageConfigInterface $config = null): ExpressionLanguageInterface + public function create(): ExpressionLanguageInterface { - if ($config === null) { - return new ExpressionLanguage(); - } - - @\trigger_error(\sprintf( - 'Passing %s in %s::create() is deprecated since 2.3.7 and will be removed in 3.0. Use a %s instead', - ExpressionLanguageConfigInterface::class, - static::class, - DecisionConfiguratorInterface::class - ), \E_USER_DEPRECATED); - - $expressionLanguage = new ExpressionLanguage($config->getBaseExpressionLanguage()); - - if ($this->functionFactory !== null) { - foreach ($config->getFunctions() ?? [] as $function) { - $expressionLanguage->addFunction($this->functionFactory->create($function)); - } - - foreach ($config->getFunctionProviders() ?? [] as $provider) { - foreach ($provider->getFunctions() as $function) { - $expressionLanguage->addFunction($this->functionFactory->create($function)); - } - } - } - - return $expressionLanguage; + return new ExpressionLanguage(); } } diff --git a/packages/EasyDecision/packages/expressions/src/Interfaces/ExpressionFunctionFactoryInterface.php b/packages/EasyDecision/packages/expressions/src/Interfaces/ExpressionFunctionFactoryInterface.php deleted file mode 100644 index 171125f7c..000000000 --- a/packages/EasyDecision/packages/expressions/src/Interfaces/ExpressionFunctionFactoryInterface.php +++ /dev/null @@ -1,16 +0,0 @@ - 'cap', - 'evaluator' => function ($arguments, $value, $max) { - return \min($value, $max); - }, - ]; - - $function = $this->getFactory() - ->create($input); - - self::assertEquals($input['name'], $function->getName()); - self::assertEquals($input['evaluator'], $function->getEvaluator()); - } - - public function testCreateFromBaseExpressionFunction(): void - { - $baseExpressionFunction = BaseExpressionFunction::fromPhp('max'); - - self::assertEquals('max', $this->getFactory()->create($baseExpressionFunction)->getName()); - } - - public function testCreateFromSimpleArraySuccessfully(): void - { - $input = ['cap', function ($arguments, $value, $max) { - return \min($value, $max); - }]; - - $function = $this->getFactory() - ->create($input); - - self::assertEquals($input[0], $function->getName()); - self::assertEquals($input[1], $function->getEvaluator()); - } - - public function testInstanceOfExpressionFunctionReturnItAsItIs(): void - { - $expressionFunction = new ExpressionFunction('function', function (): void { - }); - - self::assertEquals( - \spl_object_hash($expressionFunction), - \spl_object_hash($this->getFactory()->create($expressionFunction)) - ); - } - - public function testInvalidArrayInputException(): void - { - $this->expectException(InvalidArgumentException::class); - - $this->getFactory() - ->create([]); - } - - public function testNonArrayInputException(): void - { - $this->expectException(InvalidArgumentException::class); - - $this->getFactory() - ->create('non-array'); - } - - private function getFactory(): ExpressionFunctionFactoryInterface - { - return new ExpressionFunctionFactory(); - } -} diff --git a/packages/EasyDecision/packages/expressions/tests/ExpressionLanguageFactoryTest.php b/packages/EasyDecision/packages/expressions/tests/ExpressionLanguageFactoryTest.php index fbf834277..c1023b024 100644 --- a/packages/EasyDecision/packages/expressions/tests/ExpressionLanguageFactoryTest.php +++ b/packages/EasyDecision/packages/expressions/tests/ExpressionLanguageFactoryTest.php @@ -4,29 +4,20 @@ namespace EonX\EasyDecision\Expressions\Tests; -use EonX\EasyDecision\Expressions\ExpressionLanguageConfig; +use EonX\EasyDecision\Expressions\ExpressionFunction; use EonX\EasyDecision\Tests\AbstractTestCase; -use EonX\EasyDecision\Tests\Stubs\ExpressionFunctionProviderStub; +use Symfony\Component\ExpressionLanguage\ExpressionFunction as BaseExpressionFunction; final class ExpressionLanguageFactoryTest extends AbstractTestCase { public function testCreateWithFunctions(): void { - $expressionLanguage = $this->createExpressionLanguage(new ExpressionLanguageConfig( - null, - null, - (new ExpressionFunctionProviderStub())->getFunctions() - )); - - self::assertEquals(4, $expressionLanguage->evaluate('max(1,2) + min(2,3)')); - } - - public function testCreateWithProvider(): void - { - $expressionLanguage = $this->createExpressionLanguage(new ExpressionLanguageConfig( - null, - [new ExpressionFunctionProviderStub()] - )); + $expressionLanguage = $this + ->createExpressionLanguage() + ->addFunctions([ + new ExpressionFunction('min', BaseExpressionFunction::fromPhp('min')->getEvaluator()), + new ExpressionFunction('max', BaseExpressionFunction::fromPhp('max')->getEvaluator()), + ]); self::assertEquals(4, $expressionLanguage->evaluate('max(1,2) + min(2,3)')); } diff --git a/packages/EasyDecision/packages/expressions/tests/ExpressionLanguageTest.php b/packages/EasyDecision/packages/expressions/tests/ExpressionLanguageTest.php index 2c587d987..f40f6486a 100644 --- a/packages/EasyDecision/packages/expressions/tests/ExpressionLanguageTest.php +++ b/packages/EasyDecision/packages/expressions/tests/ExpressionLanguageTest.php @@ -9,10 +9,9 @@ use EonX\EasyDecision\Expressions\ExpressionFunction; use EonX\EasyDecision\Expressions\ExpressionLanguage; use EonX\EasyDecision\Expressions\Interfaces\ExpressionLanguageInterface; -use EonX\EasyDecision\Helpers\FromPhpExpressionFunctionProvider; use EonX\EasyDecision\Tests\AbstractTestCase; use Symfony\Component\Cache\Adapter\ArrayAdapter; -use Symfony\Component\ExpressionLanguage\ExpressionLanguage as BaseExpressionLanguage; +use Symfony\Component\ExpressionLanguage\ExpressionFunction as BaseExpressionFunction; final class ExpressionLanguageTest extends AbstractTestCase { @@ -41,14 +40,6 @@ public function testAddRemoveFunctions(): void self::assertEquals('my-description', $functions[1]->getDescription()); } - public function testDeprecatedConstructorArgument(): void - { - $expressionLanguage = new ExpressionLanguage(new BaseExpressionLanguage()); - $expressionLanguage->addFunctions((new FromPhpExpressionFunctionProvider(['min', 'max']))->getFunctions()); - - self::assertEquals(2, $expressionLanguage->evaluate('max(1, 2)')); - } - public function testExpressionLanguageLocked(): void { $this->expectException(ExpressionLanguageLockedException::class); @@ -85,7 +76,10 @@ public function testValidateValidExpression(): void private function getExpressionLanguage(): ExpressionLanguageInterface { $expressionLanguage = new ExpressionLanguage(); - $expressionLanguage->addFunctions((new FromPhpExpressionFunctionProvider(['min', 'max']))->getFunctions()); + $expressionLanguage->addFunctions([ + new ExpressionFunction('min', BaseExpressionFunction::fromPhp('min')->getEvaluator()), + new ExpressionFunction('max', BaseExpressionFunction::fromPhp('max')->getEvaluator()), + ]); return $expressionLanguage; } diff --git a/packages/EasyDecision/src/Bridge/BridgeConstantsInterface.php b/packages/EasyDecision/src/Bridge/BridgeConstantsInterface.php new file mode 100644 index 000000000..492a83e79 --- /dev/null +++ b/packages/EasyDecision/src/Bridge/BridgeConstantsInterface.php @@ -0,0 +1,18 @@ +config = $config; - $this->container = $container; - $this->decorated = $decorated; - } - - /** - * @param mixed[]|null $params - */ - public function create(string $decision, ?array $params = null): DecisionInterface - { - $config = $this->config['decisions'][$decision] ?? null; - - if ($config === null) { - throw new InvalidArgumentException(\sprintf('No decision configured for "%s"', $decision)); - } - - if (\is_array($config)) { - return $this->doCreateForConfig($decision, $config, $params); - } - - if (\is_string($config) || $config instanceof DecisionConfigProviderInterface) { - return $this->doCreateForConfigProvider($decision, $config, $params); - } - - throw new InvalidArgumentException(\sprintf( - 'Config for decision "%s" must be either an array, a string or an instance of %s, "%s" given', - $decision, - DecisionConfigProviderInterface::class, - \gettype($config) - )); - } - - /** - * @param mixed[] $providers - * @param mixed[]|null $params - * @param null|mixed $defaultOutput - */ - private function doCreate( - string $decision, - string $type, - array $providers, - ?array $params = null, - $defaultOutput = null - ): DecisionInterface { - return $this->decorated->create( - new DecisionConfig( - $type, - $decision, - $this->getRuleProviders($providers), - $this->getExpressionLanguageConfigFactory() - ->create($decision), - $params, - $defaultOutput - ) - ); - } - - /** - * @param mixed[] $config - * @param mixed[]|null $params - */ - private function doCreateForConfig(string $decision, array $config, ?array $params = null): DecisionInterface - { - if (empty($config['providers'] ?? null)) { - throw new InvalidArgumentException(\sprintf('No rule providers configured for "%s"', $decision)); - } - if (empty($config['type'] ?? null)) { - throw new InvalidArgumentException(\sprintf('No decision type configured for "%s"', $decision)); - } - - return $this->doCreate( - $decision, - (string)$config['type'], - (array)$config['providers'], - $params, - $config['default_output'] ?? null - ); - } - - /** - * @param mixed $configProvider - * @param null|mixed[] $params - */ - private function doCreateForConfigProvider( - string $decision, - $configProvider, - ?array $params = null - ): DecisionInterface { - if (\is_string($configProvider)) { - $configProvider = $this->container->get($configProvider); - } - - if ($configProvider instanceof DecisionConfigProviderInterface) { - return $this->doCreate( - $decision, - $configProvider->getDecisionType(), - $configProvider->getRuleProviders(), - $params, - $configProvider->getDefaultOutput() - ); - } - - throw new InvalidArgumentException(\sprintf( - 'Decision config provider for "%s" must be an instance of "%s", "%s" given', - $decision, - DecisionConfigProviderInterface::class, - \gettype($configProvider) - )); - } - - private function getExpressionLanguageConfigFactory(): ExpressionLanguageConfigFactoryInterface - { - if ($this->expressionLanguageConfigFactory !== null) { - return $this->expressionLanguageConfigFactory; - } - - return $this->expressionLanguageConfigFactory = $this->container->get( - ExpressionLanguageConfigFactoryInterface::class - ); - } - - /** - * @param mixed[] $providers - * - * @return \EonX\EasyDecision\Interfaces\RuleProviderInterface[] - */ - private function getRuleProviders(array $providers): array - { - return \array_map(function ($provider): RuleProviderInterface { - if ($provider instanceof RuleProviderInterface) { - return $provider; - } - - return $this->container->get($provider); - }, $providers); - } -} diff --git a/packages/EasyDecision/src/Bridge/Common/ExpressionLanguageConfigFactory.php b/packages/EasyDecision/src/Bridge/Common/ExpressionLanguageConfigFactory.php deleted file mode 100644 index ee6b056ec..000000000 --- a/packages/EasyDecision/src/Bridge/Common/ExpressionLanguageConfigFactory.php +++ /dev/null @@ -1,145 +0,0 @@ -config = $config; - $this->container = $container; - } - - public function create(string $decision): ?ExpressionLanguageConfigInterface - { - $expressions = $this->getDecisionExpressions($decision); - $globals = $this->getGlobalExpressionFunctions(); - $expressionFunctions = $this->getExpressionFunctions($expressions['functions'], $expressions['providers']); - - if (empty($expressionFunctions) === false) { - return new ExpressionLanguageConfig(null, null, $expressionFunctions + $globals); - } - - return null; - } - - /** - * @return mixed[] - */ - private function getDecisionExpressions(string $decision): array - { - $config = $this->config['decisions'][$decision] ?? []; - $functions = []; - $providers = []; - - if (\is_array($config)) { - $functions = $config['expressions']['functions'] ?? []; - $providers = $config['expressions']['providers'] ?? []; - } - - if ($config instanceof DecisionConfigProviderInterface) { - $functions = $config->getExpressionFunctions(); - $providers = $config->getExpressionFunctionProviders(); - } - - return \compact('functions', 'providers'); - } - - private function getExpressionFunctionFactory(): ExpressionFunctionFactoryInterface - { - if ($this->expressionFunctionFactory !== null) { - return $this->expressionFunctionFactory; - } - - return $this->expressionFunctionFactory = $this->container->get(ExpressionFunctionFactoryInterface::class); - } - - /** - * @param mixed $provider - */ - private function getExpressionFunctionProvider($provider): ExpressionFunctionProviderInterface - { - if ($provider instanceof ExpressionFunctionProviderInterface) { - return $provider; - } - - return $this->container->get($provider); - } - - /** - * @param mixed[] $functions - * @param mixed[] $providers - * - * @return \EonX\EasyDecision\Expressions\Interfaces\ExpressionFunctionInterface[] - */ - private function getExpressionFunctions(array $functions, array $providers): array - { - $functionFactory = $this->getExpressionFunctionFactory(); - $expressionFunctions = []; - - foreach ($functions as $function) { - $expressionFunctions[] = $functionFactory->create($function); - } - - foreach ($providers as $provider) { - foreach ($this->getExpressionFunctionProvider($provider)->getFunctions() as $function) { - $expressionFunctions[] = $functionFactory->create($function); - } - } - - return $expressionFunctions; - } - - /** - * @return \EonX\EasyDecision\Expressions\Interfaces\ExpressionFunctionInterface[] - */ - private function getGlobalExpressionFunctions(): array - { - if ($this->globalExpressionFunctions !== null) { - return $this->globalExpressionFunctions; - } - - $config = $this->config; - - return $this->globalExpressionFunctions = $this->getExpressionFunctions( - $config['expressions']['functions'] ?? [], - $config['expressions']['providers'] ?? [] - ); - } -} diff --git a/packages/EasyDecision/src/Bridge/Common/Interfaces/DecisionConfigProviderInterface.php b/packages/EasyDecision/src/Bridge/Common/Interfaces/DecisionConfigProviderInterface.php deleted file mode 100644 index 1f3687a95..000000000 --- a/packages/EasyDecision/src/Bridge/Common/Interfaces/DecisionConfigProviderInterface.php +++ /dev/null @@ -1,33 +0,0 @@ -mergeConfigFrom(__DIR__ . '/config/easy-decision.php', 'easy-decision'); - $this->app->tag(\config('easy-decision.rules', []), [TagsInterface::DECISION_RULE]); + $this->app->tag(\config('easy-decision.rules', []), [BridgeConstantsInterface::TAG_DECISION_RULE]); + + $this->app->singleton( + ExpressionLanguageFactoryInterface::class, + function (): ExpressionLanguageFactoryInterface { + return new ExpressionLanguageFactory(); + } + ); $this->app->singleton( AddRulesDecisionConfigurator::class, function (): DecisionConfiguratorInterface { - return new AddRulesDecisionConfigurator($this->app->tagged(TagsInterface::DECISION_RULE)); + return new AddRulesDecisionConfigurator($this->app->tagged( + BridgeConstantsInterface::TAG_DECISION_RULE + )); } ); @@ -58,7 +61,7 @@ function (): DecisionConfiguratorInterface { $defaultConfigurators[] = SetExpressionLanguageConfigurator::class; } - $this->app->tag($defaultConfigurators, [TagsInterface::DECISION_CONFIGURATOR]); + $this->app->tag($defaultConfigurators, [BridgeConstantsInterface::TAG_DECISION_CONFIGURATOR]); $this->app->singleton(MappingProviderInterface::class, static function (): MappingProviderInterface { return new ConfigMappingProvider(\config('easy-decision.type_mapping', [])); @@ -67,47 +70,10 @@ function (): DecisionConfiguratorInterface { $this->app->singleton(BaseDecisionFactoryInterface::class, function (): BaseDecisionFactoryInterface { return new BaseDecisionFactory( $this->app->make(MappingProviderInterface::class), - null, - $this->app->tagged(TagsInterface::DECISION_CONFIGURATOR) + $this->app->tagged(BridgeConstantsInterface::TAG_DECISION_CONFIGURATOR) ); }); $this->app->singleton(ExpressionLanguageRuleFactoryInterface::class, ExpressionLanguageRuleFactory::class); - - $this->registerDeprecatedServices(); - } - - private function registerDeprecatedServices(): void - { - $this->app->singleton(ExpressionFunctionFactoryInterface::class, ExpressionFunctionFactory::class); - - $this->app->singleton( - ExpressionLanguageConfigFactoryInterface::class, - function (): ExpressionLanguageConfigFactoryInterface { - return new ExpressionLanguageConfigFactory(\config('easy-decision', []), $this->app); - } - ); - - $this->app->singleton( - ExpressionLanguageFactoryInterface::class, - function (): ExpressionLanguageFactoryInterface { - return new ExpressionLanguageFactory($this->app->make(ExpressionFunctionFactoryInterface::class)); - } - ); - - $this->app->singleton(DecisionFactoryInterface::class, function (): DecisionFactoryInterface { - @\trigger_error(\sprintf( - 'Using %s is deprecated since 2.3.7 and will be removed in 3.0, use %s instead', - DecisionFactoryInterface::class, - BaseDecisionFactoryInterface::class - ), \E_USER_DEPRECATED); - - $baseFactory = new BaseDecisionFactory( - $this->app->make(MappingProviderInterface::class), - $this->app->make(ExpressionLanguageFactoryInterface::class) - ); - - return new BridgeDecisionFactory(\config('easy-decision', []), $this->app, $baseFactory); - }); } } diff --git a/packages/EasyDecision/src/Bridge/Symfony/DependencyInjection/EasyDecisionExtension.php b/packages/EasyDecision/src/Bridge/Symfony/DependencyInjection/EasyDecisionExtension.php index e22823d43..ef6f4f397 100644 --- a/packages/EasyDecision/src/Bridge/Symfony/DependencyInjection/EasyDecisionExtension.php +++ b/packages/EasyDecision/src/Bridge/Symfony/DependencyInjection/EasyDecisionExtension.php @@ -4,7 +4,7 @@ namespace EonX\EasyDecision\Bridge\Symfony\DependencyInjection; -use EonX\EasyDecision\Bridge\Interfaces\TagsInterface; +use EonX\EasyDecision\Bridge\BridgeConstantsInterface; use EonX\EasyDecision\Interfaces\DecisionConfiguratorInterface; use EonX\EasyDecision\Interfaces\MappingProviderInterface; use EonX\EasyDecision\Interfaces\RuleInterface; @@ -35,11 +35,11 @@ public function load(array $configs, ContainerBuilder $container): void $container ->registerForAutoconfiguration(DecisionConfiguratorInterface::class) - ->addTag(TagsInterface::DECISION_CONFIGURATOR); + ->addTag(BridgeConstantsInterface::TAG_DECISION_CONFIGURATOR); $container ->registerForAutoconfiguration(RuleInterface::class) - ->addTag(TagsInterface::DECISION_RULE); + ->addTag(BridgeConstantsInterface::TAG_DECISION_RULE); $container ->autowire(MappingProviderInterface::class, ConfigMappingProvider::class) diff --git a/packages/EasyDecision/src/Bridge/Symfony/Resources/config/services.php b/packages/EasyDecision/src/Bridge/Symfony/Resources/config/services.php index 70b475b80..88949a7f1 100644 --- a/packages/EasyDecision/src/Bridge/Symfony/Resources/config/services.php +++ b/packages/EasyDecision/src/Bridge/Symfony/Resources/config/services.php @@ -2,7 +2,7 @@ declare(strict_types=1); -use EonX\EasyDecision\Bridge\Interfaces\TagsInterface; +use EonX\EasyDecision\Bridge\BridgeConstantsInterface; use EonX\EasyDecision\Bridge\Symfony\DataCollector\DecisionDataCollector; use EonX\EasyDecision\Configurators\AddRulesDecisionConfigurator; use EonX\EasyDecision\Decisions\DecisionFactory; @@ -23,7 +23,7 @@ ->autoconfigure(); $services->set(AddRulesDecisionConfigurator::class) - ->arg('$rules', tagged_iterator(TagsInterface::DECISION_RULE)); + ->arg('$rules', tagged_iterator(BridgeConstantsInterface::TAG_DECISION_RULE)); $services->set(DecisionFactoryInterface::class, DecisionFactory::class) ->arg('$configurators', tagged_iterator('easy_decision.decision_configurator')); diff --git a/packages/EasyDecision/src/Bridge/Symfony/Resources/config/use_expression_language.php b/packages/EasyDecision/src/Bridge/Symfony/Resources/config/use_expression_language.php index bf636df96..e26a1d429 100644 --- a/packages/EasyDecision/src/Bridge/Symfony/Resources/config/use_expression_language.php +++ b/packages/EasyDecision/src/Bridge/Symfony/Resources/config/use_expression_language.php @@ -12,14 +12,15 @@ return static function (ContainerConfigurator $containerConfigurator): void { $services = $containerConfigurator->services(); - $services->defaults() ->autowire() ->autoconfigure(); - $services->set(ExpressionLanguageInterface::class, ExpressionLanguage::class) + $services + ->set(ExpressionLanguageInterface::class, ExpressionLanguage::class) ->factory([ref(ExpressionLanguageFactoryInterface::class), 'create']); - $services->set(SetExpressionLanguageConfigurator::class) + $services + ->set(SetExpressionLanguageConfigurator::class) ->arg('$priority', -5000); }; diff --git a/packages/EasyDecision/src/Decisions/DecisionConfig.php b/packages/EasyDecision/src/Decisions/DecisionConfig.php deleted file mode 100644 index d7749bbc8..000000000 --- a/packages/EasyDecision/src/Decisions/DecisionConfig.php +++ /dev/null @@ -1,104 +0,0 @@ -decisionType = $decisionType; - $this->name = $name; - $this->ruleProviders = $ruleProviders; - $this->expressionLanguageConfig = $config; - $this->params = $params; - $this->defaultOutput = $defaultOutput; - } - - public function getDecisionType(): string - { - return $this->decisionType; - } - - /** - * @return null|mixed - */ - public function getDefaultOutput() - { - return $this->defaultOutput; - } - - public function getExpressionLanguageConfig(): ?ExpressionLanguageConfigInterface - { - return $this->expressionLanguageConfig; - } - - public function getName(): string - { - return $this->name; - } - - /** - * @return null|mixed[] - */ - public function getParams(): ?array - { - return $this->params; - } - - /** - * @return \EonX\EasyDecision\Interfaces\RuleProviderInterface[] - */ - public function getRuleProviders(): array - { - return $this->ruleProviders; - } -} diff --git a/packages/EasyDecision/src/Decisions/DecisionFactory.php b/packages/EasyDecision/src/Decisions/DecisionFactory.php index bea7038cd..ec94ccc87 100644 --- a/packages/EasyDecision/src/Decisions/DecisionFactory.php +++ b/packages/EasyDecision/src/Decisions/DecisionFactory.php @@ -4,23 +4,12 @@ namespace EonX\EasyDecision\Decisions; -use EonX\EasyDecision\Configurators\AddRulesConfigurator; -use EonX\EasyDecision\Configurators\SetDefaultOutputConfigurator; -use EonX\EasyDecision\Configurators\SetExpressionLanguageConfigurator; -use EonX\EasyDecision\Configurators\SetNameConfigurator; -use EonX\EasyDecision\Exceptions\InvalidDecisionException; -use EonX\EasyDecision\Exceptions\InvalidRuleProviderException; -use EonX\EasyDecision\Expressions\ExpressionLanguageFactory; -use EonX\EasyDecision\Expressions\Interfaces\ExpressionLanguageFactoryInterface; -use EonX\EasyDecision\Interfaces\DecisionConfigInterface; use EonX\EasyDecision\Interfaces\DecisionConfiguratorInterface; use EonX\EasyDecision\Interfaces\DecisionFactoryInterface; use EonX\EasyDecision\Interfaces\DecisionInterface; use EonX\EasyDecision\Interfaces\MappingProviderInterface; use EonX\EasyDecision\Interfaces\RestrictedDecisionConfiguratorInterface; -use EonX\EasyDecision\Interfaces\RuleProviderInterface; use EonX\EasyUtils\CollectorHelper; -use Psr\Container\ContainerInterface; final class DecisionFactory implements DecisionFactoryInterface { @@ -34,21 +23,11 @@ final class DecisionFactory implements DecisionFactoryInterface */ private $configuredDecisions = []; - /** - * @var \Psr\Container\ContainerInterface - */ - private $container; - /** * @var mixed[] */ private $decisionConfigurators = []; - /** - * @var null|\EonX\EasyDecision\Expressions\Interfaces\ExpressionLanguageFactoryInterface - */ - private $expressionLanguageFactory; - /** * @var \EonX\EasyDecision\Interfaces\MappingProviderInterface */ @@ -57,69 +36,15 @@ final class DecisionFactory implements DecisionFactoryInterface /** * @param null|iterable $configurators */ - public function __construct( - MappingProviderInterface $mappingProvider, - ?ExpressionLanguageFactoryInterface $languageFactory = null, - ?iterable $configurators = null - ) { - if ($languageFactory !== null) { - @\trigger_error(\sprintf( - 'Passing %s in %s constructor is deprecated since 2.3.7 and will be removed in 3.0. Use a %s instead', - ExpressionLanguageFactoryInterface::class, - static::class, - DecisionConfiguratorInterface::class - ), \E_USER_DEPRECATED); - } - + public function __construct(MappingProviderInterface $mappingProvider, ?iterable $configurators = null) + { $this->mappingProvider = $mappingProvider; - $this->expressionLanguageFactory = $languageFactory; $this->configurators = CollectorHelper::orderLowerPriorityFirst( CollectorHelper::filterByClass($configurators ?? [], DecisionConfiguratorInterface::class) ); } - /** - * @deprecated since 2.3.7 - */ - public function create(DecisionConfigInterface $config): DecisionInterface - { - @\trigger_error(\sprintf( - '%s::%s() is deprecated since 2.3.7 and will be removed in 3.0, use one of %s methods instead', - static::class, - __METHOD__, - \implode(', ', [ - 'createAffirmativeDecision', - 'createConsensusDecision', - 'createUnanimousDecision', - 'createValueDecision', - ]) - ), \E_USER_DEPRECATED); - - $decision = $this->instantiateDecision($config->getDecisionType()); - - $this->configurators[] = new SetNameConfigurator($config->getName()); - $this->configurators[] = new SetDefaultOutputConfigurator($config->getDefaultOutput()); - $this->configurators[] = new SetExpressionLanguageConfigurator( - $this->expressionLanguageFactory ?? new ExpressionLanguageFactory() - ); - $params = $config->getParams(); - - foreach ($config->getRuleProviders() as $provider) { - if (($provider instanceof RuleProviderInterface) === false) { - throw new InvalidRuleProviderException(\sprintf( - 'RuleProvider "%s" does not implement %s', - \get_class($provider), - RuleProviderInterface::class - )); - } - - $this->configurators[] = new AddRulesConfigurator($provider->getRules($params)); - } - - return $this->configureDecision($decision); - } - public function createAffirmativeDecision(?string $name = null): DecisionInterface { return $this->configureDecision(new AffirmativeDecision($name)); @@ -163,14 +88,6 @@ public function reset(): void $this->configuredDecisions = []; } - /** - * @deprecated since 2.3.7 - */ - public function setContainer(ContainerInterface $container): void - { - $this->container = $container; - } - /** * @param \EonX\EasyDecision\Interfaces\DecisionConfiguratorInterface[] $configurators */ @@ -199,34 +116,4 @@ private function configureDecision(DecisionInterface $decision): DecisionInterfa return $decision; } - - /** - * @deprecated since 2.3.7 - */ - private function instantiateDecision(string $decisionType): DecisionInterface - { - $decision = null; - - try { - if ($this->container !== null && $this->container->has($decisionType)) { - $decision = $this->container->get($decisionType); - } - - if ($decision === null && \class_exists($decisionType)) { - $decision = new $decisionType(); - } - } catch (\Throwable $exception) { - throw new InvalidDecisionException(\sprintf('Unable to instantiate decision for type "%s"', $decisionType)); - } - - if ($decision instanceof DecisionInterface) { - return $decision; - } - - throw new InvalidDecisionException(\sprintf( - 'Configured decision "%s" does not implement %s', - $decisionType, - DecisionInterface::class - )); - } } diff --git a/packages/EasyDecision/src/Helpers/FromPhpExpressionFunctionProvider.php b/packages/EasyDecision/src/Helpers/FromPhpExpressionFunctionProvider.php deleted file mode 100644 index 6381dfe76..000000000 --- a/packages/EasyDecision/src/Helpers/FromPhpExpressionFunctionProvider.php +++ /dev/null @@ -1,61 +0,0 @@ -phpFunctions = $phpFunctions; - } - - /** - * @return mixed[] - */ - public function getFunctions(): array - { - $expressionFunctions = []; - - foreach ($this->phpFunctions as $phpFunction) { - $phpFunction = (array)$phpFunction; - - // ['function' => 'min', 'description' => 'Optional text'] - // or - // ['fn' => 'min', 'description' => 'Optional text'] - /** @var null|string $fn */ - $fn = $phpFunction['function'] ?? $phpFunction['fn'] ?? null; - if (\is_string($fn)) { - $base = BaseExpressionFunction::fromPhp($phpFunction['function'] ?? $phpFunction['fn']); - $description = $phpFunction['description'] ?? null; - - $expressionFunctions[] = new ExpressionFunction($base->getName(), $base->getEvaluator(), $description); - continue; - } - - // [0 => 'min', 1 => 'Optional text'] - if (\is_string($phpFunction[0] ?? null)) { - $base = BaseExpressionFunction::fromPhp($phpFunction[0]); - $description = $phpFunction[1] ?? null; - - $expressionFunctions[] = new ExpressionFunction($base->getName(), $base->getEvaluator(), $description); - continue; - } - } - - return $expressionFunctions; - } -} diff --git a/packages/EasyDecision/src/Helpers/ValueExpressionFunctionProvider.php b/packages/EasyDecision/src/Helpers/ValueExpressionFunctionProvider.php index 4eddcfab8..684457428 100644 --- a/packages/EasyDecision/src/Helpers/ValueExpressionFunctionProvider.php +++ b/packages/EasyDecision/src/Helpers/ValueExpressionFunctionProvider.php @@ -8,9 +8,8 @@ use EonX\EasyDecision\Exceptions\MissingValueIndexException; use EonX\EasyDecision\Expressions\ExpressionFunction; use EonX\EasyDecision\Expressions\Interfaces\ExpressionFunctionInterface; -use EonX\EasyDecision\Expressions\Interfaces\ExpressionFunctionProviderInterface; -final class ValueExpressionFunctionProvider implements ExpressionFunctionProviderInterface +final class ValueExpressionFunctionProvider { /** * @return mixed[] diff --git a/packages/EasyDecision/src/Interfaces/DecisionConfigInterface.php b/packages/EasyDecision/src/Interfaces/DecisionConfigInterface.php deleted file mode 100644 index e1bf502cd..000000000 --- a/packages/EasyDecision/src/Interfaces/DecisionConfigInterface.php +++ /dev/null @@ -1,34 +0,0 @@ -register(EasyDecisionServiceProvider::class); - $app->boot(); + $app->singleton(RulesConfiguratorStub::class); + $app->tag(RulesConfiguratorStub::class, [BridgeConstantsInterface::TAG_DECISION_CONFIGURATOR]); + return $this->app = $app; } diff --git a/packages/EasyDecision/tests/AbstractTestCase.php b/packages/EasyDecision/tests/AbstractTestCase.php index 2858911d6..a8d680722 100644 --- a/packages/EasyDecision/tests/AbstractTestCase.php +++ b/packages/EasyDecision/tests/AbstractTestCase.php @@ -4,10 +4,7 @@ namespace EonX\EasyDecision\Tests; -use EonX\EasyDecision\Expressions\ExpressionFunctionFactory; -use EonX\EasyDecision\Expressions\ExpressionLanguageConfig; use EonX\EasyDecision\Expressions\ExpressionLanguageFactory; -use EonX\EasyDecision\Expressions\Interfaces\ExpressionLanguageConfigInterface; use EonX\EasyDecision\Expressions\Interfaces\ExpressionLanguageFactoryInterface; use EonX\EasyDecision\Expressions\Interfaces\ExpressionLanguageInterface; use EonX\EasyDecision\Interfaces\DecisionInterface; @@ -34,11 +31,10 @@ abstract class AbstractTestCase extends TestCase */ private $languageRuleFactory; - protected function createExpressionLanguage( - ?ExpressionLanguageConfigInterface $config = null - ): ExpressionLanguageInterface { + protected function createExpressionLanguage(): ExpressionLanguageInterface + { return $this->getExpressionLanguageFactory() - ->create($config ?? new ExpressionLanguageConfig()); + ->create(); } protected function createFalseRule(string $name, ?int $priority = null): RuleInterface @@ -75,14 +71,12 @@ protected function getExpressionLanguageFactory(): ExpressionLanguageFactoryInte return $this->expressionLanguageFactory; } - return $this->expressionLanguageFactory = new ExpressionLanguageFactory(new ExpressionFunctionFactory()); + return $this->expressionLanguageFactory = new ExpressionLanguageFactory(); } - protected function injectExpressionLanguage( - DecisionInterface $decision, - ?ExpressionLanguageConfigInterface $config = null - ): void { - $decision->setExpressionLanguage($this->createExpressionLanguage($config)); + protected function injectExpressionLanguage(DecisionInterface $decision): void + { + $decision->setExpressionLanguage($this->createExpressionLanguage()); } protected function tearDown(): void diff --git a/packages/EasyDecision/tests/Bridge/Laravel/LaravelDecisionFactoryTest.php b/packages/EasyDecision/tests/Bridge/Laravel/LaravelDecisionFactoryTest.php index 7a9926e3b..9f65930ff 100644 --- a/packages/EasyDecision/tests/Bridge/Laravel/LaravelDecisionFactoryTest.php +++ b/packages/EasyDecision/tests/Bridge/Laravel/LaravelDecisionFactoryTest.php @@ -5,201 +5,16 @@ namespace EonX\EasyDecision\Tests\Bridge\Laravel; use EonX\EasyDecision\Decisions\AffirmativeDecision; -use EonX\EasyDecision\Decisions\ValueDecision; -use EonX\EasyDecision\Exceptions\InvalidArgumentException; -use EonX\EasyDecision\Exceptions\InvalidMappingException; -use EonX\EasyDecision\Expressions\Interfaces\ExpressionLanguageInterface; -use EonX\EasyDecision\Helpers\FromPhpExpressionFunctionProvider; -use EonX\EasyDecision\Interfaces\DecisionFactoryInterface; use EonX\EasyDecision\Tests\AbstractLumenTestCase; -use EonX\EasyDecision\Tests\Stubs\DecisionConfigProviderStub; -use EonX\EasyDecision\Tests\Stubs\RuleProviderStub; final class LaravelDecisionFactoryTest extends AbstractLumenTestCase { - public function testArrayConfigCreateDecisionSuccessfully(): void + public function testSanity(): void { - $this->setConfig([ - 'decisions' => [ - 'my-decision' => [ - 'providers' => [new RuleProviderStub()], - 'type' => AffirmativeDecision::class, - ], - ], - ]); - - self::assertInstanceOf(AffirmativeDecision::class, $this->getDecisionFactory()->create('my-decision')); - } - - public function testArrayConfigEmptyProvidersException(): void - { - $this->expectException(InvalidArgumentException::class); - - $this->setConfig([ - 'decisions' => [ - 'my-decision' => [ - 'providers' => '', - ], - ], - ]); - - $this->getDecisionFactory() - ->create('my-decision'); - } - - public function testArrayConfigEmptyType(): void - { - $this->expectException(InvalidArgumentException::class); - - $this->setConfig([ - 'decisions' => [ - 'my-decision' => [ - 'providers' => 'my-provider', - 'type' => '', - ], - ], - ]); - - $this->getDecisionFactory() - ->create('my-decision'); - } - - public function testCreateDecisionByNameThrowsInvalidMappingExceptionIfDecisionIsNotConfigured(): void - { - $this->expectException(InvalidMappingException::class); - $this->expectExceptionMessage('Decision for name "some-decision" is not configured'); - $factory = $this->getApplication() - ->get(DecisionFactoryInterface::class); - - $factory->createByName('some-decision'); - } - - public function testCreateDecisionByNameThrowsInvalidMappingExceptionIfClassIsNotValid(): void - { - $this->setConfig([ - 'type_mapping' => [ - 'some-decision' => 'NonexistentClass', - ], - ]); - $this->expectException(InvalidMappingException::class); - $this->expectExceptionMessage( - 'Decision class "NonexistentClass" for name "some-decision" is not a valid classname' + self::assertInstanceOf( + AffirmativeDecision::class, + $this->getDecisionFactory() + ->createAffirmativeDecision('my-decision') ); - $factory = $this->getApplication() - ->get(DecisionFactoryInterface::class); - - $factory->createByName('some-decision'); - } - - public function testCreateDecisionByNameSucceeds(): void - { - $this->setConfig([ - 'type_mapping' => [ - 'some-decision' => ValueDecision::class, - ], - ]); - $factory = $this->getApplication() - ->get(DecisionFactoryInterface::class); - - $decision = $factory->createByName('some-decision'); - - self::assertInstanceOf(ValueDecision::class, $decision); - } - - public function testCreateDecisionSuccessfullyWithRuleProviderFromContainer(): void - { - $this->getApplication() - ->instance(RuleProviderStub::class, new RuleProviderStub()); - - $this->setConfig([ - 'decisions' => [ - 'my-decision' => [ - 'providers' => RuleProviderStub::class, - 'type' => AffirmativeDecision::class, - ], - ], - ]); - - self::assertInstanceOf(AffirmativeDecision::class, $this->getDecisionFactory()->create('my-decision')); - } - - public function testCreateDecisionWithConfigurators(): void - { - $factory = $this->getApplication() - ->get(DecisionFactoryInterface::class); - $decision = $factory->createValueDecision(); - - self::assertInstanceOf(ValueDecision::class, $decision); - self::assertInstanceOf(ExpressionLanguageInterface::class, $decision->getExpressionLanguage()); - } - - public function testCreateWithProviderConfigWithExpressionFunctionsSuccessfully(): void - { - $this->getApplication() - ->instance('minPhpFunctionProvider', new FromPhpExpressionFunctionProvider(['min'])); - - $this->setConfig([ - 'decisions' => [ - 'my-decision' => new DecisionConfigProviderStub(), - 'my-decision-different' => new DecisionConfigProviderStub(), - ], - ]); - - $decisionFactory = $this->getDecisionFactory(); - $decision = $decisionFactory->create('my-decision'); - $decisionAgain = $decisionFactory->create('my-decision'); - $differentDecision = $decisionFactory->create('my-decision-different'); - - self::assertNotSame(\spl_object_hash($decision), \spl_object_hash($decisionAgain)); - self::assertEquals($decision->make([]), $differentDecision->make([])); - } - - public function testDecisionConfigProviderDoesntImplementInterfaceException(): void - { - $this->expectException(InvalidArgumentException::class); - - $this->getApplication() - ->instance('MyDecisionConfigProvider', new \stdClass()); - - $this->setConfig([ - 'decisions' => [ - 'my-decision' => 'MyDecisionConfigProvider', - ], - ]); - - $this->getDecisionFactory() - ->create('my-decision'); - } - - public function testInvalidConfigTypeException(): void - { - $this->expectException(InvalidArgumentException::class); - - $this->setConfig([ - 'decisions' => [ - 'my-decision' => 1, - ], - ]); - - $this->getDecisionFactory() - ->create('my-decision'); - } - - public function testNoConfigForDecisionException(): void - { - $this->expectException(InvalidArgumentException::class); - - $this->getDecisionFactory() - ->create('invalid'); - } - - /** - * @param mixed[] $config - */ - private function setConfig(array $config): void - { - $this->getApplication() - ->make('config') - ->set('easy-decision', $config); } } diff --git a/packages/EasyDecision/tests/Decisions/DecisionFactoryTest.php b/packages/EasyDecision/tests/Decisions/DecisionFactoryTest.php index a150dfc9b..ec7bc352e 100644 --- a/packages/EasyDecision/tests/Decisions/DecisionFactoryTest.php +++ b/packages/EasyDecision/tests/Decisions/DecisionFactoryTest.php @@ -4,30 +4,26 @@ namespace EonX\EasyDecision\Tests\Decisions; -use EonX\EasyDecision\Decisions\DecisionConfig; +use EonX\EasyDecision\Configurators\SetExpressionLanguageConfigurator; use EonX\EasyDecision\Decisions\DecisionFactory; use EonX\EasyDecision\Decisions\UnanimousDecision; -use EonX\EasyDecision\Exceptions\InvalidDecisionException; -use EonX\EasyDecision\Exceptions\InvalidRuleProviderException; -use EonX\EasyDecision\Expressions\ExpressionLanguageConfig; +use EonX\EasyDecision\Exceptions\InvalidMappingException; +use EonX\EasyDecision\Expressions\ExpressionLanguageFactory; use EonX\EasyDecision\Providers\ConfigMappingProvider; use EonX\EasyDecision\Tests\AbstractTestCase; use EonX\EasyDecision\Tests\Stubs\DecisionConfiguratorStub; -use EonX\EasyDecision\Tests\Stubs\RuleProviderStub; +use EonX\EasyDecision\Tests\Stubs\RulesConfiguratorStub; final class DecisionFactoryTest extends AbstractTestCase { public function testCreateDecisionSuccessfully(): void { - $config = new DecisionConfig( - UnanimousDecision::class, - 'my-decision', - [new RuleProviderStub()], - new ExpressionLanguageConfig() - ); + $configurators = [ + new RulesConfiguratorStub(), + new SetExpressionLanguageConfigurator(new ExpressionLanguageFactory()), + ]; $mappingProvider = new ConfigMappingProvider([]); - - $decision = (new DecisionFactory($mappingProvider, $this->getExpressionLanguageFactory()))->create($config); + $decision = (new DecisionFactory($mappingProvider, $configurators))->createUnanimousDecision(); $expected = [ 'true-1' => true, @@ -48,11 +44,11 @@ public function testGetConfiguredDecisions(): void $configurator1 = new DecisionConfiguratorStub('my-unanimous-decision'); $configurator2 = new DecisionConfiguratorStub('my-consensus-decision'); + $exprLanguageConfigurator = new SetExpressionLanguageConfigurator(new ExpressionLanguageFactory()); $decisionFactory = (new DecisionFactory( $mappingProvider, - $this->getExpressionLanguageFactory(), - new \ArrayIterator([$configurator1, $configurator2]) + new \ArrayIterator([$configurator1, $configurator2, $exprLanguageConfigurator]) )); $decision1 = $decisionFactory->createUnanimousDecision('my-unanimous-decision'); @@ -68,34 +64,8 @@ public function testGetConfiguredDecisions(): void public function testInvalidDecisionInMappingException(): void { - $this->expectException(InvalidDecisionException::class); + $this->expectException(InvalidMappingException::class); - $config = new DecisionConfig(\stdClass::class, 'my-decision', []); - $mappingProvider = new ConfigMappingProvider([]); - - (new DecisionFactory($mappingProvider, $this->getExpressionLanguageFactory()))->create($config); - } - - public function testInvalidRuleProviderException(): void - { - $this->expectException(InvalidRuleProviderException::class); - - $mappingProvider = new ConfigMappingProvider([]); - $config = new DecisionConfig(UnanimousDecision::class, 'my-decision', [new \stdClass()]); - - (new DecisionFactory($mappingProvider, $this->getExpressionLanguageFactory()))->create($config); - } - - public function testNotInMappingDecisionException(): void - { - $this->expectException(InvalidDecisionException::class); - - $mappingProvider = new ConfigMappingProvider([]); - - (new DecisionFactory($mappingProvider, $this->getExpressionLanguageFactory()))->create(new DecisionConfig( - '', - 'my-decision', - [] - )); + (new DecisionFactory(new ConfigMappingProvider([])))->createByName('my-decision'); } } diff --git a/packages/EasyDecision/tests/Decisions/DecisionWithExpressionLanguageTest.php b/packages/EasyDecision/tests/Decisions/DecisionWithExpressionLanguageTest.php index 896e2696e..f861a1299 100644 --- a/packages/EasyDecision/tests/Decisions/DecisionWithExpressionLanguageTest.php +++ b/packages/EasyDecision/tests/Decisions/DecisionWithExpressionLanguageTest.php @@ -7,7 +7,6 @@ use EonX\EasyDecision\Decisions\ValueDecision; use EonX\EasyDecision\Exceptions\UnableToMakeDecisionException; use EonX\EasyDecision\Expressions\ExpressionFunction; -use EonX\EasyDecision\Expressions\ExpressionLanguageConfig; use EonX\EasyDecision\Helpers\ValueExpressionFunctionProvider; use EonX\EasyDecision\Tests\AbstractTestCase; @@ -52,16 +51,18 @@ public function testSameDecisionWithDifferentInputs(): void $this->createLanguageRule('if(extra_param1 > 10).else(add(extra_param1))'), ]; - $providers = [new ValueExpressionFunctionProvider()]; - $functions = [ - new ExpressionFunction('cap', function ($arguments, $value, $max) { - return \min($value, $max); - }), - ]; - $decision = (new ValueDecision())->addRules($rules); + $expressionLanguage = $this->createExpressionLanguage(); + + $expressionLanguage->addFunction(new ExpressionFunction( + 'cap', + function ($arguments, $value, $max) { + return \min($value, $max); + } + )); + $expressionLanguage->addFunctions((new ValueExpressionFunctionProvider())->getFunctions()); - $this->injectExpressionLanguage($decision, new ExpressionLanguageConfig(null, $providers, $functions)); + $decision->setExpressionLanguage($expressionLanguage); $tests = [ [ diff --git a/packages/EasyDecision/tests/Decisions/DecisionsTest.php b/packages/EasyDecision/tests/Decisions/DecisionsTest.php index 1d43044d7..acdd2c64a 100644 --- a/packages/EasyDecision/tests/Decisions/DecisionsTest.php +++ b/packages/EasyDecision/tests/Decisions/DecisionsTest.php @@ -6,7 +6,6 @@ use EonX\EasyDecision\Decisions\ConsensusDecision; use EonX\EasyDecision\Decisions\ValueDecision; -use EonX\EasyDecision\Expressions\ExpressionLanguageConfig; use EonX\EasyDecision\Helpers\ValueExpressionFunctionProvider; use EonX\EasyDecision\Interfaces\DecisionInterface; use EonX\EasyDecision\Interfaces\RuleInterface; @@ -137,12 +136,13 @@ public function testDecisions( $expectedOutput, array $expectedRulesOutput ): void { - $this->injectExpressionLanguage( - $decision, - new ExpressionLanguageConfig(null, [new ValueExpressionFunctionProvider()]) - ); + $expressionLanguage = $this->createExpressionLanguage(); + $expressionLanguage->addFunctions((new ValueExpressionFunctionProvider())->getFunctions()); - $output = $decision->addRules($rules) + $decision->setExpressionLanguage($expressionLanguage); + + $output = $decision + ->addRules($rules) ->make($input); $context = $decision->getContext(); diff --git a/packages/EasyDecision/tests/Helpers/FromPhpExpressionFunctionProviderTest.php b/packages/EasyDecision/tests/Helpers/FromPhpExpressionFunctionProviderTest.php deleted file mode 100644 index 7221266a5..000000000 --- a/packages/EasyDecision/tests/Helpers/FromPhpExpressionFunctionProviderTest.php +++ /dev/null @@ -1,21 +0,0 @@ -getFunctions(); - - foreach ($phpFunctions as $key => $phpFunction) { - self::assertEquals($phpFunction, $expressionFunctions[$key]->getName()); - } - } -} diff --git a/packages/EasyDecision/tests/Stubs/DecisionConfigProviderStub.php b/packages/EasyDecision/tests/Stubs/DecisionConfigProviderStub.php deleted file mode 100644 index 1cf53048a..000000000 --- a/packages/EasyDecision/tests/Stubs/DecisionConfigProviderStub.php +++ /dev/null @@ -1,50 +0,0 @@ -functionFactory = new ExpressionFunctionFactory(); - } - - /** - * @return \EonX\EasyDecision\Expressions\Interfaces\ExpressionFunctionInterface[] - */ - public function getFunctions(): array - { - return [ - $this->functionFactory->create(BaseExpressionFunction::fromPhp('max')), - $this->functionFactory->create(BaseExpressionFunction::fromPhp('min')), - ]; - } -} diff --git a/packages/EasyDecision/tests/Stubs/RulesConfiguratorStub.php b/packages/EasyDecision/tests/Stubs/RulesConfiguratorStub.php new file mode 100644 index 000000000..5cbed5a0e --- /dev/null +++ b/packages/EasyDecision/tests/Stubs/RulesConfiguratorStub.php @@ -0,0 +1,21 @@ +addRules([ + new RuleStub('true-1', true), + new ExpressionLanguageRule('value === 1'), + new ExpressionLanguageRule('value < 2'), + ]); + } +} diff --git a/packages/EasyErrorHandler/composer.json b/packages/EasyErrorHandler/composer.json index 6e959907d..798d1aa49 100644 --- a/packages/EasyErrorHandler/composer.json +++ b/packages/EasyErrorHandler/composer.json @@ -5,12 +5,12 @@ "license": "MIT", "require": { "php": "^7.2", - "eonx-com/easy-logging": "^2.6", - "eonx-com/easy-utils": "^2.6", + "eonx-com/easy-logging": "^3.0", + "eonx-com/easy-utils": "^3.0", "nesbot/carbon": "^2.22" }, "require-dev": { - "eonx-com/easy-bugsnag": "^2.6", + "eonx-com/easy-bugsnag": "^3.0", "phpunit/phpunit": "^8.4 || ^9.5", "laravel/lumen-framework": "^5.5", "symfony/symfony": "^4.4 || ^5.1.5" @@ -29,7 +29,7 @@ "prefer-stable": true, "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "3.0-dev" } } } diff --git a/packages/EasyErrorHandler/src/Response/ErrorResponseFactory.php b/packages/EasyErrorHandler/src/Response/ErrorResponseFactory.php index 9c1fddd68..42f160151 100644 --- a/packages/EasyErrorHandler/src/Response/ErrorResponseFactory.php +++ b/packages/EasyErrorHandler/src/Response/ErrorResponseFactory.php @@ -14,7 +14,6 @@ final class ErrorResponseFactory implements ErrorResponseFactoryInterface { public function create(Request $request, ErrorResponseDataInterface $data): Response { - // TODO - Support more formats, using symfony serializer return new JsonResponse($data->getRawData(), $data->getStatusCode(), $data->getHeaders()); } } diff --git a/packages/EasyEventDispatcher/composer.json b/packages/EasyEventDispatcher/composer.json index 2296fea15..1b990c74c 100644 --- a/packages/EasyEventDispatcher/composer.json +++ b/packages/EasyEventDispatcher/composer.json @@ -23,7 +23,7 @@ }, "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "3.0-dev" } } } diff --git a/packages/EasyLock/composer.json b/packages/EasyLock/composer.json index c7fe36b37..cf9ed695c 100644 --- a/packages/EasyLock/composer.json +++ b/packages/EasyLock/composer.json @@ -25,7 +25,7 @@ }, "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "3.0-dev" } } } diff --git a/packages/EasyLogging/composer.json b/packages/EasyLogging/composer.json index 6c1fcb439..bbc0eed39 100644 --- a/packages/EasyLogging/composer.json +++ b/packages/EasyLogging/composer.json @@ -5,8 +5,7 @@ "license": "MIT", "require": { "php": "^7.2", - "eonx-com/externals": "^1.0 || ^2.0", - "eonx-com/easy-utils": "^2.6" + "eonx-com/easy-utils": "^3.0" }, "require-dev": { "phpunit/phpunit": "^8.4 || ^9.5", @@ -28,7 +27,7 @@ }, "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "3.0-dev" } } } diff --git a/packages/EasyLogging/src/Bridge/Laravel/BugsnagLoggingServiceProvider.php b/packages/EasyLogging/src/Bridge/Laravel/BugsnagLoggingServiceProvider.php deleted file mode 100644 index 6538e1667..000000000 --- a/packages/EasyLogging/src/Bridge/Laravel/BugsnagLoggingServiceProvider.php +++ /dev/null @@ -1,29 +0,0 @@ -app->singleton(ExternalLogClientInterface::class, function (): ExternalLogClientInterface { - return new BugsnagLogClient($this->app->get('bugsnag')); - }); - - $this->app->singleton(SqlLoggerInterface::class, function (): SqlLoggerInterface { - return new ExternalLogger( - $this->app->get(ExternalLogClientInterface::class), - \filter_var(\config('bugsnag.bindings', false), \FILTER_VALIDATE_BOOLEAN) - ); - }); - } -} diff --git a/packages/EasyLogging/src/Bridge/Laravel/config/easy-logging.php b/packages/EasyLogging/src/Bridge/Laravel/config/easy-logging.php index e06f5331c..10c2d2e5b 100644 --- a/packages/EasyLogging/src/Bridge/Laravel/config/easy-logging.php +++ b/packages/EasyLogging/src/Bridge/Laravel/config/easy-logging.php @@ -9,10 +9,12 @@ * Define the default channel name for the application. */ 'default_channel' => LoggerFactoryInterface::DEFAULT_CHANNEL, + /** * Enable/Disable the default stream handler. */ 'stream_handler' => true, + /** * The log level to set on the default stream handler, defaults to DEBUG. */ diff --git a/packages/EasyLogging/src/Bugsnag/BugsnagHandler.php b/packages/EasyLogging/src/Bugsnag/BugsnagHandler.php deleted file mode 100644 index aafca2047..000000000 --- a/packages/EasyLogging/src/Bugsnag/BugsnagHandler.php +++ /dev/null @@ -1,96 +0,0 @@ -client = $client; - } - - /** - * @param string[] $doNoReport - */ - public function setDoNotReport(array $doNoReport): self - { - $this->doNotReport = $doNoReport; - - return $this; - } - - /** - * @param mixed[] $record - */ - protected function write(array $record): void - { - // Notify exception if context exception exists - $exception = $record['context']['exception'] ?? null; - - if ($exception instanceof Throwable) { - // Do not combine if statements so we keep the notifyError feature if no exception in context - if ($this->shouldReport($exception)) { - $this->client->notifyException($exception, $this->getNotifyCallback($record)); - } - - return; - } - - $this->client->notifyError( - $record['message'] ?? 'Error Notification', - $record['formatted'] ?? '', - $this->getNotifyCallback($record) - ); - } - - /** - * @param mixed[] $record - */ - private function getNotifyCallback(array $record): \Closure - { - return static function (Report $report) use ($record): void { - $report->setSeverity(LogLevel::ERROR); - - $extra = $record['extra'] ?? null; - - if ($extra !== null) { - $report->setMetaData($extra); - } - }; - } - - private function shouldReport(\Throwable $throwable): bool - { - foreach ($this->doNotReport as $type) { - if (\is_a($throwable, $type)) { - return false; - } - } - - return true; - } -} diff --git a/packages/EasyLogging/src/Bugsnag/BugsnagLogClient.php b/packages/EasyLogging/src/Bugsnag/BugsnagLogClient.php deleted file mode 100644 index 0c93c04eb..000000000 --- a/packages/EasyLogging/src/Bugsnag/BugsnagLogClient.php +++ /dev/null @@ -1,48 +0,0 @@ -client = $client; - } - - public function clearBreadcrumbs(): void - { - $this->client->clearBreadcrumbs(); - } - - /** - * @param null|mixed[] $metaData Additional information about the breadcrumb - */ - public function leaveBreadcrumb(string $name, ?string $type = null, ?array $metaData = null): void - { - $this->client->leaveBreadcrumb($name, $type, $metaData ?? []); - } - - public function notifyError(string $name, string $message, ?callable $callback = null): void - { - $this->client->notifyError($name, $message, $callback); - } - - public function notifyException(Throwable $throwable, ?callable $callback = null): void - { - $this->client->notifyException($throwable, $callback); - } -} diff --git a/packages/EasyLogging/src/ContextModifiers/EntityValidationFailedExceptionContextModifier.php b/packages/EasyLogging/src/ContextModifiers/EntityValidationFailedExceptionContextModifier.php deleted file mode 100644 index 293e88704..000000000 --- a/packages/EasyLogging/src/ContextModifiers/EntityValidationFailedExceptionContextModifier.php +++ /dev/null @@ -1,28 +0,0 @@ -getErrors(); - } - - return $context; - } -} diff --git a/packages/EasyLogging/src/Doctrine/ExternalLogger.php b/packages/EasyLogging/src/Doctrine/ExternalLogger.php deleted file mode 100644 index ca814e225..000000000 --- a/packages/EasyLogging/src/Doctrine/ExternalLogger.php +++ /dev/null @@ -1,45 +0,0 @@ -client = $client; - $this->includeBindings = $includeBindings; - } - - public function register(EntityManagerInterface $em, Configuration $configuration): void - { - $logger = new ExternalSqlLogger( - $this->client, - $em->getConnection() - ->getDatabasePlatform() - ->getName(), - $this->includeBindings - ); - - $configuration->setSQLLogger($logger); - } -} diff --git a/packages/EasyLogging/src/Doctrine/ExternalSqlLogger.php b/packages/EasyLogging/src/Doctrine/ExternalSqlLogger.php deleted file mode 100644 index bb482c9f2..000000000 --- a/packages/EasyLogging/src/Doctrine/ExternalSqlLogger.php +++ /dev/null @@ -1,104 +0,0 @@ -client = $client; - $this->connectionName = $connectionName; - $this->includeBindings = $includeBindings; - - $this->params = []; - } - - /** - * @param string|mixed $sql The SQL to be executed. - * @param mixed[]|null $params The SQL parameters. - * @param int[]|string[]|null $types The SQL parameter types. - */ - public function startQuery($sql, ?array $params = null, ?array $types = null): void - { - // Store sql and bindings to be used in `stopQuery` - $this->sql = $sql; - - if ($this->includeBindings === true) { - $this->params = $params ?? []; - } - - // Used to calculate execution time. - $this->start = \microtime(true); - } - - public function stopQuery(): void - { - $this->client->leaveBreadcrumb('Query executed', Breadcrumb::PROCESS_TYPE, $this->formatQuery()); - } - - /** - * @return mixed[] - */ - private function formatQuery(): array - { - $data = [ - 'sql' => $this->sql, - ]; - - foreach ($this->params as $index => $binding) { - $data[\sprintf('binding %s', $index)] = $binding; - } - - $data['time'] = \sprintf('%sms', $this->getExecutionTimeInMs()); - $data['connection'] = $this->connectionName; - - return $data; - } - - private function getExecutionTimeInMs(): string - { - return \number_format((\microtime(true) - $this->start) * 1000, 2); - } -} diff --git a/packages/EasyLogging/src/Interfaces/ExceptionContextModifierInterface.php b/packages/EasyLogging/src/Interfaces/ExceptionContextModifierInterface.php deleted file mode 100644 index 8955617f8..000000000 --- a/packages/EasyLogging/src/Interfaces/ExceptionContextModifierInterface.php +++ /dev/null @@ -1,18 +0,0 @@ -handlers[] = $this->getHandler(); - - if (\class_exists('App\\Exceptions\\EntityValidationFailedException')) { - $this->exceptionContextModifiers = [new EntityValidationFailedExceptionContextModifier()]; - } - } - - public function addHandler(HandlerInterface $handler): void - { - $this->handlers[] = $handler; - } - - /** - * @param string $message - * @param null|mixed[] $context - */ - public function alert($message, ?array $context = null): void - { - $this->log('alert', $message, $context ?? []); - } - - /** - * @param string $message - * @param null|mixed[] $context - */ - public function critical($message, ?array $context = null): void - { - $this->log('critical', $message, $context ?? []); - } - - /** - * @param string $message - * @param null|mixed[] $context - */ - public function debug($message, ?array $context = null): void - { - $this->log('debug', $message, $context ?? []); - } - - /** - * @param string $message - * @param null|mixed[] $context - */ - public function emergency($message, ?array $context = null): void - { - $this->log('emergency', $message, $context ?? []); - } - - /** - * @param string $message - * @param null|mixed[] $context - */ - public function error($message, ?array $context = null): void - { - $this->log('error', $message, $context ?? []); - } - - /** - * @param null|mixed[] $context - */ - public function exception(Throwable $exception, ?string $level = null, ?array $context = null): void - { - $context = $context ?? []; - $context['exception_class'] = \get_class($exception); - $context['file'] = $exception->getFile(); - $context['line'] = $exception->getLine(); - $context['stack_trace'] = $exception->getTraceAsString(); - - $level = $level ?? 'error'; - - if ($exception instanceof InvalidApiResponseException) { - $response = $exception->getResponse(); - - $context['response'] = [ - 'headers' => $response->getHeaders(), - 'status_code' => $response->getStatusCode(), - 'content' => $response->getContent(), - ]; - } - - foreach ($this->exceptionContextModifiers as $modifier) { - $context = $modifier->modifyContext($exception, $context); - } - - $this->log($level, \sprintf('Exception caught: %s', $exception->getMessage()), $context); - } - - /** - * @param string $message - * @param null|mixed[] $context - */ - public function info($message, ?array $context = null): void - { - $this->log('info', $message, $context ?? []); - } - - /** - * @param string $level - * @param string $message - * @param null|mixed[] $context - */ - public function log($level, $message, ?array $context = null): void - { - try { - $callable = [$this->getLogger(), $level]; - - if (\is_callable($callable)) { - $callable($message, $context ?? []); - } - } catch (\Throwable $exception) { - /** @noinspection ForgottenDebugOutputInspection This is only a fallback if logger is unavailable */ - \error_log($exception->getMessage()); - } - } - - /** - * @param string $message - * @param null|mixed[] $context - */ - public function notice($message, ?array $context = null): void - { - $this->log('notice', $message, $context ?? []); - } - - public function setApp(Application $app): void - { - $serviceIds = [ - ExternalsLoggerInterface::class, - 'logger', - PsrLoggerInterface::class, - LoggerInterface::class, - ]; - - foreach ($serviceIds as $serviceId) { - $app->instance($serviceId, $this); - } - - $this->app = $app; - } - - /** - * @param string[] $doNotReport - */ - public function setBugsnagDoNotReport(array $doNotReport): void - { - $this->bugsnagDoNotReport = $doNotReport; - } - - /** - * @param \EonX\EasyLogging\Interfaces\ExceptionContextModifierInterface[] $modifiers - */ - public function setExceptionContextModifiers(array $modifiers): void - { - $this->exceptionContextModifiers = $modifiers; - } - - /** - * @param \Monolog\Processor\ProcessorInterface[] $processors - */ - public function setProcessors(array $processors): void - { - $this->processors = $processors; - } - - /** - * @param string $message - * @param null|mixed[] $context - */ - public function warning($message, ?array $context = null): void - { - $this->log('warning', $message, $context ?? []); - } - - private function getAppLogger(): PsrLoggerInterface - { - if ($this->appLogger !== null) { - return $this->appLogger; - } - - $handlers = $this->handlers; - - // Add Bugsnag handler only if enabled - if ($this->app->make('config')->get('bugsnag.enabled', false)) { - $bugsnag = new BugsnagHandler($this->app->get(ExternalLogClientInterface::class)); - - $this->handlers[] = $bugsnag->setDoNotReport($this->bugsnagDoNotReport); - } - - $processors = $this->processors ?? $this->getDefaultProcessors(); - - return $this->appLogger = new MonologLogger(self::APPLICATION, $handlers, $processors); - } - - /** - * @return \Monolog\Processor\ProcessorInterface[] - */ - private function getDefaultProcessors(): array - { - return [ - new WebProcessor(), - new IntrospectionProcessor(MonologLogger::DEBUG, [ - 'App\\Exceptions\\', - 'App\\Externals\\Libraries\\Logger', - 'Aws\\', - 'Elasticsearch\\', - 'EoneoPay\\Externals\\', - 'EoneoPay\\Framework\\', - 'EonX\\EasyLogging\\', - 'GuzzleHttp\\', - 'Illuminate\\', - 'Laravel\\', - 'React\\', - 'Symfony\\', - ]), - ]; - } - - private function getEmergencyLogger(): PsrLoggerInterface - { - if ($this->emergencyLogger !== null) { - return $this->emergencyLogger; - } - - return $this->emergencyLogger = new MonologLogger( - self::APPLICATION, - $this->handlers, - $this->processors ?? $this->getDefaultProcessors() - ); - } - - private function getHandler(): HandlerInterface - { - $handler = new StreamHandler('php://stderr'); - $handler->setFormatter(new SumoJsonFormatter()); - - return $handler; - } - - private function getLogger(): PsrLoggerInterface - { - return $this->app === null ? $this->getEmergencyLogger() : $this->getAppLogger(); - } -} diff --git a/packages/EasyNotification/composer.json b/packages/EasyNotification/composer.json index 49d5547e3..183affa48 100644 --- a/packages/EasyNotification/composer.json +++ b/packages/EasyNotification/composer.json @@ -6,7 +6,7 @@ "require": { "php": "^7.2", "aws/aws-sdk-php": "^3.134", - "eonx-com/easy-utils": "^2.6", + "eonx-com/easy-utils": "^3.0", "nette/utils": "^3.1", "symfony/http-client": "^4.4 || ^5.1.5" }, @@ -27,7 +27,7 @@ }, "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "3.0-dev" } } } diff --git a/packages/EasyPagination/composer.json b/packages/EasyPagination/composer.json index c6c6e18f5..8ea69e5c7 100644 --- a/packages/EasyPagination/composer.json +++ b/packages/EasyPagination/composer.json @@ -7,7 +7,7 @@ "php": "^7.2" }, "require-dev": { - "eonx-com/easy-psr7-factory": "^2.6", + "eonx-com/easy-psr7-factory": "^3.0", "phpunit/phpunit": "^8.4 || ^9.5", "laravel/lumen-framework": "^5.5", "vlucas/phpdotenv": "^3.3", @@ -26,7 +26,7 @@ }, "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "3.0-dev" } } } diff --git a/packages/EasyPagination/src/Interfaces/StartSizeDataResolverInterface.php b/packages/EasyPagination/src/Interfaces/StartSizeDataResolverInterface.php index 4bf68901a..ebc533f03 100644 --- a/packages/EasyPagination/src/Interfaces/StartSizeDataResolverInterface.php +++ b/packages/EasyPagination/src/Interfaces/StartSizeDataResolverInterface.php @@ -4,10 +4,9 @@ namespace EonX\EasyPagination\Interfaces; +use Symfony\Component\HttpFoundation\Request; + interface StartSizeDataResolverInterface { - /** - * @param \Symfony\Component\HttpFoundation\Request|\Psr\Http\Message\ServerRequestInterface $request - */ - public function resolve($request): StartSizeDataInterface; + public function resolve(Request $request): StartSizeDataInterface; } diff --git a/packages/EasyPagination/src/Resolvers/StartSizeAsArrayInQueryResolver.php b/packages/EasyPagination/src/Resolvers/StartSizeAsArrayInQueryResolver.php index eef2f58dd..27b188dd4 100644 --- a/packages/EasyPagination/src/Resolvers/StartSizeAsArrayInQueryResolver.php +++ b/packages/EasyPagination/src/Resolvers/StartSizeAsArrayInQueryResolver.php @@ -8,7 +8,7 @@ use EonX\EasyPagination\Interfaces\StartSizeDataInterface; use EonX\EasyPagination\Interfaces\StartSizeDataResolverInterface; use EonX\EasyPagination\Traits\DataResolverTrait; -use Psr\Http\Message\ServerRequestInterface; +use Symfony\Component\HttpFoundation\Request; final class StartSizeAsArrayInQueryResolver implements StartSizeDataResolverInterface { @@ -32,14 +32,9 @@ public function __construct(StartSizeConfigInterface $config, string $queryAttr) $this->queryAttr = $queryAttr; } - /** - * @param \Symfony\Component\HttpFoundation\Request|\Psr\Http\Message\ServerRequestInterface $request - */ - public function resolve($request): StartSizeDataInterface + public function resolve(Request $request): StartSizeDataInterface { - $queryAttr = $request instanceof ServerRequestInterface - ? $request->getQueryParams()[$this->queryAttr] ?? [] - : $request->query->get($this->queryAttr, []); + $queryAttr = $request->query->get($this->queryAttr, []); return $this->createStartSizeData($this->config, $queryAttr, $request); } diff --git a/packages/EasyPagination/src/Resolvers/StartSizeInQueryResolver.php b/packages/EasyPagination/src/Resolvers/StartSizeInQueryResolver.php index 112247523..a46252d70 100644 --- a/packages/EasyPagination/src/Resolvers/StartSizeInQueryResolver.php +++ b/packages/EasyPagination/src/Resolvers/StartSizeInQueryResolver.php @@ -8,7 +8,7 @@ use EonX\EasyPagination\Interfaces\StartSizeDataInterface; use EonX\EasyPagination\Interfaces\StartSizeDataResolverInterface; use EonX\EasyPagination\Traits\DataResolverTrait; -use Psr\Http\Message\ServerRequestInterface; +use Symfony\Component\HttpFoundation\Request; final class StartSizeInQueryResolver implements StartSizeDataResolverInterface { @@ -24,14 +24,9 @@ public function __construct(StartSizeConfigInterface $config) $this->config = $config; } - /** - * @param \Symfony\Component\HttpFoundation\Request|\Psr\Http\Message\ServerRequestInterface $request - */ - public function resolve($request): StartSizeDataInterface + public function resolve(Request $request): StartSizeDataInterface { - $queryParams = $request instanceof ServerRequestInterface - ? $request->getQueryParams() - : $request->query->all(); + $queryParams = $request->query->all(); return $this->createStartSizeData($this->config, $queryParams, $request); } diff --git a/packages/EasyPagination/src/Traits/DataResolverTrait.php b/packages/EasyPagination/src/Traits/DataResolverTrait.php index db93ccd04..e68dd6f6b 100644 --- a/packages/EasyPagination/src/Traits/DataResolverTrait.php +++ b/packages/EasyPagination/src/Traits/DataResolverTrait.php @@ -7,28 +7,18 @@ use EonX\EasyPagination\Data\StartSizeData; use EonX\EasyPagination\Interfaces\StartSizeConfigInterface; use EonX\EasyPagination\Interfaces\StartSizeDataInterface; -use Psr\Http\Message\ServerRequestInterface; use Symfony\Component\HttpFoundation\Request; trait DataResolverTrait { /** * @param mixed $data - * @param \Symfony\Component\HttpFoundation\Request|\Psr\Http\Message\ServerRequestInterface $request */ private function createStartSizeData( StartSizeConfigInterface $config, $data, - $request + Request $request ): StartSizeDataInterface { - if ($request instanceof ServerRequestInterface) { - @\trigger_error(\sprintf( - 'Passing $request as %s is deprecated since 2.4 and will not be supported in 3.0. Use %s instead.', - ServerRequestInterface::class, - Request::class - ), \E_USER_DEPRECATED); - } - if (\is_array($data) === false) { return new StartSizeData( $config->getStartDefault(), diff --git a/packages/EasyPagination/tests/AbstractTestCase.php b/packages/EasyPagination/tests/AbstractTestCase.php index 113478e3f..4fe4e3932 100644 --- a/packages/EasyPagination/tests/AbstractTestCase.php +++ b/packages/EasyPagination/tests/AbstractTestCase.php @@ -5,9 +5,7 @@ namespace EonX\EasyPagination\Tests; use EonX\EasyPagination\Resolvers\Config\StartSizeConfig; -use EonX\EasyPsr7Factory\EasyPsr7Factory; use PHPUnit\Framework\TestCase; -use Psr\Http\Message\ServerRequestInterface; use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\HttpFoundation\Request; @@ -34,13 +32,13 @@ protected function createConfig( /** * @param null|mixed[] $query */ - protected function createServerRequest(?array $query = null): ServerRequestInterface + protected function createServerRequest(?array $query = null): Request { $server = [ 'HTTP_HOST' => 'eonx.com', ]; - return (new EasyPsr7Factory())->createRequest(new Request($query ?? [], [], [], [], [], $server)); + return new Request($query ?? [], [], [], [], [], $server); } protected function tearDown(): void diff --git a/packages/EasyPipeline/composer.json b/packages/EasyPipeline/composer.json index b9bde5fd4..58c3d1cfc 100644 --- a/packages/EasyPipeline/composer.json +++ b/packages/EasyPipeline/composer.json @@ -27,7 +27,7 @@ }, "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "3.0-dev" } } } diff --git a/packages/EasyPsr7Factory/composer.json b/packages/EasyPsr7Factory/composer.json index 6ef0c48a0..a1f04c009 100644 --- a/packages/EasyPsr7Factory/composer.json +++ b/packages/EasyPsr7Factory/composer.json @@ -26,7 +26,7 @@ }, "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "3.0-dev" } } } diff --git a/packages/EasyRandom/composer.json b/packages/EasyRandom/composer.json index adb3b6897..6b741f428 100644 --- a/packages/EasyRandom/composer.json +++ b/packages/EasyRandom/composer.json @@ -26,7 +26,7 @@ }, "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "3.0-dev" } } } diff --git a/packages/EasyRepository/composer.json b/packages/EasyRepository/composer.json index 89f7cfeba..b4083df10 100644 --- a/packages/EasyRepository/composer.json +++ b/packages/EasyRepository/composer.json @@ -10,7 +10,7 @@ "phpunit/phpunit": "^8.4 || ^9.5", "mockery/mockery": "^1.2", "doctrine/orm": "^2.6", - "eonx-com/easy-pagination": "^2.6", + "eonx-com/easy-pagination": "^3.0", "laravel/lumen-framework": "^5.5", "vlucas/phpdotenv": "^3.3" }, @@ -33,7 +33,7 @@ "prefer-stable": true, "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "3.0-dev" } } } diff --git a/packages/EasyRepository/src/Implementations/Doctrine/ORM/AbstractPaginatedDoctrineOrmRepository.php b/packages/EasyRepository/src/Implementations/Doctrine/ORM/AbstractPaginatedDoctrineOrmRepository.php index 1fddee00e..ab69bd612 100644 --- a/packages/EasyRepository/src/Implementations/Doctrine/ORM/AbstractPaginatedDoctrineOrmRepository.php +++ b/packages/EasyRepository/src/Implementations/Doctrine/ORM/AbstractPaginatedDoctrineOrmRepository.php @@ -5,7 +5,6 @@ namespace EonX\EasyRepository\Implementations\Doctrine\ORM; use Doctrine\ORM\Query; -use Doctrine\ORM\Tools\Pagination\Paginator as DoctrinePaginator; use Doctrine\Persistence\ManagerRegistry; use EonX\EasyPagination\Interfaces\LengthAwarePaginatorInterface; use EonX\EasyPagination\Interfaces\StartSizeDataInterface; @@ -55,28 +54,4 @@ protected function createLengthAwarePaginator( $fromAlias ?? $this->getEntityAlias() ); } - - protected function doPaginate( - Query $query, - ?StartSizeDataInterface $startSizeData = null, - ?bool $fetchJoinCollection = null - ): LengthAwarePaginatorInterface { - @\trigger_error(\sprintf( - '%s::%s() is deprecated since 2.1.5 and will be removed in 3.0, use %s::%s() instead', - static::class, - __METHOD__, - static::class, - 'createLengthAwarePaginator' - ), \E_USER_DEPRECATED); - - $this->addPaginationToQuery($query, $startSizeData); - - $startSizeData = $startSizeData ?? $this->startSizeData; - - return new LengthAwareDoctrineOrmPaginator( - new DoctrinePaginator($query, $fetchJoinCollection ?? true), - $startSizeData->getStart(), - $startSizeData->getSize() - ); - } } diff --git a/packages/EasyRepository/src/Implementations/Doctrine/ORM/LengthAwareDoctrineOrmPaginator.php b/packages/EasyRepository/src/Implementations/Doctrine/ORM/LengthAwareDoctrineOrmPaginator.php deleted file mode 100644 index ad4716132..000000000 --- a/packages/EasyRepository/src/Implementations/Doctrine/ORM/LengthAwareDoctrineOrmPaginator.php +++ /dev/null @@ -1,49 +0,0 @@ - - */ - private $doctrinePaginator; - - /** - * @param \Doctrine\ORM\Tools\Pagination\Paginator $doctrinePaginator - */ - public function __construct(Paginator $doctrinePaginator, int $start, int $size) - { - @\trigger_error(\sprintf( - '%s is deprecated since 2.1.5 and will be removed in 3.0, use %s instead', - static::class, - 'EonX\EasyPagination\Paginators\DoctrineOrmLengthAwarePaginator' - ), \E_USER_DEPRECATED); - - $this->doctrinePaginator = $doctrinePaginator; - - parent::__construct(new StartSizeData($start, $size)); - } - - /** - * @return mixed[] - */ - public function getItems(): array - { - return \iterator_to_array($this->doctrinePaginator); - } - - public function getTotalItems(): int - { - return $this->doctrinePaginator->count(); - } -} diff --git a/packages/EasyRepository/tests/Implementation/Doctrine/ORM/LengthAwareDoctrineOrmPaginatorTest.php b/packages/EasyRepository/tests/Implementation/Doctrine/ORM/LengthAwareDoctrineOrmPaginatorTest.php deleted file mode 100644 index abe5c1c05..000000000 --- a/packages/EasyRepository/tests/Implementation/Doctrine/ORM/LengthAwareDoctrineOrmPaginatorTest.php +++ /dev/null @@ -1,46 +0,0 @@ - $doctrinePaginator */ - $doctrinePaginator = $this->mockDoctrinePaginator(); - $paginator = new LengthAwareDoctrineOrmPaginator($doctrinePaginator, 1, 2); - - self::assertCount(3, $paginator->getItems()); - self::assertEquals(3, $paginator->getTotalItems()); - self::assertEquals(1, $paginator->getCurrentPage()); - self::assertEquals(2, $paginator->getTotalPages()); - self::assertEquals(2, $paginator->getItemsPerPage()); - self::assertTrue($paginator->hasNextPage()); - self::assertFalse($paginator->hasPreviousPage()); - } - - private function mockDoctrinePaginator(): LegacyMockInterface - { - return $this->mock(DoctrinePaginator::class, function (LegacyMockInterface $paginator): void { - // 3 items - $items = [new \stdClass(), new \stdClass(), new \stdClass()]; - $iterator = new \ArrayIterator($items); - - $paginator->shouldReceive('getIterator') - ->once() - ->withNoArgs() - ->andReturn($iterator); - $paginator->shouldReceive('count') - ->once() - ->withNoArgs() - ->andReturn(\count($items)); - }); - } -} diff --git a/packages/EasyRequestId/composer.json b/packages/EasyRequestId/composer.json index 211592ecf..8bc47c1e3 100644 --- a/packages/EasyRequestId/composer.json +++ b/packages/EasyRequestId/composer.json @@ -5,8 +5,8 @@ "license": "MIT", "require": { "php": "^7.2", - "eonx-com/easy-random": "^2.6", - "eonx-com/easy-utils": "^2.6" + "eonx-com/easy-random": "^3.0", + "eonx-com/easy-utils": "^3.0" }, "require-dev": { "ramsey/uuid": "^3.9", @@ -26,7 +26,7 @@ }, "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "3.0-dev" } } } diff --git a/packages/EasySchedule/composer.json b/packages/EasySchedule/composer.json index a162f6ad7..cc9d87be9 100644 --- a/packages/EasySchedule/composer.json +++ b/packages/EasySchedule/composer.json @@ -8,7 +8,7 @@ "nesbot/carbon": "^2.22", "dragonmantank/cron-expression": "^2.3", "symfony/console": "^4.4 || ^5.1.5", - "eonx-com/easy-lock": "^2.6" + "eonx-com/easy-lock": "^3.0" }, "require-dev": { "phpunit/phpunit": "^8.4 || ^9.5", @@ -28,7 +28,7 @@ "prefer-stable": true, "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "3.0-dev" } } } diff --git a/packages/EasySecurity/composer.json b/packages/EasySecurity/composer.json index 9705e4432..1f98a1197 100644 --- a/packages/EasySecurity/composer.json +++ b/packages/EasySecurity/composer.json @@ -6,11 +6,11 @@ "require": { "php": "^7.2", "nette/utils": "^3.1", - "eonx-com/easy-api-token": "^2.6", - "eonx-com/easy-utils": "^2.6" + "eonx-com/easy-api-token": "^3.0", + "eonx-com/easy-utils": "^3.0" }, "require-dev": { - "eonx-com/easy-bugsnag": "^2.6", + "eonx-com/easy-bugsnag": "^3.0", "phpunit/phpunit": "^8.4 || ^9.5", "laravel/lumen-framework": "^5.5", "symfony/symfony": "^4.4 || ^5.1.5" @@ -27,7 +27,7 @@ }, "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "3.0-dev" } } } diff --git a/packages/EasySecurity/src/AbstractSecurityContextFactory.php b/packages/EasySecurity/src/AbstractSecurityContextFactory.php index 647049333..50b129a6b 100644 --- a/packages/EasySecurity/src/AbstractSecurityContextFactory.php +++ b/packages/EasySecurity/src/AbstractSecurityContextFactory.php @@ -4,28 +4,46 @@ namespace EonX\EasySecurity; -use EonX\EasySecurity\Interfaces\Authorization\AuthorizationMatrixInterface; +use EonX\EasyEventDispatcher\Interfaces\EventDispatcherInterface; +use EonX\EasySecurity\Events\SecurityContextCreatedEvent; use EonX\EasySecurity\Interfaces\SecurityContextFactoryInterface; use EonX\EasySecurity\Interfaces\SecurityContextInterface; abstract class AbstractSecurityContextFactory implements SecurityContextFactoryInterface { /** - * @var \EonX\EasySecurity\Interfaces\Authorization\AuthorizationMatrixInterface + * @var null|\EonX\EasySecurity\Interfaces\SecurityContextInterface */ - private $authorizationMatrix; + private $cached; - public function __construct(AuthorizationMatrixInterface $authorizationMatrix) + /** + * @var null|\EonX\EasyEventDispatcher\Interfaces\EventDispatcherInterface + */ + private $eventDispatcher; + + public function __construct(?EventDispatcherInterface $eventDispatcher = null) { - $this->authorizationMatrix = $authorizationMatrix; + $this->eventDispatcher = $eventDispatcher; } public function create(): SecurityContextInterface { + if ($this->cached !== null) { + return $this->cached; + } + $context = $this->doCreate(); - $context->setAuthorizationMatrix($this->authorizationMatrix); - return $context; + if ($this->eventDispatcher !== null) { + $this->eventDispatcher->dispatch(new SecurityContextCreatedEvent($context)); + } + + return $this->cached = $context; + } + + public function reset(): void + { + $this->cached = null; } abstract protected function doCreate(): SecurityContextInterface; diff --git a/packages/EasySecurity/src/Bridge/BridgeConstantsInterface.php b/packages/EasySecurity/src/Bridge/BridgeConstantsInterface.php index c86eb8ace..e1ac80763 100644 --- a/packages/EasySecurity/src/Bridge/BridgeConstantsInterface.php +++ b/packages/EasySecurity/src/Bridge/BridgeConstantsInterface.php @@ -29,17 +29,17 @@ interface BridgeConstantsInterface /** * @var string */ - public const TAG_CONTEXT_MODIFIER = 'easy_security.context_modifier'; + public const TAG_PERMISSIONS_PROVIDER = 'easy_security.permissions_provider'; /** * @var string */ - public const TAG_PERMISSIONS_PROVIDER = 'easy_security.permissions_provider'; + public const TAG_ROLES_PROVIDER = 'easy_security.roles_provider'; /** * @var string */ - public const TAG_ROLES_PROVIDER = 'easy_security.roles_provider'; + public const SERVICE_API_TOKEN_DECODER = 'easy_security.api_token_decoder'; /** * @var string diff --git a/packages/EasySecurity/src/Bridge/Laravel/EasySecurityServiceProvider.php b/packages/EasySecurity/src/Bridge/Laravel/EasySecurityServiceProvider.php index d60b8e221..04d4f71c2 100644 --- a/packages/EasySecurity/src/Bridge/Laravel/EasySecurityServiceProvider.php +++ b/packages/EasySecurity/src/Bridge/Laravel/EasySecurityServiceProvider.php @@ -4,19 +4,25 @@ namespace EonX\EasySecurity\Bridge\Laravel; +use EonX\EasyApiToken\Interfaces\ApiTokenDecoderInterface; use EonX\EasyApiToken\Interfaces\Factories\ApiTokenDecoderFactoryInterface; use EonX\EasyBugsnag\Bridge\BridgeConstantsInterface as EasyBugsnagBridgeConstantsInterface; use EonX\EasySecurity\Authorization\AuthorizationMatrixFactory; use EonX\EasySecurity\Authorization\CachedAuthorizationMatrixFactory; use EonX\EasySecurity\Bridge\BridgeConstantsInterface; use EonX\EasySecurity\Bridge\EasyBugsnag\SecurityContextClientConfigurator; +use EonX\EasySecurity\Bridge\Laravel\Listeners\ConfigureSecurityContextListener; +use EonX\EasySecurity\Configurators\ApiTokenConfigurator; +use EonX\EasySecurity\Configurators\AuthorizationMatrixConfigurator; use EonX\EasySecurity\DeferredSecurityContextProvider; +use EonX\EasySecurity\Events\SecurityContextCreatedEvent; use EonX\EasySecurity\Interfaces\Authorization\AuthorizationMatrixFactoryInterface; use EonX\EasySecurity\Interfaces\Authorization\AuthorizationMatrixInterface; use EonX\EasySecurity\Interfaces\DeferredSecurityContextProviderInterface; +use EonX\EasySecurity\Interfaces\SecurityContextConfiguratorInterface; +use EonX\EasySecurity\Interfaces\SecurityContextFactoryInterface; use EonX\EasySecurity\Interfaces\SecurityContextInterface; -use EonX\EasySecurity\MainSecurityContextConfigurator; -use EonX\EasySecurity\SecurityContext; +use EonX\EasySecurity\SecurityContextFactory; use Illuminate\Http\Request; use Illuminate\Support\ServiceProvider; use Symfony\Component\Cache\Adapter\ArrayAdapter; @@ -28,6 +34,9 @@ public function boot(): void $this->publishes([ __DIR__ . '/config/easy-security.php' => \base_path('config/easy-security.php'), ]); + + $this->app->make('events') + ->listen(SecurityContextCreatedEvent::class, ConfigureSecurityContextListener::class); } public function register(): void @@ -36,12 +45,27 @@ public function register(): void $contextServiceId = \config('easy-security.context_service_id'); + $this->registerApiTokenDecoder(); $this->registerAuthorizationMatrix(); + $this->registerDefaultConfigurators(); $this->registerEasyBugsnag(); + $this->registerListeners(); $this->registerSecurityContext($contextServiceId); $this->registerDeferredSecurityContextProvider($contextServiceId); } + private function registerApiTokenDecoder(): void + { + $this->app->singleton( + BridgeConstantsInterface::SERVICE_API_TOKEN_DECODER, + function (): ApiTokenDecoderInterface { + return $this->app + ->make(ApiTokenDecoderFactoryInterface::class) + ->build(\config('easy-security.token_decoder')); + } + ); + } + private function registerAuthorizationMatrix(): void { $this->app->singleton(BridgeConstantsInterface::SERVICE_AUTHORIZATION_MATRIX_CACHE, ArrayAdapter::class); @@ -64,6 +88,32 @@ function (): AuthorizationMatrixFactoryInterface { }); } + private function registerDefaultConfigurators(): void + { + if (\config('easy-security.use_default_configurators', true) === false) { + return; + } + + $this->app->singleton(ApiTokenConfigurator::class, function (): ApiTokenConfigurator { + return new ApiTokenConfigurator( + $this->app->make(BridgeConstantsInterface::SERVICE_API_TOKEN_DECODER), + SecurityContextConfiguratorInterface::SYSTEM_PRIORITY + ); + }); + + $this->app->singleton(AuthorizationMatrixConfigurator::class, function (): AuthorizationMatrixConfigurator { + return new AuthorizationMatrixConfigurator( + $this->app->make(AuthorizationMatrixInterface::class), + SecurityContextConfiguratorInterface::SYSTEM_PRIORITY + ); + }); + + $this->app->tag( + [ApiTokenConfigurator::class, AuthorizationMatrixConfigurator::class], + [BridgeConstantsInterface::TAG_CONTEXT_CONFIGURATOR] + ); + } + private function registerDeferredSecurityContextProvider(string $contextServiceId): void { $this->app->singleton( @@ -95,35 +145,24 @@ function (): SecurityContextClientConfigurator { ); } - private function registerSecurityContext(string $contextServiceId): void + private function registerListeners(): void { - $this->app->singleton(MainSecurityContextConfigurator::class, function (): MainSecurityContextConfigurator { - $request = $this->app->make(Request::class); - $apiTokenDecoderFactory = $this->app->make(ApiTokenDecoderFactoryInterface::class); - $apiTokenDecoder = $apiTokenDecoderFactory->build(\config('easy-security.token_decoder')); - - $mainConfigurator = new MainSecurityContextConfigurator( - $this->app->make(AuthorizationMatrixInterface::class), - $request, - $apiTokenDecoder->decode($request) + $this->app->singleton(ConfigureSecurityContextListener::class, function (): ConfigureSecurityContextListener { + return new ConfigureSecurityContextListener( + $this->app->tagged(BridgeConstantsInterface::TAG_CONTEXT_CONFIGURATOR), + $this->app->make(Request::class) ); - - return $mainConfigurator - ->withConfigurators($this->app->tagged(BridgeConstantsInterface::TAG_CONTEXT_CONFIGURATOR)) - ->withModifiers($this->app->tagged(BridgeConstantsInterface::TAG_CONTEXT_MODIFIER)); }); + } + + private function registerSecurityContext(string $contextServiceId): void + { + // SecurityContextFactory + $this->app->singleton(SecurityContextFactoryInterface::class, SecurityContextFactory::class); + // SecurityContext $this->app->singleton($contextServiceId, function (): SecurityContextInterface { - return new SecurityContext(); + return $this->app->make(SecurityContextFactoryInterface::class)->create(); }); - - $extend = function (SecurityContextInterface $securityContext): SecurityContextInterface { - /** @var \EonX\EasySecurity\MainSecurityContextConfigurator $configurator */ - $configurator = $this->app->make(MainSecurityContextConfigurator::class); - - return $configurator->configure($securityContext); - }; - - $this->app->extend($contextServiceId, $extend); } } diff --git a/packages/EasySecurity/src/Bridge/Laravel/Http/Middleware/ContextResolverMiddleware.php b/packages/EasySecurity/src/Bridge/Laravel/Http/Middleware/ContextResolverMiddleware.php deleted file mode 100644 index 16dd76ddd..000000000 --- a/packages/EasySecurity/src/Bridge/Laravel/Http/Middleware/ContextResolverMiddleware.php +++ /dev/null @@ -1,10 +0,0 @@ -resolver = $resolver; - } - - /** - * @return mixed - */ - public function handle(Request $request, Closure $next) - { - $this->resolver->resolve($request); - - return $next($request); - } -} diff --git a/packages/EasySecurity/src/Bridge/Laravel/Interfaces/DeferredContextResolverInterface.php b/packages/EasySecurity/src/Bridge/Laravel/Interfaces/DeferredContextResolverInterface.php deleted file mode 100644 index d2091a2e9..000000000 --- a/packages/EasySecurity/src/Bridge/Laravel/Interfaces/DeferredContextResolverInterface.php +++ /dev/null @@ -1,12 +0,0 @@ - $configurators + */ + public function __construct(iterable $configurators, Request $request) + { + $this->configurators = CollectorHelper::orderLowerPriorityFirst( + CollectorHelper::filterByClass($configurators, SecurityContextConfiguratorInterface::class) + ); + + $this->request = $request; + } + + public function handle(SecurityContextCreatedEvent $event): void + { + $context = $event->getSecurityContext(); + + foreach ($this->configurators as $configurator) { + $configurator->configure($context, $this->request); + } + } +} diff --git a/packages/EasySecurity/src/Bridge/Laravel/config/easy-security.php b/packages/EasySecurity/src/Bridge/Laravel/config/easy-security.php index 003da6ad4..fed59836a 100644 --- a/packages/EasySecurity/src/Bridge/Laravel/config/easy-security.php +++ b/packages/EasySecurity/src/Bridge/Laravel/config/easy-security.php @@ -8,4 +8,5 @@ 'context_service_id' => SecurityContextInterface::class, 'token_decoder' => null, 'easy_bugsnag' => true, + 'use_default_configurators' => true, ]; diff --git a/packages/EasySecurity/src/Bridge/Symfony/DataCollector/SecurityContextDataCollector.php b/packages/EasySecurity/src/Bridge/Symfony/DataCollector/SecurityContextDataCollector.php index 1873c9952..3c6b1a88f 100644 --- a/packages/EasySecurity/src/Bridge/Symfony/DataCollector/SecurityContextDataCollector.php +++ b/packages/EasySecurity/src/Bridge/Symfony/DataCollector/SecurityContextDataCollector.php @@ -9,10 +9,11 @@ use EonX\EasySecurity\Authorization\CachedAuthorizationMatrixFactory; use EonX\EasySecurity\Interfaces\Authorization\AuthorizationMatrixFactoryInterface; use EonX\EasySecurity\Interfaces\Authorization\AuthorizationMatrixInterface; +use EonX\EasySecurity\Interfaces\DeferredSecurityContextProviderInterface; use EonX\EasySecurity\Interfaces\ProviderInterface; -use EonX\EasySecurity\Interfaces\SecurityContextInterface; +use EonX\EasySecurity\Interfaces\SecurityContextConfiguratorInterface; use EonX\EasySecurity\Interfaces\UserInterface; -use EonX\EasySecurity\MainSecurityContextConfigurator; +use EonX\EasyUtils\CollectorHelper; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\DataCollector\DataCollector; @@ -30,33 +31,41 @@ final class SecurityContextDataCollector extends DataCollector private $authorizationMatrixFactory; /** - * @var \EonX\EasySecurity\Interfaces\SecurityContextInterface + * @var \EonX\EasySecurity\Interfaces\SecurityContextConfiguratorInterface[] */ - private $securityContext; + private $configurators; /** - * @var \EonX\EasySecurity\MainSecurityContextConfigurator + * @var \EonX\EasySecurity\Interfaces\DeferredSecurityContextProviderInterface */ - private $securityContextConfigurator; + private $securityContextProvider; + /** + * @param iterable $configurators + */ public function __construct( AuthorizationMatrixFactoryInterface $authorizationMatrixFactory, - MainSecurityContextConfigurator $securityContextConfigurator, - SecurityContextInterface $securityContext + DeferredSecurityContextProviderInterface $securityContextProvider, + iterable $configurators ) { $this->authorizationMatrixFactory = $authorizationMatrixFactory; - $this->securityContextConfigurator = $securityContextConfigurator; - $this->securityContext = $securityContextConfigurator->configure($securityContext); + $this->securityContextProvider = $securityContextProvider; + + $this->configurators = CollectorHelper::orderLowerPriorityFirst( + CollectorHelper::filterByClass($configurators, SecurityContextConfiguratorInterface::class) + ); } public function collect(Request $request, Response $response, ?\Throwable $throwable = null): void { - $this->data['authorization_matrix'] = $this->securityContext->getAuthorizationMatrix(); - $this->data['permissions'] = $this->securityContext->getPermissions(); - $this->data['roles'] = $this->securityContext->getRoles(); - $this->data['provider'] = $this->securityContext->getProvider(); - $this->data['user'] = $this->securityContext->getUser(); - $this->data['token'] = $this->securityContext->getToken(); + $securityContext = $this->securityContextProvider->getSecurityContext(); + + $this->data['authorization_matrix'] = $securityContext->getAuthorizationMatrix(); + $this->data['permissions'] = $securityContext->getPermissions(); + $this->data['roles'] = $securityContext->getRoles(); + $this->data['provider'] = $securityContext->getProvider(); + $this->data['user'] = $securityContext->getUser(); + $this->data['token'] = $securityContext->getToken(); $this->setContextConfigurators(); $this->setRolesPermissionsProviders(); @@ -136,7 +145,7 @@ private function setContextConfigurators(): void { $this->data['context_configurators'] = []; - foreach ($this->securityContextConfigurator->getContextConfigurators() as $contextConfigurator) { + foreach ($this->configurators as $contextConfigurator) { $reflection = new \ReflectionClass($contextConfigurator); $this->data['context_configurators'][] = [ diff --git a/packages/EasySecurity/src/Bridge/Symfony/DependencyInjection/Compiler/ConfigureSecurityContextPass.php b/packages/EasySecurity/src/Bridge/Symfony/DependencyInjection/Compiler/ConfigureSecurityContextPass.php deleted file mode 100644 index 15f4a56c3..000000000 --- a/packages/EasySecurity/src/Bridge/Symfony/DependencyInjection/Compiler/ConfigureSecurityContextPass.php +++ /dev/null @@ -1,32 +0,0 @@ -getParameter($container, BridgeConstantsInterface::PARAM_CONTEXT_SERVICE_ID); - - if ($contextServiceId === null || $container->hasDefinition($contextServiceId) === false) { - return; - } - - $container - ->getDefinition($contextServiceId) - ->setConfigurator([new Reference(MainSecurityContextConfigurator::class), 'configure']); - } - - private function getParameter(ContainerBuilder $container, string $param): ?string - { - return $container->hasParameter($param) ? $container->getParameter($param) : null; - } -} diff --git a/packages/EasySecurity/src/Bridge/Symfony/DependencyInjection/Compiler/RegisterPermissionExpressionFunctionPass.php b/packages/EasySecurity/src/Bridge/Symfony/DependencyInjection/Compiler/RegisterPermissionExpressionFunctionPass.php index 8ba5cfd5c..952a73dab 100644 --- a/packages/EasySecurity/src/Bridge/Symfony/DependencyInjection/Compiler/RegisterPermissionExpressionFunctionPass.php +++ b/packages/EasySecurity/src/Bridge/Symfony/DependencyInjection/Compiler/RegisterPermissionExpressionFunctionPass.php @@ -4,7 +4,7 @@ namespace EonX\EasySecurity\Bridge\Symfony\DependencyInjection\Compiler; -use EonX\EasySecurity\Bridge\Symfony\Interfaces\ParametersInterface; +use EonX\EasySecurity\Bridge\BridgeConstantsInterface; use EonX\EasySecurity\Bridge\Symfony\Security\PermissionExpressionFunctionProvider; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -15,7 +15,7 @@ final class RegisterPermissionExpressionFunctionPass implements CompilerPassInte { public function process(ContainerBuilder $container): void { - $locations = $container->getParameter(ParametersInterface::PERMISSIONS_LOCATIONS); + $locations = $container->getParameter(BridgeConstantsInterface::PARAM_PERMISSIONS_LOCATIONS); $exprLangId = 'security.expression_language'; if (empty($locations) || $container->has($exprLangId) === false) { diff --git a/packages/EasySecurity/src/Bridge/Symfony/DependencyInjection/Compiler/RegisterSecurityContextPass.php b/packages/EasySecurity/src/Bridge/Symfony/DependencyInjection/Compiler/RegisterSecurityContextPass.php new file mode 100644 index 000000000..0c658bc68 --- /dev/null +++ b/packages/EasySecurity/src/Bridge/Symfony/DependencyInjection/Compiler/RegisterSecurityContextPass.php @@ -0,0 +1,44 @@ +getParameter($container, BridgeConstantsInterface::PARAM_CONTEXT_SERVICE_ID); + + if ($contextServiceId === null) { + return; + } + + // Clean up existing alias/definition for service context service + if ($container->hasAlias($contextServiceId)) { + $container->removeAlias($contextServiceId); + } + + if ($container->hasDefinition($contextServiceId)) { + $container->removeDefinition($contextServiceId); + } + + // Set definition using security context factory + $container + ->setDefinition($contextServiceId, new Definition(SecurityContextInterface::class)) + ->setFactory([new Reference(SecurityContextFactoryInterface::class), 'create']); + } + + private function getParameter(ContainerBuilder $container, string $param): ?string + { + return $container->hasParameter($param) ? $container->getParameter($param) : null; + } +} diff --git a/packages/EasySecurity/src/Bridge/Symfony/DependencyInjection/Configuration.php b/packages/EasySecurity/src/Bridge/Symfony/DependencyInjection/Configuration.php index 341e49632..2cd7fc847 100644 --- a/packages/EasySecurity/src/Bridge/Symfony/DependencyInjection/Configuration.php +++ b/packages/EasySecurity/src/Bridge/Symfony/DependencyInjection/Configuration.php @@ -30,6 +30,7 @@ public function getConfigTreeBuilder(): TreeBuilder ->booleanNode('role_enabled')->defaultFalse()->end() ->end() ->end() + ->booleanNode('use_default_configurators')->defaultTrue()->end() ->end(); return $treeBuilder; diff --git a/packages/EasySecurity/src/Bridge/Symfony/DependencyInjection/EasySecurityExtension.php b/packages/EasySecurity/src/Bridge/Symfony/DependencyInjection/EasySecurityExtension.php index 3a82b90e4..8ea49ff7c 100644 --- a/packages/EasySecurity/src/Bridge/Symfony/DependencyInjection/EasySecurityExtension.php +++ b/packages/EasySecurity/src/Bridge/Symfony/DependencyInjection/EasySecurityExtension.php @@ -11,7 +11,6 @@ use EonX\EasySecurity\Bridge\Symfony\Security\Voters\RoleVoter; use EonX\EasySecurity\Interfaces\Authorization\PermissionsProviderInterface; use EonX\EasySecurity\Interfaces\Authorization\RolesProviderInterface; -use EonX\EasySecurity\Interfaces\ContextModifierInterface; use EonX\EasySecurity\Interfaces\SecurityContextConfiguratorInterface; use EonX\EasySecurity\Interfaces\SecurityContextInterface; use EonX\EasySecurity\SecurityContext; @@ -26,17 +25,16 @@ final class EasySecurityExtension extends Extension /** * @var string[] */ - protected static $autoConfigTags = [ + private const AUTO_CONFIG_TAGS = [ RolesProviderInterface::class => BridgeConstantsInterface::TAG_ROLES_PROVIDER, PermissionsProviderInterface::class => BridgeConstantsInterface::TAG_PERMISSIONS_PROVIDER, - ContextModifierInterface::class => BridgeConstantsInterface::TAG_CONTEXT_MODIFIER, SecurityContextConfiguratorInterface::class => BridgeConstantsInterface::TAG_CONTEXT_CONFIGURATOR, ]; /** * @var string[] */ - protected static $voters = [ + private const VOTERS = [ 'permission' => PermissionVoter::class, 'provider' => ProviderVoter::class, 'role' => RoleVoter::class, @@ -61,8 +59,9 @@ public function load(array $configs, ContainerBuilder $container): void $container->setParameter(BridgeConstantsInterface::PARAM_CONTEXT_SERVICE_ID, $contextServiceId); $container->setParameter(BridgeConstantsInterface::PARAM_TOKEN_DECODER, $config['token_decoder'] ?? null); - foreach (static::$autoConfigTags as $interface => $tag) { - $container->registerForAutoconfiguration($interface) + foreach (self::AUTO_CONFIG_TAGS as $interface => $tag) { + $container + ->registerForAutoconfiguration($interface) ->addTag($tag); } @@ -72,7 +71,7 @@ public function load(array $configs, ContainerBuilder $container): void $container->setAlias(SecurityContextInterface::class, $contextServiceId); } - foreach (static::$voters as $name => $class) { + foreach (self::VOTERS as $name => $class) { $configName = \sprintf('%s_enabled', $name); if (($config['voters'][$configName] ?? false) === false) { @@ -86,5 +85,10 @@ public function load(array $configs, ContainerBuilder $container): void if (($config['easy_bugsnag'] ?? false) && \interface_exists(EasyBugsnagBridgeConstantsInterface::class)) { $loader->load('easy_bugsnag.php'); } + + // Default configurators + if ($config['use_default_configurators'] ?? true) { + $loader->load('default_configurators.php'); + } } } diff --git a/packages/EasySecurity/src/Bridge/Symfony/EasySecurityBundle.php b/packages/EasySecurity/src/Bridge/Symfony/EasySecurityBundle.php index dbbf24ce6..d04b67204 100644 --- a/packages/EasySecurity/src/Bridge/Symfony/EasySecurityBundle.php +++ b/packages/EasySecurity/src/Bridge/Symfony/EasySecurityBundle.php @@ -4,8 +4,8 @@ namespace EonX\EasySecurity\Bridge\Symfony; -use EonX\EasySecurity\Bridge\Symfony\DependencyInjection\Compiler\ConfigureSecurityContextPass; use EonX\EasySecurity\Bridge\Symfony\DependencyInjection\Compiler\RegisterPermissionExpressionFunctionPass; +use EonX\EasySecurity\Bridge\Symfony\DependencyInjection\Compiler\RegisterSecurityContextPass; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\Bundle\Bundle; @@ -16,6 +16,6 @@ public function build(ContainerBuilder $container): void parent::build($container); $container->addCompilerPass(new RegisterPermissionExpressionFunctionPass()); - $container->addCompilerPass(new ConfigureSecurityContextPass()); + $container->addCompilerPass(new RegisterSecurityContextPass()); } } diff --git a/packages/EasySecurity/src/Bridge/Symfony/Factories/MainSecurityContextConfiguratorFactory.php b/packages/EasySecurity/src/Bridge/Symfony/Factories/MainSecurityContextConfiguratorFactory.php deleted file mode 100644 index 544469882..000000000 --- a/packages/EasySecurity/src/Bridge/Symfony/Factories/MainSecurityContextConfiguratorFactory.php +++ /dev/null @@ -1,67 +0,0 @@ -authorizationMatrix = $authorizationMatrix; - $this->apiTokenDecoder = $apiTokenDecoder; - $this->requestStack = $requestStack; - } - - public function __invoke(): MainSecurityContextConfigurator - { - $request = $this->getRequest(); - - return new MainSecurityContextConfigurator( - $this->authorizationMatrix, - $request, - $this->apiTokenDecoder->decode($request) - ); - } - - private function getFakeRequest(): Request - { - return new Request([], [], [], [], [], [ - 'HTTP_HOST' => 'eonx.com', - ]); - } - - private function getRequest(): Request - { - // Fake request when running in console - if (\getenv('LINES') && \getenv('COLUMNS')) { - return $this->getFakeRequest(); - } - - return $this->requestStack->getMasterRequest() ?? $this->getFakeRequest(); - } -} diff --git a/packages/EasySecurity/src/Bridge/Symfony/Helpers/DeferredContextResolver.php b/packages/EasySecurity/src/Bridge/Symfony/Helpers/DeferredContextResolver.php deleted file mode 100644 index 7da994ace..000000000 --- a/packages/EasySecurity/src/Bridge/Symfony/Helpers/DeferredContextResolver.php +++ /dev/null @@ -1,13 +0,0 @@ -container = $container; - $this->contextServiceId = $contextServiceId; - } - - public function resolve(): SecurityContextInterface - { - return $this->container->get($this->contextServiceId); - } -} diff --git a/packages/EasySecurity/src/Bridge/Symfony/Interfaces/DeferredContextAwareInterface.php b/packages/EasySecurity/src/Bridge/Symfony/Interfaces/DeferredContextAwareInterface.php deleted file mode 100644 index e78076835..000000000 --- a/packages/EasySecurity/src/Bridge/Symfony/Interfaces/DeferredContextAwareInterface.php +++ /dev/null @@ -1,13 +0,0 @@ - $configurators + */ + public function __construct(iterable $configurators, RequestStack $requestStack) + { + $this->configurators = CollectorHelper::orderLowerPriorityFirst( + CollectorHelper::filterByClass($configurators, SecurityContextConfiguratorInterface::class) + ); + + $this->requestStack = $requestStack; + } + + public function __invoke(SecurityContextCreatedEvent $event): void + { + $context = $event->getSecurityContext(); + $request = $this->requestStack->getMasterRequest() ?? new Request(); + + foreach ($this->configurators as $configurator) { + $configurator->configure($context, $request); + } + } +} diff --git a/packages/EasySecurity/src/Bridge/Symfony/Resources/config/default_configurators.php b/packages/EasySecurity/src/Bridge/Symfony/Resources/config/default_configurators.php new file mode 100644 index 000000000..5242b019f --- /dev/null +++ b/packages/EasySecurity/src/Bridge/Symfony/Resources/config/default_configurators.php @@ -0,0 +1,27 @@ +services(); + $services->defaults() + ->autowire() + ->autoconfigure(); + + $services + ->set(ApiTokenConfigurator::class) + ->arg('$apiTokenDecoder', ref(BridgeConstantsInterface::SERVICE_API_TOKEN_DECODER)) + ->arg('$priority', SecurityContextConfiguratorInterface::SYSTEM_PRIORITY); + + $services + ->set(AuthorizationMatrixConfigurator::class) + ->arg('$priority', SecurityContextConfiguratorInterface::SYSTEM_PRIORITY); +}; diff --git a/packages/EasySecurity/src/Bridge/Symfony/Resources/config/services.php b/packages/EasySecurity/src/Bridge/Symfony/Resources/config/services.php index a09b53891..608d3092c 100644 --- a/packages/EasySecurity/src/Bridge/Symfony/Resources/config/services.php +++ b/packages/EasySecurity/src/Bridge/Symfony/Resources/config/services.php @@ -4,19 +4,21 @@ use EonX\EasyApiToken\Interfaces\ApiTokenDecoderInterface; use EonX\EasyApiToken\Interfaces\Factories\ApiTokenDecoderFactoryInterface; +use EonX\EasyEventDispatcher\Interfaces\EventDispatcherInterface; use EonX\EasySecurity\Authorization\AuthorizationMatrixFactory; use EonX\EasySecurity\Authorization\CachedAuthorizationMatrixFactory; use EonX\EasySecurity\Bridge\BridgeConstantsInterface; use EonX\EasySecurity\Bridge\Symfony\DataCollector\SecurityContextDataCollector; use EonX\EasySecurity\Bridge\Symfony\Factories\AuthenticationFailureResponseFactory; -use EonX\EasySecurity\Bridge\Symfony\Factories\MainSecurityContextConfiguratorFactory; use EonX\EasySecurity\Bridge\Symfony\Interfaces\AuthenticationFailureResponseFactoryInterface; +use EonX\EasySecurity\Bridge\Symfony\Listeners\ConfigureSecurityContextListener; use EonX\EasySecurity\Bridge\Symfony\Security\ContextAuthenticator; use EonX\EasySecurity\DeferredSecurityContextProvider; use EonX\EasySecurity\Interfaces\Authorization\AuthorizationMatrixFactoryInterface; use EonX\EasySecurity\Interfaces\Authorization\AuthorizationMatrixInterface; use EonX\EasySecurity\Interfaces\DeferredSecurityContextProviderInterface; -use EonX\EasySecurity\MainSecurityContextConfigurator; +use EonX\EasySecurity\Interfaces\SecurityContextFactoryInterface; +use EonX\EasySecurity\SecurityContextFactory; use Symfony\Component\Cache\Adapter\ArrayAdapter; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; @@ -29,6 +31,12 @@ ->autowire() ->autoconfigure(); + // ApiTokenDecoder + $services + ->set(BridgeConstantsInterface::SERVICE_API_TOKEN_DECODER, ApiTokenDecoderInterface::class) + ->factory([ref(ApiTokenDecoderFactoryInterface::class), 'build']) + ->args(['%' . BridgeConstantsInterface::PARAM_TOKEN_DECODER . '%']); + // Authorization $services->set(BridgeConstantsInterface::SERVICE_AUTHORIZATION_MATRIX_CACHE, ArrayAdapter::class); @@ -46,36 +54,32 @@ ->set(AuthorizationMatrixInterface::class) ->factory([ref(AuthorizationMatrixFactoryInterface::class), 'create']); - // MainSecurityContextConfigurator + // DataCollector $services - ->set('easy_security.api_token_decoder', ApiTokenDecoderInterface::class) - ->factory([ref(ApiTokenDecoderFactoryInterface::class), 'build']) - ->args(['%' . BridgeConstantsInterface::PARAM_TOKEN_DECODER . '%']); + ->set(SecurityContextDataCollector::class) + ->arg('$configurators', tagged_iterator(BridgeConstantsInterface::TAG_CONTEXT_CONFIGURATOR)) + ->tag('data_collector', [ + 'template' => '@EasySecurity/Collector/security_context_collector.html.twig', + 'id' => SecurityContextDataCollector::NAME, + ]); + // Deferred Security Provider $services - ->set(MainSecurityContextConfiguratorFactory::class) - ->arg('$apiTokenDecoder', ref('easy_security.api_token_decoder')); + ->set(DeferredSecurityContextProviderInterface::class, DeferredSecurityContextProvider::class) + ->arg('$contextServiceId', '%' . BridgeConstantsInterface::PARAM_CONTEXT_SERVICE_ID . '%'); + // Listeners $services - ->set(MainSecurityContextConfigurator::class) - ->factory([ref(MainSecurityContextConfiguratorFactory::class), '__invoke']) - ->call('withConfigurators', [tagged_iterator(BridgeConstantsInterface::TAG_CONTEXT_CONFIGURATOR)]) - ->call('withModifiers', [tagged_iterator(BridgeConstantsInterface::TAG_CONTEXT_MODIFIER)]); + ->set(ConfigureSecurityContextListener::class) + ->arg('$configurators', tagged_iterator(BridgeConstantsInterface::TAG_CONTEXT_CONFIGURATOR)) + ->tag('kernel.event_listener'); - // Deferred Security Provider + // SecurityContextFactory $services - ->set(DeferredSecurityContextProviderInterface::class, DeferredSecurityContextProvider::class) - ->arg('$contextServiceId', '%' . BridgeConstantsInterface::PARAM_CONTEXT_SERVICE_ID . '%'); + ->set(SecurityContextFactoryInterface::class, SecurityContextFactory::class) + ->arg('$eventDispatcher', ref(EventDispatcherInterface::class)); // Symfony Security $services->set(AuthenticationFailureResponseFactoryInterface::class, AuthenticationFailureResponseFactory::class); $services->set(ContextAuthenticator::class); - - // DataCollector - $services - ->set(SecurityContextDataCollector::class) - ->tag('data_collector', [ - 'template' => '@EasySecurity/Collector/security_context_collector.html.twig', - 'id' => 'easy_security.security_context_collector', - ]); }; diff --git a/packages/EasySecurity/src/Bridge/Symfony/Security/ContextAuthenticator.php b/packages/EasySecurity/src/Bridge/Symfony/Security/ContextAuthenticator.php index 000521ae1..4fbe35cd6 100644 --- a/packages/EasySecurity/src/Bridge/Symfony/Security/ContextAuthenticator.php +++ b/packages/EasySecurity/src/Bridge/Symfony/Security/ContextAuthenticator.php @@ -5,7 +5,7 @@ namespace EonX\EasySecurity\Bridge\Symfony\Security; use EonX\EasySecurity\Bridge\Symfony\Interfaces\AuthenticationFailureResponseFactoryInterface; -use EonX\EasySecurity\Interfaces\ContextInterface; +use EonX\EasySecurity\Interfaces\DeferredSecurityContextProviderInterface; use EonX\EasySecurity\Interfaces\SecurityContextInterface; use EonX\EasySecurity\Interfaces\UserInterface as EonxUserInterface; use Symfony\Component\HttpFoundation\Request; @@ -24,15 +24,15 @@ final class ContextAuthenticator extends AbstractGuardAuthenticator private $responseFactory; /** - * @var \EonX\EasySecurity\Interfaces\SecurityContextInterface + * @var \EonX\EasySecurity\Interfaces\DeferredSecurityContextProviderInterface */ - private $securityContext; + private $securityContextProvider; public function __construct( - SecurityContextInterface $securityContext, + DeferredSecurityContextProviderInterface $securityContextProvider, AuthenticationFailureResponseFactoryInterface $respFactory ) { - $this->securityContext = $securityContext; + $this->securityContextProvider = $securityContextProvider; $this->responseFactory = $respFactory; } @@ -44,13 +44,13 @@ public function checkCredentials($credentials, UserInterface $user): bool return true; } - public function getCredentials(Request $request): ContextInterface + public function getCredentials(Request $request): SecurityContextInterface { - return $this->securityContext; + return $this->securityContextProvider->getSecurityContext(); } /** - * @param \EonX\EasySecurity\Interfaces\ContextInterface $context + * @param \EonX\EasySecurity\Interfaces\SecurityContextInterface $context * * @return null|void|\EonX\EasySecurity\Interfaces\UserInterface */ diff --git a/packages/EasySecurity/src/Bridge/Symfony/Traits/DeferredContextAwareTrait.php b/packages/EasySecurity/src/Bridge/Symfony/Traits/DeferredContextAwareTrait.php deleted file mode 100644 index 4f435b1c1..000000000 --- a/packages/EasySecurity/src/Bridge/Symfony/Traits/DeferredContextAwareTrait.php +++ /dev/null @@ -1,29 +0,0 @@ -contextResolver = $contextResolver; - } - - protected function resolveContext(): ContextInterface - { - return $this->contextResolver->resolve(); - } -} diff --git a/packages/EasySecurity/src/Bridge/Symfony/Traits/DeferredSecurityContextAwareTrait.php b/packages/EasySecurity/src/Bridge/Symfony/Traits/DeferredSecurityContextAwareTrait.php deleted file mode 100644 index 8bc252671..000000000 --- a/packages/EasySecurity/src/Bridge/Symfony/Traits/DeferredSecurityContextAwareTrait.php +++ /dev/null @@ -1,26 +0,0 @@ -securityContextResolver = $resolver; - } - - protected function resolveSecurityContext(): SecurityContextInterface - { - return $this->securityContextResolver->resolve(); - } -} diff --git a/packages/EasySecurity/src/Configurators/AbstractSecurityContextConfigurator.php b/packages/EasySecurity/src/Configurators/AbstractSecurityContextConfigurator.php index 3308b05fc..74764ba44 100644 --- a/packages/EasySecurity/src/Configurators/AbstractSecurityContextConfigurator.php +++ b/packages/EasySecurity/src/Configurators/AbstractSecurityContextConfigurator.php @@ -5,21 +5,14 @@ namespace EonX\EasySecurity\Configurators; use EonX\EasySecurity\Interfaces\SecurityContextConfiguratorInterface; +use EonX\EasyUtils\Traits\HasPriorityTrait; abstract class AbstractSecurityContextConfigurator implements SecurityContextConfiguratorInterface { - /** - * @var int - */ - private $priority; + use HasPriorityTrait; public function __construct(?int $priority = null) { $this->priority = $priority ?? 0; } - - public function getPriority(): int - { - return $this->priority; - } } diff --git a/packages/EasySecurity/src/Configurators/ApiTokenConfigurator.php b/packages/EasySecurity/src/Configurators/ApiTokenConfigurator.php new file mode 100644 index 000000000..d503a7f57 --- /dev/null +++ b/packages/EasySecurity/src/Configurators/ApiTokenConfigurator.php @@ -0,0 +1,29 @@ +apiTokenDecoder = $apiTokenDecoder; + + parent::__construct($priority); + } + + public function configure(SecurityContextInterface $context, Request $request): void + { + $context->setToken($this->apiTokenDecoder->decode($request)); + } +} diff --git a/packages/EasySecurity/src/Configurators/AuthorizationMatrixConfigurator.php b/packages/EasySecurity/src/Configurators/AuthorizationMatrixConfigurator.php new file mode 100644 index 000000000..4264f0a53 --- /dev/null +++ b/packages/EasySecurity/src/Configurators/AuthorizationMatrixConfigurator.php @@ -0,0 +1,29 @@ +authorizationMatrix = $authorizationMatrix; + + parent::__construct($priority); + } + + public function configure(SecurityContextInterface $context, Request $request): void + { + $context->setAuthorizationMatrix($this->authorizationMatrix); + } +} diff --git a/packages/EasySecurity/src/Context.php b/packages/EasySecurity/src/Context.php deleted file mode 100644 index 66d047bdb..000000000 --- a/packages/EasySecurity/src/Context.php +++ /dev/null @@ -1,15 +0,0 @@ - $contextModifiers - */ - public function __construct( - ContextInterface $context, - EasyPsr7FactoryInterface $psr7Factory, - ApiTokenDecoderInterface $tokenDecoder, - iterable $contextModifiers - ) { - $this->context = $context; - $this->psr7Factory = $psr7Factory; - $this->tokenDecoder = $tokenDecoder; - - $this->setContextModifiers($contextModifiers); - } - - public function resolve(Request $request): ContextInterface - { - $this->context->setToken($this->tokenDecoder->decode($this->psr7Factory->createRequest($request))); - - foreach ($this->contextModifiers as $modifier) { - $modifier->modify($this->context, $request); - } - - return $this->context; - } - - /** - * @param mixed[]|iterable $modifiers - */ - private function setContextModifiers(iterable $modifiers): void - { - $this->contextModifiers = CollectorHelper::orderLowerPriorityFirst( - CollectorHelper::filterByClass($modifiers, ContextModifierInterface::class) - ); - } -} diff --git a/packages/EasySecurity/src/Events/SecurityContextCreatedEvent.php b/packages/EasySecurity/src/Events/SecurityContextCreatedEvent.php new file mode 100644 index 000000000..eb2921f64 --- /dev/null +++ b/packages/EasySecurity/src/Events/SecurityContextCreatedEvent.php @@ -0,0 +1,25 @@ +securityContext = $securityContext; + } + + public function getSecurityContext(): SecurityContextInterface + { + return $this->securityContext; + } +} diff --git a/packages/EasySecurity/src/Interfaces/Authorization/AuthorizationMatrixInterface.php b/packages/EasySecurity/src/Interfaces/Authorization/AuthorizationMatrixInterface.php index 588c22fb2..d67cb1d90 100644 --- a/packages/EasySecurity/src/Interfaces/Authorization/AuthorizationMatrixInterface.php +++ b/packages/EasySecurity/src/Interfaces/Authorization/AuthorizationMatrixInterface.php @@ -7,26 +7,26 @@ interface AuthorizationMatrixInterface { /** - * @return \EonX\EasySecurity\Interfaces\PermissionInterface[] + * @return \EonX\EasySecurity\Interfaces\Authorization\PermissionInterface[] */ public function getPermissions(): array; /** * @param string[] $identifiers * - * @return \EonX\EasySecurity\Interfaces\PermissionInterface[] + * @return \EonX\EasySecurity\Interfaces\Authorization\PermissionInterface[] */ public function getPermissionsByIdentifiers(array $identifiers): array; /** - * @return \EonX\EasySecurity\Interfaces\RoleInterface[] + * @return \EonX\EasySecurity\Interfaces\Authorization\RoleInterface[] */ public function getRoles(): array; /** * @param string[] $identifiers * - * @return \EonX\EasySecurity\Interfaces\RoleInterface[] + * @return \EonX\EasySecurity\Interfaces\Authorization\RoleInterface[] */ public function getRolesByIdentifiers(array $identifiers): array; diff --git a/packages/EasySecurity/src/Interfaces/Authorization/PermissionInterface.php b/packages/EasySecurity/src/Interfaces/Authorization/PermissionInterface.php index af92a5b08..fffab5dc7 100644 --- a/packages/EasySecurity/src/Interfaces/Authorization/PermissionInterface.php +++ b/packages/EasySecurity/src/Interfaces/Authorization/PermissionInterface.php @@ -4,7 +4,7 @@ namespace EonX\EasySecurity\Interfaces\Authorization; -interface PermissionInterface extends \EonX\EasySecurity\Interfaces\PermissionInterface +interface PermissionInterface { public function __toString(): string; diff --git a/packages/EasySecurity/src/Interfaces/Authorization/RoleInterface.php b/packages/EasySecurity/src/Interfaces/Authorization/RoleInterface.php index 9f77f4c49..726a0bccf 100644 --- a/packages/EasySecurity/src/Interfaces/Authorization/RoleInterface.php +++ b/packages/EasySecurity/src/Interfaces/Authorization/RoleInterface.php @@ -4,7 +4,7 @@ namespace EonX\EasySecurity\Interfaces\Authorization; -interface RoleInterface extends \EonX\EasySecurity\Interfaces\RoleInterface +interface RoleInterface { public function __toString(): string; diff --git a/packages/EasySecurity/src/Interfaces/ContextFactoryInterface.php b/packages/EasySecurity/src/Interfaces/ContextFactoryInterface.php deleted file mode 100644 index 9247c672d..000000000 --- a/packages/EasySecurity/src/Interfaces/ContextFactoryInterface.php +++ /dev/null @@ -1,14 +0,0 @@ -apiToken = $apiToken; - $this->authorizationMatrix = $authorizationMatrix; - $this->request = $request; - } - - public function configure(SecurityContextInterface $securityContext): SecurityContextInterface - { - $securityContext->setAuthorizationMatrix($this->authorizationMatrix); - $securityContext->setToken($this->apiToken); - - if (empty($this->modifiers) === false) { - @\trigger_error( - \sprintf( - 'Using %s is deprecated since 2.4 and will be removed in 3.0. Use %s instead', - ContextModifierInterface::class, - ConfiguratorInterface::class - ), - \E_USER_DEPRECATED - ); - - foreach ($this->modifiers as $modifier) { - $modifier->modify($securityContext, $this->request); - } - } - - foreach ($this->configurators as $configurator) { - $configurator->configure($securityContext, $this->request); - } - - return $securityContext; - } - - /** - * @return \EonX\EasySecurity\Interfaces\SecurityContextConfiguratorInterface[] - */ - public function getContextConfigurators(): array - { - return $this->configurators; - } - - /** - * @param iterable $configurators - */ - public function withConfigurators(iterable $configurators): self - { - $this->configurators = CollectorHelper::orderLowerPriorityFirst( - CollectorHelper::filterByClass($configurators, ConfiguratorInterface::class) - ); - - return $this; - } - - /** - * @param iterable $modifiers - */ - public function withModifiers(iterable $modifiers): self - { - $this->modifiers = CollectorHelper::orderLowerPriorityFirst( - CollectorHelper::filterByClass($modifiers, ContextModifierInterface::class) - ); - - return $this; - } -} diff --git a/packages/EasySecurity/src/Modifiers/AbstractContextModifier.php b/packages/EasySecurity/src/Modifiers/AbstractContextModifier.php deleted file mode 100644 index 6fafb8ee2..000000000 --- a/packages/EasySecurity/src/Modifiers/AbstractContextModifier.php +++ /dev/null @@ -1,38 +0,0 @@ -priority = $priority; - - @\trigger_error( - \sprintf( - 'Using %s is deprecated since 2.4 and will be removed in 3.0. Use %s instead', - ContextModifierInterface::class, - SecurityContextConfiguratorInterface::class - ), - \E_USER_DEPRECATED - ); - } - - public function getPriority(): int - { - return $this->priority ?? 0; - } -} diff --git a/packages/EasySecurity/src/Modifiers/AbstractFromJwtContextModifier.php b/packages/EasySecurity/src/Modifiers/AbstractFromJwtContextModifier.php deleted file mode 100644 index d5dca737e..000000000 --- a/packages/EasySecurity/src/Modifiers/AbstractFromJwtContextModifier.php +++ /dev/null @@ -1,65 +0,0 @@ -jwtClaim = $jwtClaim; - $this->jwtClaimFetcher = $jwtClaimFetcher ?? new JwtClaimFetcher(); - - parent::__construct($priority); - } - - /** - * @param null|mixed $default - * - * @return mixed - */ - protected function getClaim(JwtInterface $token, string $claim, $default = null) - { - return $this->jwtClaimFetcher->getClaim($token, $claim, $default); - } - - /** - * @param null|mixed[] $default - * - * @return mixed[] - */ - protected function getMainClaim(JwtInterface $token, ?array $default = null): array - { - return $this->jwtClaimFetcher->getArrayClaim($token, $this->jwtClaim, $default); - } -} diff --git a/packages/EasySecurity/src/Modifiers/ProviderFromHeaderModifier.php b/packages/EasySecurity/src/Modifiers/ProviderFromHeaderModifier.php deleted file mode 100644 index ebe14d6a3..000000000 --- a/packages/EasySecurity/src/Modifiers/ProviderFromHeaderModifier.php +++ /dev/null @@ -1,76 +0,0 @@ -providerProvider = $providerProvider; - $this->headerNames = (array)($headerNames ?? ['Provider-Id', 'X-Provider-Id']); - $this->permission = $permission ?? 'provider:switch'; - - parent::__construct($priority); - } - - public function modify(ContextInterface $context, Request $request): void - { - $header = $this->getHeaderValue($request); - - // If header empty, skip - if (empty($header)) { - return; - } - - // If current context hasn't required permission, skip - if ($context->hasPermission($this->permission) === false) { - return; - } - - $context->setProvider($this->providerProvider->getProvider($header)); - } - - private function getHeaderValue(Request $request): ?string - { - foreach ($this->headerNames as $headerName) { - $header = $request->headers->get($headerName); - - if (empty($header) === false) { - return $header; - } - } - - return null; - } -} diff --git a/packages/EasySecurity/src/Modifiers/ProviderFromJwtModifier.php b/packages/EasySecurity/src/Modifiers/ProviderFromJwtModifier.php deleted file mode 100644 index 0c99fe367..000000000 --- a/packages/EasySecurity/src/Modifiers/ProviderFromJwtModifier.php +++ /dev/null @@ -1,54 +0,0 @@ -providerProvider = $providerProvider; - - parent::__construct($jwtClaim, $priority, $jwtClaimFetcher); - } - - public function modify(ContextInterface $context, Request $request): void - { - $token = $context->getToken(); - - // Work only for JWT - if ($token instanceof JwtInterface === false) { - return; - } - - /** @var \EonX\EasyApiToken\Interfaces\Tokens\JwtInterface $token */ - - $providerId = $this->getMainClaim($token)['provider'] ?? null; - - // If no providerId given in token, skip - if (empty($providerId)) { - return; - } - - $context->setProvider($this->providerProvider->getProvider($providerId)); - } -} diff --git a/packages/EasySecurity/src/Modifiers/RolesFromJwtModifier.php b/packages/EasySecurity/src/Modifiers/RolesFromJwtModifier.php deleted file mode 100644 index c1bc3ff2a..000000000 --- a/packages/EasySecurity/src/Modifiers/RolesFromJwtModifier.php +++ /dev/null @@ -1,53 +0,0 @@ -rolesProvider = $rolesProvider; - - parent::__construct($jwtClaim, $priority, $jwtClaimFetcher); - } - - public function modify(ContextInterface $context, Request $request): void - { - $token = $context->getToken(); - - // Work only for JWT - if ($token instanceof JwtInterface === false) { - return; - } - - /** @var \EonX\EasyApiToken\Interfaces\Tokens\JwtInterface $token */ - - $roles = $this->rolesProvider->getRolesByIdentifiers($this->getMainClaim($token)['roles'] ?? []); - - if (empty($roles)) { - return; - } - - $context->setRoles($roles); - } -} diff --git a/packages/EasySecurity/src/Modifiers/UserFromJwtModifier.php b/packages/EasySecurity/src/Modifiers/UserFromJwtModifier.php deleted file mode 100644 index 5b97fa79a..000000000 --- a/packages/EasySecurity/src/Modifiers/UserFromJwtModifier.php +++ /dev/null @@ -1,54 +0,0 @@ -userProvider = $userProvider; - - parent::__construct($jwtClaim, $priority, $jwtClaimFetcher); - } - - public function modify(ContextInterface $context, Request $request): void - { - $token = $context->getToken(); - - // Work only for JWT - if ($token instanceof JwtInterface === false) { - return; - } - - /** @var \EonX\EasyApiToken\Interfaces\Tokens\JwtInterface $token */ - - $userId = $this->getClaim($token, 'sub'); - - // If no userId given in token, skip - if (empty($userId)) { - return; - } - - $context->setUser($this->userProvider->getUser($userId, $this->getMainClaim($token))); - } -} diff --git a/packages/EasySecurity/src/Permission.php b/packages/EasySecurity/src/Permission.php deleted file mode 100644 index 17cecf236..000000000 --- a/packages/EasySecurity/src/Permission.php +++ /dev/null @@ -1,13 +0,0 @@ -roles !== null) { - return $this->roles; - } - - return $this->roles = \array_filter($this->initRoles(), static function ($role): bool { - return $role instanceof RoleInterface; - }); - } - - /** - * @param string|string[] $identifiers - * - * @return \EonX\EasySecurity\Interfaces\RoleInterface[] - */ - public function getRolesByIdentifiers($identifiers): array - { - if (empty($identifiers)) { - return []; - } - - $roles = []; - - foreach ((array)$identifiers as $identifier) { - foreach ($this->getRoles() as $role) { - if ($role->getIdentifier() === $identifier) { - $roles[] = $role; - } - } - } - - return $roles; - } - - /** - * @return \EonX\EasySecurity\Interfaces\RoleInterface[] - */ - abstract protected function initRoles(): array; -} diff --git a/packages/EasySecurity/src/SecurityContext.php b/packages/EasySecurity/src/SecurityContext.php index 0de8e9366..e2f48fb85 100644 --- a/packages/EasySecurity/src/SecurityContext.php +++ b/packages/EasySecurity/src/SecurityContext.php @@ -14,7 +14,7 @@ use EonX\EasySecurity\Interfaces\UserInterface; /** - * Class not final because each app MUST extend it and define their own return types. + * Class not final to allow apps to extend it. */ class SecurityContext implements SecurityContextInterface { @@ -131,7 +131,7 @@ public function getProviderOrFail(): ProviderInterface } /** - * @return \EonX\EasySecurity\Interfaces\RoleInterface[] + * @return \EonX\EasySecurity\Interfaces\Authorization\RoleInterface[] */ public function getRoles(): array { diff --git a/packages/EasySecurity/src/SecurityContextFactory.php b/packages/EasySecurity/src/SecurityContextFactory.php index d3535053d..9cdeda429 100644 --- a/packages/EasySecurity/src/SecurityContextFactory.php +++ b/packages/EasySecurity/src/SecurityContextFactory.php @@ -6,9 +6,6 @@ use EonX\EasySecurity\Interfaces\SecurityContextInterface; -/** - * Not final on purpose for BC compatibility until 3.0. - */ final class SecurityContextFactory extends AbstractSecurityContextFactory { protected function doCreate(): SecurityContextInterface diff --git a/packages/EasySecurity/tests/Bridge/Laravel/AbstractLumenTestCase.php b/packages/EasySecurity/tests/Bridge/Laravel/AbstractLumenTestCase.php index 7752af25e..d8c5801b4 100644 --- a/packages/EasySecurity/tests/Bridge/Laravel/AbstractLumenTestCase.php +++ b/packages/EasySecurity/tests/Bridge/Laravel/AbstractLumenTestCase.php @@ -4,9 +4,11 @@ namespace EonX\EasySecurity\Tests\Bridge\Laravel; +use EonX\EasyApiToken\Bridge\BridgeConstantsInterface as EasyApiTokenConstantsInterface; use EonX\EasyApiToken\Bridge\Laravel\EasyApiTokenServiceProvider; use EonX\EasySecurity\Bridge\Laravel\EasySecurityServiceProvider; use EonX\EasySecurity\Tests\AbstractTestCase; +use EonX\EasySecurity\Tests\Stubs\ApiTokenDecoderProviderStub; use Laravel\Lumen\Application; abstract class AbstractLumenTestCase extends AbstractTestCase @@ -41,6 +43,9 @@ protected function getApplication(?array $providers = null, ?array $config = nul $app->register($provider); } + $app->singleton(ApiTokenDecoderProviderStub::class); + $app->tag(ApiTokenDecoderProviderStub::class, [EasyApiTokenConstantsInterface::TAG_DECODER_PROVIDER]); + return $this->app = $app; } } diff --git a/packages/EasySecurity/tests/Bridge/Laravel/EasySecurityServiceProviderTest.php b/packages/EasySecurity/tests/Bridge/Laravel/EasySecurityServiceProviderTest.php index 7472e6686..dc2399d79 100644 --- a/packages/EasySecurity/tests/Bridge/Laravel/EasySecurityServiceProviderTest.php +++ b/packages/EasySecurity/tests/Bridge/Laravel/EasySecurityServiceProviderTest.php @@ -4,6 +4,7 @@ namespace EonX\EasySecurity\Tests\Bridge\Laravel; +use EonX\EasyApiToken\Decoders\BasicAuthDecoder; use EonX\EasySecurity\Interfaces\SecurityContextInterface; use EonX\EasySecurity\SecurityContext; use Illuminate\Http\Request; @@ -14,13 +15,8 @@ final class EasySecurityServiceProviderTest extends AbstractLumenTestCase public function testSanity(): void { $app = $this->getApplication(null, [ - 'easy-api-token' => [ - 'decoders' => [ - 'basic' => null, - ], - ], 'easy-security' => [ - 'token_decoder' => 'basic', + 'token_decoder' => BasicAuthDecoder::class, ], ]); diff --git a/packages/EasySecurity/tests/Bridge/Symfony/Fixtures/config/default.yaml b/packages/EasySecurity/tests/Bridge/Symfony/Fixtures/config/default.yaml index 6d680ec83..a7a8cf34b 100644 --- a/packages/EasySecurity/tests/Bridge/Symfony/Fixtures/config/default.yaml +++ b/packages/EasySecurity/tests/Bridge/Symfony/Fixtures/config/default.yaml @@ -1,10 +1,2 @@ -easy_api_token: - default_decoder: chain - decoders: - chain: - list: - - user-apikey - user-apikey: null - easy_security: context_service_id: service-id diff --git a/packages/EasySecurity/tests/Bridge/Symfony/Helpers/DeferredContextResolverTest.php b/packages/EasySecurity/tests/Bridge/Symfony/Helpers/DeferredContextResolverTest.php deleted file mode 100644 index 5d3980047..000000000 --- a/packages/EasySecurity/tests/Bridge/Symfony/Helpers/DeferredContextResolverTest.php +++ /dev/null @@ -1,22 +0,0 @@ -getKernel() - ->getContainer(); - - $helper = new DeferredContextResolver($container, 'service-id'); - - self::assertInstanceOf(ContextInterface::class, $helper->resolve()); - } -} diff --git a/packages/EasySecurity/tests/Bridge/Symfony/Stubs/DeferredContextAwareTraitStub.php b/packages/EasySecurity/tests/Bridge/Symfony/Stubs/DeferredContextAwareTraitStub.php deleted file mode 100644 index 45e84a085..000000000 --- a/packages/EasySecurity/tests/Bridge/Symfony/Stubs/DeferredContextAwareTraitStub.php +++ /dev/null @@ -1,19 +0,0 @@ -resolveContext(); - } -} diff --git a/packages/EasySecurity/tests/Bridge/Symfony/Stubs/KernelStub.php b/packages/EasySecurity/tests/Bridge/Symfony/Stubs/KernelStub.php index 4ffb68451..565a5e0c8 100644 --- a/packages/EasySecurity/tests/Bridge/Symfony/Stubs/KernelStub.php +++ b/packages/EasySecurity/tests/Bridge/Symfony/Stubs/KernelStub.php @@ -4,16 +4,21 @@ namespace EonX\EasySecurity\Tests\Bridge\Symfony\Stubs; +use EonX\EasyApiToken\Bridge\BridgeConstantsInterface as EasyApiTokenConstantsInterface; use EonX\EasyApiToken\Bridge\Symfony\EasyApiTokenBundle; +use EonX\EasyEventDispatcher\Bridge\Symfony\EasyEventDispatcherBundle; use EonX\EasySecurity\Bridge\Symfony\EasySecurityBundle; +use EonX\EasySecurity\Tests\Stubs\ApiTokenDecoderProviderStub; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpKernel\Bundle\BundleInterface; use Symfony\Component\HttpKernel\Kernel; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; final class KernelStub extends Kernel implements CompilerPassInterface { @@ -40,6 +45,15 @@ public function __construct(string $environment, bool $debug, ?array $configs = public function process(ContainerBuilder $container): void { + // ApiTokenDecoderProvider + $container + ->setDefinition(ApiTokenDecoderProviderStub::class, new Definition(ApiTokenDecoderProviderStub::class)) + ->addTag(EasyApiTokenConstantsInterface::TAG_DECODER_PROVIDER); + + // EventDispatcher + $container->setDefinition(EventDispatcherInterface::class, new Definition(EventDispatcher::class)); + + // RequestStack $requestStackDef = new Definition(RequestStack::class); if ($this->request !== null) { @@ -60,6 +74,7 @@ public function registerBundles(): iterable { yield new EasyApiTokenBundle(); yield new EasySecurityBundle(); + yield new EasyEventDispatcherBundle(); } public function registerContainerConfiguration(LoaderInterface $loader): void @@ -70,9 +85,4 @@ public function registerContainerConfiguration(LoaderInterface $loader): void $loader->load($config); } } - - protected function build(ContainerBuilder $container): void - { - $container->addCompilerPass($this); - } } diff --git a/packages/EasySecurity/tests/Bridge/Symfony/Traits/DeferredContextAwareTraitTest.php b/packages/EasySecurity/tests/Bridge/Symfony/Traits/DeferredContextAwareTraitTest.php deleted file mode 100644 index 953259d2e..000000000 --- a/packages/EasySecurity/tests/Bridge/Symfony/Traits/DeferredContextAwareTraitTest.php +++ /dev/null @@ -1,28 +0,0 @@ -getKernel() - ->getContainer(); - - $container->set('service-id', $context); - - $stub = new DeferredContextAwareTraitStub(); - $stub->setDeferredContextResolver(new DeferredContextResolver($container, 'service-id')); - - self::assertEquals($context, $stub->getContext()); - self::assertEquals($context, $stub->getContext()); - } -} diff --git a/packages/EasySecurity/tests/Configurators/RolesFromJwtConfiguratorTest.php b/packages/EasySecurity/tests/Configurators/RolesFromJwtConfiguratorTest.php index 78e57b11f..f2d2aeff8 100644 --- a/packages/EasySecurity/tests/Configurators/RolesFromJwtConfiguratorTest.php +++ b/packages/EasySecurity/tests/Configurators/RolesFromJwtConfiguratorTest.php @@ -7,11 +7,11 @@ use EonX\EasyApiToken\Tokens\ApiKey; use EonX\EasyApiToken\Tokens\Jwt; use EonX\EasySecurity\Authorization\AuthorizationMatrix; +use EonX\EasySecurity\Authorization\Role; use EonX\EasySecurity\Configurators\RolesFromJwtConfigurator; use EonX\EasySecurity\Interfaces\JwtClaimFetcherInterface; use EonX\EasySecurity\Interfaces\SecurityContextInterface; use EonX\EasySecurity\JwtClaimFetcher; -use EonX\EasySecurity\Role; use EonX\EasySecurity\SecurityContext; use EonX\EasySecurity\Tests\AbstractTestCase; use Symfony\Component\HttpFoundation\Request; diff --git a/packages/EasySecurity/tests/Modifiers/ProviderFromHeaderModifierTest.php b/packages/EasySecurity/tests/Modifiers/ProviderFromHeaderModifierTest.php deleted file mode 100644 index 80c90b1c9..000000000 --- a/packages/EasySecurity/tests/Modifiers/ProviderFromHeaderModifierTest.php +++ /dev/null @@ -1,83 +0,0 @@ - - * - * @see testModify - */ - public function modifyProvider(): iterable - { - yield 'No provider resolved because no header' => [new ProviderProviderInterfaceStub()]; - - $request = new Request(); - $request->headers->set('X-Provider-Id', ''); - - yield 'No provider resolved because header empty' => [new ProviderProviderInterfaceStub(), $request]; - - $request = new Request(); - $request->headers->set('X-Provider-Id', 'provider-id'); - - yield 'No provider resolved because no permission' => [new ProviderProviderInterfaceStub(), $request]; - - $context = new Context(); - $context->setRoles([new Role('app:role', ['provider:switch'])]); - - yield 'No provider resolved because provider provider returns null' => [ - new ProviderProviderInterfaceStub(), - $request, - $context, - ]; - - yield 'Provider resolved' => [ - new ProviderProviderInterfaceStub($provider = new ProviderInterfaceStub('provider-id')), - $request, - $context, - $provider, - ]; - - yield 'Provider resolved with multiple headers' => [ - new ProviderProviderInterfaceStub($provider = new ProviderInterfaceStub('provider-id')), - $request, - $context, - $provider, - ['provider', 'custom-header', 'x-provider-id'], - ]; - } - - /** - * @param null|string|string[] $headerNames - * - * @dataProvider modifyProvider - */ - public function testModify( - ProviderProviderInterface $providerProvider, - ?Request $request = null, - ?ContextInterface $context = null, - ?ProviderInterface $provider = null, - $headerNames = null - ): void { - $context = $context ?? new Context(); - $modifier = new ProviderFromHeaderModifier($providerProvider, null, $headerNames); - - $modifier->modify($context, $request ?? new Request()); - - self::assertEquals($provider, $context->getProvider()); - } -} diff --git a/packages/EasySecurity/tests/Modifiers/ProviderFromJwtModifierTest.php b/packages/EasySecurity/tests/Modifiers/ProviderFromJwtModifierTest.php deleted file mode 100644 index 93618a0cb..000000000 --- a/packages/EasySecurity/tests/Modifiers/ProviderFromJwtModifierTest.php +++ /dev/null @@ -1,88 +0,0 @@ - - * - * @see testModify - */ - public function modifyProvider(): iterable - { - yield 'No provider resolved because not token' => [new ProviderProviderInterfaceStub()]; - - $context = new Context(); - $context->setToken(new ApiKey('api-key')); - - yield 'No provider resolved because token not jwt' => [new ProviderProviderInterfaceStub(), $context]; - - $context->setToken(new Jwt([], 'jwt')); - - yield 'No provider resolved because no provider claim' => [new ProviderProviderInterfaceStub(), $context]; - - $context->setToken(new Jwt([ - static::$mainJwtClaim => [ - 'provider' => '', - ], - ], 'jwt')); - - yield 'No provider resolved because provider claim empty' => [ - new ProviderProviderInterfaceStub(), - $context, - ]; - - $context->setToken(new Jwt([ - static::$mainJwtClaim => [ - 'provider' => 'provider-id', - ], - ], 'jwt')); - - yield 'No provider resolved because provider provider returns null' => [ - new ProviderProviderInterfaceStub(), - $context, - ]; - - $context->setToken(new Jwt([ - static::$mainJwtClaim => [ - 'provider' => 'provider-id', - ], - ], 'jwt')); - - yield 'Provider resolved' => [ - new ProviderProviderInterfaceStub($provider = new ProviderInterfaceStub('provider-id')), - $context, - $provider, - ]; - } - - /** - * @dataProvider modifyProvider - */ - public function testModify( - ProviderProviderInterface $providerProvider, - ?ContextInterface $context = null, - ?ProviderInterface $provider = null - ): void { - $context = $context ?? new Context(); - - (new ProviderFromJwtModifier($providerProvider, static::$mainJwtClaim))->modify($context, new Request()); - - self::assertEquals($provider, $context->getProvider()); - } -} diff --git a/packages/EasySecurity/tests/Modifiers/RolesFromJwtModifierTest.php b/packages/EasySecurity/tests/Modifiers/RolesFromJwtModifierTest.php deleted file mode 100644 index 6ffcaf419..000000000 --- a/packages/EasySecurity/tests/Modifiers/RolesFromJwtModifierTest.php +++ /dev/null @@ -1,80 +0,0 @@ - - * - * @see testModify - */ - public function modifyProvider(): iterable - { - yield 'No role resolved because not token' => [new InMemoryRolesProviderStub()]; - - $context = new Context(); - $context->setToken(new ApiKey('api-key')); - - yield 'No role resolved because token not jwt' => [new InMemoryRolesProviderStub(), $context]; - - $context->setToken(new Jwt([], 'jwt')); - - yield 'No role resolved because no roles in token' => [new InMemoryRolesProviderStub(), $context]; - - $context->setToken(new Jwt([ - static::$mainJwtClaim => [ - 'roles' => ['app:role'], - ], - ], 'jwt')); - - yield 'No role resolved because provider return empty array' => [ - new InMemoryRolesProviderStub(), - $context, - ]; - - $context->setToken(new Jwt([ - static::$mainJwtClaim => [ - 'roles' => ['app:role'], - ], - ], 'jwt')); - - yield 'Roles resolved' => [ - new InMemoryRolesProviderStub([new Role('app:role', [])]), - $context, - [ - 'app:role' => new Role('app:role', []), - ], - ]; - } - - /** - * @param null|mixed[] $roles - * - * @dataProvider modifyProvider - */ - public function testModify( - RolesProviderInterface $rolesProvider, - ?ContextInterface $context = null, - ?array $roles = null - ): void { - $context = $context ?? new Context(); - - (new RolesFromJwtModifier($rolesProvider, static::$mainJwtClaim))->modify($context, new Request()); - - self::assertEquals($roles ?? [], $context->getRoles()); - } -} diff --git a/packages/EasySecurity/tests/Modifiers/UserFromJwtModifierTest.php b/packages/EasySecurity/tests/Modifiers/UserFromJwtModifierTest.php deleted file mode 100644 index 1bffc3144..000000000 --- a/packages/EasySecurity/tests/Modifiers/UserFromJwtModifierTest.php +++ /dev/null @@ -1,81 +0,0 @@ - - * - * @see testResolve - */ - public function modifyProvider(): iterable - { - yield 'No user resolved because no token given' => [new UserProviderInterfaceStub()]; - - $context = new Context(); - $context->setToken(new ApiKey('api-key')); - - yield 'No user resolved because token not jwt' => [new UserProviderInterfaceStub(), $context]; - - $context->setToken(new Jwt([], 'jwt')); - - yield 'No user resolved because no sub claim' => [new UserProviderInterfaceStub(), $context]; - - $context->setToken(new Jwt([ - 'sub' => '', - ], 'jwt')); - - yield 'No user resolved because sub claim empty' => [new UserProviderInterfaceStub(), $context]; - - $context->setToken(new Jwt([ - 'sub' => 'user-id', - ], 'jwt')); - - yield 'No user resolved because provider returned null' => [new UserProviderInterfaceStub(), $context]; - - $context->setToken(new Jwt([ - 'sub' => 'user-id', - // To cover getClaimSafely - static::$mainJwtClaim => new stdClass(), - ], 'jwt')); - - yield 'User resolved' => [ - new UserProviderInterfaceStub($user = new UserInterfaceStub('user-id')), - $context, - $user, - ]; - } - - /** - * @dataProvider modifyProvider - */ - public function testResolve( - UserProviderInterface $userProvider, - ?ContextInterface $context = null, - ?UserInterface $user = null - ): void { - $context = $context ?? new Context(); - $modifier = new UserFromJwtModifier($userProvider, static::$mainJwtClaim); - - $modifier->modify($context, new Request()); - - self::assertEquals($user, $context->getUser()); - self::assertEquals(0, $modifier->getPriority()); - } -} diff --git a/packages/EasySecurity/tests/RolesProviders/InMemoryRolesProviderStub.php b/packages/EasySecurity/tests/RolesProviders/InMemoryRolesProviderStub.php deleted file mode 100644 index ffdb9ff24..000000000 --- a/packages/EasySecurity/tests/RolesProviders/InMemoryRolesProviderStub.php +++ /dev/null @@ -1,31 +0,0 @@ -rolesToInit = $rolesToInit ?? []; - } - - /** - * @return \EonX\EasySecurity\Interfaces\RoleInterface[] - */ - protected function initRoles(): array - { - return $this->rolesToInit; - } -} diff --git a/packages/EasySecurity/tests/RolesProviders/InMemoryRolesProviderTest.php b/packages/EasySecurity/tests/RolesProviders/InMemoryRolesProviderTest.php deleted file mode 100644 index e18610b19..000000000 --- a/packages/EasySecurity/tests/RolesProviders/InMemoryRolesProviderTest.php +++ /dev/null @@ -1,81 +0,0 @@ - - * - * @see testGetRolesByIdentifiers - */ - public function getRolesByIdentifiersDataProvider(): iterable - { - yield 'Zero role in provider' => [[], 'app:role', 0]; - - yield 'Zero role because empty array identifiers' => [[], [], 0]; - - yield 'Zero role because empty string identifiers' => [[], '', 0]; - - yield 'One match using string identifier' => [[new Role('app:role', [])], 'app:role', 1]; - - yield 'One match using array identifier' => [[new Role('app:role', [])], ['app:role'], 1]; - - yield 'Only one match for two identifiers' => [[new Role('app:role', [])], ['app:role', 'app:role1'], 1]; - - yield 'Multiple matches' => [ - [new Role('app:role', []), new Role('app:role1', [])], - ['app:role', 'app:role1'], - 2, - ]; - } - - /** - * @return iterable - * - * @see testGetRoles - */ - public function getRolesDataProvider(): iterable - { - yield 'Zero role' => [[], 0]; - - yield 'One role' => [[new Role('app:role', [])], 1]; - - yield 'Two roles' => [[new Role('app:role1', []), new Role('app:role2', [])], 2]; - - yield 'Three roles but only two instances' => [ - [new Role('app:role1', []), new Role('app:role2', []), 'non-role'], - 2, - ]; - } - - /** - * @param mixed[] $roles - * - * @dataProvider getRolesDataProvider - */ - public function testGetRoles(array $roles, int $count): void - { - $provider = new InMemoryRolesProviderStub($roles); - - self::assertCount($count, $provider->getRoles()); - } - - /** - * @param mixed[] $roles - * @param string|string[] $identifiers - * - * @dataProvider getRolesByIdentifiersDataProvider - */ - public function testGetRolesByIdentifiers(array $roles, $identifiers, int $count): void - { - $provider = new InMemoryRolesProviderStub($roles); - - self::assertCount($count, $provider->getRolesByIdentifiers($identifiers)); - } -} diff --git a/packages/EasySecurity/tests/SecurityContextTest.php b/packages/EasySecurity/tests/SecurityContextTest.php index 33701ce71..e1fa2c0d8 100644 --- a/packages/EasySecurity/tests/SecurityContextTest.php +++ b/packages/EasySecurity/tests/SecurityContextTest.php @@ -5,10 +5,10 @@ namespace EonX\EasySecurity\Tests; use EonX\EasyApiToken\Tokens\ApiKey; +use EonX\EasySecurity\Authorization\Permission; +use EonX\EasySecurity\Authorization\Role; use EonX\EasySecurity\Exceptions\NoProviderInContextException; use EonX\EasySecurity\Exceptions\NoUserInContextException; -use EonX\EasySecurity\Permission; -use EonX\EasySecurity\Role; use EonX\EasySecurity\SecurityContext; use EonX\EasySecurity\Tests\Stubs\ProviderInterfaceStub; use EonX\EasySecurity\Tests\Stubs\UserInterfaceStub; diff --git a/packages/EasySecurity/tests/Stubs/ApiTokenDecoderProviderStub.php b/packages/EasySecurity/tests/Stubs/ApiTokenDecoderProviderStub.php new file mode 100644 index 000000000..15690cac9 --- /dev/null +++ b/packages/EasySecurity/tests/Stubs/ApiTokenDecoderProviderStub.php @@ -0,0 +1,27 @@ + + */ + public function getDecoders(): iterable + { + yield new BasicAuthDecoder(); + } + + public function getDefaultDecoder(): ?string + { + return BasicAuthDecoder::class; + } +} diff --git a/packages/EasySecurity/tests/Stubs/ContextFactoryInterfaceStub.php b/packages/EasySecurity/tests/Stubs/ContextFactoryInterfaceStub.php deleted file mode 100644 index 00791ed95..000000000 --- a/packages/EasySecurity/tests/Stubs/ContextFactoryInterfaceStub.php +++ /dev/null @@ -1,17 +0,0 @@ -provider = $provider; - } - - /** - * @param int|string $uniqueId - */ - public function getProvider($uniqueId): ?ProviderInterface - { - return $this->provider; - } -} diff --git a/packages/EasySecurity/tests/Stubs/UserProviderInterfaceStub.php b/packages/EasySecurity/tests/Stubs/UserProviderInterfaceStub.php deleted file mode 100644 index 8532eeb10..000000000 --- a/packages/EasySecurity/tests/Stubs/UserProviderInterfaceStub.php +++ /dev/null @@ -1,30 +0,0 @@ -user = $user; - } - - /** - * @param int|string $uniqueId - * @param mixed[] $data - */ - public function getUser($uniqueId, array $data): ?UserInterface - { - return $this->user; - } -} diff --git a/packages/EasySsm/composer.json b/packages/EasySsm/composer.json index e7271d723..4d83039f6 100644 --- a/packages/EasySsm/composer.json +++ b/packages/EasySsm/composer.json @@ -6,8 +6,8 @@ "require": { "php": "^7.2", "aws/aws-sdk-php": "^3.134", - "eonx-com/easy-aws-credentials-finder": "^2.6", - "eonx-com/easy-random": "^2.6", + "eonx-com/easy-aws-credentials-finder": "^3.0", + "eonx-com/easy-random": "^3.0", "nette/utils": "^3.1", "symplify/package-builder": "^8.3.41", "symplify/autowire-array-parameter": "^8.3.41" @@ -31,7 +31,7 @@ ], "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "3.0-dev" } } } diff --git a/packages/EasyStandard/composer.json b/packages/EasyStandard/composer.json index 66f198c8b..63d2bcc1e 100644 --- a/packages/EasyStandard/composer.json +++ b/packages/EasyStandard/composer.json @@ -25,7 +25,7 @@ }, "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "3.0-dev" } } } diff --git a/packages/EasyTest/composer.json b/packages/EasyTest/composer.json index b249a94eb..1285a34e7 100644 --- a/packages/EasyTest/composer.json +++ b/packages/EasyTest/composer.json @@ -28,7 +28,7 @@ ], "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "3.0-dev" } } } diff --git a/packages/EasyUtils/composer.json b/packages/EasyUtils/composer.json index 506bdfd31..1f0788ac6 100644 --- a/packages/EasyUtils/composer.json +++ b/packages/EasyUtils/composer.json @@ -21,7 +21,7 @@ }, "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "3.0-dev" } } } diff --git a/packages/EasyWebhook/composer.json b/packages/EasyWebhook/composer.json index c3a174633..1fb6d87fd 100644 --- a/packages/EasyWebhook/composer.json +++ b/packages/EasyWebhook/composer.json @@ -5,10 +5,10 @@ "license": "MIT", "require": { "php": "^7.2", - "eonx-com/easy-event-dispatcher": "^2.6", - "eonx-com/easy-lock": "^2.6", - "eonx-com/easy-random": "^2.6", - "eonx-com/easy-utils": "^2.6", + "eonx-com/easy-event-dispatcher": "^3.0", + "eonx-com/easy-lock": "^3.0", + "eonx-com/easy-random": "^3.0", + "eonx-com/easy-utils": "^3.0", "nesbot/carbon": "^2.22", "nette/utils": "^3.1", "symfony/http-client": "^4.4 || ^5.1.5" @@ -31,7 +31,7 @@ }, "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "3.0-dev" } } } diff --git a/phpstan.neon b/phpstan.neon index 7bd3892ff..64216c942 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -59,18 +59,12 @@ parameters: path: packages/EasyBankFiles/tests/Parsers/Nai/ParserTest.php # ---- EasyCore ---- - - message: '#Access to an undefined property object::\$[\w]+.#' - path: packages/EasyCore/tests/Http/Middleware - - message: '#Access to an undefined property object::\$[\w]+.#' path: packages/EasyCore/tests/Bridge/Laravel/Middleware/SetContentLengthTest.php - message: '#Access to an undefined property EonX\\EasyCore\\Bridge\\Laravel\\Providers\\CachedConfigServiceProvider::\$loadedConfigurations.#' path: packages/EasyCore/src/Bridge/Laravel/Providers - - message: '#Parameter \#1 \$connOrDsn of class Symfony\\Component\\Lock\\Store\\PdoStore constructor expects Doctrine\\DBAL\\Connection\|PDO\|string, object given#' - path: packages/EasyCore/src/Lock/LockService.php - - message: '#Method EonX\\EasyCore\\Tests\\AbstractTestCase\:\:mock\(\) should return Mockery\\MockInterface but returns Mockery\\LegacyMockInterface#' path: packages/EasyCore/tests/AbstractTestCase.php @@ -99,31 +93,11 @@ parameters: path: packages/EasyCore/tests/Bridge/Symfony/Traits/TranslatorAwareTraitTest.php # ---- EasyDecision ---- - - message: '#Strict comparison using === between true and false will always evaluate to false.#' - path: packages/EasyDecision/src/Decisions - - - message: '#Parameter \#3 \$ruleProviders of class EonX\\EasyDecision\\Decisions\\DecisionConfig constructor expects array, array given.#' - path: packages/EasyDecision/tests/Decisions - - - message: "#Offset 'fn' does not exist on array\\(string\\).#" - path: packages/EasyDecision/src/Helpers - # ---- EasyErrorHandler ---- - message: '#Parameter \#1 \$argument of class ReflectionClass constructor expects class\-string\|object, object\|string given#' path: packages/EasyErrorHandler/tests - # ---- EasyLogging ---- - - message: '#Call to an undefined method Symfony\\Component\\Config\\Definition\\Builder\\NodeDefinition\:\:children\(\)#' - path: packages/EasyLogging/src/Bridge/Symfony/DependencyInjection/Configuration.php - - - message: '#Class App\\Exceptions\\EntityValidationFailedException not found.#' - path: packages/EasyLogging/src/ContextModifiers - - - message: '#Call to method getErrors\(\) on an unknown class App\\Exceptions\\EntityValidationFailedException.#' - path: packages/EasyLogging/src/ContextModifiers - # ---- EasyLock ---- - - message: '#Method EonX\\EasyLock\\Bridge\\Symfony\\Messenger\\ProcessWithLockMiddleware\:\:getLockData\(\) should return EonX\\EasyLock\\Interfaces\\WithLockDataInterface\|null but returns Symfony\\Component\\Messenger\\Stamp\\StampInterface\|null#' path: packages/EasyLock/src/Bridge/Symfony/Messenger/ProcessWithLockMiddleware.php @@ -131,6 +105,9 @@ parameters: path: packages/EasyLock/tests/Bridge/Laravel/AbstractLaravelTestCase.php # ---- EasyLogging ---- + - message: '#Call to an undefined method Symfony\\Component\\Config\\Definition\\Builder\\NodeDefinition\:\:children\(\)#' + path: packages/EasyLogging/src/Bridge/Symfony/DependencyInjection/Configuration.php + # ---- EasyPagination ---- - message: '#Call to an undefined method Illuminate\\Support\\ServiceProvider::boot\(\).#' path: packages/EasyPagination/tests/Bridge/Laravel @@ -212,9 +189,6 @@ parameters: path: packages/EasySchedule/src/Bridge/Symfony/TraceableSchedule.php # ---- EasySecurity ---- - - message: '#Method EonX\\EasySecurity\\Bridge\\Symfony\\Helpers\\DeferredSecurityContextResolver\:\:resolve\(\) should return EonX\\EasySecurity\\Interfaces\\SecurityContextInterface but returns object\|null#' - path: packages/EasySecurity/src/Bridge/Symfony/Helpers/DeferredSecurityContextResolver.php - - message: '#Parameter \#2 \$permissions of class EonX\\EasySecurity\\Authorization\\Role constructor expects array\|null, array given#' path: packages/EasySecurity/tests/Authorization/RoleTest.php