From 996fc7d43361720e3749401fd0f005ed3d97404b Mon Sep 17 00:00:00 2001 From: Tobias Gross-Vogt <tgros@tugraz.at> Date: Wed, 23 Nov 2022 13:35:13 +0100 Subject: [PATCH] extending the authorization expression language --- .../FilterExpressionFunctionProvider.php | 40 +++++++++++++++++++ .../MapExpressionFunctionProvider.php | 38 ++++++++++++++++++ .../PhpArrayExpressionFunctionProvider.php | 20 ++++++++++ .../PhpNumericExpressionFunctionProvider.php | 22 ++++++++++ .../PhpStringExpressionFunctionProvider.php | 22 ++++++++++ .../ExpressionLanguage/ExpressionLanguage.php | 29 ++++++++++++++ .../UserAuthorizationChecker.php | 2 +- 7 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 src/Authorization/ExpressionLanguage/ExpressionFunctionProviders/FilterExpressionFunctionProvider.php create mode 100644 src/Authorization/ExpressionLanguage/ExpressionFunctionProviders/MapExpressionFunctionProvider.php create mode 100644 src/Authorization/ExpressionLanguage/ExpressionFunctionProviders/PhpArrayExpressionFunctionProvider.php create mode 100644 src/Authorization/ExpressionLanguage/ExpressionFunctionProviders/PhpNumericExpressionFunctionProvider.php create mode 100644 src/Authorization/ExpressionLanguage/ExpressionFunctionProviders/PhpStringExpressionFunctionProvider.php create mode 100644 src/Authorization/ExpressionLanguage/ExpressionLanguage.php diff --git a/src/Authorization/ExpressionLanguage/ExpressionFunctionProviders/FilterExpressionFunctionProvider.php b/src/Authorization/ExpressionLanguage/ExpressionFunctionProviders/FilterExpressionFunctionProvider.php new file mode 100644 index 0000000..54bb280 --- /dev/null +++ b/src/Authorization/ExpressionLanguage/ExpressionFunctionProviders/FilterExpressionFunctionProvider.php @@ -0,0 +1,40 @@ +<?php + +declare(strict_types=1); + +namespace Dbp\Relay\CoreBundle\Authorization\ExpressionLanguage\ExpressionFunctionProviders; + +use Symfony\Component\ExpressionLanguage\ExpressionFunction; +use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; +use Symfony\Component\ExpressionLanguage\ExpressionLanguage; + +class FilterExpressionFunctionProvider implements ExpressionFunctionProviderInterface +{ + /** @var ExpressionLanguage */ + private $expressionLanguage; + + public function __construct(ExpressionLanguage $expressionLanguage) + { + $this->expressionLanguage = $expressionLanguage; + } + + public function getFunctions(): array + { + return [ + new ExpressionFunction('filter', + function (string $iterableName, string $expression): string { + return sprintf('filter(%s, %s)', $iterableName, $expression); + }, + function ($arguments, iterable $iterable, string $expression): array { + $filteredResult = []; + foreach ($iterable as $key => $value) { + if ($this->expressionLanguage->evaluate($expression, ['key' => $key, 'value' => $value])) { + $filteredResult[] = $value; + } + } + + return $filteredResult; + }), + ]; + } +} diff --git a/src/Authorization/ExpressionLanguage/ExpressionFunctionProviders/MapExpressionFunctionProvider.php b/src/Authorization/ExpressionLanguage/ExpressionFunctionProviders/MapExpressionFunctionProvider.php new file mode 100644 index 0000000..e1d7b00 --- /dev/null +++ b/src/Authorization/ExpressionLanguage/ExpressionFunctionProviders/MapExpressionFunctionProvider.php @@ -0,0 +1,38 @@ +<?php + +declare(strict_types=1); + +namespace Dbp\Relay\CoreBundle\Authorization\ExpressionLanguage\ExpressionFunctionProviders; + +use Symfony\Component\ExpressionLanguage\ExpressionFunction; +use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; +use Symfony\Component\ExpressionLanguage\ExpressionLanguage; + +class MapExpressionFunctionProvider implements ExpressionFunctionProviderInterface +{ + /** @var ExpressionLanguage */ + private $expressionLanguage; + + public function __construct(ExpressionLanguage $expressionLanguage) + { + $this->expressionLanguage = $expressionLanguage; + } + + public function getFunctions(): array + { + return [ + new ExpressionFunction('map', + function (string $iterableName, string $expression): string { + return sprintf('map(%s, %s)', $iterableName, $expression); + }, + function ($arguments, iterable $iterable, string $expression): array { + $transformedResult = []; + foreach ($iterable as $key => $value) { + $transformedResult[$key] = $this->expressionLanguage->evaluate($expression, ['key' => $key, 'value' => $value]); + } + + return $transformedResult; + }), + ]; + } +} diff --git a/src/Authorization/ExpressionLanguage/ExpressionFunctionProviders/PhpArrayExpressionFunctionProvider.php b/src/Authorization/ExpressionLanguage/ExpressionFunctionProviders/PhpArrayExpressionFunctionProvider.php new file mode 100644 index 0000000..db907ca --- /dev/null +++ b/src/Authorization/ExpressionLanguage/ExpressionFunctionProviders/PhpArrayExpressionFunctionProvider.php @@ -0,0 +1,20 @@ +<?php + +declare(strict_types=1); + +namespace Dbp\Relay\CoreBundle\Authorization\ExpressionLanguage\ExpressionFunctionProviders; + +use Symfony\Component\ExpressionLanguage\ExpressionFunction; +use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; + +class PhpArrayExpressionFunctionProvider implements ExpressionFunctionProviderInterface +{ + public function getFunctions(): array + { + return [ + ExpressionFunction::fromPhp('count'), + ExpressionFunction::fromPhp('implode'), + ExpressionFunction::fromPhp('explode'), + ]; + } +} diff --git a/src/Authorization/ExpressionLanguage/ExpressionFunctionProviders/PhpNumericExpressionFunctionProvider.php b/src/Authorization/ExpressionLanguage/ExpressionFunctionProviders/PhpNumericExpressionFunctionProvider.php new file mode 100644 index 0000000..ca7ec43 --- /dev/null +++ b/src/Authorization/ExpressionLanguage/ExpressionFunctionProviders/PhpNumericExpressionFunctionProvider.php @@ -0,0 +1,22 @@ +<?php + +declare(strict_types=1); + +namespace Dbp\Relay\CoreBundle\Authorization\ExpressionLanguage\ExpressionFunctionProviders; + +use Symfony\Component\ExpressionLanguage\ExpressionFunction; +use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; + +class PhpNumericExpressionFunctionProvider implements ExpressionFunctionProviderInterface +{ + public function getFunctions(): array + { + return [ + ExpressionFunction::fromPhp('ceil'), + ExpressionFunction::fromPhp('floor'), + ExpressionFunction::fromPhp('round'), + ExpressionFunction::fromPhp('max'), + ExpressionFunction::fromPhp('min'), + ]; + } +} diff --git a/src/Authorization/ExpressionLanguage/ExpressionFunctionProviders/PhpStringExpressionFunctionProvider.php b/src/Authorization/ExpressionLanguage/ExpressionFunctionProviders/PhpStringExpressionFunctionProvider.php new file mode 100644 index 0000000..1412daf --- /dev/null +++ b/src/Authorization/ExpressionLanguage/ExpressionFunctionProviders/PhpStringExpressionFunctionProvider.php @@ -0,0 +1,22 @@ +<?php + +declare(strict_types=1); + +namespace Dbp\Relay\CoreBundle\Authorization\ExpressionLanguage\ExpressionFunctionProviders; + +use Symfony\Component\ExpressionLanguage\ExpressionFunction; +use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; + +class PhpStringExpressionFunctionProvider implements ExpressionFunctionProviderInterface +{ + public function getFunctions(): array + { + return [ + ExpressionFunction::fromPhp('str_starts_with'), + ExpressionFunction::fromPhp('str_ends_with'), + ExpressionFunction::fromPhp('substr'), + ExpressionFunction::fromPhp('strpos'), + ExpressionFunction::fromPhp('strlen'), + ]; + } +} diff --git a/src/Authorization/ExpressionLanguage/ExpressionLanguage.php b/src/Authorization/ExpressionLanguage/ExpressionLanguage.php new file mode 100644 index 0000000..a997ab8 --- /dev/null +++ b/src/Authorization/ExpressionLanguage/ExpressionLanguage.php @@ -0,0 +1,29 @@ +<?php + +declare(strict_types=1); + +namespace Dbp\Relay\CoreBundle\Authorization\ExpressionLanguage; + +use Dbp\Relay\CoreBundle\Authorization\ExpressionLanguage\ExpressionFunctionProviders\FilterExpressionFunctionProvider; +use Dbp\Relay\CoreBundle\Authorization\ExpressionLanguage\ExpressionFunctionProviders\MapExpressionFunctionProvider; +use Dbp\Relay\CoreBundle\Authorization\ExpressionLanguage\ExpressionFunctionProviders\PhpArrayExpressionFunctionProvider; +use Dbp\Relay\CoreBundle\Authorization\ExpressionLanguage\ExpressionFunctionProviders\PhpNumericExpressionFunctionProvider; +use Dbp\Relay\CoreBundle\Authorization\ExpressionLanguage\ExpressionFunctionProviders\PhpStringExpressionFunctionProvider; +use Psr\Cache\CacheItemPoolInterface; +use Symfony\Component\ExpressionLanguage\ExpressionLanguage as SymfonyExpressionLanguage; + +class ExpressionLanguage extends SymfonyExpressionLanguage +{ + public function __construct(CacheItemPoolInterface $cache = null, array $providers = []) + { + $providers = array_merge([ + new FilterExpressionFunctionProvider($this), + new MapExpressionFunctionProvider($this), + new PhpArrayExpressionFunctionProvider(), + new PhpNumericExpressionFunctionProvider(), + new PhpStringExpressionFunctionProvider(), + ], $providers); + + parent::__construct($cache, $providers); + } +} diff --git a/src/Authorization/UserAuthorizationChecker.php b/src/Authorization/UserAuthorizationChecker.php index dda9986..ba961d6 100644 --- a/src/Authorization/UserAuthorizationChecker.php +++ b/src/Authorization/UserAuthorizationChecker.php @@ -4,8 +4,8 @@ declare(strict_types=1); namespace Dbp\Relay\CoreBundle\Authorization; +use Dbp\Relay\CoreBundle\Authorization\ExpressionLanguage\ExpressionLanguage; use Dbp\Relay\CoreBundle\Helpers\Tools; -use Symfony\Component\ExpressionLanguage\ExpressionLanguage; class UserAuthorizationChecker { -- GitLab