0

The security of my Symfony 4 application is using @security annotations in controllers :

/**
 * @Route("/cat/list", name="cat_list")
 *
 * @Security("is_granted('ROLE_XYZ'")
 */
public function listAction()
{
    // [...]
}

I am building a menu with twig from a list of route names :

{% for route_name in ["cat_list","cat_map", ,"cat_trips"] %}
    <a href="{{ path(route_name) }}"/> {{ route_name|trans }} </a>
{% endfor %}

I would like to add a security check to only display the routes my user have access, something like that :

{% for route_name in ["cat_list","cat_map", ,"cat_trips"] %}
    {% if can_access_route(route_name) %}
        <a href="{{ path(route_name) }}"/> {{ route_name|trans }} </a>
    {% endif %}
{% endfor %}

Is there something built in Symfony for that ? Or how would you build is_route_granted() ?

Wink
  • 43
  • 6
  • `route` is not granted. `ROLE` is granted. If user granted a `ROLE` - he can access a `route`. – u_mulder May 25 '18 at 14:03
  • So why not use the same approach in twig? Check the user's ROLE and show or not some link (_or only a part of a menu_), but for a better implementation you should take a look at the [KnpMenuBundle](https://symfony.com/doc/master/bundles/KnpMenuBundle/index.html). – gp_sflover May 25 '18 at 14:13
  • 1
    also you can use voter to check your conditions. see https://symfony.com/doc/current/security/voters.html – LeshaZ May 25 '18 at 14:13
  • Voters or Roles are using the same isGranted() method, it wouldn't change that specific problem of access security checks from outside the Action. is_route_granted("route_name") might not be the best name, let's say it would be called can_access_route("route_name") – Wink May 25 '18 at 14:22
  • you can put your access logic to for example voter method canSee. then in twig just check {% if is_granted(constant(Voter::SEE), user) %} look at custom voter to get more details – LeshaZ May 25 '18 at 14:34
  • i'm sorry. Instead of user there will be route and user will be got in voter from token – LeshaZ May 25 '18 at 14:45
  • @LeshaZ In my last code block, how would you retrieve "constant(Voter::SEE), user" in the for loop (it's a different one for each route, I have lots of routes) ? It's easy to re-write the logic manually, but it would be way better to extract it from the @ Security anotation written in the first code block. – Wink May 25 '18 at 14:54
  • @Wink In your voter should be an array (constant or static variable) with routes as a value and as a key your user name or role or somthing else that is deferent for each user. Then you call is_granted(constant('My\Super\Namespace\Voter::CAN_SEE'), each_route_in_the_loop) and then in voter you can check it like return in_array($each_route_in_the_loop, self::MY_ROUTES[$token->getUser()->getRole()] CAN_SEE should contain method as a string. Looke at voteOnAttribute more carefully. – LeshaZ May 26 '18 at 10:48

0 Answers0