diff --git a/application/Espo/Core/Acl/Table/DefaultTable.php b/application/Espo/Core/Acl/Table/DefaultTable.php index 0531146f3a..5065d1accd 100644 --- a/application/Espo/Core/Acl/Table/DefaultTable.php +++ b/application/Espo/Core/Acl/Table/DefaultTable.php @@ -235,6 +235,7 @@ class DefaultTable implements Table $fieldTable = (object) []; $this->applyHighest($aclTable, $fieldTable); + $this->applyAdminMandatory($aclTable, $fieldTable); } foreach ($aclTable as $scope => $data) { @@ -459,13 +460,9 @@ class DefaultTable implements Table } } - protected function applyMandatory(&$table, &$fieldTable): void + protected function applyMandatoryInternal(StdClass $table, StdClass $fieldTable, string $type): void { - if ($this->user->isAdmin()) { - return; - } - - $data = $this->metadata->get(['app', $this->type, 'mandatory', 'scopeLevel']) ?? []; + $data = $this->metadata->get(['app', $this->type, $type, 'scopeLevel']) ?? []; foreach ($data as $scope => $item) { $value = $item; @@ -477,7 +474,7 @@ class DefaultTable implements Table $table->$scope = $value; } - $mandatoryFieldData = $this->metadata->get(['app', $this->type, 'mandatory', 'fieldLevel']) ?? []; + $mandatoryFieldData = $this->metadata->get(['app', $this->type, $type, 'fieldLevel']) ?? []; foreach ($this->getScopeList() as $scope) { if (isset($table->$scope) && $table->$scope === false) { @@ -491,7 +488,7 @@ class DefaultTable implements Table $fieldList = array_keys($this->metadata->get(['entityDefs', $scope, 'fields']) ?? []); $mandatoryScopeFieldData = $this->metadata - ->get(['app', $this->type, 'mandatory', 'scopeFieldLevel', $scope]) ?? []; + ->get(['app', $this->type, $type, 'scopeFieldLevel', $scope]) ?? []; foreach (array_merge($mandatoryFieldData, $mandatoryScopeFieldData) as $field => $item) { if (!in_array($field, $fieldList)) { @@ -522,6 +519,16 @@ class DefaultTable implements Table } } + private function applyMandatory(StdClass $table, StdClass $fieldTable): void + { + $this->applyMandatoryInternal($table, $fieldTable, 'mandatory'); + } + + private function applyAdminMandatory(StdClass $table, StdClass $fieldTable): void + { + $this->applyMandatoryInternal($table, $fieldTable, 'adminMandatory'); + } + protected function applyDisabled(&$table, &$fieldTable): void { if ($this->user->isAdmin()) { diff --git a/application/Espo/Resources/metadata/app/acl.json b/application/Espo/Resources/metadata/app/acl.json index f2132e5cd5..22075ae236 100644 --- a/application/Espo/Resources/metadata/app/acl.json +++ b/application/Espo/Resources/metadata/app/acl.json @@ -120,6 +120,22 @@ } } }, + "adminMandatory": { + "scopeLevel": { + "User": { + "create": "yes", + "read": "all", + "edit": "all", + "delete": "all" + }, + "Team": { + "create": "yes", + "read": "all", + "edit": "all", + "delete": "all" + } + } + }, "valuePermissionList": [ "assignmentPermission", "userPermission", diff --git a/tests/integration/Espo/User/AclAdminTest.php b/tests/integration/Espo/User/AclAdminTest.php new file mode 100644 index 0000000000..ede0663ac6 --- /dev/null +++ b/tests/integration/Espo/User/AclAdminTest.php @@ -0,0 +1,180 @@ +createUser([ + 'userName' => 'admin-test', + 'type' => 'admin', + ]); + + $this->auth('admin-test'); + + $app = $this->createApplication(); + + $processor = $app->getContainer() + ->get('injectableFactory') + ->create(ActionProcessor::class); + + $data = [ + 'userName' => 'test', + 'lastName' => 'Test', + 'password' => '1', + ]; + + $request = $this->createRequest( + 'POST', + [], + ['Content-Type' => 'application/json'], + json_encode($data) + ); + + $response = $this->createMock(Response::class); + + $response + ->expects($this->once()) + ->method('writeBody'); + + $processor->process('User', 'create', $request, $response); + } + + public function testCreateTeam() + { + $this->createUser([ + 'userName' => 'admin-test', + 'type' => 'admin', + ]); + + $this->auth('admin-test'); + + $app = $this->createApplication(); + + $processor = $app->getContainer() + ->get('injectableFactory') + ->create(ActionProcessor::class); + + $data = [ + 'name' => 'test', + ]; + + $request = $this->createRequest( + 'POST', + [], + ['Content-Type' => 'application/json'], + json_encode($data) + ); + + $response = $this->createMock(Response::class); + + $response + ->expects($this->once()) + ->method('writeBody'); + + $processor->process('Team', 'create', $request, $response); + } + + public function testCreateRole() + { + $this->createUser([ + 'userName' => 'admin-test', + 'type' => 'admin', + ]); + + $this->auth('admin-test'); + + $app = $this->createApplication(); + + $processor = $app->getContainer() + ->get('injectableFactory') + ->create(ActionProcessor::class); + + $data = [ + 'name' => 'test', + ]; + + $request = $this->createRequest( + 'POST', + [], + ['Content-Type' => 'application/json'], + json_encode($data) + ); + + $response = $this->createMock(Response::class); + + $response + ->expects($this->once()) + ->method('writeBody'); + + $processor->process('Role', 'create', $request, $response); + } + + public function testCreatePortal() + { + $this->createUser([ + 'userName' => 'admin-test', + 'type' => 'admin', + ]); + + $this->auth('admin-test'); + + $app = $this->createApplication(); + + $processor = $app->getContainer() + ->get('injectableFactory') + ->create(ActionProcessor::class); + + $data = [ + 'name' => 'test', + ]; + + $request = $this->createRequest( + 'POST', + [], + ['Content-Type' => 'application/json'], + json_encode($data) + ); + + $response = $this->createMock(Response::class); + + $response + ->expects($this->once()) + ->method('writeBody'); + + $processor->process('Portal', 'create', $request, $response); + } +}