snapshot of https://github.com/espocrm/espocrm.git (master, 2026-09-18; blobs > 131072B omitted)
Some checks failed
Test / Test on PHP 8.3 (push) Failing after 5s
Test / Test on PHP 8.4 (push) Failing after 4s
Test / Test on PHP 8.5 (push) Failing after 3s
TypeScript static analysis / TypeScript check (push) Failing after 14s
Test Integration on MySQL / Test on PHP 8.3 (push) Failing after 2s
Test Integration on MySQL / Test on PHP 8.5 (push) Failing after 0s
Test Integration on PostgreSQL / Test on PHP 8.4 fix (push) Failing after 1s
Test Integration on PostgreSQL / Test on PHP 8.4 master (push) Failing after 1s

This commit is contained in:
upstream-mirror
2026-09-18 04:19:15 +05:00
commit 7cc7e6b4f3
10077 changed files with 900756 additions and 0 deletions

View File

@@ -0,0 +1,79 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM – Open Source CRM application.
* Copyright (C) 2014-2026 EspoCRM, Inc.
* 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\FieldData,
Acl\Table,
};
class FieldDataTest extends \PHPUnit\Framework\TestCase
{
protected function setUp() : void
{
}
public function testGet1(): void
{
$raw = (object) [
Table::ACTION_EDIT => Table::LEVEL_YES,
Table::ACTION_READ => Table::LEVEL_NO,
];
$data = FieldData::fromRaw($raw);
$this->assertEquals(Table::LEVEL_NO, $data->getRead());
$this->assertEquals(Table::LEVEL_YES, $data->getEdit());
}
public function testGet2(): void
{
$raw = (object) [
Table::ACTION_EDIT => Table::LEVEL_NO,
Table::ACTION_READ => Table::LEVEL_YES,
];
$data = FieldData::fromRaw($raw);
$this->assertEquals(Table::LEVEL_YES, $data->getRead());
$this->assertEquals(Table::LEVEL_NO, $data->getEdit());
}
public function testGetEmpty(): void
{
$raw = (object) [
];
$data = FieldData::fromRaw($raw);
$this->assertEquals(Table::LEVEL_NO, $data->getRead());
$this->assertEquals(Table::LEVEL_NO, $data->getEdit());
}
}

View File

@@ -0,0 +1,65 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM – Open Source CRM application.
* Copyright (C) 2014-2026 EspoCRM, Inc.
* 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\Map;
use Espo\Core\Acl\Map\DefaultCacheKeyProvider;
use Espo\Entities\User;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
class DefaultCacheKeyProviderTest extends TestCase
{
#[DataProvider('provider')]
public function testKey(string $expected, string $userId, ?array $scopes = null): void
{
$user = $this->createMock(User::class);
$user->expects(self::any())
->method('getId')
->willReturn($userId);
$user->expects(self::any())
->method('getScopes')
->willReturn($scopes);
$provider = new DefaultCacheKeyProvider($user);
$this->assertEquals($expected, $provider->get());
}
public static function provider(): array
{
return [
['aclMap/01', '01', null],
['aclMap/01/37f6e5e382faedc68e0769892e78d8d3', '01', ['Admin', 'Global']],
['aclMap/01/99aa06d3014798d86001c324468d497f', '01', []],
];
}
}

View File

