ACL with GrandChildren Entities of Account

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • czcpf
    Senior Member
    • Aug 2022
    • 160

    ACL with GrandChildren Entities of Account

    Hello friends,

    In Espo we can set ACL for entities with default choices such as 'All', 'account', 'contact', 'own','no'.

    Suppose we have some custom entity `MyCustomEntity`

    `MyCustomEntity` has Many-To-One `Account` relation

    We can set ACL for 'MyCustomEntity` to `Account` for read,write, etc in GUI and if user visits http://{espoUrl}#MyCustomEntity they can only see/access MyCustomEntities related to their `Account` as expected.

    Suppose `MyCustomEntity` has One-To-Many `MyCustomEntityChild` relation
    We can set ACL for `MyCustomEntityChild` to 'account' for read, write, etc. and if user visits http://{espoUrl}#MyCustomEntityChild they see nothing unless `MyCustomEntityChild` has relation defined to `Account` as well.

    So my question is, what is the best practice here? It seems like having to have a duplicate relationship to `Account` and have extra database field `accountId` along with saveFormula or saveHook to set accountId/accountName from parent when creating `MyCustomEntityChild` is redundant. Or is it better to define custom AccessChecker classes for such grandchild relations in order to avoid having to duplicate Account relationships?

    In short, `MyCustomEntityChild` is related to `MyCustomEntity` which is related to `Account` so what is the recommended way to ensure account user can only see/access MyCustomEntityChild related to their account.

    Options:
    1. Create `MyCustomEntityChild` Many-To-One `Account` relation and implement saveFormula or saveHook to set accountId, accountName based on `MyCustomEntity` accountId and accountName.
    2. Create custom AccessChecker class for `MyCustomEntityChild` and do something like below.
    3. Other suggestions?


    PHP Code:
    <?php
    
    
    namespace Espo\Custom\Classes\Acl\MyCustomEntityChild;
    
    use Espo\Classes\Acl\Attachment\AccessChecker as AttachmentAccessChecker;
    use Espo\Core\Acl\Traits\DefaultAccessCheckerDependenc y;
    use Espo\Core\Acl\AccessEntityCREDChecker;
    use Espo\Core\Acl\DefaultAccessChecker;
    use Espo\ORM\Entity;
    use Espo\Entities\User;
    use Espo\Core\Acl\ScopeData;
    use Espo\ORM\EntityManager;
    
    class TemplateAccessChecker implements AccessEntityCREDChecker
    {
    use DefaultAccessCheckerDependency;
    
    private AttachmentAccessChecker $parentAccessChecker;
    private EntityManager $entityManager;
    
    public function __construct(
    AttachmentAccessChecker $parentAccessChecker,
    DefaultAccessChecker $defaultAccessChecker,
    EntityManager $entityManager,
    // here add needed additional dependencies
    )
    {
    $this->parentAccessChecker = $parentAccessChecker;
    $this->defaultAccessChecker = $defaultAccessChecker;
    $this->entityManager = $entityManager;
    }
    
    public function checkEntityRead(User $user, Entity $entity, ScopeData $data): bool
    {
    // here add your custom check that returns true if some conditions met
    
    $userAccountIds = $user?->getAccounts()->getIdList();
    
    $myCustomEntityAccountId = $this->entityManager
    ->getRDBRepository($entity->getEntityType())
    ->getRelation($entity, 'MyCustomEntity')
    ->findOne()?->get('accountId');
    
    if( in_array($myCustomEntityAccountId, $userAccountIds) ) {return true;}return $this->parentAccessChecker->checkEntityRead($user, $entity, $data);
    }
    }

    Thank you in advance.
    Last edited by czcpf; 04-11-2023, 12:35 AM.
Working...