acl portal changes and tests
This commit is contained in:
@@ -104,6 +104,13 @@ class Base extends \Espo\Core\Acl\Base
|
||||
}
|
||||
if ($inAccount) {
|
||||
return true;
|
||||
} else {
|
||||
if (is_null($isOwnContact) && $entity) {
|
||||
$isOwnContact = $this->checkIsOwnContact($user, $entity);
|
||||
}
|
||||
if ($isOwnContact) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,7 +124,6 @@ class Base extends \Espo\Core\Acl\Base
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
public function checkReadOnlyAccount(User $user, $data)
|
||||
@@ -152,13 +158,13 @@ class Base extends \Espo\Core\Acl\Base
|
||||
{
|
||||
$accountIdList = $user->getLinkMultipleIdList('accounts');
|
||||
if (count($accountIdList)) {
|
||||
if ($entity->hasAttribute('accountId')) {
|
||||
if ($entity->hasAttribute('accountId') && $entity->getRelationParam('account', 'entity') === 'Account') {
|
||||
if (in_array($entity->get('accountId'), $accountIdList)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($entity->hasRelation('accounts')) {
|
||||
if ($entity->hasRelation('accounts') && $entity->getRelationParam('accounts', 'entity') === 'Account') {
|
||||
$repository = $this->getEntityManager()->getRepository($entity->getEntityType());
|
||||
foreach ($accountIdList as $accountId) {
|
||||
if ($repository->isRelated($entity, 'accounts', $accountId)) {
|
||||
@@ -183,13 +189,13 @@ class Base extends \Espo\Core\Acl\Base
|
||||
{
|
||||
$contactId = $user->get('contactId');
|
||||
if ($contactId) {
|
||||
if ($entity->hasAttribute('contactId')) {
|
||||
if ($entity->hasAttribute('contactId') && $entity->getRelationParam('contact', 'entity') === 'Contact') {
|
||||
if ($entity->get('contactId') === $contactId) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($entity->hasRelation('contacts')) {
|
||||
if ($entity->hasRelation('contacts') && $entity->getRelationParam('contacts', 'entity') === 'Contact') {
|
||||
$repository = $this->getEntityManager()->getRepository($entity->getEntityType());
|
||||
if ($repository->isRelated($entity, 'contacts', $contactId)) {
|
||||
return true;
|
||||
@@ -207,6 +213,4 @@ class Base extends \Espo\Core\Acl\Base
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -552,16 +552,16 @@ class Base
|
||||
return;
|
||||
}
|
||||
|
||||
$d = [
|
||||
$or = [
|
||||
'teamsAccess.id' => $this->getUser()->getLinkMultipleIdList('teams')
|
||||
];
|
||||
if ($this->hasAssignedUserField()) {
|
||||
$d['assignedUserId'] = $this->getUser()->id;
|
||||
$or['assignedUserId'] = $this->getUser()->id;
|
||||
} else if ($this->hasCreatedByField()) {
|
||||
$d['createdById'] = $this->getUser()->id;
|
||||
$or['createdById'] = $this->getUser()->id;
|
||||
}
|
||||
$result['whereClause'][] = [
|
||||
'OR' => $d
|
||||
'OR' => $or
|
||||
];
|
||||
}
|
||||
|
||||
@@ -580,38 +580,42 @@ class Base
|
||||
|
||||
protected function accessPortalOnlyContact(&$result)
|
||||
{
|
||||
$d = [];
|
||||
$or = [];
|
||||
|
||||
$contactId = $this->getUser()->get('contactId');
|
||||
|
||||
if ($contactId) {
|
||||
if ($this->getSeed()->hasAttribute('contactId')) {
|
||||
$d['contactId'] = $contactId;
|
||||
if (
|
||||
$this->getSeed()->hasAttribute('contactId') && $this->getSeed()->getRelationParam('contact', 'entity') === 'Contact'
|
||||
) {
|
||||
$or['contactId'] = $contactId;
|
||||
}
|
||||
if ($this->getSeed()->hasRelation('contacts')) {
|
||||
if (
|
||||
$this->getSeed()->hasRelation('contacts') && $this->getSeed()->getRelationParam('contacts', 'entity') === 'Contact'
|
||||
) {
|
||||
$this->addLeftJoin(['contacts', 'contactsAccess'], $result);
|
||||
$this->setDistinct(true, $result);
|
||||
$d['contactsAccess.id'] = $contactId;
|
||||
$or['contactsAccess.id'] = $contactId;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->getSeed()->hasAttribute('createdById')) {
|
||||
$d['createdById'] = $this->getUser()->id;
|
||||
$or['createdById'] = $this->getUser()->id;
|
||||
}
|
||||
|
||||
if ($this->getSeed()->hasAttribute('parentId') && $this->getSeed()->hasRelation('parent')) {
|
||||
$contactId = $this->getUser()->get('contactId');
|
||||
if ($contactId) {
|
||||
$d[] = [
|
||||
$or[] = [
|
||||
'parentType' => 'Contact',
|
||||
'parentId' => $contactId
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($d)) {
|
||||
if (!empty($or)) {
|
||||
$result['whereClause'][] = [
|
||||
'OR' => $d
|
||||
'OR' => $or
|
||||
];
|
||||
} else {
|
||||
$result['whereClause'][] = [
|
||||
@@ -622,27 +626,31 @@ class Base
|
||||
|
||||
protected function accessPortalOnlyAccount(&$result)
|
||||
{
|
||||
$d = [];
|
||||
$or = [];
|
||||
|
||||
$accountIdList = $this->getUser()->getLinkMultipleIdList('accounts');
|
||||
$contactId = $this->getUser()->get('contactId');
|
||||
|
||||
if (count($accountIdList)) {
|
||||
if ($this->getSeed()->hasAttribute('accountId')) {
|
||||
$d['accountId'] = $accountIdList;
|
||||
if (
|
||||
$this->getSeed()->hasAttribute('accountId') && $this->getSeed()->getRelationParam('account', 'entity') === 'Account'
|
||||
) {
|
||||
$or['accountId'] = $accountIdList;
|
||||
}
|
||||
if ($this->getSeed()->hasRelation('accounts')) {
|
||||
if (
|
||||
$this->getSeed()->hasRelation('accounts') && $this->getSeed()->getRelationParam('accounts', 'entity') === 'Account'
|
||||
) {
|
||||
$this->addLeftJoin(['accounts', 'accountsAccess'], $result);
|
||||
$this->setDistinct(true, $result);
|
||||
$d['accountsAccess.id'] = $accountIdList;
|
||||
$or['accountsAccess.id'] = $accountIdList;
|
||||
}
|
||||
if ($this->getSeed()->hasAttribute('parentId') && $this->getSeed()->hasRelation('parent')) {
|
||||
$d[] = [
|
||||
$or[] = [
|
||||
'parentType' => 'Account',
|
||||
'parentId' => $accountIdList
|
||||
];
|
||||
if ($contactId) {
|
||||
$d[] = [
|
||||
$or[] = [
|
||||
'parentType' => 'Contact',
|
||||
'parentId' => $contactId
|
||||
];
|
||||
@@ -651,23 +659,27 @@ class Base
|
||||
}
|
||||
|
||||
if ($contactId) {
|
||||
if ($this->getSeed()->hasAttribute('contactId')) {
|
||||
$d['contactId'] = $contactId;
|
||||
if (
|
||||
$this->getSeed()->hasAttribute('contactId') && $this->getSeed()->getRelationParam('contact', 'entity') === 'Contact'
|
||||
) {
|
||||
$or['contactId'] = $contactId;
|
||||
}
|
||||
if ($this->getSeed()->hasRelation('contacts')) {
|
||||
if (
|
||||
$this->getSeed()->hasRelation('contacts') && $this->getSeed()->getRelationParam('contacts', 'entity') === 'Contact'
|
||||
) {
|
||||
$this->addLeftJoin(['contacts', 'contactsAccess'], $result);
|
||||
$this->setDistinct(true, $result);
|
||||
$d['contactsAccess.id'] = $contactId;
|
||||
$or['contactsAccess.id'] = $contactId;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->getSeed()->hasAttribute('createdById')) {
|
||||
$d['createdById'] = $this->getUser()->id;
|
||||
$or['createdById'] = $this->getUser()->id;
|
||||
}
|
||||
|
||||
if (!empty($d)) {
|
||||
if (!empty($or)) {
|
||||
$result['whereClause'][] = [
|
||||
'OR' => $d
|
||||
'OR' => $or
|
||||
];
|
||||
} else {
|
||||
$result['whereClause'][] = [
|
||||
|
||||
@@ -67,9 +67,9 @@ abstract class BaseTestCase extends \PHPUnit\Framework\TestCase
|
||||
|
||||
protected $initData = null;
|
||||
|
||||
protected function createApplication($clearCache = true)
|
||||
protected function createApplication($clearCache = true, $portalId = null)
|
||||
{
|
||||
return $this->espoTester->getApplication(true, $clearCache);
|
||||
return $this->espoTester->getApplication(true, $clearCache, $portalId);
|
||||
}
|
||||
|
||||
protected function auth($userName, $password = null, $portalId = null, $authenticationMethod = null)
|
||||
|
||||
@@ -117,15 +117,18 @@ class Tester
|
||||
$this->authenticationMethod = $authenticationMethod;
|
||||
}
|
||||
|
||||
public function getApplication($reload = false, $clearCache = true)
|
||||
public function getApplication($reload = false, $clearCache = true, $portalId = null)
|
||||
{
|
||||
$portalId = $portalId ?? $this->portalId ?? null;
|
||||
|
||||
if (!isset($this->application) || $reload) {
|
||||
|
||||
if ($clearCache) {
|
||||
$this->clearCache();
|
||||
}
|
||||
|
||||
$this->application = empty($this->portalId) ? new \Espo\Core\Application() : new \Espo\Core\Portal\Application($this->portalId);
|
||||
$this->application = !$portalId ? new \Espo\Core\Application() : new \Espo\Core\Portal\Application($portalId);
|
||||
|
||||
$auth = new \Espo\Core\Utils\Auth($this->application->getContainer());
|
||||
|
||||
if (isset($this->userName)) {
|
||||
|
||||
@@ -0,0 +1,248 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2019 Yuri Kuznetsov, Taras Machyshyn, Oleksiy 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 tests\integration\Espo\Portal;
|
||||
|
||||
class AclTest extends \tests\integration\Core\BaseTestCase
|
||||
{
|
||||
public function testAccessContact()
|
||||
{
|
||||
$app = $this->createApplication();
|
||||
|
||||
$em = $app->getContainer()->get('entityManager');
|
||||
|
||||
$contact = $em->createEntity('Contact', []);
|
||||
$portal = $em->createEntity('Portal', [
|
||||
'name' => 'Portal',
|
||||
]);
|
||||
|
||||
$this->createUser([
|
||||
'userName' => 'tester',
|
||||
'portalsIds' => [$portal->id],
|
||||
'contactId' => $contact->id,
|
||||
], [
|
||||
'data' => [
|
||||
'Case' => [
|
||||
'create' => 'no',
|
||||
'read' => 'contact',
|
||||
'edit' => 'no',
|
||||
'delete' => 'no',
|
||||
'stream' => 'contact',
|
||||
]
|
||||
],
|
||||
], true);
|
||||
|
||||
$this->auth('tester', null, $portal->id);
|
||||
|
||||
$app = $this->createApplication(true, $portal->id);
|
||||
|
||||
$em = $app->getContainer()->get('entityManager');
|
||||
|
||||
$acl = $app->getContainer()->get('acl');
|
||||
|
||||
$case1 = $em->createEntity('Case', [
|
||||
'contactId' => $contact->id,
|
||||
], ['createdById' => '1']);
|
||||
$case2 = $em->createEntity('Case', [
|
||||
'contactsIds' => [$contact->id],
|
||||
], ['createdById' => '1']);
|
||||
$case3 = $em->createEntity('Case', [
|
||||
], ['createdById' => '1']);
|
||||
|
||||
$this->assertFalse($acl->check('Case', 'create'));
|
||||
$this->assertFalse($acl->check('Case', 'edit'));
|
||||
$this->assertFalse($acl->check('Case', 'delete'));
|
||||
|
||||
$this->assertTrue($acl->check($case1, 'read'));
|
||||
$this->assertTrue($acl->check($case2, 'read'));
|
||||
$this->assertFalse($acl->check($case3, 'read'));
|
||||
|
||||
$service = $app->getContainer()->get('serviceFactory')->create('Case');
|
||||
$result = $service->find([]);
|
||||
|
||||
$idList = [];
|
||||
foreach ($result['collection'] as $e) {
|
||||
$idList[] = $e->id;
|
||||
}
|
||||
|
||||
$this->assertTrue(in_array($case1->id, $idList));
|
||||
$this->assertTrue(in_array($case2->id, $idList));
|
||||
$this->assertFalse(in_array($case3->id, $idList));
|
||||
}
|
||||
|
||||
public function testAccessAccount()
|
||||
{
|
||||
$app = $this->createApplication();
|
||||
|
||||
$em = $app->getContainer()->get('entityManager');
|
||||
|
||||
$contact = $em->createEntity('Contact', []);
|
||||
$account = $em->createEntity('Account', []);
|
||||
$portal = $em->createEntity('Portal', [
|
||||
'name' => 'Portal',
|
||||
]);
|
||||
|
||||
$this->createUser([
|
||||
'userName' => 'tester',
|
||||
'portalsIds' => [$portal->id],
|
||||
'contactId' => $contact->id,
|
||||
'accountsIds' => [$account->id],
|
||||
], [
|
||||
'data' => [
|
||||
'Case' => [
|
||||
'create' => 'no',
|
||||
'read' => 'account',
|
||||
'edit' => 'no',
|
||||
'delete' => 'no',
|
||||
'stream' => 'account',
|
||||
]
|
||||
],
|
||||
], true);
|
||||
|
||||
$this->auth('tester', null, $portal->id);
|
||||
|
||||
$app = $this->createApplication(true, $portal->id);
|
||||
|
||||
$em = $app->getContainer()->get('entityManager');
|
||||
|
||||
$acl = $app->getContainer()->get('acl');
|
||||
|
||||
$case1 = $em->createEntity('Case', [
|
||||
'contactId' => $contact->id,
|
||||
], ['createdById' => '1']);
|
||||
$case2 = $em->createEntity('Case', [
|
||||
'contactsIds' => [$contact->id],
|
||||
], ['createdById' => '1']);
|
||||
$case3 = $em->createEntity('Case', [
|
||||
], ['createdById' => '1']);
|
||||
$case4 = $em->createEntity('Case', [
|
||||
'accountId' => $account->id,
|
||||
], ['createdById' => '1']);
|
||||
|
||||
$this->assertFalse($acl->check('Case', 'create'));
|
||||
$this->assertFalse($acl->check('Case', 'edit'));
|
||||
$this->assertFalse($acl->check('Case', 'delete'));
|
||||
|
||||
$this->assertTrue($acl->check($case1, 'read'));
|
||||
$this->assertTrue($acl->check($case2, 'read'));
|
||||
$this->assertFalse($acl->check($case3, 'read'));
|
||||
$this->assertTrue($acl->check($case4, 'read'));
|
||||
|
||||
$service = $app->getContainer()->get('serviceFactory')->create('Case');
|
||||
$result = $service->find([]);
|
||||
|
||||
$idList = [];
|
||||
foreach ($result['collection'] as $e) {
|
||||
$idList[] = $e->id;
|
||||
}
|
||||
|
||||
$this->assertTrue(in_array($case1->id, $idList));
|
||||
$this->assertTrue(in_array($case2->id, $idList));
|
||||
$this->assertFalse(in_array($case3->id, $idList));
|
||||
$this->assertTrue(in_array($case4->id, $idList));
|
||||
}
|
||||
|
||||
public function testAccessOwn()
|
||||
{
|
||||
$app = $this->createApplication();
|
||||
|
||||
$em = $app->getContainer()->get('entityManager');
|
||||
|
||||
$contact = $em->createEntity('Contact', []);
|
||||
$account = $em->createEntity('Account', []);
|
||||
$portal = $em->createEntity('Portal', [
|
||||
'name' => 'Portal',
|
||||
]);
|
||||
|
||||
$this->createUser([
|
||||
'userName' => 'tester',
|
||||
'portalsIds' => [$portal->id],
|
||||
'contactId' => $contact->id,
|
||||
'accountsIds' => [$account->id],
|
||||
], [
|
||||
'data' => [
|
||||
'Case' => [
|
||||
'create' => 'no',
|
||||
'read' => 'own',
|
||||
'edit' => 'no',
|
||||
'delete' => 'no',
|
||||
'stream' => 'own',
|
||||
]
|
||||
],
|
||||
], true);
|
||||
|
||||
$this->auth('tester', null, $portal->id);
|
||||
|
||||
$app = $this->createApplication(true, $portal->id);
|
||||
|
||||
$em = $app->getContainer()->get('entityManager');
|
||||
|
||||
$acl = $app->getContainer()->get('acl');
|
||||
$user = $app->getContainer()->get('user');
|
||||
|
||||
$case1 = $em->createEntity('Case', [
|
||||
'contactId' => $contact->id,
|
||||
], ['createdById' => '1']);
|
||||
$case2 = $em->createEntity('Case', [
|
||||
'contactsIds' => [$contact->id],
|
||||
], ['createdById' => '1']);
|
||||
$case3 = $em->createEntity('Case', [
|
||||
], ['createdById' => '1']);
|
||||
$case4 = $em->createEntity('Case', [
|
||||
'accountId' => $account->id,
|
||||
], ['createdById' => '1']);
|
||||
$case5 = $em->createEntity('Case', [
|
||||
'accountId' => $account->id,
|
||||
], ['createdById' => $user->id]);
|
||||
|
||||
$this->assertFalse($acl->check('Case', 'create'));
|
||||
$this->assertFalse($acl->check('Case', 'edit'));
|
||||
$this->assertFalse($acl->check('Case', 'delete'));
|
||||
|
||||
$this->assertFalse($acl->check($case1, 'read'));
|
||||
$this->assertFalse($acl->check($case2, 'read'));
|
||||
$this->assertFalse($acl->check($case3, 'read'));
|
||||
$this->assertFalse($acl->check($case4, 'read'));
|
||||
$this->assertTrue($acl->check($case5, 'read'));
|
||||
|
||||
$service = $app->getContainer()->get('serviceFactory')->create('Case');
|
||||
$result = $service->find([]);
|
||||
|
||||
$idList = [];
|
||||
foreach ($result['collection'] as $e) {
|
||||
$idList[] = $e->id;
|
||||
}
|
||||
|
||||
$this->assertFalse(in_array($case1->id, $idList));
|
||||
$this->assertFalse(in_array($case2->id, $idList));
|
||||
$this->assertFalse(in_array($case3->id, $idList));
|
||||
$this->assertFalse(in_array($case4->id, $idList));
|
||||
$this->assertTrue(in_array($case5->id, $idList));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user