Skip to content

Commit

Permalink
Repair menu pruned based on entity actions in links
Browse files Browse the repository at this point in the history
  • Loading branch information
alterphp committed Feb 5, 2018
1 parent 2c4a260 commit a880c97
Show file tree
Hide file tree
Showing 11 changed files with 105 additions and 138 deletions.
1 change: 0 additions & 1 deletion src/Helper/EditableRolesHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
namespace AlterPHP\EasyAdminExtensionBundle\Helper;

use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;

/**
* This file is part of the EasyAdmin Extension package.
Expand Down
28 changes: 12 additions & 16 deletions src/Helper/MenuHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,43 @@

namespace AlterPHP\EasyAdminExtensionBundle\Helper;

use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;

/**
* @author Pierre-Charles Bertineau <pc.bertineau@alterphp.com>
*/
class MenuHelper
{
protected $tokenStorage;
protected $authorizationChecker;
protected $adminAuthorizationChecker;

public function __construct(TokenStorageInterface $tokenStorage, AuthorizationCheckerInterface $authorizationChecker)
public function __construct($adminAuthorizationChecker)
{
$this->tokenStorage = $tokenStorage;
$this->authorizationChecker = $authorizationChecker;
$this->adminAuthorizationChecker = $adminAuthorizationChecker;
}

public function pruneMenuItems(array $menuConfig)
public function pruneMenuItems(array $menuConfig, array $entitiesConfig)
{
$menuConfig = $this->pruneAccessDeniedEntries($menuConfig);
$menuConfig = $this->pruneAccessDeniedEntries($menuConfig, $entitiesConfig);
$menuConfig = $this->pruneEmptyFolderEntries($menuConfig);

return $menuConfig;
}

protected function pruneAccessDeniedEntries(array $menuConfig)
protected function pruneAccessDeniedEntries(array $menuConfig, array $entitiesConfig)
{
foreach ($menuConfig as $key => $entry) {
if (
isset($entry['role'])
&& is_string($entry['role'])
&& (
null === $this->tokenStorage->getToken() || !$this->authorizationChecker->isGranted($entry['role'])
'entity' == $entry['type']
&& isset($entry['entity'])
&& !$this->adminAuthorizationChecker->isEasyAdminGranted(
$entitiesConfig[$entry['entity']],
isset($entry['params']) && isset($entry['params']['action']) ? $entry['params']['action'] : 'list'
)
) {
unset($menuConfig[$key]);
continue;
}

if (isset($entry['children']) && is_array($entry['children'])) {
$menuConfig[$key]['children'] = $this->pruneAccessDeniedEntries($entry['children']);
$menuConfig[$key]['children'] = $this->pruneAccessDeniedEntries($entry['children'], $entitiesConfig);
}
}

Expand Down
3 changes: 1 addition & 2 deletions src/Resources/config/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@
<argument>%easy_admin_extension.minimum_role%</argument>
</service>
<service id="alterphp.easyadmin_extension.helper.menu" class="AlterPHP\EasyAdminExtensionBundle\Helper\MenuHelper">
<argument type="service" id="security.token_storage"/>
<argument type="service" id="security.authorization_checker"/>
<argument type="service" id="alterphp.easyadmin_extension.admin_authorization_checker"/>
</service>
<service id="alterphp.easyadmin_extension.twig.extension.menu" class="AlterPHP\EasyAdminExtensionBundle\Twig\MenuExtension">
<argument type="service" id="alterphp.easyadmin_extension.helper.menu"/>
Expand Down
2 changes: 1 addition & 1 deletion src/Resources/views/default/menu.html.twig
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{% extends '@BaseEasyAdmin/default/menu.html.twig' %}

{% block main_menu %}
{% set _menu_items = _menu_items|prune_menu_items %}
{% set _menu_items = _menu_items|prune_menu_items(easyadmin_config('entities')) %}
{{ parent() }}
{% endblock %}
11 changes: 11 additions & 0 deletions src/Security/AdminAuthorizationChecker.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,17 @@ public function checksUserAccess(array $entity, string $actionName)
}
}

public function isEasyAdminGranted(array $entity, string $actionName)
{
try {
$this->checksUserAccess($entity, $actionName);
} catch (AccessDeniedException $e) {
return false;
}

return true;
}

protected function getRequiredRole(array $entity, string $actionName)
{
if (isset($entity[$actionName]) && isset($entity[$actionName]['role'])) {
Expand Down
11 changes: 2 additions & 9 deletions src/Twig/AdminAuthorizationExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

namespace AlterPHP\EasyAdminExtensionBundle\Twig;

use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
use Twig\TwigFunction;
Expand Down Expand Up @@ -30,15 +29,9 @@ public function getFilters()
);
}

public function isEasyAdminGranted(array $entity, string $actionName)
public function isEasyAdminGranted(array $entity, string $actionName = 'list')
{
try {
$this->adminAuthorizationChecker->checksUserAccess($entity, $actionName);
} catch (AccessDeniedException $e) {
return false;
}

return true;
return $this->adminAuthorizationChecker->isEasyAdminGranted($entity, $actionName);
}

public function pruneItemsActions(array $itemActions, array $entity, array $forbiddenActions = [])
Expand Down
5 changes: 2 additions & 3 deletions src/Twig/MenuExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

namespace AlterPHP\EasyAdminExtensionBundle\Twig;

use Symfony\Component\Form\FormView;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;

Expand All @@ -22,8 +21,8 @@ public function getFilters()
);
}

