2012-10-11 75 views
7

我已经设置了一个允许用户创建特定内容的奏鸣曲管理界面,但是如何限制用户编辑由其他用户创建的内容?Sonata Admin - 只允许显示登录用户创建的内容

为了参数,用户登录并创建博客。 在博客列表视图中,仅显示用户创建的博客

目前,一切都显示给每个用户 - 我有组/角色设置来限制访问管理区域,这很好。

我目前唯一能想到的只显示特定登录用户内容的方法是覆盖模板吗?

但是,当然,这是一个明显而简单的配置设置?

回答

13

有更多的选择如何显示当前登录用户的唯一的数据:

第一首选的方法是使用Symfony's ACL,这里有more informations, how it works and how to do it in Sonata

如果您不想使用ACL,则可以通过向SQL查询(DQL查询)添加一些条件来更改默认查询,例如'WHERE adminId = 5'。这将是更多的工作,但我会告诉你基本的例子,如何去做。

通过添加新的设置器setSecurityContext在您的services.xml中更改您的管理服务的定义。我将使用管理员列出和编辑一些产品。

<service id="acme_demo_admin.product" class="Acme\Bundle\DemoAdminBundle\Admin\ProductAdmin"> 
     <tag name="sonata.admin" manager_type="orm" group="product_group" label_catalogue="admin" label="Products"/> 
     <argument /> 
     <argument>Acme\Bundle\DemoAdminBundle\Entity\Product</argument> 
     <argument>AcmeDemoAdminBundle:ProductAdmin</argument> 

     <call method="setSecurityContext"> 
      <argument type="service" id="security.context" /> 
     </call> 
    </service> 

SecurityContext是服务,它包含有关当前登录用户的信息。

在阿克米/包/ DemoAdminBundle /管理/ ProductAdmin.php添加二传手setSecurityContext和更改的createQuery方法:

<?php 

namespace Acme\Bundle\DemoAdminBundle\Admin; 

use Symfony\Component\Security\Core\SecurityContextInterface; 
// ... 

class ProductAdmin extends Admin 
{ 
    /** 
    * Security Context 
    * @var \Symfony\Component\Security\Core\SecurityContextInterface 
    */ 
    protected $securityContext; 

    public function setSecurityContext(SecurityContextInterface $securityContext) 
    { 
     $this->securityContext = $securityContext; 
    } 

    protected function configureRoutes(RouteCollection $collection) 
    { 
     //remove all routes except those, you are using in admin and you can secure by yourself 
     $collection 
       ->clearExcept(array(
        'list', 
        'edit', 
       )) 
     ; 
    } 

    public function createQuery($context = 'list') 
    { 
     $queryBuilder = $this->getModelManager()->getEntityManager($this->getClass())->createQueryBuilder(); 

     //if is logged admin, show all data 
     if ($this->securityContext->isGranted('ROLE_ADMIN')) { 
      $queryBuilder->select('p') 
        ->from($this->getClass(), 'p') 
      ; 
     } else { 
      //for other users, show only data, which belongs to them 
      $adminId = $this->securityContext->getToken()->getUser()->getAdminId(); 

      $queryBuilder->select('p') 
        ->from($this->getClass(), 'p') 
        ->where('p.adminId=:adminId') 
        ->setParameter('adminId', $adminId, Type::INTEGER) 
      ; 
     } 

     $proxyQuery = new ProxyQuery($queryBuilder); 
     return $proxyQuery; 
    } 

    //... configureListFields, configureDatagridFilters etc. 
} 

用户无需角色SONATA_ADMIN不能看到所有记录。

第二步 - 确保一些特殊路线,例如编辑 - 您应该检查当前登录的管理员是否可以编辑指定的产品。

您可以创建您的own security voter(首选解决方案)或使用自定义CRUD控制器。

在自定义CRUD控制器中:Acme/Bundle/DemoAdminBundle/Controller/ProductController.php重载editAction

<?php 
    namespace Acme\Bundle\DemoAdminBundle\Controller; 

    use Sonata\AdminBundle\Controller\CRUDController as Controller; 
    use Symfony\Component\Security\Core\Exception\AccessDeniedException; 


    class ProductAdminController extends Controller 
    { 
     public function editAction($id = null) 
     { 
      $request = $this->getRequest(); 
      $id = $request->get($this->admin->getIdParameter()); 

      $securityContext = $this->get('security.context'); 
      if (!$securityContext->isGranted('ROLE_ADMIN')) { 

       $adminId = $securityContext->getToken()->getUser()->getId(); 

       $accessGranted = //here you should check if user with adminId can edit product with $id 

       if (!$accessGranted) { 
        throw new AccessDeniedException(sprintf('Admin ID %s has no access to product with id %s', $adminId, $id)); 
       } 
      } 

      return parent::editAction($id); 
     } 

    } 

正如您所看到的,您可以重载许多方法和路由以添加所需的任何功能。但正如我之前所说,这是更多的工作,所以不要重载方法,首先检查Symfony的ACL(或者只是创建自己的安全投票者)是否是您的项目需要的。

+0

为了确保访问的安全性,最好使用[Voter](http://symfony.com/doc/master/cookbook/security/voters.html)。 –

+0

确实。我已经更新了答案。谢谢。 – pulzarraider

相关问题