@@ -0,0 +1,427 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM – Open Source CRM application.
* Copyright (C) 2014-2026 EspoCRM, Inc.
* 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\Map;
use Espo\Core\Acl\FieldData;
use Espo\Core\Acl\Map\CacheKeyProvider;
use Espo\Core\Acl\Map\DataBuilder;
use Espo\Core\Acl\Map\Map;
use Espo\Core\Acl\Map\MetadataProvider;
use Espo\Core\Acl\ScopeData;
use Espo\Core\Acl\Table;
use Espo\Core\Utils\Cache\DataCacheAccess;
use Espo\Core\Utils\Config\SystemConfig;
use Espo\Core\Utils\DataCache;
use Espo\Core\Utils\FieldUtil;
use Espo\Core\Utils\Log;
use PHPUnit\Framework\TestCase;
use stdClass;
class MapTest extends TestCase
{
private $fieldUtil;
private $table;
private $metadataProvider;
private $cacheKeyProvider;
protected function setUp(): void
{
$this->fieldUtil = $this->createMock(FieldUtil::class);
$this->table = $this->createMock(Table::class);
$this->metadataProvider = $this->createMock(MetadataProvider::class);
$this->cacheKeyProvider = $this->createMock(CacheKeyProvider::class);
}
private function mockTableData(array $scopeData, array $fieldData, array $permissionData): void
{
$returnMap1 = [];
foreach ($scopeData as $scope => $item) {
$returnMap1[] = [$scope, ScopeData::fromRaw($item)];
}
$this->table
->expects($this->any())
->method('getScopeData')
->willReturnMap($returnMap1);
$returnMap2 = [];
foreach ($fieldData as $scope => $item1) {
foreach ($item1 as $field => $item2) {
$returnMap2[] = [$scope, $field, FieldData::fromRaw($item2)];
}
}
$this->table
->expects($this->any())
->method('getFieldData')
->willReturnMap($returnMap2);
$returnMap3 = [];
foreach ($permissionData as $permission => $level) {
$returnMap3[] = [$permission, $level];
}
$this->table
->expects($this->any())
->method('getPermissionLevel')
->willReturnMap($returnMap3);
}
public function testMap1(): void
{
$dataBuilder = new DataBuilder($this->metadataProvider, $this->fieldUtil);
$this->metadataProvider
->expects($this->any())
->method('getScopeList')
->willReturn(['Test1', 'Test2', 'Test3', 'Test4', 'Test5']);
$this->metadataProvider
->expects($this->any())
->method('getPermissionList')
->willReturn(['assignment', 'portal']);
$this->metadataProvider
->expects($this->any())
->method('isScopeEntity')
->willReturnMap([
['Test1', true],
['Test2', true],
['Test3', true],
['Test4', true],
['Test5', false],
]);
$this->metadataProvider
->expects($this->any())
->method('getScopeFieldList')
->willReturnMap([
['Test1', ['field1', 'field2', 'field3', 'field4']],
['Test2', ['field1']],
['Test3', []],
['Test4', []],
['Test5', []],
]);
$this->fieldUtil
->expects($this->any())
->method('getAttributeList')
->willReturnMap([
['Test1', 'field1', ['attr1a', 'attr1b']],
['Test1', 'field2', ['field2']],
['Test1', 'field3', ['field3']],
['Test1', 'field4', ['field4']],
['Test2', 'field1', ['field1']],
]);
$this->mockTableData(
[
'Test1' => (object) [
Table::ACTION_CREATE => Table::LEVEL_YES,
Table::ACTION_READ => Table::LEVEL_TEAM,
],
'Test2' => (object) [
Table::ACTION_CREATE => Table::LEVEL_YES,
Table::ACTION_READ => Table::LEVEL_TEAM,
Table::ACTION_EDIT => Table::LEVEL_OWN,
],
'Test3' => false,
'Test4' => true,
'Test5' => true,
],
[
'Test1' => [
'field1' => (object) [
Table::ACTION_READ => Table::LEVEL_YES,
Table::ACTION_EDIT => Table::LEVEL_NO,
],
'field2' => (object) [
Table::ACTION_READ => Table::LEVEL_NO,
Table::ACTION_EDIT => Table::LEVEL_YES,
],
'field3' => (object) [
Table::ACTION_READ => Table::LEVEL_NO,
Table::ACTION_EDIT => Table::LEVEL_NO,
],
'field4' => (object) [
Table::ACTION_READ => Table::LEVEL_YES,
Table::ACTION_EDIT => Table::LEVEL_YES,
],
],
'Test2' => [
'field1' => (object) [
Table::ACTION_READ => Table::LEVEL_NO,
Table::ACTION_EDIT => Table::LEVEL_NO,
],
],
],
[
'assignment' => Table::LEVEL_YES,
'portal' => Table::LEVEL_NO,
],
);
$expectedData = $this->getExpectedRawData();
$this->cacheKeyProvider->method('get')
->willReturn('key');
$dataCacheAccess = new DataCacheAccess(
dataCache: $this->createMock(DataCache::class),
systemConfig: $this->createMock(SystemConfig::class),
log: $this->createMock(Log::class),
);
$map = new Map(
table: $this->table,
dataBuilder: $dataBuilder,
cacheKeyProvider: $this->cacheKeyProvider,
dataCacheAccess: $dataCacheAccess,
);
$this->assertEquals($expectedData, $map->getData());
$this->assertEquals(
['field2', 'field3'],
$map->getScopeForbiddenFieldList('Test1', Table::ACTION_READ)
);
$this->assertEquals(
['field1', 'field3'],
$map->getScopeForbiddenFieldList('Test1', Table::ACTION_EDIT)
);
$this->assertEquals(
['field2', 'field3'],
$map->getScopeForbiddenAttributeList('Test1', Table::ACTION_READ)
);
$this->assertEquals(
['attr1a', 'attr1b', 'field3'],
$map->getScopeForbiddenAttributeList('Test1', Table::ACTION_EDIT)
);
$this->assertEquals(
['attr1a', 'attr1b', 'field3'],
$map->getScopeForbiddenAttributeList('Test1', Table::ACTION_EDIT)
);
$this->assertEquals(
['field1'],
$map->getScopeForbiddenFieldList('Test2', Table::ACTION_READ)
);
$this->assertEquals(
['field1'],
$map->getScopeForbiddenFieldList('Test2', Table::ACTION_READ)
);
$this->assertEquals(
[],
$map->getScopeForbiddenFieldList('Test3', Table::ACTION_READ)
);
}
private function getExpectedRawData(): stdClass
{
return (object) [
'table' => (object) [
'Test1' => (object) [
'read' => 'team',
'stream' => 'no',
'edit' => 'no',
'delete' => 'no',
'create' => 'yes'
],
'Test2' => (object) [
'read' => 'team',
'stream' => 'no',
'edit' => 'own',
'delete' => 'no',
'create' => 'yes'
],
'Test3' => false,
'Test4' => true,
'Test5' => true
],
'fieldTable' => (object) [
'Test1' => (object) [
'field1' => (object) [
'read' => 'yes',
'edit' => 'no'
],
'field2' => (object) [
'read' => 'no',
'edit' => 'yes'
],
'field3' => (object) [
'read' => 'no',
'edit' => 'no'
]
],
'Test2' => (object) [
'field1' => (object) [
'read' => 'no',
'edit' => 'no'
]
],
'Test3' => (object) [],
'Test4' => (object) []
],
'assignmentPermission' => 'yes',
'portalPermission' => 'no',
'fieldTableQuickAccess' => (object) [
'Test1' => (object) [
'attributes' => (object) [
'read' => (object) [
'yes' => [
'attr1a',
'attr1b'
],
'no' => [
'field2',
'field3'
]
],
'edit' => (object) [
'yes' => [
'field2'
],
'no' => [
'attr1a',
'attr1b',
'field3'
]
]
],
'fields' => (object) [
'read' => (object) [
'yes' => [
'field1'
],
'no' => [
'field2',
'field3'
]
],
'edit' => (object) [
'yes' => [
'field2'
],
'no' => [
'field1',
'field3'
]
]
]
],
'Test2' => (object) [
'attributes' => (object) [
'read' => (object) [
'yes' => [],
'no' => [
'field1'
]
],
'edit' => (object) [
'yes' => [],
'no' => [
'field1'
]
]
],
'fields' => (object) [
'read' => (object) [
'yes' => [],
'no' => [
'field1'
]
],
'edit' => (object) [
'yes' => [],
'no' => [
'field1'
]
]
]
],
'Test3' => (object) [
'attributes' => (object) [
'read' => (object) [
'yes' => [],
'no' => []
],
'edit' => (object) [
'yes' => [],
'no' => []
]
],
'fields' => (object) [
'read' => (object) [
'yes' => [],
'no' => []
],
'edit' => (object) [
'yes' => [],
'no' => []
]
]
],
'Test4' => (object) [
'attributes' => (object) [
'read' => (object) [
'yes' => [],
'no' => []
],
'edit' => (object) [
'yes' => [],
'no' => []
]
],
'fields' => (object) [
'read' => (object) [
'yes' => [],
'no' => []
],
'edit' => (object) [
'yes' => [],
'no' => []
]
]
]
]
];
}
}

