diff --git a/application/Espo/Acl/ActionHistoryRecord.php b/application/Espo/Acl/ActionHistoryRecord.php index ef9afaab3e..a5176256b8 100644 --- a/application/Espo/Acl/ActionHistoryRecord.php +++ b/application/Espo/Acl/ActionHistoryRecord.php @@ -29,14 +29,13 @@ namespace Espo\Acl; -use \Espo\Entities\User as EntityUser; -use \Espo\ORM\Entity; +use Espo\Entities\User as EntityUser; +use Espo\ORM\Entity; -class ActionHistoryRecord extends \Espo\Core\Acl\Base +class ActionHistoryRecord extends \Espo\Core\Acl\Acl { public function checkIsOwner(EntityUser $user, Entity $entity) { return $entity->get('userId') === $user->id; } } - diff --git a/application/Espo/Acl/Attachment.php b/application/Espo/Acl/Attachment.php index c45bc414e0..8b8c91fa97 100644 --- a/application/Espo/Acl/Attachment.php +++ b/application/Espo/Acl/Attachment.php @@ -29,10 +29,10 @@ namespace Espo\Acl; -use \Espo\Entities\User as EntityUser; -use \Espo\ORM\Entity; +use Espo\Entities\User as EntityUser; +use Espo\ORM\Entity; -class Attachment extends \Espo\Core\Acl\Base +class Attachment extends \Espo\Core\Acl\Acl { public function checkEntityRead(EntityUser $user, Entity $entity, $data) { @@ -90,4 +90,3 @@ class Attachment extends \Espo\Core\Acl\Base return false; } } - diff --git a/application/Espo/Acl/Email.php b/application/Espo/Acl/Email.php index b8f485fd0b..4e2dc999ce 100644 --- a/application/Espo/Acl/Email.php +++ b/application/Espo/Acl/Email.php @@ -29,10 +29,10 @@ namespace Espo\Acl; -use \Espo\Entities\User as EntityUser; -use \Espo\ORM\Entity; +use Espo\Entities\User as EntityUser; +use Espo\ORM\Entity; -class Email extends \Espo\Core\Acl\Base +class Email extends \Espo\Core\Acl\Acl { protected $ownerUserIdAttribute = 'usersIds'; diff --git a/application/Espo/Acl/EmailAddress.php b/application/Espo/Acl/EmailAddress.php index 2c997326ea..a1134a4924 100644 --- a/application/Espo/Acl/EmailAddress.php +++ b/application/Espo/Acl/EmailAddress.php @@ -29,10 +29,10 @@ namespace Espo\Acl; -use \Espo\Entities\User as EntityUser; -use \Espo\ORM\Entity; +use Espo\Entities\User as EntityUser; +use Espo\ORM\Entity; -class EmailAddress extends \Espo\Core\Acl\Base +class EmailAddress extends \Espo\Core\Acl\Acl { public function checkEditInEntity(EntityUser $user, Entity $entity, Entity $excludeEntity) { @@ -62,4 +62,3 @@ class EmailAddress extends \Espo\Core\Acl\Base return !$isFobidden; } } - diff --git a/application/Espo/Acl/EmailFilter.php b/application/Espo/Acl/EmailFilter.php index 6ed3c2d4cb..4d06096159 100644 --- a/application/Espo/Acl/EmailFilter.php +++ b/application/Espo/Acl/EmailFilter.php @@ -29,10 +29,10 @@ namespace Espo\Acl; -use \Espo\Entities\User as EntityUser; -use \Espo\ORM\Entity; +use Espo\Entities\User as EntityUser; +use Espo\ORM\Entity; -class EmailFilter extends \Espo\Core\Acl\Base +class EmailFilter extends \Espo\Core\Acl\Acl { public function checkIsOwner(EntityUser $user, Entity $entity) { @@ -53,4 +53,3 @@ class EmailFilter extends \Espo\Core\Acl\Base return; } } - diff --git a/application/Espo/Acl/Import.php b/application/Espo/Acl/Import.php index 7b372b7a8e..22df20b82a 100644 --- a/application/Espo/Acl/Import.php +++ b/application/Espo/Acl/Import.php @@ -29,12 +29,11 @@ namespace Espo\Acl; -use \Espo\Entities\User as EntityUser; -use \Espo\ORM\Entity; +use Espo\Entities\User as EntityUser; +use Espo\ORM\Entity; -class Import extends \Espo\Core\Acl\Base +class Import extends \Espo\Core\Acl\Acl { - public function checkEntityRead(EntityUser $user, Entity $entity, $data) { if ($user->isAdmin()) return true; diff --git a/application/Espo/Acl/Note.php b/application/Espo/Acl/Note.php index d0c3091ccf..22ce30037a 100644 --- a/application/Espo/Acl/Note.php +++ b/application/Espo/Acl/Note.php @@ -29,10 +29,10 @@ namespace Espo\Acl; -use \Espo\Entities\User as EntityUser; -use \Espo\ORM\Entity; +use Espo\Entities\User as EntityUser; +use Espo\ORM\Entity; -class Note extends \Espo\Core\Acl\Base +class Note extends \Espo\Core\Acl\Acl { protected $deleteThresholdPeriod = '1 month'; diff --git a/application/Espo/Acl/Notification.php b/application/Espo/Acl/Notification.php index 2ace2ea712..ee35ae6ecc 100644 --- a/application/Espo/Acl/Notification.php +++ b/application/Espo/Acl/Notification.php @@ -29,10 +29,10 @@ namespace Espo\Acl; -use \Espo\Entities\User as EntityUser; -use \Espo\ORM\Entity; +use Espo\Entities\User as EntityUser; +use Espo\ORM\Entity; -class Notification extends \Espo\Core\Acl\Base +class Notification extends \Espo\Core\Acl\Acl { public function checkIsOwner(EntityUser $user, Entity $entity) { @@ -42,4 +42,3 @@ class Notification extends \Espo\Core\Acl\Base return false; } } - diff --git a/application/Espo/Acl/PhoneNumber.php b/application/Espo/Acl/PhoneNumber.php index 8eaae405db..f4a14f273b 100644 --- a/application/Espo/Acl/PhoneNumber.php +++ b/application/Espo/Acl/PhoneNumber.php @@ -29,10 +29,10 @@ namespace Espo\Acl; -use \Espo\Entities\User as EntityUser; -use \Espo\ORM\Entity; +use Espo\Entities\User as EntityUser; +use Espo\ORM\Entity; -class PhoneNumber extends \Espo\Core\Acl\Base +class PhoneNumber extends \Espo\Core\Acl\Acl { public function checkEditInEntity(EntityUser $user, Entity $entity, Entity $excludeEntity) { diff --git a/application/Espo/Acl/ScheduledJob.php b/application/Espo/Acl/ScheduledJob.php index 2969f8e1f3..19b3c9c34c 100644 --- a/application/Espo/Acl/ScheduledJob.php +++ b/application/Espo/Acl/ScheduledJob.php @@ -29,10 +29,10 @@ namespace Espo\Acl; -use \Espo\Entities\User as EntityUser; -use \Espo\ORM\Entity; +use Espo\Entities\User as EntityUser; +use Espo\ORM\Entity; -class ScheduledJob extends \Espo\Core\Acl\Base +class ScheduledJob extends \Espo\Core\Acl\Acl { public function checkEntityRead(EntityUser $user, Entity $entity, $data) { @@ -58,4 +58,3 @@ class ScheduledJob extends \Espo\Core\Acl\Base return $this->checkEntity($user, $entity, $data, 'create'); } } - diff --git a/application/Espo/Acl/Team.php b/application/Espo/Acl/Team.php index 8920a9ac85..40542f6119 100644 --- a/application/Espo/Acl/Team.php +++ b/application/Espo/Acl/Team.php @@ -29,13 +29,15 @@ namespace Espo\Acl; -use \Espo\ORM\Entity; +use Espo\ORM\Entity; -class Team extends \Espo\Core\Acl\Base +use Espo\Entities\User as UserEntity; + +class Team extends \Espo\Core\Acl\Acl { - public function checkInTeam(\Espo\Entities\User $user, Entity $entity) + public function checkInTeam(UserEntity $user, Entity $entity) { $userTeamIdList = $user->getLinkMultipleIdList('teams'); return in_array($entity->id, $userTeamIdList); } -} \ No newline at end of file +} diff --git a/application/Espo/Acl/User.php b/application/Espo/Acl/User.php index 34908fce55..db13a25c15 100644 --- a/application/Espo/Acl/User.php +++ b/application/Espo/Acl/User.php @@ -29,12 +29,12 @@ namespace Espo\Acl; -use \Espo\ORM\Entity; -use \Espo\Entities\User as EntityUser; +use Espo\ORM\Entity; +use Espo\Entities\User as EntityUser; -class User extends \Espo\Core\Acl\Base +class User extends \Espo\Core\Acl\Acl { - public function checkIsOwner(\Espo\Entities\User $user, Entity $entity) + public function checkIsOwner(EntityUser $user, Entity $entity) { return $user->id === $entity->id; } diff --git a/application/Espo/Acl/Webhook.php b/application/Espo/Acl/Webhook.php index 48e643fb28..a995dea934 100644 --- a/application/Espo/Acl/Webhook.php +++ b/application/Espo/Acl/Webhook.php @@ -29,10 +29,10 @@ namespace Espo\Acl; -use \Espo\Entities\User as EntityUser; -use \Espo\ORM\Entity; +use Espo\Entities\User as EntityUser; +use Espo\ORM\Entity; -class Webhook extends \Espo\Core\Acl\Base +class Webhook extends \Espo\Core\Acl\Acl { public function checkIsOwner(EntityUser $user, Entity $entity) { diff --git a/application/Espo/Core/Acl/Acl.php b/application/Espo/Core/Acl/Acl.php new file mode 100644 index 0000000000..32897f4f18 --- /dev/null +++ b/application/Espo/Core/Acl/Acl.php @@ -0,0 +1,293 @@ +scope = $scope; + + $this->entityManager = $entityManager; + $this->aclManager = $aclManager; + $this->config = $config; + } + + protected function getConfig() + { + return $this->config; + } + + protected function getEntityManager() + { + return $this->entityManager; + } + + protected function getAclManager() + { + return $this->aclManager; + } + + public function checkReadOnlyTeam(User $user, $data) + { + if (empty($data) || !is_object($data) || !isset($data->read)) { + return false; + } + return $data->read === 'team'; + } + + public function checkReadNo(User $user, $data) + { + if (empty($data) || !is_object($data) || !isset($data->read)) { + return false; + } + return $data->read === 'no'; + } + + public function checkReadOnlyOwn(User $user, $data) + { + if (empty($data) || !is_object($data) || !isset($data->read)) { + return false; + } + return $data->read === 'own'; + } + + public function checkEntity(User $user, Entity $entity, $data, $action) + { + if ($user->isAdmin()) { + return true; + } + return $this->checkScope($user, $data, $action, $entity); + } + + public function checkScope(User $user, $data, $action = null, Entity $entity = null, $entityAccessData = []) + { + if ($user->isAdmin()) { + return true; + } + + if (is_null($data)) { + return false; + } + if ($data === false) { + return false; + } + if ($data === true) { + return true; + } + if (is_string($data)) { + return true; + } + + $isOwner = null; + if (isset($entityAccessData['isOwner'])) { + $isOwner = $entityAccessData['isOwner']; + } + $inTeam = null; + if (isset($entityAccessData['inTeam'])) { + $inTeam = $entityAccessData['inTeam']; + } + + if (is_null($action)) { + return true; + } + + if (!isset($data->$action)) { + return false; + } + + $value = $data->$action; + + if ($value === 'all' || $value === 'yes' || $value === true) { + return true; + } + + if (!$value || $value === 'no') { + return false; + } + + if (is_null($isOwner)) { + if ($entity) { + $isOwner = $this->checkIsOwner($user, $entity); + } else { + return true; + } + } + + if ($isOwner) { + if ($value === 'own' || $value === 'team') { + return true; + } + } + if (is_null($inTeam) && $entity) { + $inTeam = $this->checkInTeam($user, $entity); + } + + if ($inTeam) { + if ($value === 'team') { + return true; + } + } + return false; + } + + public function checkIsOwner(User $user, Entity $entity) + { + if ($entity->hasAttribute('assignedUserId')) { + if ($entity->has('assignedUserId')) { + if ($user->id === $entity->get('assignedUserId')) { + return true; + } + } + } else if ($entity->hasAttribute('createdById')) { + if ($entity->has('createdById')) { + if ($user->id === $entity->get('createdById')) { + return true; + } + } + } + + if ($entity->hasLinkMultipleField('assignedUsers')) { + if ($entity->hasLinkMultipleId('assignedUsers', $user->id)) { + return true; + } + } + + return false; + } + + public function checkInTeam(User $user, Entity $entity) + { + $userTeamIdList = $user->getLinkMultipleIdList('teams'); + + if (!$entity->hasRelation('teams') || !$entity->hasAttribute('teamsIds')) { + return false; + } + + $entityTeamIdList = $entity->getLinkMultipleIdList('teams'); + + if (empty($entityTeamIdList)) { + return false; + } + + foreach ($userTeamIdList as $id) { + if (in_array($id, $entityTeamIdList)) { + return true; + } + } + return false; + } + + public function checkEntityDelete(User $user, Entity $entity, $data) + { + if ($user->isAdmin()) { + return true; + } + + if ($this->checkEntity($user, $entity, $data, 'delete')) { + return true; + } + + if (is_object($data)) { + if ($data->edit !== 'no' || $data->create !== 'no') { + if ( + $this->config->get('aclAllowDeleteCreated') + && + $entity->has('createdById') && $entity->get('createdById') == $user->id + ) { + $isDeletedAllowed = false; + if (!$entity->has('assignedUserId')) { + $isDeletedAllowed = true; + } else { + if (!$entity->get('assignedUserId')) { + $isDeletedAllowed = true; + } else if ($entity->get('assignedUserId') == $entity->get('createdById')) { + $isDeletedAllowed = true; + } + } + + if ($isDeletedAllowed) { + $createdAt = $entity->get('createdAt'); + if ($createdAt) { + $deleteThresholdPeriod = $this->config->get( + 'aclAllowDeleteCreatedThresholdPeriod', + $this->allowDeleteCreatedThresholdPeriod + ); + if (\Espo\Core\Utils\DateTime::isAfterThreshold($createdAt, $deleteThresholdPeriod)) { + return false; + } + } + return true; + } + } + } + } + + return false; + } + + public function getOwnerUserIdAttribute(Entity $entity) + { + if ($this->ownerUserIdAttribute) { + return $this->ownerUserIdAttribute; + } + + if ($entity->hasLinkMultipleField('assignedUsers')) { + return 'assignedUsersIds'; + } + + if ($entity->hasAttribute('assignedUserId')) { + return 'assignedUserId'; + } + + if ($entity->hasAttribute('createdById')) { + return 'createdById'; + } + } +} diff --git a/application/Espo/Core/Acl/Base.php b/application/Espo/Core/Acl/Base.php index 640635e471..5d537bc9f1 100644 --- a/application/Espo/Core/Acl/Base.php +++ b/application/Espo/Core/Acl/Base.php @@ -29,39 +29,39 @@ namespace Espo\Core\Acl; -use \Espo\Core\Interfaces\Injectable; +use Espo\Core\Interfaces\Injectable; -use \Espo\Entities\User; -use \Espo\ORM\Entity; +use Espo\Entities\User; +use Espo\ORM\Entity; -class Base implements Injectable +use Espo\Core\{ + ORM\EntityManager, + AclManager, + Utils\Config, +}; + +/** Deprecated */ +class Base extends Acl implements Injectable { - protected $dependencyList = [ - 'config', - 'entityManager', - 'aclManager', - ]; + protected $dependencyList = []; - protected $dependencies = []; // for backward compatibility - - protected $scope; + protected $dependencies = []; protected $injections = []; - protected $ownerUserIdAttribute = null; + public function __construct(string $scope, EntityManager $entityManager, AclManager $aclManager, Config $config) + { + $this->scope = $scope; + parent::__construct($scope, $entityManager, $aclManager, $config); - protected $allowDeleteCreatedThresholdPeriod = '24 hours'; + $this->init(); + } public function inject($name, $object) { $this->injections[$name] = $object; } - public function __construct(string $scope) - { - $this->scope = $scope; - $this->init(); - } protected function init() { @@ -88,233 +88,4 @@ class Base implements Injectable { return array_merge($this->dependencyList, $this->dependencies); } - - protected function getConfig() - { - return $this->getInjection('config'); - } - - protected function getEntityManager() - { - return $this->getInjection('entityManager'); - } - - protected function getAclManager() - { - return $this->getInjection('aclManager'); - } - - public function checkReadOnlyTeam(User $user, $data) - { - if (empty($data) || !is_object($data) || !isset($data->read)) { - return false; - } - return $data->read === 'team'; - } - - public function checkReadNo(User $user, $data) - { - if (empty($data) || !is_object($data) || !isset($data->read)) { - return false; - } - return $data->read === 'no'; - } - - public function checkReadOnlyOwn(User $user, $data) - { - if (empty($data) || !is_object($data) || !isset($data->read)) { - return false; - } - return $data->read === 'own'; - } - - public function checkEntity(User $user, Entity $entity, $data, $action) - { - if ($user->isAdmin()) { - return true; - } - return $this->checkScope($user, $data, $action, $entity); - } - - public function checkScope(User $user, $data, $action = null, Entity $entity = null, $entityAccessData = array()) - { - if ($user->isAdmin()) { - return true; - } - - if (is_null($data)) { - return false; - } - if ($data === false) { - return false; - } - if ($data === true) { - return true; - } - if (is_string($data)) { - return true; - } - - $isOwner = null; - if (isset($entityAccessData['isOwner'])) { - $isOwner = $entityAccessData['isOwner']; - } - $inTeam = null; - if (isset($entityAccessData['inTeam'])) { - $inTeam = $entityAccessData['inTeam']; - } - - if (is_null($action)) { - return true; - } - - if (!isset($data->$action)) { - return false; - } - - $value = $data->$action; - - if ($value === 'all' || $value === 'yes' || $value === true) { - return true; - } - - if (!$value || $value === 'no') { - return false; - } - - if (is_null($isOwner)) { - if ($entity) { - $isOwner = $this->checkIsOwner($user, $entity); - } else { - return true; - } - } - - if ($isOwner) { - if ($value === 'own' || $value === 'team') { - return true; - } - } - if (is_null($inTeam) && $entity) { - $inTeam = $this->checkInTeam($user, $entity); - } - - if ($inTeam) { - if ($value === 'team') { - return true; - } - } - return false; - } - - public function checkIsOwner(User $user, Entity $entity) - { - if ($entity->hasAttribute('assignedUserId')) { - if ($entity->has('assignedUserId')) { - if ($user->id === $entity->get('assignedUserId')) { - return true; - } - } - } else if ($entity->hasAttribute('createdById')) { - if ($entity->has('createdById')) { - if ($user->id === $entity->get('createdById')) { - return true; - } - } - } - - if ($entity->hasLinkMultipleField('assignedUsers')) { - if ($entity->hasLinkMultipleId('assignedUsers', $user->id)) { - return true; - } - } - - return false; - } - - public function checkInTeam(User $user, Entity $entity) - { - $userTeamIdList = $user->getLinkMultipleIdList('teams'); - - if (!$entity->hasRelation('teams') || !$entity->hasAttribute('teamsIds')) { - return false; - } - - $entityTeamIdList = $entity->getLinkMultipleIdList('teams'); - - if (empty($entityTeamIdList)) { - return false; - } - - foreach ($userTeamIdList as $id) { - if (in_array($id, $entityTeamIdList)) { - return true; - } - } - return false; - } - - public function checkEntityDelete(User $user, Entity $entity, $data) - { - if ($user->isAdmin()) { - return true; - } - - if ($this->checkEntity($user, $entity, $data, 'delete')) { - return true; - } - - if (is_object($data)) { - if ($data->edit !== 'no' || $data->create !== 'no') { - if ( - $this->getConfig()->get('aclAllowDeleteCreated') - && - $entity->has('createdById') && $entity->get('createdById') == $user->id - ) { - $isDeletedAllowed = false; - if (!$entity->has('assignedUserId')) { - $isDeletedAllowed = true; - } else { - if (!$entity->get('assignedUserId')) { - $isDeletedAllowed = true; - } else if ($entity->get('assignedUserId') == $entity->get('createdById')) { - $isDeletedAllowed = true; - } - } - - if ($isDeletedAllowed) { - $createdAt = $entity->get('createdAt'); - if ($createdAt) { - $deleteThresholdPeriod = $this->getConfig()->get('aclAllowDeleteCreatedThresholdPeriod', $this->allowDeleteCreatedThresholdPeriod); - if (\Espo\Core\Utils\DateTime::isAfterThreshold($createdAt, $deleteThresholdPeriod)) { - return false; - } - } - return true; - } - } - } - } - - return false; - } - - public function getOwnerUserIdAttribute(Entity $entity) - { - if ($this->ownerUserIdAttribute) { - return $this->ownerUserIdAttribute; - } - - if ($entity->hasLinkMultipleField('assignedUsers')) { - return 'assignedUsersIds'; - } - - if ($entity->hasAttribute('assignedUserId')) { - return 'assignedUserId'; - } - - if ($entity->hasAttribute('createdById')) { - return 'createdById'; - } - } } diff --git a/application/Espo/Core/AclPortal/Acl.php b/application/Espo/Core/AclPortal/Acl.php new file mode 100644 index 0000000000..9f2ae3ae88 --- /dev/null +++ b/application/Espo/Core/AclPortal/Acl.php @@ -0,0 +1,37 @@ +isAdmin()) { - return true; - } - - if (is_null($data)) { - return false; - } - if ($data === false) { - return false; - } - if ($data === true) { - return true; - } - if (is_string($data)) { - return true; - } - - $isOwner = null; - if (isset($entityAccessData['isOwner'])) { - $isOwner = $entityAccessData['isOwner']; - } - $inAccount = null; - if (isset($entityAccessData['inAccount'])) { - $inAccount = $entityAccessData['inAccount']; - } - $isOwnContact = null; - if (isset($entityAccessData['isOwnContact'])) { - $isOwnContact = $entityAccessData['isOwnContact']; - } - - if (is_null($action)) { - return true; - } - - if (!isset($data->$action)) { - return false; - } - - $value = $data->$action; - - if ($value === 'all' || $value === 'yes' || $value === true) { - return true; - } - - if (!$value || $value === 'no') { - return false; - } - - if (is_null($isOwner)) { - if ($entity) { - $isOwner = $this->checkIsOwner($user, $entity); - } else { - return true; - } - } - - if ($isOwner) { - if ($value === 'own' || $value === 'account' || $value === 'contact') { - return true; - } - } - - if ($value === 'account') { - if (is_null($inAccount) && $entity) { - $inAccount = $this->checkInAccount($user, $entity); - } - if ($inAccount) { - return true; - } else { - if (is_null($isOwnContact) && $entity) { - $isOwnContact = $this->checkIsOwnContact($user, $entity); - } - if ($isOwnContact) { - return true; - } - } - } - - if ($value === 'contact') { - if (is_null($isOwnContact) && $entity) { - $isOwnContact = $this->checkIsOwnContact($user, $entity); - } - if ($isOwnContact) { - return true; - } - } - - return false; - } - - public function checkReadOnlyAccount(User $user, $data) - { - if (empty($data) || !is_object($data) || !isset($data->read)) { - return false; - } - return $data->read === 'account'; - } - - public function checkReadOnlyContact(User $user, $data) - { - if (empty($data) || !is_object($data) || !isset($data->read)) { - return false; - } - return $data->read === 'contact'; - } - - public function checkIsOwner(User $user, Entity $entity) - { - if ($entity->hasAttribute('createdById')) { - if ($entity->has('createdById')) { - if ($user->id === $entity->get('createdById')) { - return true; - } - } - } - return false; - } - - public function checkInAccount(User $user, Entity $entity) - { - $accountIdList = $user->getLinkMultipleIdList('accounts'); - if (count($accountIdList)) { - if ($entity->hasAttribute('accountId') && $entity->getRelationParam('account', 'entity') === 'Account') { - if (in_array($entity->get('accountId'), $accountIdList)) { - return true; - } - } - - if ($entity->hasRelation('accounts') && $entity->getRelationParam('accounts', 'entity') === 'Account') { - $repository = $this->getEntityManager()->getRepository($entity->getEntityType()); - foreach ($accountIdList as $accountId) { - if ($repository->isRelated($entity, 'accounts', $accountId)) { - return true; - } - } - } - - if ($entity->hasAttribute('parentId') && $entity->hasRelation('parent')) { - if ($entity->get('parentType') === 'Account') { - if (in_array($entity->get('parentId'), $accountIdList)) { - return true; - } - } - } - } - - return false; - } - - public function checkIsOwnContact(User $user, Entity $entity) - { - $contactId = $user->get('contactId'); - if ($contactId) { - if ($entity->hasAttribute('contactId') && $entity->getRelationParam('contact', 'entity') === 'Contact') { - if ($entity->get('contactId') === $contactId) { - return true; - } - } - - if ($entity->hasRelation('contacts') && $entity->getRelationParam('contacts', 'entity') === 'Contact') { - $repository = $this->getEntityManager()->getRepository($entity->getEntityType()); - if ($repository->isRelated($entity, 'contacts', $contactId)) { - return true; - } - } - - if ($entity->hasAttribute('parentId') && $entity->hasRelation('parent')) { - if ($entity->get('parentType') === 'Contact') { - if ($entity->get('parentId') === $contactId) { - return true; - } - } - } - } - - return false; - } + use Portal; } diff --git a/application/Espo/Core/AclPortal/Portal.php b/application/Espo/Core/AclPortal/Portal.php new file mode 100644 index 0000000000..d2b4ce88a0 --- /dev/null +++ b/application/Espo/Core/AclPortal/Portal.php @@ -0,0 +1,216 @@ +isAdmin()) { + return true; + } + + if (is_null($data)) { + return false; + } + if ($data === false) { + return false; + } + if ($data === true) { + return true; + } + if (is_string($data)) { + return true; + } + + $isOwner = null; + if (isset($entityAccessData['isOwner'])) { + $isOwner = $entityAccessData['isOwner']; + } + $inAccount = null; + if (isset($entityAccessData['inAccount'])) { + $inAccount = $entityAccessData['inAccount']; + } + $isOwnContact = null; + if (isset($entityAccessData['isOwnContact'])) { + $isOwnContact = $entityAccessData['isOwnContact']; + } + + if (is_null($action)) { + return true; + } + + if (!isset($data->$action)) { + return false; + } + + $value = $data->$action; + + if ($value === 'all' || $value === 'yes' || $value === true) { + return true; + } + + if (!$value || $value === 'no') { + return false; + } + + if (is_null($isOwner)) { + if ($entity) { + $isOwner = $this->checkIsOwner($user, $entity); + } else { + return true; + } + } + + if ($isOwner) { + if ($value === 'own' || $value === 'account' || $value === 'contact') { + return true; + } + } + + if ($value === 'account') { + if (is_null($inAccount) && $entity) { + $inAccount = $this->checkInAccount($user, $entity); + } + if ($inAccount) { + return true; + } else { + if (is_null($isOwnContact) && $entity) { + $isOwnContact = $this->checkIsOwnContact($user, $entity); + } + if ($isOwnContact) { + return true; + } + } + } + + if ($value === 'contact') { + if (is_null($isOwnContact) && $entity) { + $isOwnContact = $this->checkIsOwnContact($user, $entity); + } + if ($isOwnContact) { + return true; + } + } + + return false; + } + + public function checkReadOnlyAccount(User $user, $data) + { + if (empty($data) || !is_object($data) || !isset($data->read)) { + return false; + } + return $data->read === 'account'; + } + + public function checkReadOnlyContact(User $user, $data) + { + if (empty($data) || !is_object($data) || !isset($data->read)) { + return false; + } + return $data->read === 'contact'; + } + + public function checkIsOwner(User $user, Entity $entity) + { + if ($entity->hasAttribute('createdById')) { + if ($entity->has('createdById')) { + if ($user->id === $entity->get('createdById')) { + return true; + } + } + } + return false; + } + + public function checkInAccount(User $user, Entity $entity) + { + $accountIdList = $user->getLinkMultipleIdList('accounts'); + if (count($accountIdList)) { + if ($entity->hasAttribute('accountId') && $entity->getRelationParam('account', 'entity') === 'Account') { + if (in_array($entity->get('accountId'), $accountIdList)) { + return true; + } + } + + if ($entity->hasRelation('accounts') && $entity->getRelationParam('accounts', 'entity') === 'Account') { + $repository = $this->getEntityManager()->getRepository($entity->getEntityType()); + foreach ($accountIdList as $accountId) { + if ($repository->isRelated($entity, 'accounts', $accountId)) { + return true; + } + } + } + + if ($entity->hasAttribute('parentId') && $entity->hasRelation('parent')) { + if ($entity->get('parentType') === 'Account') { + if (in_array($entity->get('parentId'), $accountIdList)) { + return true; + } + } + } + } + + return false; + } + + public function checkIsOwnContact(User $user, Entity $entity) + { + $contactId = $user->get('contactId'); + if ($contactId) { + if ($entity->hasAttribute('contactId') && $entity->getRelationParam('contact', 'entity') === 'Contact') { + if ($entity->get('contactId') === $contactId) { + return true; + } + } + + if ($entity->hasRelation('contacts') && $entity->getRelationParam('contacts', 'entity') === 'Contact') { + $repository = $this->getEntityManager()->getRepository($entity->getEntityType()); + if ($repository->isRelated($entity, 'contacts', $contactId)) { + return true; + } + } + + if ($entity->hasAttribute('parentId') && $entity->hasRelation('parent')) { + if ($entity->get('parentType') === 'Contact') { + if ($entity->get('parentId') === $contactId) { + return true; + } + } + } + } + + return false; + } +} diff --git a/application/Espo/Modules/Crm/AclPortal/Account.php b/application/Espo/Modules/Crm/AclPortal/Account.php index e162113af2..e86f37b5ee 100644 --- a/application/Espo/Modules/Crm/AclPortal/Account.php +++ b/application/Espo/Modules/Crm/AclPortal/Account.php @@ -29,10 +29,12 @@ namespace Espo\Modules\Crm\AclPortal; -use \Espo\Entities\User; -use \Espo\ORM\Entity; +use Espo\Entities\User; +use Espo\ORM\Entity; -class Account extends \Espo\Core\AclPortal\Base +use Espo\Core\AclPortal\Acl; + +class Account extends Acl { public function checkInAccount(User $user, Entity $entity) { @@ -45,4 +47,3 @@ class Account extends \Espo\Core\AclPortal\Base return false; } } - diff --git a/application/Espo/Modules/Crm/AclPortal/Contact.php b/application/Espo/Modules/Crm/AclPortal/Contact.php index 2c129cede4..a1454b0523 100644 --- a/application/Espo/Modules/Crm/AclPortal/Contact.php +++ b/application/Espo/Modules/Crm/AclPortal/Contact.php @@ -29,10 +29,12 @@ namespace Espo\Modules\Crm\AclPortal; -use \Espo\Entities\User; -use \Espo\ORM\Entity; +use Espo\Entities\User; +use Espo\ORM\Entity; -class Contact extends \Espo\Core\AclPortal\Base +use Espo\Core\AclPortal\Acl; + +class Contact extends Acl { public function checkIsOwnContact(User $user, Entity $entity) { @@ -45,4 +47,3 @@ class Contact extends \Espo\Core\AclPortal\Base return false; } } - diff --git a/application/Espo/Modules/Crm/AclPortal/KnowledgeBaseArticle.php b/application/Espo/Modules/Crm/AclPortal/KnowledgeBaseArticle.php index 3394d928fa..8395a5c715 100644 --- a/application/Espo/Modules/Crm/AclPortal/KnowledgeBaseArticle.php +++ b/application/Espo/Modules/Crm/AclPortal/KnowledgeBaseArticle.php @@ -29,12 +29,13 @@ namespace Espo\Modules\Crm\AclPortal; -use \Espo\Entities\User as EntityUser; -use \Espo\ORM\Entity; +use Espo\Entities\User as EntityUser; +use Espo\ORM\Entity; -class KnowledgeBaseArticle extends \Espo\Core\AclPortal\Base +use Espo\Core\AclPortal\Acl; + +class KnowledgeBaseArticle extends Acl { - public function checkEntityRead(EntityUser $user, Entity $entity, $data) { if (!$this->checkEntity($user, $entity, $data, 'read')) { @@ -52,4 +53,3 @@ class KnowledgeBaseArticle extends \Espo\Core\AclPortal\Base return true; } } -