diff options
author | Fabien Potencier <fabien.potencier@gmail.com> | 2013-12-26 08:59:17 +0100 |
---|---|---|
committer | Fabien Potencier <fabien.potencier@gmail.com> | 2013-12-26 08:59:17 +0100 |
commit | 7553159be393b2a5adaf195dd1a212276930cfd9 (patch) | |
tree | 8d7cb8ae73928c1a10ac7a1769351bf3c8d1e0c1 | |
parent | 476058b80d856b0df5906d674a306b3a4e200081 (diff) | |
parent | 0fff311596235f2196f9b36750ff97fbe899ab72 (diff) | |
download | symfony-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.php | 9 | ||||
-rw-r--r-- | Core/Tests/Authentication/Token/AbstractTokenTest.php | 41 | ||||
-rw-r--r-- | Core/Tests/Authorization/Voter/ExpressionVoterTest.php | 97 | ||||
-rw-r--r-- | Core/composer.json | 1 | ||||
-rw-r--r-- | Http/Firewall/ContextListener.php | 7 |
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; |