Merge branch 'fix'

This commit is contained in:
Yuri Kuznetsov
2024-01-10 14:20:43 +02:00
15 changed files with 678 additions and 37 deletions
@@ -0,0 +1,80 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM Open Source CRM application.
* Copyright (C) 2014-2024 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
* Website: https://www.espocrm.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://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 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\Email\LinkCheckers;
use Espo\Core\Acl\LinkChecker;
use Espo\Core\AclManager;
use Espo\Entities\Email;
use Espo\Entities\User;
use Espo\ORM\Entity;
use Espo\ORM\EntityManager;
/**
* @implements LinkChecker<Email, Entity>
* @noinspection PhpUnused
*/
class ParentLinkChecker implements LinkChecker
{
public function __construct(
private EntityManager $entityManager,
private AclManager $aclManager
) {}
public function check(User $user, Entity $entity, Entity $foreignEntity): bool
{
if ($this->aclManager->checkEntityRead($user, $foreignEntity)) {
return true;
}
if (!$entity->getReplied()) {
return false;
}
$replied = $this->entityManager
->getRepositoryByClass(Email::class)
->getById($entity->getReplied()->getId());
if (!$replied) {
return false;
}
$parentLink = $replied->getParent();
if (
!$parentLink ||
$parentLink->getId() !== $foreignEntity->getId() ||
$parentLink->getEntityType() !== $foreignEntity->getEntityType()
) {
return false;
}
return $this->aclManager->checkEntityRead($user, $replied);
}
}
@@ -51,7 +51,7 @@ use Espo\ORM\EntityManager;
use Espo\ORM\Type\RelationType;
/**
* Check access for record linking.
* Check access for record linking. When linking directly through relationships or via link fields.
*/
class LinkCheck
{
@@ -223,16 +223,32 @@ class LinkCheck
);
}
if ($isOne) {
$this->linkForeignAccessCheckOne($entityType, $link, $foreignEntity);
$toSkip = $this->linkForeignAccessCheck($isOne, $entityType, $link, $foreignEntity);
if ($toSkip) {
return;
}
$this->linkForeignAccessCheck($entityType, $link, $foreignEntity, true);
$this->linkEntityAccessCheck($entity, $foreignEntity, $link);
}
/**
* @throws Forbidden
*/
private function linkForeignAccessCheck(
bool $isOne,
string $entityType,
string $link,
Entity $foreignEntity
): bool {
if ($isOne) {
return $this->linkForeignAccessCheckOne($entityType, $link, $foreignEntity);
}
return $this->linkForeignAccessCheckMany($entityType, $link, $foreignEntity, true);
}
private function getParam(string $entityType, string $link, string $param): mixed
{
return $this->metadata->get(['recordDefs', $entityType, 'relationships', $link, $param]);
@@ -283,7 +299,12 @@ class LinkCheck
*/
public function processLinkForeign(Entity $entity, string $link, Entity $foreignEntity): void
{
$this->linkForeignAccessCheck($entity->getEntityType(), $link, $foreignEntity);
$toSkip = $this->linkForeignAccessCheckMany($entity->getEntityType(), $link, $foreignEntity);
if ($toSkip) {
return;
}
$this->linkEntityAccessCheck($entity, $foreignEntity, $link);
}
@@ -299,14 +320,17 @@ class LinkCheck
}
/**
* Check access to foreign record for has-many and many-many links.
*
* @return bool True indicates that the link checker should be bypassed.
* @throws Forbidden
*/
private function linkForeignAccessCheck(
private function linkForeignAccessCheckMany(
string $entityType,
string $link,
Entity $foreignEntity,
bool $fromUpdate = false
): void {
): bool {
$action = in_array($link, $this->noEditAccessRequiredLinkList) ?
AclTable::ACTION_READ :
@@ -318,7 +342,7 @@ class LinkCheck
}
if ($this->getParam($entityType, $link, 'linkForeignAccessCheckDisabled')) {
return;
return true;
}
$fieldDefs = $fromUpdate ?
@@ -336,19 +360,23 @@ class LinkCheck
$action = AclTable::ACTION_READ;
if ($this->checkInDefaults($fieldDefs, $link, $foreignEntity)) {
return;
return true;
}
}
if ($this->acl->check($foreignEntity, $action)) {
return;
}
if (
$action === AclTable::ACTION_READ &&
$this->checkIsAllowedForPortal($foreignEntity)
) {
return;
return true;
}
if ($this->acl->check($foreignEntity, $action)) {
return false;
}
if ($this->getLinkChecker($entityType, $link)) {
return false;
}
$body = ErrorBody::create();
@@ -409,8 +437,10 @@ class LinkCheck
throw ForbiddenSilent::createWithBody(
"No access for link operation ($entityType:$link).",
ErrorBody::create()
->withMessageTranslation('noLinkAccess')
->encode()
->withMessageTranslation('noLinkAccess', null, [
'foreignEntityType' => $foreignEntity->getEntityType(),
'link' => $link,
])
);
}
@@ -537,12 +567,15 @@ class LinkCheck
}
/**
* Check access to foreign record for belongs-to, has-one and belongs-to-parent links.
*
* @return bool True indicates that the link checker should be bypassed.
* @throws Forbidden
*/
private function linkForeignAccessCheckOne(string $entityType, string $link, Entity $foreignEntity): void
private function linkForeignAccessCheckOne(string $entityType, string $link, Entity $foreignEntity): bool
{
if ($this->getParam($entityType, $link, 'linkForeignAccessCheckDisabled')) {
return;
return true;
}
$fieldDefs = $this->entityManager
@@ -555,16 +588,20 @@ class LinkCheck
in_array($fieldDefs->getType(), $this->oneFieldTypeList)
) {
if ($this->checkIsDefault($fieldDefs, $link, $foreignEntity)) {
return;
return true;
}
}
if ($this->acl->check($foreignEntity, AclTable::ACTION_READ)) {
return;
if ($this->checkIsAllowedForPortal($foreignEntity)) {
return true;
}
if ($this->checkIsAllowedForPortal($foreignEntity)) {
return;
if ($this->acl->check($foreignEntity, AclTable::ACTION_READ)) {
return false;
}
if ($this->getLinkChecker($entityType, $link)) {
return false;
}
throw ForbiddenSilent::createWithBody(
@@ -590,7 +627,6 @@ class LinkCheck
{
return $foreignEntity->getId() === $this->getDefault($fieldDefs, $link . 'Id');
}
private function getDefault(FieldDefs $fieldDefs, string $attribute): mixed
{
$defaultAttributes = (object) ($fieldDefs->getParam('defaultAttributes') ?? []);
@@ -0,0 +1,91 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM Open Source CRM application.
* Copyright (C) 2014-2024 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
* Website: https://www.espocrm.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://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 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\Modules\Crm\Classes\Acl\Case\LinkCheckers;
use Espo\Core\Acl\LinkChecker;
use Espo\Core\AclManager;
use Espo\Entities\Email;
use Espo\Entities\User;
use Espo\Modules\Crm\Entities\Account;
use Espo\Modules\Crm\Entities\CaseObj;
use Espo\ORM\Entity;
use Espo\ORM\EntityManager;
/**
* @implements LinkChecker<CaseObj, Account>
* @noinspection PhpUnused
*/
class AccountLinkChecker implements LinkChecker
{
public function __construct(
private AclManager $aclManager,
private EntityManager $entityManager
) {}
public function check(User $user, Entity $entity, Entity $foreignEntity): bool
{
if ($this->aclManager->checkEntityRead($user, $foreignEntity)) {
return true;
}
if (!$entity->isNew()) {
return false;
}
$emailIds = $entity->getLinkMultipleIdList('emails');
if (count($emailIds) === 0 || count($emailIds) > 1) {
return false;
}
$email = $this->entityManager
->getRepositoryByClass(Email::class)
->getById($emailIds[0]);
if (!$email) {
return false;
}
$parent = $email->getParent();
if (!$parent) {
return false;
}
if (
$parent->getEntityType() !== Account::ENTITY_TYPE ||
$parent->getId() !== $foreignEntity->getId()
) {
return false;
}
return $this->aclManager->checkEntityRead($user, $email);
}
}
@@ -0,0 +1,91 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM Open Source CRM application.
* Copyright (C) 2014-2024 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
* Website: https://www.espocrm.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://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 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\Modules\Crm\Classes\Acl\Case\LinkCheckers;
use Espo\Core\Acl\LinkChecker;
use Espo\Core\AclManager;
use Espo\Entities\Email;
use Espo\Entities\User;
use Espo\Modules\Crm\Entities\CaseObj;
use Espo\Modules\Crm\Entities\Contact;
use Espo\ORM\Entity;
use Espo\ORM\EntityManager;
/**
* @implements LinkChecker<CaseObj, Contact>
* @noinspection PhpUnused
*/
class ContactLinkChecker implements LinkChecker
{
public function __construct(
private AclManager $aclManager,
private EntityManager $entityManager
) {}
public function check(User $user, Entity $entity, Entity $foreignEntity): bool
{
if ($this->aclManager->checkEntityRead($user, $foreignEntity)) {
return true;
}
if (!$entity->isNew()) {
return false;
}
$emailIds = $entity->getLinkMultipleIdList('emails');
if (count($emailIds) === 0 || count($emailIds) > 1) {
return false;
}
$email = $this->entityManager
->getRepositoryByClass(Email::class)
->getById($emailIds[0]);
if (!$email) {
return false;
}
$parent = $email->getParent();
if (!$parent) {
return false;
}
if (
$parent->getEntityType() !== Contact::ENTITY_TYPE ||
$parent->getId() !== $foreignEntity->getId()
) {
return false;
}
return $this->aclManager->checkEntityRead($user, $email);
}
}
@@ -0,0 +1,91 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM Open Source CRM application.
* Copyright (C) 2014-2024 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
* Website: https://www.espocrm.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://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 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\Modules\Crm\Classes\Acl\Case\LinkCheckers;
use Espo\Core\Acl\LinkChecker;
use Espo\Core\AclManager;
use Espo\Entities\Email;
use Espo\Entities\User;
use Espo\Modules\Crm\Entities\CaseObj;
use Espo\Modules\Crm\Entities\Lead;
use Espo\ORM\Entity;
use Espo\ORM\EntityManager;
/**
* @implements LinkChecker<CaseObj, Lead>
* @noinspection PhpUnused
*/
class LeadLinkChecker implements LinkChecker
{
public function __construct(
private AclManager $aclManager,
private EntityManager $entityManager
) {}
public function check(User $user, Entity $entity, Entity $foreignEntity): bool
{
if ($this->aclManager->checkEntityRead($user, $foreignEntity)) {
return true;
}
if (!$entity->isNew()) {
return false;
}
$emailIds = $entity->getLinkMultipleIdList('emails');
if (count($emailIds) === 0 || count($emailIds) > 1) {
return false;
}
$email = $this->entityManager
->getRepositoryByClass(Email::class)
->getById($emailIds[0]);
if (!$email) {
return false;
}
$parent = $email->getParent();
if (!$parent) {
return false;
}
if (
$parent->getEntityType() !== Lead::ENTITY_TYPE ||
$parent->getId() !== $foreignEntity->getId()
) {
return false;
}
return $this->aclManager->checkEntityRead($user, $email);
}
}
@@ -0,0 +1,8 @@
{
"linkCheckerClassNameMap": {
"lead": "Espo\\Modules\\Crm\\Classes\\Acl\\Case\\LinkCheckers\\LeadLinkChecker",
"account": "Espo\\Modules\\Crm\\Classes\\Acl\\Case\\LinkCheckers\\AccountLinkChecker",
"contact": "Espo\\Modules\\Crm\\Classes\\Acl\\Case\\LinkCheckers\\ContactLinkChecker",
"contacts": "Espo\\Modules\\Crm\\Classes\\Acl\\Case\\LinkCheckers\\ContactLinkChecker"
}
}
@@ -376,7 +376,7 @@
"loggedOutLeaveOut": "Logged out. The session is inactive. You may lose unsaved form data after page refresh. You may need to make a copy.",
"noAccessToRecord": "Operation requires `{action}` access to record.",
"noAccessToForeignRecord": "Operation requires `{action}` access to foreign record.",
"noLinkAccess": "No access to link operation for a specific record.",
"noLinkAccess": "Can't relate with {foreignEntityType} record through the link '{link}'. No access.",
"cannotUnrelateRequiredLink": "Can't unrelate required link.",
"cannotRelateNonExisting": "Can't relate with non-existing {foreignEntityType} record.",
"cannotRelateForbidden": "Can't relate with forbidden {foreignEntityType} record. `{action}` access required.",
@@ -4,5 +4,8 @@
"portalAccessCheckerClassName": "Espo\\Classes\\AclPortal\\Email\\AccessChecker",
"portalOwnershipCheckerClassName": "Espo\\Classes\\AclPortal\\Email\\OwnershipChecker",
"assignmentCheckerClassName": "Espo\\Classes\\Acl\\Email\\AssignmentChecker",
"readOwnerUserField": "users"
"readOwnerUserField": "users",
"linkCheckerClassNameMap": {
"parent": "Espo\\Classes\\Acl\\Email\\LinkCheckers\\ParentLinkChecker"
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
<p class="credit small">&copy; 2023
<p class="credit small">&copy; 2024
<a
href="https://www.espocrm.com"
title="Powered by EspoCRM"
+1 -1
View File
@@ -36,7 +36,7 @@
<body>
<div class="container content"></div>
<footer>
<p class="credit small">&copy; 2023
<p class="credit small">&copy; 2024
<a href="https://www.espocrm.com" title="Powered by EspoCRM" rel="noopener" target="_blank">EspoCRM</a></p>
</footer>
</body>
+1 -1
View File
@@ -1,2 +1,2 @@
<p class="credit small">&copy; 2023 <a href="https://www.espocrm.com">EspoCRM</a></p>
<p class="credit small">&copy; 2024 <a href="https://www.espocrm.com">EspoCRM</a></p>
+1 -1
View File
@@ -30,7 +30,7 @@
"type": "string"
},
"linkCheckerClassNameMap": {
"description": "Link checker classes for specific links.",
"description": "Link checker classes for specific links. Should implement `Espo\\Core\\Acl\\LinkChecker`.",
"type": "object",
"additionalProperties": {
"type": "string"
+77 -7
View File
@@ -29,13 +29,17 @@
namespace tests\integration\Espo\Portal;
use Espo\Core\{
Select\SearchParams,
};
use Espo\Core\Exceptions\Forbidden;
use Espo\Core\Record\CreateParams;
use Espo\Core\Record\Service;
use Espo\Core\Record\ServiceContainer;
use Espo\Core\Select\SearchParams;
use Espo\Modules\Crm\Entities\CaseObj;
use tests\integration\Core\BaseTestCase;
class AclTest extends \tests\integration\Core\BaseTestCase
class AclTest extends BaseTestCase
{
public function testAccessContact()
public function testAccessContact(): void
{
$app = $this->createApplication();
@@ -101,7 +105,7 @@ class AclTest extends \tests\integration\Core\BaseTestCase
$this->assertFalse(in_array($case3->id, $idList));
}
public function testAccessAccount()
public function testAccessAccount(): void
{
$app = $this->createApplication();
@@ -173,7 +177,7 @@ class AclTest extends \tests\integration\Core\BaseTestCase
$this->assertTrue(in_array($case4->id, $idList));
}
public function testAccessOwn()
public function testAccessOwn(): void
{
$app = $this->createApplication();
@@ -252,4 +256,70 @@ class AclTest extends \tests\integration\Core\BaseTestCase
$this->assertFalse(in_array($case4->id, $idList));
$this->assertTrue(in_array($case5->id, $idList));
}
public function testCreateCase(): void
{
$em = $this->getEntityManager();
$contact = $em->createEntity('Contact');
$account = $em->createEntity('Account');
$contactNotOwn = $em->createEntity('Contact');
$accountNotOwn = $em->createEntity('Account');
$portal = $em->createEntity('Portal', [
'name' => 'Portal',
]);
$this->createUser([
'userName' => 'tester',
'portalsIds' => [$portal->getId()],
'contactId' => $contact->getId(),
'accountsIds' => [$account->getId()],
], [
'data' => [
'Case' => [
'create' => 'yes',
'read' => 'own',
'edit' => 'no',
'delete' => 'no',
'stream' => 'own',
]
],
], true);
$this->auth('tester', null, $portal->getId());
$app = $this->createApplication(true, $portal->getId());
/** @var Service<CaseObj> $caseService */
$caseService = $app->getContainer()
->getByClass(ServiceContainer::class)
->getByClass(CaseObj::class);
/** @noinspection PhpUnhandledExceptionInspection */
$caseService->create((object) [
'name' => 'Test 1',
'accountId' => $account->getId(),
'contactId' => $contact->getId(),
'contactsIds' => [$contact->getId()],
], CreateParams::create());
$isThrown = false;
try {
/** @noinspection PhpUnhandledExceptionInspection */
$caseService->create((object)[
'name' => 'Test 1',
'accountId' => $accountNotOwn->getId(),
'contactId' => $contactNotOwn->getId(),
'contactsIds' => [$contactNotOwn->getId()],
], CreateParams::create());
}
catch (Forbidden) {
$isThrown = true;
}
$this->assertTrue($isThrown);
}
}
+168
View File
@@ -35,8 +35,11 @@ use Espo\Core\Record\CreateParams;
use Espo\Core\Record\ServiceContainer;
use Espo\Core\Record\UpdateParams;
use Espo\Core\Utils\Metadata;
use Espo\Entities\Email;
use Espo\Modules\Crm\Entities\Account;
use Espo\Modules\Crm\Entities\CaseObj;
use Espo\Modules\Crm\Entities\Contact;
use Espo\Modules\Crm\Entities\Lead;
use Espo\Modules\Crm\Entities\Opportunity;
use Espo\Modules\Crm\Entities\Task;
use Espo\ORM\EntityManager;
@@ -232,4 +235,169 @@ class LinkTest extends BaseTestCase
'closeDate' => Date::createToday()->toString(),
], CreateParams::create());
}
public function testLinkCheckEmailToCase(): void
{
$user = $this->createUser('test', [
'data' => [
'Account' => [
'create' => 'no',
'read' => 'own',
'edit' => 'no',
'delete' => 'no',
],
'Case' => [
'create' => 'yes',
'read' => 'own',
'edit' => 'own',
'delete' => 'no',
],
'Contact' => [
'create' => 'yes',
'read' => 'own',
'edit' => 'own',
'delete' => 'no',
],
'Lead' => [
'create' => 'yes',
'read' => 'own',
'edit' => 'own',
'delete' => 'no',
],
'Email' => [
'create' => 'yes',
'read' => 'own',
'edit' => 'own',
'delete' => 'no',
],
],
]);
$em = $this->getEntityManager();
$account = $em->createEntity(Account::ENTITY_TYPE, ['assignedUserId' => $user->getId()]);
$lead = $em->createEntity(Lead::ENTITY_TYPE);
$contact = $em->createEntity(Contact::ENTITY_TYPE);
$email = $em->createEntity(Email::ENTITY_TYPE, [
'assignedUserId' => $user->getId(),
'parentId' => $lead->getId(),
'parentType' => Lead::ENTITY_TYPE,
]);
$this->auth('test');
$this->reCreateApplication();
$caseService = $this->getContainer()
->getByClass(ServiceContainer::class)
->getByClass(CaseObj::class);
// Should not create if no access to the Lead.
$isThrown = false;
try {
/** @noinspection PhpUnhandledExceptionInspection */
$caseService->create((object) [
'name' => '1',
'assignedUserId' => $user->getId(),
'leadId' => $lead->getId(),
'accountId' => $account->getId(),
], CreateParams::create());
}
catch (Forbidden) {
$isThrown = true;
}
$this->assertTrue($isThrown);
// Should create if an email with a Lead parent is passed.
/** @noinspection PhpUnhandledExceptionInspection */
$caseService->create((object) [
'name' => '1',
'assignedUserId' => $user->getId(),
'leadId' => $lead->getId(),
'accountId' => $account->getId(),
'emailsIds' => [$email->getId()]
], CreateParams::create());
//
$account = $em->createEntity(Account::ENTITY_TYPE);
$email = $em->createEntity(Email::ENTITY_TYPE, [
'assignedUserId' => $user->getId(),
'parentId' => $account->getId(),
'parentType' => Account::ENTITY_TYPE,
]);
// Should not create if no access to the Account.
$isThrown = false;
try {
/** @noinspection PhpUnhandledExceptionInspection */
$caseService->create((object) [
'name' => '1',
'assignedUserId' => $user->getId(),
'accountId' => $account->getId(),
], CreateParams::create());
}
catch (Forbidden) {
$isThrown = true;
}
$this->assertTrue($isThrown);
// Should create if an email with an Account parent is passed.
/** @noinspection PhpUnhandledExceptionInspection */
$caseService->create((object) [
'name' => '1',
'assignedUserId' => $user->getId(),
'accountId' => $account->getId(),
'emailsIds' => [$email->getId()]
], CreateParams::create());
//
$account = $em->createEntity(Account::ENTITY_TYPE, ['assignedUserId' => $user->getId()]);
$email = $em->createEntity(Email::ENTITY_TYPE, [
'assignedUserId' => $user->getId(),
'parentId' => $contact->getId(),
'parentType' => Contact::ENTITY_TYPE,
]);
// Should not create if no access to the Contact.
$isThrown = false;
try {
/** @noinspection PhpUnhandledExceptionInspection */
$caseService->create((object) [
'name' => '1',
'assignedUserId' => $user->getId(),
'accountId' => $account->getId(),
'contactId' => $contact->getId(),
'contactsIds' => [$contact->getId()],
], CreateParams::create());
}
catch (Forbidden) {
$isThrown = true;
}
$this->assertTrue($isThrown);
// Should create if an email with a Contact parent is passed.
/** @noinspection PhpUnhandledExceptionInspection */
$caseService->create((object) [
'name' => '1',
'assignedUserId' => $user->getId(),
'accountId' => $account->getId(),
'contactId' => $contact->getId(),
'contactsIds' => [$contact->getId()],
'emailsIds' => [$email->getId()]
], CreateParams::create());
}
}
@@ -69,6 +69,9 @@ class SanitizeTest extends BaseTestCase
$numbers = $account->getPhoneNumberGroup()->getNumberList();
$this->assertCount(2, $numbers);
sort($numbers);
$this->assertEquals('+380904443322', $numbers[0]);
$this->assertEquals('+380904443333', $numbers[1]);
}