mirror of
https://github.com/getgrav/grav.git
synced 2026-06-09 18:00:46 +02:00
Fixed checking ACL for another user in a Flex Object or Directory, added support getting Flex page permissions
This commit is contained in:
@@ -4,7 +4,10 @@
|
||||
1. [](#bugfix)
|
||||
* Grav 1.7: Fixed error on page initialization [#2753](https://github.com/getgrav/grav/issues/2753)
|
||||
1. [](#improved)
|
||||
* Twig filter `|yaml_serialize`: added support for `JsonSerializable` objects
|
||||
* Twig filter `|yaml_serialize`: added support for `JsonSerializable` objects and other array-like objects
|
||||
* Added support for returning Flex Page specific permissions for admin and testing
|
||||
1. [](#bugfix)
|
||||
* Fixed checking ACL for another user (who is not currently logged in) in a Flex Object or Directory
|
||||
|
||||
# v1.7.0-rc.2
|
||||
## 12/04/2019
|
||||
|
||||
@@ -223,6 +223,7 @@ class UserObject extends FlexObject implements UserInterface, MediaManipulationI
|
||||
return $authorized;
|
||||
}
|
||||
|
||||
// If specific rule isn't hit, check if user is super user.
|
||||
if ($access->authorize('admin.super') === true) {
|
||||
return true;
|
||||
}
|
||||
@@ -521,16 +522,17 @@ class UserObject extends FlexObject implements UserInterface, MediaManipulationI
|
||||
* @param UserInterface $user
|
||||
* @param string $action
|
||||
* @param string $scope
|
||||
* @param bool $isMe
|
||||
* @return bool|null
|
||||
*/
|
||||
protected function isAuthorizedOverride(UserInterface $user, string $action, string $scope): ?bool
|
||||
protected function isAuthorizedOverride(UserInterface $user, string $action, string $scope, bool $isMe = false): ?bool
|
||||
{
|
||||
if ($user instanceof self && $user->getStorageKey() === $this->getStorageKey()) {
|
||||
// User cannot delete his own account, otherwise he has full access.
|
||||
return $action !== 'delete';
|
||||
}
|
||||
|
||||
return parent::isAuthorizedOverride($user, $action, $scope);
|
||||
return parent::isAuthorizedOverride($user, $action, $scope, $isMe);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -48,7 +48,7 @@ class Access implements \JsonSerializable, \IteratorAggregate, \Countable
|
||||
public function authorize(string $action, string $scope = null): ?bool
|
||||
{
|
||||
if (null !== $scope) {
|
||||
$action = "{$scope}.{$action}";
|
||||
$action = $scope !== 'test' ? "{$scope}.{$action}" : $action;
|
||||
}
|
||||
|
||||
return $this->acl[$action] ?? null;
|
||||
|
||||
@@ -17,6 +17,7 @@ use Grav\Common\Page\Traits\PageFormTrait;
|
||||
use Grav\Common\User\Interfaces\UserCollectionInterface;
|
||||
use Grav\Framework\File\Formatter\YamlFormatter;
|
||||
use Grav\Framework\Flex\FlexObject;
|
||||
use Grav\Framework\Flex\Interfaces\FlexCollectionInterface;
|
||||
use Grav\Framework\Flex\Interfaces\FlexObjectInterface;
|
||||
use Grav\Framework\Flex\Interfaces\FlexTranslateInterface;
|
||||
use Grav\Framework\Flex\Pages\Traits\PageAuthorsTrait;
|
||||
@@ -424,10 +425,10 @@ class FlexPageObject extends FlexObject implements PageInterface, MediaManipulat
|
||||
}
|
||||
|
||||
/**
|
||||
* @return UserCollectionInterface|null
|
||||
* @return UserCollectionInterface|FlexCollectionInterface|null
|
||||
* @internal
|
||||
*/
|
||||
protected function loadAccounts(): ?UserCollectionInterface
|
||||
protected function loadAccounts()
|
||||
{
|
||||
return Grav::instance()['accounts'] ?? null;
|
||||
}
|
||||
|
||||
@@ -54,12 +54,17 @@ trait PageAuthorsTrait
|
||||
public function getAuthors(): array
|
||||
{
|
||||
if (null === $this->_authors) {
|
||||
$this->_authors = (array)$this->loadAuthors($this->getNestedProperty('header.authors'));
|
||||
$this->_authors = (array)$this->loadAuthors($this->getNestedProperty('header.authors', []));
|
||||
}
|
||||
|
||||
return $this->_authors;
|
||||
}
|
||||
|
||||
public function getPermissions()
|
||||
{
|
||||
return $this->loadPermissions();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param iterable $authors
|
||||
* @return array<int,UserInterface>
|
||||
@@ -86,13 +91,14 @@ trait PageAuthorsTrait
|
||||
* @param UserInterface $user
|
||||
* @param string $action
|
||||
* @param string $scope
|
||||
* @param bool $isMe
|
||||
* @return bool|null
|
||||
*/
|
||||
protected function isAuthorizedOverride(UserInterface $user, string $action, string $scope): ?bool
|
||||
protected function isAuthorizedOverride(UserInterface $user, string $action, string $scope, bool $isMe): ?bool
|
||||
{
|
||||
$authorized = $this->isAuthorizedByGroup($user, $action, $scope);
|
||||
|
||||
return $authorized ?? parent::isAuthorizedOverride($user, $action, $scope);
|
||||
return $authorized ?? parent::isAuthorizedOverride($user, $action, $scope, $isMe);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,16 +116,28 @@ trait PageAuthorsTrait
|
||||
protected function isAuthorizedByGroup(UserInterface $user, string $action, string $scope): ?bool
|
||||
{
|
||||
$authorized = null;
|
||||
$username = $user->username;
|
||||
|
||||
// In admin we want to check against group permissions.
|
||||
$groups = $this->loadPermissions($user);
|
||||
$pageGroups = $this->loadPermissions();
|
||||
$userGroups = (array)$user->groups;
|
||||
|
||||
/** @var Access $access */
|
||||
foreach ($groups as $access) {
|
||||
foreach ($pageGroups as $group => $access) {
|
||||
if ($group === 'authors') {
|
||||
if (!$this->hasAuthor($username)) {
|
||||
continue;
|
||||
}
|
||||
} elseif (!in_array($group, $userGroups, true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$auth = $access->authorize($action, $scope);
|
||||
if (is_bool($auth)) {
|
||||
if ($auth === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$authorized = true;
|
||||
}
|
||||
}
|
||||
@@ -128,10 +146,9 @@ trait PageAuthorsTrait
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UserInterface $user
|
||||
* @return array
|
||||
*/
|
||||
protected function loadPermissions(UserInterface $user): array
|
||||
protected function loadPermissions(): array
|
||||
{
|
||||
$permissions = $this->getNestedProperty('header.permissions');
|
||||
if (empty($permissions)) {
|
||||
@@ -143,18 +160,8 @@ trait PageAuthorsTrait
|
||||
if (is_string($access)) {
|
||||
$access = $this->resolvePermissions($access);
|
||||
}
|
||||
if ($group === 'author') {
|
||||
// Special case for authors.
|
||||
if ($this->hasAuthor($user->username)) {
|
||||
$list[$group] = new Access($permissions);
|
||||
}
|
||||
} else {
|
||||
$groups = (array)$user->groups;
|
||||
if (in_array($groups, $groups, true)) {
|
||||
$list[$group] = new Access($permissions);
|
||||
}
|
||||
}
|
||||
$list[$group] = $access;
|
||||
|
||||
$list[$group] = new Access($access);
|
||||
}
|
||||
|
||||
return $list;
|
||||
@@ -192,6 +199,6 @@ trait PageAuthorsTrait
|
||||
}
|
||||
|
||||
abstract public function getNestedProperty($property, $default = null, $separator = null);
|
||||
abstract protected function loadAccounts(): ?UserCollectionInterface;
|
||||
abstract protected function loadAccounts();
|
||||
|
||||
}
|
||||
|
||||
@@ -41,13 +41,18 @@ trait FlexAuthorizeTrait
|
||||
{
|
||||
$action = $this->getAuthorizeAction($action);
|
||||
$scope = $scope ?? $this->getAuthorizeScope();
|
||||
$user = $user ?? $this->getActiveUser();
|
||||
|
||||
$isMe = null === $user;
|
||||
if ($isMe) {
|
||||
$user = $this->getActiveUser();
|
||||
}
|
||||
|
||||
if (null === $user) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Finally authorize against given action.
|
||||
return $this->isAuthorizedOverride($user, $action, $scope);
|
||||
return $this->isAuthorizedOverride($user, $action, $scope, $isMe);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -56,11 +61,12 @@ trait FlexAuthorizeTrait
|
||||
* @param UserInterface $user
|
||||
* @param string $action
|
||||
* @param string $scope
|
||||
* @param bool $isMe
|
||||
* @return bool|null
|
||||
*/
|
||||
protected function isAuthorizedOverride(UserInterface $user, string $action, string $scope): ?bool
|
||||
protected function isAuthorizedOverride(UserInterface $user, string $action, string $scope, bool $isMe): ?bool
|
||||
{
|
||||
return $this->isAuthorizedAction($user, $action, $scope);
|
||||
return $this->isAuthorizedAction($user, $action, $scope, $isMe);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -69,9 +75,10 @@ trait FlexAuthorizeTrait
|
||||
* @param UserInterface $user
|
||||
* @param string $action
|
||||
* @param string $scope
|
||||
* @param bool $isMe
|
||||
* @return bool|null
|
||||
*/
|
||||
protected function isAuthorizedAction(UserInterface $user, string $action, string $scope): ?bool
|
||||
protected function isAuthorizedAction(UserInterface $user, string $action, string $scope, bool $isMe): ?bool
|
||||
{
|
||||
// Check if the action has been denied in the flex type configuration.
|
||||
$directory = $this instanceof FlexDirectory ? $this : $this->getFlexDirectory();
|
||||
@@ -88,7 +95,7 @@ trait FlexAuthorizeTrait
|
||||
}
|
||||
|
||||
// Finally authorize the action.
|
||||
return $user->authorize($this->getAuthorizeRule($scope, $action));
|
||||
return $user->authorize($this->getAuthorizeRule($scope, $action), !$isMe ? 'test' : null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user