From cd216007af29fda3bed12a1dcfdda6529fd96053 Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Fri, 19 Apr 2024 11:28:01 +0300 Subject: [PATCH] assigned to self and default team if no assignment permission --- .../Core/Record/Defaults/DefaultPopulator.php | 68 ++++++++++++---- .../Espo/Record/AssignmentTest.php | 78 +++++++++++++++++++ 2 files changed, 132 insertions(+), 14 deletions(-) create mode 100644 tests/integration/Espo/Record/AssignmentTest.php diff --git a/application/Espo/Core/Record/Defaults/DefaultPopulator.php b/application/Espo/Core/Record/Defaults/DefaultPopulator.php index b5e49993e3..6318496cb9 100644 --- a/application/Espo/Core/Record/Defaults/DefaultPopulator.php +++ b/application/Espo/Core/Record/Defaults/DefaultPopulator.php @@ -38,6 +38,7 @@ use Espo\Core\Utils\FieldUtil; use Espo\Entities\User; use Espo\ORM\Entity; use Espo\ORM\EntityManager; +use RuntimeException; /** * @implements Populator @@ -61,14 +62,12 @@ class DefaultPopulator implements Populator $entity->set('assignedUserName', $this->user->getName()); } - if ( - !$this->user->isPortal() && - $entity instanceof CoreEntity && - $entity->hasLinkMultipleField('teams') && - $this->user->getDefaultTeam() && - !$this->acl->checkField($entityType, 'teams', AclTable::ACTION_EDIT) - ) { - $defaultTeamId = $this->user->getDefaultTeam()->getId(); + if ($this->toAddDetailTeam($entity)) { + $defaultTeamId = $this->user->getDefaultTeam()?->getId(); + + if (!$defaultTeamId || !$entity instanceof CoreEntity) { + throw new RuntimeException(); + } $entity->addLinkMultipleId('teams', $defaultTeamId); @@ -107,17 +106,58 @@ class DefaultPopulator implements Populator $defs = $this->entityManager->getDefs()->getEntity($entityType); - if ( - !$defs->hasField('assignedUser') || - $defs->getField('assignedUser')->getType() !== FieldType::LINK - ) { + if ($defs->tryGetField('assignedUser')?->getType() !== FieldType::LINK) { return false; } - if ($this->acl->checkField($entityType, 'assignedUser', AclTable::ACTION_EDIT)) { + if ($this->acl->getPermissionLevel('assignment') === AclTable::LEVEL_NO && !$this->user->isApi()) { + return true; + } + + if (!$this->acl->checkField($entityType, 'assignedUser', AclTable::ACTION_EDIT)) { + return true; + } + + return false; + } + + /** + * @phpstan-assert-if-true CoreEntity $entity + */ + private function toAddDetailTeam(Entity $entity): bool + { + if ($this->user->isPortal()) { return false; } - return true; + if (!$this->user->getDefaultTeam()) { + return false; + } + + if (!$entity instanceof CoreEntity) { + return false; + } + + if ($entity->hasLinkMultipleId('teams', $this->user->getDefaultTeam()->getId())) { + return false; + } + + $entityType = $entity->getEntityType(); + + $defs = $this->entityManager->getDefs()->getEntity($entityType); + + if ($defs->tryGetField('teams')?->getType() !== FieldType::LINK_MULTIPLE) { + return false; + } + + if ($this->acl->getPermissionLevel('assignment') === AclTable::LEVEL_NO) { + return true; + } + + if (!$this->acl->checkField($entityType, 'teams', AclTable::ACTION_EDIT)) { + return true; + } + + return false; } } diff --git a/tests/integration/Espo/Record/AssignmentTest.php b/tests/integration/Espo/Record/AssignmentTest.php new file mode 100644 index 0000000000..babb3a89ff --- /dev/null +++ b/tests/integration/Espo/Record/AssignmentTest.php @@ -0,0 +1,78 @@ +. + * + * 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 tests\integration\Espo\Record; + +use Espo\Core\Acl\Table; +use Espo\Core\Record\CreateParams; +use Espo\Core\Record\ServiceContainer; +use Espo\Entities\Team; +use Espo\Modules\Crm\Entities\Lead; +use tests\integration\Core\BaseTestCase; + +class AssignmentTest extends BaseTestCase +{ + public function testAssignment1(): void + { + $team1 = $this->getEntityManager()->createEntity(Team::ENTITY_TYPE); + + $user1 = $this->createUser([ + 'userName' => 'test1', + 'defaultTeamId' => $team1->getId(), + 'teamsIds' => [$team1->getId()], + ], [ + 'data' => [ + Lead::ENTITY_TYPE => [ + 'create' => Table::LEVEL_YES, + 'read' => Table::LEVEL_OWN, + 'edit' => Table::LEVEL_OWN, + 'delete' => Table::LEVEL_OWN, + ], + ], + 'assignmentPermission' => Table::LEVEL_NO, + ]); + + $this->auth('test1'); + $this->reCreateApplication(); + + /** + * @noinspection PhpUnhandledExceptionInspection + * @var Lead $lead1 + */ + $lead1 = $this->getContainer() + ->getByClass(ServiceContainer::class) + ->getByClass(Lead::class) + ->create((object) [ + 'lastName' => 'Test 1', + ], CreateParams::create()); + + $this->assertEquals($user1->getId(), $lead1->getAssignedUser()?->getId()); + $this->assertEquals([$team1->getId()], $lead1->getLinkMultipleIdList('teams')); + } +}