assignment checking refactoring

This commit is contained in:
Yuri Kuznetsov
2021-05-11 15:29:16 +03:00
parent 6b62fc7963
commit 6e023222de
12 changed files with 705 additions and 249 deletions
@@ -0,0 +1,51 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
* Website: https://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* 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 General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Classes\Acl\Email;
use Espo\Entities\User;
use Espo\ORM\Entity;
use Espo\Core\{
Acl\AssignmentChecker\DefaultAssignmentChecker,
};
class AssignmentChecker extends DefaultAssignmentChecker
{
protected function isPermittedAssignedUser(User $user, Entity $entity): bool
{
return true;
}
protected function isPermittedAssignedUsers(User $user, Entity $entity): bool
{
return true;
}
}
@@ -0,0 +1,42 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
* Website: https://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* 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 General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\Acl;
use Espo\ORM\Entity;
use Espo\Entities\User;
interface AssignmentChecker
{
/**
* Check assignment.
*/
public function check(User $user, Entity $entity): bool;
}
@@ -0,0 +1,86 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
* Website: https://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* 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 General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\Acl\AssignmentChecker;
use Espo\Core\{
Utils\ClassFinder,
Utils\Metadata,
InjectableFactory,
Acl\AssignmentChecker,
Acl\Exceptions\NotImplemented,
};
class AssignmentCheckerFactory
{
private $defaultClassName = DefaultAssignmentChecker::class;
private $classFinder;
private $metadata;
private $injectableFactory;
public function __construct(
ClassFinder $classFinder,
Metadata $metadata,
InjectableFactory $injectableFactory
) {
$this->classFinder = $classFinder;
$this->metadata = $metadata;
$this->injectableFactory = $injectableFactory;
}
/**
* Create an access checker.
*
* @throws NotImplemented
*/
public function create(string $scope): AssignmentChecker
{
$className = $this->getClassName($scope);
return $this->injectableFactory->create($className);
}
private function getClassName(string $scope): string
{
$className = $this->metadata->get(['aclDefs', $scope, 'assignmentCheckerClassName']);
if ($className) {
return $className;
}
if (!$this->metadata->get(['scopes', $scope])) {
throw new NotImplemented();
}
return $this->defaultClassName;
}
}
@@ -0,0 +1,78 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
* Website: https://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* 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 General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\Acl\AssignmentChecker;
use Espo\ORM\Entity;
use Espo\Entities\User;
use Espo\Core\{
Utils\Metadata,
Acl\AssignmentChecker,
};
class AssignmentCheckerManager
{
private $checkerCache = [];
private $metadata;
private $factory;
public function __construct(Metadata $metadata, AssignmentCheckerFactory $factory)
{
$this->metadata = $metadata;
$this->factory = $factory;
}
public function check(User $user, Entity $entity): bool
{
$entityType = $entity->getEntityType();
$checker = $this->getChecker($entityType);
return $checker->check($user, $entity);
}
private function getChecker(string $entityType): AssignmentChecker
{
if (!array_key_exists($entityType, $this->checkerCache)) {
$this->loadChecker($entityType);
}
return $this->checkerCache[$entityType];
}
private function loadChecker(string $entityType): void
{
$this->checkerCache[$entityType] = $this->factory->create($entityType);
}
}
@@ -0,0 +1,353 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
* Website: https://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* 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 General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\Acl\AssignmentChecker;
use Espo\ORM\{
Entity,
EntityManager,
Defs\Defs,
};
use Espo\Entities\User;
use Espo\Core\{
AclManager,
Acl\AssignmentChecker,
Acl\Table,
};
class DefaultAssignmentChecker implements AssignmentChecker
{
protected const FIELD_ASSIGNED_USERS = 'assignedUsers';
protected const FIELD_TEAMS = 'teams';
protected const ATTR_ASSIGNED_USER_ID = 'assignedUserId';
protected const ATTR_TEAMS_IDS = 'teamsIds';
protected const ATTR_ASSIGNED_USERS_IDS = 'assignedUsersIds';
private $aclManager;
private $entityManager;
private $ormDefs;
public function __construct(AclManager $aclManager, EntityManager $entityManager, Defs $ormDefs)
{
$this->aclManager = $aclManager;
$this->entityManager = $entityManager;
$this->ormDefs = $ormDefs;
}
public function check(User $user, Entity $entity): bool
{
if (!$this->isPermittedAssignedUser($user, $entity)) {
return false;
}
if (!$this->isPermittedTeams($user, $entity)) {
return false;
}
if ( $this->hasAssignedUsersField($entity->getEntityType())) {
if (!$this->isPermittedAssignedUsers($user, $entity)) {
return false;
}
}
return true;
}
private function hasAssignedUsersField(string $entityType): bool
{
$entityDefs = $this->ormDefs->getEntity($entityType);
return
$entityDefs->hasField(self::FIELD_ASSIGNED_USERS) &&
$entityDefs->getField(self::FIELD_ASSIGNED_USERS)->getType() === 'linkMultiple' &&
$entityDefs->hasRelation(self::FIELD_ASSIGNED_USERS) &&
$entityDefs->getRelation(self::FIELD_ASSIGNED_USERS)->getForeignEntityType() === 'User';
}
protected function isPermittedAssignedUser(User $user, Entity $entity): bool
{
if (!$entity->hasAttribute(self::ATTR_ASSIGNED_USER_ID)) {
return true;
}
$assignedUserId = $entity->get(self::ATTR_ASSIGNED_USER_ID);
if ($user->isPortal()) {
if (!$entity->isAttributeChanged(self::ATTR_ASSIGNED_USER_ID) && !$assignedUserId) {
return true;
}
return false;
}
$assignmentPermission = $this->aclManager->getPermissionLevel($user, 'assignmentPermission');
if (
$assignmentPermission === Table::LEVEL_YES ||
!in_array($assignmentPermission, [Table::LEVEL_TEAM, Table::LEVEL_NO])
) {
return true;
}
$toProcess = false;
if (!$entity->isNew()) {
if ($entity->isAttributeChanged(self::ATTR_ASSIGNED_USER_ID)) {
$toProcess = true;
}
}
else {
$toProcess = true;
}
if (!$toProcess) {
return true;
}
if (empty($assignedUserId)) {
if ($assignmentPermission === Table::LEVEL_NO && !$user->isApi()) {
return false;
}
return true;
}
if ($assignmentPermission === Table::LEVEL_NO) {
if ($user->id !== $assignedUserId) {
return false;
}
}
else if ($assignmentPermission === Table::LEVEL_TEAM) {
$teamIdList = $user->get(self::ATTR_TEAMS_IDS);
if (
!$this->entityManager
->getRepository('User')
->checkBelongsToAnyOfTeams($assignedUserId, $teamIdList)
) {
return false;
}
}
return true;
}
protected function isPermittedTeams(User $user, Entity $entity): bool
{
$assignmentPermission = $this->aclManager->getPermissionLevel($user, 'assignmentPermission');
if (!in_array($assignmentPermission, [Table::LEVEL_TEAM, Table::LEVEL_NO])) {
return true;
}
if (!$entity->hasLinkMultipleField(self::FIELD_TEAMS)) {
return true;
}
$teamIdList = $entity->getLinkMultipleIdList(self::FIELD_TEAMS);
if (empty($teamIdList)) {
return $this->isPermittedTeamsEmpty($user, $entity);
}
$newIdList = [];
if (!$entity->isNew()) {
$existingIdList = [];
$teamCollection = $this->entityManager
->getRDBRepository($entity->getEntityType())
->getRelation($entity, self::FIELD_TEAMS)
->select('id')
->find();
foreach ($teamCollection as $team) {
$existingIdList[] = $team->getId();
}
foreach ($teamIdList as $id) {
if (!in_array($id, $existingIdList)) {
$newIdList[] = $id;
}
}
}
else {
$newIdList = $teamIdList;
}
if (empty($newIdList)) {
return true;
}
$userTeamIdList = $user->getLinkMultipleIdList(self::FIELD_TEAMS);
foreach ($newIdList as $id) {
if (!in_array($id, $userTeamIdList)) {
return false;
}
}
return true;
}
private function isPermittedTeamsEmpty(User $user, Entity $entity): bool
{
$assignmentPermission = $this->aclManager->getPermissionLevel($user, 'assignmentPermission');
if ($assignmentPermission !== Table::LEVEL_TEAM) {
return true;
}
if ($entity->hasLinkMultipleField(self::FIELD_ASSIGNED_USERS)) {
$assignedUserIdList = $entity->getLinkMultipleIdList(self::FIELD_ASSIGNED_USERS);
if (empty($assignedUserIdList)) {
return false;
}
}
else if ($entity->hasAttribute(self::ATTR_ASSIGNED_USER_ID)) {
if (!$entity->get(self::ATTR_ASSIGNED_USER_ID)) {
return false;
}
}
return true;
}
protected function isPermittedAssignedUsers(User $user, Entity $entity): bool
{
if (!$entity->hasLinkMultipleField(self::FIELD_ASSIGNED_USERS)) {
return true;
}
if ($user->isPortal()) {
if (count($entity->getLinkMultipleIdList(self::FIELD_ASSIGNED_USERS)) === 0) {
return true;
}
}
$assignmentPermission = $this->aclManager->getPermissionLevel($user, 'assignmentPermission');
if (
$assignmentPermission === Table::LEVEL_YES ||
!in_array($assignmentPermission, [Table::LEVEL_TEAM, Table::LEVEL_NO])
) {
return true;
}
$toProcess = false;
if (!$entity->isNew()) {
$userIdList = $entity->getLinkMultipleIdList(self::FIELD_ASSIGNED_USERS);
if ($entity->isAttributeChanged(self::ATTR_ASSIGNED_USERS_IDS)) {
$toProcess = true;
}
}
else {
$toProcess = true;
}
$userIdList = $entity->getLinkMultipleIdList(self::FIELD_ASSIGNED_USERS);
if (!$toProcess) {
return true;
}
if (empty($userIdList)) {
if ($assignmentPermission === Table::LEVEL_NO && !$user->isApi()) {
return false;
}
return true;
}
if ($assignmentPermission === Table::LEVEL_NO) {
return $this->isPermittedAssignedUsersLevelNo($user, $entity);
}
if ($assignmentPermission === Table::LEVEL_TEAM) {
return $this->isPermittedAssignedUsersLevelTeam($user, $entity);
}
return true;
}
private function isPermittedAssignedUsersLevelNo(User $user, Entity $entity): bool
{
$userIdList = $entity->getLinkMultipleIdList(self::FIELD_ASSIGNED_USERS);
$fetchedAssignedUserIdList = $entity->getFetched(self::ATTR_ASSIGNED_USERS_IDS);
foreach ($userIdList as $userId) {
if (!$entity->isNew() && in_array($userId, $fetchedAssignedUserIdList)) {
continue;
}
if ($user->getId() !== $userId) {
return false;
}
}
return true;
}
private function isPermittedAssignedUsersLevelTeam(User $user, Entity $entity): bool
{
$userIdList = $entity->getLinkMultipleIdList(self::FIELD_ASSIGNED_USERS);
$fetchedAssignedUserIdList = $entity->getFetched(self::ATTR_ASSIGNED_USERS_IDS);
$teamIdList = $user->getLinkMultipleIdList(self::FIELD_TEAMS);
foreach ($userIdList as $userId) {
if (!$entity->isNew() && in_array($userId, $fetchedAssignedUserIdList)) {
continue;
}
if (
!$this->entityManager
->getRepository('User')
->checkBelongsToAnyOfTeams($userId, $teamIdList)
) {
return false;
}
}
return true;
}
}
@@ -0,0 +1,37 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
* Website: https://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* 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 General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\Di;
use Espo\Core\Acl\AssignmentChecker\AssignmentCheckerManager;
interface AssignmentCheckerManagerAware
{
public function setAssignmentCheckerManager(AssignmentCheckerManager $assignmentCheckerManager): void;
}
@@ -0,0 +1,45 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
* Website: https://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* 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 General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\Di;
use Espo\Core\Acl\AssignmentChecker\AssignmentCheckerManager;
trait AssignmentCheckerManagerSetter
{
/**
* @var AssignmentCheckerManager
*/
protected $assignmentCheckerManager;
public function setAssignmentCheckerManager(AssignmentCheckerManager $assignmentCheckerManager): void
{
$this->assignmentCheckerManager = $assignmentCheckerManager;
}
}
+8 -238
View File
@@ -84,7 +84,8 @@ class Service implements Crud,
Di\FieldUtilAware,
Di\FieldValidationManagerAware,
Di\RecordServiceContainerAware,
Di\SelectBuilderFactoryAware
Di\SelectBuilderFactoryAware,
Di\AssignmentCheckerManagerAware
{
use Di\ConfigSetter;
use Di\ServiceFactorySetter;
@@ -97,6 +98,7 @@ class Service implements Crud,
use Di\FieldValidationManagerSetter;
use Di\RecordServiceContainerSetter;
use Di\SelectBuilderFactorySetter;
use Di\AssignmentCheckerManagerSetter;
protected $getEntityBeforeUpdate = false;
@@ -364,253 +366,21 @@ class Service implements Crud,
}
/**
* @return void
* @throws Forbidden
*/
public function processAssignmentCheck(Entity $entity)
protected function processAssignmentCheck(Entity $entity): void
{
if (!$this->checkAssignment($entity)) {
throw new Forbidden("Assignment failure: assigned user or team not allowed.");
}
}
/**
* Check whether assignment can be applied for an entity.
*/
public function checkAssignment(Entity $entity): bool
{
if (!$this->isPermittedAssignedUser($entity)) {
return false;
}
if (!$this->isPermittedTeams($entity)) {
return false;
}
if ($entity->hasLinkMultipleField('assignedUsers')) {
if (!$this->isPermittedAssignedUsers($entity)) {
return false;
}
}
return true;
}
public function isPermittedAssignedUsers(Entity $entity): bool
{
if (!$entity->hasLinkMultipleField('assignedUsers')) {
return true;
}
if ($this->user->isPortal()) {
if (count($entity->getLinkMultipleIdList('assignedUsers')) === 0) {
return true;
}
}
$assignmentPermission = $this->acl->get('assignmentPermission');
if (
$assignmentPermission === true ||
$assignmentPermission === AclTable::LEVEL_YES ||
!in_array($assignmentPermission, [AclTable::LEVEL_TEAM, AclTable::LEVEL_NO])
) {
return true;
}
$toProcess = false;
if (!$entity->isNew()) {
$userIdList = $entity->getLinkMultipleIdList('assignedUsers');
if ($entity->isAttributeChanged('assignedUsersIds')) {
$toProcess = true;
}
}
else {
$toProcess = true;
}
$userIdList = $entity->getLinkMultipleIdList('assignedUsers');
if ($toProcess) {
if (empty($userIdList)) {
if ($assignmentPermission == AclTable::LEVEL_NO && !$this->user->isApi()) {
return false;
}
return true;
}
$fetchedAssignedUserIdList = $entity->getFetched('assignedUsersIds');
if ($assignmentPermission === AclTable::LEVEL_NO) {
foreach ($userIdList as $userId) {
if (!$entity->isNew() && in_array($userId, $fetchedAssignedUserIdList)) {
continue;
}
if ($this->user->id != $userId) {
return false;
}
}
} else if ($assignmentPermission === AclTable::LEVEL_TEAM) {
$teamIdList = $this->user->getLinkMultipleIdList('teams');
foreach ($userIdList as $userId) {
if (!$entity->isNew() && in_array($userId, $fetchedAssignedUserIdList)) {
continue;
}
if (
!$this->entityManager
->getRepository('User')
->checkBelongsToAnyOfTeams($userId, $teamIdList)
) {
return false;
}
}
}
}
return true;
}
public function isPermittedAssignedUser(Entity $entity): bool
{
if (!$entity->hasAttribute('assignedUserId')) {
return true;
}
$assignedUserId = $entity->get('assignedUserId');
if ($this->user->isPortal()) {
if (!$entity->isAttributeChanged('assignedUserId') && empty($assignedUserId)) {
return true;
}
}
$assignmentPermission = $this->acl->get('assignmentPermission');
if (
$assignmentPermission === true ||
$assignmentPermission === AclTable::LEVEL_YES ||
!in_array($assignmentPermission, [AclTable::LEVEL_TEAM, AclTable::LEVEL_NO])
) {
return true;
}
$toProcess = false;
if (!$entity->isNew()) {
if ($entity->isAttributeChanged('assignedUserId')) {
$toProcess = true;
}
} else {
$toProcess = true;
}
if ($toProcess) {
if (empty($assignedUserId)) {
if ($assignmentPermission === AclTable::LEVEL_NO && !$this->user->isApi()) {
return false;
}
return true;
}
if ($assignmentPermission === AclTable::LEVEL_NO) {
if ($this->user->id !== $assignedUserId) {
return false;
}
}
else if ($assignmentPermission === AclTable::LEVEL_TEAM) {
$teamIdList = $this->user->get('teamsIds');
if (
!$this->entityManager
->getRepository('User')
->checkBelongsToAnyOfTeams($assignedUserId, $teamIdList)
) {
return false;
}
}
}
return true;
}
public function isPermittedTeams(Entity $entity): bool
{
$assignmentPermission = $this->acl->get('assignmentPermission');
if (
empty($assignmentPermission) ||
$assignmentPermission === true ||
!in_array($assignmentPermission, [AclTable::LEVEL_TEAM, AclTable::LEVEL_NO])
) {
return true;
}
if (!$entity->hasLinkMultipleField('teams')) {
return true;
}
$teamIdList = $entity->getLinkMultipleIdList('teams');
if (empty($teamIdList)) {
if ($assignmentPermission === 'team') {
if ($entity->hasLinkMultipleField('assignedUsers')) {
$assignedUserIdList = $entity->getLinkMultipleIdList('assignedUsers');
if (empty($assignedUserIdList)) {
return false;
}
}
else if ($entity->hasAttribute('assignedUserId')) {
if (!$entity->get('assignedUserId')) {
return false;
}
}
}
return true;
}
$newIdList = [];
if (!$entity->isNew()) {
$existingIdList = [];
$teamCollection = $this->entityManager
->getRepository($entity->getEntityType())
->getRelation($entity, 'teams')
->select('id')
->find();
foreach ($teamCollection as $team) {
$existingIdList[] = $team->id;
}
foreach ($teamIdList as $id) {
if (!in_array($id, $existingIdList)) {
$newIdList[] = $id;
}
}
} else {
$newIdList = $teamIdList;
}
if (empty($newIdList)) {
return true;
}
$userTeamIdList = $this->user->getLinkMultipleIdList('teams');
foreach ($newIdList as $id) {
if (!in_array($id, $userTeamIdList)) {
return false;
}
}
return true;
return $this->assignmentCheckerManager->check($this->user, $entity);
}
protected function filterInputAttribute($attribute, $value)
@@ -3,5 +3,6 @@
"ownershipCheckerClassName": "Espo\\Classes\\Acl\\Email\\OwnershipChecker",
"portalAccessCheckerClassName": "Espo\\Classes\\AclPortal\\Email\\AccessChecker",
"portalOwnershipCheckerClassName": "Espo\\Classes\\AclPortal\\Email\\OwnershipChecker",
"assignmentCheckerClassName": "Espo\\Classes\\Acl\\Email\\AssignmentChecker",
"readOwnerUserField": "users"
}
@@ -80,6 +80,9 @@
"fieldValidationManager": {
"className": "Espo\\Core\\FieldValidation\\FieldValidationManager"
},
"assignmentCheckerManager": {
"className": "Espo\\Core\\Acl\\AssignmentChecker\\AssignmentCheckerManager"
},
"hasher": {
"className": "Espo\\Core\\Utils\\Hasher"
},
-10
View File
@@ -963,14 +963,4 @@ class Email extends Record implements
return $data;
}
public function isPermittedAssignedUser(Entity $entity): bool
{
return true;
}
public function isPermittedAssignedUsers(Entity $entity): bool
{
return true;
}
}
+1 -1
View File
@@ -190,7 +190,7 @@ class Note extends Record
$entity->set('post', $post);
}
public function processAssignmentCheck(Entity $entity)
protected function processAssignmentCheck(Entity $entity): void
{
if (!$entity->isNew()) {
return;