View File

@@ -0,0 +1,58 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM – Open Source CRM application.
* Copyright (C) 2014-2026 EspoCRM, Inc.
* 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\Map;
use Espo\Core\Acl\Map\MetadataProvider;
use Espo\Core\Acl\Permission;
use Espo\Core\Utils\Metadata;
use PHPUnit\Framework\TestCase;
class MetadataProviderTest extends TestCase
{
private $metadata;
protected function setUp(): void
{
$this->metadata = $this->createMock(Metadata::class);
}
public function testGetPermissionList(): void
{
$provider = new MetadataProvider($this->metadata);
$this->metadata
->expects($this->once())
->method('get')
->with(['app', 'acl', 'valuePermissionList'])
->willReturn(['assignmentPermission', 'portalPermission']);
$this->assertEquals([Permission::ASSIGNMENT, 'portal'], $provider->getPermissionList());
}
}

View File

@@ -0,0 +1,113 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM – Open Source CRM application.
* Copyright (C) 2014-2026 EspoCRM, Inc.
* 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\AccessChecker\ScopeCheckerData;
use PHPUnit\Framework\TestCase;
class ScopeCheckerDataTest extends TestCase
{
protected function setUp() : void
{
}
public function testCheckerData0()
{
$checkerData = ScopeCheckerData
::createBuilder()
->build();
$this->assertFalse($checkerData->isOwn());
$this->assertFalse($checkerData->inTeam());
$this->assertFalse($checkerData->isShared());
}
public function testCheckerData1()
{
$checkerData = ScopeCheckerData
::createBuilder()
->setIsOwn(true)
->setInTeam(true)
->setIsShared(true)
->build();
$this->assertTrue($checkerData->isOwn());
$this->assertTrue($checkerData->inTeam());
$this->assertTrue($checkerData->isShared());
}
public function testCheckerData2()
{
$checkerData = ScopeCheckerData
::createBuilder()
->setIsOwn(false)
->setInTeamChecker(
function (): bool {
return true;
}
)
->setIsSharedChecker(
function (): bool {
return true;
}
)
->build();
$this->assertFalse($checkerData->isOwn());
$this->assertTrue($checkerData->inTeam());
$this->assertTrue($checkerData->isShared());
}
public function testCheckerData3()
{
$checkerData = ScopeCheckerData
::createBuilder()
->setIsOwnChecker(
function (): bool {
return true;
}
)
->setInTeamChecker(
function (): bool {
return false;
}
)
->setIsSharedChecker(
function (): bool {
return false;
}
)
->build();
$this->assertTrue($checkerData->isOwn());
$this->assertFalse($checkerData->inTeam());
$this->assertFalse($checkerData->isShared());
}
}

