Initial commit
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2025 EspoCRM, Inc.
|
||||
* 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\Core\Portal\Acl\AccessChecker;
|
||||
|
||||
use Espo\Core\Acl\AccessChecker;
|
||||
use Espo\Core\Acl\Exceptions\NotImplemented;
|
||||
use Espo\Core\AclManager;
|
||||
use Espo\Core\Binding\Binder;
|
||||
use Espo\Core\Binding\BindingContainer;
|
||||
use Espo\Core\Binding\BindingData;
|
||||
use Espo\Core\InjectableFactory;
|
||||
use Espo\Core\Portal\Acl\DefaultAccessChecker;
|
||||
use Espo\Core\Portal\AclManager as PortalAclManager;
|
||||
use Espo\Core\Utils\Metadata;
|
||||
|
||||
class AccessCheckerFactory
|
||||
{
|
||||
/** @var class-string<AccessChecker> */
|
||||
private $defaultClassName = DefaultAccessChecker::class;
|
||||
|
||||
public function __construct(
|
||||
private Metadata $metadata,
|
||||
private InjectableFactory $injectableFactory
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Create an access checker.
|
||||
*
|
||||
* @throws NotImplemented
|
||||
*/
|
||||
public function create(string $scope, PortalAclManager $aclManager): AccessChecker
|
||||
{
|
||||
$className = $this->getClassName($scope);
|
||||
|
||||
$bindingContainer = $this->createBindingContainer($className, $aclManager, $scope);
|
||||
|
||||
return $this->injectableFactory->createWithBinding($className, $bindingContainer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return class-string<AccessChecker>
|
||||
*/
|
||||
private function getClassName(string $scope): string
|
||||
{
|
||||
/** @var ?class-string<AccessChecker> $className1 */
|
||||
$className1 = $this->metadata->get(['aclDefs', $scope, 'portalAccessCheckerClassName']);
|
||||
|
||||
if ($className1) {
|
||||
return $className1;
|
||||
}
|
||||
|
||||
if (!$this->metadata->get(['scopes', $scope])) {
|
||||
throw new NotImplemented();
|
||||
}
|
||||
|
||||
return $this->defaultClassName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param class-string<AccessChecker> $className
|
||||
*/
|
||||
private function createBindingContainer(
|
||||
string $className,
|
||||
PortalAclManager $aclManager,
|
||||
string $scope
|
||||
): BindingContainer {
|
||||
|
||||
$bindingData = new BindingData();
|
||||
$binder = new Binder($bindingData);
|
||||
|
||||
$binder
|
||||
->bindInstance(PortalAclManager::class, $aclManager)
|
||||
->bindInstance(AclManager::class, $aclManager);
|
||||
|
||||
$binder
|
||||
->for($className)
|
||||
->bindValue('$entityType', $scope);
|
||||
|
||||
return new BindingContainer($bindingData);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2025 EspoCRM, Inc.
|
||||
* 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\Core\Portal\Acl\AccessChecker;
|
||||
|
||||
use Espo\Core\Acl\ScopeData;
|
||||
use Espo\Core\Portal\Acl\Table;
|
||||
|
||||
/**
|
||||
* Checks scope access.
|
||||
*/
|
||||
class ScopeChecker
|
||||
{
|
||||
public function __construct()
|
||||
{}
|
||||
|
||||
public function check(ScopeData $data, ?string $action = null, ?ScopeCheckerData $checkerData = null): bool
|
||||
{
|
||||
if ($data->isFalse()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($data->isTrue()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($action === null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$level = $data->get($action);
|
||||
|
||||
if ($level === Table::LEVEL_ALL || $level === Table::LEVEL_YES) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($level === Table::LEVEL_NO) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$checkerData) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($level === Table::LEVEL_OWN || $level === Table::LEVEL_ACCOUNT || $level === Table::LEVEL_CONTACT) {
|
||||
if ($checkerData->isOwn()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($level === Table::LEVEL_ACCOUNT || $level === Table::LEVEL_CONTACT) {
|
||||
if ($checkerData->inContact()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($level === Table::LEVEL_ACCOUNT) {
|
||||
if ($checkerData->inAccount()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2025 EspoCRM, Inc.
|
||||
* 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\Core\Portal\Acl\AccessChecker;
|
||||
|
||||
use Closure;
|
||||
|
||||
/**
|
||||
* Scope checker data.
|
||||
*/
|
||||
class ScopeCheckerData
|
||||
{
|
||||
public function __construct(
|
||||
private Closure $isOwnChecker,
|
||||
private Closure $inAccountChecker,
|
||||
private Closure $inContactChecker
|
||||
) {}
|
||||
|
||||
public function isOwn(): bool
|
||||
{
|
||||
return ($this->isOwnChecker)();
|
||||
}
|
||||
|
||||
public function inAccount(): bool
|
||||
{
|
||||
return ($this->inAccountChecker)();
|
||||
}
|
||||
|
||||
public function inContact(): bool
|
||||
{
|
||||
return ($this->inContactChecker)();
|
||||
}
|
||||
|
||||
public static function createBuilder(): ScopeCheckerDataBuilder
|
||||
{
|
||||
return new ScopeCheckerDataBuilder();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2025 EspoCRM, Inc.
|
||||
* 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\Core\Portal\Acl\AccessChecker;
|
||||
|
||||
use Closure;
|
||||
|
||||
/**
|
||||
* Builds scope checker data.
|
||||
*/
|
||||
class ScopeCheckerDataBuilder
|
||||
{
|
||||
private Closure $isOwnChecker;
|
||||
private Closure $inAccountChecker;
|
||||
private Closure $inContactChecker;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->isOwnChecker = function (): bool {
|
||||
return false;
|
||||
};
|
||||
|
||||
$this->inAccountChecker = function (): bool {
|
||||
return false;
|
||||
};
|
||||
|
||||
$this->inContactChecker = function (): bool {
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
public function setIsOwn(bool $value): self
|
||||
{
|
||||
if ($value) {
|
||||
$this->isOwnChecker = function (): bool {
|
||||
return true;
|
||||
};
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->isOwnChecker = function (): bool {
|
||||
return false;
|
||||
};
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setInAccount(bool $value): self
|
||||
{
|
||||
if ($value) {
|
||||
$this->inAccountChecker = function (): bool {
|
||||
return true;
|
||||
};
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->inAccountChecker = function (): bool {
|
||||
return false;
|
||||
};
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setInContact(bool $value): self
|
||||
{
|
||||
if ($value) {
|
||||
$this->inContactChecker = function (): bool {
|
||||
return true;
|
||||
};
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->inContactChecker = function (): bool {
|
||||
return false;
|
||||
};
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Closure(): bool $checker
|
||||
*/
|
||||
public function setIsOwnChecker(Closure $checker): self
|
||||
{
|
||||
$this->isOwnChecker = $checker;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Closure(): bool $checker
|
||||
*/
|
||||
public function setInAccountChecker(Closure $checker): self
|
||||
{
|
||||
$this->inAccountChecker = $checker;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Closure(): bool $checker
|
||||
*/
|
||||
public function setInContactChecker(Closure $checker): self
|
||||
{
|
||||
$this->inContactChecker = $checker;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function build(): ScopeCheckerData
|
||||
{
|
||||
return new ScopeCheckerData($this->isOwnChecker, $this->inAccountChecker, $this->inContactChecker);
|
||||
}
|
||||
}
|
||||
157
application/Espo/Core/Portal/Acl/DefaultAccessChecker.php
Normal file
157
application/Espo/Core/Portal/Acl/DefaultAccessChecker.php
Normal file
@@ -0,0 +1,157 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2025 EspoCRM, Inc.
|
||||
* 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\Core\Portal\Acl;
|
||||
|
||||
use Espo\Entities\User;
|
||||
use Espo\ORM\Entity;
|
||||
|
||||
use Espo\Core\Acl\AccessEntityCreateChecker;
|
||||
use Espo\Core\Acl\AccessEntityDeleteChecker;
|
||||
use Espo\Core\Acl\AccessEntityEditChecker;
|
||||
use Espo\Core\Acl\AccessEntityReadChecker;
|
||||
use Espo\Core\Acl\AccessEntityStreamChecker;
|
||||
use Espo\Core\Acl\ScopeData;
|
||||
use Espo\Core\Portal\Acl\AccessChecker\ScopeChecker;
|
||||
use Espo\Core\Portal\Acl\AccessChecker\ScopeCheckerData;
|
||||
use Espo\Core\Portal\AclManager as PortalAclManager;
|
||||
|
||||
/**
|
||||
* A default implementation for access checking for portal.
|
||||
*
|
||||
* @implements AccessEntityCreateChecker<Entity>
|
||||
* @implements AccessEntityReadChecker<Entity>
|
||||
* @implements AccessEntityEditChecker<Entity>
|
||||
* @implements AccessEntityDeleteChecker<Entity>
|
||||
* @implements AccessEntityStreamChecker<Entity>
|
||||
*/
|
||||
class DefaultAccessChecker implements
|
||||
|
||||
AccessEntityCreateChecker,
|
||||
AccessEntityReadChecker,
|
||||
AccessEntityEditChecker,
|
||||
AccessEntityDeleteChecker,
|
||||
AccessEntityStreamChecker
|
||||
{
|
||||
public function __construct(
|
||||
private PortalAclManager $aclManager,
|
||||
private ScopeChecker $scopeChecker
|
||||
) {}
|
||||
|
||||
private function checkEntity(User $user, Entity $entity, ScopeData $data, string $action): bool
|
||||
{
|
||||
$checkerData = ScopeCheckerData
|
||||
::createBuilder()
|
||||
->setIsOwnChecker(
|
||||
function () use ($user, $entity): bool {
|
||||
return $this->aclManager->checkOwnershipOwn($user, $entity);
|
||||
}
|
||||
)
|
||||
->setInAccountChecker(
|
||||
function () use ($user, $entity): bool {
|
||||
return $this->aclManager->checkOwnershipAccount($user, $entity);
|
||||
}
|
||||
)
|
||||
->setInContactChecker(
|
||||
function () use ($user, $entity): bool {
|
||||
return $this->aclManager->checkOwnershipContact($user, $entity);
|
||||
}
|
||||
)
|
||||
->build();
|
||||
|
||||
return $this->scopeChecker->check($data, $action, $checkerData);
|
||||
}
|
||||
|
||||
private function checkScope(User $user, ScopeData $data, ?string $action = null): bool
|
||||
{
|
||||
$checkerData = ScopeCheckerData
|
||||
::createBuilder()
|
||||
->setIsOwn(true)
|
||||
->setInAccount(true)
|
||||
->setInContact(true)
|
||||
->build();
|
||||
|
||||
return $this->scopeChecker->check($data, $action, $checkerData);
|
||||
}
|
||||
|
||||
public function check(User $user, ScopeData $data): bool
|
||||
{
|
||||
return $this->checkScope($user, $data);
|
||||
}
|
||||
|
||||
public function checkCreate(User $user, ScopeData $data): bool
|
||||
{
|
||||
return $this->checkScope($user, $data, Table::ACTION_CREATE);
|
||||
}
|
||||
|
||||
public function checkRead(User $user, ScopeData $data): bool
|
||||
{
|
||||
return $this->checkScope($user, $data, Table::ACTION_READ);
|
||||
}
|
||||
|
||||
public function checkEdit(User $user, ScopeData $data): bool
|
||||
{
|
||||
return $this->checkScope($user, $data, Table::ACTION_EDIT);
|
||||
}
|
||||
|
||||
public function checkDelete(User $user, ScopeData $data): bool
|
||||
{
|
||||
return $this->checkScope($user, $data, Table::ACTION_DELETE);
|
||||
}
|
||||
|
||||
public function checkStream(User $user, ScopeData $data): bool
|
||||
{
|
||||
return $this->checkScope($user, $data, Table::ACTION_STREAM);
|
||||
}
|
||||
|
||||
public function checkEntityCreate(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
return $this->checkEntity($user, $entity, $data, Table::ACTION_CREATE);
|
||||
}
|
||||
|
||||
public function checkEntityRead(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
return $this->checkEntity($user, $entity, $data, Table::ACTION_READ);
|
||||
}
|
||||
|
||||
public function checkEntityEdit(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
return $this->checkEntity($user, $entity, $data, Table::ACTION_EDIT);
|
||||
}
|
||||
|
||||
public function checkEntityStream(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
return $this->checkEntity($user, $entity, $data, Table::ACTION_STREAM);
|
||||
}
|
||||
|
||||
public function checkEntityDelete(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
return $this->checkEntity($user, $entity, $data, Table::ACTION_DELETE);
|
||||
}
|
||||
}
|
||||
189
application/Espo/Core/Portal/Acl/DefaultOwnershipChecker.php
Normal file
189
application/Espo/Core/Portal/Acl/DefaultOwnershipChecker.php
Normal file
@@ -0,0 +1,189 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2025 EspoCRM, Inc.
|
||||
* 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\Core\Portal\Acl;
|
||||
|
||||
use Espo\Core\Field\Link;
|
||||
use Espo\Core\Field\LinkParent;
|
||||
use Espo\Core\Name\Field;
|
||||
use Espo\Core\ORM\Type\FieldType;
|
||||
use Espo\Core\Portal\Acl\OwnershipChecker\MetadataProvider;
|
||||
use Espo\Modules\Crm\Entities\Account;
|
||||
use Espo\Modules\Crm\Entities\Contact;
|
||||
use Espo\ORM\Entity;
|
||||
use Espo\ORM\EntityManager;
|
||||
use Espo\Entities\User;
|
||||
use Espo\Core\Acl\OwnershipOwnChecker;
|
||||
use Espo\ORM\Type\RelationType;
|
||||
|
||||
/**
|
||||
* A default implementation for ownership checking for portal.
|
||||
*
|
||||
* @implements OwnershipOwnChecker<\Espo\Core\ORM\Entity>
|
||||
* @implements OwnershipAccountChecker<\Espo\Core\ORM\Entity>
|
||||
* @implements OwnershipContactChecker<\Espo\Core\ORM\Entity>
|
||||
*/
|
||||
class DefaultOwnershipChecker implements
|
||||
OwnershipOwnChecker,
|
||||
OwnershipAccountChecker,
|
||||
OwnershipContactChecker
|
||||
{
|
||||
private const ATTR_CREATED_BY_ID = Field::CREATED_BY . 'Id';
|
||||
|
||||
public function __construct(
|
||||
private EntityManager $entityManager,
|
||||
private MetadataProvider $metadataProvider,
|
||||
) {}
|
||||
|
||||
public function checkOwn(User $user, Entity $entity): bool
|
||||
{
|
||||
if ($entity->hasAttribute(self::ATTR_CREATED_BY_ID)) {
|
||||
if (
|
||||
$entity->has(self::ATTR_CREATED_BY_ID) &&
|
||||
$user->getId() === $entity->get(self::ATTR_CREATED_BY_ID)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function checkAccount(User $user, Entity $entity): bool
|
||||
{
|
||||
$linkDefs = $this->metadataProvider->getAccountLink($entity->getEntityType());
|
||||
|
||||
if (!$linkDefs) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$link = $linkDefs->getName();
|
||||
|
||||
$accountIds = $user->getAccounts()->getIdList();
|
||||
|
||||
if ($accountIds === []) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$fieldDefs = $this->entityManager
|
||||
->getDefs()
|
||||
->getEntity($entity->getEntityType())
|
||||
->tryGetField($link);
|
||||
|
||||
if (
|
||||
$linkDefs->getType() === RelationType::BELONGS_TO &&
|
||||
$fieldDefs?->getType() === FieldType::LINK
|
||||
) {
|
||||
$setAccountLink = $entity->getValueObject($link);
|
||||
|
||||
if (!$setAccountLink instanceof Link) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return in_array($setAccountLink->getId(), $accountIds);
|
||||
}
|
||||
|
||||
if (
|
||||
$linkDefs->getType() === RelationType::BELONGS_TO_PARENT &&
|
||||
$fieldDefs?->getType() === FieldType::LINK_PARENT
|
||||
) {
|
||||
$setLink = $entity->getValueObject($link);
|
||||
|
||||
if (!$setLink instanceof LinkParent || $setLink->getEntityType() !== Account::ENTITY_TYPE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return in_array($setLink->getId(), $accountIds);
|
||||
}
|
||||
|
||||
foreach ($accountIds as $accountId) {
|
||||
$isRelated = $this->entityManager
|
||||
->getRelation($entity, $link)
|
||||
->isRelatedById($accountId);
|
||||
|
||||
if ($isRelated) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function checkContact(User $user, Entity $entity): bool
|
||||
{
|
||||
$linkDefs = $this->metadataProvider->getContactLink($entity->getEntityType());
|
||||
|
||||
if (!$linkDefs) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$link = $linkDefs->getName();
|
||||
|
||||
$contactId = $user->getContactId();
|
||||
|
||||
if (!$contactId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$fieldDefs = $this->entityManager
|
||||
->getDefs()
|
||||
->getEntity($entity->getEntityType())
|
||||
->tryGetField($link);
|
||||
|
||||
if (
|
||||
$linkDefs->getType() === RelationType::BELONGS_TO &&
|
||||
$fieldDefs?->getType() === FieldType::LINK
|
||||
) {
|
||||
$setContactLink = $entity->getValueObject($link);
|
||||
|
||||
if (!$setContactLink instanceof Link) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $setContactLink->getId() === $contactId;
|
||||
}
|
||||
|
||||
if (
|
||||
$linkDefs->getType() === RelationType::BELONGS_TO_PARENT &&
|
||||
$fieldDefs?->getType() === FieldType::LINK_PARENT
|
||||
) {
|
||||
$setLink = $entity->getValueObject($link);
|
||||
|
||||
if (!$setLink instanceof LinkParent || $setLink->getEntityType() !== Contact::ENTITY_TYPE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $setLink->getId() === $contactId;
|
||||
}
|
||||
|
||||
return$this->entityManager
|
||||
->getRelation($entity, $link)
|
||||
->isRelatedById($contactId);
|
||||
}
|
||||
}
|
||||
45
application/Espo/Core/Portal/Acl/Map/CacheKeyProvider.php
Normal file
45
application/Espo/Core/Portal/Acl/Map/CacheKeyProvider.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2025 EspoCRM, Inc.
|
||||
* 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\Core\Portal\Acl\Map;
|
||||
|
||||
use Espo\Entities\Portal;
|
||||
use Espo\Entities\User;
|
||||
use Espo\Core\Acl\Map\CacheKeyProvider as CacheKeyProviderInterface;
|
||||
|
||||
class CacheKeyProvider implements CacheKeyProviderInterface
|
||||
{
|
||||
public function __construct(private User $user, private Portal $portal)
|
||||
{}
|
||||
|
||||
public function get(): string
|
||||
{
|
||||
return 'aclPortalMap/' . $this->portal->getId() . '/' . $this->user->getId();
|
||||
}
|
||||
}
|
||||
74
application/Espo/Core/Portal/Acl/Map/MapFactory.php
Normal file
74
application/Espo/Core/Portal/Acl/Map/MapFactory.php
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2025 EspoCRM, Inc.
|
||||
* 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\Core\Portal\Acl\Map;
|
||||
|
||||
use Espo\Entities\Portal;
|
||||
use Espo\Entities\User;
|
||||
|
||||
use Espo\Core\Acl\Map\CacheKeyProvider;
|
||||
use Espo\Core\Acl\Map\Map;
|
||||
use Espo\Core\Acl\Map\MetadataProvider;
|
||||
use Espo\Core\Acl\Table;
|
||||
use Espo\Core\Binding\Binder;
|
||||
use Espo\Core\Binding\BindingContainer;
|
||||
use Espo\Core\Binding\BindingData;
|
||||
use Espo\Core\InjectableFactory;
|
||||
use Espo\Core\Portal\Acl\Map\CacheKeyProvider as PortalCacheKeyProvider;
|
||||
use Espo\Core\Portal\Acl\Map\MetadataProvider as PortalMetadataProvider;
|
||||
use Espo\Core\Portal\Acl\Table as PortalTable;
|
||||
|
||||
class MapFactory
|
||||
{
|
||||
public function __construct(private InjectableFactory $injectableFactory)
|
||||
{}
|
||||
|
||||
public function create(User $user, PortalTable $table, Portal $portal): Map
|
||||
{
|
||||
$bindingContainer = $this->createBindingContainer($user, $table, $portal);
|
||||
|
||||
return $this->injectableFactory->createWithBinding(Map::class, $bindingContainer);
|
||||
}
|
||||
|
||||
private function createBindingContainer(User $user, PortalTable $table, Portal $portal): BindingContainer
|
||||
{
|
||||
$bindingData = new BindingData();
|
||||
|
||||
$binder = new Binder($bindingData);
|
||||
|
||||
$binder
|
||||
->bindInstance(User::class, $user)
|
||||
->bindInstance(Table::class, $table)
|
||||
->bindInstance(Portal::class, $portal)
|
||||
->bindImplementation(MetadataProvider::class, PortalMetadataProvider::class)
|
||||
->bindImplementation(CacheKeyProvider::class, PortalCacheKeyProvider::class);
|
||||
|
||||
return new BindingContainer($bindingData);
|
||||
}
|
||||
}
|
||||
37
application/Espo/Core/Portal/Acl/Map/MetadataProvider.php
Normal file
37
application/Espo/Core/Portal/Acl/Map/MetadataProvider.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2025 EspoCRM, Inc.
|
||||
* 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\Core\Portal\Acl\Map;
|
||||
|
||||
use Espo\Core\Acl\Map\MetadataProvider as BaseMetadataProvider;
|
||||
|
||||
class MetadataProvider extends BaseMetadataProvider
|
||||
{
|
||||
protected string $type = 'aclPortal';
|
||||
}
|
||||
48
application/Espo/Core/Portal/Acl/OwnershipAccountChecker.php
Normal file
48
application/Espo/Core/Portal/Acl/OwnershipAccountChecker.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2025 EspoCRM, Inc.
|
||||
* 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\Core\Portal\Acl;
|
||||
|
||||
use Espo\ORM\Entity;
|
||||
use Espo\Entities\User;
|
||||
|
||||
use Espo\Core\Acl\OwnershipChecker;
|
||||
|
||||
/**
|
||||
* @template TEntity of Entity
|
||||
*/
|
||||
interface OwnershipAccountChecker extends OwnershipChecker
|
||||
{
|
||||
/**
|
||||
* Check whether an entity belongs to a portal user account.
|
||||
*
|
||||
* @param TEntity $entity
|
||||
*/
|
||||
public function checkAccount(User $user, Entity $entity): bool;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2025 EspoCRM, Inc.
|
||||
* 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\Core\Portal\Acl\OwnershipChecker;
|
||||
|
||||
use Espo\Core\Utils\Metadata;
|
||||
use Espo\ORM\Defs;
|
||||
use Espo\ORM\Defs\RelationDefs;
|
||||
|
||||
class MetadataProvider
|
||||
{
|
||||
public function __construct(
|
||||
private Metadata $metadata,
|
||||
private Defs $defs,
|
||||
) {}
|
||||
|
||||
public function getAccountLink(string $entityType): ?RelationDefs
|
||||
{
|
||||
$link = $this->metadata->get("aclDefs.$entityType.accountLink");
|
||||
|
||||
if (!$link) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->defs->getEntity($entityType)->tryGetRelation($link);
|
||||
}
|
||||
|
||||
public function getContactLink(string $entityType): ?RelationDefs
|
||||
{
|
||||
$link = $this->metadata->get("aclDefs.$entityType.contactLink");
|
||||
|
||||
if (!$link) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->defs->getEntity($entityType)->tryGetRelation($link);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2025 EspoCRM, Inc.
|
||||
* 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\Core\Portal\Acl\OwnershipChecker;
|
||||
|
||||
use Espo\Core\Acl\Exceptions\NotImplemented;
|
||||
use Espo\Core\Acl\OwnershipChecker;
|
||||
use Espo\Core\AclManager;
|
||||
use Espo\Core\Binding\Binder;
|
||||
use Espo\Core\Binding\BindingContainer;
|
||||
use Espo\Core\Binding\BindingData;
|
||||
use Espo\Core\InjectableFactory;
|
||||
use Espo\Core\Portal\Acl\DefaultOwnershipChecker;
|
||||
use Espo\Core\Portal\AclManager as PortalAclManager;
|
||||
use Espo\Core\Utils\Metadata;
|
||||
|
||||
class OwnershipCheckerFactory
|
||||
{
|
||||
/** @var class-string<OwnershipChecker> */
|
||||
private $defaultClassName = DefaultOwnershipChecker::class;
|
||||
|
||||
public function __construct(
|
||||
private Metadata $metadata,
|
||||
private InjectableFactory $injectableFactory
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Create an ownership checker.
|
||||
*
|
||||
* @throws NotImplemented
|
||||
*/
|
||||
public function create(string $scope, PortalAclManager $aclManager): OwnershipChecker
|
||||
{
|
||||
$className = $this->getClassName($scope);
|
||||
|
||||
$bindingContainer = $this->createBindingContainer($className, $aclManager, $scope);
|
||||
|
||||
return $this->injectableFactory->createWithBinding($className, $bindingContainer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return class-string<OwnershipChecker>
|
||||
*/
|
||||
private function getClassName(string $scope): string
|
||||
{
|
||||
$className = $this->metadata->get(['aclDefs', $scope, 'portalOwnershipCheckerClassName']);
|
||||
|
||||
if ($className) {
|
||||
/** @var class-string<OwnershipChecker> */
|
||||
return $className;
|
||||
}
|
||||
|
||||
if (!$this->metadata->get(['scopes', $scope])) {
|
||||
throw new NotImplemented();
|
||||
}
|
||||
|
||||
return $this->defaultClassName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param class-string<OwnershipChecker> $className
|
||||
*/
|
||||
private function createBindingContainer(
|
||||
string $className,
|
||||
PortalAclManager $aclManager,
|
||||
string $scope
|
||||
): BindingContainer {
|
||||
|
||||
$bindingData = new BindingData();
|
||||
|
||||
$binder = new Binder($bindingData);
|
||||
|
||||
$binder
|
||||
->bindInstance(PortalAclManager::class, $aclManager)
|
||||
->bindInstance(AclManager::class, $aclManager);
|
||||
|
||||
$binder
|
||||
->for($className)
|
||||
->bindValue('$entityType', $scope);
|
||||
|
||||
return new BindingContainer($bindingData);
|
||||
}
|
||||
}
|
||||
48
application/Espo/Core/Portal/Acl/OwnershipContactChecker.php
Normal file
48
application/Espo/Core/Portal/Acl/OwnershipContactChecker.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2025 EspoCRM, Inc.
|
||||
* 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\Core\Portal\Acl;
|
||||
|
||||
use Espo\ORM\Entity;
|
||||
use Espo\Entities\User;
|
||||
|
||||
use Espo\Core\Acl\OwnershipChecker;
|
||||
|
||||
/**
|
||||
* @template TEntity of Entity
|
||||
*/
|
||||
interface OwnershipContactChecker extends OwnershipChecker
|
||||
{
|
||||
/**
|
||||
* Check whether an entity belongs to a portal user contact.
|
||||
*
|
||||
* @param TEntity $entity
|
||||
*/
|
||||
public function checkContact(User $user, Entity $entity): bool;
|
||||
}
|
||||
102
application/Espo/Core/Portal/Acl/Table.php
Normal file
102
application/Espo/Core/Portal/Acl/Table.php
Normal file
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2025 EspoCRM, Inc.
|
||||
* 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\Core\Portal\Acl;
|
||||
|
||||
use Espo\Core\Acl\Table\DefaultTable as BaseTable;
|
||||
|
||||
use stdClass;
|
||||
|
||||
class Table extends BaseTable
|
||||
{
|
||||
public const LEVEL_ACCOUNT = 'account';
|
||||
public const LEVEL_CONTACT = 'contact';
|
||||
|
||||
protected string $type = 'aclPortal';
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
protected $levelList = [
|
||||
self::LEVEL_YES,
|
||||
self::LEVEL_ALL,
|
||||
self::LEVEL_ACCOUNT,
|
||||
self::LEVEL_CONTACT,
|
||||
self::LEVEL_OWN,
|
||||
self::LEVEL_NO,
|
||||
];
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
protected function getScopeWithAclList(): array
|
||||
{
|
||||
$scopeList = [];
|
||||
|
||||
$scopes = $this->metadata->get('scopes');
|
||||
|
||||
foreach ($scopes as $scope => $item) {
|
||||
if (empty($item['acl'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (empty($item['aclPortal'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$scopeList[] = $scope;
|
||||
}
|
||||
|
||||
return $scopeList;
|
||||
}
|
||||
|
||||
protected function applyDefault(stdClass &$table, stdClass &$fieldTable): void
|
||||
{
|
||||
parent::applyDefault($table, $fieldTable);
|
||||
|
||||
foreach ($this->getScopeList() as $scope) {
|
||||
if (!isset($table->$scope)) {
|
||||
$table->$scope = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function applyDisabled(stdClass $table, stdClass $fieldTable): void
|
||||
{
|
||||
foreach ($this->getScopeList() as $scope) {
|
||||
$item = $this->metadata->get(['scopes', $scope]) ?? [];
|
||||
|
||||
if (!empty($item['disabled']) || !empty($item['portalDisabled'])) {
|
||||
$table->$scope = false;
|
||||
|
||||
unset($fieldTable->$scope);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
46
application/Espo/Core/Portal/Acl/Table/CacheKeyProvider.php
Normal file
46
application/Espo/Core/Portal/Acl/Table/CacheKeyProvider.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2025 EspoCRM, Inc.
|
||||
* 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\Core\Portal\Acl\Table;
|
||||
|
||||
use Espo\Entities\Portal;
|
||||
use Espo\Entities\User;
|
||||
|
||||
use Espo\Core\Acl\Table\CacheKeyProvider as CacheKeyProviderInterface;
|
||||
|
||||
class CacheKeyProvider implements CacheKeyProviderInterface
|
||||
{
|
||||
public function __construct(private User $user, private Portal $portal)
|
||||
{}
|
||||
|
||||
public function get(): string
|
||||
{
|
||||
return 'aclPortal/' . $this->portal->getId() . '/' . $this->user->getId();
|
||||
}
|
||||
}
|
||||
83
application/Espo/Core/Portal/Acl/Table/RoleListProvider.php
Normal file
83
application/Espo/Core/Portal/Acl/Table/RoleListProvider.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2025 EspoCRM, Inc.
|
||||
* 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\Core\Portal\Acl\Table;
|
||||
|
||||
use Espo\ORM\EntityManager;
|
||||
|
||||
use Espo\Entities\Portal;
|
||||
use Espo\Entities\PortalRole;
|
||||
use Espo\Entities\User;
|
||||
use Espo\Core\Acl\Table\Role;
|
||||
use Espo\Core\Acl\Table\RoleEntityWrapper;
|
||||
use Espo\Core\Acl\Table\RoleListProvider as RoleListProviderInterface;
|
||||
|
||||
class RoleListProvider implements RoleListProviderInterface
|
||||
{
|
||||
public function __construct(
|
||||
private User $user,
|
||||
private Portal $portal,
|
||||
private EntityManager $entityManager
|
||||
) {}
|
||||
|
||||
/**
|
||||
* @return Role[]
|
||||
*/
|
||||
public function get(): array
|
||||
{
|
||||
$roleList = [];
|
||||
|
||||
/** @var iterable<PortalRole> $userRoleList */
|
||||
$userRoleList = $this->entityManager
|
||||
->getRDBRepository(User::ENTITY_TYPE)
|
||||
->getRelation($this->user, 'portalRoles')
|
||||
->find();
|
||||
|
||||
foreach ($userRoleList as $role) {
|
||||
$roleList[] = $role;
|
||||
}
|
||||
|
||||
/** @var iterable<PortalRole> $portalRoleList */
|
||||
$portalRoleList = $this->entityManager
|
||||
->getRDBRepository(Portal::ENTITY_TYPE)
|
||||
->getRelation($this->portal, 'portalRoles')
|
||||
->find();
|
||||
|
||||
foreach ($portalRoleList as $role) {
|
||||
$roleList[] = $role;
|
||||
}
|
||||
|
||||
return array_map(
|
||||
function (PortalRole $role): RoleEntityWrapper {
|
||||
return new RoleEntityWrapper($role);
|
||||
},
|
||||
$roleList
|
||||
);
|
||||
}
|
||||
}
|
||||
74
application/Espo/Core/Portal/Acl/Table/TableFactory.php
Normal file
74
application/Espo/Core/Portal/Acl/Table/TableFactory.php
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2025 EspoCRM, Inc.
|
||||
* 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\Core\Portal\Acl\Table;
|
||||
|
||||
use Espo\Entities\Portal;
|
||||
use Espo\Entities\User;
|
||||
|
||||
use Espo\Core\Acl\Table\CacheKeyProvider;
|
||||
use Espo\Core\Acl\Table\RoleListProvider;
|
||||
use Espo\Core\Binding\Binder;
|
||||
use Espo\Core\Binding\BindingContainer;
|
||||
use Espo\Core\Binding\BindingData;
|
||||
use Espo\Core\InjectableFactory;
|
||||
use Espo\Core\Portal\Acl\Table;
|
||||
use Espo\Core\Portal\Acl\Table\CacheKeyProvider as PortalCacheKeyProvider;
|
||||
use Espo\Core\Portal\Acl\Table\RoleListProvider as PortalRoleListProvider;
|
||||
|
||||
class TableFactory
|
||||
{
|
||||
public function __construct(private InjectableFactory $injectableFactory)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Create a table.
|
||||
*/
|
||||
public function create(User $user, Portal $portal): Table
|
||||
{
|
||||
$bindingContainer = $this->createBindingContainer($user, $portal);
|
||||
|
||||
return $this->injectableFactory->createWithBinding(Table::class, $bindingContainer);
|
||||
}
|
||||
|
||||
private function createBindingContainer(User $user, Portal $portal): BindingContainer
|
||||
{
|
||||
$bindingData = new BindingData();
|
||||
|
||||
$binder = new Binder($bindingData);
|
||||
|
||||
$binder
|
||||
->bindInstance(User::class, $user)
|
||||
->bindInstance(Portal::class, $portal)
|
||||
->bindImplementation(RoleListProvider::class, PortalRoleListProvider::class)
|
||||
->bindImplementation(CacheKeyProvider::class, PortalCacheKeyProvider::class);
|
||||
|
||||
return new BindingContainer($bindingData);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2025 EspoCRM, Inc.
|
||||
* 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\Core\Portal\Acl\Traits;
|
||||
|
||||
use Espo\ORM\Entity;
|
||||
use Espo\Entities\User;
|
||||
use Espo\Core\Acl\ScopeData;
|
||||
use Espo\Core\Portal\Acl\DefaultAccessChecker;
|
||||
|
||||
trait DefaultAccessCheckerDependency
|
||||
{
|
||||
private DefaultAccessChecker $defaultAccessChecker;
|
||||
|
||||
public function check(User $user, ScopeData $data): bool
|
||||
{
|
||||
return $this->defaultAccessChecker->check($user, $data);
|
||||
}
|
||||
|
||||
public function checkCreate(User $user, ScopeData $data): bool
|
||||
{
|
||||
return $this->defaultAccessChecker->checkCreate($user, $data);
|
||||
}
|
||||
|
||||
public function checkRead(User $user, ScopeData $data): bool
|
||||
{
|
||||
return $this->defaultAccessChecker->checkRead($user, $data);
|
||||
}
|
||||
|
||||
public function checkEdit(User $user, ScopeData $data): bool
|
||||
{
|
||||
return $this->defaultAccessChecker->checkEdit($user, $data);
|
||||
}
|
||||
|
||||
public function checkDelete(User $user, ScopeData $data): bool
|
||||
{
|
||||
return $this->defaultAccessChecker->checkDelete($user, $data);
|
||||
}
|
||||
|
||||
public function checkStream(User $user, ScopeData $data): bool
|
||||
{
|
||||
return $this->defaultAccessChecker->checkStream($user, $data);
|
||||
}
|
||||
|
||||
public function checkEntityCreate(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
return $this->defaultAccessChecker->checkEntityCreate($user, $entity, $data);
|
||||
}
|
||||
|
||||
public function checkEntityRead(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
return $this->defaultAccessChecker->checkEntityRead($user, $entity, $data);
|
||||
}
|
||||
|
||||
public function checkEntityEdit(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
return $this->defaultAccessChecker->checkEntityEdit($user, $entity, $data);
|
||||
}
|
||||
|
||||
public function checkEntityDelete(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
return $this->defaultAccessChecker->checkEntityDelete($user, $entity, $data);
|
||||
}
|
||||
|
||||
public function checkEntityStream(User $user, Entity $entity, ScopeData $data): bool
|
||||
{
|
||||
return $this->defaultAccessChecker->checkEntityStream($user, $entity, $data);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user