Browse Source

Add function to check access without exception message, return only true/false.

Alexander 9 năm trước cách đây
mục cha
commit
a81dae941b
3 tập tin đã thay đổi với 136 bổ sung2 xóa
  1. 43 2
      Admin/Admin.php
  2. 11 0
      Admin/AdminInterface.php
  3. 82 0
      Tests/Admin/AdminTest.php

+ 43 - 2
Admin/Admin.php

@@ -2921,9 +2921,11 @@ abstract class Admin implements AdminInterface, DomainObjectInterface
     }
 
     /**
-     * {@inheritdoc}
+     * Return list routes with permissions name.
+     *
+     * @return array
      */
-    public function checkAccess($action, $object = null)
+    protected function getAccess()
     {
         $access = array_merge(array(
             'acl'                     => 'MASTER',
@@ -2946,6 +2948,16 @@ abstract class Admin implements AdminInterface, DomainObjectInterface
             }
         }
 
+        return $access;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function checkAccess($action, $object = null)
+    {
+        $access = $this->getAccess();
+
         if (!array_key_exists($action, $access)) {
             throw new \InvalidArgumentException(sprintf('Action "%s" could not be found in access mapping. Please make sure your action is defined into your admin class accessMapping property.', $action));
         }
@@ -2961,6 +2973,35 @@ abstract class Admin implements AdminInterface, DomainObjectInterface
         }
     }
 
+    /**
+     * Hook to handle access authorization, without throw Exception.
+     *
+     * @param string $action
+     * @param object $object
+     * 
+     * @return bool
+     */
+    public function hasAccess($action, $object = null)
+    {
+        $access = $this->getAccess();
+
+        if (!array_key_exists($action, $access)) {
+            return false;
+        }
+
+        if (!is_array($access[$action])) {
+            $access[$action] = array($access[$action]);
+        }
+
+        foreach ($access[$action] as $role) {
+            if (false === $this->isGranted($role, $object)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
     /**
      * {@inheritdoc}
      */

+ 11 - 0
Admin/AdminInterface.php

@@ -1022,4 +1022,15 @@ interface AdminInterface
      *
      */
     // public function configureActionButtons($action, $object = null);
+
+//    TODO: uncomment this method for next major release
+//    /**
+//     * Hook to handle access authorization, without throw Exception
+//     *
+//     * @param string $action
+//     * @param object $object
+//     *
+//     * @return bool
+//     */
+//    public function hasAccess($action, $object = null);
 }

+ 82 - 0
Tests/Admin/AdminTest.php

@@ -133,6 +133,88 @@ class AdminTest extends \PHPUnit_Framework_TestCase
         $admin->checkAccess('custom_action');
     }
 
+    public function testHasAccessOnMadeUpAction()
+    {
+        $admin = new PostAdmin(
+            'sonata.post.admin.post',
+            'Application\Sonata\NewsBundle\Entity\Post',
+            'SonataNewsBundle:PostAdmin'
+        );
+
+        $this->assertFalse($admin->hasAccess('made-up'));
+    }
+
+    public function testHasAccess()
+    {
+        $admin = new PostAdmin(
+            'sonata.post.admin.post',
+            'Application\Sonata\NewsBundle\Entity\Post',
+            'SonataNewsBundle:PostAdmin'
+        );
+        $securityHandler = $this->prophesize(
+            'Sonata\AdminBundle\Security\Handler\SecurityHandlerInterface'
+        );
+        $securityHandler->isGranted($admin, 'CUSTOM_ROLE', $admin)->willReturn(true);
+        $securityHandler->isGranted($admin, 'EXTRA_CUSTOM_ROLE', $admin)->willReturn(false);
+        $customExtension = $this->prophesize(
+            'Sonata\AdminBundle\Admin\AdminExtension'
+        );
+        $customExtension->getAccessMapping($admin)->willReturn(
+            array('custom_action' => array('CUSTOM_ROLE', 'EXTRA_CUSTOM_ROLE'))
+        );
+        $admin->addExtension($customExtension->reveal());
+        $admin->setSecurityHandler($securityHandler->reveal());
+
+        $this->assertFalse($admin->hasAccess('custom_action'));
+    }
+
+    public function testHasAccessAllowsAccess()
+    {
+        $admin = new PostAdmin(
+            'sonata.post.admin.post',
+            'Application\Sonata\NewsBundle\Entity\Post',
+            'SonataNewsBundle:PostAdmin'
+        );
+        $securityHandler = $this->prophesize(
+            'Sonata\AdminBundle\Security\Handler\SecurityHandlerInterface'
+        );
+        $securityHandler->isGranted($admin, 'CUSTOM_ROLE', $admin)->willReturn(true);
+        $securityHandler->isGranted($admin, 'EXTRA_CUSTOM_ROLE', $admin)->willReturn(true);
+        $customExtension = $this->prophesize(
+            'Sonata\AdminBundle\Admin\AdminExtension'
+        );
+        $customExtension->getAccessMapping($admin)->willReturn(
+            array('custom_action' => array('CUSTOM_ROLE', 'EXTRA_CUSTOM_ROLE'))
+        );
+        $admin->addExtension($customExtension->reveal());
+        $admin->setSecurityHandler($securityHandler->reveal());
+
+        $this->assertTrue($admin->hasAccess('custom_action'));
+    }
+
+    public function testHasAccessAllowsAccessEditAction()
+    {
+        $admin = new PostAdmin(
+            'sonata.post.admin.post',
+            'Application\Sonata\NewsBundle\Entity\Post',
+            'SonataNewsBundle:PostAdmin'
+        );
+        $securityHandler = $this->prophesize(
+            'Sonata\AdminBundle\Security\Handler\SecurityHandlerInterface'
+        );
+        $securityHandler->isGranted($admin, 'EDIT_ROLE', $admin)->willReturn(true);
+        $customExtension = $this->prophesize(
+            'Sonata\AdminBundle\Admin\AdminExtension'
+        );
+        $customExtension->getAccessMapping($admin)->willReturn(
+            array('edit_action' => array('EDIT_ROLE'))
+        );
+        $admin->addExtension($customExtension->reveal());
+        $admin->setSecurityHandler($securityHandler->reveal());
+
+        $this->assertTrue($admin->hasAccess('edit_action'));
+    }
+
     public function testGetBreadCrumbs()
     {
         $class = 'Application\Sonata\NewsBundle\Entity\Post';