View File

@@ -0,0 +1,435 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM – Open Source CRM application.
* Copyright (C) 2014-2026 EspoCRM, Inc.
* 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\AccessChecker\ScopeChecker,
Acl\AccessChecker\ScopeCheckerData,
Acl\ScopeData,
Acl\Table,
};
class ScopeCheckerTest extends \PHPUnit\Framework\TestCase
{
/**
* @var ScopeChecker
*/
private $scopeChecker;
protected function setUp() : void
{
$this->scopeChecker = new ScopeChecker();
}
public function testCheckerNoData1()
{
$data = ScopeData::fromRaw(false);
$result = $this->scopeChecker->check($data);
$this->assertEquals(false, $result);
}
public function testCheckerNoData2()
{
$data = ScopeData::fromRaw(true);
$result = $this->scopeChecker->check($data);
$this->assertEquals(true, $result);
}
public function testCheckerNoData3()
{
$data = ScopeData::fromRaw(
(object) [
Table::ACTION_READ => Table::LEVEL_NO,
],
);
$result = $this->scopeChecker->check($data);
$this->assertEquals(true, $result);
}
public function testCheckerNoData4()
{
$data = ScopeData::fromRaw(
(object) [
Table::ACTION_READ => Table::LEVEL_ALL,
],
);
$result = $this->scopeChecker->check($data);
$this->assertEquals(true, $result);
}
public function testCheckerNoData5()
{
$data = ScopeData::fromRaw(
(object) [
Table::ACTION_READ => Table::LEVEL_TEAM,
],
);
$result = $this->scopeChecker->check($data);
$this->assertEquals(true, $result);
}
public function testCheckerActionNoData1()
{
$data = ScopeData::fromRaw(false);
$result = $this->scopeChecker->check($data, Table::ACTION_CREATE);
$this->assertEquals(false, $result);
}
public function testCheckerActionNoData2()
{
$data = ScopeData::fromRaw(true);
$result = $this->scopeChecker->check($data, Table::ACTION_CREATE);
$this->assertEquals(true, $result);
}
public function testCheckerData1()
{
$checkerData = ScopeCheckerData
::createBuilder()
->setIsOwn(false)
->setInTeam(false)
->build();
$data = ScopeData::fromRaw(
(object) [
Table::ACTION_READ => Table::LEVEL_ALL,
],
);
$result = $this->scopeChecker->check($data, Table::ACTION_READ, $checkerData);
$this->assertEquals(true, $result);
}
public function testCheckerData2()
{
$checkerData = ScopeCheckerData
::createBuilder()
->setIsOwn(false)
->setInTeam(false)
->build();
$data = ScopeData::fromRaw(
(object) [
Table::ACTION_READ => Table::LEVEL_TEAM,
],
);
$result = $this->scopeChecker->check($data, Table::ACTION_READ, $checkerData);
$this->assertEquals(false, $result);
}
public function testCheckerData3()
{
$checkerData = ScopeCheckerData
::createBuilder()
->setIsOwn(false)
->setInTeam(false)
->build();
$data = ScopeData::fromRaw(
(object) [
Table::ACTION_READ => Table::LEVEL_OWN,
],
);
$result = $this->scopeChecker->check($data, Table::ACTION_READ, $checkerData);
$this->assertEquals(false, $result);
}
public function testCheckerData4()
{
$checkerData = ScopeCheckerData
::createBuilder()
->setIsOwn(false)
->setInTeam(false)
->build();
$data = ScopeData::fromRaw(
(object) [
Table::ACTION_READ => Table::LEVEL_NO,
],
);
$result = $this->scopeChecker->check($data, Table::ACTION_READ, $checkerData);
$this->assertEquals(false, $result);
}
public function testCheckerData5()
{
$checkerData = ScopeCheckerData
::createBuilder()
->setIsOwn(false)
->setInTeam(true)
->build();
$data = ScopeData::fromRaw(
(object) [
Table::ACTION_READ => Table::LEVEL_OWN,
],
);
$result = $this->scopeChecker->check($data, Table::ACTION_READ, $checkerData);
$this->assertEquals(false, $result);
}
public function testCheckerData6()
{
$checkerData = ScopeCheckerData
::createBuilder()
->setIsOwn(false)
->setInTeam(true)
->build();
$data = ScopeData::fromRaw(
(object) [
Table::ACTION_READ => Table::LEVEL_TEAM,
],
);
$result = $this->scopeChecker->check($data, Table::ACTION_READ, $checkerData);
$this->assertEquals(true, $result);
}
public function testCheckerData7()
{
$checkerData = ScopeCheckerData
::createBuilder()
->setIsOwn(true)
->setInTeam(true)
->build();
$data = ScopeData::fromRaw(
(object) [
Table::ACTION_READ => Table::LEVEL_TEAM,
],
);
$result = $this->scopeChecker->check($data, Table::ACTION_READ, $checkerData);
$this->assertEquals(true, $result);
}
public function testCheckerData8()
{
$checkerData = ScopeCheckerData
::createBuilder()
->setIsOwn(false)
->setInTeam(false)
->build();
$data = ScopeData::fromRaw(
(object) [
Table::ACTION_CREATE => Table::LEVEL_YES,
],
);
$result = $this->scopeChecker->check($data, Table::ACTION_CREATE, $checkerData);
$this->assertEquals(true, $result);
}
public function testCheckerData9()
{
$checkerData = ScopeCheckerData
::createBuilder()
->setIsOwn(true)
->setInTeam(false)
->build();
$data = ScopeData::fromRaw(
(object) [
Table::ACTION_READ => Table::LEVEL_OWN,
],
);
$result = $this->scopeChecker->check($data, Table::ACTION_READ, $checkerData);
$this->assertEquals(true, $result);
}
public function testCheckerData10()
{
$checkerData = ScopeCheckerData
::createBuilder()
->setIsOwn(true)
->setInTeam(true)
->build();
$data = ScopeData::fromRaw(
(object) [
Table::ACTION_READ => Table::LEVEL_OWN,
],
);
$result = $this->scopeChecker->check($data, Table::ACTION_READ, $checkerData);
$this->assertEquals(true, $result);
}
public function testCheckerData11()
{
$checkerData = ScopeCheckerData
::createBuilder()
->setIsOwn(true)
->setInTeam(false)
->build();
$data = ScopeData::fromRaw(
(object) [
Table::ACTION_READ => Table::LEVEL_TEAM,
],
);
$result = $this->scopeChecker->check($data, Table::ACTION_READ, $checkerData);
$this->assertEquals(true, $result);
}
public function testCheckerData12()
{
$checkerData = ScopeCheckerData
::createBuilder()
->setIsOwn(true)
->setInTeam(true)
->build();
$data = ScopeData::fromRaw(
(object) [],
);
$result = $this->scopeChecker->check($data, Table::ACTION_READ, $checkerData);
$this->assertEquals(false, $result);
}
public function testCheckerData13()
{
$checkerData = ScopeCheckerData
::createBuilder()
->setIsOwn(false)
->setInTeam(false)
->build();
$data = ScopeData::fromRaw(false);
$result = $this->scopeChecker->check($data, Table::ACTION_READ, $checkerData);
$this->assertEquals(false, $result);
}
public function testCheckerDataNoAction1()
{
$checkerData = ScopeCheckerData
::createBuilder()
->setIsOwn(true)
->setInTeam(true)
->build();
$data = ScopeData::fromRaw(false);
$result = $this->scopeChecker->check($data, null, $checkerData);
$this->assertEquals(false, $result);
}
public function testCheckerDataNoAction2()
{
$checkerData = ScopeCheckerData
::createBuilder()
->setIsOwn(false)
->setInTeam(false)
->build();
$data = ScopeData::fromRaw(true);
$result = $this->scopeChecker->check($data, null, $checkerData);
$this->assertEquals(true, $result);
}
public function testCheckerDataNoAction3()
{
$checkerData = ScopeCheckerData
::createBuilder()
->setIsOwn(true)
->setInTeam(true)
->build();
$data = ScopeData::fromRaw(
(object) [
Table::ACTION_READ => Table::LEVEL_TEAM,
],
);
$result = $this->scopeChecker->check($data, null, $checkerData);
$this->assertEquals(true, $result);
}
public function testCheckerDataNoAction4()
{
$checkerData = ScopeCheckerData
::createBuilder()
->setIsOwn(true)
->setInTeam(true)
->build();
$data = ScopeData::fromRaw(
(object) [
Table::ACTION_CREATE => Table::LEVEL_NO,
Table::ACTION_READ => Table::LEVEL_NO,
],
);
$result = $this->scopeChecker->check($data, null, $checkerData);
$this->assertEquals(true, $result);
}
}

