Skip to content

Instantly share code, notes, and snippets.

@dbu
Last active January 13, 2016 13:53
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save dbu/c269f79deee3245157e6 to your computer and use it in GitHub Desktop.
Save dbu/c269f79deee3245157e6 to your computer and use it in GitHub Desktop.
Symfony2: Role Hierarchy check independent of firewall

We needed to decide whether a user loaded from FOSUserBundle is granted a specific role. Because of the role hierarchy, this is not as simple as doing in_array($role, $user->getRoles()). The user model only knows about its roles, not about what other roles those roles grant it.

The only thing that handles this situation that i found is the SecurityContext::isGranted method. But the problem of that is that its a check about the role of the "current" user. We needed this information in a command that generates a file and needs to know which user has permission for a specific role.

The RoleHierarchy service can not do decisions but only explode roles into all roles granted through the tree. The RoleHiararchyVoter is part of the security manager. Both are private service and thus not intended to be reused in application code.

The simplest we could come up with is this code, which we use like this:

$roleHierarchy = $this->getContainer()->get('acme_demo.security.role_hierarchy_checker');
foreach ($users as $user) {
    if (!$roleHierarchy->check($user, 'ROLE_DEMO')) {
       continue;
    }
    // do things with the authorized user...
}
<?php
namespace Acme\DemoBundle\Security;
use Acme\DemoBundle\Entity\User;
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
use Symfony\Component\Security\Core\Authorization\Voter\RoleHierarchyVoter;
use Symfony\Component\Security\Core\Role\Role;
/**
* Convenience wrapper around the role hierarchy voter.
*/
class RoleHierarchyChecker extends RoleHierarchyVoter
{
/**
* Check whether a user is granted a specific role, respecting the role hierarchy.
*
* @return boolean Whether this user is granted the $requiredRole
*/
public function check(User $user, $requiredRole)
{
$roles = array();
foreach ($user->getRoles() as $roleName) {
$roles[] = new Role($roleName);
}
$token = new AnonymousToken('dummy', 'dummy', $roles);
return static::ACCESS_GRANTED == $this->vote($token, null, array($requiredRole));
}
}
acme_demo.security.role_hierarchy_checker:
class: Acme\DemoBundle\Security\RoleHierarchyChecker
arguments: [@security.role_hierarchy]
@javiereguiluz
Copy link

David, what do you think about creating a new DX (Developer Experience) issue in Symfony repository about this? I've been asked for this same feature some times, so adding it to the core of the framework could be useful for lots of people.

@dsbaars
Copy link

dsbaars commented Feb 22, 2015

You are my hero, I looked for a solution for long time. Needed it for group permission checking

    /**
     * Check whether a group is granted a specific role, respecting the role hierarchy.
     *
     * @return boolean Whether this group is granted the $requiredRole
     */
    public function checkGroup(Group $group, $requiredRole)
    {
        $roles = array();
        foreach ($group->getRoles() as $roleName) {
            $roles[] = new Role($roleName);
        }

        $token = new AnonymousToken('dummy', 'dummy', $roles);

        return static::ACCESS_GRANTED == $this->vote($token, null, array($requiredRole));
    }

Possibly related: http://symfony.com/blog/new-in-symfony-2-7-inherited-security-roles-in-the-web-profiler

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment