Skip to content

Commit f300ede

Browse files
committed
fixes several bugs
1 parent a4f05ac commit f300ede

File tree

12 files changed

+138
-34
lines changed

12 files changed

+138
-34
lines changed

UPDATE.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ RC4 to RC5
7777
Session::getAttributes() -> Session::all()
7878
Session::setAttributes() -> Session::replace()
7979

80+
* {_locale} is not supported in paths in the access_control section anymore. You can
81+
rewrite the paths using a regular expression such as "(?:[a-z]{2})".
82+
8083
RC3 to RC4
8184
----------
8285

src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Controller/LocalizedController.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ public function logoutAction()
3434
throw new \RuntimeException('logoutAction() should never be called.');
3535
}
3636

37+
public function secureAction()
38+
{
39+
throw new \RuntimeException('secureAction() should never be called.');
40+
}
41+
3742
public function profileAction()
3843
{
3944
return new Response('Profile');
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,30 @@
11
localized_login_path:
22
pattern: /{_locale}/login
33
defaults: { _controller: FormLoginBundle:Localized:login }
4+
requirements: { _locale: "^[a-z]{2}$" }
45

56
localized_check_path:
67
pattern: /{_locale}/login_check
78
defaults: { _controller: FormLoginBundle:Localized:loginCheck }
9+
requirements: { _locale: "^[a-z]{2}$" }
810

911
localized_default_target_path:
1012
pattern: /{_locale}/profile
1113
defaults: { _controller: FormLoginBundle:Localized:profile }
14+
requirements: { _locale: "^[a-z]{2}$" }
1215

1316
localized_logout_path:
1417
pattern: /{_locale}/logout
1518
defaults: { _controller: FormLoginBundle:Localized:logout }
19+
requirements: { _locale: "^[a-z]{2}$" }
1620

1721
localized_logout_target_path:
1822
pattern: /{_locale}/
19-
defaults: { _controller: FormLoginBundle:Localized:homepage }
23+
defaults: { _controller: FormLoginBundle:Localized:homepage }
24+
requirements: { _locale: "^[a-z]{2}$" }
25+
26+
localized_secure_path:
27+
pattern: /{_locale}/secure/
28+
defaults: { _controller: FormLoginBundle:Localized:secure }
29+
requirements: { _locale: "^[a-z]{2}$" }
30+

src/Symfony/Bundle/SecurityBundle/Tests/Functional/LocalizedRoutesAsPathTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,30 @@ public function testLoginLogoutProcedure($locale)
2626
$this->assertEquals('Homepage', $client->followRedirect()->text());
2727
}
2828