public function pruneMenuItems(array $menuConfig)
public function pruneMenuItems(array $menuConfig, array $entitiesConfig)
{
return $this->menuHelper->pruneMenuItems($menuConfig);
return $this->menuHelper->pruneMenuItems($menuConfig, $entitiesConfig);
}
}
40 changes: 20 additions & 20 deletions tests/Controller/UserRolesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ public function testAdminIsNotReachableWithoutMinimumRole()

$crawler = $this->getBackendPage();

$this->assertEquals(403, $this->client->getResponse()->getStatusCode());
$this->assertSame(403, $this->client->getResponse()->getStatusCode());

$this->assertEquals(
$this->assertSame(
'You must be granted ROLE_ADMIN role to access admin ! (403 Forbidden)',
trim($crawler->filterXPath('//head/title')->text())
);
Expand All @@ -54,7 +54,7 @@ public function testAdminIsReachableWithMinimumRole()

$crawler = $this->getBackendPage();

$this->assertEquals(200, $this->client->getResponse()->getStatusCode());
$this->assertSame(200, $this->client->getResponse()->getStatusCode());
}

public function testMenuIsWellPruned()
Expand All @@ -65,33 +65,33 @@ public function testMenuIsWellPruned()

$crawler = $this->getBackendPage();

$this->assertEquals(200, $this->client->getResponse()->getStatusCode());
$this->assertSame(200, $this->client->getResponse()->getStatusCode());

