. * * 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\Services; use Espo\Core\Exceptions\Forbidden; use Espo\Core\Exceptions\BadRequest; use Espo\Repositories\User as UserRepository; use Espo\Core\Acl\Table as AclTable; use Espo\Entities\Note as NoteEntity; use Espo\Entities\User as UserEntity; use Espo\ORM\Entity; use stdClass; /** * @extends Record */ class Note extends Record { public function filterUpdateInput(stdClass $data): void { parent::filterUpdateInput($data); unset($data->parentId); unset($data->parentType); unset($data->targetType); unset($data->usersIds); unset($data->teamsIds); unset($data->portalsIds); unset($data->isGlobal); } /** * @throws BadRequest * @throws Forbidden */ protected function processAssignmentCheck(Entity $entity): void { /** @var NoteEntity $entity */ if (!$entity->isNew()) { return; } $targetType = $entity->getTargetType(); if (!$targetType) { return; } $userTeamIdList = $this->user->getTeamIdList(); $userIdList = $entity->getLinkMultipleIdList('users'); $portalIdList = $entity->getLinkMultipleIdList('portals'); $teamIdList = $entity->getLinkMultipleIdList('teams'); /** @var iterable $targetUserList */ $targetUserList = []; if ($targetType === NoteEntity::TARGET_USERS) { /** @var iterable $targetUserList */ $targetUserList = $this->entityManager ->getRDBRepository(UserEntity::ENTITY_TYPE) ->select(['id', 'type']) ->where([ 'id' => $userIdList, ]) ->find(); } $hasPortalTargetUser = false; $allTargetUsersArePortal = true; foreach ($targetUserList as $user) { if (!$user->isPortal()) { $allTargetUsersArePortal = false; } if ($user->isPortal()) { $hasPortalTargetUser = true; } } $messagePermission = $this->acl->getPermissionLevel('message'); if ($messagePermission === AclTable::LEVEL_NO) { if ( $targetType !== NoteEntity::TARGET_SELF && $targetType !== NoteEntity::TARGET_PORTALS && !( $targetType === NoteEntity::TARGET_USERS && count($userIdList) === 1 && $userIdList[0] === $this->user->getId() ) && !( $targetType === NoteEntity::TARGET_USERS && $allTargetUsersArePortal ) ) { throw new Forbidden('Not permitted to post to anybody except self.'); } } if ($targetType === NoteEntity::TARGET_TEAMS) { if (empty($teamIdList)) { throw new BadRequest("No team IDS."); } } if ($targetType === NoteEntity::TARGET_USERS) { if (empty($userIdList)) { throw new BadRequest("No user IDs."); } } if ($targetType === NoteEntity::TARGET_PORTALS) { if (empty($portalIdList)) { throw new BadRequest("No portal IDs."); } if ($this->acl->getPermissionLevel('portal') !== AclTable::LEVEL_YES) { throw new Forbidden('Not permitted to post to portal users.'); } } if ( $targetType === NoteEntity::TARGET_USERS && $this->acl->getPermissionLevel('portal') !== AclTable::LEVEL_YES ) { if ($hasPortalTargetUser) { throw new Forbidden('Not permitted to post to portal users.'); } } if ($messagePermission === AclTable::LEVEL_TEAM) { if ($targetType === NoteEntity::TARGET_ALL) { throw new Forbidden('Not permitted to post to all.'); } } if ( $messagePermission === AclTable::LEVEL_TEAM && $targetType === NoteEntity::TARGET_TEAMS ) { if (empty($userTeamIdList)) { throw new Forbidden('Not permitted to post to foreign teams.'); } foreach ($teamIdList as $teamId) { if (!in_array($teamId, $userTeamIdList)) { throw new Forbidden("Not permitted to post to foreign teams."); } } } if ( $messagePermission === AclTable::LEVEL_TEAM && $targetType === NoteEntity::TARGET_USERS ) { if (empty($userTeamIdList)) { throw new Forbidden('Not permitted to post to users from foreign teams.'); } foreach ($targetUserList as $user) { if ($user->getId() === $this->user->getId()) { continue; } if ($user->isPortal()) { continue; } $inTeam = $this->getUserRepository()->checkBelongsToAnyOfTeams($user->getId(), $userTeamIdList); if (!$inTeam) { throw new Forbidden('Not permitted to post to users from foreign teams.'); } } } } public function link(string $id, string $link, string $foreignId) : void { if ($link === 'teams' || $link === 'users') { throw new Forbidden(); } parent::link($id, $link, $foreignId); } public function unlink(string $id, string $link, string $foreignId) : void { if ($link === 'teams' || $link === 'users') { throw new Forbidden(); } parent::unlink($id, $link, $foreignId); } /** * @param NoteEntity $entity * @return void */ public function loadAdditionalFields(Entity $entity) { parent::loadAdditionalFields($entity); $entity->loadAdditionalFields(); } private function getUserRepository(): UserRepository { /** @var UserRepository */ return $this->entityManager->getRepository(UserEntity::ENTITY_TYPE); } }