我想在列出父项时检查几个子实体的acl条目。
这是当前的设置:
Gallery (parent)
Gallerycategory (child)
Gallerylanguage (child)
Gallerycategory -> ROLE_(Usergroup)
关系的VIEW条目。 现在,当我想列出我的画廊时,只应显示允许的Gallerycategory或Gallerylanguage的条目。
最好的方法是什么?进入存储库并检查当前用户?
答案 0 :(得分:0)
我想我想通了。
首先,我创建了一个名为 AclChildEntityInterface 的新界面。 很简单:
interface AclChildEntityInterface{
public function getAclChildren();
}
我想要检查子ACL / ACE的每个实体都实现它并返回一个函数数组来让孩子参与其中。
class Gallery implements AclChildEntityInterface
{
public function getAclChildren(){
return array(
'mediacategories' => 'getMediacategories',
'medialanguages' => 'getMedialanguages',
);
}
}
注意:数组值必须作为当前实体类中的函数存在。
之后我创建了一个扩展Symfony\Component\Security\Acl\Voter\AclVoter
的新AclVoter:
Class几乎相同,我juste改变了
的投票功能中的行为 catch (AclNotFoundException $noAcl)
use Symfony\Component\Security\Acl\Voter\AclVoter as BaseVoter;
...
use Develth\Prodcut\GalleryBundle\Entity\AclChildEntityInterface;
class MediaAclVoter extends BaseVoter
{
...
public function vote(TokenInterface $token, $object, array $attributes)
{
...
} catch (AclNotFoundException $noAcl) {
if (null !== $this->logger) {
$this->logger->debug('No ACL found for the object identity. Voting to deny access.');
}
// Check if entity has childs to check
if($object instanceof AclChildEntityInterface){
$entityChilds = $object->getAclChildren();
foreach ($entityChilds as $child) {
$childEntites = call_user_func( array($object,$child) );
foreach ($childEntites as $childEntity) {
$mapping = $childEntity->getName();
$oid = $this->objectIdentityRetrievalStrategy->getObjectIdentity($childEntity);
try{
$acl = $this->aclProvider->findAcl($oid, $sids);
if($acl->isGranted($masks, $sids, false)){
// Has permission to view. show it.
return self::ACCESS_GRANTED;
}
}catch(AclNotFoundException $noAcl){
// No ACL for this entity. Ignore
}catch(NoAceFoundException $noAce){
// No ACE for this entity. Ignore because other could have.
}
}
}
}
return self::ACCESS_DENIED;
} catch (NoAceFoundException $noAce) {
...
}
这里发生了什么?
如果找不到当前实体的ACL,它会检查它是否是先前创建的AclChildEntityInterface的实例。如果找到ACE,它会检查每个childAcl并返回ACCESS_GRANTED
。
但仍有一些我不喜欢的东西,我认为可以改进。
在实现AclChildEntityInterface
的Entity类中,我想做类似的事情:
public function getAclChildren(){
return array(
'mediacategories' => $this->mediacategories,
'medialanguages' => $this->medialanguages,
);
}
或关于获取方法。
但是,如果我想访问选民中的那些,我总是以主实体媒体作为所有者获得PersistentCollection,因此我无法直接访问这些。这就是为什么我使用call_user_funk
。
我感谢你的改进!
答案 1 :(得分:0)
我刚刚根据@develth所描述的方法发布了一个解决确切问题的Symfony软件包。
https://github.com/GoDisco/AclTreeBundle
AclTree Bundle 允许您在实体之间为ACL权限创建层次结构关系。