
Crédit: Yannick (Rêveries)
This article is part of a series of Article around the customization of EasyAdmin within Symfony. You can find the list of related articles and the context of it in this article : Symfony & EasyAdmin – space for extra functionalities. Since April 2025, the update to Symfony 7.2 has been done, please see the changes here: Custom Easy Admin - update to Symfony 7.2
Introduction
Let’s continue our dive into the customization of Easy Admin listing page. We’ve first looked at the fields customization. Here, we want to continue exploring the listing and its specificities.
In this second, out of three posts here, we’ll concentrate ourselves on how to define data access restrictions.
Impacted functionalities
To allow the customization of the data access into our listing, we’ll need to look at the following functionalities of EasyAdmin :
- Access restriction at the entity level

Entity restriction
Still working on the Post entity (see previous posts), we want only specific roles to be able to see the Posts : the Authors and the Publishers.
The idea is to disallow access to the whole data on the Posts for the non-author and non-publishers to the view of the data in the listing and in the details.
To do that, we’ll use the Crud entity level access restriction with a custom Voter to allow fine definition of the access rights.
The updates in the PostCrudController :
1//App/Controller/EasyAdmin/PostCrudController.php
2
3public function configureCrud(Crud $crud): Crud
4{
5 return $crud
6 ->setDefaultSort(['publishedAt' => 'DESC'])
7 // set for the entire entity (for any instance) the needed permission by using a Custom Voter
8 ->setEntityPermission(PostVoter::SHOW)
9 ;
10}
So, here we do the possibility of EasyAdmin to define permissions at the entity level by using the ->setEntityPermission() which can be used with:
- a Role
- a custom Voter
leveraging here the core security functionalities of Symfony.
The details of the PostVoter:
1//App/Security/EasyAdmin/PostVoter.php
2
3class PostVoter extends Voter
4{
5 public const CREATE = 'easyadmin_create';
6 public const SHOW = 'easyadmin_show';
7 public const PUBLISH = 'easyadmin_publish';
8 public const CANCEL = 'easyadmin_cancel';
9
10 public function __construct(private Security $security)
11 {
12 }
13
14 protected function supports(string $attribute, mixed $subject): bool
15 {
16 return (($subject instanceof Post
17 && \in_array($attribute, [self::SHOW, self::PUBLISH, self::CANCEL], true))
18 || \in_array($attribute, [self::CREATE], true)
19 );
20 }
21 protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
22 {
23 $user = $token->getUser();
24
25 // the user must be logged in; if not, deny permission
26 if (!$user instanceof User) {
27 return false;
28 }
29
30 return match ($attribute) {
31 self::SHOW => $this->voteOnShow(),
32 self::PUBLISH => $this->voteOnPublish(),
33 self::CREATE => $this->voteOnCreate(),
34 self::CANCEL => $this->voteOnCancel(),
35 default => false,
36 };
37 }
38
39 protected function voteOnShow(): bool
40 {
41 if ($this->security->isGranted(UserRoles::ROLE_AUTHOR) || $this->security->isGranted(UserRoles::ROLE_PUBLISHER)) {
42 return true;
43 }
44
45 return false;
46 }
47
48 ...
49}
Here, nothing fancy, as per the Voter functionality, we build here a PostVoter that will determine access to the Posts for specific attributes
REPOSITORY : the code of this example is available in the branch 02.Post_Workflow_Listing
All pictures of this article are of the making of the author and some can be seen here : Rêveries