Permalink
Browse files

[Security][ACL] Fixed ObjectIdentity::fromDomainObject and UserSecuri…

…tyIdentity::from(Account|Token) when working with proxies

Backported ClassUtils class from Doctrine Common 2.2
Fixes #2611, #2056, #2048, #2035
  • Loading branch information...
jalliot committed Apr 7, 2012
1 parent 1cba0bf commit 477dfe3591444527bd840c1ba325085883c62841
@@ -11,6 +11,7 @@
namespace Symfony\Component\Security\Acl\Domain;
+use Symfony\Component\Security\Core\Util\ClassUtils;
use Symfony\Component\Security\Acl\Exception\InvalidDomainObjectException;
use Symfony\Component\Security\Acl\Model\DomainObjectInterface;
use Symfony\Component\Security\Acl\Model\ObjectIdentityInterface;
@@ -59,9 +60,9 @@ static public function fromDomainObject($domainObject)
try {
if ($domainObject instanceof DomainObjectInterface) {
- return new self($domainObject->getObjectIdentifier(), get_class($domainObject));
+ return new self($domainObject->getObjectIdentifier(), ClassUtils::getRealClass($domainObject));
} elseif (method_exists($domainObject, 'getId')) {
- return new self($domainObject->getId(), get_class($domainObject));
+ return new self($domainObject->getId(), ClassUtils::getRealClass($domainObject));
}
} catch (\InvalidArgumentException $invalid) {
throw new InvalidDomainObjectException($invalid->getMessage(), 0, $invalid);
@@ -13,6 +13,7 @@
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\User\UserInterface;
+use Symfony\Component\Security\Core\Util\ClassUtils;
use Symfony\Component\Security\Acl\Model\SecurityIdentityInterface;
/**
@@ -52,7 +53,7 @@ public function __construct($username, $class)
*/
static public function fromAccount(UserInterface $user)
{
- return new self($user->getUsername(), get_class($user));
+ return new self($user->getUsername(), ClassUtils::getRealClass($user));
}
/**
@@ -69,7 +70,7 @@ static public function fromToken(TokenInterface $token)
return self::fromAccount($user);
}
- return new self((string) $user, is_object($user)? get_class($user) : get_class($token));
+ return new self((string) $user, is_object($user) ? ClassUtils::getRealClass($user) : ClassUtils::getRealClass($token));
}
/**
View
@@ -0,0 +1,55 @@
+<?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\Util;
+
+/**
+ * Class related functionality for objects that
+ * might or might not be proxy objects at the moment.
+ *
+ * @see Doctrine\Common\Util\ClassUtils
+ *
+ * @author Benjamin Eberlei <kontakt@beberlei.de>
+ * @author Johannes Schmitt <schmittjoh@gmail.com>
+ */
+class ClassUtils
+{
+ /**
+ * Marker for Proxy class names.
+ *
+ * @var string
+ */
+ const MARKER = '__CG__';
+
+ /**
+ * Length of the proxy marker
+ *
+ * @var int
+ */
+ const MARKER_LENGTH = 6;
+
+ /**
+ * Gets the real class name of a class name that could be a proxy.
+ *
+ * @param string|object
+ * @return string
+ */
+ public static function getRealClass($object)
+ {
+ $class = is_object($object) ? get_class($object) : $object;
+
+ if (false === $pos = strrpos($class, '\\'.self::MARKER.'\\')) {
+ return $class;
+ }
+
+ return substr($class, $pos + self::MARKER_LENGTH + 2);
+ }
+}
@@ -9,83 +9,108 @@
* file that was distributed with this source code.
*/
-namespace Symfony\Component\Security\Tests\Acl\Domain;
-
-use Symfony\Component\Security\Acl\Domain\ObjectIdentity;
-
-class ObjectIdentityTest extends \PHPUnit_Framework_TestCase
+namespace Symfony\Component\Security\Tests\Acl\Domain
{
- public function testConstructor()
+ use Symfony\Component\Security\Acl\Domain\ObjectIdentity;
+
+ class ObjectIdentityTest extends \PHPUnit_Framework_TestCase
{
- $id = new ObjectIdentity('fooid', 'footype');
-
- $this->assertEquals('fooid', $id->getIdentifier());
- $this->assertEquals('footype', $id->getType());
- }
-
- public function testFromDomainObjectPrefersInterfaceOverGetId()
- {
- $domainObject = $this->getMock('Symfony\Component\Security\Acl\Model\DomainObjectInterface');
- $domainObject
- ->expects($this->once())
- ->method('getObjectIdentifier')
- ->will($this->returnValue('getObjectIdentifier()'))
- ;
- $domainObject
- ->expects($this->never())
- ->method('getId')
- ->will($this->returnValue('getId()'))
- ;
-
- $id = ObjectIdentity::fromDomainObject($domainObject);
- $this->assertEquals('getObjectIdentifier()', $id->getIdentifier());
- }
+ public function testConstructor()
+ {
+ $id = new ObjectIdentity('fooid', 'footype');
+
+ $this->assertEquals('fooid', $id->getIdentifier());
+ $this->assertEquals('footype', $id->getType());
+ }
- public function testFromDomainObjectWithoutInterface()
- {
- $id = ObjectIdentity::fromDomainObject(new TestDomainObject());
- $this->assertEquals('getId()', $id->getIdentifier());
- }
+ // Test that constructor never changes passed type, even with proxies
+ public function testConstructorWithProxy()
+ {
+ $id = new ObjectIdentity('fooid', 'Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Tests\Acl\Domain\TestDomainObject');
- /**
- * @dataProvider getCompareData
- */
- public function testEquals($oid1, $oid2, $equal)
- {
- if ($equal) {
- $this->assertTrue($oid1->equals($oid2));
- } else {
- $this->assertFalse($oid1->equals($oid2));
+ $this->assertEquals('fooid', $id->getIdentifier());
+ $this->assertEquals('Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Tests\Acl\Domain\TestDomainObject', $id->getType());
+ }
+
+ public function testFromDomainObjectPrefersInterfaceOverGetId()
+ {
+ $domainObject = $this->getMock('Symfony\Component\Security\Acl\Model\DomainObjectInterface');
+ $domainObject
+ ->expects($this->once())
+ ->method('getObjectIdentifier')
+ ->will($this->returnValue('getObjectIdentifier()'))
+ ;
+ $domainObject
+ ->expects($this->never())
+ ->method('getId')
+ ->will($this->returnValue('getId()'))
+ ;
+
+ $id = ObjectIdentity::fromDomainObject($domainObject);
+ $this->assertEquals('getObjectIdentifier()', $id->getIdentifier());
+ }
+
+ public function testFromDomainObjectWithoutInterface()
+ {
+ $id = ObjectIdentity::fromDomainObject(new TestDomainObject());
+ $this->assertEquals('getId()', $id->getIdentifier());
+ $this->assertEquals('Symfony\Component\Security\Tests\Acl\Domain\TestDomainObject', $id->getType());
}
- }
- public function getCompareData()
- {
- return array(
- array(new ObjectIdentity('123', 'foo'), new ObjectIdentity('123', 'foo'), true),
- array(new ObjectIdentity('123', 'foo'), new ObjectIdentity(123, 'foo'), true),
- array(new ObjectIdentity('1', 'foo'), new ObjectIdentity('2', 'foo'), false),
- array(new ObjectIdentity('1', 'bla'), new ObjectIdentity('1', 'blub'), false),
- );
+ public function testFromDomainObjectWithProxy()
+ {
+ $id = ObjectIdentity::fromDomainObject(new \Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Tests\Acl\Domain\TestDomainObject());
+ $this->assertEquals('getId()', $id->getIdentifier());
+ $this->assertEquals('Symfony\Component\Security\Tests\Acl\Domain\TestDomainObject', $id->getType());
+ }
+
+ /**
+ * @dataProvider getCompareData
+ */
+ public function testEquals($oid1, $oid2, $equal)
+ {
+ if ($equal) {
+ $this->assertTrue($oid1->equals($oid2));
+ } else {
+ $this->assertFalse($oid1->equals($oid2));
+ }
+ }
+
+ public function getCompareData()
+ {
+ return array(
+ array(new ObjectIdentity('123', 'foo'), new ObjectIdentity('123', 'foo'), true),
+ array(new ObjectIdentity('123', 'foo'), new ObjectIdentity(123, 'foo'), true),
+ array(new ObjectIdentity('1', 'foo'), new ObjectIdentity('2', 'foo'), false),
+ array(new ObjectIdentity('1', 'bla'), new ObjectIdentity('1', 'blub'), false),
+ );
+ }
+
+ protected function setUp()
+ {
+ if (!class_exists('Doctrine\DBAL\DriverManager')) {
+ $this->markTestSkipped('The Doctrine2 DBAL is required for this test');
+ }
+ }
}
-
- protected function setUp()
+
+ class TestDomainObject
{
- if (!class_exists('Doctrine\DBAL\DriverManager')) {
- $this->markTestSkipped('The Doctrine2 DBAL is required for this test');
+ public function getObjectIdentifier()
+ {
+ return 'getObjectIdentifier()';
+ }
+
+ public function getId()
+ {
+ return 'getId()';
}
}
}
-class TestDomainObject
+namespace Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Tests\Acl\Domain
{
- public function getObjectIdentifier()
- {
- return 'getObjectIdentifier()';
- }
-
- public function getId()
+ class TestDomainObject extends \Symfony\Component\Security\Tests\Acl\Domain\TestDomainObject
{
- return 'getId()';
}
}
@@ -24,6 +24,15 @@ public function testConstructor()
$this->assertEquals('Foo', $id->getClass());
}
+ // Test that constructor never changes the type, even for proxies
+ public function testContructorWithProxy()
+ {
+ $id = new UserSecurityIdentity('foo', 'Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Tests\Acl\Domain\Foo');
+
+ $this->assertEquals('foo', $id->getUsername());
+ $this->assertEquals('Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Tests\Acl\Domain\Foo', $id->getClass());
+ }
+
/**
* @dataProvider getCompareData
*/
@@ -0,0 +1,41 @@
+<?php
+
+namespace Symfony\Component\Security\Tests\Core\Util
+{
+ use Symfony\Component\Security\Core\Util\ClassUtils;
+
+ class ClassUtilsTest extends \PHPUnit_Framework_TestCase
+ {
+ static public function dataGetClass()
+ {
+ return array(
+ array('stdClass', 'stdClass'),
+ array('Symfony\Component\Security\Core\Util\ClassUtils', 'Symfony\Component\Security\Core\Util\ClassUtils'),
+ array('MyProject\Proxies\__CG__\stdClass', 'stdClass'),
+ array('MyProject\Proxies\__CG__\OtherProject\Proxies\__CG__\stdClass', 'stdClass'),
+ array('MyProject\Proxies\__CG__\Symfony\Component\Security\Tests\Core\Util\ChildObject', 'Symfony\Component\Security\Tests\Core\Util\ChildObject'),
+ array(new TestObject(), 'Symfony\Component\Security\Tests\Core\Util\TestObject'),
+ array(new \Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Tests\Core\Util\TestObject(), 'Symfony\Component\Security\Tests\Core\Util\TestObject'),
+ );
+ }
+
+ /**
+ * @dataProvider dataGetClass
+ */
+ public function testGetRealClass($object, $expectedClassName)
+ {
+ $this->assertEquals($expectedClassName, ClassUtils::getRealClass($object));
+ }
+ }
+
+ class TestObject
+ {
+ }
+}
+
+namespace Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Tests\Core\Util
+{
+ class TestObject extends \Symfony\Component\Security\Tests\Core\Util\TestObject
+ {
+ }
+}

0 comments on commit 477dfe3

Please sign in to comment.