Skip to content

Commit

Permalink
[SecurityBundle] Allow switching to the user that is already imperson…
Browse files Browse the repository at this point in the history
…ated (fix #2554)

Disabled exception when switching to the user that is already impersonated, exception is now only thrown when trying to switch to a new user.

Added an Excption exception when switching fails because target user does not exist.

Added funtional tests for switching users.
  • Loading branch information
Andreas Hucks committed Mar 15, 2012
1 parent 632077a commit a98d554
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 6 deletions.
@@ -0,0 +1,91 @@
<?php

/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

namespace Symfony\Bundle\SecurityBundle\Tests\Functional;

/**
* @group functional
*/
class SwitchUserTest extends WebTestCase
{
/**
* @dataProvider getTestParameters
*/
public function testSwitchUser($originalUser, $targetUser, $expectedUser, $expectedStatus)
{
$client = $this->createAuthenticatedClient($originalUser);

$client->request('GET', '/profile?_switch_user=' . $targetUser);

$this->assertEquals($expectedStatus, $client->getResponse()->getStatusCode());
$this->assertEquals($expectedUser, $client->getProfile()->getCollector('security')->getUser());
}

public function testSwitchedUserCannotSwitchToOther()
{
$client = $this->createAuthenticatedClient('user_can_switch');

$client->request('GET', '/profile?_switch_user=user_cannot_switch_1');
$client->request('GET', '/profile?_switch_user=user_cannot_switch_2');

$this->assertEquals(500, $client->getResponse()->getStatusCode());
$this->assertEquals('user_cannot_switch_1', $client->getProfile()->getCollector('security')->getUser());
}

public function testSwitchedUserExit()
{
$client = $this->createAuthenticatedClient('user_can_switch');

$client->request('GET', '/profile?_switch_user=user_cannot_switch_1');
$client->request('GET', '/profile?_switch_user=_exit');

$this->assertEquals(200, $client->getResponse()->getStatusCode());
$this->assertEquals('user_can_switch', $client->getProfile()->getCollector('security')->getUser());
}

public function getTestParameters()
{
return array(
'unauthorized_user_cannot_switch' => array('user_cannot_switch_1', 'user_cannot_switch_1', 'user_cannot_switch_1', 403),
'authorized_user_can_switch' => array('user_can_switch', 'user_cannot_switch_1', 'user_cannot_switch_1', 200),
'authorized_user_cannot_switch_to_non_existent' => array('user_can_switch', 'user_does_not_exist', 'user_can_switch', 500),
'authorized_user_can_switch_to_himself' => array('user_can_switch', 'user_can_switch', 'user_can_switch', 200),
);
}

protected function createAuthenticatedClient($username)
{
$client = $this->createClient(array('test_case' => 'StandardFormLogin', 'root_config' => 'switchuser.yml'));
$client->followRedirects(true);
$client->insulate();

$form = $client->request('GET', '/login')->selectButton('login')->form();
$form['_username'] = $username;
$form['_password'] = 'test';
$client->submit($form);

return $client;
}

protected function setUp()
{
parent::setUp();

$this->deleteTmpDir('StandardFormLogin');
}

protected function tearDown()
{
parent::tearDown();

$this->deleteTmpDir('StandardFormLogin');
}
}
@@ -0,0 +1,17 @@
imports:
- { resource: config.yml }

framework:
profiler: { only_exceptions: false }

security:
providers:
in_memory:
memory:
users:
user_can_switch: { password: test, roles: [ROLE_USER, ROLE_ALLOWED_TO_SWITCH] }
user_cannot_switch_1: { password: test, roles: [ROLE_USER] }
user_cannot_switch_2: { password: test, roles: [ROLE_USER] }
firewalls:
default:
switch_user: true
Expand Up @@ -86,9 +86,7 @@ public function handle(GetResponseEvent $event)
try {
$this->securityContext->setToken($this->attemptSwitchUser($request));
} catch (AuthenticationException $e) {
if (null !== $this->logger) {
$this->logger->warn(sprintf('Switch User failed: "%s"', $e->getMessage()));
}
throw new \LogicException(sprintf('Switch User failed: "%s"', $e->getMessage()));
}
}

Expand All @@ -108,8 +106,14 @@ public function handle(GetResponseEvent $event)
private function attemptSwitchUser(Request $request)
{
$token = $this->securityContext->getToken();
if (false !== $this->getOriginalToken($token)) {
throw new \LogicException(sprintf('You are already switched to "%s" user.', $token->getUsername()));
$originalToken = $this->getOriginalToken($token);

if (false !== $originalToken) {
if ($token->getUsername() === $request->get($this->usernameParameter)) {
return $token;
} else {
throw new \LogicException(sprintf('You are already switched to "%s" user.', $token->getUsername()));
}
}

if (false === $this->accessDecisionManager->decide($token, array($this->role))) {
Expand Down Expand Up @@ -148,7 +152,7 @@ private function attemptSwitchUser(Request $request)
private function attemptExitUser(Request $request)
{
if (false === $original = $this->getOriginalToken($this->securityContext->getToken())) {
throw new AuthenticationCredentialsNotFoundException(sprintf('Could not find original Token object.'));
throw new AuthenticationCredentialsNotFoundException('Could not find original Token object.');
}

if (null !== $this->dispatcher) {
Expand Down

0 comments on commit a98d554

Please sign in to comment.