8000 deprecate the Role and SwitchUserRole classes · symfony/symfony@2054024 · GitHub
[go: up one dir, main page]

Skip to content

Commit 2054024

Browse files
committed
deprecate the Role and SwitchUserRole classes
1 parent e970c6c commit 2054024

File tree

14 files changed

+245
-63
lines changed

14 files changed

+245
-63
lines changed

src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Symfony\Bundle\SecurityBundle\Debug\TraceableFirewallListener;
1515
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
16+
use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
1617
use Symfony\Component\Security\Core\Role\Role;
1718
use Symfony\Component\Security\Core\Role\RoleHierarchyInterface;
1819
use Symfony\Component\HttpFoundation\Request;
@@ -93,10 +94,14 @@ public function collect(Request $request, Response $response, \Exception $except
9394
$assignedRoles = $token->getRoles();
9495

9596
$impersonatorUser = null;
96-
foreach ($assignedRoles as $role) {
97-
if ($role instanceof SwitchUserRole) {
98-
F438 $impersonatorUser = $role->getSource()->getUsername();
99-
break;
97+
if ($token instanceof SwitchUserToken) {
98+
$impersonatorUser = $token->getOriginalToken()->getUsername();
99+
} else {
100+
foreach ($assignedRoles as $role) {
101+
if ($role instanceof SwitchUserRole) {
102+
$impersonatorUser = $role->getSource()->getUsername();
103+
break;
104+
}
100105
}
101106
}
102107

src/Symfony/Bundle/SecurityBundle/Tests/DataCollector/SecurityDataCollectorTest.php

Lines changed: 38 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,12 @@
1717
use Symfony\Bundle\SecurityBundle\Security\FirewallConfig;
1818
use Symfony\Bundle\SecurityBundle\Security\FirewallMap;
1919
use Symfony\Component\EventDispatcher\EventDispatcher;
20+
use Symfony\Component\HttpFoundation\Request;
21+
use Symfony\Component\HttpFoundation\Response;
2022
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
2123
use Symfony\Component\HttpKernel\HttpKernelInterface;
2224
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
25+
use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
2326
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
2427
use Symfony\Component\Security\Core\Role\Role;
2528
use Symfony\Component\Security\Core\Role\RoleHierarchy;
@@ -33,7 +36,7 @@ class SecurityDataCollectorTest extends TestCase
3336
public function testCollectWhenSecurityIsDisabled()
3437
{
3538
$collector = new SecurityDataCollector();
36-
$collector->collect($this->getRequest(), $this->getResponse());
39+
$collector->collect(new Request(), new Response());
3740

3841
$this->assertSame('security', $collector->getName());
3942
$this->assertFalse($collector->isEnabled());
@@ -53,7 +56,7 @@ public function testCollectWhenAuthenticationTokenIsNull()
5356
{
5457
$tokenStorage = new TokenStorage();
5558
$collector = new SecurityDataCollector($tokenStorage, $this->getRoleHierarchy());
56-
$collector->collect($this->getRequest(), $this->getResponse());
59+
$collector->collect(new Request(), new Response());
5760

5861
$this->assertTrue($collector->isEnabled());
5962
$this->assertFalse($collector->isAuthenticated());
@@ -75,7 +78,7 @@ public function testCollectAuthenticationTokenAndRoles(array $roles, array $norm
7578
$tokenStorage->setToken(new UsernamePasswordToken('hhamon', 'P4$$w0rD', 'provider', $roles));
7679

7780
$collector = new SecurityDataCollector($tokenStorage, $this->getRoleHierarchy());
78-
$collector->collect($this->getRequest(), $this->getResponse());
81+
$collector->collect(new Request(), new Response());
7982
$collector->lateCollect();
8083

8184
$this->assertTrue($collector->isEnabled());
@@ -90,6 +93,9 @@ public function testCollectAuthenticationTokenAndRoles(array $roles, array $norm
9093
$this->assertSame('hhamon', $collector->getUser());
9194
}
9295

96+
/**
97+
* @group legacy
98+
*/
9399
public function testCollectImpersonatedToken()
94100
{
95101
$adminToken = new UsernamePasswordToken('yceruto', 'P4$$w0rD', 'provider', array('ROLE_ADMIN'));
@@ -103,7 +109,7 @@ public function testCollectImpersonatedToken()
103109
$tokenStorage->setToken(new UsernamePasswordToken('hhamon', 'P4$$w0rD', 'provider', $userRoles));
104110

105111
$collector = new SecurityDataCollector($tokenStorage, $this->getRoleHierarchy());
106-
$collector->collect($this->getRequest(), $this->getResponse());
112+
$collector->collect(new Request(), new Response());
107113
$collector->lateCollect();
108114

109115
$this->assertTrue($collector->isEnabled());
@@ -117,10 +123,32 @@ public function testCollectImpersonatedToken()
117123
$this->assertSame('hhamon', $collector->getUser());
118124
}
119125

126+
public function testCollectSwitchUserToken()
127+
{
128+
$adminToken = new UsernamePasswordToken('yceruto', 'P4$$w0rD', 'provider', array('ROLE_ADMIN'));
129+
130+
$tokenStorage = new TokenStorage();
131+
$tokenStorage->setToken(new SwitchUserToken('hhamon', 'P4$$w0rD', 'provider', array('ROLE_USER', 'ROLE_PREVIOUS_ADMIN'), $adminToken));
132+
133+
$collector = new SecurityDataCollector($tokenStorage, $this->getRoleHierarchy());
134+
$collector->collect(new Request(), new Response());
135+
$collector->lateCollect();
136+
137+
$this->assertTrue($collector->isEnabled());
138+
$this->assertTrue($collector->isAuthenticated());
139+
$this->assertTrue($collector->isImpersonated());
140+
$this->assertSame('yceruto', $collector->getImpersonatorUser());
141+
$this->assertSame(SwitchUserToken::class, $collector->getTokenClass()->getValue());
142+
$this->assertTrue($collector->supportsRoleHierarchy());
143+
$this->assertSame(array('ROLE_USER', 'ROLE_PREVIOUS_ADMIN'), $collector->getRoles()->getValue(true));
144+
$this->assertSame(array(), $collector->getInheritedRoles()->getValue(true));
145+
$this->assertSame('hhamon', $collector->getUser());
146+
}
147+
120148
public function testGetFirewall()
121149
{
122150
$firewallConfig = new FirewallConfig('dummy', 'security.request_matcher.dummy', 'security.user_checker.dummy');
123-
$request = $this->getRequest();
151+
$request = new Request();
124152

125153
$firewallMap = $this
126154
->getMockBuilder(FirewallMap::class)
@@ -133,7 +161,7 @@ public function testGetFirewall()
133161
->willReturn($firewallConfig);
134162

135163
$collector = new SecurityDataCollector(null, null, null, null, $firewallMap, new TraceableFirewallListener($firewallMap, new EventDispatcher(), new LogoutUrlGenerator()));
136-
$collector->collect($request, $this->getResponse());
164+
$collector->collect($request, new Response());
137165
$collector->lateCollect();
138166
$collected = $collector->getFirewall();
139167

@@ -153,8 +181,8 @@ public function testGetFirewall()
153181

154182
public function testGetFirewallReturnsNull()
155183
{
156-
$request = $this->getRequest();
157-
$response = $this->getResponse();
184+
$request = new Request();
185+
$response = new Response();
158186

159187
// Don't inject any firewall map
160188
$collector = new SecurityDataCollector();
@@ -187,9 +215,9 @@ public function testGetFirewallReturnsNull()
187215
*/
188216
public function testGetListeners()
189217
{
190-
$request = $this->getRequest();
218+
$request = new Request();
191219
$event = new GetResponseEvent($this->getMockBuilder(HttpKernelInterface::class)->getMock(), $request, HttpKernelInterface::MASTER_REQUEST);
192-
$event->setResponse($response = $this->getResponse());
220+
$event->setResponse($response = new Response());
193221
$listener = $this->getMockBuilder(ListenerInterface::class)->getMock();
194222
$listener
195223
->expects($this->once())
@@ -261,20 +289,4 @@ private function getRoleHierarchy()
261289
'ROLE_OPERATOR' => array('ROLE_USER'),
262290
));
263291
}
264-
265-
private function getRequest()
266-
{
267-
return $this
268-
->getMockBuilder('Symfony\Component\HttpFoundation\Request')
269-
->disableOriginalConstructor()
270-
->getMock();
271-
}
272-
273-
private function getResponse()
274-
{
275-
return $this
276-
->getMockBuilder('Symfony\Component\HttpFoundation\Response')
277-
->disableOriginalConstructor()
278-
->getMock();
279-
}
280292
}

src/Symfony/Component/Security/Core/Authentication/Provider/UserAuthenticationProvider.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Symfony\Component\Security\Core\Authentication\Provider;
1313

14+
use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
1415
use Symfony\Component\Security\Core\User\UserInterface;
1516
use Symfony\Component\Security\Core\User\UserCheckerInterface;
1617
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
@@ -87,7 +88,12 @@ public function authenticate(TokenInterface $token)
8788
throw $e;
8889
}
8990

90-
$authenticatedToken = new UsernamePasswordToken($user, $token->getCredentials(), $this->providerKey, $this->getRoles($user, $token));
91+
if ($token instanceof SwitchUserToken) {
92+
$authenticatedToken = new SwitchUserToken($user, $token->getCredentials(), $this->providerKey, $this->getRoles($user, $token), $token->getOriginalToken());
93+
} else {
94+
$authenticatedToken = new UsernamePasswordToken($user, $token->getCredentials(), $this->providerKey, $this->getRoles($user, $token));
95+
}
96+
9197
$authenticatedToken->setAttributes($token->getAttributes());
9298

9399
return $authenticatedToken;
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Security\Core\Authentication\Token;
13+
14+
/**
15+
* Token representing a user who temporarily impersonates another one.
16+
*
17+
* @author Christian Flothmann <christian.flothmann@sensiolabs.de>
18+
*/
19+
class SwitchUserToken extends UsernamePasswordToken
20+
{
21+
private $originalToken;
22+
23+
/**
24+
* @param string|object $user The username (like a nickname, email address, etc.), or a UserInterface instance or an object implementing a __toString method
25+
* @param mixed $credentials This usually is the password of the user
26+
* @param string $providerKey The provider key
27+
* @param (Role|string)[] $roles An array of roles
28+
* @param TokenInterface $originalToken The token of the user who switched to the current user
29+
*
30+
* @throws \InvalidArgumentException
31+
*/
32+
public function __construct($user, $credentials, string $providerKey, array $roles = array(), TokenInterface $originalToken)
33+
{
34+
parent::__construct($user, $credentials, $providerKey, $roles);
35+
36+
$this->originalToken = $originalToken;
37+
}
38+
39+
public function getOriginalToken(): TokenInterface
40+
{
41+
return $this->originalToken;
42+
}
43+
44+
/**
45+
* {@inheritdoc}
46+
*/
47+
public function serialize(): string
48+
{
49+
return serialize(array(clone $this->originalToken, parent::serialize()));
50+
}
51+
52+
/**
53+
* {@inheritdoc}
54+
*/
55+
public function unserialize($serialized): void
56+
{
57+
list($this->originalToken, $parentStr) = unserialize($serialized);
58+
59+
parent::unserialize($parentStr);
60+
}
61+
}

src/Symfony/Component/Security/Core/Authentication/Token/TokenInterface.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public function __toString();
3333
/**
3434
* Returns the user roles.
3535
*
36-
* @return Role[] An array of Role instances
36+
* @return string[] An array of Role instances
3737
*/
3838
public function getRoles();
3939

src/Symfony/Component/Security/Core/Role/Role.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,9 @@ public function getRole()
3434
{
3535
return $this->role;
3636
}
37+
38+
public function __toString(): string
39+
{
40+
return $this->role;
41+
}
3742
}

src/Symfony/Component/Security/Core/Role/SwitchUserRole.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,12 @@
1818
* another one.
1919
*
2020
* @author Fabien Potencier <fabien@symfony.com>
21+
*
22+
* @deprecated since version 4.1, to be removed in 5.0. Use strings as roles instead.
2123
*/
2224
class SwitchUserRole extends Role
2325
{
26+
private $deprecationTriggered = false;
2427
private $source;
2528

2629
/**
@@ -29,6 +32,12 @@ class SwitchUserRole extends Role
2932
*/
3033
public function __construct(string $role, TokenInterface $source)
3134
{
35+
if (func_num_args() < 3 || func_get_arg(2)) {
36+
@trigger_error(sprintf('The "%s" class is deprecated since version 4.1 and will be removed in 5.0. Use strings as roles instead.', __CLASS__), E_USER_DEPRECATED);
37+
38+
$this->deprecationTriggered = true;
39+
}
40+
3241
parent::__construct($role);
3342

3443
$this->source = $source;
@@ -41,6 +50,12 @@ public function __construct(string $role, TokenInterface $source)
4150
*/
4251
public function getSource()
4352
{
53+
if (!$this->deprecationTriggered && (func_num_args() < 1 || func_get_arg(0))) {
54+
@trigger_error(sprintf('The "%s" class is deprecated since version 4.1 and will be removed in 5.0. Use strings as roles instead.', __CLASS__), E_USER_DEPRECATED);
55+
56+
$this->deprecationTriggered = true;
57+
}
58+
4459
return $this->source;
4560
}
4661
}

src/Symfony/Component/Security/Core/Tests/Authentication/Provider/UserAuthenticationProviderTest.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Security\Core\Tests\Authentication\Provider;
1313

1414
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
1516
use Symfony\Component\Security\Core\Exception\AccountExpiredException;
1617
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
1718
use Symfony\Component\Security\Core\Exception\CredentialsExpiredException;
@@ -194,6 +195,9 @@ public function testAuthenticate()
194195
$this->assertEquals(array('foo' => 'bar'), $authToken->getAttributes(), '->authenticate() copies token attributes');
195196
}
196197

198+
/**
199+
* @group legacy
200+
*/
197201
public function testAuthenticateWithPreservingRoleSwitchUserRole()
198202
{
199203
$user = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')->getMock();
@@ -230,6 +234,34 @@ public function testAuthenticateWithPreservingRoleSwitchUserRole()
230234
$this->assertEquals(array('foo' => 'bar'), $authToken->getAttributes(), '->authenticate() copies token attributes');
231235
}
232236

237+
public function testAuthenticatePreservesOriginalToken()
238+
{
239+
$user = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')->getMock();
240+
$user->expects($this->once())
241+
->method('getRoles')
242+
->will($this->returnValue(array('ROLE_FOO')))
243+
;
244+
245+
$provider = $this->getProvider();
246+
$provider->expects($this->once())
247+
->method('retrieveUser')
248+
->will($this->returnValue($user))
249+
;
250+
251+
$originalToken = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock();
252+
$token = new SwitchUserToken($this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')->getMock(), 'foo', 'key', array(), $originalToken);
253+
$token->setAttributes(array('foo' => 'bar'));
254+
255+
$authToken = $provider->authenticate($token);
256+
257+
$this->assertInstanceOf(SwitchUserToken::class, $authToken);
258+
$this->assertSame($originalToken, $authToken->getOriginalToken());
259+
$this->assertSame($user, $authToken->getUser());
260+
$this->assertContains(new Role('ROLE_FOO'), $authToken->getRoles(), '', false, false);
261+
$this->assertEquals('foo', $authToken->getCredentials());
262+
$this->assertEquals(array('foo' => 'bar'), $authToken->getAttributes(), '->authenticate() copies token attributes');
263+
}
264+
233265
protected function getSupportedToken()
234266
{
235267
$mock = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken')->setMethods(array('getCredentials', 'getProviderKey', 'getRoles'))->disableOriginalConstructor()->getMock();

src/Symfony/Component/Security/Core/Tests/Authentication/Token/AbstractTokenTest.php

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\Security\Core\Authentication\Token\AbstractToken;
1616
use Symfony\Component\Security\Core\Role\Role;
17-
use Symfony\Component\Security\Core\Role\SwitchUserRole;
1817
use Symfony\Component\Security\Core\User\User;
1918

2019
class TestUser
@@ -112,20 +111,6 @@ public function testSerializeWithRoleObjects()
112111
$this->assertEquals($roles, $user->getRoles());
113112
}
114113

115-
public function testSerializeParent()
116-
{
117-
$user = new TestUser('fabien');
118-
$token = new ConcreteToken($user, array('ROLE_FOO'));
119-
120-
$parentToken = new ConcreteToken($user, array(new SwitchUserRole('ROLE_PREVIOUS', $token)));
121-
$uToken = unserialize(serialize($parentToken));
122-
123-
$this->assertEquals(
124-
current($parentToken->getRoles())->getSource()->getUser(),
125-
current($uToken->getRoles())->getSource()->getUser()
126-
);
127-
}
128-
129114
public function testConstructor()
130115
{
131116
$token = $this->getToken(array('ROLE_FOO'));

0 commit comments

Comments
 (0)
0