I'd like to be able to verify whether or not attributes (roles) are granted to any arbitrary object implementing UserInterface
in Symfony2. Is this possible?
UserInterface->getRoles()
is not suitable for my needs because it does not take the role hierarchy into account, and I'd rather not reinvent the wheel in that department, which is why I'd like to use the Access Decision Manager if possible.
Thanks.
In response to Olivier's solution below, here is my experience:
You can use the security.context service with the isGranted method. You can pass a second argument which is your object.
$user = new Core\Model\User();
var_dump($user->getRoles(), $this->get('security.context')->isGranted('ROLE_ADMIN', $user));
Output:
array (size=1)
0 => string 'ROLE_USER' (length=9)
boolean true
My role hierarchy:
role_hierarchy:
ROLE_USER: ~
ROLE_VERIFIED_USER: [ROLE_USER]
ROLE_ADMIN: [ROLE_VERIFIED_USER]
ROLE_SUPERADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
ROLE_ALLOWED_TO_SWITCH: ~
My UserInterface->getRoles()
method:
public function getRoles()
{
$roles = [$this->isVerified() ? 'ROLE_VERIFIED_USER' : 'ROLE_USER'];
/**
* @var UserSecurityRole $userSecurityRole
*/
foreach ($this->getUserSecurityRoles() as $userSecurityRole) {
$roles[] = $userSecurityRole->getRole();
}
return $roles;
}
ROLE_ADMIN
must be explicitly assigned, yet isGranted('ROLE_ADMIN', $user)
returns TRUE
even if the user was just created and has not been assigned any roles other than the default ROLE_USER
, as long as the currently logged in user is granted ROLE_ADMIN
. This leads me to believe the 2nd argument to isGranted()
is just ignored and that the Token
provided to AccessDecisionManager->decide()
by the SecurityContext
is used instead.
If this is a bug I'll submit a report, but maybe I'm still doing something wrong?
You need only AccessDecisionManager
for this, no need for security context since you don't need authentication.
$user = new Core\Model\User();
$token = new UsernamePasswordToken($user, 'none', 'none', $user->getRoles());
$isGranted = $this->get('security.access.decision_manager')
->decide($token, array('ROLE_ADMIN'));
This will correctly take role hierarchy into account, since RoleHierarchyVoter
is registered by default
Update
As noted by @redalaanait, security.access.decision_manager is a private service, so accessing it directly is not a good thing to do. It's better to use service aliasing, which allows you to access private services.
security.context
Is deprecated since 2.6.
Use AuthorizationChecker
:
$token = new UsernamePasswordToken(
$user,
null,
'secured_area',
$user->getRoles()
);
$tokenStorage = $this->container->get('security.token_storage');
$tokenStorage->setToken($token);
$authorizationChecker = new AuthorizationChecker(
$tokenStorage,
$this->container->get('security.authentication.manager'),
$this->container->get('security.access.decision_manager')
);
if (!$authorizationChecker->isGranted('ROLE_ADMIN')) {
throw new AccessDeniedException();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With