我已經設置了一個允許用戶創建特定內容的奏鳴曲管理界面,但是如何限制用戶編輯由其他用戶創建的內容?Sonata Admin - 只允許顯示登錄用戶創建的內容
爲了參數,用戶登錄並創建博客。 在博客列表視圖中,僅顯示用戶創建的博客。
目前,一切都顯示給每個用戶 - 我有組/角色設置來限制訪問管理區域,這很好。
我目前唯一能想到的只顯示特定登錄用戶內容的方法是覆蓋模板嗎?
但是,當然,這是一個明顯而簡單的配置設置?
我已經設置了一個允許用戶創建特定內容的奏鳴曲管理界面,但是如何限制用戶編輯由其他用戶創建的內容?Sonata Admin - 只允許顯示登錄用戶創建的內容
爲了參數,用戶登錄並創建博客。 在博客列表視圖中,僅顯示用戶創建的博客。
目前,一切都顯示給每個用戶 - 我有組/角色設置來限制訪問管理區域,這很好。
我目前唯一能想到的只顯示特定登錄用戶內容的方法是覆蓋模板嗎?
但是,當然,這是一個明顯而簡單的配置設置?
有更多的選擇如何顯示當前登錄用戶的唯一的數據:
第一首選的方法是使用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(或者只是創建自己的安全投票者)是否是您的項目需要的。
爲了確保訪問的安全性,最好使用[Voter](http://symfony.com/doc/master/cookbook/security/voters.html)。 –
確實。我已經更新了答案。謝謝。 – pulzarraider