From 4edb1ca61b3513ab250048228ba7abfb8a13d487 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Wed, 13 Nov 2019 11:36:10 +0200 Subject: [PATCH] Improved twig `authorize()` function to work better with nested rule parameters --- CHANGELOG.md | 1 + system/src/Grav/Common/Twig/TwigExtension.php | 34 ++++++++++++++----- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 23e8dbcad..3f7a42140 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ * Improved twig `|array` filter to work with iterators and objects with `toArray()` method * Updated Flex `SimpleStorage` code to feature match the other storages * Improved user and group ACL to support deny permissions (`Flex Users` only) + * Improved twig `authorize()` function to work better with nested rule parameters 1. [](#bugfix) * Regression: Fixed Grav update bug [#2722](https://github.com/getgrav/grav/issues/2722) diff --git a/system/src/Grav/Common/Twig/TwigExtension.php b/system/src/Grav/Common/Twig/TwigExtension.php index cb4f13252..fc25807b3 100644 --- a/system/src/Grav/Common/Twig/TwigExtension.php +++ b/system/src/Grav/Common/Twig/TwigExtension.php @@ -30,6 +30,7 @@ use Grav\Common\User\Interfaces\UserInterface; use Grav\Common\Utils; use Grav\Common\Yaml; use Grav\Common\Helpers\Base32; +use Grav\Framework\Flex\Interfaces\FlexObjectInterface; use Grav\Framework\Psr7\Response; use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator; use Twig\Environment; @@ -1033,18 +1034,33 @@ class TwigExtension extends AbstractExtension implements GlobalsInterface /** @var UserInterface|null $user */ $user = $this->grav['user'] ?? null; - if (!$user || !$user->authenticated || (isset($user->authorized) && !$user->authorized)) { + if (!$user) { return false; } - $action = (array) $action; - foreach ($action as $key => $perms) { - $prefix = is_int($key) ? '' : $key . '.'; - $perms = $prefix ? (array) $perms : [$perms => true]; - foreach ($perms as $action2 => $authenticated) { - if ($user->authorize($prefix . $action2)) { - return $authenticated; - } + if (is_array($action)) { + if (Utils::isAssoc($action)) { + // Handle nested access structure. + $actions = Utils::arrayFlattenDotNotation($action); + } else { + // Handle simple access list. + $actions = array_combine($action, array_fill(0, count($action), true)); + } + } else { + // Handle single action. + $actions = [(string)$action => true]; + } + + $count = count($actions); + foreach ($actions as $act => $authenticated) { + // Ignore 'admin.super' if it's not the only value to be checked. + if ($act === 'admin.super' && $count > 1 && $user instanceof FlexObjectInterface) { + continue; + } + + $auth = $user->authorize($act); + if (is_bool($auth) && $auth === Utils::isPositive($authenticated)) { + return true; } }