Динамическое добавление ролей пользователю - PullRequest
14 голосов
/ 16 января 2012

Мы используем функцию ролей Symfony2, чтобы ограничить доступ пользователей к определенным частям нашего приложения.Каждая из наших сущностей пользователей имеет много сущностей подписки, которые имеют дату начала и окончания, и пользователи могут приобретать годовые подписки.

Теперь есть способ динамически добавить роль пользователю, основываясь на том, есть ли у него«активная» подписка?В рельсах я бы просто позволил модели обрабатывать, имеет ли она необходимые права, но я знаю, что по замыслу сущности symfony2 не должны иметь доступ к Doctrine.

Я знаю, что вы можете получить доступ к ассоциациям сущности изнутриэкземпляр сущности, но он прошел бы через все объекты подписки пользователя, и это мне кажется излишне громоздким.

Ответы [ 2 ]

27 голосов
/ 16 января 2012

Думаю, вам лучше настроить настраиваемого избирателя и атрибут.

/**
 * @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 }
2 голосов
/ 16 января 2012

Предполагая, что у вас есть правильное отношение "подписки" в вашей пользовательской сущности.

Вы можете попробовать что-то вроде:

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, роль перезаписывается запросом.Чтобы избежать этого, вам нужен специальный провайдер.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...