From ad1dece946a906c53e8709863ce021fa122984da Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Sat, 17 Apr 2021 10:33:26 +0300 Subject: [PATCH] new acl usage --- .../Acl/Import/AccessChecker.php} | 28 ++++-- .../Acl/Note/AccessChecker.php} | 86 ++++++++++++------- .../Classes/Acl/Note/OwnershipChecker.php | 50 +++++++++++ .../Acl/Notification/OwnershipChecker.php} | 12 +-- .../Acl/ScheduledJob/AccessChecker.php} | 44 ++++++---- .../Acl/Team/OwnershipChecker.php} | 14 +-- .../metadata/aclDefs/ActionHistoryRecord.json | 2 +- .../metadata/aclDefs/Attachment.json | 2 +- .../Resources/metadata/aclDefs/Email.json | 2 +- .../metadata/aclDefs/EmailFilter.json | 2 +- .../Resources/metadata/aclDefs/Import.json | 3 + .../Espo/Resources/metadata/aclDefs/Note.json | 4 + .../metadata/aclDefs/Notification.json | 3 + .../metadata/aclDefs/ScheduledJob.json | 3 + .../Espo/Resources/metadata/aclDefs/Team.json | 3 + 15 files changed, 187 insertions(+), 71 deletions(-) rename application/Espo/{Acl/Import.php => Classes/Acl/Import/AccessChecker.php} (71%) rename application/Espo/{Acl/Note.php => Classes/Acl/Note/AccessChecker.php} (61%) create mode 100644 application/Espo/Classes/Acl/Note/OwnershipChecker.php rename application/Espo/{Acl/Notification.php => Classes/Acl/Notification/OwnershipChecker.php} (86%) rename application/Espo/{Acl/ScheduledJob.php => Classes/Acl/ScheduledJob/AccessChecker.php} (60%) rename application/Espo/{Acl/Team.php => Classes/Acl/Team/OwnershipChecker.php} (87%) create mode 100644 application/Espo/Resources/metadata/aclDefs/Import.json create mode 100644 application/Espo/Resources/metadata/aclDefs/Note.json create mode 100644 application/Espo/Resources/metadata/aclDefs/Notification.json create mode 100644 application/Espo/Resources/metadata/aclDefs/ScheduledJob.json create mode 100644 application/Espo/Resources/metadata/aclDefs/Team.json diff --git a/application/Espo/Acl/Import.php b/application/Espo/Classes/Acl/Import/AccessChecker.php similarity index 71% rename from application/Espo/Acl/Import.php rename to application/Espo/Classes/Acl/Import/AccessChecker.php index b2cca57ff0..3c10f1ab49 100644 --- a/application/Espo/Acl/Import.php +++ b/application/Espo/Classes/Acl/Import/AccessChecker.php @@ -27,20 +27,36 @@ * these Appropriate Legal Notices must retain the display of the "EspoCRM" word. ************************************************************************/ -namespace Espo\Acl; +namespace Espo\Classes\Acl\Import; -use Espo\Entities\User as EntityUser; +use Espo\Entities\User; use Espo\ORM\Entity; use Espo\Core\{ - Acl\Acl, Acl\ScopeData, + Acl\AccessEntityReadChecker, + Acl\AccessEntityDeleteChecker, }; -class Import extends Acl +class AccessChecker implements AccessEntityReadChecker, AccessEntityDeleteChecker { - public function checkEntityRead(EntityUser $user, Entity $entity, ScopeData $data): bool + public function check(User $user, ScopeData $data): bool + { + return $data->isTrue(); + } + + public function checkRead(User $user, ScopeData $data): bool + { + return $data->isTrue(); + } + + public function checkDelete(User $user, ScopeData $data): bool + { + return $data->isTrue(); + } + + public function checkEntityRead(User $user, Entity $entity, ScopeData $data): bool { if ($user->isAdmin()) { return true; @@ -53,7 +69,7 @@ class Import extends Acl return false; } - public function checkEntityDelete(EntityUser $user, Entity $entity, ScopeData $data): bool + public function checkEntityDelete(User $user, Entity $entity, ScopeData $data): bool { if ($user->isAdmin()) { return true; diff --git a/application/Espo/Acl/Note.php b/application/Espo/Classes/Acl/Note/AccessChecker.php similarity index 61% rename from application/Espo/Acl/Note.php rename to application/Espo/Classes/Acl/Note/AccessChecker.php index d5ac22f288..a476e67632 100644 --- a/application/Espo/Acl/Note.php +++ b/application/Espo/Classes/Acl/Note/AccessChecker.php @@ -27,62 +27,82 @@ * these Appropriate Legal Notices must retain the display of the "EspoCRM" word. ************************************************************************/ -namespace Espo\Acl; +namespace Espo\Classes\Acl\Note; -use Espo\Entities\User as EntityUser; +use Espo\Entities\User; use Espo\ORM\Entity; use Espo\Core\{ - Acl\Acl, Acl\ScopeData, - Acl\Table, + Acl\DefaultAccessChecker, + Acl\AccessEntityCREDChecker, + Acl\Traits\DefaultAccessCheckerDependency, + AclManager, + ORM\EntityManager, + Utils\Config, }; -use Exception; use DateTime; +use Exception; -class Note extends Acl +class AccessChecker implements AccessEntityCREDChecker { - protected $deleteThresholdPeriod = '1 month'; + use DefaultAccessCheckerDependency; - protected $editThresholdPeriod = '7 days'; + private const EDIT_PERIOD = '7 days'; - public function checkIsOwner(EntityUser $user, Entity $entity) + private const DELETE_PERIOD = '1 month'; + + private $defaultAccessChecker; + + private $aclManager; + + private $entityManager; + + private $config; + + public function __construct( + DefaultAccessChecker $defaultAccessChecker, + AclManager $aclManager, + EntityManager $entityManager, + Config $config + ) { + $this->defaultAccessChecker = $defaultAccessChecker; + $this->aclManager = $aclManager; + $this->entityManager = $entityManager; + $this->config = $config; + } + + public function checkEntityCreate(User $user, Entity $entity, ScopeData $data): bool { - if ($entity->get('type') === 'Post' && $user->id === $entity->get('createdById')) { + $parentId = $entity->get('parentId'); + $parentType = $entity->get('parentType'); + + if (!$parentId || !$parentType) { + return true; + } + + $parent = $this->entityManager->getEntity($parentType, $parentId); + + if ($parent && $this->aclManager->checkEntityStream($user, $parent)) { return true; } return false; } - public function checkEntityCreate(EntityUser $user, Entity $entity, ScopeData $data): bool - { - if (!$entity->get('parentId') || !$entity->get('parentType')) { - return true; - } - - $parent = $this->entityManager->getEntity($entity->get('parentType'), $entity->get('parentId')); - - if ($parent && $this->aclManager->checkEntity($user, $parent, 'stream')) { - return true; - } - - return false; - } - - public function checkEntityEdit(EntityUser $user, Entity $entity, ScopeData $data): bool + public function checkEntityEdit(User $user, Entity $entity, ScopeData $data): bool { if ($user->isAdmin()) { return true; } - if (!$this->checkEntity($user, $entity, $data, Table::ACTION_EDIT)) { + if (!$this->defaultAccessChecker->checkEntityEdit($user, $entity, $data)) { return false; } - if (!$this->checkIsOwner($user, $entity)) { + if (!$this->aclManager->checkOwnershipOwn($user, $entity)) { return true; } @@ -93,7 +113,7 @@ class Note extends Acl } $noteEditThresholdPeriod = - '-' . $this->config->get('noteEditThresholdPeriod', $this->editThresholdPeriod); + '-' . $this->config->get('noteEditThresholdPeriod', self::EDIT_PERIOD); $dt = new DateTime(); @@ -111,17 +131,17 @@ class Note extends Acl return true; } - public function checkEntityDelete(EntityUser $user, Entity $entity, ScopeData $data): bool + public function checkEntityDelete(User $user, Entity $entity, ScopeData $data): bool { if ($user->isAdmin()) { return true; } - if (!$this->checkEntity($user, $entity, $data, Table::ACTION_DELETE)) { + if (!$this->defaultAccessChecker->checkEntityDelete($user, $entity, $data)) { return false; } - if (!$this->checkIsOwner($user, $entity)) { + if (!$this->aclManager->checkOwnershipOwn($user, $entity)) { return true; } @@ -132,7 +152,7 @@ class Note extends Acl } $deleteThresholdPeriod = - '-' . $this->config->get('noteDeleteThresholdPeriod', $this->deleteThresholdPeriod); + '-' . $this->config->get('noteDeleteThresholdPeriod', self::DELETE_PERIOD); $dt = new DateTime(); diff --git a/application/Espo/Classes/Acl/Note/OwnershipChecker.php b/application/Espo/Classes/Acl/Note/OwnershipChecker.php new file mode 100644 index 0000000000..bbbcd1e17f --- /dev/null +++ b/application/Espo/Classes/Acl/Note/OwnershipChecker.php @@ -0,0 +1,50 @@ +get('type') === 'Post' && $user->getId() === $entity->get('createdById')) { + return true; + } + + return false; + } +} diff --git a/application/Espo/Acl/Notification.php b/application/Espo/Classes/Acl/Notification/OwnershipChecker.php similarity index 86% rename from application/Espo/Acl/Notification.php rename to application/Espo/Classes/Acl/Notification/OwnershipChecker.php index 347870173f..2a98b5609b 100644 --- a/application/Espo/Acl/Notification.php +++ b/application/Espo/Classes/Acl/Notification/OwnershipChecker.php @@ -27,17 +27,19 @@ * these Appropriate Legal Notices must retain the display of the "EspoCRM" word. ************************************************************************/ -namespace Espo\Acl; +namespace Espo\Classes\Acl\Notification; -use Espo\Entities\User as EntityUser; +use Espo\Entities\User; use Espo\ORM\Entity; -use Espo\Core\Acl\Acl; +use Espo\Core\{ + Acl\OwnershipOwnChecker, +}; -class Notification extends Acl +class OwnershipChecker implements OwnershipOwnChecker { - public function checkIsOwner(EntityUser $user, Entity $entity) + public function checkOwn(User $user, Entity $entity): bool { if ($user->getId() === $entity->get('userId')) { return true; diff --git a/application/Espo/Acl/ScheduledJob.php b/application/Espo/Classes/Acl/ScheduledJob/AccessChecker.php similarity index 60% rename from application/Espo/Acl/ScheduledJob.php rename to application/Espo/Classes/Acl/ScheduledJob/AccessChecker.php index 3a6861994a..41cd2bd9ce 100644 --- a/application/Espo/Acl/ScheduledJob.php +++ b/application/Espo/Classes/Acl/ScheduledJob/AccessChecker.php @@ -27,53 +27,63 @@ * these Appropriate Legal Notices must retain the display of the "EspoCRM" word. ************************************************************************/ -namespace Espo\Acl; +namespace Espo\Classes\Acl\ScheduledJob; -use Espo\Entities\User as EntityUser; +use Espo\Entities\User; use Espo\ORM\Entity; use Espo\Core\{ - Acl\Acl, Acl\ScopeData, - Acl\Table, + Acl\DefaultAccessChecker, + Acl\AccessEntityCREDChecker, + Acl\Traits\DefaultAccessCheckerDependency, }; -class ScheduledJob extends Acl +class AccessChecker implements AccessEntityCREDChecker { - public function checkEntityRead(EntityUser $user, Entity $entity, ScopeData $data): bool - { - if ($entity->get('isInternal')) { - return false; - } + use DefaultAccessCheckerDependency; - return $this->checkEntity($user, $entity, $data, Table::ACTION_READ); + private $defaultAccessChecker; + + public function __construct(DefaultAccessChecker $defaultAccessChecker) + { + $this->defaultAccessChecker = $defaultAccessChecker; } - public function checkEntityEdit(EntityUser $user, Entity $entity, ScopeData $data): bool + public function checkEntityCreate(User $user, Entity $entity, ScopeData $data): bool { if ($entity->get('isInternal')) { return false; } - return $this->checkEntity($user, $entity, $data, Table::ACTION_EDIT); + return $this->defaultAccessChecker->checkEntityCreate($user, $entity, $data); } - public function checkEntityDelete(EntityUser $user, Entity $entity, ScopeData $data): bool + public function checkEntityRead(User $user, Entity $entity, ScopeData $data): bool { if ($entity->get('isInternal')) { return false; } - return $this->checkEntity($user, $entity, $data, Table::ACTION_DELETE); + return $this->defaultAccessChecker->checkEntityRead($user, $entity, $data); } - public function checkEntityCreate(EntityUser $user, Entity $entity, ScopeData $data): bool + public function checkEntityEdit(User $user, Entity $entity, ScopeData $data): bool { if ($entity->get('isInternal')) { return false; } - return $this->checkEntity($user, $entity, $data, Table::ACTION_CREATE); + return $this->defaultAccessChecker->checkEntityEdit($user, $entity, $data); + } + + public function checkEntityDelete(User $user, Entity $entity, ScopeData $data): bool + { + if ($entity->get('isInternal')) { + return false; + } + + return $this->defaultAccessChecker->checkEntityDelete($user, $entity, $data); } } diff --git a/application/Espo/Acl/Team.php b/application/Espo/Classes/Acl/Team/OwnershipChecker.php similarity index 87% rename from application/Espo/Acl/Team.php rename to application/Espo/Classes/Acl/Team/OwnershipChecker.php index 3448c5e457..6a8ae41e29 100644 --- a/application/Espo/Acl/Team.php +++ b/application/Espo/Classes/Acl/Team/OwnershipChecker.php @@ -27,17 +27,19 @@ * these Appropriate Legal Notices must retain the display of the "EspoCRM" word. ************************************************************************/ -namespace Espo\Acl; +namespace Espo\Classes\Acl\Team; + +use Espo\Entities\User; use Espo\ORM\Entity; -use Espo\Entities\User as UserEntity; +use Espo\Core\{ + Acl\OwnershipOwnChecker, +}; -use Espo\Core\Acl\Acl; - -class Team extends Acl +class OwnershipChecker implements OwnershipOwnChecker { - public function checkInTeam(UserEntity $user, Entity $entity) + public function checkOwn(User $user, Entity $entity): bool { $userTeamIdList = $user->getLinkMultipleIdList('teams'); diff --git a/application/Espo/Resources/metadata/aclDefs/ActionHistoryRecord.json b/application/Espo/Resources/metadata/aclDefs/ActionHistoryRecord.json index a8743aae6b..97554510d2 100644 --- a/application/Espo/Resources/metadata/aclDefs/ActionHistoryRecord.json +++ b/application/Espo/Resources/metadata/aclDefs/ActionHistoryRecord.json @@ -1,3 +1,3 @@ { "ownershipCheckerClassName": "Espo\\Classes\\Acl\\ActionHistoryRecord\\OwnershipChecker" -} \ No newline at end of file +} diff --git a/application/Espo/Resources/metadata/aclDefs/Attachment.json b/application/Espo/Resources/metadata/aclDefs/Attachment.json index 9fc5e9fd31..8f89639041 100644 --- a/application/Espo/Resources/metadata/aclDefs/Attachment.json +++ b/application/Espo/Resources/metadata/aclDefs/Attachment.json @@ -1,4 +1,4 @@ { "accessCheckerClassName": "Espo\\Classes\\Acl\\Attachment\\AccessChecker", "ownershipCheckerClassName": "Espo\\Classes\\Acl\\Attachment\\OwnershipChecker" -} \ No newline at end of file +} diff --git a/application/Espo/Resources/metadata/aclDefs/Email.json b/application/Espo/Resources/metadata/aclDefs/Email.json index 6c65a967e8..36821aa618 100644 --- a/application/Espo/Resources/metadata/aclDefs/Email.json +++ b/application/Espo/Resources/metadata/aclDefs/Email.json @@ -2,4 +2,4 @@ "accessCheckerClassName": "Espo\\Classes\\Acl\\Email\\AccessChecker", "ownershipCheckerClassName": "Espo\\Classes\\Acl\\Email\\OwnershipChecker", "readOwnerUserField": "users" -} \ No newline at end of file +} diff --git a/application/Espo/Resources/metadata/aclDefs/EmailFilter.json b/application/Espo/Resources/metadata/aclDefs/EmailFilter.json index d71e954fcd..9cf97baf89 100644 --- a/application/Espo/Resources/metadata/aclDefs/EmailFilter.json +++ b/application/Espo/Resources/metadata/aclDefs/EmailFilter.json @@ -1,3 +1,3 @@ { "ownershipCheckerClassName": "Espo\\Classes\\Acl\\EmailFilter\\OwnershipChecker" -} \ No newline at end of file +} diff --git a/application/Espo/Resources/metadata/aclDefs/Import.json b/application/Espo/Resources/metadata/aclDefs/Import.json new file mode 100644 index 0000000000..13a8a5f565 --- /dev/null +++ b/application/Espo/Resources/metadata/aclDefs/Import.json @@ -0,0 +1,3 @@ +{ + "accessCheckerClassName": "Espo\\Classes\\Acl\\Import\\AccessChecker" +} diff --git a/application/Espo/Resources/metadata/aclDefs/Note.json b/application/Espo/Resources/metadata/aclDefs/Note.json new file mode 100644 index 0000000000..f58a806f3e --- /dev/null +++ b/application/Espo/Resources/metadata/aclDefs/Note.json @@ -0,0 +1,4 @@ +{ + "accessCheckerClassName": "Espo\\Classes\\Acl\\Note\\AccessChecker", + "ownershipCheckerClassName": "Espo\\Classes\\Acl\\Note\\OwnershipChecker" +} diff --git a/application/Espo/Resources/metadata/aclDefs/Notification.json b/application/Espo/Resources/metadata/aclDefs/Notification.json new file mode 100644 index 0000000000..a246ed4f0f --- /dev/null +++ b/application/Espo/Resources/metadata/aclDefs/Notification.json @@ -0,0 +1,3 @@ +{ + "ownershipCheckerClassName": "Espo\\Classes\\Acl\\Notification\\OwnershipChecker" +} diff --git a/application/Espo/Resources/metadata/aclDefs/ScheduledJob.json b/application/Espo/Resources/metadata/aclDefs/ScheduledJob.json new file mode 100644 index 0000000000..f6f40f3a25 --- /dev/null +++ b/application/Espo/Resources/metadata/aclDefs/ScheduledJob.json @@ -0,0 +1,3 @@ +{ + "accessCheckerClassName": "Espo\\Classes\\Acl\\ScheduledJob\\AccessChecker" +} diff --git a/application/Espo/Resources/metadata/aclDefs/Team.json b/application/Espo/Resources/metadata/aclDefs/Team.json new file mode 100644 index 0000000000..3bce47863b --- /dev/null +++ b/application/Espo/Resources/metadata/aclDefs/Team.json @@ -0,0 +1,3 @@ +{ + "ownershipCheckerClassName": "Espo\\Classes\\Acl\\Team\\OwnershipChecker" +}