Dynamically adding roles to a user

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.


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 }