29+
/**
30+
* @dataProvider getLocales
31+
*/
32+
public function testAccessRestrictedResource($locale)
33+
{
34+
$client = $this->createClient(array('test_case' => 'StandardFormLogin', 'root_config' => 'localized_routes.yml'));
35+
$client->insulate();
36+
37+
$client->request('GET', '/'.$locale.'/secure/');
38+
$this->assertRedirect($client->getResponse(), '/'.$locale.'/login');
39+
}
40+
41+
/**
42+
* @dataProvider getLocales
43+
*/
44+
public function testAccessRestrictedResourceWithForward($locale)
45+
{
46+
$client = $this->createClient(array('test_case' => 'StandardFormLogin', 'root_config' => 'localized_routes_with_forward.yml'));
47+
$client->insulate();
48+
49+
$crawler = $client->request('GET', '/'.$locale.'/secure/');
50+
$this->assertEquals(1, count($crawler->selectButton('login')), (string) $client->getResponse());
51+
}
52+
2953
public function getLocales()
3054
{
3155
return array(array('en'), array('de'));

src/Symfony/Bundle/SecurityBundle/Tests/Functional/SecurityRoutingIntegrationTest.php

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,37 @@
1313

1414
class SecurityRoutingIntegrationTest extends WebTestCase
1515
{
16-
public function testRoutingErrorIsNotExposedForProtectedResourceWhenAnonymous()
16+
/**
17+
* @dataProvider getConfigs
18+
*/
19+
public function testRoutingErrorIsNotExposedForProtectedResourceWhenAnonymous($config)
1720
{
18-
$client = $this->createClient(array('test_case' => 'StandardFormLogin'));
21+
$client = $this->createClient(array('test_case' => 'StandardFormLogin', 'root_config' => $config));
22+
$client->insulate();
1923
$client->request('GET', '/protected_resource');
2024

2125
$this->assertRedirect($client->getResponse(), '/login');
2226
}
2327

24-
public function testRoutingErrorIsExposedWhenNotProtected()
28+
/**
29+
* @dataProvider getConfigs
30+
*/
31+
public function testRoutingErrorIsExposedWhenNotProtected($config)
2532
{
26-
$client = $this->createClient(array('test_case' => 'StandardFormLogin'));
33+
$client = $this->createClient(array('test_case' => 'StandardFormLogin', 'root_config' => $config));
34+
$client->insulate();
2735
$client->request('GET', '/unprotected_resource');
2836

29-
$this->assertEquals(404, $client->getResponse()->getStatusCode());
37+
$this->assertEquals(404, $client->getResponse()->getStatusCode(), (string) $client->getResponse());
3038
}
3139

32-
public function testRoutingErrorIsNotExposedForProtectedResourceWhenLoggedInWithInsufficientRights()
40+
/**
41+
* @dataProvider getConfigs
42+
*/
43+
public function testRoutingErrorIsNotExposedForProtectedResourceWhenLoggedInWithInsufficientRights($config)
3344
{
34-
$client = $this->createClient(array('test_case' => 'StandardFormLogin'));
45+
$client = $this->createClient(array('test_case' => 'StandardFormLogin', 'root_config' => $config));
46+
$client->insulate();
3547

3648
$form = $client->request('GET', '/login')->selectButton('login')->form();
3749
$form['_username'] = 'johannes';
@@ -43,6 +55,11 @@ public function testRoutingErrorIsNotExposedForProtectedResourceWhenLoggedInWith
4355
$this->assertNotEquals(404, $client->getResponse()->getStatusCode());
4456
}
4557

58+
public function getConfigs()
59+
{
60+
return array(array('config.yml'), array('routes_as_path.yml'));
61+
}
62+
4663
protected function setUp()
4764
{
4865
parent::setUp();

src/Symfony/Bundle/SecurityBundle/Tests/Functional/WebTestCase.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class WebTestCase extends BaseWebTestCase
1818
{
1919
static public function assertRedirect($response, $location)
2020
{
21-
self::assertTrue($response->isRedirect());
21+
self::assertTrue($response->isRedirect(), 'Response is not a redirect, got status code: '.$response->getStatusCode());
2222
self::assertEquals('http://localhost'.$location, $response->headers->get('Location'));
2323
}
2424

src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/localized_routes.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,8 @@ security:
1919
logout:
2020
path: localized_logout_path
2121
target: localized_logout_target_path
22-
anonymous: ~
22+
anonymous: ~
23+
24+
access_control:
25+
- { path: '^/(?:[a-z]{2})/secure/.*', roles: ROLE_USER }
26+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
imports:
2+
- { resource: ./localized_routes.yml }
3+
4+
security:
5+
firewalls:
6+
default:
7+
form_login:
8+
use_forward: true
9+
failure_forward: true

src/Symfony/Component/HttpFoundation/RequestMatcher.php

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,7 @@ public function matches(Request $request)
100100
}
101101

102102
if (null !== $this->path) {
103-
if (null !== $session = $request->getSession()) {
104-
$path = strtr($this->path, array('{_locale}' => $session->getLocale(), '#' => '\\#'));
105-
} else {
106-
$path = str_replace('#', '\\#', $this->path);
107-
}
103+
$path = str_replace('#', '\\#', $this->path);
108104

109105
if (!preg_match('#'.$path.'#', $request->getPathInfo())) {
110106
return false;

src/Symfony/Component/Security/Http/HttpUtils.php

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
namespace Symfony\Component\Security\Http;
1313

14+
use Symfony\Component\Security\Core\SecurityContextInterface;
15+
1416
use Symfony\Component\HttpFoundation\Request;
1517
use Symfony\Component\HttpFoundation\RedirectResponse;
1618
use Symfony\Component\Routing\RouterInterface;
@@ -45,22 +47,10 @@ public function __construct(RouterInterface $router = null)
4547
*/
4648
public function createRedirectResponse(Request $request, $path, $status = 302)
4749
{
48-
if (0 === strpos($path, '/')) {
50+
if ('/' === $path[0]) {
4951
$path = $request->getUriForPath($path);
5052
} elseif (0 !== strpos($path, 'http')) {
51-
// hack (don't have a better solution for now)
52-
$context = $this->router->getContext();
53-
try {
54-
$parameters = $this->router->match($request->getPathInfo());
55-
} catch (\Exception $e) {
56-
}
57-
58-
if (isset($parameters['_locale'])) {
59-
$context->setParameter('_locale', $parameters['_locale']);
60-
} elseif ($session = $request->getSession()) {
61-
$context->setParameter('_locale', $session->getLocale());
62-
}
63-
53+
$this->resetLocale($request);
6454
$path = $this->generateUrl($path, true);
6555
}
6656

@@ -78,10 +68,26 @@ public function createRedirectResponse(Request $request, $path, $status = 302)
7868
public function createRequest(Request $request, $path)
7969
{
8070
if ($path && '/' !== $path[0] && 0 !== strpos($path, 'http')) {
71+
$this->resetLocale($request);
8172
$path = $this->generateUrl($path, true);
8273
}
8374

84-
return Request::create($path, 'get', array(), $request->cookies->all(), array(), $request->server->all());
75+
$newRequest = Request::create($path, 'get', array(), $request->cookies->all(), array(), $request->server->all());
76+
if ($session = $request->getSession()) {
77+
$newRequest->setSession($session);
78+
}
79+
80+
if ($request->attributes->has(SecurityContextInterface::AUTHENTICATION_ERROR)) {
81+
$newRequest->attributes->set(SecurityContextInterface::AUTHENTICATION_ERROR, $request->attributes->get(SecurityContextInterface::AUTHENTICATION_ERROR));
82+
}
83+
if ($request->attributes->has(SecurityContextInterface::ACCESS_DENIED_ERROR)) {
84+
$newRequest->attributes->set(SecurityContextInterface::ACCESS_DENIED_ERROR, $request->attributes->get(SecurityContextInterface::ACCESS_DENIED_ERROR));
85+
}
86+
if ($request->attributes->has(SecurityContextInterface::LAST_USERNAME)) {
87+
$newRequest->attributes->set(SecurityContextInterface::LAST_USERNAME, $request->attributes->get(SecurityContextInterface::LAST_USERNAME));
88+
}
89+
90+
return $newRequest;
8591
}
8692

8793
/**
@@ -107,6 +113,27 @@ public function checkRequestPath(Request $request, $path)
107113
return $path === $request->getPathInfo();
108114
}
109115

116+
// hack (don't have a better solution for now)
117+
private function resetLocale(Request $request)
118+
{
119+
$context = $this->router->getContext();
120+
if ($context->getParameter('_locale')) {
121+
return;
122+
}
123+
124+
try {
125+
$parameters = $this->router->match($request->getPathInfo());
126+
127+
if (isset($parameters['_locale'])) {
128+
$context->setParameter('_locale', $parameters['_locale']);
129+
} elseif ($session = $request->getSession()) {
130+
$context->setParameter('_locale', $session->getLocale());
131+
}
132+
} catch (\Exception $e) {
133+
// let's hope user doesn't use the locale in the path
134+
}
135+
}
136+
110137
private function generateUrl($route, $absolute = false)
111138
{
112139
if (null === $this->router) {

tests/Symfony/Tests/Component/HttpFoundation/RequestMatcherTest.php

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ public function testPath()
142142
$this->assertFalse($matcher->matches($request));
143143
}
144144

145-
public function testPathWithLocale()
145+
public function testPathWithLocaleIsNotSupported()
146146
{
147147
$matcher = new RequestMatcher();
148148
$request = Request::create('/en/login');
@@ -152,9 +152,6 @@ public function testPathWithLocale()
152152
$request->setSession($session);
153153

154154
$matcher->matchPath('^/{_locale}/login$');
155-
$this->assertTrue($matcher->matches($request));
156-
157-
$session->setLocale('de');
158155
$this->assertFalse($matcher->matches($request));
159156
}
160157

tests/Symfony/Tests/Component/Security/Http/HttpUtilsTest.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,17 @@ public function testCreateRequest()
6161
$this->assertEquals('bar', $subRequest->server->get('Foo'));
6262

6363
// route name
64+
$utils = new HttpUtils($router = $this->getMockBuilder('Symfony\Component\Routing\Router')->disableOriginalConstructor()->getMock());
65+
$router
66+
->expects($this->once())
67+
->method('generate')
68+
->will($this->returnValue('/foo/bar'))
69+
;
70+
$router
71+
->expects($this->any())
72+
->method('getContext')
73+
->will($this->returnValue($this->getMock('Symfony\Component\Routing\RequestContext')))
74+
;
6475
$subRequest = $utils->createRequest($this->getRequest(), 'foobar');
6576
$this->assertEquals('/foo/bar', $subRequest->getPathInfo());
6677

0 commit comments

Comments
 (0)