2013-06-10 6 views
5

私はユーザーを管理するためにFOSUserでSonataUserを使用し、カスタムフィールドcompanyを作成してそれぞれの会社に添付しました。ソナタユーザー - カスタムフィールドのセキュリティ

今、私は単にユーザーに同じ会社に接続ユーザーのみを管理する能力を与える必要があるだろう:

user1 company1 
user2 company1 
user3 company2 
user4 company2 

例:user1が唯一& user2の

USER1 /編集を一覧表示することができるはずですACLを使用すべきですか?

この目的のためにSonataUserをカスタマイズするための正しい方向またはチュートリアルを教えてください。

答えて

10

はいアクセスするにはACLが必要です。 VoterInterfaceを実装しているCompanyVoterを作成し、ユーザが同じ会社のvote()メソッド内にいるかどうかを確認します。

料理本の項目「How to implement your own Voter to blacklist IP Addresses」は良い紹介です。

アクセス決定マネージャの戦略を「全会一致」に変更します。これは、1人の有権者のみがアクセスを拒否した場合(例えば、CompanyVoter)、エンドユーザにアクセスが許可されないことを意味する。

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

今すぐあなたの投票者

// 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; 
    } 

} 

最後にサービス

# 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 } 

...今

あなたの小枝テンプレートで使用
{% if is_granted('EDIT', user) %}<a href="#">Edit</a>{% endif %} 
{% if is_granted('ACTIVATE', user) %}<a href="#">activate</a>{% endif %} 

などとして有権者登録を作成しますまたはあなたのコントローラで...

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

またはJMSSecurityExtraBundleを使用して...

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

について承認された私は、それが版のために働く、この方法を試してみました(他の企業のための版を防止する)が、リストには、まだすべてのユーザーが表示されます。有権者がその行を表示するために呼び出されていないようです。 –

+0

行を表示することはどういう意味ですか? – nifr

+0

リストグリッド内の特定のユーザーのみを表示する必要があるので、(読み取り専用ではなく)行が表示されないようにしてください。注SonataAdminグリッドについては –

1

私はソナタの役割のセキュリティハンドラを使用(のみ有権者)、ここではACLを必要としなかったよう。

しかし、デフォルトの実装isGranted()は、現在のオブジェクトを有権者に渡さないため、問題を使用していました。

私はそれを拡張しなければならなかったので、このgithub issueの私の独り言をチェックしてください。ところで


、私のPRがこの問題