$this->assertEquals(
$this->assertSame(
1,
$crawler->filter('body ul.sidebar-menu li:contains("Catalog")')->count()
);
$this->assertEquals(
$this->assertSame(
1,
$crawler->filter('body ul.sidebar-menu li ul li:contains("Categories")')->count()
);
$this->assertEquals(
$this->assertSame(
0,
$crawler->filter('body ul.sidebar-menu li ul li:contains("Products")')->count()
);
$this->assertEquals(
$this->assertSame(
0,
$crawler->filter('body ul.sidebar-menu li:contains("Images")')->count()
);
$this->assertEquals(
$this->assertSame(
0,
$crawler->filter('body ul.sidebar-menu li:contains("Sales")')->count()
);
$this->assertEquals(
$this->assertSame(
0,
$crawler->filter('body ul.sidebar-menu li ul li:contains("Purchases")')->count()
);
$this->assertEquals(
$this->assertSame(
0,
$crawler->filter('body ul.sidebar-menu li ul li:contains("Purchases items")')->count()
);
Expand All @@ -104,21 +104,21 @@ public function testEntityActionsAreFilteredOnPrefixedRoles()
$this->client->followRedirects();

$this->getBackendPage(['entity' => 'Category', 'action' => 'list']);
$this->assertEquals(200, $this->client->getResponse()->getStatusCode());
$this->assertSame(200, $this->client->getResponse()->getStatusCode());

// Tests that embeddedList is mapped on list action required roles
$this->getBackendPage(['entity' => 'Category', 'action' => 'embeddedList']);
$this->assertEquals(200, $this->client->getResponse()->getStatusCode());
$this->assertSame(200, $this->client->getResponse()->getStatusCode());

$crawler = $this->getBackendPage(['entity' => 'Category', 'action' => 'edit', 'id' => 1]);
$this->assertEquals(403, $this->client->getResponse()->getStatusCode());
$this->assertEquals(
$this->assertSame(403, $this->client->getResponse()->getStatusCode());
$this->assertSame(
'You must be granted ROLE_CATEGORY_EDIT role to perform this entity action ! (403 Forbidden)',
trim($crawler->filterXPath('//head/title')->text())
);

$this->getBackendPage(['entity' => 'Category', 'action' => 'show', 'id' => 1]);
$this->assertEquals(200, $this->client->getResponse()->getStatusCode());
$this->assertSame(200, $this->client->getResponse()->getStatusCode());
}

public function testEntityActionsAreFilteredOnSpecificRoles()
Expand All @@ -130,11 +130,11 @@ public function testEntityActionsAreFilteredOnSpecificRoles()
$this->getBackendPage(['entity' => 'Product', 'action' => 'list']);

$this->getBackendPage(['entity' => 'Product', 'action' => 'edit', 'id' => 1]);
$this->assertEquals(200, $this->client->getResponse()->getStatusCode());
$this->assertSame(200, $this->client->getResponse()->getStatusCode());

$crawler = $this->getBackendPage(['entity' => 'Product', 'action' => 'show', 'id' => 1]);
$this->assertEquals(403, $this->client->getResponse()->getStatusCode());
$this->assertEquals(
$this->assertSame(403, $this->client->getResponse()->getStatusCode());
$this->assertSame(
'You must be granted ROLE_TEST_SHOW_PRODUCT role to perform this entity action ! (403 Forbidden)',
trim($crawler->filterXPath('//head/title')->text())
);
Expand All @@ -148,7 +148,7 @@ public function testAdminGroupRolesFormMayDisplay()

$crawler = $this->getBackendPage(['entity' => 'AdminGroup', 'action' => 'edit', 'id' => 1]);

$this->assertEquals(
$this->assertSame(
25,
$crawler->filter('form#edit-admingroup-form .field-easyadmin_admin_roles input[type="checkbox"]')->count()
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public function load(ObjectManager $manager)
foreach (range(1, 20) as $i) {
$group = new AdminGroup();
$group->setName('group'.$i);
$group->setRoles(array('ROLE_GROUP_'.$i, 'ROLE_GROUP_'.($i+1)));
$group->setRoles(array('ROLE_GROUP_'.$i, 'ROLE_GROUP_'.($i + 1)));

$this->addReference('group-'.$i, $group);
$manager->persist($group);
Expand Down
22 changes: 11 additions & 11 deletions tests/Helper/EditableRolesHelperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,30 @@

class EditableRolesHelperTest extends TestCase
{
private static $roleHierarchy = array (
'ROLE_SUPER_ADMIN' => array (
private static $roleHierarchy = array(
'ROLE_SUPER_ADMIN' => array(
0 => 'ROLE_ORGANIZATION',
3 => 'ROLE_SYSTEM',
),
'ROLE_SYSTEM' => array (
'ROLE_SYSTEM' => array(
0 => 'ROLE_ADMINUSER',
1 => 'ROLE_ADMINGROUP',
),
'ROLE_ORGANIZATION' => array (
'ROLE_ORGANIZATION' => array(
0 => 'ROLE_ORGANIZATION_LIST',
1 => 'ROLE_ORGANIZATION_SEARCH',
2 => 'ROLE_ORGANIZATION_NEW',
3 => 'ROLE_ORGANIZATION_EDIT',
4 => 'ROLE_ORGANIZATION_SHOW',
),
'ROLE_ADMINUSER' => array (
'ROLE_ADMINUSER' => array(
0 => 'ROLE_ADMINUSER_LIST',
1 => 'ROLE_ADMINUSER_SEARCH',
2 => 'ROLE_ADMINUSER_EDIT',
3 => 'ROLE_ADMINUSER_SHOW',
4 => 'ROLE_ADMINUSER_DELETE',
),
'ROLE_ADMINGROUP' => array (
'ROLE_ADMINGROUP' => array(
0 => 'ROLE_ADMINGROUP_LIST',
1 => 'ROLE_ADMINGROUP_SEARCH',
2 => 'ROLE_ADMINGROUP_NEW',
Expand Down Expand Up @@ -62,26 +62,26 @@ public function testRoleHierarchyIsMappedForChoicesWithoutSuperAdmin()

$editableRolesHelper = new EditableRolesHelper($tokenStorage, static::$roleHierarchy);

$expected = array (
'ROLE_SYSTEM' => array (
$expected = array(
'ROLE_SYSTEM' => array(
'ROLE_ADMINUSER' => 'ROLE_ADMINUSER',
'ROLE_ADMINGROUP' => 'ROLE_ADMINGROUP',
),
'ROLE_ORGANIZATION' => array (
'ROLE_ORGANIZATION' => array(
'ROLE_ORGANIZATION_LIST' => 'ROLE_ORGANIZATION_LIST',
'ROLE_ORGANIZATION_SEARCH' => 'ROLE_ORGANIZATION_SEARCH',
'ROLE_ORGANIZATION_NEW' => 'ROLE_ORGANIZATION_NEW',
'ROLE_ORGANIZATION_EDIT' => 'ROLE_ORGANIZATION_EDIT',
'ROLE_ORGANIZATION_SHOW' => 'ROLE_ORGANIZATION_SHOW',
),
'ROLE_ADMINUSER' => array (
'ROLE_ADMINUSER' => array(
'ROLE_ADMINUSER_LIST' => 'ROLE_ADMINUSER_LIST',
'ROLE_ADMINUSER_SEARCH' => 'ROLE_ADMINUSER_SEARCH',
'ROLE_ADMINUSER_EDIT' => 'ROLE_ADMINUSER_EDIT',
'ROLE_ADMINUSER_SHOW' => 'ROLE_ADMINUSER_SHOW',
'ROLE_ADMINUSER_DELETE' => 'ROLE_ADMINUSER_DELETE',
),
'ROLE_ADMINGROUP' => array (
'ROLE_ADMINGROUP' => array(
'ROLE_ADMINGROUP_LIST' => 'ROLE_ADMINGROUP_LIST',
'ROLE_ADMINGROUP_SEARCH' => 'ROLE_ADMINGROUP_SEARCH',
'ROLE_ADMINGROUP_NEW' => 'ROLE_ADMINGROUP_NEW',
Expand Down
Loading

0 comments on commit a880c97

Please sign in to comment.