deprecate the Role and SwitchUserRole classes
This commit is contained in:
parent
fec0475e8c
commit
d7aaa615b9
@ -53,6 +53,13 @@ HttpFoundation
|
||||
Security
|
||||
--------
|
||||
|
||||
* The `Role` and `SwitchUserRole` classes are deprecated and will be removed in 5.0. Use strings for roles
|
||||
instead.
|
||||
* The `RoleHierarchyInterface` is deprecated and will be removed in 5.0.
|
||||
* The `getReachableRoles()` method of the `RoleHierarchy` class is deprecated and will be removed in 5.0.
|
||||
Use the `getReachableRoleNames()` method instead.
|
||||
* The `getRoles()` method of the `TokenInterface` is deprecated. Tokens must implement the `getRoleNames()`
|
||||
method instead and return roles as strings.
|
||||
* The `AbstractToken::serialize()`, `AbstractToken::unserialize()`,
|
||||
`AuthenticationException::serialize()` and `AuthenticationException::unserialize()`
|
||||
methods are now final, use `getState()` and `setState()` instead.
|
||||
|
@ -226,6 +226,11 @@ Process
|
||||
Security
|
||||
--------
|
||||
|
||||
* The `Role` and `SwitchUserRole` classes have been removed.
|
||||
* The `RoleHierarchyInterface` has been removed.
|
||||
* The `getReachableRoles()` method of the `RoleHierarchy` class has been removed.
|
||||
* The `getRoles()` method has been removed from the `TokenInterface`. It has been replaced by the new
|
||||
`getRoleNames()` method.
|
||||
* The `ContextListener::setLogoutOnUserChange()` method has been removed.
|
||||
* The `Symfony\Component\Security\Core\User\AdvancedUserInterface` has been removed.
|
||||
* The `ExpressionVoter::addExpressionLanguageProvider()` method has been removed.
|
||||
|
@ -31,10 +31,16 @@ class TokenProcessor
|
||||
{
|
||||
$records['extra']['token'] = null;
|
||||
if (null !== $token = $this->tokenStorage->getToken()) {
|
||||
if (method_exists($token, 'getRoleNames')) {
|
||||
$roles = $token->getRoleNames();
|
||||
} else {
|
||||
$roles = array_map(function ($role) { return $role->getRole(); }, $token->getRoles(false));
|
||||
}
|
||||
|
||||
$records['extra']['token'] = [
|
||||
'username' => $token->getUsername(),
|
||||
'authenticated' => $token->isAuthenticated(),
|
||||
'roles' => array_map(function ($role) { return $role->getRole(); }, $token->getRoles()),
|
||||
'roles' => $roles,
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,6 @@ class TokenProcessorTest extends TestCase
|
||||
$this->assertArrayHasKey('token', $record['extra']);
|
||||
$this->assertEquals($token->getUsername(), $record['extra']['token']['username']);
|
||||
$this->assertEquals($token->isAuthenticated(), $record['extra']['token']['authenticated']);
|
||||
$roles = array_map(function ($role) { return $role->getRole(); }, $token->getRoles());
|
||||
$this->assertEquals($roles, $record['extra']['token']['roles']);
|
||||
$this->assertEquals(['ROLE_USER'], $record['extra']['token']['roles']);
|
||||
}
|
||||
}
|
||||
|
@ -18,10 +18,12 @@ use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\DataCollector\DataCollector;
|
||||
use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
|
||||
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
|
||||
use Symfony\Component\Security\Core\Authorization\TraceableAccessDecisionManager;
|
||||
use Symfony\Component\Security\Core\Authorization\Voter\TraceableVoter;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Symfony\Component\Security\Core\Role\RoleHierarchy;
|
||||
use Symfony\Component\Security\Core\Role\RoleHierarchyInterface;
|
||||
use Symfony\Component\Security\Core\Role\SwitchUserRole;
|
||||
use Symfony\Component\Security\Http\Firewall\SwitchUserListener;
|
||||
@ -91,18 +93,32 @@ class SecurityDataCollector extends DataCollector implements LateDataCollectorIn
|
||||
];
|
||||
} else {
|
||||
$inheritedRoles = [];
|
||||
$assignedRoles = $token->getRoles();
|
||||
|
||||
if (method_exists($token, 'getRoleNames')) {
|
||||
$assignedRoles = $token->getRoleNames();
|
||||
} else {
|
||||
$assignedRoles = array_map(function (Role $role) { return $role->getRole(); }, $token->getRoles(false));
|
||||
}
|
||||
|
||||
$impersonatorUser = null;
|
||||
foreach ($assignedRoles as $role) {
|
||||
if ($role instanceof SwitchUserRole) {
|
||||
$impersonatorUser = $role->getSource()->getUsername();
|
||||
break;
|
||||
if ($token instanceof SwitchUserToken) {
|
||||
$impersonatorUser = $token->getOriginalToken()->getUsername();
|
||||
} else {
|
||||
foreach ($token->getRoles(false) as $role) {
|
||||
if ($role instanceof SwitchUserRole) {
|
||||
$impersonatorUser = $role->getSource()->getUsername();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (null !== $this->roleHierarchy) {
|
||||
$allRoles = $this->roleHierarchy->getReachableRoles($assignedRoles);
|
||||
if ($this->roleHierarchy instanceof RoleHierarchy) {
|
||||
$allRoles = $this->roleHierarchy->getReachableRoleNames($assignedRoles);
|
||||
} else {
|
||||
$allRoles = array_map(function (Role $role) { return (string) $role; }, $this->roleHierarchy->getReachableRoles($token->getRoles(false)));
|
||||
}
|
||||
|
||||
foreach ($allRoles as $role) {
|
||||
if (!\in_array($role, $assignedRoles, true)) {
|
||||
$inheritedRoles[] = $role;
|
||||
@ -129,8 +145,8 @@ class SecurityDataCollector extends DataCollector implements LateDataCollectorIn
|
||||
'token_class' => $this->hasVarDumper ? new ClassStub(\get_class($token)) : \get_class($token),
|
||||
'logout_url' => $logoutUrl,
|
||||
'user' => $token->getUsername(),
|
||||
'roles' => array_map(function (Role $role) { return $role->getRole(); }, $assignedRoles),
|
||||
'inherited_roles' => array_unique(array_map(function (Role $role) { return $role->getRole(); }, $inheritedRoles)),
|
||||
'roles' => $assignedRoles,
|
||||
'inherited_roles' => array_unique($inheritedRoles),
|
||||
'supports_role_hierarchy' => null !== $this->roleHierarchy,
|
||||
];
|
||||
}
|
||||
|
@ -98,6 +98,7 @@
|
||||
<argument>%security.role_hierarchy.roles%</argument>
|
||||
</service>
|
||||
<service id="Symfony\Component\Security\Core\Role\RoleHierarchyInterface" alias="security.role_hierarchy" />
|
||||
<service id="Symfony\Component\Security\Core\Role\RoleHierarchy" alias="security.role_hierarchy" />
|
||||
|
||||
|
||||
<!-- Security Voters -->
|
||||
|
@ -18,9 +18,12 @@ use Symfony\Bundle\SecurityBundle\Security\FirewallConfig;
|
||||
use Symfony\Bundle\SecurityBundle\Security\FirewallMap;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
|
||||
use Symfony\Component\Security\Core\Authorization\AccessDecisionManager;
|
||||
use Symfony\Component\Security\Core\Authorization\TraceableAccessDecisionManager;
|
||||
@ -38,7 +41,7 @@ class SecurityDataCollectorTest extends TestCase
|
||||
public function testCollectWhenSecurityIsDisabled()
|
||||
{
|
||||
$collector = new SecurityDataCollector();
|
||||
$collector->collect($this->getRequest(), $this->getResponse());
|
||||
$collector->collect(new Request(), new Response());
|
||||
|
||||
$this->assertSame('security', $collector->getName());
|
||||
$this->assertFalse($collector->isEnabled());
|
||||
@ -58,7 +61,7 @@ class SecurityDataCollectorTest extends TestCase
|
||||
{
|
||||
$tokenStorage = new TokenStorage();
|
||||
$collector = new SecurityDataCollector($tokenStorage, $this->getRoleHierarchy());
|
||||
$collector->collect($this->getRequest(), $this->getResponse());
|
||||
$collector->collect(new Request(), new Response());
|
||||
|
||||
$this->assertTrue($collector->isEnabled());
|
||||
$this->assertFalse($collector->isAuthenticated());
|
||||
@ -80,7 +83,7 @@ class SecurityDataCollectorTest extends TestCase
|
||||
$tokenStorage->setToken(new UsernamePasswordToken('hhamon', 'P4$$w0rD', 'provider', $roles));
|
||||
|
||||
$collector = new SecurityDataCollector($tokenStorage, $this->getRoleHierarchy());
|
||||
$collector->collect($this->getRequest(), $this->getResponse());
|
||||
$collector->collect(new Request(), new Response());
|
||||
$collector->lateCollect();
|
||||
|
||||
$this->assertTrue($collector->isEnabled());
|
||||
@ -95,6 +98,9 @@ class SecurityDataCollectorTest extends TestCase
|
||||
$this->assertSame('hhamon', $collector->getUser());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*/
|
||||
public function testCollectImpersonatedToken()
|
||||
{
|
||||
$adminToken = new UsernamePasswordToken('yceruto', 'P4$$w0rD', 'provider', ['ROLE_ADMIN']);
|
||||
@ -108,7 +114,7 @@ class SecurityDataCollectorTest extends TestCase
|
||||
$tokenStorage->setToken(new UsernamePasswordToken('hhamon', 'P4$$w0rD', 'provider', $userRoles));
|
||||
|
||||
$collector = new SecurityDataCollector($tokenStorage, $this->getRoleHierarchy());
|
||||
$collector->collect($this->getRequest(), $this->getResponse());
|
||||
$collector->collect(new Request(), new Response());
|
||||
$collector->lateCollect();
|
||||
|
||||
$this->assertTrue($collector->isEnabled());
|
||||
@ -122,10 +128,32 @@ class SecurityDataCollectorTest extends TestCase
|
||||
$this->assertSame('hhamon', $collector->getUser());
|
||||
}
|
||||
|
||||
public function testCollectSwitchUserToken()
|
||||
{
|
||||
$adminToken = new UsernamePasswordToken('yceruto', 'P4$$w0rD', 'provider', ['ROLE_ADMIN']);
|
||||
|
||||
$tokenStorage = new TokenStorage();
|
||||
$tokenStorage->setToken(new SwitchUserToken('hhamon', 'P4$$w0rD', 'provider', ['ROLE_USER', 'ROLE_PREVIOUS_ADMIN'], $adminToken));
|
||||
|
||||
$collector = new SecurityDataCollector($tokenStorage, $this->getRoleHierarchy());
|
||||
$collector->collect(new Request(), new Response());
|
||||
$collector->lateCollect();
|
||||
|
||||
$this->assertTrue($collector->isEnabled());
|
||||
$this->assertTrue($collector->isAuthenticated());
|
||||
$this->assertTrue($collector->isImpersonated());
|
||||
$this->assertSame('yceruto', $collector->getImpersonatorUser());
|
||||
$this->assertSame(SwitchUserToken::class, $collector->getTokenClass()->getValue());
|
||||
$this->assertTrue($collector->supportsRoleHierarchy());
|
||||
$this->assertSame(['ROLE_USER', 'ROLE_PREVIOUS_ADMIN'], $collector->getRoles()->getValue(true));
|
||||
$this->assertSame([], $collector->getInheritedRoles()->getValue(true));
|
||||
$this->assertSame('hhamon', $collector->getUser());
|
||||
}
|
||||
|
||||
public function testGetFirewall()
|
||||
{
|
||||
$firewallConfig = new FirewallConfig('dummy', 'security.request_matcher.dummy', 'security.user_checker.dummy');
|
||||
$request = $this->getRequest();
|
||||
$request = new Request();
|
||||
|
||||
$firewallMap = $this
|
||||
->getMockBuilder(FirewallMap::class)
|
||||
@ -138,7 +166,7 @@ class SecurityDataCollectorTest extends TestCase
|
||||
->willReturn($firewallConfig);
|
||||
|
||||
$collector = new SecurityDataCollector(null, null, null, null, $firewallMap, new TraceableFirewallListener($firewallMap, new EventDispatcher(), new LogoutUrlGenerator()));
|
||||
$collector->collect($request, $this->getResponse());
|
||||
$collector->collect($request, new Response());
|
||||
$collector->lateCollect();
|
||||
$collected = $collector->getFirewall();
|
||||
|
||||
@ -158,8 +186,8 @@ class SecurityDataCollectorTest extends TestCase
|
||||
|
||||
public function testGetFirewallReturnsNull()
|
||||
{
|
||||
$request = $this->getRequest();
|
||||
$response = $this->getResponse();
|
||||
$request = new Request();
|
||||
$response = new Response();
|
||||
|
||||
// Don't inject any firewall map
|
||||
$collector = new SecurityDataCollector();
|
||||
@ -192,9 +220,9 @@ class SecurityDataCollectorTest extends TestCase
|
||||
*/
|
||||
public function testGetListeners()
|
||||
{
|
||||
$request = $this->getRequest();
|
||||
$request = new Request();
|
||||
$event = new GetResponseEvent($this->getMockBuilder(HttpKernelInterface::class)->getMock(), $request, HttpKernelInterface::MASTER_REQUEST);
|
||||
$event->setResponse($response = $this->getResponse());
|
||||
$event->setResponse($response = new Response());
|
||||
$listener = $this->getMockBuilder(ListenerInterface::class)->getMock();
|
||||
$listener
|
||||
->expects($this->once())
|
||||
@ -345,7 +373,7 @@ class SecurityDataCollectorTest extends TestCase
|
||||
->willReturn($decisionLog);
|
||||
|
||||
$dataCollector = new SecurityDataCollector(null, null, null, $accessDecisionManager);
|
||||
$dataCollector->collect($this->getRequest(), $this->getResponse());
|
||||
$dataCollector->collect(new Request(), new Response());
|
||||
|
||||
$this->assertEquals($dataCollector->getAccessDecisionLog(), $expectedDecisionLog, 'Wrong value returned by getAccessDecisionLog');
|
||||
|
||||
@ -367,7 +395,7 @@ class SecurityDataCollectorTest extends TestCase
|
||||
[],
|
||||
],
|
||||
[
|
||||
[new Role('ROLE_USER')],
|
||||
[new Role('ROLE_USER', false)],
|
||||
['ROLE_USER'],
|
||||
[],
|
||||
],
|
||||
@ -378,7 +406,7 @@ class SecurityDataCollectorTest extends TestCase
|
||||
['ROLE_USER', 'ROLE_ALLOWED_TO_SWITCH'],
|
||||
],
|
||||
[
|
||||
[new Role('ROLE_ADMIN')],
|
||||
[new Role('ROLE_ADMIN', false)],
|
||||
['ROLE_ADMIN'],
|
||||
['ROLE_USER', 'ROLE_ALLOWED_TO_SWITCH'],
|
||||
],
|
||||
@ -397,20 +425,4 @@ class SecurityDataCollectorTest extends TestCase
|
||||
'ROLE_OPERATOR' => ['ROLE_USER'],
|
||||
]);
|
||||
}
|
||||
|
||||
private function getRequest()
|
||||
{
|
||||
return $this
|
||||
->getMockBuilder('Symfony\Component\HttpFoundation\Request')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
}
|
||||
|
||||
private function getResponse()
|
||||
{
|
||||
return $this
|
||||
->getMockBuilder('Symfony\Component\HttpFoundation\Response')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@
|
||||
"symfony/config": "^4.2",
|
||||
"symfony/dependency-injection": "^4.2",
|
||||
"symfony/http-kernel": "^4.1",
|
||||
"symfony/security-core": "~4.2",
|
||||
"symfony/security-core": "~4.3",
|
||||
"symfony/security-csrf": "~4.2",
|
||||
"symfony/security-guard": "~4.2",
|
||||
"symfony/security-http": "~4.2"
|
||||
|
@ -4,6 +4,13 @@ CHANGELOG
|
||||
4.3.0
|
||||
-----
|
||||
|
||||
* The `Role` and `SwitchUserRole` classes are deprecated and will be removed in 5.0. Use strings for roles
|
||||
instead.
|
||||
* The `RoleHierarchyInterface` is deprecated and will be removed in 5.0.
|
||||
* The `getReachableRoles()` method of the `RoleHierarchy` class is deprecated and will be removed in 5.0.
|
||||
Use the `getReachableRoleNames()` method instead.
|
||||
* The `getRoles()` method of the `TokenInterface` is deprecated. Tokens must implement the `getRoleNames()`
|
||||
method instead and return roles as strings.
|
||||
* Made the `serialize()` and `unserialize()` methods of `AbstractToken` and
|
||||
`AuthenticationException` final, use `getState()`/`setState()` instead
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
namespace Symfony\Component\Security\Core\Authentication\Provider;
|
||||
|
||||
use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
@ -87,7 +88,12 @@ abstract class UserAuthenticationProvider implements AuthenticationProviderInter
|
||||
throw $e;
|
||||
}
|
||||
|
||||
$authenticatedToken = new UsernamePasswordToken($user, $token->getCredentials(), $this->providerKey, $this->getRoles($user, $token));
|
||||
if ($token instanceof SwitchUserToken) {
|
||||
$authenticatedToken = new SwitchUserToken($user, $token->getCredentials(), $this->providerKey, $this->getRoles($user, $token), $token->getOriginalToken());
|
||||
} else {
|
||||
$authenticatedToken = new UsernamePasswordToken($user, $token->getCredentials(), $this->providerKey, $this->getRoles($user, $token));
|
||||
}
|
||||
|
||||
$authenticatedToken->setAttributes($token->getAttributes());
|
||||
|
||||
return $authenticatedToken;
|
||||
@ -110,7 +116,7 @@ abstract class UserAuthenticationProvider implements AuthenticationProviderInter
|
||||
{
|
||||
$roles = $user->getRoles();
|
||||
|
||||
foreach ($token->getRoles() as $role) {
|
||||
foreach ($token->getRoles(false) as $role) {
|
||||
if ($role instanceof SwitchUserRole) {
|
||||
$roles[] = $role;
|
||||
|
||||
|
@ -26,11 +26,12 @@ abstract class AbstractToken implements TokenInterface
|
||||
{
|
||||
private $user;
|
||||
private $roles = [];
|
||||
private $roleNames = [];
|
||||
private $authenticated = false;
|
||||
private $attributes = [];
|
||||
|
||||
/**
|
||||
* @param (Role|string)[] $roles An array of roles
|
||||
* @param string[] $roles An array of roles
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
@ -38,20 +39,30 @@ abstract class AbstractToken implements TokenInterface
|
||||
{
|
||||
foreach ($roles as $role) {
|
||||
if (\is_string($role)) {
|
||||
$role = new Role($role);
|
||||
$role = new Role($role, false);
|
||||
} elseif (!$role instanceof Role) {
|
||||
throw new \InvalidArgumentException(sprintf('$roles must be an array of strings, or Role instances, but got %s.', \gettype($role)));
|
||||
}
|
||||
|
||||
$this->roles[] = $role;
|
||||
$this->roleNames[] = (string) $role;
|
||||
}
|
||||
}
|
||||
|
||||
public function getRoleNames(): array
|
||||
{
|
||||
return $this->roleNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRoles()
|
||||
{
|
||||
if (0 === \func_num_args() || func_get_arg(0)) {
|
||||
@trigger_error(sprintf('The %s() method is deprecated since Symfony 4.3. Use the getRoleNames() method instead.', __METHOD__), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
return $this->roles;
|
||||
}
|
||||
|
||||
@ -172,7 +183,7 @@ abstract class AbstractToken implements TokenInterface
|
||||
*/
|
||||
protected function getState(): array
|
||||
{
|
||||
return [$this->user, $this->authenticated, $this->roles, $this->attributes];
|
||||
return [$this->user, $this->authenticated, $this->roles, $this->attributes, $this->roleNames];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -193,7 +204,7 @@ abstract class AbstractToken implements TokenInterface
|
||||
*/
|
||||
protected function setState(array $data)
|
||||
{
|
||||
[$this->user, $this->authenticated, $this->roles, $this->attributes] = $data;
|
||||
[$this->user, $this->authenticated, $this->roles, $this->attributes, $this->roleNames] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -225,7 +236,7 @@ abstract class AbstractToken implements TokenInterface
|
||||
*/
|
||||
public function hasAttribute($name)
|
||||
{
|
||||
return array_key_exists($name, $this->attributes);
|
||||
return \array_key_exists($name, $this->attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -239,7 +250,7 @@ abstract class AbstractToken implements TokenInterface
|
||||
*/
|
||||
public function getAttribute($name)
|
||||
{
|
||||
if (!array_key_exists($name, $this->attributes)) {
|
||||
if (!\array_key_exists($name, $this->attributes)) {
|
||||
throw new \InvalidArgumentException(sprintf('This token has no "%s" attribute.', $name));
|
||||
}
|
||||
|
||||
|
@ -11,8 +11,6 @@
|
||||
|
||||
namespace Symfony\Component\Security\Core\Authentication\Token;
|
||||
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
|
||||
/**
|
||||
* AnonymousToken represents an anonymous token.
|
||||
*
|
||||
@ -25,7 +23,7 @@ class AnonymousToken extends AbstractToken
|
||||
/**
|
||||
* @param string $secret A secret used to make sure the token is created by the app and not by a malicious client
|
||||
* @param string|object $user The user can be a UserInterface instance, or an object implementing a __toString method or the username as a regular string
|
||||
* @param Role[] $roles An array of roles
|
||||
* @param string[] $roles An array of roles
|
||||
*/
|
||||
public function __construct(string $secret, $user, array $roles = [])
|
||||
{
|
||||
|
@ -11,8 +11,6 @@
|
||||
|
||||
namespace Symfony\Component\Security\Core\Authentication\Token;
|
||||
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
|
||||
/**
|
||||
* PreAuthenticatedToken implements a pre-authenticated token.
|
||||
*
|
||||
@ -24,10 +22,10 @@ class PreAuthenticatedToken extends AbstractToken
|
||||
private $providerKey;
|
||||
|
||||
/**
|
||||
* @param string|object $user The user can be a UserInterface instance, or an object implementing a __toString method or the username as a regular string
|
||||
* @param mixed $credentials The user credentials
|
||||
* @param string $providerKey The provider key
|
||||
* @param (Role|string)[] $roles An array of roles
|
||||
* @param string|object $user The user can be a UserInterface instance, or an object implementing a __toString method or the username as a regular string
|
||||
* @param mixed $credentials The user credentials
|
||||
* @param string $providerKey The provider key
|
||||
* @param string[] $roles An array of roles
|
||||
*/
|
||||
public function __construct($user, $credentials, string $providerKey, array $roles = [])
|
||||
{
|
||||
|
@ -39,6 +39,10 @@ class TokenStorage implements TokenStorageInterface, ResetInterface
|
||||
*/
|
||||
public function setToken(TokenInterface $token = null)
|
||||
{
|
||||
if (null !== $token && !method_exists($token, 'getRoleNames')) {
|
||||
@trigger_error(sprintf('Not implementing the getRoleNames() method in %s which implements %s is deprecated since Symfony 4.3.', \get_class($token), TokenInterface::class), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
$this->token = $token;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Core\Authentication\Token;
|
||||
|
||||
/**
|
||||
* Token representing a user who temporarily impersonates another one.
|
||||
*
|
||||
* @author Christian Flothmann <christian.flothmann@sensiolabs.de>
|
||||
*/
|
||||
class SwitchUserToken extends UsernamePasswordToken
|
||||
{
|
||||
private $originalToken;
|
||||
|
||||
/**
|
||||
* @param string|object $user The username (like a nickname, email address, etc.), or a UserInterface instance or an object implementing a __toString method
|
||||
* @param mixed $credentials This usually is the password of the user
|
||||
* @param string $providerKey The provider key
|
||||
* @param string[] $roles An array of roles
|
||||
* @param TokenInterface $originalToken The token of the user who switched to the current user
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function __construct($user, $credentials, string $providerKey, array $roles = [], TokenInterface $originalToken)
|
||||
{
|
||||
parent::__construct($user, $credentials, $providerKey, $roles);
|
||||
|
||||
$this->originalToken = $originalToken;
|
||||
}
|
||||
|
||||
public function getOriginalToken(): TokenInterface
|
||||
{
|
||||
return $this->originalToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getState(): array
|
||||
{
|
||||
return [$this->originalToken, parent::getState()];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setState(array $data)
|
||||
{
|
||||
[$this->originalToken, $parentData] = $data;
|
||||
parent::setState($parentData);
|
||||
}
|
||||
}
|
@ -18,6 +18,8 @@ use Symfony\Component\Security\Core\Role\Role;
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*
|
||||
* @method string[] getRoleNames() The associated roles - not implementing it is deprecated since Symfony 4.3
|
||||
*/
|
||||
interface TokenInterface extends \Serializable
|
||||
{
|
||||
@ -34,6 +36,8 @@ interface TokenInterface extends \Serializable
|
||||
* Returns the user roles.
|
||||
*
|
||||
* @return Role[] An array of Role instances
|
||||
*
|
||||
* @deprecated since Symfony 4.3, use the getRoleNames() method instead
|
||||
*/
|
||||
public function getRoles();
|
||||
|
||||
|
@ -11,8 +11,6 @@
|
||||
|
||||
namespace Symfony\Component\Security\Core\Authentication\Token;
|
||||
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
|
||||
/**
|
||||
* UsernamePasswordToken implements a username and password token.
|
||||
*
|
||||
@ -24,10 +22,10 @@ class UsernamePasswordToken extends AbstractToken
|
||||
private $providerKey;
|
||||
|
||||
/**
|
||||
* @param string|object $user The username (like a nickname, email address, etc.), or a UserInterface instance or an object implementing a __toString method
|
||||
* @param mixed $credentials This usually is the password of the user
|
||||
* @param string $providerKey The provider key
|
||||
* @param (Role|string)[] $roles An array of roles
|
||||
* @param string|object $user The username (like a nickname, email address, etc.), or a UserInterface instance or an object implementing a __toString method
|
||||
* @param mixed $credentials This usually is the password of the user
|
||||
* @param string $providerKey The provider key
|
||||
* @param string[] $roles An array of roles
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
|
@ -18,6 +18,8 @@ use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverIn
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
|
||||
use Symfony\Component\Security\Core\Authorization\ExpressionLanguage;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Symfony\Component\Security\Core\Role\RoleHierarchy;
|
||||
use Symfony\Component\Security\Core\Role\RoleHierarchyInterface;
|
||||
|
||||
/**
|
||||
@ -90,18 +92,34 @@ class ExpressionVoter implements VoterInterface
|
||||
|
||||
private function getVariables(TokenInterface $token, $subject)
|
||||
{
|
||||
if (null !== $this->roleHierarchy) {
|
||||
$roles = $this->roleHierarchy->getReachableRoles($token->getRoles());
|
||||
if ($this->roleHierarchy instanceof RoleHierarchy) {
|
||||
if (method_exists($token, 'getRoleNames')) {
|
||||
$rolesFromToken = $token->getRoleNames();
|
||||
} else {
|
||||
@trigger_error(sprintf('Not implementing the getRoleNames() method in %s which implements %s is deprecated since Symfony 4.3.', \get_class($token), TokenInterface::class), E_USER_DEPRECATED);
|
||||
|
||||
$rolesFromToken = $token->getRoles(false);
|
||||
}
|
||||
|
||||
$roles = $this->roleHierarchy->getReachableRoleNames($rolesFromToken);
|
||||
} elseif (null !== $this->roleHierarchy) {
|
||||
$roles = $this->roleHierarchy->getReachableRoles($token->getRoles(false));
|
||||
} elseif (method_exists($token, 'getRoleNames')) {
|
||||
$roles = $token->getRoleNames();
|
||||
} else {
|
||||
$roles = $token->getRoles();
|
||||
@trigger_error(sprintf('Not implementing the getRoleNames() method in %s which implements %s is deprecated since Symfony 4.3.', \get_class($token), TokenInterface::class), E_USER_DEPRECATED);
|
||||
|
||||
$roles = $token->getRoles(false);
|
||||
}
|
||||
|
||||
$roles = array_map(function ($role) { return $role instanceof Role ? $role->getRole() : $role; }, $roles);
|
||||
|
||||
$variables = [
|
||||
'token' => $token,
|
||||
'user' => $token->getUser(),
|
||||
'object' => $subject,
|
||||
'subject' => $subject,
|
||||
'roles' => array_map(function ($role) { return $role->getRole(); }, $roles),
|
||||
'roles' => $roles,
|
||||
'trust_resolver' => $this->trustResolver,
|
||||
'auth_checker' => $this->authChecker,
|
||||
];
|
||||
|
@ -12,6 +12,7 @@
|
||||
namespace Symfony\Component\Security\Core\Authorization\Voter;
|
||||
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Role\RoleHierarchy;
|
||||
use Symfony\Component\Security\Core\Role\RoleHierarchyInterface;
|
||||
|
||||
/**
|
||||
@ -26,6 +27,10 @@ class RoleHierarchyVoter extends RoleVoter
|
||||
|
||||
public function __construct(RoleHierarchyInterface $roleHierarchy, string $prefix = 'ROLE_')
|
||||
{
|
||||
if (!$roleHierarchy instanceof RoleHierarchy) {
|
||||
@trigger_error(sprintf('Passing a role hierarchy to "%s" that is not an instance of "%s" is deprecated since Symfony 4.3 and support for it will be dropped in Symfony 5.0 ("%s" given).', __CLASS__, RoleHierarchy::class, \get_class($roleHierarchy)), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
$this->roleHierarchy = $roleHierarchy;
|
||||
|
||||
parent::__construct($prefix);
|
||||
@ -36,6 +41,18 @@ class RoleHierarchyVoter extends RoleVoter
|
||||
*/
|
||||
protected function extractRoles(TokenInterface $token)
|
||||
{
|
||||
return $this->roleHierarchy->getReachableRoles($token->getRoles());
|
||||
if ($this->roleHierarchy instanceof RoleHierarchy) {
|
||||
if (method_exists($token, 'getRoleNames')) {
|
||||
$roles = $token->getRoleNames();
|
||||
} else {
|
||||
@trigger_error(sprintf('Not implementing the getRoleNames() method in %s which implements %s is deprecated since Symfony 4.3.', \get_class($token), TokenInterface::class), E_USER_DEPRECATED);
|
||||
|
||||
$roles = $token->getRoles(false);
|
||||
}
|
||||
|
||||
return $this->roleHierarchy->getReachableRoleNames($roles);
|
||||
}
|
||||
|
||||
return $this->roleHierarchy->getReachableRoles($token->getRoles(false));
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ class RoleVoter implements VoterInterface
|
||||
|
||||
$result = VoterInterface::ACCESS_DENIED;
|
||||
foreach ($roles as $role) {
|
||||
if ($attribute === $role->getRole()) {
|
||||
if ($attribute === $role) {
|
||||
return VoterInterface::ACCESS_GRANTED;
|
||||
}
|
||||
}
|
||||
@ -58,6 +58,12 @@ class RoleVoter implements VoterInterface
|
||||
|
||||
protected function extractRoles(TokenInterface $token)
|
||||
{
|
||||
return $token->getRoles();
|
||||
if (method_exists($token, 'getRoleNames')) {
|
||||
return $token->getRoleNames();
|
||||
}
|
||||
|
||||
@trigger_error(sprintf('Not implementing the getRoleNames() method in %s which implements %s is deprecated since Symfony 4.3.', \get_class($token), TokenInterface::class), E_USER_DEPRECATED);
|
||||
|
||||
return array_map(function (Role $role) { return $role->getRole(); }, $token->getRoles(false));
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,8 @@ namespace Symfony\Component\Security\Core\Role;
|
||||
* Role is a simple implementation representing a role identified by a string.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @deprecated since Symfony 4.3, to be removed in 5.0. Use strings as roles instead.
|
||||
*/
|
||||
class Role
|
||||
{
|
||||
@ -22,6 +24,10 @@ class Role
|
||||
|
||||
public function __construct(string $role)
|
||||
{
|
||||
if (\func_num_args() < 2 || func_get_arg(1)) {
|
||||
@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3 and will be removed in 5.0. Use strings as roles instead.', __CLASS__), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
$this->role = $role;
|
||||
}
|
||||
|
||||
@ -34,4 +40,9 @@ class Role
|
||||
{
|
||||
return $this->role;
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->role;
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,8 @@ class RoleHierarchy implements RoleHierarchyInterface
|
||||
*/
|
||||
public function getReachableRoles(array $roles)
|
||||
{
|
||||
@trigger_error(sprintf('The %s() method is deprecated since Symfony 4.3 and will be removed in 5.0. Use roles as strings and the getReachableRoleNames() method instead.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
$reachableRoles = $roles;
|
||||
foreach ($roles as $role) {
|
||||
if (!isset($this->map[$role->getRole()])) {
|
||||
@ -50,6 +52,37 @@ class RoleHierarchy implements RoleHierarchyInterface
|
||||
return $reachableRoles;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $roles
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function getReachableRoleNames(array $roles): array
|
||||
{
|
||||
$reachableRoles = $roles = array_map(
|
||||
function ($role) {
|
||||
if ($role instanceof Role) {
|
||||
return $role->getRole();
|
||||
}
|
||||
|
||||
return $role;
|
||||
},
|
||||
$roles
|
||||
);
|
||||
|
||||
foreach ($roles as $role) {
|
||||
if (!isset($this->map[$role])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($this->map[$role] as $r) {
|
||||
$reachableRoles[] = $r;
|
||||
}
|
||||
}
|
||||
|
||||
return $reachableRoles;
|
||||
}
|
||||
|
||||
protected function buildRoleMap()
|
||||
{
|
||||
$this->map = [];
|
||||
|
@ -15,6 +15,8 @@ namespace Symfony\Component\Security\Core\Role;
|
||||
* RoleHierarchyInterface is the interface for a role hierarchy.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @deprecated since Symfony 4.3, to be removed in 5.0.
|
||||
*/
|
||||
interface RoleHierarchyInterface
|
||||
{
|
||||
|
@ -18,9 +18,12 @@ use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
* another one.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @deprecated since version 4.3, to be removed in 5.0. Use strings as roles instead.
|
||||
*/
|
||||
class SwitchUserRole extends Role
|
||||
{
|
||||
private $deprecationTriggered = false;
|
||||
private $source;
|
||||
|
||||
/**
|
||||
@ -29,7 +32,13 @@ class SwitchUserRole extends Role
|
||||
*/
|
||||
public function __construct(string $role, TokenInterface $source)
|
||||
{
|
||||
parent::__construct($role);
|
||||
if ($triggerDeprecation = \func_num_args() < 3 || func_get_arg(2)) {
|
||||
@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3 and will be removed in 5.0. Use strings as roles instead.', __CLASS__), E_USER_DEPRECATED);
|
||||
|
||||
$this->deprecationTriggered = true;
|
||||
}
|
||||
|
||||
parent::__construct($role, $triggerDeprecation);
|
||||
|
||||
$this->source = $source;
|
||||
}
|
||||
@ -41,6 +50,12 @@ class SwitchUserRole extends Role
|
||||
*/
|
||||
public function getSource()
|
||||
{
|
||||
if (!$this->deprecationTriggered && (\func_num_args() < 1 || func_get_arg(0))) {
|
||||
@trigger_error(sprintf('The "%s" class is deprecated since version 4.3 and will be removed in 5.0. Use strings as roles instead.', __CLASS__), E_USER_DEPRECATED);
|
||||
|
||||
$this->deprecationTriggered = true;
|
||||
}
|
||||
|
||||
return $this->source;
|
||||
}
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ class PreAuthenticatedAuthenticationProviderTest extends TestCase
|
||||
$this->assertInstanceOf('Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken', $token);
|
||||
$this->assertEquals('pass', $token->getCredentials());
|
||||
$this->assertEquals('key', $token->getProviderKey());
|
||||
$this->assertEquals([], $token->getRoles());
|
||||
$this->assertEquals([], $token->getRoleNames());
|
||||
$this->assertEquals(['foo' => 'bar'], $token->getAttributes(), '->authenticate() copies token attributes');
|
||||
$this->assertSame($user, $token->getUser());
|
||||
}
|
||||
|
@ -14,7 +14,6 @@ namespace Symfony\Component\Security\Core\Tests\Authentication\Provider;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Security\Core\Authentication\Provider\RememberMeAuthenticationProvider;
|
||||
use Symfony\Component\Security\Core\Exception\DisabledException;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
|
||||
class RememberMeAuthenticationProviderTest extends TestCase
|
||||
{
|
||||
@ -78,7 +77,7 @@ class RememberMeAuthenticationProviderTest extends TestCase
|
||||
|
||||
$this->assertInstanceOf('Symfony\Component\Security\Core\Authentication\Token\RememberMeToken', $authToken);
|
||||
$this->assertSame($user, $authToken->getUser());
|
||||
$this->assertEquals([new Role('ROLE_FOO')], $authToken->getRoles());
|
||||
$this->assertEquals(['ROLE_FOO'], $authToken->getRoleNames());
|
||||
$this->assertEquals('', $authToken->getCredentials());
|
||||
}
|
||||
|
||||
|
@ -12,11 +12,11 @@
|
||||
namespace Symfony\Component\Security\Core\Tests\Authentication\Provider;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
|
||||
use Symfony\Component\Security\Core\Exception\AccountExpiredException;
|
||||
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
|
||||
use Symfony\Component\Security\Core\Exception\CredentialsExpiredException;
|
||||
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Symfony\Component\Security\Core\Role\SwitchUserRole;
|
||||
|
||||
class UserAuthenticationProviderTest extends TestCase
|
||||
@ -189,11 +189,14 @@ class UserAuthenticationProviderTest extends TestCase
|
||||
|
||||
$this->assertInstanceOf('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', $authToken);
|
||||
$this->assertSame($user, $authToken->getUser());
|
||||
$this->assertEquals([new Role('ROLE_FOO')], $authToken->getRoles());
|
||||
$this->assertEquals(['ROLE_FOO'], $authToken->getRoleNames());
|
||||
$this->assertEquals('foo', $authToken->getCredentials());
|
||||
$this->assertEquals(['foo' => 'bar'], $authToken->getAttributes(), '->authenticate() copies token attributes');
|
||||
}
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*/
|
||||
public function testAuthenticateWithPreservingRoleSwitchUserRole()
|
||||
{
|
||||
$user = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')->getMock();
|
||||
@ -224,12 +227,40 @@ class UserAuthenticationProviderTest extends TestCase
|
||||
|
||||
$this->assertInstanceOf('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', $authToken);
|
||||
$this->assertSame($user, $authToken->getUser());
|
||||
$this->assertContains(new Role('ROLE_FOO'), $authToken->getRoles(), '', false, false);
|
||||
$this->assertContains('ROLE_FOO', $authToken->getRoleNames(), '', false, false);
|
||||
$this->assertContains($switchUserRole, $authToken->getRoles(), '', false, false);
|
||||
$this->assertEquals('foo', $authToken->getCredentials());
|
||||
$this->assertEquals(['foo' => 'bar'], $authToken->getAttributes(), '->authenticate() copies token attributes');
|
||||
}
|
||||
|
||||
public function testAuthenticatePreservesOriginalToken()
|
||||
{
|
||||
$user = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')->getMock();
|
||||
$user->expects($this->once())
|
||||
->method('getRoles')
|
||||
->will($this->returnValue(['ROLE_FOO']))
|
||||
;
|
||||
|
||||
$provider = $this->getProvider();
|
||||
$provider->expects($this->once())
|
||||
->method('retrieveUser')
|
||||
->will($this->returnValue($user))
|
||||
;
|
||||
|
||||
$originalToken = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock();
|
||||
$token = new SwitchUserToken($this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')->getMock(), 'foo', 'key', [], $originalToken);
|
||||
$token->setAttributes(['foo' => 'bar']);
|
||||
|
||||
$authToken = $provider->authenticate($token);
|
||||
|
||||
$this->assertInstanceOf(SwitchUserToken::class, $authToken);
|
||||
$this->assertSame($originalToken, $authToken->getOriginalToken());
|
||||
$this->assertSame($user, $authToken->getUser());
|
||||
$this->assertContains('ROLE_FOO', $authToken->getRoleNames(), '', false, false);
|
||||
$this->assertEquals('foo', $authToken->getCredentials());
|
||||
$this->assertEquals(['foo' => 'bar'], $authToken->getAttributes(), '->authenticate() copies token attributes');
|
||||
}
|
||||
|
||||
protected function getSupportedToken()
|
||||
{
|
||||
$mock = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken')->setMethods(['getCredentials', 'getProviderKey', 'getRoles'])->disableOriginalConstructor()->getMock();
|
||||
|
@ -14,61 +14,14 @@ namespace Symfony\Component\Security\Core\Tests\Authentication\Token;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\AbstractToken;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Symfony\Component\Security\Core\Role\SwitchUserRole;
|
||||
use Symfony\Component\Security\Core\User\User;
|
||||
|
||||
class TestUser
|
||||
{
|
||||
protected $name;
|
||||
|
||||
public function __construct($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
}
|
||||
|
||||
class ConcreteToken extends AbstractToken
|
||||
{
|
||||
private $credentials = 'credentials_value';
|
||||
|
||||
public function __construct($user, array $roles = [])
|
||||
{
|
||||
parent::__construct($roles);
|
||||
|
||||
$this->setUser($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
$serialized = [$this->credentials, parent::serialize(true)];
|
||||
|
||||
return $this->doSerialize($serialized, \func_num_args() ? \func_get_arg(0) : null);
|
||||
}
|
||||
|
||||
public function unserialize($serialized)
|
||||
{
|
||||
list($this->credentials, $parentStr) = unserialize($serialized);
|
||||
parent::unserialize($parentStr);
|
||||
}
|
||||
|
||||
public function getCredentials()
|
||||
{
|
||||
}
|
||||
}
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
|
||||
class AbstractTokenTest extends TestCase
|
||||
{
|
||||
public function testGetUsername()
|
||||
{
|
||||
$token = $this->getToken(['ROLE_FOO']);
|
||||
$token = new ConcreteToken(['ROLE_FOO']);
|
||||
$token->setUser('fabien');
|
||||
$this->assertEquals('fabien', $token->getUsername());
|
||||
|
||||
@ -83,7 +36,7 @@ class AbstractTokenTest extends TestCase
|
||||
|
||||
public function testEraseCredentials()
|
||||
{
|
||||
$token = $this->getToken(['ROLE_FOO']);
|
||||
$token = new ConcreteToken(['ROLE_FOO']);
|
||||
|
||||
$user = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')->getMock();
|
||||
$user->expects($this->once())->method('eraseCredentials');
|
||||
@ -94,19 +47,22 @@ class AbstractTokenTest extends TestCase
|
||||
|
||||
public function testSerialize()
|
||||
{
|
||||
$token = $this->getToken(['ROLE_FOO', new Role('ROLE_BAR')]);
|
||||
$token = new ConcreteToken(['ROLE_FOO', new Role('ROLE_BAR', false)]);
|
||||
$token->setAttributes(['foo' => 'bar']);
|
||||
|
||||
$uToken = unserialize(serialize($token));
|
||||
|
||||
$this->assertEquals($token->getRoles(), $uToken->getRoles());
|
||||
$this->assertEquals($token->getRoleNames(), $uToken->getRoleNames());
|
||||
$this->assertEquals($token->getAttributes(), $uToken->getAttributes());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*/
|
||||
public function testSerializeWithRoleObjects()
|
||||
{
|
||||
$user = new User('name', 'password', [new Role('ROLE_FOO'), new Role('ROLE_BAR')]);
|
||||
$token = new ConcreteToken($user, $user->getRoles());
|
||||
$token = new ConcreteToken($user->getRoles(), $user);
|
||||
|
||||
$serialized = serialize($token);
|
||||
$unserialized = unserialize($serialized);
|
||||
@ -116,35 +72,42 @@ class AbstractTokenTest extends TestCase
|
||||
$this->assertEquals($roles, $user->getRoles());
|
||||
}
|
||||
|
||||
public function testSerializeParent()
|
||||
{
|
||||
$user = new TestUser('fabien');
|
||||
$token = new ConcreteToken($user, ['ROLE_FOO']);
|
||||
|
||||
$parentToken = new ConcreteToken($user, [new SwitchUserRole('ROLE_PREVIOUS', $token)]);
|
||||
$uToken = unserialize(serialize($parentToken));
|
||||
|
||||
$this->assertEquals(
|
||||
current($parentToken->getRoles())->getSource()->getUser(),
|
||||
current($uToken->getRoles())->getSource()->getUser()
|
||||
);
|
||||
}
|
||||
|
||||
public function testConstructor()
|
||||
{
|
||||
$token = $this->getToken(['ROLE_FOO']);
|
||||
$token = new ConcreteToken(['ROLE_FOO']);
|
||||
$this->assertEquals(['ROLE_FOO'], $token->getRoleNames());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*/
|
||||
public function testConstructorWithRoleObjects()
|
||||
{
|
||||
$token = new ConcreteToken([new Role('ROLE_FOO')]);
|
||||
$this->assertEquals(['ROLE_FOO'], $token->getRoleNames());
|
||||
|
||||
$token = new ConcreteToken([new Role('ROLE_FOO'), 'ROLE_BAR']);
|
||||
$this->assertEquals(['ROLE_FOO', 'ROLE_BAR'], $token->getRoleNames());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*/
|
||||
public function testGetRoles()
|
||||
{
|
||||
$token = new ConcreteToken(['ROLE_FOO']);
|
||||
$this->assertEquals([new Role('ROLE_FOO')], $token->getRoles());
|
||||
|
||||
$token = $this->getToken([new Role('ROLE_FOO')]);
|
||||
$token = new ConcreteToken([new Role('ROLE_FOO')]);
|
||||
$this->assertEquals([new Role('ROLE_FOO')], $token->getRoles());
|
||||
|
||||
$token = $this->getToken([new Role('ROLE_FOO'), 'ROLE_BAR']);
|
||||
$token = new ConcreteToken([new Role('ROLE_FOO'), 'ROLE_BAR']);
|
||||
$this->assertEquals([new Role('ROLE_FOO'), new Role('ROLE_BAR')], $token->getRoles());
|
||||
}
|
||||
|
||||
public function testAuthenticatedFlag()
|
||||
{
|
||||
$token = $this->getToken();
|
||||
$token = new ConcreteToken();
|
||||
$this->assertFalse($token->isAuthenticated());
|
||||
|
||||
$token->setAuthenticated(true);
|
||||
@ -157,7 +120,7 @@ class AbstractTokenTest extends TestCase
|
||||
public function testAttributes()
|
||||
{
|
||||
$attributes = ['foo' => 'bar'];
|
||||
$token = $this->getToken();
|
||||
$token = new ConcreteToken();
|
||||
$token->setAttributes($attributes);
|
||||
|
||||
$this->assertEquals($attributes, $token->getAttributes(), '->getAttributes() returns the token attributes');
|
||||
@ -181,7 +144,7 @@ class AbstractTokenTest extends TestCase
|
||||
*/
|
||||
public function testSetUser($user)
|
||||
{
|
||||
$token = $this->getToken();
|
||||
$token = new ConcreteToken();
|
||||
$token->setUser($user);
|
||||
$this->assertSame($user, $token->getUser());
|
||||
}
|
||||
@ -202,7 +165,7 @@ class AbstractTokenTest extends TestCase
|
||||
*/
|
||||
public function testSetUserSetsAuthenticatedToFalseWhenUserChanges($firstUser, $secondUser)
|
||||
{
|
||||
$token = $this->getToken();
|
||||
$token = new ConcreteToken();
|
||||
$token->setAuthenticated(true);
|
||||
$this->assertTrue($token->isAuthenticated());
|
||||
|
||||
@ -236,7 +199,7 @@ class AbstractTokenTest extends TestCase
|
||||
*/
|
||||
public function testSetUserSetsAuthenticatedToFalseWhenUserChangesAdvancedUser($firstUser, $secondUser)
|
||||
{
|
||||
$token = $this->getToken();
|
||||
$token = new ConcreteToken();
|
||||
$token->setAuthenticated(true);
|
||||
$this->assertTrue($token->isAuthenticated());
|
||||
|
||||
@ -275,7 +238,7 @@ class AbstractTokenTest extends TestCase
|
||||
*/
|
||||
public function testSetUserDoesNotSetAuthenticatedToFalseWhenUserDoesNotChange($user)
|
||||
{
|
||||
$token = $this->getToken();
|
||||
$token = new ConcreteToken();
|
||||
$token->setAuthenticated(true);
|
||||
$this->assertTrue($token->isAuthenticated());
|
||||
|
||||
@ -285,9 +248,48 @@ class AbstractTokenTest extends TestCase
|
||||
$token->setUser($user);
|
||||
$this->assertTrue($token->isAuthenticated());
|
||||
}
|
||||
}
|
||||
|
||||
protected function getToken(array $roles = [])
|
||||
class TestUser
|
||||
{
|
||||
protected $name;
|
||||
|
||||
public function __construct($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
}
|
||||
|
||||
class ConcreteToken extends AbstractToken
|
||||
{
|
||||
private $credentials = 'credentials_value';
|
||||
|
||||
public function __construct(array $roles = [], UserInterface $user = null)
|
||||
{
|
||||
parent::__construct($roles);
|
||||
|
||||
if (null !== $user) {
|
||||
$this->setUser($user);
|
||||
}
|
||||
}
|
||||
|
||||
public function serialize()
|
||||
{
|
||||
return serialize([$this->credentials, parent::serialize()]);
|
||||
}
|
||||
|
||||
public function unserialize($serialized)
|
||||
{
|
||||
list($this->credentials, $parentStr) = unserialize($serialized);
|
||||
parent::unserialize($parentStr);
|
||||
}
|
||||
|
||||
public function getCredentials()
|
||||
{
|
||||
return $this->getMockForAbstractClass('Symfony\Component\Security\Core\Authentication\Token\AbstractToken', [$roles]);
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,6 @@ namespace Symfony\Component\Security\Core\Tests\Authentication\Token;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
|
||||
class AnonymousTokenTest extends TestCase
|
||||
{
|
||||
@ -23,7 +22,7 @@ class AnonymousTokenTest extends TestCase
|
||||
$this->assertTrue($token->isAuthenticated());
|
||||
|
||||
$token = new AnonymousToken('foo', 'bar', ['ROLE_FOO']);
|
||||
$this->assertEquals([new Role('ROLE_FOO')], $token->getRoles());
|
||||
$this->assertEquals(['ROLE_FOO'], $token->getRoleNames());
|
||||
}
|
||||
|
||||
public function testGetKey()
|
||||
|
@ -13,7 +13,6 @@ namespace Symfony\Component\Security\Core\Tests\Authentication\Token;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
|
||||
class PreAuthenticatedTokenTest extends TestCase
|
||||
{
|
||||
@ -24,7 +23,7 @@ class PreAuthenticatedTokenTest extends TestCase
|
||||
|
||||
$token = new PreAuthenticatedToken('foo', 'bar', 'key', ['ROLE_FOO']);
|
||||
$this->assertTrue($token->isAuthenticated());
|
||||
$this->assertEquals([new Role('ROLE_FOO')], $token->getRoles());
|
||||
$this->assertEquals(['ROLE_FOO'], $token->getRoleNames());
|
||||
$this->assertEquals('key', $token->getProviderKey());
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,6 @@ namespace Symfony\Component\Security\Core\Tests\Authentication\Token;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\RememberMeToken;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
|
||||
class RememberMeTokenTest extends TestCase
|
||||
{
|
||||
@ -24,7 +23,7 @@ class RememberMeTokenTest extends TestCase
|
||||
|
||||
$this->assertEquals('fookey', $token->getProviderKey());
|
||||
$this->assertEquals('foo', $token->getSecret());
|
||||
$this->assertEquals([new Role('ROLE_FOO')], $token->getRoles());
|
||||
$this->assertEquals(['ROLE_FOO'], $token->getRoleNames());
|
||||
$this->assertSame($user, $token->getUser());
|
||||
$this->assertTrue($token->isAuthenticated());
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ namespace Symfony\Component\Security\Core\Tests\Authentication\Token\Storage;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
|
||||
|
||||
class TokenStorageTest extends TestCase
|
||||
{
|
||||
@ -20,7 +21,7 @@ class TokenStorageTest extends TestCase
|
||||
{
|
||||
$tokenStorage = new TokenStorage();
|
||||
$this->assertNull($tokenStorage->getToken());
|
||||
$token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock();
|
||||
$token = new UsernamePasswordToken('username', 'password', 'provider');
|
||||
$tokenStorage->setToken($token);
|
||||
$this->assertSame($token, $tokenStorage->getToken());
|
||||
}
|
||||
|
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Core\Tests\Authentication\Token;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
|
||||
|
||||
class SwitchUserTokenTest extends TestCase
|
||||
{
|
||||
public function testSerialize()
|
||||
{
|
||||
$originalToken = new UsernamePasswordToken('user', 'foo', 'provider-key', ['ROLE_ADMIN', 'ROLE_ALLOWED_TO_SWITCH']);
|
||||
$token = new SwitchUserToken('admin', 'bar', 'provider-key', ['ROLE_USER'], $originalToken);
|
||||
|
||||
$unserializedToken = unserialize(serialize($token));
|
||||
|
||||
$this->assertInstanceOf(SwitchUserToken::class, $unserializedToken);
|
||||
$this->assertSame('admin', $unserializedToken->getUsername());
|
||||
$this->assertSame('bar', $unserializedToken->getCredentials());
|
||||
$this->assertSame('provider-key', $unserializedToken->getProviderKey());
|
||||
$this->assertEquals(['ROLE_USER'], $unserializedToken->getRoleNames());
|
||||
|
||||
$unserializedOriginalToken = $unserializedToken->getOriginalToken();
|
||||
|
||||
$this->assertInstanceOf(UsernamePasswordToken::class, $unserializedOriginalToken);
|
||||
$this->assertSame('user', $unserializedOriginalToken->getUsername());
|
||||
$this->assertSame('foo', $unserializedOriginalToken->getCredentials());
|
||||
$this->assertSame('provider-key', $unserializedOriginalToken->getProviderKey());
|
||||
$this->assertEquals(['ROLE_ADMIN', 'ROLE_ALLOWED_TO_SWITCH'], $unserializedOriginalToken->getRoleNames());
|
||||
}
|
||||
}
|
@ -13,7 +13,6 @@ namespace Symfony\Component\Security\Core\Tests\Authentication\Token;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
|
||||
class UsernamePasswordTokenTest extends TestCase
|
||||
{
|
||||
@ -23,7 +22,7 @@ class UsernamePasswordTokenTest extends TestCase
|
||||
$this->assertFalse($token->isAuthenticated());
|
||||
|
||||
$token = new UsernamePasswordToken('foo', 'bar', 'key', ['ROLE_FOO']);
|
||||
$this->assertEquals([new Role('ROLE_FOO')], $token->getRoles());
|
||||
$this->assertEquals(['ROLE_FOO'], $token->getRoleNames());
|
||||
$this->assertTrue($token->isAuthenticated());
|
||||
$this->assertEquals('key', $token->getProviderKey());
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ namespace Symfony\Component\Security\Core\Tests\Authorization;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
|
||||
use Symfony\Component\Security\Core\Authorization\AuthorizationChecker;
|
||||
|
||||
class AuthorizationCheckerTest extends TestCase
|
||||
@ -37,10 +38,10 @@ class AuthorizationCheckerTest extends TestCase
|
||||
|
||||
public function testVoteAuthenticatesTokenIfNecessary()
|
||||
{
|
||||
$token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock();
|
||||
$token = new UsernamePasswordToken('username', 'password', 'provider');
|
||||
$this->tokenStorage->setToken($token);
|
||||
|
||||
$newToken = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock();
|
||||
$newToken = new UsernamePasswordToken('username', 'password', 'provider');
|
||||
|
||||
$this->authenticationManager
|
||||
->expects($this->once())
|
||||
@ -79,11 +80,7 @@ class AuthorizationCheckerTest extends TestCase
|
||||
*/
|
||||
public function testIsGranted($decide)
|
||||
{
|
||||
$token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock();
|
||||
$token
|
||||
->expects($this->once())
|
||||
->method('isAuthenticated')
|
||||
->will($this->returnValue(true));
|
||||
$token = new UsernamePasswordToken('username', 'password', 'provider', ['ROLE_USER']);
|
||||
|
||||
$this->accessDecisionManager
|
||||
->expects($this->once())
|
||||
|
@ -12,6 +12,7 @@
|
||||
namespace Symfony\Component\Security\Core\Tests\Authorization\Voter;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\AbstractToken;
|
||||
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
|
||||
use Symfony\Component\Security\Core\Authorization\Voter\ExpressionVoter;
|
||||
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
|
||||
@ -20,6 +21,7 @@ use Symfony\Component\Security\Core\Role\Role;
|
||||
class ExpressionVoterTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @group legacy
|
||||
* @dataProvider getVoteTests
|
||||
*/
|
||||
public function testVote($roles, $attributes, $expected, $tokenExpectsGetRoles = true, $expressionLanguageExpectsEvaluate = true)
|
||||
@ -29,6 +31,16 @@ class ExpressionVoterTest extends TestCase
|
||||
$this->assertSame($expected, $voter->vote($this->getToken($roles, $tokenExpectsGetRoles), null, $attributes));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getVoteTests
|
||||
*/
|
||||
public function testVoteWithTokenThatReturnsRoleNames($roles, $attributes, $expected, $tokenExpectsGetRoles = true, $expressionLanguageExpectsEvaluate = true)
|
||||
{
|
||||
$voter = new ExpressionVoter($this->createExpressionLanguage($expressionLanguageExpectsEvaluate), $this->createTrustResolver(), $this->createAuthorizationChecker());
|
||||
|
||||
$this->assertSame($expected, $voter->vote($this->getTokenWithRoleNames($roles, $tokenExpectsGetRoles), null, $attributes));
|
||||
}
|
||||
|
||||
public function getVoteTests()
|
||||
{
|
||||
return [
|
||||
@ -58,6 +70,19 @@ class ExpressionVoterTest extends TestCase
|
||||
return $token;
|
||||
}
|
||||
|
||||
protected function getTokenWithRoleNames(array $roles, $tokenExpectsGetRoles = true)
|
||||
{
|
||||
$token = $this->getMockBuilder(AbstractToken::class)->getMock();
|
||||
|
||||
if ($tokenExpectsGetRoles) {
|
||||
$token->expects($this->once())
|
||||
->method('getRoleNames')
|
||||
->will($this->returnValue($roles));
|
||||
}
|
||||
|
||||
return $token;
|
||||
}
|
||||
|
||||
protected function createExpressionLanguage($expressionLanguageExpectsEvaluate = true)
|
||||
{
|
||||
$mock = $this->getMockBuilder('Symfony\Component\Security\Core\Authorization\ExpressionLanguage')->getMock();
|
||||
|
@ -18,6 +18,7 @@ use Symfony\Component\Security\Core\Role\RoleHierarchy;
|
||||
class RoleHierarchyVoterTest extends RoleVoterTest
|
||||
{
|
||||
/**
|
||||
* @group legacy
|
||||
* @dataProvider getVoteTests
|
||||
*/
|
||||
public function testVote($roles, $attributes, $expected)
|
||||
@ -27,6 +28,16 @@ class RoleHierarchyVoterTest extends RoleVoterTest
|
||||
$this->assertSame($expected, $voter->vote($this->getToken($roles), null, $attributes));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getVoteTests
|
||||
*/
|
||||
public function testVoteUsingTokenThatReturnsRoleNames($roles, $attributes, $expected)
|
||||
{
|
||||
$voter = new RoleHierarchyVoter(new RoleHierarchy(['ROLE_FOO' => ['ROLE_FOOBAR']]));
|
||||
|
||||
$this->assertSame($expected, $voter->vote($this->getTokenWithRoleNames($roles), null, $attributes));
|
||||
}
|
||||
|
||||
public function getVoteTests()
|
||||
{
|
||||
return array_merge(parent::getVoteTests(), [
|
||||
@ -35,6 +46,18 @@ class RoleHierarchyVoterTest extends RoleVoterTest
|
||||
}
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
* @dataProvider getLegacyVoteOnRoleObjectsTests
|
||||
*/
|
||||
public function testVoteOnRoleObjects($roles, $attributes, $expected)
|
||||
{
|
||||
$voter = new RoleHierarchyVoter(new RoleHierarchy(['ROLE_FOO' => ['ROLE_FOOBAR']]));
|
||||
|
||||
$this->assertSame($expected, $voter->vote($this->getToken($roles), null, $attributes));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
* @dataProvider getVoteWithEmptyHierarchyTests
|
||||
*/
|
||||
public function testVoteWithEmptyHierarchy($roles, $attributes, $expected)
|
||||
@ -44,6 +67,16 @@ class RoleHierarchyVoterTest extends RoleVoterTest
|
||||
$this->assertSame($expected, $voter->vote($this->getToken($roles), null, $attributes));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getVoteWithEmptyHierarchyTests
|
||||
*/
|
||||
public function testVoteWithEmptyHierarchyUsingTokenThatReturnsRoleNames($roles, $attributes, $expected)
|
||||
{
|
||||
$voter = new RoleHierarchyVoter(new RoleHierarchy([]));
|
||||
|
||||
$this->assertSame($expected, $voter->vote($this->getTokenWithRoleNames($roles), null, $attributes));
|
||||
}
|
||||
|
||||
public function getVoteWithEmptyHierarchyTests()
|
||||
{
|
||||
return parent::getVoteTests();
|
||||
|
@ -12,6 +12,7 @@
|
||||
namespace Symfony\Component\Security\Core\Tests\Authorization\Voter;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\AbstractToken;
|
||||
use Symfony\Component\Security\Core\Authorization\Voter\RoleVoter;
|
||||
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
@ -19,6 +20,7 @@ use Symfony\Component\Security\Core\Role\Role;
|
||||
class RoleVoterTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @group legacy
|
||||
* @dataProvider getVoteTests
|
||||
*/
|
||||
public function testVote($roles, $attributes, $expected)
|
||||
@ -28,6 +30,16 @@ class RoleVoterTest extends TestCase
|
||||
$this->assertSame($expected, $voter->vote($this->getToken($roles), null, $attributes));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getVoteTests
|
||||
*/
|
||||
public function testVoteUsingTokenThatReturnsRoleNames($roles, $attributes, $expected)
|
||||
{
|
||||
$voter = new RoleVoter();
|
||||
|
||||
$this->assertSame($expected, $voter->vote($this->getTokenWithRoleNames($roles), null, $attributes));
|
||||
}
|
||||
|
||||
public function getVoteTests()
|
||||
{
|
||||
return [
|
||||
@ -41,6 +53,23 @@ class RoleVoterTest extends TestCase
|
||||
// Test mixed Types
|
||||
[[], [[]], VoterInterface::ACCESS_ABSTAIN],
|
||||
[[], [new \stdClass()], VoterInterface::ACCESS_ABSTAIN],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
* @dataProvider getLegacyVoteOnRoleObjectsTests
|
||||
*/
|
||||
public function testVoteOnRoleObjects($roles, $attributes, $expected)
|
||||
{
|
||||
$voter = new RoleVoter();
|
||||
|
||||
$this->assertSame($expected, $voter->vote($this->getToken($roles), null, $attributes));
|
||||
}
|
||||
|
||||
public function getLegacyVoteOnRoleObjectsTests()
|
||||
{
|
||||
return [
|
||||
[['ROLE_BAR'], [new Role('ROLE_BAR')], VoterInterface::ACCESS_GRANTED],
|
||||
[['ROLE_BAR'], [new Role('ROLE_FOO')], VoterInterface::ACCESS_DENIED],
|
||||
];
|
||||
@ -58,4 +87,14 @@ class RoleVoterTest extends TestCase
|
||||
|
||||
return $token;
|
||||
}
|
||||
|
||||
protected function getTokenWithRoleNames(array $roles)
|
||||
{
|
||||
$token = $this->getMockBuilder(AbstractToken::class)->getMock();
|
||||
$token->expects($this->once())
|
||||
->method('getRoleNames')
|
||||
->will($this->returnValue($roles));
|
||||
|
||||
return $token;
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,9 @@ use Symfony\Component\Security\Core\Role\RoleHierarchy;
|
||||
|
||||
class RoleHierarchyTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @group legacy
|
||||
*/
|
||||
public function testGetReachableRoles()
|
||||
{
|
||||
$role = new RoleHierarchy([
|
||||
@ -30,4 +33,18 @@ class RoleHierarchyTest extends TestCase
|
||||
$this->assertEquals([new Role('ROLE_FOO'), new Role('ROLE_ADMIN'), new Role('ROLE_USER')], $role->getReachableRoles([new Role('ROLE_FOO'), new Role('ROLE_ADMIN')]));
|
||||
$this->assertEquals([new Role('ROLE_SUPER_ADMIN'), new Role('ROLE_ADMIN'), new Role('ROLE_FOO'), new Role('ROLE_USER')], $role->getReachableRoles([new Role('ROLE_SUPER_ADMIN')]));
|
||||
}
|
||||
|
||||
public function testGetReachableRoleNames()
|
||||
{
|
||||
$role = new RoleHierarchy(array(
|
||||
'ROLE_ADMIN' => array('ROLE_USER'),
|
||||
'ROLE_SUPER_ADMIN' => array('ROLE_ADMIN', 'ROLE_FOO'),
|
||||
));
|
||||
|
||||
$this->assertEquals(array('ROLE_USER'), $role->getReachableRoleNames(array('ROLE_USER')));
|
||||
$this->assertEquals(array('ROLE_FOO'), $role->getReachableRoleNames(array('ROLE_FOO')));
|
||||
$this->assertEquals(array('ROLE_ADMIN', 'ROLE_USER'), $role->getReachableRoleNames(array('ROLE_ADMIN')));
|
||||
$this->assertEquals(array('ROLE_FOO', 'ROLE_ADMIN', 'ROLE_USER'), $role->getReachableRoleNames(array('ROLE_FOO', 'ROLE_ADMIN')));
|
||||
$this->assertEquals(array('ROLE_SUPER_ADMIN', 'ROLE_ADMIN', 'ROLE_FOO', 'ROLE_USER'), $role->getReachableRoleNames(array('ROLE_SUPER_ADMIN')));
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,9 @@ namespace Symfony\Component\Security\Core\Tests\Role;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*/
|
||||
class RoleTest extends TestCase
|
||||
{
|
||||
public function testGetRole()
|
||||
|
@ -14,6 +14,9 @@ namespace Symfony\Component\Security\Core\Tests\Role;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Security\Core\Role\SwitchUserRole;
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*/
|
||||
class SwitchUserRoleTest extends TestCase
|
||||
{
|
||||
public function testGetSource()
|
||||
|
@ -12,7 +12,6 @@
|
||||
namespace Symfony\Component\Security\Guard\Token;
|
||||
|
||||
use Symfony\Component\Security\Core\Authentication\Token\AbstractToken;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
|
||||
/**
|
||||
@ -28,9 +27,9 @@ class PostAuthenticationGuardToken extends AbstractToken implements GuardTokenIn
|
||||
private $providerKey;
|
||||
|
||||
/**
|
||||
* @param UserInterface $user The user!
|
||||
* @param string $providerKey The provider (firewall) key
|
||||
* @param (Role|string)[] $roles An array of roles
|
||||
* @param UserInterface $user The user!
|
||||
* @param string $providerKey The provider (firewall) key
|
||||
* @param string[] $roles An array of roles
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
|
@ -21,6 +21,7 @@ use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverIn
|
||||
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\RememberMeToken;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
|
||||
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
|
||||
@ -189,10 +190,14 @@ class ContextListener implements ListenerInterface
|
||||
if (null !== $this->logger) {
|
||||
$context = ['provider' => \get_class($provider), 'username' => $refreshedUser->getUsername()];
|
||||
|
||||
foreach ($token->getRoles() as $role) {
|
||||
if ($role instanceof SwitchUserRole) {
|
||||
$context['impersonator_username'] = $role->getSource()->getUsername();
|
||||
break;
|
||||
if ($token instanceof SwitchUserToken) {
|
||||
$context['impersonator_username'] = $token->getOriginalToken()->getUsername();
|
||||
} else {
|
||||
foreach ($token->getRoles(false) as $role) {
|
||||
if ($role instanceof SwitchUserRole) {
|
||||
$context['impersonator_username'] = $role->getSource(false)->getUsername();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,8 +17,8 @@ use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
|
||||
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
|
||||
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
|
||||
@ -122,7 +122,7 @@ class SwitchUserListener implements ListenerInterface
|
||||
$token = $this->tokenStorage->getToken();
|
||||
$originalToken = $this->getOriginalToken($token);
|
||||
|
||||
if (false !== $originalToken) {
|
||||
if (null !== $originalToken) {
|
||||
if ($token->getUsername() === $username) {
|
||||
return $token;
|
||||
}
|
||||
@ -146,9 +146,9 @@ class SwitchUserListener implements ListenerInterface
|
||||
$this->userChecker->checkPostAuth($user);
|
||||
|
||||
$roles = $user->getRoles();
|
||||
$roles[] = new SwitchUserRole('ROLE_PREVIOUS_ADMIN', $this->tokenStorage->getToken());
|
||||
$roles[] = new SwitchUserRole('ROLE_PREVIOUS_ADMIN', $this->tokenStorage->getToken(), false);
|
||||
|
||||
$token = new UsernamePasswordToken($user, $user->getPassword(), $this->providerKey, $roles);
|
||||
$token = new SwitchUserToken($user, $user->getPassword(), $this->providerKey, $roles, $token);
|
||||
|
||||
if (null !== $this->dispatcher) {
|
||||
$switchEvent = new SwitchUserEvent($request, $token->getUser(), $token);
|
||||
@ -169,7 +169,7 @@ class SwitchUserListener implements ListenerInterface
|
||||
*/
|
||||
private function attemptExitUser(Request $request)
|
||||
{
|
||||
if (false === $original = $this->getOriginalToken($this->tokenStorage->getToken())) {
|
||||
if (null === ($currentToken = $this->tokenStorage->getToken()) || null === $original = $this->getOriginalToken($currentToken)) {
|
||||
throw new AuthenticationCredentialsNotFoundException('Could not find original Token object.');
|
||||
}
|
||||
|
||||
@ -183,19 +183,18 @@ class SwitchUserListener implements ListenerInterface
|
||||
return $original;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the original Token from a switched one.
|
||||
*
|
||||
* @return TokenInterface|false The original TokenInterface instance, false if the current TokenInterface is not switched
|
||||
*/
|
||||
private function getOriginalToken(TokenInterface $token)
|
||||
private function getOriginalToken(TokenInterface $token): ?TokenInterface
|
||||
{
|
||||
foreach ($token->getRoles() as $role) {
|
||||
if ($token instanceof SwitchUserToken) {
|
||||
return $token->getOriginalToken();
|
||||
}
|
||||
|
||||
foreach ($token->getRoles(false) as $role) {
|
||||
if ($role instanceof SwitchUserRole) {
|
||||
return $role->getSource();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ use Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolve
|
||||
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
use Symfony\Component\Security\Http\Controller\UserValueResolver;
|
||||
|
||||
@ -35,7 +36,7 @@ class UserValueResolverTest extends TestCase
|
||||
public function testResolveNoUser()
|
||||
{
|
||||
$mock = $this->getMockBuilder(UserInterface::class)->getMock();
|
||||
$token = $this->getMockBuilder(TokenInterface::class)->getMock();
|
||||
$token = new UsernamePasswordToken('username', 'password', 'provider');
|
||||
$tokenStorage = new TokenStorage();
|
||||
$tokenStorage->setToken($token);
|
||||
|
||||
@ -57,8 +58,7 @@ class UserValueResolverTest extends TestCase
|
||||
public function testResolve()
|
||||
{
|
||||
$user = $this->getMockBuilder(UserInterface::class)->getMock();
|
||||
$token = $this->getMockBuilder(TokenInterface::class)->getMock();
|
||||
$token->expects($this->any())->method('getUser')->willReturn($user);
|
||||
$token = new UsernamePasswordToken($user, 'password', 'provider');
|
||||
$tokenStorage = new TokenStorage();
|
||||
$tokenStorage->setToken($token);
|
||||
|
||||
@ -72,8 +72,7 @@ class UserValueResolverTest extends TestCase
|
||||
public function testIntegration()
|
||||
{
|
||||
$user = $this->getMockBuilder(UserInterface::class)->getMock();
|
||||
$token = $this->getMockBuilder(TokenInterface::class)->getMock();
|
||||
$token->expects($this->any())->method('getUser')->willReturn($user);
|
||||
$token = new UsernamePasswordToken($user, 'password', 'provider');
|
||||
$tokenStorage = new TokenStorage();
|
||||
$tokenStorage->setToken($token);
|
||||
|
||||
@ -83,7 +82,7 @@ class UserValueResolverTest extends TestCase
|
||||
|
||||
public function testIntegrationNoUser()
|
||||
{
|
||||
$token = $this->getMockBuilder(TokenInterface::class)->getMock();
|
||||
$token = new UsernamePasswordToken('username', 'password', 'provider');
|
||||
$tokenStorage = new TokenStorage();
|
||||
$tokenStorage->setToken($token);
|
||||
|
||||
|
@ -16,6 +16,7 @@ use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
|
||||
use Symfony\Component\Security\Core\Role\SwitchUserRole;
|
||||
use Symfony\Component\Security\Core\User\User;
|
||||
@ -93,7 +94,7 @@ class SwitchUserListenerTest extends TestCase
|
||||
public function testExitUserUpdatesToken()
|
||||
{
|
||||
$originalToken = new UsernamePasswordToken('username', '', 'key', []);
|
||||
$this->tokenStorage->setToken(new UsernamePasswordToken('username', '', 'key', [new SwitchUserRole('ROLE_PREVIOUS', $originalToken)]));
|
||||
$this->tokenStorage->setToken(new SwitchUserToken('username', '', 'key', [new SwitchUserRole('ROLE_PREVIOUS', $originalToken, false)], $originalToken));
|
||||
|
||||
$this->request->query->set('_switch_user', SwitchUserListener::EXIT_VALUE);
|
||||
|
||||
@ -107,6 +108,22 @@ class SwitchUserListenerTest extends TestCase
|
||||
$this->assertSame($originalToken, $this->tokenStorage->getToken());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*/
|
||||
public function testExitUserBasedOnSwitchUserRoleUpdatesToken()
|
||||
{
|
||||
$originalToken = new UsernamePasswordToken('username', '', 'key', array());
|
||||
$this->tokenStorage->setToken(new UsernamePasswordToken('username', '', 'key', array(new SwitchUserRole('ROLE_PREVIOUS', $originalToken, false)), $originalToken));
|
||||
|
||||
$this->request->query->set('_switch_user', SwitchUserListener::EXIT_VALUE);
|
||||
|
||||
$listener = new SwitchUserListener($this->tokenStorage, $this->userProvider, $this->userChecker, 'provider123', $this->accessDecisionManager);
|
||||
$listener->handle($this->event);
|
||||
|
||||
$this->assertSame($originalToken, $this->tokenStorage->getToken());
|
||||
}
|
||||
|
||||
public function testExitUserDispatchesEventWithRefreshedUser()
|
||||
{
|
||||
$originalUser = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')->getMock();
|
||||
@ -118,7 +135,7 @@ class SwitchUserListenerTest extends TestCase
|
||||
->with($originalUser)
|
||||
->willReturn($refreshedUser);
|
||||
$originalToken = new UsernamePasswordToken($originalUser, '', 'key');
|
||||
$this->tokenStorage->setToken(new UsernamePasswordToken('username', '', 'key', [new SwitchUserRole('ROLE_PREVIOUS', $originalToken)]));
|
||||
$this->tokenStorage->setToken(new SwitchUserToken('username', '', 'key', [new SwitchUserRole('ROLE_PREVIOUS', $originalToken, false)], $originalToken));
|
||||
$this->request->query->set('_switch_user', SwitchUserListener::EXIT_VALUE);
|
||||
|
||||
$dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock();
|
||||
@ -142,7 +159,7 @@ class SwitchUserListenerTest extends TestCase
|
||||
->expects($this->never())
|
||||
->method('refreshUser');
|
||||
$originalToken = new UsernamePasswordToken($originalUser, '', 'key');
|
||||
$this->tokenStorage->setToken(new UsernamePasswordToken('username', '', 'key', [new SwitchUserRole('ROLE_PREVIOUS', $originalToken)]));
|
||||
$this->tokenStorage->setToken(new SwitchUserToken('username', '', 'key', [new SwitchUserRole('ROLE_PREVIOUS', $originalToken, false)], $originalToken));
|
||||
$this->request->query->set('_switch_user', SwitchUserListener::EXIT_VALUE);
|
||||
|
||||
$dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock();
|
||||
|
@ -95,7 +95,7 @@ class LogoutUrlGeneratorTest extends TestCase
|
||||
|
||||
public function testGuessFromTokenWithoutProviderKeyFallbacksToCurrentFirewall()
|
||||
{
|
||||
$this->tokenStorage->setToken($this->getMockBuilder(TokenInterface::class)->getMock());
|
||||
$this->tokenStorage->setToken(new UsernamePasswordToken('username', 'password', 'provider'));
|
||||
$this->generator->registerListener('secured_area', '/logout', null, null);
|
||||
$this->generator->setCurrentFirewall('secured_area');
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.1.3",
|
||||
"symfony/security-core": "~3.4|~4.0",
|
||||
"symfony/security-core": "~4.3",
|
||||
"symfony/event-dispatcher": "~3.4|~4.0",
|
||||
"symfony/http-foundation": "~3.4|~4.0",
|
||||
"symfony/http-kernel": "~3.4|~4.0",
|
||||
|
@ -14,6 +14,8 @@ namespace Symfony\Component\Workflow\EventListener;
|
||||
use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Symfony\Component\Security\Core\Role\RoleHierarchy;
|
||||
use Symfony\Component\Security\Core\Role\RoleHierarchyInterface;
|
||||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
use Symfony\Component\Workflow\Event\GuardEvent;
|
||||
@ -80,19 +82,23 @@ class GuardListener
|
||||
throw new InvalidTokenConfigurationException(sprintf('There are no tokens available for workflow %s.', $event->getWorkflowName()));
|
||||
}
|
||||
|
||||
if (null !== $this->roleHierarchy) {
|
||||
$roles = $this->roleHierarchy->getReachableRoles($token->getRoles());
|
||||
if (method_exists($token, 'getRoleNames')) {
|
||||
$roles = $token->getRoleNames();
|
||||
} else {
|
||||
$roles = $token->getRoles();
|
||||
$roles = array_map(function (Role $role) { return $role->getRole(); }, $token->getRoles(false));
|
||||
}
|
||||
|
||||
if ($this->roleHierarchy instanceof RoleHierarchy) {
|
||||
$roles = $this->roleHierarchy->getReachableRoleNames($roles);
|
||||
} elseif (null !== $this->roleHierarchy) {
|
||||
$roles = $this->roleHierarchy->getReachableRoles($token->getRoles(false));
|
||||
}
|
||||
|
||||
$variables = [
|
||||
'token' => $token,
|
||||
'user' => $token->getUser(),
|
||||
'subject' => $event->getSubject(),
|
||||
'roles' => array_map(function ($role) {
|
||||
return $role->getRole();
|
||||
}, $roles),
|
||||
'roles' => $roles,
|
||||
// needed for the is_granted expression function
|
||||
'auth_checker' => $this->authorizationChecker,
|
||||
// needed for the is_* expression function
|
||||
|
@ -6,6 +6,7 @@ use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
|
||||
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
@ -35,8 +36,7 @@ class GuardListenerTest extends TestCase
|
||||
],
|
||||
];
|
||||
$expressionLanguage = new ExpressionLanguage();
|
||||
$token = $this->getMockBuilder(TokenInterface::class)->getMock();
|
||||
$token->expects($this->any())->method('getRoles')->willReturn([new Role('ROLE_USER')]);
|
||||
$token = new UsernamePasswordToken('username', 'credentials', 'provider', ['ROLE_USER']);
|
||||
$tokenStorage = $this->getMockBuilder(TokenStorageInterface::class)->getMock();
|
||||
$tokenStorage->expects($this->any())->method('getToken')->willReturn($token);
|
||||
$this->authenticationChecker = $this->getMockBuilder(AuthorizationCheckerInterface::class)->getMock();
|
||||
|
Reference in New Issue
Block a user