2011-10-24 15 views
26

symfony2 ACLシステムを使ってこれを実現するうまい方法が分かっているのでしょうか? Symfony2のACLと別の条件の組み合わせ

は私が ROLE_USERで編集可能にする必要がある Commentエンティティ(私のドメインオブジェクト)を持っているが、これはのみ掲載されたコメントの5分以内に許可されている - そうでない場合は、コメントのみ ROLE_ADMINで編集することができます。

ROLE_USERROLE_ADMINでのみ編集できるようにするには、それぞれRoleSecurityIdentityとしてください。

私の問題は、ROLE_USERの時間係数を組み込むときに発生します。私の最初の問題は、ACLテーブルだけでなく、ドメインオブジェクトからの情報が必要だということですが、Commentが投稿された時刻を保持できるカスタムObjectIdentityクラスを作成することによってこれが解決できると思います。

は今難しい部分

のために私はまた、作成時に見て知っているカスタムPermissionGrantingStrategyを作成する必要があると思います。これは、Commentタイプがチェックされているときにロードされなければなりませんが、ロードする方法はわかりません。この種のものを設定するための工場があるかどうかは誰にも分かりますか?したがって、エンティティに特定のPermissionGrantingStrategyが関連付けられている場合、そのエンティティが使用されます。それ以外の場合は、デフォルトが使用されます。

これは長いものですが、ACL文書が現時点ではあまり表示されていないので、これを達成する方法を知っていれば、多くのおかげです。私のフォールバックの解決策は、Commentを編集できるかどうかをチェックし、ACLをまったく気にかけないようにするためのサービスを提供することです。

答えて

23

投票者の使用を検討しましたか? IPブラックリストの投票者を実装するためのcookbook recipeがありますが、Commentオブジェクトの編集のチェックを処理するために簡単に変更できます。

デフォルトのAclVoterをSymfony\Component\Security\Acl\Voter\AclVoter(オンラインhere)から見ることができますが、あなたは明らかにそれを置き換えるのではなく、ずっと簡単に増やすことができます。

は、コンセプトの迅速な証拠として:他の人が私の最終的なコードを見ることができるように

class CommentTimestampVoter implements VoterInterface 
{ 
    public function supportsAttribute($attribute) 
    { 
     return 'edit' === $attribute; 
    } 

    public function vote(TokenInterface $token, $object, array $attributes) 
    { 
     // 1. check if $token->getUser() has ROLE_ADMIN and return VoterInterface::ACCESS_GRANTED if so 
     // 2. check if $token->getUser() equals $object->getAuthor() and return VoterInterface::ACCESS_DENIED if not 
     // 3. check that $object->getCreatedAt() is within the window allowed for editing and return VoterInterface::ACCESS_GRANTED if so 
     // 4. return VoterInterface::ACCESS_DENIED 
    } 

    public function supportsClass($class) 
    { 
     return 'Acme\CommentBundle\Entity\Comment' === $class; 
    } 
} 
+0

セキュリティコンテキストのisGranted(コメントを編集するためのコントロールを条件付きで表示するためにフロントエンドで使用することもできます)を介して、プラグインがうまくプラグインできます。私はそれを今夜のショットを与え、それが動作する場合は答えをチェックしますが、それはあなたが勝者になっているように見えます:)ありがとう! – Kasheen

+0

[OK]をこのソリューションを実装した後私はそれが行く方法だと思いますが、私は投票者を作成するときに落とし穴の多くを見つけたので、私は他人に正当性を保証することはできません)。 – Kasheen

36

私は、このソリューションを投稿していますが、ここで問題のが示唆されているように投票を実装するときに私が見つけた落とし穴があります。

supportsAttribute:あなたがSecurityContextisGrantedメソッドを呼び出したとき、それは実際にあなたが実際に属性を自分で確認する必要があり、あなたのvoteメソッド内でそうVoterInterfacevote呼び出しを委任する前にこの方法をチェックしていないことと思われます。

supportsClass:それ以上の問題の答えではVoterInterface sが投票することができたの工場に基づく選択のための鍵となる可能性があり、この方法のように思えますが、実際にSymfony2のドキュメントを読み取ります

supportsClass()メソッドを有権者が現在のユーザートークンクラスをサポートしているかどうかを確認するために使用されます。

したがって、実際にはVoterがトークンタイプをサポートしているかどうかに関係しているようです。問題を悪化させるために、PHP文書はあいまいであるようです。

有権者が指定されたクラスをサポートしているかどうかをチェックします。主な問題は、この方法は、任意の有権者のvoteメソッドの呼び出しを委任する前SecurityContextによって確認されることはありませんということですいずれにしても

- このメソッドはreturn falsevoteにハードコードされている場合でも、まだ呼び出されます! $attributes$objectを手動vote方法に着信チェック:

だから基本的にはこの話の教訓はあるように思われました。

マイコード:

services.yml

parameters: 
    comment_voter.class: Acme\Bundle\CommentBundle\Security\Authorization\Voter\CommentVoter 

services: 
    comment_voter: 
     class: %comment_voter.class% 
     arguments: [@service_container] 
     public: false 
     tags: 
      - { name: security.voter } 

と有権者クラス:

<?php 

namespace Acme\Bundle\CommentBundle\Security\Authorization\Voter; 

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

use Acme\Bundle\CommentBundle\Entity\Comment; 
use Symfony\Component\Security\Core\User\UserInterface; 

/** 
* A class to check editing privileges for Comments. 
*/ 
class CommentVoter implements VoterInterface { 

    const AUTHOR_EDIT_TIME_LIMIT = 300; 

    private $container; 

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

    public function supportsAttribute($attribute) { 
     return $attribute === 'EDIT'; 
    } 

    public function supportsClass($class) { 
     return true; 
    } 

    /** 
    * Checks whether or not the current user can edit a comment. 
    * 
    * Users with the role ROLE_COMMENT_MODERATOR may always edit. 
    * A comment's author can only edit within 5 minutes of it being posted. 
    * 
    * {@inheritdoc} 
    */ 
    public function vote(TokenInterface $token, $object, array $attributes) { 
     if (!($object instanceof Comment)) { 
      return VoterInterface::ACCESS_ABSTAIN; 
     } 

     // Only supports 'EDIT' for now. 
     if (!$this->supportsAttribute($attributes[0])) { 
      return VoterInterface::ACCESS_ABSTAIN; 
     } 

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

     // Is the token a comment moderator? 
     if ($this->container->get('security.context')->isGranted('ROLE_COMMENT_MODERATOR')) { 
      return VoterInterface::ACCESS_GRANTED; 
     } 

     // Is the token the author of the post and within the edit window. 
     $originalRevision = $object->getOriginalRevision(); 
     if ($originalRevision->getAuthor()->equals($user)) { 
      if ( 
       (time() - $originalRevision->getCreationDate()->getTimestamp()) 
       <= self::AUTHOR_EDIT_TIME_LIMIT 
      ) { 
       return VoterInterface::ACCESS_GRANTED; 
      } 
     } 

     return VoterInterface::ACCESS_DENIED; 
    } 

} 

、最終的には、テンプレート:

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

私はこれが将来誰か他の人に役立つことを願っており、Problematicのおかげで有権者の方に私を向けることができました。

+6

_Great_こちらはこちら。あなたの足取りに感謝します! – Problematic

+6

おかげさまで@Problematicとkasheen、これはSymfony料理の本https://github.com/symfony/symfony-docs;にぴったりのものです)PRを提出してください。 – maxwell2022

関連する問題