2013-01-09 34 views
0

我想在列出父項時檢查多個子實體的acl條目。Symfony2檢查子實體的ACL

這就是當前的設置:

Gallery (parent) 
    Gallerycategory (child) 
    Gallerylanguage (child) 
  • 每個用戶組都有自己的角色。
  • 創建GalleryCategory或Gallerylanguage時,我列出了所有應該訪問此實體的組。
  • 選中時,組將在ACL中獲取關於Gallerycategory -> ROLE_(Usergroup)關係的VIEW項。

現在,當我想列出我的畫廊時,只會顯示允許的GalleryCategory或Gallerylanguage的條目。

最好的方法是什麼?進入存儲庫並檢查當前用戶?

回答

0

我想我想通了。

首先,我創建了一個新的接口,稱爲AclChildEntityInterface。 很簡單:

interface AclChildEntityInterface{ 
    public function getAclChildren(); 
} 

我要檢查孩子ACL/ACE每個實體實現它,並返回的功能的陣列來獲得孩子的entites。

class Gallery implements AclChildEntityInterface 
{ 
    public function getAclChildren(){ 
     return array(
      'mediacategories' => 'getMediacategories', 
      'medialanguages' => 'getMedialanguages', 
     ); 
    } 
} 

注:數組值必須存在作爲當前實體類功能。

之後我創建的擴展Symfony\Component\Security\Acl\Voter\AclVoter新AclVoter:

類是幾乎一樣的,我中庸之道改變了行爲的

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實體類我想要做這樣的事情:

public function getAclChildren(){ 
    return array(
     'mediacategories' => $this->mediacategories, 
     'medialanguages' => $this->medialanguages, 
    ); 
} 

或有關Get方法。

但是,如果我想訪問選民中的那些,我總是得到與主實體媒體作爲所有者的PersistentCollection,所以我不能直接訪問這些。這就是爲什麼我使用call_user_funk

我很感謝改進!