. * * 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 Espo\Classes\Acl\Attachment; use Espo\Core\Name\Field; use Espo\Entities\Attachment; use Espo\Entities\Note; use Espo\Entities\Settings; use Espo\Entities\User; use Espo\ORM\Entity; use Espo\Core\Acl\AccessEntityCREDChecker; use Espo\Core\Acl\DefaultAccessChecker; use Espo\Core\Acl\ScopeData; use Espo\Core\Acl\Traits\DefaultAccessCheckerDependency; use Espo\Core\AclManager; use Espo\Core\ORM\EntityManager; /** * @implements AccessEntityCREDChecker */ class AccessChecker implements AccessEntityCREDChecker { use DefaultAccessCheckerDependency; public function __construct( DefaultAccessChecker $defaultAccessChecker, private AclManager $aclManager, private EntityManager $entityManager ) { $this->defaultAccessChecker = $defaultAccessChecker; } public function checkEntityRead(User $user, Entity $entity, ScopeData $data): bool { if ($entity->getParentType() === Settings::ENTITY_TYPE) { // Allow the logo. return true; } $parent = null; $parentType = $entity->getParentType(); $parentId = $entity->getParent()?->getId(); $relatedType = $entity->getRelatedType(); $relatedId = $entity->getRelated()?->getId(); if ($parentId && $parentType) { $parent = $this->entityManager->getEntityById($parentType, $parentId); } else if ($relatedId && $relatedType) { $parent = $this->entityManager->getEntityById($relatedType, $relatedId); } if (!$parent) { if ($this->defaultAccessChecker->checkEntityRead($user, $entity, $data)) { return true; } return false; } if ($parent->getEntityType() === Note::ENTITY_TYPE) { /** @var Note $parent */ $result = $this->checkEntityReadNoteParent($user, $parent); if ($result !== null) { return $result; } } else if ($this->aclManager->checkEntity($user, $parent)) { if ( $entity->getTargetField() && !$this->aclManager->checkField($user, $parent->getEntityType(), $entity->getTargetField()) ) { return false; } return true; } if ($this->defaultAccessChecker->checkEntityRead($user, $entity, $data)) { return true; } return false; } private function checkEntityReadNoteParent(User $user, Note $note): ?bool { if ($note->getTargetType() === Note::TARGET_TEAMS) { $intersect = array_intersect( $note->getLinkMultipleIdList(Field::TEAMS), $user->getLinkMultipleIdList(Field::TEAMS) ); if (count($intersect)) { return true; } return null; } if ($note->getTargetType() === Note::TARGET_USERS) { $isRelated = $this->entityManager ->getRDBRepository(Note::ENTITY_TYPE) ->getRelation($note, 'users') ->isRelated($user); if ($isRelated) { return true; } return null; } if ($note->getTargetType() === Note::TARGET_ALL) { return true; } if (!$note->getParentId() || !$note->getParentType()) { return null; } $parent = $this->entityManager->getEntityById($note->getParentType(), $note->getParentId()); if ($parent && $this->aclManager->checkEntity($user, $parent)) { return true; } return null; } }