Dynamically adding roles to a user

后端 未结 2 1845
孤独总比滥情好
孤独总比滥情好 2020-12-13 20:58

We are using Symfony2\'s roles feature to restrict users\' access to certain parts of our app. Users can purchase yearly subscriptions and each of our User enti

相关标签:
2条回答
  • 2020-12-13 21:39

    Assuming that you have the right relation "subscriptions" in your User Entity.

    You can maybe try something like :

    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');
    }
    

    Changing role can be done with :

    $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);
    

    But after a page change, the refreshUser function of the provider is called and sometimes, as this is the case with EntityUserProvider, the role is overwrite by a query. You need a custom provider to avoid this.

    0 讨论(0)
  • 2020-12-13 21:49

    I think you would do better setting up a custom voter and attribute.

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

    The SUBSCRIPTION_X role (aka attribute) would need to be handled by a custom voter class.

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

    You would need to configure and tag your voter:

    services:
        subscription_voter:
            class: SubscriptionVoter
            public: false
            arguments: [ @doctrine.orm.entity_manager ]
            tags:
                - { name: security.voter }
    
    0 讨论(0)
提交回复
热议问题