Announcement

Collapse
No announcement yet.

ACL with GrandChildren Entities of Account

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • 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 $userEntity $entityScopeData $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...
X