15

Symfony2のロール機能を使用して、アプリの特定の部分へのユーザーのアクセスを制限しています。ユーザーは年間サブスクリプションを購入でき、各エンティティには開始日と終了日をUser持つ多くのエンティティがあります。Subscription

さて、ユーザーが「アクティブな」サブスクリプションを持っているかどうかに基づいて、ユーザーにロールを動的に追加する方法はありますか?Railsでは、モデルに必要な権限があるかどうかを処理させるだけですが、設計上、symfony2エンティティがDoctrineにアクセスすることは想定されていません。

エンティティインスタンス内からエンティティの関連付けにアクセスできることは知っていますが、それはすべてのユーザーのサブスクリプションオブジェクトを経由するため、不必要に面倒に思えます。

4

2 に答える 2

27

カスタムボーターと属性を設定したほうがよいと思います。

/**
 * @Route("/whatever/")
 * @Template
 * @Secure("SUBSCRIPTION_X")
 */
public function viewAction()
{
    // etc...
}

ロール (別名属性)はSUBSCRIPTION_X、カスタム ボーター クラスによって処理される必要があります。

class SubscriptionVoter implements VoterInterface
{
    private $em;

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

    public function supportsAttribute($attribute)
    {
        return 0 === strpos($attribute, 'SUBSCRIPTION_');
    }

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

    public function vote(TokenInterface $token, $object, array $attributes)
    {
        // run your query and return either...
        //  * VoterInterface::ACCESS_GRANTED
        //  * VoterInterface::ACCESS_ABSTAIN
        //  * VoterInterface::ACCESS_DENIED
    }
}

投票者を構成してタグ付けする必要があります。

services:
    subscription_voter:
        class: SubscriptionVoter
        public: false
        arguments: [ @doctrine.orm.entity_manager ]
        tags:
            - { name: security.voter }
于 2012-01-16T16:45:37.447 に答える
2

ユーザーエンティティに正しい関係「サブスクリプション」があると仮定します。

次のようなものを試すことができます:

public function getRoles()
{
    $todayDate = new DateTime();
    $activesSubscriptions = $this->subscriptions->filter(function($entity) use ($todayDate) {
        return (($todayDate >= $entity->dateBegin()) && ($todayDate < $entity->dateEnd()));
    });

    if (!isEmpty($activesSubscriptions)) {
        return array('ROLE_OK');
    }

    return array('ROLE_KO');
}

役割の変更は、次の方法で実行できます。

$sc = $this->get('security.context')
$user = $sc->getToken()->getUser();
$user->setRole('ROLE_NEW');
// Assuming that "main" is your firewall name :
$token = new \Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken($user, null, 'main', $user->getRoles());
$sc->setToken($token);

しかし、ページが変更された後、プロバイダーの refreshUser 関数が呼び出され、EntityUserProvider の場合のように、クエリによってロールが上書きされることがあります。これを回避するには、カスタム プロバイダーが必要です。

于 2012-01-16T13:38:19.123 に答える