Sonata Admin - Allow showing just registered user

I installed a sonata admin interface that allows users to create specific content, but how can I restrict users from editing content created by other users?

For arguments, the user logs in and creates a blog. In the blog list view, only user-created blogs should be displayed.

Currently, everything is displayed to each user - I have settings for groups / roles to restrict access to the administration areas, which works great.

The only way I can only now present specific registered user content is to override templates?

But of course, is this an obvious and simple configuration setting?

+7
source share
1 answer

There are more options for displaying only the current user data:

The first preferred way is to use the Symfony ACL , here is more information on how it works and how to do it in Sonata .

If you do not want to use the ACL, you can change the default queries by adding some conditions to the SQL query (DQL query), for example, "WHERE adminId = 5". This will be more work, but I will show you a basic example of how to do this.

Change the definition of your admin services in services.xml by adding a new setter setSecurityContext. I will use admin to list and edit some products.

<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 is a service that contains information about the currently registered user.

In Acme / Bundle / DemoAdminBundle / Admin / ProductAdmin.php add setter setSecurityContext and change the createQuery method:

 <?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. } 

Users without the SONATA_ADMIN role cannot see all records.

The second step is to protect some special routes, for exmaple edit you should check if the administrator can register the specified product at the moment.

You can create your own security selector (preferred solution) or use a custom CRUD controller.

In the CRUD user controller: Acme / Bundle / DemoAdminBundle / Controller / ProductController.php overload 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); } } 

As you can see, you can overload many methods and routes to add whatever functionality you need. But, as I said, this works more, so instead of overloading, the methods first check whether the Symfony ACL (or just create your own security selector) is suitable for what you need in your project or not.

+13
source

All Articles