Sonata Admin - 只允许显示登录用户创建的内容

Posted

技术标签:

【中文标题】Sonata Admin - 只允许显示登录用户创建的内容【英文标题】:Sonata Admin - Only allow show what logged in user has created 【发布时间】:2012-10-02 08:39:21 【问题描述】:

我设置了一个允许用户创建特定内容的奏鸣曲管理界面,但我如何限制用户编辑其他用户创建的内容?

为了争论,用户登录并创建博客。 在博客列表视图中,应该只显示用户创建的博客

目前,所有内容都会显示给每个用户 - 我确实设置了组/角色来限制对管理区域的访问,这很好。

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

但是,可以肯定,这是一个显而易见且简单的配置设置吗?

【问题讨论】:

【参考方案1】:

有更多选项如何仅显示当前登录用户的数据:

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

如果您不想使用 ACL,可以通过向 SQL 查询(DQL 查询)添加一些条件来更改默认查询,例如“WHERE adminId=5”。这将是更多的工作,但我将向您展示基本示例,如何做到这一点。

通过添加新的 setter 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 是服务,包含当前登录用户的信息。

在 Acme/Bundle/DemoAdminBundle/Admin/ProductAdmin.php 添加 setter 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 的用户无法查看所有记录。

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

您可以创建 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(或者只是创建自己的安全投票者)是否是您项目中需要的。

【讨论】:

为了保护访问权限,最好使用Voter。

以上是关于Sonata Admin - 只允许显示登录用户创建的内容的主要内容,如果未能解决你的问题,请参考以下文章

Sonata admin 一对多和多对一显示列表

Sonata Admin Bundle - 添加多步骤批处理操作

Sonata Admin Bundle:在列表视图中显示收藏总数

Sonata Admin Bundle + Sonata User Bundle:覆盖登录表单

在 Sonata Admin 登录屏幕上覆盖翻译

Symfony / Sonata Admin:编辑表单上的列表表单