french_dev
french_dev

Reputation: 2177

fos user: allow route to many roles even if user have just one role

In my symfony project, using the FOS bundle, I have 4 roles like this:

They can't access to the same views, except for one. This is my controller for render the view:

/**
 * @Security("has_role('ROLE_USER_ONE', 'ROLE_USER_TWO', 'ROLE_USER_THREE')")
 * @Route("/add-note", name="add_user_note")
 * @Method({"GET"})
 */
public function addNoteToUserAction()
{
  $securityContext = $this->container->get('security.authorization_checker');

  if ($securityContext->isGranted('ROLE_USER_ONE', 'ROLE_USER_TWO', 'ROLE_USER_THREE')) {
    /* ... some persist datas and process here ... */
    return $this->render('MyBundle:NoteUser:addNote.html.twig', array(
    ));
  } else {
      throw new \Exception('You have no right to access this page');
  }
}

To test the view rendering, I create a user with role ROLE_USER_TWO. And when I render the view I have this error:

Expression "has_role('ROLE_USER_ONE', 'ROLE_USER_TWO', 'ROLE_USER_THREE')" denied access.

As I understand, Symfony expected the user have all the roles, how can I allow the view access to user which as at less one of these roles in my controller annotations and controller code?

Upvotes: 4

Views: 2922

Answers (2)

Emanuel Oster
Emanuel Oster

Reputation: 1296

Instead of trying to put every role into the same has_role() statement, you have to concatenate them with or like this:

@Security("has_role('ROLE_USER_ONE') or has_role('ROLE_USER_TWO') or has_role('ROLE_USER_THREE')")

This way, you are actually checking that the current user has at least one of these roles instead of all of them.

Upvotes: 9

jkucharovic
jkucharovic

Reputation: 4244

I suppose you're looking for role hierarchy. Your configuration will be like:

security:
    # ...

    role_hierarchy:
        ROLE_USER_ONE : ROLE_USER_BASE
        ROLE_USER_TWO : ROLE_USER_BASE
        ROLE_USER_THREE : ROLE_USER_BASE

So users with ROLE_USER_ONE role has also role ROLE_USER_BASE etc. Then, in your controller you just need to check only for ROLE_USER_BASE:

/**
 * @Security("has_role('ROLE_USER_BASE')")
 * @Route("/add-note", name="add_user_note")
 * @Method({"GET"})
 */
public function addNoteToUserAction()

Upvotes: 3

Related Questions