Skip to content

Commit b84b82f

Browse files
author
Amrouche Hamza
committed
[TwigBridge] Create impersonation_exit_path() and *_url() functions
1 parent d222648 commit b84b82f

File tree

2 files changed

+189
-0
lines changed

2 files changed

+189
-0
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
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\Bridge\Twig\Extension;
13+
14+
use Symfony\Component\Security\Http\Logout\ImpersonateUrlGenerator;
15+
use Twig\Extension\AbstractExtension;
16+
use Twig\TwigFunction;
17+
18+
/**
19+
* SecurityExtension exposes security context features.
20+
*
21+
* @author Amrouche Hamza <hamza.simperfit@gmail.com>
22+
*/
23+
class ImpersonateExitExtension extends AbstractExtension
24+
{
25+
private $impersonateUrlGenerator;
26+
27+
public function __construct(ImpersonateUrlGenerator $impersonateUrlGenerator)
28+
{
29+
$this->impersonateUrlGenerator = $impersonateUrlGenerator;
30+
}
31+
32+
/**
33+
* {@inheritdoc}
34+
*/
35+
public function getFunctions()
36+
{
37+
return array(
38+
new TwigFunction('impersonation_exit_path', array($this, 'getImpersonateExitPath')),
39+
new TwigFunction('impersonation_exit_url', array($this, 'getImpersonateExitUrl')),
40+
);
41+
}
42+
43+
public function getImpersonateExitPath()
44+
{
45+
$this->impersonateUrlGenerator->getImpersonateExitPath();
46+
}
47+
48+
public function getImpersonateExitUrl()
49+
{
50+
$this->impersonateUrlGenerator->getImpersonateExitUrl();
51+
}
52+
53+
/**
54+
* {@inheritdoc}
55+
*/
56+
public function getName()
57+
{
58+
return 'impersonation_exit';
59+
}
60+
}
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
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\Http\Logout;
13+
14+
use Symfony\Component\HttpFoundation\RequestStack;
15+
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
16+
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
17+
use Symfony\Component\Security\Core\Role\SwitchUserRole;
18+
use Symfony\Component\Security\Http\Firewall\SwitchUserListener;
19+
use Symfony\Component\Security\Http\FirewallMapInterface;
20+
use Symfony\Bundle\SecurityBundle\Security\FirewallMap;
21+
22+
/**
23+
* Provides generator functions for the impersonate url exit.
24+
*
25+
* @author Amrouche Hamza <hamza.simperfit@gmail.com>
26+
*/
27+
class ImpersonateUrlGenerator
28+
{
29+
private $requestStack;
30+
private $router;
31+
private $tokenStorage;
32+
private $firewallMap;
33+
34+
public function __construct(RequestStack $requestStack = null, UrlGeneratorInterface $router = null, TokenStorageInterface $tokenStorage = null, FirewallMapInterface $firewallMap)
35+
{
36+
$this->requestStack = $requestStack;
37+
$this->router = $router;
38+
$this->tokenStorage = $tokenStorage;
39+
$this->firewallMap = $firewallMap;
40+
}
41+
42+
/**
43+
* Generates the absolute logout path for the firewall.
44+
**.
45+
*
46+
* @return string The Impersonate exit path
47+
*/
48+
public function getImpersonateExitPath()
49+
{
50+
return $this->generateImpersonateExitUrl(UrlGeneratorInterface::ABSOLUTE_PATH);
51+
}
52+
53+
/**
54+
* Generates the absolute logout URL for the firewall.
55+
*
56+
* @return string The Impersonate exit URL
57+
*/
58+
public function getImpersonateExitUrl()
59+
{
60+
return $this->generateImpersonateExitUrl(UrlGeneratorInterface::ABSOLUTE_URL);
61+
}
62+
63+
/**
64+
* Generates the Impersonate exit URL for the firewall.
65+
*
66+
* @param int $referenceType The type of reference (one of the constants in UrlGeneratorInterface)
67+
*
68+
* @return string The Impersonate exit URL
69+
*/
70+
private function generateImpersonateExitUrl($referenceType)
71+
{
72+
$request = $this->requestStack->getCurrentRequest();
73+
$exitPath = null;
74+
if ($this->firewallMap instanceof FirewallMap) {
75+
$firewallConfig = $this->firewallMap->getFirewallConfig($request);
76+
77+
// generate exit impersonation path from current request
78+
if ($this->getImpersonatedUser() && null !== $switchUserConfig = $firewallConfig->getSwitchUser()) {
79+
$exitPath = $request->getRequestUri();
80+
$exitPath .= null === $request->getQueryString() ? '?' : '&';
81+
$exitPath .= sprintf(
82+
'%s=%s',
83+
urlencode($switchUserConfig['parameter']),
84+
SwitchUserListener::EXIT_VALUE
85+
);
86+
}
87+
}
88+
if (null === $exitPath) {
89+
throw new \LogicException('Unable to generate the impersonate exit URL without a path.');
90+
}
91+
92+
if ('/' === $exitPath[0]) {
93+
if (!$this->requestStack) {
94+
throw new \LogicException('Unable to generate the impersonate exit URL without a RequestStack.');
95+
}
96+
97+
$url = UrlGeneratorInterface::ABSOLUTE_URL === $referenceType ? $request->getUriForPath($exitPath) : $request->getBaseUrl().$exitPath;
98+
99+
if (!empty($parameters)) {
100+
$url .= '?'.http_build_query($parameters);
101+
}
102+
} else {
103+
if (!$this->router) {
104+
throw new \LogicException('Unable to generate the impersonate exit URL without a Router.');
105+
}
106+
107+
$url = $this->router->generate($exitPath, array(), $referenceType);
108+
}
109+
110+
return $url;
111+
}
112+
113+
private function getImpersonatedUser()
114+
{
115+
$token = $this->tokenStorage->getToken();
116+
if (null === $token) {
117+
return false;
118+
}
119+
120+
$assignedRoles = $token->getRoles();
121+
122+
$impersonatorUser = null;
123+
foreach ($assignedRoles as $role) {
124+
if ($role instanceof SwitchUserRole) {
125+
return $role->getSource()->getUsername();
126+
}
127+
}
128+
}
129+
}

0 commit comments

Comments
 (0)