summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabien Potencier <fabien.potencier@gmail.com>2013-12-26 08:59:17 +0100
committerFabien Potencier <fabien.potencier@gmail.com>2013-12-26 08:59:17 +0100
commit7553159be393b2a5adaf195dd1a212276930cfd9 (patch)
tree8d7cb8ae73928c1a10ac7a1769351bf3c8d1e0c1
parent476058b80d856b0df5906d674a306b3a4e200081 (diff)
parent0fff311596235f2196f9b36750ff97fbe899ab72 (diff)
downloadsymfony-security-7553159be393b2a5adaf195dd1a212276930cfd9.zip
symfony-security-7553159be393b2a5adaf195dd1a212276930cfd9.tar.gz
symfony-security-7553159be393b2a5adaf195dd1a212276930cfd9.tar.bz2
Merge branch '2.4'
* 2.4: (44 commits) [FrameworkBundle] Add missing license headers Fix parent serialization of user object [DependencyInjection] fixed typo added condition to avoid skipping tests on JSON_PRETTY support add memcache, memcached, and mongodb extensions to run skipped tests [DependencyInjection] Fixed support for backslashes in service ids. fix #9356 [Security] Logger should manipulate the user reloaded from provider [FrameworkBundle] Added extra details in XMLDescriptor to improve container description fixed CS Crawler default namespace fix [BrowserKit] fixes #8311 CookieJar is totally ignorant of RFC 6265 edge cases [HttpFoundation] fixed constants that do exist in 2.3 (only in 2.4) fix 5528 let ArrayNode::normalizeValue respect order of value array provided fix #7243 allow 0 as arraynode name Fixed issue in BaseDateTimeTransformer when invalid timezone cause Transformation filed exception (closes #9403). BinaryFileResponse should also return 416 or 200 on some range-requets fix deprecated usage and clarify constructor defaults for number formatter Bumping dependency to ProxyManager to allow testing against the new 0.5.x branch changes Do normalization on tag options bumped Symfony version to 2.3.9 ...
-rw-r--r--Core/Authentication/Token/AbstractToken.php9
-rw-r--r--Core/Tests/Authentication/Token/AbstractTokenTest.php41
-rw-r--r--Core/Tests/Authorization/Voter/ExpressionVoterTest.php97
-rw-r--r--Core/composer.json1
-rw-r--r--Http/Firewall/ContextListener.php7
5 files changed, 151 insertions, 4 deletions
diff --git a/Core/Authentication/Token/AbstractToken.php b/Core/Authentication/Token/AbstractToken.php
index e62f73c..59510ee 100644
--- a/Core/Authentication/Token/AbstractToken.php
+++ b/Core/Authentication/Token/AbstractToken.php
@@ -142,7 +142,14 @@ abstract class AbstractToken implements TokenInterface
*/
public function serialize()
{
- return serialize(array($this->user, $this->authenticated, $this->roles, $this->attributes));
+ return serialize(
+ array(
+ is_object($this->user) ? clone $this->user : $this->user,
+ $this->authenticated,
+ $this->roles,
+ $this->attributes
+ )
+ );
}
/**
diff --git a/Core/Tests/Authentication/Token/AbstractTokenTest.php b/Core/Tests/Authentication/Token/AbstractTokenTest.php
index 928ee40..098017e 100644
--- a/Core/Tests/Authentication/Token/AbstractTokenTest.php
+++ b/Core/Tests/Authentication/Token/AbstractTokenTest.php
@@ -11,7 +11,9 @@
namespace Symfony\Component\Security\Core\Tests\Authentication\Token;
+use Symfony\Component\Security\Core\Authentication\Token\AbstractToken;
use Symfony\Component\Security\Core\Role\Role;
+use Symfony\Component\Security\Core\Role\SwitchUserRole;
class TestUser
{
@@ -28,6 +30,31 @@ class TestUser
}
}
+class ConcreteToken extends AbstractToken
+{
+ private $credentials = 'credentials_value';
+
+ public function __construct($user, array $roles = array())
+ {
+ parent::__construct($roles);
+
+ $this->setUser($user);
+ }
+
+ public function serialize()
+ {
+ return serialize(array($this->credentials, parent::serialize()));
+ }
+
+ public function unserialize($serialized)
+ {
+ list($this->credentials, $parentStr) = unserialize($serialized);
+ parent::unserialize($parentStr);
+ }
+
+ public function getCredentials() {}
+}
+
class AbstractTokenTest extends \PHPUnit_Framework_TestCase
{
public function testGetUsername()
@@ -71,6 +98,20 @@ class AbstractTokenTest extends \PHPUnit_Framework_TestCase
$this->assertEquals($token->getAttributes(), $uToken->getAttributes());
}
+ public function testSerializeParent()
+ {
+ $user = new TestUser('fabien');
+ $token = new ConcreteToken($user, array('ROLE_FOO'));
+
+ $parentToken = new ConcreteToken($user, array(new SwitchUserRole('ROLE_PREVIOUS', $token)));
+ $uToken = unserialize(serialize($parentToken));
+
+ $this->assertEquals(
+ current($parentToken->getRoles())->getSource()->getUser(),
+ current($uToken->getRoles())->getSource()->getUser()
+ );
+ }
+
/**
* @covers Symfony\Component\Security\Core\Authentication\Token\AbstractToken::__construct
*/
diff --git a/Core/Tests/Authorization/Voter/ExpressionVoterTest.php b/Core/Tests/Authorization/Voter/ExpressionVoterTest.php
new file mode 100644
index 0000000..dc8ea79
--- /dev/null
+++ b/Core/Tests/Authorization/Voter/ExpressionVoterTest.php
@@ -0,0 +1,97 @@
+<?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\Authorization\Voter;
+
+use Symfony\Component\Security\Core\Authorization\Voter\ExpressionVoter;
+use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
+use Symfony\Component\Security\Core\Role\Role;
+
+class ExpressionVoterTest extends \PHPUnit_Framework_TestCase
+{
+ public function testSupportsAttribute()
+ {
+ $expression = $this->createExpression();
+ $expressionLanguage = $this->getMock('Symfony\Component\Security\Core\Authorization\ExpressionLanguage');
+ $voter = new ExpressionVoter($expressionLanguage, $this->createTrustResolver(), $this->createRoleHierarchy());
+
+ $this->assertTrue($voter->supportsAttribute($expression));
+ }
+
+ /**
+ * @dataProvider getVoteTests
+ */
+ public function testVote($roles, $attributes, $expected, $tokenExpectsGetRoles = true, $expressionLanguageExpectsEvaluate = true)
+ {
+ $voter = new ExpressionVoter($this->createExpressionLanguage($expressionLanguageExpectsEvaluate), $this->createTrustResolver());
+
+ $this->assertSame($expected, $voter->vote($this->getToken($roles, $tokenExpectsGetRoles), null, $attributes));
+ }
+
+ public function getVoteTests()
+ {
+ return array(
+ array(array(), array(), VoterInterface::ACCESS_ABSTAIN, false, false),
+ array(array(), array('FOO'), VoterInterface::ACCESS_ABSTAIN, false, false),
+
+ array(array(), array($this->createExpression()), VoterInterface::ACCESS_DENIED, true, false),
+
+ array(array('ROLE_FOO'), array($this->createExpression(), $this->createExpression()), VoterInterface::ACCESS_GRANTED),
+ array(array('ROLE_BAR', 'ROLE_FOO'), array($this->createExpression()), VoterInterface::ACCESS_GRANTED),
+ );
+ }
+
+ protected function getToken(array $roles, $tokenExpectsGetRoles = true)
+ {
+ foreach ($roles as $i => $role) {
+ $roles[$i] = new Role($role);
+ }
+ $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
+
+ if ($tokenExpectsGetRoles) {
+ $token->expects($this->once())
+ ->method('getRoles')
+ ->will($this->returnValue($roles));
+ }
+
+ return $token;
+ }
+
+ protected function createExpressionLanguage($expressionLanguageExpectsEvaluate = true)
+ {
+ $mock = $this->getMock('Symfony\Component\Security\Core\Authorization\ExpressionLanguage');
+
+ if ($expressionLanguageExpectsEvaluate) {
+ $mock->expects($this->once())
+ ->method('evaluate')
+ ->will($this->returnValue(true));
+ }
+
+ return $mock;
+ }
+
+ protected function createTrustResolver()
+ {
+ return $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface');
+ }
+
+ protected function createRoleHierarchy()
+ {
+ return $this->getMock('Symfony\Component\Security\Core\Role\RoleHierarchyInterface');
+ }
+
+ protected function createExpression()
+ {
+ return $this->getMockBuilder('Symfony\Component\ExpressionLanguage\Expression')
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+}
diff --git a/Core/composer.json b/Core/composer.json
index 09b9765..249d4c1 100644
--- a/Core/composer.json
+++ b/Core/composer.json
@@ -20,6 +20,7 @@
},
"require-dev": {
"symfony/event-dispatcher": "~2.1",
+ "symfony/expression-language": "~2.4",
"symfony/http-foundation": "~2.4",
"symfony/validator": "~2.2",
"psr/log": "~1.0",
diff --git a/Http/Firewall/ContextListener.php b/Http/Firewall/ContextListener.php
index 2db79f3..05e260e 100644
--- a/Http/Firewall/ContextListener.php
+++ b/Http/Firewall/ContextListener.php
@@ -155,10 +155,11 @@ class ContextListener implements ListenerInterface
foreach ($this->userProviders as $provider) {
try {
- $token->setUser($provider->refreshUser($user));
+ $refreshedUser = $provider->refreshUser($user);
+ $token->setUser($refreshedUser);
if (null !== $this->logger) {
- $this->logger->debug(sprintf('Username "%s" was reloaded from user provider.', $user->getUsername()));
+ $this->logger->debug(sprintf('Username "%s" was reloaded from user provider.', $refreshedUser->getUsername()));
}
return $token;
@@ -166,7 +167,7 @@ class ContextListener implements ListenerInterface
// let's try the next user provider
} catch (UsernameNotFoundException $notFound) {
if (null !== $this->logger) {
- $this->logger->warning(sprintf('Username "%s" could not be found.', $user->getUsername()));
+ $this->logger->warning(sprintf('Username "%s" could not be found.', $notFound->getUsername()));
}
return null;