From 45539289fd7755a0b6922ca1ea45c44fc592cb90 Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Sat, 3 Apr 2021 18:39:45 +0300 Subject: [PATCH] acl refactoring --- application/Espo/Core/Acl.php | 8 ++++ application/Espo/Core/Acl/Acl.php | 12 +++++- application/Espo/Core/Acl/EntityAcl.php | 2 + application/Espo/Core/AclManager.php | 39 ++++++++++++++++--- application/Espo/Core/AclPortal/Portal.php | 10 ----- .../Espo/Core/AclPortal/PortalScopeAcl.php | 4 +- application/Espo/Core/Portal/AclManager.php | 35 ++++++++++------- 7 files changed, 79 insertions(+), 31 deletions(-) diff --git a/application/Espo/Core/Acl.php b/application/Espo/Core/Acl.php index aa8ac240e3..09971f0339 100644 --- a/application/Espo/Core/Acl.php +++ b/application/Espo/Core/Acl.php @@ -98,6 +98,14 @@ class Acl return $this->aclManager->checkReadOnlyOwn($this->user, $scope); } + /** + * Whether 'read' access is set to 'all' for a specific scope. + */ + public function checkReadAll(string $scope): bool + { + return $this->aclManager->checkReadAll($this->user, $scope); + } + /** * Check a scope or entity. If $action is omitted, it will check whether a scope level is set to 'enabled'. */ diff --git a/application/Espo/Core/Acl/Acl.php b/application/Espo/Core/Acl/Acl.php index 2e59240308..d6f6fe9e64 100644 --- a/application/Espo/Core/Acl/Acl.php +++ b/application/Espo/Core/Acl/Acl.php @@ -92,7 +92,12 @@ class Acl implements ScopeAcl, EntityAcl, EntityDeleteAcl return $this->checkScopeInternal($user, $data, $action); } - public function checkReadOnlyTeam(User $user, ScopeData $data): bool + public function getReadLevel(User $user, ScopeData $data) : string + { + return $data->getRead(); + } + + /*public function checkReadOnlyTeam(User $user, ScopeData $data): bool { return $data->getRead() === Table::LEVEL_TEAM; } @@ -107,6 +112,11 @@ class Acl implements ScopeAcl, EntityAcl, EntityDeleteAcl return $data->getRead() === Table::LEVEL_OWN; } + public function checkReadAll(User $user, ScopeData $data): bool + { + return $data->getRead() === Table::LEVEL_ALL; + }*/ + protected function checkScopeInternal( User $user, ScopeData $data, diff --git a/application/Espo/Core/Acl/EntityAcl.php b/application/Espo/Core/Acl/EntityAcl.php index 546a1d9e62..494621d8ff 100644 --- a/application/Espo/Core/Acl/EntityAcl.php +++ b/application/Espo/Core/Acl/EntityAcl.php @@ -38,4 +38,6 @@ interface EntityAcl public function checkEntity(User $user, Entity $entity, ScopeData $data, string $action = Table::ACTION_READ): bool; public function getOwnerUserIdAttribute(Entity $entity): ?string; + + public function getReadLevel(User $user, ScopeData $data) : string; } diff --git a/application/Espo/Core/AclManager.php b/application/Espo/Core/AclManager.php index 7adb5e4ecb..b44344c156 100644 --- a/application/Espo/Core/AclManager.php +++ b/application/Espo/Core/AclManager.php @@ -110,6 +110,17 @@ class AclManager return $this->implementationHashMap[$scope]; } + protected function getEntityImplementation(string $scope): EntityAcl + { + $impl = $this->getImplementation($scope); + + if (!$impl instanceof EntityAcl) { + throw new RuntimeException("Acl must implement EntityAcl interface."); + } + + return $impl; + } + protected function getTable(User $user): Table { $key = $user->getId(); @@ -163,7 +174,9 @@ class AclManager { $data = $this->getTable($user)->getScopeData($scope); - return $this->getImplementation($scope)->checkReadNo($user, $data); + $impl = $this->getEntityImplementation($scope); + + return $impl->getReadLevel($user, $data) === Table::LEVEL_NO; } /** @@ -173,7 +186,9 @@ class AclManager { $data = $this->getTable($user)->getScopeData($scope); - return $this->getImplementation($scope)->checkReadOnlyTeam($user, $data); + $impl = $this->getEntityImplementation($scope); + + return $impl->getReadLevel($user, $data) === Table::LEVEL_TEAM; } /** @@ -183,7 +198,21 @@ class AclManager { $data = $this->getTable($user)->getScopeData($scope); - return $this->getImplementation($scope)->checkReadOnlyOwn($user, $data); + $impl = $this->getEntityImplementation($scope); + + return $impl->getReadLevel($user, $data) === Table::LEVEL_OWN; + } + + /** + * Whether 'read' access is set to 'all' for a specific scope. + */ + public function checkReadAll(User $user, string $scope): bool + { + $data = $this->getTable($user)->getScopeData($scope); + + $impl = $this->getEntityImplementation($scope); + + return $impl->getReadLevel($user, $data) === Table::LEVEL_ALL; } /** @@ -288,7 +317,7 @@ class AclManager */ public function checkIsOwner(User $user, Entity $entity): bool { - return (bool) $this->getImplementation($entity->getEntityType())->checkIsOwner($user, $entity); + return (bool) $this->getEntityImplementation($entity->getEntityType())->checkIsOwner($user, $entity); } /** @@ -296,7 +325,7 @@ class AclManager */ public function checkInTeam(User $user, Entity $entity): bool { - return (bool) $this->getImplementation($entity->getEntityType())->checkInTeam($user, $entity); + return (bool) $this->getEntityImplementation($entity->getEntityType())->checkInTeam($user, $entity); } /** diff --git a/application/Espo/Core/AclPortal/Portal.php b/application/Espo/Core/AclPortal/Portal.php index a3f2e0011c..6f29522923 100644 --- a/application/Espo/Core/AclPortal/Portal.php +++ b/application/Espo/Core/AclPortal/Portal.php @@ -133,16 +133,6 @@ trait Portal return false; } - public function checkReadOnlyAccount(User $user, ScopeData $data) : bool - { - return $data->getRead() === Table::LEVEL_ACCOUNT; - } - - public function checkReadOnlyContact(User $user, ScopeData $data) : bool - { - return $data->getRead() === Table::LEVEL_CONTACT; - } - /** * @return bool */ diff --git a/application/Espo/Core/AclPortal/PortalScopeAcl.php b/application/Espo/Core/AclPortal/PortalScopeAcl.php index 1d0de85543..fa8b02199f 100644 --- a/application/Espo/Core/AclPortal/PortalScopeAcl.php +++ b/application/Espo/Core/AclPortal/PortalScopeAcl.php @@ -29,7 +29,9 @@ namespace Espo\Core\AclPortal; -interface PortalScopeAcl +use Espo\Core\Acl\ScopeAcl; + +interface PortalScopeAcl extends ScopeAcl { } diff --git a/application/Espo/Core/Portal/AclManager.php b/application/Espo/Core/Portal/AclManager.php index 4acc18bb14..27a3922321 100644 --- a/application/Espo/Core/Portal/AclManager.php +++ b/application/Espo/Core/Portal/AclManager.php @@ -124,24 +124,28 @@ class AclManager extends BaseAclManager { $data = $this->getTable($user)->getScopeData($scope); - return $this->getImplementation($scope)->checkReadOnlyAccount($user, $data); + $impl = $this->getEntityImplementation($scope); + + return $impl->getReadLevel($user, $data) === Table::LEVEL_ACCOUNT; } public function checkReadOnlyContact(User $user, string $scope): bool { $data = $this->getTable($user)->getScopeData($scope); - return $this->getImplementation($scope)->checkReadOnlyContact($user, $data); + $impl = $this->getEntityImplementation($scope); + + return $impl->getReadLevel($user, $data) === Table::LEVEL_CONTACT; } public function checkInAccount(User $user, Entity $entity): bool { - return (bool) $this->getImplementation($entity->getEntityType())->checkInAccount($user, $entity); + return (bool) $this->getEntityImplementation($entity->getEntityType())->checkInAccount($user, $entity); } public function checkIsOwnContact(User $user, Entity $entity): bool { - return (bool) $this->getImplementation($entity->getEntityType())->checkIsOwnContact($user, $entity); + return (bool) $this->getEntityImplementation($entity->getEntityType())->checkIsOwnContact($user, $entity); } public function getMap(User $user): StdClass @@ -174,20 +178,16 @@ class AclManager extends BaseAclManager public function checkReadOnlyTeam(User $user, string $scope): bool { if ($this->checkUserIsNotPortal($user)) { - $data = $this->getTable($user)->getScopeData($scope); - - return $this->mainManager->checkReadOnlyTeam($user, $data); + return $this->mainManager->checkReadOnlyTeam($user, $scope); } - return parent::checkReadOnlyTeam($user, $scope); + return false; } public function checkReadNo(User $user, string $scope): bool { if ($this->checkUserIsNotPortal($user)) { - $data = $this->getTable($user)->getScopeData($scope); - - return $this->mainManager->checkReadNo($user, $data); + return $this->mainManager->checkReadNo($user, $scope); } return parent::checkReadNo($user, $scope); @@ -196,14 +196,21 @@ class AclManager extends BaseAclManager public function checkReadOnlyOwn(User $user, string $scope): bool { if ($this->checkUserIsNotPortal($user)) { - $data = $this->getTable($user)->getScopeData($scope); - - return $this->mainManager->checkReadOnlyOwn($user, $data); + return $this->mainManager->checkReadOnlyOwn($user, $scope); } return parent::checkReadOnlyOwn($user, $scope); } + public function checkReadAll(User $user, string $scope): bool + { + if ($this->checkUserIsNotPortal($user)) { + return $this->mainManager->checkReadAll($user, $scope); + } + + return parent::checkReadAll($user, $scope); + } + public function check(User $user, $subject, ?string $action = null): bool { if ($this->checkUserIsNotPortal($user)) {