View File

@@ -0,0 +1,106 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM – Open Source CRM application.
* Copyright (C) 2014-2026 EspoCRM, Inc.
* 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')->isTrue());
}
}

View File

@@ -0,0 +1,146 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM – Open Source CRM application.
* Copyright (C) 2014-2026 EspoCRM, Inc.
* 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 InvalidArgumentException;
use RuntimeException;
class ScopeDataTest extends \PHPUnit\Framework\TestCase
{
protected function setUp() : void
{
}
public function testBooleanTrue()
{
$data = ScopeData::fromRaw(true);
$this->assertTrue($data->isBoolean());
$this->assertTrue($data->isTrue());
$this->assertFalse($data->isFalse());
$this->assertEquals(Table::LEVEL_NO, $data->getDelete());
}
public function testBooleanFalse()
{
$data = ScopeData::fromRaw(false);
$this->assertTrue($data->isBoolean());
$this->assertTrue($data->isFalse());
$this->assertFalse($data->isTrue());
$this->assertEquals(Table::LEVEL_NO, $data->getDelete());
}
public function testNotBoolean()
{
$data = ScopeData::fromRaw((object) []);
$this->assertFalse($data->isBoolean());
$this->assertFalse($data->isTrue());
$this->assertFalse($data->isFalse());
}
public function testInvalid()
{
$this->expectException(InvalidArgumentException::class);
ScopeData::fromRaw(null);
}
public function testRecord()
{
$raw = (object) [
Table::ACTION_CREATE => Table::LEVEL_YES,
Table::ACTION_READ => Table::LEVEL_ALL,
Table::ACTION_EDIT => Table::LEVEL_TEAM,
Table::ACTION_DELETE => Table::LEVEL_NO,
];
$data = ScopeData::fromRaw($raw);
$this->assertEquals(Table::LEVEL_YES, $data->getCreate());
$this->assertEquals(Table::LEVEL_ALL, $data->getRead());
$this->assertEquals(Table::LEVEL_TEAM, $data->getEdit());
$this->assertEquals(Table::LEVEL_NO, $data->getDelete());
$this->assertTrue($data->hasNotNo());
}
public function testRecordEmpty()
{
$raw = (object) [];
$data = ScopeData::fromRaw($raw);
$this->assertEquals(Table::LEVEL_NO, $data->getDelete());
$this->assertFalse($data->hasNotNo());
}
public function testRecordOnlyNo()
{
$raw = (object) [
Table::ACTION_CREATE => Table::LEVEL_NO,
Table::ACTION_READ => Table::LEVEL_NO,
Table::ACTION_EDIT => Table::LEVEL_NO,
Table::ACTION_DELETE => Table::LEVEL_NO,
];
$data = ScopeData::fromRaw($raw);
$this->assertEquals(Table::LEVEL_NO, $data->getDelete());
$this->assertFalse($data->hasNotNo());
}
public function testAccessingProperty()
{
$this->expectException(RuntimeException::class);
$data = ScopeData::fromRaw(false);
$data->read;
}
public function testBadKey()
{
$this->expectException(RuntimeException::class);
ScopeData::fromRaw((object) [
Table::ACTION_CREATE => false,
]);
}
}

View File

@@ -0,0 +1,65 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM – Open Source CRM application.
* Copyright (C) 2014-2026 EspoCRM, Inc.
* 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\Table;
use Espo\Core\Acl\Table\DefaultCacheKeyProvider;
use Espo\Entities\User;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
class DefaultCacheKeyProviderTest extends TestCase
{
#[DataProvider('provider')]
public function testKey(string $expected, string $userId, ?array $scopes = null): void
{
$user = $this->createMock(User::class);
$user->expects(self::any())
->method('getId')
->willReturn($userId);
$user->expects(self::any())
->method('getScopes')
->willReturn($scopes);
$provider = new DefaultCacheKeyProvider($user);
$this->assertEquals($expected, $provider->get());
}
public static function provider(): array
{
return [
['acl/01', '01', null],
['acl/01/37f6e5e382faedc68e0769892e78d8d3', '01', ['Admin', 'Global']],
['acl/01/99aa06d3014798d86001c324468d497f', '01', []],
];
}
}