Closed nfx closed 12 years ago
IMO the good solution would be to check the role when creating the menu instead of adding such a dependency in the MenuItem object:
<?php
$menu = new MenuItem('Courses');
if ($securityContext->isGranted('ROLE_CREATE_COURSE') {
$menu->addChild('Create new', $router->generate('create_course'));
}
if ($securityContext->isGranted('ROLE_EDIT_OWN_COURSE') {
$menu->addChild('Edit own', $router->generate('edit_own_courses'));
}
$mainMenu->addChild($menu);
Such a way to do gives far more flexibility about the checks you can perform.
Third solution:
create a MenuItem subclass that handles this special case:
You could add a condition on url generation based on securityContext->hasRole
method and generate route only if granted.
This logic could be put in a addChildIf
method for example.
Is this a good idea?
docteurklein, yes, addChildIf
or addSecureChild
could help. Maybe adding some Renderer\SecureRenderer
could help?
the same default renderer can be used.
If you don't provide a url, then only the label will be displayed, without link. You could also decide not to show anything at all if credentials are not matched.
I wrote MillwrightMenuBundle which extends base functionality of KnpMenuBundle and adds configuration, route, translation and security context support.
Configuration example and options descriptions in Resources/doc/index.md
Given the new architecture of the bundle, the cleanest way is probably to do some checks in the builder of the menu using the security context (injected as a dependency when using a service, or retrieved from the container when using the alias provider). Doing these checks in the renderer seems weird to me.
Confirmed passing in the security context via the service is a nicer way to doing things.
arguments: ["@knp_menu.factory", "@security.context"]
Then in your MenuBuilder
public function __construct(FactoryInterface $factory, SecurityContextInterface $securityContext)
{
$this->factory = $factory;
$this->securityContext = $securityContext;
}
public function createMainMenu(Request $request)
{
$menu = $this->factory->createItem('root');
$menu->setCurrentUri($request->getRequestUri());
$menu->addChild('Home', array('route' => '_welcome'));
if ($this->securityContext->isGranted('ROLE_ADMIN') !== false) {
$menu->addChild('Admin', array('route' => 'sonata_admin_dashboard'));
}
}
Goal
Possible solution
Modify function signatures to fit the following possible usage:
$menu = new MenuItem('Courses'); $menu->addChild('Create new', $router->generate('create_course'), 'ROLE_CREATE_COURSE'); $menu->addChild('Edit own', $router->generate('edit_own_courses'), 'ROLE_EDIT_OWN_COURSES'); $mainMenu->addChild($menu);