Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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:

  • ROLE_USER_ONE
  • ROLE_USER_TWO
  • ROLE_USER_THREE

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?

like image 412
french_dev Avatar asked Dec 14 '22 06:12

french_dev


2 Answers

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.

like image 75
Emanuel Oster Avatar answered Dec 17 '22 05:12

Emanuel Oster


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()
like image 28
jkucharovic Avatar answered Dec 17 '22 07:12

jkucharovic