浏览代码

Fix deprecated SecurityContextInterface usage

Sullivan SENECHAL 10 年之前
父节点
当前提交
9927aa2b05

+ 20 - 0
DependencyInjection/SonataAdminExtension.php

@@ -13,6 +13,7 @@ namespace Sonata\AdminBundle\DependencyInjection;
 
 use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
 use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Reference;
 use Symfony\Component\HttpKernel\DependencyInjection\Extension;
 use Symfony\Component\Config\FileLocator;
 use Symfony\Component\Config\Definition\Processor;
@@ -130,6 +131,25 @@ BOOM
 
         $loader->load('security.xml');
 
+        // Set the SecurityContext for Symfony <2.6
+        // TODO: Go back to simple xml configuration when bumping requirements to SF 2.6+
+        if (interface_exists('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface')) {
+            $tokenStorageReference = new Reference('security.token_storage');
+            $authorizationCheckerReference = new Reference('security.authorization_checker');
+        } else {
+            $tokenStorageReference = new Reference('security.context');
+            $authorizationCheckerReference = new Reference('security.context');
+        }
+        $container
+            ->getDefinition('sonata.admin.security.handler.role')
+            ->replaceArgument(0, $tokenStorageReference)
+        ;
+        $container
+            ->getDefinition('sonata.admin.security.handler.acl')
+            ->replaceArgument(0, $tokenStorageReference)
+            ->replaceArgument(1, $authorizationCheckerReference)
+        ;
+
         $container->setParameter('sonata.admin.extension.map', $config['extensions']);
 
         /**

+ 3 - 2
Resources/config/security.xml

@@ -16,13 +16,14 @@
     <services>
         <service id="sonata.admin.security.handler.noop" class="%sonata.admin.security.handler.noop.class%" public="false" />
         <service id="sonata.admin.security.handler.role" class="%sonata.admin.security.handler.role.class%" public="false">
-            <argument type="service" id="security.context" on-invalid="null" />
+            <argument /> <!-- security.token_storage or security.context for Symfony <2.6 -->
             <argument type="collection">
                 <argument>ROLE_SUPER_ADMIN</argument>
             </argument>
         </service>
         <service id="sonata.admin.security.handler.acl" class="%sonata.admin.security.handler.acl.class%" public="false">
-            <argument type="service" id="security.context" on-invalid="null" />
+            <argument /> <!-- security.token_storage or security.context for Symfony <2.6 -->
+            <argument /> <!-- security.authorization_checker or security.context for Symfony <2.6 -->
             <argument type="service" id="security.acl.provider" on-invalid="null" />
             <argument>%sonata.admin.security.mask.builder.class%</argument>
             <argument type="collection">

+ 34 - 12
Security/Handler/AclSecurityHandler.php

@@ -11,6 +11,8 @@
 
 namespace Sonata\AdminBundle\Security\Handler;
 
+use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
+use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
 use Symfony\Component\Security\Core\SecurityContextInterface;
 use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
 use Symfony\Component\Security\Acl\Model\MutableAclProviderInterface;
@@ -31,7 +33,16 @@ use Sonata\AdminBundle\Admin\AdminInterface;
  */
 class AclSecurityHandler implements AclSecurityHandlerInterface
 {
-    protected $securityContext;
+    /**
+     * @var TokenStorageInterface|SecurityContextInterface
+     */
+    protected $tokenStorage;
+
+    /**
+     * @var AuthorizationCheckerInterface|SecurityContextInterface
+     */
+    protected $authorizationChecker;
+
     protected $aclProvider;
     protected $superAdminRoles;
     protected $adminPermissions;
@@ -39,17 +50,28 @@ class AclSecurityHandler implements AclSecurityHandlerInterface
     protected $maskBuilderClass;
 
     /**
-     * @param \Symfony\Component\Security\Core\SecurityContextInterface         $securityContext
-     * @param \Symfony\Component\Security\Acl\Model\MutableAclProviderInterface $aclProvider
-     * @param string                                                            $maskBuilderClass
-     * @param array                                                             $superAdminRoles
+     * @param TokenStorageInterface|SecurityContextInterface $tokenStorage
+     * @param TokenStorageInterface|SecurityContextInterface $authorizationChecker
+     * @param MutableAclProviderInterface                    $aclProvider
+     * @param string                                         $maskBuilderClass
+     * @param array                                          $superAdminRoles
+     *
+     * @todo Go back to signature class check when bumping requirements to SF 2.6+
      */
-    public function __construct(SecurityContextInterface $securityContext, MutableAclProviderInterface $aclProvider, $maskBuilderClass, array $superAdminRoles)
+    public function __construct($tokenStorage, $authorizationChecker, MutableAclProviderInterface $aclProvider, $maskBuilderClass, array $superAdminRoles)
     {
-        $this->securityContext  = $securityContext;
-        $this->aclProvider      = $aclProvider;
-        $this->maskBuilderClass = $maskBuilderClass;
-        $this->superAdminRoles  = $superAdminRoles;
+        if (!$tokenStorage instanceof TokenStorageInterface && !$tokenStorage instanceof SecurityContextInterface) {
+            throw new \InvalidArgumentException('Argument 1 should be an instance of Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface or Symfony\Component\Security\Core\SecurityContextInterface');
+        }
+        if (!$authorizationChecker instanceof AuthorizationCheckerInterface && !$authorizationChecker instanceof SecurityContextInterface) {
+            throw new \InvalidArgumentException('Argument 2 should be an instance of Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface or Symfony\Component\Security\Core\SecurityContextInterface');
+        }
+
+        $this->tokenStorage         = $tokenStorage;
+        $this->authorizationChecker = $authorizationChecker;
+        $this->aclProvider          = $aclProvider;
+        $this->maskBuilderClass     = $maskBuilderClass;
+        $this->superAdminRoles      = $superAdminRoles;
     }
 
     /**
@@ -94,7 +116,7 @@ class AclSecurityHandler implements AclSecurityHandlerInterface
         }
 
         try {
-            return $this->securityContext->isGranted($this->superAdminRoles) || $this->securityContext->isGranted($attributes, $object);
+            return $this->authorizationChecker->isGranted($this->superAdminRoles) || $this->authorizationChecker->isGranted($attributes, $object);
         } catch (AuthenticationCredentialsNotFoundException $e) {
             return false;
         } catch (\Exception $e) {
@@ -138,7 +160,7 @@ class AclSecurityHandler implements AclSecurityHandlerInterface
         }
 
         // retrieving the security identity of the currently logged-in user
-        $user             = $this->securityContext->getToken()->getUser();
+        $user             = $this->tokenStorage->getToken()->getUser();
         $securityIdentity = UserSecurityIdentity::fromAccount($user);
 
         $this->addObjectOwner($acl, $securityIdentity);

+ 17 - 7
Security/Handler/RoleSecurityHandler.php

@@ -11,6 +11,7 @@
 
 namespace Sonata\AdminBundle\Security\Handler;
 
+use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
 use Symfony\Component\Security\Core\SecurityContextInterface;
 use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
 use Sonata\AdminBundle\Admin\AdminInterface;
@@ -23,17 +24,26 @@ use Sonata\AdminBundle\Admin\AdminInterface;
  */
 class RoleSecurityHandler implements SecurityHandlerInterface
 {
-    protected $securityContext;
+    /**
+     * @var TokenStorageInterface|SecurityContextInterface
+     */
+    protected $tokenStorage;
 
     protected $superAdminRoles;
 
     /**
-     * @param \Symfony\Component\Security\Core\SecurityContextInterface $securityContext
-     * @param array                                                     $superAdminRoles
+     * @param TokenStorageInterface|SecurityContextInterface $tokenStorage
+     * @param array                                          $superAdminRoles
+     *
+     * @todo Go back to signature class check when bumping requirements to SF 2.6+
      */
-    public function __construct(SecurityContextInterface $securityContext, array $superAdminRoles)
+    public function __construct($tokenStorage, array $superAdminRoles)
     {
-        $this->securityContext = $securityContext;
+        if (!$tokenStorage instanceof TokenStorageInterface && !$tokenStorage instanceof SecurityContextInterface) {
+            throw new \InvalidArgumentException('Argument 1 should be an instance of Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface or Symfony\Component\Security\Core\SecurityContextInterface');
+        }
+
+        $this->tokenStorage = $tokenStorage;
         $this->superAdminRoles = $superAdminRoles;
     }
 
@@ -51,8 +61,8 @@ class RoleSecurityHandler implements SecurityHandlerInterface
         }
 
         try {
-            return $this->securityContext->isGranted($this->superAdminRoles)
-                || $this->securityContext->isGranted($attributes, $object);
+            return $this->tokenStorage->isGranted($this->superAdminRoles)
+                || $this->tokenStorage->isGranted($attributes, $object);
         } catch (AuthenticationCredentialsNotFoundException $e) {
             return false;
         } catch (\Exception $e) {

+ 37 - 14
Tests/Security/Handler/AclSecurityHandlerTest.php

@@ -16,6 +16,29 @@ use Sonata\AdminBundle\Security\Acl\Permission\MaskBuilder;
 
 class AclSecurityHandlerTest extends \PHPUnit_Framework_TestCase
 {
+    public function getTokenStorageMock()
+    {
+        // Set the SecurityContext for Symfony <2.6
+        // TODO: Remove conditional return when bumping requirements to SF 2.6+
+        if (interface_exists('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface')) {
+            return $this->getMock('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface');
+            $this->authorizationChecker = $this->getMock('Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface');
+        }
+
+        return $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
+    }
+
+    public function getAuthorizationCheckerMock()
+    {
+        // Set the SecurityContext for Symfony <2.6
+        // TODO: Remove conditional return when bumping requirements to SF 2.6+
+        if (interface_exists('Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface')) {
+            return $this->getMock('Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface');
+        }
+
+        return $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
+    }
+
     public function testAcl()
     {
         $admin = $this->getMock('Sonata\AdminBundle\Admin\AdminInterface');
@@ -23,24 +46,24 @@ class AclSecurityHandlerTest extends \PHPUnit_Framework_TestCase
             ->method('getCode')
             ->will($this->returnValue('test'));
 
-        $securityContext = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
-        $securityContext->expects($this->any())
+        $authorizationChecker = $this->getAuthorizationCheckerMock();
+        $authorizationChecker->expects($this->any())
             ->method('isGranted')
             ->will($this->returnValue(true));
 
         $aclProvider = $this->getMock('Symfony\Component\Security\Acl\Model\MutableAclProviderInterface');
 
-        $handler = new AclSecurityHandler($securityContext, $aclProvider, 'Sonata\AdminBundle\Security\Acl\Permission\MaskBuilder', array());
+        $handler = new AclSecurityHandler($this->getTokenStorageMock(), $authorizationChecker, $aclProvider, 'Sonata\AdminBundle\Security\Acl\Permission\MaskBuilder', array());
 
         $this->assertTrue($handler->isGranted($admin, array('TOTO')));
         $this->assertTrue($handler->isGranted($admin, 'TOTO'));
 
-        $securityContext = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
-        $securityContext->expects($this->any())
+        $authorizationChecker = $this->getAuthorizationCheckerMock();
+        $authorizationChecker->expects($this->any())
             ->method('isGranted')
             ->will($this->returnValue(false));
 
-        $handler = new AclSecurityHandler($securityContext, $aclProvider, 'Sonata\AdminBundle\Security\Acl\Permission\MaskBuilder', array());
+        $handler = new AclSecurityHandler($this->getTokenStorageMock(), $authorizationChecker, $aclProvider, 'Sonata\AdminBundle\Security\Acl\Permission\MaskBuilder', array());
 
         $this->assertFalse($handler->isGranted($admin, array('TOTO')));
         $this->assertFalse($handler->isGranted($admin, 'TOTO'));
@@ -52,7 +75,7 @@ class AclSecurityHandlerTest extends \PHPUnit_Framework_TestCase
             'EDIT' => array('EDIT')
         );
 
-        $securityContext = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
+        $authorizationChecker = $this->getAuthorizationCheckerMock();
         $admin = $this->getMock('Sonata\AdminBundle\Admin\AdminInterface');
         $admin->expects($this->once())
             ->method('getCode')
@@ -64,7 +87,7 @@ class AclSecurityHandlerTest extends \PHPUnit_Framework_TestCase
 
         $aclProvider = $this->getMock('Symfony\Component\Security\Acl\Model\MutableAclProviderInterface');
 
-        $handler = new AclSecurityHandler($securityContext, $aclProvider, 'Sonata\AdminBundle\Security\Acl\Permission\MaskBuilder', array());
+        $handler = new AclSecurityHandler($this->getTokenStorageMock(), $authorizationChecker, $aclProvider, 'Sonata\AdminBundle\Security\Acl\Permission\MaskBuilder', array());
 
         $results = $handler->buildSecurityInformation($admin);
 
@@ -75,14 +98,14 @@ class AclSecurityHandlerTest extends \PHPUnit_Framework_TestCase
     {
         $admin = $this->getMock('Sonata\AdminBundle\Admin\AdminInterface');
 
-        $securityContext = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
-        $securityContext->expects($this->any())
+        $authorizationChecker = $this->getAuthorizationCheckerMock();
+        $authorizationChecker->expects($this->any())
             ->method('isGranted')
             ->will($this->throwException(new AuthenticationCredentialsNotFoundException('FAIL')));
 
         $aclProvider = $this->getMock('Symfony\Component\Security\Acl\Model\MutableAclProviderInterface');
 
-        $handler = new AclSecurityHandler($securityContext, $aclProvider, 'Sonata\AdminBundle\Security\Acl\Permission\MaskBuilder', array());
+        $handler = new AclSecurityHandler($this->getTokenStorageMock(), $authorizationChecker, $aclProvider, 'Sonata\AdminBundle\Security\Acl\Permission\MaskBuilder', array());
 
         $this->assertFalse($handler->isGranted($admin, 'raise exception', $admin));
     }
@@ -94,14 +117,14 @@ class AclSecurityHandlerTest extends \PHPUnit_Framework_TestCase
     {
         $admin = $this->getMock('Sonata\AdminBundle\Admin\AdminInterface');
 
-        $securityContext = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
-        $securityContext->expects($this->any())
+        $authorizationChecker = $this->getAuthorizationCheckerMock();
+        $authorizationChecker->expects($this->any())
             ->method('isGranted')
             ->will($this->throwException(new \RunTimeException('FAIL')));
 
         $aclProvider = $this->getMock('Symfony\Component\Security\Acl\Model\MutableAclProviderInterface');
 
-        $handler = new AclSecurityHandler($securityContext, $aclProvider, 'Sonata\AdminBundle\Security\Acl\Permission\MaskBuilder', array());
+        $handler = new AclSecurityHandler($this->getTokenStorageMock(), $authorizationChecker, $aclProvider, 'Sonata\AdminBundle\Security\Acl\Permission\MaskBuilder', array());
 
         $this->assertFalse($handler->isGranted($admin, 'raise exception', $admin));
     }

+ 5 - 1
UPGRADE-2.4.md

@@ -21,4 +21,8 @@ The inline validation has been migrating to CoreBundle. Just rename ``Sonata\Adm
 
 ## AdminLTE 2
 
-AdminLTE version 2 has been integrated, this should work out of the box if you havn't change templates. If not you can review the upgrade guide here : [http://almsaeedstudio.com/themes/AdminLTE/documentation/index.html#upgrade](http://almsaeedstudio.com/themes/AdminLTE/documentation/index.html#upgrade)
+AdminLTE version 2 has been integrated, this should work out of the box if you havn't change templates. If not you can review the upgrade guide here : [http://almsaeedstudio.com/themes/AdminLTE/documentation/index.html#upgrade](http://almsaeedstudio.com/themes/AdminLTE/documentation/index.html#upgrade)
+
+## AclSecurityHandler
+
+In order to fix deprecated issue by spiting `SecurityContextInterface`, `AclSecurityHandler` constructor got a new argument.