2013-06-10 10 views
5

Użyłem SonataUser z FOSUser do zarządzania moimi użytkownikami i stworzyłem niestandardowe pole company, aby dołączyć je do danej firmy.Użytkownik sonaty - Bezpieczeństwo na niestandardowym polu

Teraz ja po prostu trzeba dać użytkownikom możliwość zarządzania tylko użytkowników podłączonych do tej samej firmy:

user1 company1 
user2 company1 
user3 company2 
user4 company2 

Przykład: user1 powinien być w stanie wymienić/edytować tylko user1 & użytkownik2

Czy powinienem używać list ACL?

Czy możesz wskazać mi właściwy kierunek lub samouczek, aby dostosować SonataUser do tego celu?

Odpowiedz

10

Tak ACL jest drogą do zrobienia. utwórz usługę CompanyVoter implementującą VoterInterface i sprawdź, czy użytkownik znajduje się w tej samej firmie w ramach metody vote().

wpis do książki kucharskiej "How to implement your own Voter to blacklist IP Addresses" stanowi dobre wprowadzenie.

zmienić strategię "dostęp-decyzja-menedżer" na "jednomyślność". Oznacza to, że jeśli tylko jeden głosujący odmawia dostępu (np. CompanyVoter), dostęp nie jest przyznawany użytkownikowi końcowemu.

# app/config/security.yml 
security: 
    access_decision_manager: 
     strategy: unanimous 

teraz tworzyć Wyborcy

// src/Acme/AcmeBundle/YourBundle/Security/Authorization/Voter/CompanyVoter.php 
namespace Acme\YourBundle\Security\Authorization\Voter; 

use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface; 
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; 

use Acme\YourUserBundleBundle\Entity\User; 
use Symfony\Component\Security\Core\User\UserInterface; 

class CompanyVoter implements VoterInterface 
{ 

    private $container; 

    public function __construct($container) 
    { 
     $this->container = $container; 
    } 

    public function supportsAttribute($attribute) 
    { 
     return in_array($attribute, array(
      'EDIT', 
      'ACTIVATE', 
      // ... 
     )); 
    } 

    public function supportsClass($class) 
    { 
     return in_array("FOS\UserBundle\Model\UserInterface", class_implements($class)); 
    } 

    public function vote(TokenInterface $token, $object, array $attributes) 
    { 
     if (!($this->supportsClass(get_class($object)))) { 
      return VoterInterface::ACCESS_ABSTAIN; 
     } 

     foreach ($attributes as $attribute) { 
      if (!$this->supportsAttribute($attribute)) { 
       return VoterInterface::ACCESS_ABSTAIN; 
      } 
     } 

     $user = $token->getUser(); 
     if (!($user instanceof UserInterface)) { 
      return VoterInterface::ACCESS_DENIED; 
     } 

     // check if the user has the same company 
     if ($user->getCompany() == $object->getCompany()) { 
      return VoterInterface::ACCESS_GRANTED; 
     } 

     return VoterInterface::ACCESS_DENIED; 
    } 

} 

Wreszcie zarejestrować jako wyborcy jako usługa

# src/Acme/AcmeBundle/Resources/config/services.yml 
services: 
    security.access.company_voter: 
     class:  Acme\YourBundle\Security\Authorization\Voter\CompanyVoter 
     public:  false 
     tags: 
      - { name: security.voter } 

... teraz używać go w szablonie gałązka

{% if is_granted('EDIT', user) %}<a href="#">Edit</a>{% endif %} 
{% if is_granted('ACTIVATE', user) %}<a href="#">activate</a>{% endif %} 

lub w kontrolerze ...

public function editAction(UserInterface $user) 
{ 
    if ($this->get('security.context')->isGranted('EDIT',$user)) { 
     throw new \Symfony\ComponentSecurity\Core\Exception\AccessDeniedException(); 
    } 
} 

lub używając JMSSecurityExtraBundle ...

/** 
* @SecureParam(name="user", permissions="EDIT") 
*/ 
public function editUser(UserInterface $user) 
{ 
    // ... 
} 
+0

Próbowałem w ten sposób, że pracuje dla edycji (uniemożliwia wydanie dla innych firm), ale nadal wyświetla listę wszystkich użytkowników. Wygląda na to, że wyborca ​​nie jest wezwany do wyświetlenia linii. –

+0

co masz na myśli wyświetlając linię? – nifr

+0

Ponieważ muszę pokazywać tylko niektórych użytkowników w siatce list, nie powinien być wyświetlany żaden wiersz (zamiast pojawiać się tylko do odczytu) Uwaga Mówię o siatce SonataAdmin –

1

Ponieważ nie muszę ACL tutaj (tylko wyborcy) użyłem obsługi zabezpieczeń roli sonaty.

Ale miałem problemy z używaniem go, ponieważ jego domyślna implementacja isGranted() nie przekazuje bieżącego obiektu wyborcy.

Więc musiałem przedłużyć to, sprawdź mój monolog w tym github issue po więcej szczegółów.


Nawiasem mówiąc, moja PR została przyjęta na ten temat

Powiązane problemy