acl resolve foreign to boolean

This commit is contained in:
Yuri Kuznetsov
2024-07-09 13:11:56 +03:00
parent 06c173486e
commit f69eed63d7
5 changed files with 187 additions and 33 deletions
@@ -52,9 +52,7 @@ class DefaultTable implements Table
protected string $type = 'acl';
protected string $defaultAclType = 'recordAllTeamOwnNo';
/**
* @var string[]
*/
/** @var string[] */
private $actionList = [
self::ACTION_READ,
self::ACTION_STREAM,
@@ -63,16 +61,12 @@ class DefaultTable implements Table
self::ACTION_CREATE,
];
/**
* @var string[]
*/
/** @var string[] */
private $booleanActionList = [
self::ACTION_CREATE,
];
/**
* @var string[]
*/
/** @var string[] */
protected $levelList = [
self::LEVEL_YES,
self::LEVEL_ALL,
@@ -81,30 +75,23 @@ class DefaultTable implements Table
self::LEVEL_NO,
];
/**
* @var string[]
*/
/** @var string[] */
private $fieldActionList = [
self::ACTION_READ,
self::ACTION_EDIT,
];
/**
* @var string[]
*/
/** @var string[] */
protected $fieldLevelList = [
self::LEVEL_YES,
self::LEVEL_NO,
];
private stdClass $data;
private string $cacheKey;
/**
* @var string[]
*/
/** @var string[] */
private $valuePermissionList = [];
private ScopeDataResolver $scopeDataResolver;
public function __construct(
private RoleListProvider $roleListProvider,
@@ -112,7 +99,7 @@ class DefaultTable implements Table
protected User $user,
Config $config,
protected Metadata $metadata,
DataCache $dataCache
DataCache $dataCache,
) {
$this->data = (object) [
@@ -135,14 +122,15 @@ class DefaultTable implements Table
$cachedData = $dataCache->get($this->cacheKey);
$this->data = $cachedData;
}
else {
} else {
$this->load();
if ($config->get('useCache')) {
$dataCache->store($this->cacheKey, $this->data);
}
}
$this->scopeDataResolver = new ScopeDataResolver($this);
}
/**
@@ -156,11 +144,7 @@ class DefaultTable implements Table
$data = $this->data->scopes->$scope;
if (is_string($data)) {
return $this->getScopeData($data);
}
return ScopeData::fromRaw($data);
return $this->scopeDataResolver->resolve($data);
}
/**
@@ -0,0 +1,66 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM Open Source CRM application.
* Copyright (C) 2014-2024 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
* Website: https://www.espocrm.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\Acl\Table;
use Espo\Core\Acl\ScopeData;
use Espo\Core\Acl\Table;
/**
* @internal
*/
class ScopeDataResolver
{
public function __construct(
private Table $table,
) {}
public function resolve(mixed $data): ScopeData
{
if (!is_string($data)) {
return ScopeData::fromRaw($data);
}
$foreignScope = $data;
$isBoolean = false;
if (str_starts_with($data, 'boolean:')) {
[, $foreignScope] = explode(':', $data, 2);
$isBoolean = true;
}
$scopeData = $this->table->getScopeData($foreignScope);
if ($isBoolean && !$scopeData->isBoolean()) {
return ScopeData::fromRaw($scopeData->hasNotNo());
}
return $scopeData;
}
}
+1 -1
View File
@@ -96,7 +96,7 @@
"type": "object",
"description": "A scope level.",
"additionalProperties": {
"description": "A scope. True enables access to scopes that don't have actions. False fully restricts access to a scope. A string value makes the framework to use roles from another scope and apply it to our scope. It can be useful to have roles only for one parent scope, when child scopes uses roles of the parent scope.",
"description": "A scope. True enables access to scopes that don't have actions. False fully restricts access to a scope. A string value makes the framework to use roles from another scope and apply it to our scope. It can be useful to have roles only for one parent scope, when child scopes uses roles of the parent scope. `boolean:{scope}` format will convert a foreign scope data to the boolean type.",
"anyOf": [
{
"type": "object",
@@ -0,0 +1,106 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM Open Source CRM application.
* Copyright (C) 2014-2024 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
* Website: https://www.espocrm.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace tests\unit\Espo\Core\Acl;
use Espo\Core\Acl\ScopeData;
use Espo\Core\Acl\Table;
use PHPUnit\Framework\TestCase;
class ScopeDataResolverTest extends TestCase
{
public function testResolve1(): void
{
$table = $this->createMock(Table::class);
$resolver = new Table\ScopeDataResolver($table);
$table->expects($this->once())
->method('getScopeData')
->with('Test')
->willReturn(ScopeData::fromRaw(true));
$this->assertTrue($resolver->resolve('Test')->isTrue());
}
public function testResolve2(): void
{
$table = $this->createMock(Table::class);
$resolver = new Table\ScopeDataResolver($table);
$table->expects($this->once())
->method('getScopeData')
->willReturnMap([
['Test', ScopeData::fromRaw(false)]
]);
$this->assertTrue($resolver->resolve('Test')->isFalse());
}
public function testResolve3(): void
{
$table = $this->createMock(Table::class);
$resolver = new Table\ScopeDataResolver($table);
$table->expects($this->once())
->method('getScopeData')
->with('Test')
->willReturn(ScopeData::fromRaw((object) ['create' => 'yes', 'edit' => 'no']));
$result = $resolver->resolve('Test');
$this->assertEquals('yes', $result->getCreate());
$this->assertEquals('no', $result->getEdit());
}
public function testResolve4(): void
{
$table = $this->createMock(Table::class);
$resolver = new Table\ScopeDataResolver($table);
$table->expects($this->once())
->method('getScopeData')
->with('Test')
->willReturn(ScopeData::fromRaw((object) ['create' => 'yes', 'edit' => 'no']));
$this->assertTrue($resolver->resolve('boolean:Test')->isTrue());
}
public function testResolve5(): void
{
$table = $this->createMock(Table::class);
$resolver = new Table\ScopeDataResolver($table);
$table->expects($this->once())
->method('getScopeData')
->with('Test')
->willReturn(ScopeData::fromRaw((object) ['create' => 'no', 'edit' => 'no']));
$this->assertTrue($resolver->resolve('boolean:Test')->isFalse());
}
}
+2 -4
View File
@@ -29,10 +29,8 @@
namespace tests\unit\Espo\Core\Acl;
use Espo\Core\{
Acl\ScopeData,
Acl\Table,
};
use Espo\Core\Acl\ScopeData;
use Espo\Core\Acl\Table;
use InvalidArgumentException;
use RuntimeException;