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.