2012-08-28 20 views
5

Jestem zajęty aplikacją Symfony2, która wymaga pewnych uprawnień ACL.Symfony2 Dostęp ACL do wielu obiektów dla wielu użytkowników

Jestem początkującym z Symfony2, więc nie jestem pewien, czy patrzę na to we właściwy sposób.

Mam wielu klientów, każdy z wieloma kontami.

Mam superadministratora (ROLE_SUPER_ADMIN), który ma dostęp do wszystkich klientów i wszystkich kont. Następnie mam rolę administratora (ROLE_ADMIN), która będzie miała dostęp tylko do określonego klienta i wszystkich kont dla tych klientów. Następnie są agenci (ROLE_AGENT), którzy powinni mieć uprawnienia tylko do niektórych kont klientów.

widziałem na docs symfony że dać użytkownikowi dostęp do określonego obiektu, można użyć następującego kodu:

// creating the ACL 
$aclProvider = $this->get('security.acl.provider'); 
$objectIdentity = ObjectIdentity::fromDomainObject($account); 
$acl = $aclProvider->createAcl($objectIdentity); 

// retrieving the security identity of the currently logged-in user 
$securityContext = $this->get('security.context'); 
$user = $securityContext->getToken()->getUser(); 
$securityIdentity = UserSecurityIdentity::fromAccount($user); 

// grant owner access  
$acl->insertObjectAce($securityIdentity, MaskBuilder::MASK_OWNER); 
$aclProvider->updateAcl($acl); 

Więc podczas tworzenia nowego konta, mogę dać prąd zalogowanych dostęp użytkownika do nowo utworzonego konta. Ale w jaki sposób mogę przyznać dostęp do wszystkich innych użytkowników klienta, którzy mają dostęp do konta?

Nie chcę przechodzić przez wszystkich użytkowników i uruchamiać powyższy kod dla każdego użytkownika.

Na przykład podczas przeglądania wszystkich klientów muszę wiedzieć, do których klientów użytkownik ma dostęp lub kiedy przegląda konta, muszę wiedzieć, do których kont ma dostęp użytkownik.

Również podczas dodawania nowego użytkownika do klienta, użytkownik automatycznie musi mieć dostęp do wszystkich kont dla tego klienta.

Na marginesie, muszę tylko wiedzieć, czy użytkownik ma dostęp do konta/klienta. Jeśli użytkownik ma dostęp, wówczas automatycznie może przeglądać/edytować/usuwać itd.

+2

Jeśli musisz przypisać uprawnienia każdemu użytkownikowi w określonej roli, powinieneś użyć opartego na rolach 'ACL' zamiast tego ... który jest bardzo podobny do konta. Powinienem być w stanie napisać przykładowy kod (w ciągu najbliższych kilku godzin). Jednak jeśli role nie są czymś, czego szukasz, ** musisz ** iterować przez każdego użytkownika, któremu chcesz przypisać uprawnienia .... –

Odpowiedz

0

W tym przypadku użyłem niestandardowej usługi zabezpieczeń, która weryfikuje relacje ManyToMany między jednostkami. To nie jest idealna decyzja, ale należy pamiętać.

Najpierw musimy stworzyć detektor, który będzie uruchamiany przy każdej akcji kontrolera.

class SecurityListener 
{ 
    protected $appSecurity; 

    function __construct(AppSecurity $appSecurity) 
    { 
     $this->appSecurity = $appSecurity; 
    } 

    public function onKernelController(FilterControllerEvent $event) 
    { 
     $c = $event->getController(); 

     /* 
     * $controller passed can be either a class or a Closure. This is not usual in Symfony2 but it may happen. 
     * If it is a class, it comes in array format 
     */ 
     if (!is_array($c)) { 
      return; 
     } 

     $hasAccess = $this->appSecurity->hasAccessToContoller($c[0], $c[1], $event->getRequest()); 

     if(!$hasAccess) { 
      throw new AccessDeniedHttpException('Access denied.'); 
     } 

    } 
} 

W serwisie mamy dostęp do żądania, instancji kontrolera i wywoływanej akcji. Dzięki temu możemy podjąć decyzję, czy użytkownik ma dostęp, czy nie.

class AppSecurity 
{ 
    protected $em; 
    protected $security; 
    /** @var $user User */ 
    protected $user; 

    public function __construct(EntityManager $em, SecurityContext $security) 
    { 
     $this->em = $em; 
     $this->security = $security; 

     if($security->getToken() !== null && !$security->getToken() instanceof AnonymousToken) { 
      $this->user = $security->getToken()->getUser(); 
     } 
    } 

    /** 
    * @param $controller 
    * @param string $action 
    */ 
    public function hasAccessToContoller($controller, $action, Request $request) 
    { 
     $attrs = $request->attributes->all(); 
     $client = $attrs['client']; 

     /* db query to check link between logged user and request client */ 
    } 
} 

Jeśli używasz bardzo nieprzyjemnych adnotacje jak ParamConverter można łatwo wyodrębnić gotowy do użycia udziałów w jednostkach od wniosku.