Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show menus and allow actions based on roles and permissions #807

Closed
reypm opened this issue Jan 17, 2016 · 51 comments

Comments

Projects
None yet
@reypm
Copy link
Contributor

commented Jan 17, 2016

I'm not sure if this has been discussed before or whether the new functionality supports menus, if so my sincere apologies.

Let's say my admin is complete, has all its menus and sub-menus. Is there any way to restrict access to certain menus|sub-menus and possibly actions based on roles and permissions in EasyAdmin?

Let's said:

  • user with ROL_EDITOR can only access list and edit actions but can't add or delete and can access menu-1, menu-2 and menu-3 but not the rest of the menus defined on the admin
  • user with ROL_VIEWER can only access list action but can't add or edit or delete and can access menu-1 and sub-menu 1.1 but not the rest of the menus defined on the admin

Is this complex setup allowed in EasyAdmin? If not any ideas to achieve something like this?

@javiereguiluz

This comment has been minimized.

Copy link
Collaborator

commented Jan 17, 2016

Thanks for proposing this feature!

For now, this feature is not available. It's in our long-term roadmap, so it will take a while before we implement it. The reason is that it's very hard to do it right.

These are the alternatives that I can give you:

  1. If hiding things is to make it easier to use, you can use a CSS trick. Add the user role as a CSS class in the body of the layout:
{% block body_class %}{{ app.user.roles|default|([])join(' ')|lower }}{% endblock %}

Then, in your custom CSS you just hide the parts you don't want those users to see:

body.role_user .sidebar-menu ... { display: none; }
  1. If you really want to remove those elements from the page, you'll have to override the default templates. Luckily, after the last big redesign, the code of the templates will be stable and your maintenance work will be small.

If you must do a heavy use of security and roles, another alternative is to forget about EasyAdmin for that backend and use Sonata instead.

I'm closing this issue because we are ware of this feature and we labeled it with future + feature so we don't loose track of it. Thanks!

@reypm

This comment has been minimized.

Copy link
Contributor Author

commented Jan 17, 2016

@javiereguiluz Excellent! glad to help improve this bundle and not I don't go back to Sonata I'd like to much EasyAdmin 😄

"If you really want to remove those elements from the page, you'll have to override the default templates. Luckily, after the last big redesign, the code of the templates will be stable and your maintenance work will be small." can you put a little example of what is on your mind regarding this one? I can use the first approach for now but would also like to play with 2nd but need a little example first, could you add it?

@reypm

This comment has been minimized.

Copy link
Contributor Author

commented Jan 18, 2016

Hi there @javiereguiluz I am using your snippet:

{#app/Resources/views/easy_admin/layout.html.twig#}    
{% extends '@EasyAdmin/default/layout.html.twig' %}
{% block body_class %}{{ app.user.roles|default|([])join('')|lower }}{% endblock %}

But I am getting this error:

Unexpected token "punctuation" of value "(" ("name" expected) in easy_admin/layout.html.twig at line 3.

Could you give me some advice?

@javiereguiluz

This comment has been minimized.

Copy link
Collaborator

commented Jan 18, 2016

This line:

{% block body_class %}{{ app.user.roles|default|([])join('')|lower }}{% endblock %}

should be:

{% block body_class %}{{ app.user.roles|default([])|join(' ')|lower }}{% endblock %}

Anyway, keep in mind that this trick is just to hide things in an unsecure way. If you need real security, you can't use this.

@reypm

This comment has been minimized.

Copy link
Contributor Author

commented Jan 18, 2016

@javiereguiluz yes, thx I can use this for now, it's a internal app and I don't know hackers will go after it lol.

After user gets logged in I can see this in the web debug toolbar:

Roles   [ROLE_ADMIN, ROLE_USER]
Inherited Roles [ROLE_USER, ROLE_CHATTER]

But those values are not in the body class, should them be there?

@javiereguiluz

This comment has been minimized.

Copy link
Collaborator

commented Jan 18, 2016

This code app.user.roles|default([])|join(' ')|lower should make your <body> look like this:

<body ... class="... role_admin role_user" ... >
@reypm

This comment has been minimized.

Copy link
Contributor Author

commented Jan 19, 2016

@javiereguiluz I don't want to go back to Sonata and I love EasyAdmin I'll start working on this feature on my own but I need a few ideas on how to start and where from this means what should I understand, where I need to look and hook or so on the EasyAdmin side. Can you give me this? Perhaps will not be a good solution what I would do but maybe could be integrated sooner if I end it. For now I will use FOSUser roles and kind of permissions for give access to menus and/or actions on controllers.

@javiereguiluz

This comment has been minimized.

Copy link
Collaborator

commented Jan 20, 2016

I haven't tested this, but you could start as follows:

  • Add a new role (or roles to support several) to everything in EasyAdmin: menu items, entities, properties.
  • Since we are very liberal regarding configuration, this role option should survive our config processing. So you have the role available in every template.
  • Redefine every relevant template to show/hide things regarding the user role.

Quick example for the menu.html.twig template:

BEFORE:

<ul class="sidebar-menu">
    {% block main_menu %}
        {% for item in easyadmin_config('design.menu') %}
            <li class="">
                {{ helper.render_menu_item(item) }}
        ...

AFTER:

<ul class="sidebar-menu">
    {% block main_menu %}
        {% for item in easyadmin_config('design.menu') if item.role in app.user.roles %}
            <li class="">
                {{ helper.render_menu_item(item) }}
        ...
@reypm

This comment has been minimized.

Copy link
Contributor Author

commented Jan 20, 2016

@javiereguiluz my idea here is define a table where I have the menu name (a label) and four basic actions: CRUD, then I can assign as many roles as I want to each of them and them apply using your code snippet. I am not sure if this is what you said at first point of your answer, I am right? If not could you improve your idea so I can catch it? Thanks

@Pierstoval

This comment has been minimized.

Copy link
Contributor

commented Jan 21, 2016

@reypm EasyAdmin should not have entities and should not create new tables, so I hope this CRUD table is only for your app.

The implementation we need is to:

  1. Set up the role property for everything in the backend (menus, actions, links, buttons, properties, controller method, etc.)
  2. Everywhere we need the role, we must check that there is a User in the security context and that it has the needed Role. Search for the user in the context is mandatory, because you might not have one if the firewall is configured with anonymous: false for example, or if the anonymous user is linked to no User object.

Don't worry, once you will make the PR we'll help you ;)

@reypm

This comment has been minimized.

Copy link
Contributor Author

commented Jan 21, 2016

@Pierstoval Even if I am not fully understand the first point (I will need a little more here, again due to my poor knowledge) what happen with dynamic roles? You're thinking only on roles defined on the security.yml or I am wrong? In my case I would like to use also roles from FOSUserBundle because the business rules can define a new roles (same as permissions) after the project ends.

@javiereguiluz

This comment has been minimized.

Copy link
Collaborator

commented Jan 21, 2016

I still think that if you make a heavy use of security/roles ... you should use Sonata or a custom development. Using EasyAdmin may hurt you in this case and make everything more complicated than it should be.

@reypm

This comment has been minimized.

Copy link
Contributor Author

commented Jan 21, 2016

@javiereguiluz the problem with Sonata is the bundle isn't ready yet for use with Symfony 2.8 or 3.0 I know they are working hard to get it done but still not ready and therefore other bundles as UserBundle aren't ready yet so I still sticky to EasyAdmin anyway this is not a thing that I will need soon and the project is a long term project so perhaps in the middle of the year I still working on the same project and you could add this feature as labeled in the future+feature ;)

@crossplatformdev

This comment has been minimized.

Copy link

commented Jul 13, 2016

@reypm If you want, you can use this twig function:

{# example security usage, see below #}
{% if is_granted('IS_AUTHENTICATED_FULLY') %}
    {# ... #}
{% endif %}
{# you can put any role up there #}

It's way better than hide content with only CSS ;-)

In order to do so, I had to override the templates by placing the @javiereguiluz folder from vendors and placing it under src and renamed the folder and subfolder, as it is indicated in Symfony book, but at first it did not work, because I was not able to match the namespace, reflecting it on the directory tree (I ask here help for this topic, as it is very related).

Just to try the twig function out, I renamed the namespace and the backslashed strings containing also the namespace and made Symfony believe that it is one of my sources (I've also modified the bundle initialization in AppKernel.php).

It works indeed, thus, I am not comfortable with having to do such a mess (rename the namespace), in order to do what Symfony is supposed to do for me, just using a valid directory tree. I ask @javiereguiluz support for that.

Also, I've successfully added these snippets on the AdminController.php file, which also works:

[edit, show]:

    $id = $this->request->query->get('id');
    $user = $this->get('security.token_storage')->getToken()->getUser();
    if ($this->isGranted("ROLE_SUPER_ADMIN") || $id === strval($user->getId())) {
         // ... Your role-granted or user id code goes here ...
    } else {
        throw new \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException();
    }
    if (!$this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) {
        //$this->renderForbiddenActionError($this->request->query->get('action'));
        throw new \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException();
    }

[list, new, index]:

    $this->denyAccessUnlessGranted('ROLE_SUPER_ADMIN', null, "You have not the right permissions to render this page!");

I just have two roles, and this trick does fit my needs. I just only need to work on the webflow (navigation) now, as the usual easy admin won't work for regular users, but it will still work great to users with ROLE_SUPER_ADMIN.

BTW, the function renderForbiddenActtionError(), did not find the template. Not even present on vendor folder, version ^1.14.

Very related to mine: http://symfony.com/doc/current/cookbook/bundles/override.html
Very related to @reypm: http://symfony.com/doc/current/book/security.html

@crossplatformdev

This comment has been minimized.

Copy link

commented Jul 17, 2016

By the way, I finally solved my issue.

To override EasyAdminBundle controller or views, you have to follow the steps described in here:

http://symfony.com/doc/current/cookbook/bundles/override.html

@javiereguiluz

This comment has been minimized.

Copy link
Collaborator

commented Jul 17, 2016

@crossplatformdev I don't recommend you to do that. EasyAdmin provides its own overriding mechanism which is easier and more powerful than the default bundle overriding mechanism.

@crossplatformdev

This comment has been minimized.

Copy link

commented Jul 17, 2016

@javiereguiluz I see your point, thank you.

I followed the documentation to override the controller and also the views.

Here is how to override the Controller:
https://github.com/javiereguiluz/EasyAdminBundle/blob/master/Resources/doc/book/7-complex-dynamic-backends.md

My AdminController:

//OhmyBundle/Controller/AdminController

/*
 * This file is part of the EasyAdminBundle.
 *
 * (c) Javier Eguiluz <javier.eguiluz@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace OhmyBundle\Controller;

use Symfony\Component\Routing\Annotation\Route;
use JavierEguiluz\Bundle\EasyAdminBundle\Controller\AdminController as BaseAdminController;
use JavierEguiluz\Bundle\EasyAdminBundle\Event\EasyAdminEvents;
use Symfony\Component\EventDispatcher\GenericEvent;
use Symfony\Component\HttpFoundation\Request as Request;

class AdminController extends BaseAdminController
{
    /**
     * @Route("/", name="easyadmin")
     * @Route("/", name="admin")
     *
     * The 'admin' route is deprecated since version 1.8.0 and it will be removed in 2.0.
     *
     * @param Request $request
     *
     * @return RedirectResponse|Response
     */
    public function indexAction(Request $request) {
        $this->denyAccessUnlessGranted('ROLE_SUPER_ADMIN', null, "You have not the right permissions to render this page!");
        $this->initialize($request);

        if (null === $request->query->get('entity')) {
            return $this->redirectToBackendHomepage();
        }

        $action = $request->query->get('action', 'list');
        if (!$this->isActionAllowed($action)) {
            throw new ForbiddenActionException(array('action' => $action, 'entity' => $this->entity['name']));
        }

        return $this->executeDynamicMethod($action . '<EntityName>Action');
    }

    /**
     * The method that is executed when the user performs a 'list' action on an entity.
     *
     * @return Response
     */
    protected function listAction() {
        $this->denyAccessUnlessGranted('ROLE_SUPER_ADMIN', null, "You have not the right permissions to render this page!");
        $this->dispatch(EasyAdminEvents::PRE_LIST);

        $fields = $this->entity['list']['fields'];
        $paginator = $this->findAll($this->entity['class'], $this->request->query->get('page', 1), $this->config['list']['max_results'], $this->request->query->get('sortField'), $this->request->query->get('sortDirection'));

        $this->dispatch(EasyAdminEvents::POST_LIST, array('paginator' => $paginator));

        return $this->render($this->entity['templates']['list'], array(
                    'paginator' => $paginator,
                    'fields' => $fields,
                    'delete_form_template' => $this->createDeleteForm($this->entity['name'], '__id__')->createView(),
        ));
    }

    /**
     * The method that is executed when the user performs a 'edit' action on an entity.
     *
     * @return RedirectResponse|Response
     */
    protected function editAction() {
        $this->dispatch(EasyAdminEvents::PRE_EDIT);

        $id = $this->request->query->get('id');
        $user = $this->get('security.token_storage')->getToken()->getUser();
        if ($this->isGranted("ROLE_SUPER_ADMIN") || $id === strval($user->getId())) {

        } else {
            throw new \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException();
            //$this->renderForbiddenActionError($this->request->query->get('action'));
        }
        if (!$this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) {
            //$this->renderForbiddenActionError($this->request->query->get('action'));
            throw new \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException();
        }


        $easyadmin = $this->request->attributes->get('easyadmin');
        $entity = $easyadmin['item'];

        if ($this->request->isXmlHttpRequest() && $property = $this->request->query->get('property')) {
            $newValue = 'true' === strtolower($this->request->query->get('newValue'));
            $fieldsMetadata = $this->entity['list']['fields'];

            if (!isset($fieldsMetadata[$property]) || 'toggle' !== $fieldsMetadata[$property]['dataType']) {
                throw new \RuntimeException(sprintf('The type of the "%s" property is not "toggle".', $property));
            }

            $this->updateEntityProperty($entity, $property, $newValue);

            return new Response((string) $newValue);
        }

        $fields = $this->entity['edit']['fields'];

        $editForm = $this->executeDynamicMethod('create<EntityName>EditForm', array($entity, $fields));
        $deleteForm = $this->createDeleteForm($this->entity['name'], $id);

        $editForm->handleRequest($this->request);
        if ($editForm->isValid()) {
            $this->dispatch(EasyAdminEvents::PRE_UPDATE, array('entity' => $entity));

            $this->executeDynamicMethod('preUpdate<EntityName>Entity', array($entity));
            $this->em->flush();

            $this->dispatch(EasyAdminEvents::POST_UPDATE, array('entity' => $entity));

            $refererUrl = $this->request->query->get('referer', '');

            return !empty($refererUrl) ? $this->redirect(urldecode($refererUrl)) : $this->redirect($this->generateUrl('easyadmin', array('action' => 'list', 'entity' => $this->entity['name'])));
        }

        $this->dispatch(EasyAdminEvents::POST_EDIT);

        return $this->render($this->entity['templates']['edit'], array(
                    'form' => $editForm->createView(),
                    'entity_fields' => $fields,
                    'entity' => $entity,
                    'delete_form' => $deleteForm->createView(),
        ));
    }

    /**
     * The method that is executed when the user performs a 'show' action on an entity.
     *
     * @return Response
     */
    protected function showAction() {
        $this->dispatch(EasyAdminEvents::PRE_SHOW);

        $id = $this->request->query->get('id');
        $user = $this->get('security.token_storage')->getToken()->getUser();
        if ($this->isGranted("ROLE_SUPER_ADMIN") || $id === strval($user->getId())) {

        } else {
            //$this->renderForbiddenActionError($this->request->query->get('action'));
            throw new \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException();
        }
        if (!$this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) {
            //$this->renderForbiddenActionError($this->request->query->get('action'));
            throw new \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException();
        }


        $easyadmin = $this->request->attributes->get('easyadmin');
        $entity = $easyadmin['item'];

        $fields = $this->entity['show']['fields'];
        $deleteForm = $this->createDeleteForm($this->entity['name'], $id);

        $this->dispatch(EasyAdminEvents::POST_SHOW, array(
            'deleteForm' => $deleteForm,
            'fields' => $fields,
            'entity' => $entity,
        ));

        return $this->render($this->entity['templates']['show'], array(
                    'entity' => $entity,
                    'fields' => $fields,
                    'delete_form' => $deleteForm->createView(),
        ));
    }

    /**
     * The method that is executed when the user performs a 'new' action on an entity.
     *
     * @return RedirectResponse|Response
     */
    protected function newAction() {
        $this->denyAccessUnlessGranted('ROLE_SUPER_ADMIN', null, "You have not the right permissions to render this page!");
        $this->dispatch(EasyAdminEvents::PRE_NEW);

        $entity = $this->executeDynamicMethod('createNew<EntityName>Entity');

        $easyadmin = $this->request->attributes->get('easyadmin');
        $easyadmin['item'] = $entity;
        $this->request->attributes->set('easyadmin', $easyadmin);

        $fields = $this->entity['new']['fields'];

        $newForm = $this->executeDynamicMethod('create<EntityName>NewForm', array($entity, $fields));

        $newForm->handleRequest($this->request);
        if ($newForm->isValid()) {
            $this->dispatch(EasyAdminEvents::PRE_PERSIST, array('entity' => $entity));

            $this->executeDynamicMethod('prePersist<EntityName>Entity', array($entity));

            $this->em->persist($entity);
            $this->em->flush();

            $this->dispatch(EasyAdminEvents::POST_PERSIST, array('entity' => $entity));

            $refererUrl = $this->request->query->get('referer', '');

            return !empty($refererUrl) ? $this->redirect(urldecode($refererUrl)) : $this->redirect($this->generateUrl('easyadmin', array('action' => 'list', 'entity' => $this->entity['name'])));
        }

        $this->dispatch(EasyAdminEvents::POST_NEW, array(
            'entity_fields' => $fields,
            'form' => $newForm,
            'entity' => $entity,
        ));

        return $this->render($this->entity['templates']['new'], array(
                    'form' => $newForm->createView(),
                    'entity_fields' => $fields,
                    'entity' => $entity,
        ));
    }

Here is how to override templates:
#464
(assume they are under 'src\OhmyBundle\Resources\views\EasyAdminBundle\views'). My config.yml is as follows:

easy_admin:
     entities:
         OhmyUser:
             templates:
                 layout: '@Ohmy/EasyAdminBundle/views/layout.html.twig'
                 edit: '@Ohmy/EasyAdminBundle/views/edit.html.twig'
                 list: '@Ohmy/EasyAdminBundle/views/list.html.twig'
                 new: '@Ohmy/EasyAdminBundle/views/new.html.twig'
                 show: '@Ohmy/EasyAdminBundle/views/show.html.twig'
                 form: '@Ohmy/EasyAdminBundle/views/form.html.twig'
                 flash_messages: '@Ohmy/EasyAdminBundle/views/flash_messages.html.twig'
                 paginator: '@Ohmy/EasyAdminBundle/views/paginator.html.twig'
                 field_array: '@Ohmy/EasyAdminBundle/views/field_array.html.twig'
                 field_association: '@Ohmy/EasyAdminBundle/views/field_association.html.twig'
                 field_bigint: '@Ohmy/EasyAdminBundle/views/field_bigint.html.twig'
                 field_boolean: '@Ohmy/EasyAdminBundle/views/field_boolean.html.twig'
                 field_date: '@Ohmy/EasyAdminBundle/views/field_date.html.twig'
                 field_datetime: '@Ohmy/EasyAdminBundle/views/field_datetime.html.twig'
                 field_datetimetz: '@Ohmy/EasyAdminBundle/views/field_datetimetz.html.twig'
                 field_decimal: '@Ohmy/EasyAdminBundle/views/field_decimal.html.twig'
                 field_float: '@Ohmy/EasyAdminBundle/views/field_float.html.twig'
                 field_id: '@Ohmy/EasyAdminBundle/views/field_id.html.twig'
                 field_image: ':easy_admin:field_image.html.twig'
                 field_integer: '@Ohmy/EasyAdminBundle/views/field_integer.html.twig'
                 field_simple_array: '@Ohmy/EasyAdminBundle/views/field_simple_array.html.twig'
                 field_smallint: '@Ohmy/EasyAdminBundle/views/field_smallint.html.twig'
                 field_string: '@Ohmy/EasyAdminBundle/views/field_string.html.twig'
                 field_text: '@Ohmy/EasyAdminBundle/views/field_text.html.twig'
                 field_time: '@Ohmy/EasyAdminBundle/views/field_time.html.twig'
                 field_toggle: '@Ohmy/EasyAdminBundle/views/field_toggle.html.twig'
                 label_empty: '@Ohmy/EasyAdminBundle/views/label_empty.html.twig'
                 label_inaccessible: '@Ohmy/EasyAdminBundle/views/label_inaccessible.html.twig'
                 label_null: ':easy_admin:label_null.html.twig'
                 label_undefined: '@Ohmy/EasyAdminBundle/views/label_undefined.html.twig'

It would be nice to have a way to override templates globally, apart than per entity.

@javiereguiluz

This comment has been minimized.

Copy link
Collaborator

commented Jul 17, 2016

It would be nice to have a way to override templates globally, apart than per entity.

There are four ways to override templates: global or per entity and config-based or convention-based. It's explained here: https://github.com/javiereguiluz/EasyAdminBundle/blob/master/Resources/doc/book/3-list-search-show-configuration.md#advanced-design-configuration and here: https://github.com/javiereguiluz/EasyAdminBundle/blob/master/Resources/doc/book/4-edit-new-configuration.md#advanced-design-configuration

@Pierstoval

This comment has been minimized.

Copy link
Contributor

commented Jul 18, 2016

Plus, @crossplatformdev , you do not need to throw
$this->denyAccessUnlessGranted('ROLE_SUPER_ADMIN', null, "You have not the right permissions to render this page!"); on each action, because indexAction is the only route EasyAdmin uses, so you should throw this exception only in indexAction

@crossplatformdev

This comment has been minimized.

Copy link

commented Jul 20, 2016

@Pierstoval is right, I missed that. I moved the logic to the indexAction, here it is:

    public function indexAction(Request $request) {
        $this->initialize($request);

        if (null === $request->query->get('entity')) {
            return $this->redirectToBackendHomepage();
        }

        $action = $request->query->get('action', 'list');
        if (!$this->isActionAllowed($action)) {
            throw new ForbiddenActionException(array('action' => $action, 'entity' => $this->entity['name']));
        }

        $user = $this->get('security.token_storage')->getToken()->getUser();
        if (!$this->isGranted("ROLE_SUPER_ADMIN")) {
            if ($request->query->get('entity') === 'OhmyUser') {
                $id = $request->query->get('id');

                if (is_null($id)) {
                    //$this->renderForbiddenActionError($this->request->query->get('action'));
                    return $this->redirect($this->generateUrl('easyadmin', array('action' => 'show', 'entity' => $this->entity['name'], 'id' => $user->getId())));
                }


                if (!$this->isGranted("ROLE_SUPER_ADMIN") && is_null($user)) {
                    //$this->renderForbiddenActionError($this->request->query->get('action'));
                    throw new \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException();
                }

                if (!$this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) {
                    //$this->renderForbiddenActionError($this->request->query->get('action'));
                    throw new \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException();
                }


                $action = $request->query->get('action');
                switch ($action) {
                    default:
                    case 'show':
                        return $this->executeDynamicMethod('show' . '<EntityName>Action');
                    case 'edit':
                        return $this->executeDynamicMethod('edit' . '<EntityName>Action');
                }
            }
        }
        return $this->executeDynamicMethod($action . '<EntityName>Action');
    }

This way I force non ROLE_SUPER_ADMIN users to be only able to view 'edit' and 'show' views. In order to acomplish that, I also had to modify the return sentences of some other actions:

Edit and Delete actions, so it does not go back tu list view unless user is privileged:

return !empty($refererUrl) ? $this->redirect(urldecode($refererUrl)) :
    $this->isGranted('ROLE_SUPER_ADMIN') ? 
        $this->redirect($this->generateUrl('easyadmin', array('action' => 'list', 'entity' => $this->entity['name']))) :
        $this->redirect($this->generateUrl('easyadmin', array('action' => 'show', 'entity' => $this->entity['name'], 'id' => $id)));

On the YAML config, I placed all the view overrides in global scope:

easyadmin:
    design:
        templates:
           layout: '@Ohmy/EasyAdminBundle/views/layout.html.twig'
           edit: '@Ohmy/EasyAdminBundle/views/edit.html.twig'
           list: '@Ohmy/EasyAdminBundle/views/list.html.twig'
           new: '@Ohmy/EasyAdminBundle/views/new.html.twig'
           show: '@Ohmy/EasyAdminBundle/views/show.html.twig'
           # Absolutely everyone. 'form' launches a dependency injection exception, 
           # as the bundle thinks it is another setting

    entities:
        Servers:
            class: OhmyBundle\Entity\Server
            label: 'Servers'
        OhmyUser:
            class: OhmyBundle\Entity\OhmyUser
            label: 'Users'
            list:
                title: "Users list."
                fields: [ {label: "User", property: "usernameCanonical" }, "phone","address","company","vat","firstName","lastName", "password"]
            show:
                title: "Show User."
                fields: [ {label: "User", property: "usernameCanonical" }, "phone","address","company","vat","firstName","lastName", "password"]
                actions: ['edit', '-delete', '-list']
            edit:
                title: "Edit User."
                fields: [ {label: "User", property: "usernameCanonical" }, "phone","address","company","vat","firstName","lastName", "password"]
                actions: ['-delete', '-list']
            new:
                title: "New User."
                fields: [ {label: "User", property: "usernameCanonical" }, "phone","address","company","vat","firstName","lastName", "password"]

So the next step is customizing the twig templates by using is_granted('ROLE_SUPER_ADMIN') function to change views behaviour based on user role. For example, in menu.html.twig, I wrote:

line 20:

        {% if is_granted('ROLE_SUPER_ADMIN') %}
        <a href="{{ path }}" {% if item.target|default(false) %}target="{{ item.target }}"{% endif %}>
            {% if item.icon is not empty %}<i class="fa {{ item.icon }}"></i>{% endif %}
            <span>{{ item.label|trans }}</span>
            {% if item.children|default([]) is not empty %}<i class="fa fa-angle-left pull-right"></i>{% endif %}
        </a>
        {% else %}
            {% if item.label == 'Servers' %}
                <a href="{{ path }}" {% if item.target|default(false) %}target="{{ item.target }}"{% endif %}>
                {% if item.icon is not empty %}<i class="fa {{ item.icon }}"></i>{% endif %}
                <span>{{ item.label|trans }}</span>
                {% if item.children|default([]) is not empty %}<i class="fa fa-angle-left pull-right"></i>{% endif %}
            {% endif %}
        {% endif `%}

Is a simple proof of concept, but it works, and is way better than hiding content by using CSS (as anyone with a F12 key could see the content ;) )

Now I almost have all the functionalities of EasyAdmin for the ROLE_SUPER_ADMIN and a very limited instance of it for regular users.

Now I am wondering if there is a way to customize view fields shown based on roles... On this case, it would be desirable for the admin to view all de FOSUser fields (OhmyUser extends the model class), while keeping regular users to view (and furthermore, edit...) only certain ones.

@javiereguiluz BTW, this function does not work at all:

$this->renderForbiddenActionError($this->request->query->get('action'));

as the twig template that it tries to render does not exist on version "^1.14".

@Glideh

This comment has been minimized.

Copy link

commented Sep 19, 2016

Here is my small workaround

class EasyAdminController extends BaseEasyAdminController
{
    private function checkPermissions()
    {
        $easyAdmin = $this->request->attributes->get('easyadmin');
        if (isset($easyAdmin['entity']['require_permission'])) {
            $requiredPermission = $easyAdmin['entity']['require_permission'];
        } else {
            $view = $easyAdmin['view'];
            $entity = $easyAdmin['entity']['name'];
            $requiredPermission = 'ROLE_'.strtoupper($view).'_'.strtoupper($entity);
            # Or any other default strategy
        }
        $this->denyAccessUnlessGranted(
            $requiredPermission, null, $requiredPermission.' permission required'
        );
    }

    /**
     * @Route("/", name="easyadmin")
     * @param Request $request
     * @return RedirectResponse|Response
     */
    public function indexAction(Request $request)
    {
        $response = parent::indexAction($request);
        $this->checkPermissions();
        return $response;
    }
#...

The menu part is quite simple.

@Pierstoval

This comment has been minimized.

Copy link
Contributor

commented Sep 20, 2016

@Glideh I like your solution! @javiereguiluz , could it be documented/implemented?

@bernardpeh

This comment has been minimized.

Copy link

commented Sep 29, 2016

hi all, chipping in my 5 cents here. first of all, thanks javier for the wonderful bundle. I think that roles and permission support is still something highly sought after but I agree that doing it correctly requires a lot of thinking and code refactoring. Ideally, we should be able to manipulate the yaml to support role, ie something along the lines of

easy_admin:
    entities:
        UserLog:
            class: AppBundle\Entity\UserLog
            label: admin.link.user_log
            role: ROLE_ADMIN
                 show:
                       actions: ['list', '-edit', '-delete']
                       .... 
            role: ROLE_USER
                list:
                    actions: ['show', '-edit', '-delete']
                    ....

We should be able to implement this using a combination of compilerpass and event listeners. For those who are interested, I've wrote a simple article describing the process. It doesn't cover everything but should points to a direction - https://leanpub.com/practicalsymfony3/read#leanpub-auto-adding-simple-access-control-to-easyadminbundle

@Pierstoval

This comment has been minimized.

Copy link
Contributor

commented Sep 29, 2016

Actually, entity metadata is really flexible and you can add custom fields as you want :)

A compiler pass cannot be used because the configuration is processed on cache warmup because it needs doctrine metadata.
By the way, this yml syntax does not work, we should find something else like

easy_admin:
    entities:
        UserLog:
            class: AppBundle\Entity\UserLog
            label: admin.link.user_log
            show:
                role: ROLE_ADMIN
                actions: ['list', '-edit', '-delete']
                .... 
            list:
                role: ROLE_USER
                actions: ['show', '-edit', '-delete']
                ....
@AntoscencoVladimir

This comment has been minimized.

Copy link

commented Jan 6, 2017

@bernardpeh Thanks man, you saved my day

@Yondz

This comment has been minimized.

Copy link

commented Feb 20, 2017

Hey guys, following to this interesting topic, I'm using something based on @Glideh solution with per-view role, not sure if it's stable enough but here's my checkPermission() version.

private function checkPermissions()
 {

     $easyAdmin = $this->request->attributes->get('easyadmin');
     
     if (isset($easyAdmin['entity'][$easyAdmin['view']]['require_permission'])) {
         $requiredPermission = $easyAdmin['entity'][$easyAdmin['view']]['require_permission'];
     } else if(isset($easyAdmin['entity']['require_permission']) ){
         $requiredPermission = $easyAdmin['entity']['require_permission'];
     } else {
         $view = $easyAdmin['view'];
         $entity = $easyAdmin['entity']['name'];
         $requiredPermission = 'ROLE_'.strtoupper($view).'_'.strtoupper($entity);
     }
     $this->denyAccessUnlessGranted(
         $requiredPermission, null, $requiredPermission.' permission required'
     );
 }

Like this I'm still keeping the default ROLE policy but I can define roles this way :

easy_admin:
  entities:
    User:
      class: AppBundle\Entity\User
      label: 'Utilisateurs'
      require_permission: "ROLE_TEST2" # Defaut permission for all views without the require_permission option
      # for new user
      new:
        require_permission: "ROLE_TEST1"
        fields:
         ...
      edit: 
         # No permission here, it'll take the one from User, or ROLE_EDIT_USER if none is defined on User
        actions: ['-delete', '-list']
        ...
@Pierstoval

This comment has been minimized.

Copy link
Contributor

commented Feb 20, 2017

@javiereguiluz Can't we use ExpressionLanguage + permission attributes/roles for this ?

We could add two options permission_expression and roles that would be handled manually.

The advantage of permission expression is that we could allow extending it and make it very flexible

@luislaborda

This comment has been minimized.

Copy link

commented Feb 21, 2017

Is the option of show/hide an entity menu item available by user role? or still to be implemented.

@Pierstoval

This comment has been minimized.

Copy link
Contributor

commented Feb 21, 2017

@luislaborda It has to be implemented, but I think @javiereguiluz is not very fond of the idea... Javier? 😉

@luislaborda

This comment has been minimized.

Copy link

commented Feb 23, 2017

@Pierstoval Thanks, it will be nice having roles because then I can limit views based on roles.

@laurent-bientz

This comment has been minimized.

Copy link
Contributor

commented Apr 10, 2017

For french people (sry), if you want to implement some ACL while waiting EasyAdmin 2.0, a quick draft of how we've implemented it in our company (based on @bernardpeh works):

https://github.com/WandiParis/documentation/blob/master/symfony/06-easy-admin-bundle-acl.md

@Pierstoval

This comment has been minimized.

Copy link
Contributor

commented Apr 10, 2017

@laurent-bientz VERY interesting! @javiereguiluz You should link this article on the next "A week of Symfony" blog post 😉 And by the way, as everything is based on templates + events + compiler pass, you could propose the very first EasyAdmin extension bundle 😉

@bernardpeh

This comment has been minimized.

Copy link

commented Apr 10, 2017

I don't know french but nice work @laurent-bientz ... An alternative to using "currentEntityConfig[actionName].role" in the views is to overwrite getActionsForItem as describe in https://leanpub.com/practicalsymfony3/read#leanpub-auto-adding-roles-to-easyadmin-actions

@laurent-bientz

This comment has been minimized.

Copy link
Contributor

commented Apr 10, 2017

@guyz, sorry for the french, it was an internal workshop ;)

@bernardpeh thx for your clever idea for overwriting actions in the view side, really great approach!
It was for us the worse, crappy and less generic part of this work, i'll give it a try on the next project.

@reypm

This comment has been minimized.

Copy link
Contributor Author

commented Apr 10, 2017

@laurent-bientz is there any chance you translate this into English? I can't understand French and this seems to be a very good work so I want to learn 👍

@laurent-bientz

This comment has been minimized.

Copy link
Contributor

commented Apr 12, 2017

@reypm not now sry, too many work.

Try to follow and adapt works from @bernardpeh, it's really nice documented:

https://leanpub.com/practicalsymfony3/read#leanpub-auto-adding-simple-access-control-to-easyadminbundle

Put your questions here if any problems.

Cheers

@djluza

This comment has been minimized.

Copy link

commented Jun 23, 2017

I just add Menu with roles. Follow these step:

1)config.yml

    menu:
        - label: 'Test'
          require_permission: ["ROLE_ADMIN", "ROLE_USER"]
          icon: 'users'
          children:
            - { label: 'Menu1', icon: 'file-new', entity: 'Clienti' }
            - { label: 'Menu2', icon: 'file-new', entity: 'Utilizzatori' }

        - label: 'Menu'
          require_permission: ["ROLE_GUEST"]
          icon: 'users'
          children:
            - { label: 'Menu1', icon: 'file-new', entity: 'Clienti' }

2)Template menu.html.twig

    {% block main_menu %}
        {% for role in app.user.roles %}
            {% for item in easyadmin_config('design.menu') %}
                {% if role in item.require_permission|default([]) %}
                    <li class="{{ item.type == 'divider' ? 'header' }} {{ item.children is not empty ? 'treeview' }} {{ app.request.query.get('menuIndex')|default(-1) == loop.index0 ? 'active' }} {{ app.request.query.get('submenuIndex')|default(-1) != -1 ? 'submenu-active' }}">
                        {{ helper.render_menu_item(item, _entity_config.translation_domain|default('messages')) }}
    
                        {% if item.children|default([]) is not empty %}
                            <ul class="treeview-menu">
                                {% for subitem in item.children %}
                                    <li class="{{ subitem.type == 'divider' ? 'header' }} {{ app.request.query.get('menuIndex')|default(-1) == loop.parent.loop.index0 and app.request.query.get('submenuIndex')|default(-1) == loop.index0 ? 'active' }}">
                                        {{ helper.render_menu_item(subitem, _entity_config.translation_domain|default('messages')) }}
                                    </li>
                                {% endfor %}
                            </ul>
                        {% endif %}
                    </li>
    
                {% endif %}
            {%  endfor %}
    
        {% endfor %}
    {% endblock main_menu %}
    

3)Thats all!

@Pierstoval

This comment has been minimized.

Copy link
Contributor

commented Jun 23, 2017

You don't even need to update the compiler pass, a simple isset() in php or |default([]) in twig makes everything work without more override :D

@djluza

This comment has been minimized.

Copy link

commented Jun 24, 2017

You are right, thank you for the clarification. 👍

@zkkan

This comment has been minimized.

Copy link

commented Aug 1, 2017

menu:
        - label: 'Test'
          require_permission: ["ROLE_ADMIN", "ROLE_USER"]
          icon: 'users'
          children:
            - { label: 'Menu1', icon: 'file-new', entity: 'Clienti' }
            - { label: 'Menu2', icon: 'file-new', entity: 'Utilizzatori' }

        - label: 'Menu'
          require_permission: ["ROLE_GUEST"]
          icon: 'users'
      children:
        - { label: 'Menu1', icon: 'file-new', entity: 'Clienti' }

How to restricting action with this implementation? I tried but it doesn't work

@djluza

This comment has been minimized.

Copy link

commented Aug 2, 2017

You can restrict action in this way:

entities:
        Clienti:
                class: App\xxx\Entity\Clienti
                controller: App\xxx\Controller\ClientiController
                require_permission: ["ROLE_ADMIN","ROLE_USER"]
                list:
                    require_permission: ["ROLE_ADMIN","ROLE_USER"]
                    actions:
                         - { name: 'new', label: 'Crea Nuovo', css_class: 'btn btn-success' }
                    title: 'Clienti'
                    fields:
                        #- { property: 'codcliente', label: 'Codice' }
                        - { property: 'desccliente', label: 'Descrizione' }
                        - { property: 'rifgruppoclienti', label: 'Riferimento Gruppo' }
                edit:
                    require_permission: ["ROLE_ADMIN","ROLE_USER"]
                    title: 'Modifica Clienti'
                    fields:
                        #- { property: 'codcliente', label: 'Codice' }
                        - { property: 'desccliente', label: 'Descrizione' }
                        - { property: 'rifgruppoclienti', label: 'Riferimento Gruppo'}
                new:
                    require_permission: ["ROLE_ADMIN","ROLE_USER"]
                    #actions:
                        #- { type: 'entity', name: 'Gruppiclienti', action: 'new', label: 'User Details' }
                    title: 'Crea Clienti'
                    fields:
                        - { type: 'section', label: 'Test Linea' }
                        #- { property: 'codcliente', label: 'Codice' }
                        - { property: 'desccliente', label: 'Descrizione' }
                        - { property: 'rifgruppoclienti', label: 'Riferimento Gruppo'}
                delete:
                    require_permission: ["ROLE_ADMIN","ROLE_USER"]

Add this code in AdminController.php

private function checkPermissions()
    {
        if (!$this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) {
            throw $this->createAccessDeniedException();
        }

        $easyAdmin = $this->request->attributes->get('easyadmin');

        $action = $this->request->query->get('action');

        $perms = $easyAdmin['entity'][$action]['require_permission'];
        $roles = $this->get('security.context')->getToken()->getUser()->getRoles();

        foreach ($roles as $key => $value)
        {

            $permessi_file = $value;

            if (in_array($permessi_file, $perms)) {

                $requiredPermission = $permessi_file;

            }
            else
            {
                $view = $easyAdmin['view'];
                $entity = $easyAdmin['entity']['name'];
                $requiredPermission = 'ROLE_'.strtoupper($view).'_'.strtoupper($entity);
                # Or any other default strategy
            }
            $this->denyAccessUnlessGranted(
                $requiredPermission, null, $requiredPermission.' permission required'
            );
        }

    }

public function indexAction(Request $request)
    {
        $this->initialize($request);

        if (null === $request->query->get('entity')) {
            return $this->redirectToBackendHomepage();
        }

        $action = $request->query->get('action', 'list');
        if (!$this->isActionAllowed($action)) {
            throw new ForbiddenActionException(array('action' => $action, 'entity_name' => $this->entity['name']));
        }
        $this->checkPermissions();
        return $this->executeDynamicMethod($action.'<EntityName>Action');
    }

@forsetius

This comment has been minimized.

Copy link
Contributor

commented Aug 2, 2017

When it comes to restricting the actions, I did it a bit differently:

# /app/config/security
parameters:
    role_hierarchy:
        ROLE_ADMIN:       ROLE_USER
        ROLE_SUPER_ADMIN: ROLE_ADMIN

security:
    role_hierarchy: '%role_hierarchy%'
# User entity definition: user.yml
security:
    role_hierarchy:
        ROLE_USER_SHOW: ~
        ROLE_USER_LIST: ROLE_USER_SEARCH
        ROLE_USER_NEW: ~
        ROLE_USER_EDIT: ~
        ROLE_USER_DELETE: ~
        ROLE_USER_SEE:
            - ROLE_USER_SHOW
            - ROLE_USER_LIST
        ROLE_USER_ALL:
            - ROLE_USER_SEE
            - ROLE_USER_NEW
            - ROLE_USER_EDIT
            - ROLE_USER_DELETE
// ...
use JavierEguiluz\Bundle\EasyAdminBundle\Controller\AdminController as BaseAdminController;
use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Security\Core\Role\RoleHierarchy;
// ...

class AdminController extends BaseAdminController
{
    public function indexAction(Request $request)
    {
        // ...
        $r = $request->query;
        if (! $this->hasRole(strtoupper('ROLE_'.$r->get('entity').'_'.$r->get('action'))) ) {
            throw $this->createAccessDeniedException();
        }
    }

    protected $roleHierarchy;
    protected function hasRole($role)
    {
        if (\is_null($this->roleHierarchy)) {
            $this->roleHierarchy = new RoleHierarchy($this->container->getParameter('security.role_hierarchy.roles'));
        }

        return \count($this->roleHierarchy->getReachableRoles([new Role($role)])) > 0;
    }
}

It doesn't require you to write entries for every view separately. Sure, you have to write the hierarchy but once you do it once it is find _ENTITY1NAME_, replace _ENTITY2NAME_. And you have nice role hierarchy you could use to assign roles to groups dynamically :)

@Pierstoval

This comment has been minimized.

Copy link
Contributor

commented Aug 2, 2017

@forsetius your solution only takes roles from the role hierarchy system.
Using $this->denyAccessUnlessGranted() like the above answer is much better because it allows you to use security attributes instead of roles, which is important when you have voters in your application 😄

@zkkan

This comment has been minimized.

Copy link

commented Aug 2, 2017

I tried this but it doesn't work. I can't find the error. This is my conf

easy_admin:
    site_name: 'Amitié App'
    formats:
        date:       'd/m/Y'
        time:       'H:i'
        datetime:   'd/m/Y H:i:s'
        number:     '%.2f'
    design:
        menu: 
            - label:                'Members'
              entity:               Member
              icon:                 'users'
              require_permission:   ["ROLE_USER"]

            - label:                'Interventions'
              entity:               Intervention
              icon:                 ambulance
              require_permission:   ["ROLE_USER"]

            - label:                'Intervention type'
              entity:               InterventionType
              icon:                 tags
              require_permission:   ["ROLE_USER"]

            - label:                'Languages'
              entity:               Language
              icon:                 language
              require_permission:   ["ROLE_ADMIN"]

            - label:                'Mental Workers'
              entity:               User
              icon:                 user-circle-o
              require_permission:   ["ROLE_ADMIN"]

            - label:                'Source Of Income'
              entity:               SourceOfIncome
              icon:                 money
              require_permission:   ["ROLE_ADMIN"]
              
            - label:                'NeighborHood'
              entity:               NeighborHood
              icon:                 street-view
              require_permission:   ["ROLE_ADMIN"]

            - label:                'Housing Arrangement'
              entity:               HousingArrangement
              icon:                 home
              require_permission:   ["ROLE_ADMIN"]

            - label:                'Follow-up Hospital'
              entity:               FollowUpHospital
              icon:                 hospital-o
              require_permission:   ["ROLE_ADMIN"]

            - label:                'Diagnostics'
              entity:               Diagnostic
              icon:                 thermometer-0
              require_permission:   ["ROLE_ADMIN"]

            - label:                'Services'
              entity:               Service
              icon:                 server
              require_permission:   ["ROLE_ADMIN"]

            - label:                'Referred by'
              entity:               ReferredBy
              icon:                 user-plus
              require_permission:   ["ROLE_ADMIN"]

        templates:
            menu: 'AmitiePlatformBundle:Menu:menu.html.twig'
    list:
        actions:
            - { name: 'show', label: 'Show' }
            - { name: 'statistic', label: 'Statistic'}
    entities:
        User:
            class: Amitie\PlatformBundle\Entity\User
            list:
                fields: ['id', 'enabled', 'firstName', 'lastName', 'username' , 'email']
                sort: ['firstName', 'ASC']
            form:
                fields:
                    - { type: 'group', css_class: 'col-sm-6', label: 'Basic information' }
                    - firstName
                    - lastName
                    - username
                    - { property: 'plainPassword', type: 'text', type_options: { required: true } }
                    - email
                    - { type: 'group', css_class: 'col-sm-6', label: 'Others informations' }
                    - usernameCanonical
                    - emailCanonical
                    - roles
                    - enabled
            show: 
                fields: [
                    'id', 
                    'enabled', 
                    'firstName', 
                    'lastName', 
                    'username', 
                    'password', 
                    'email', 
                    'usernameCanonical',
                    'emailCanonical',
                    'roles',
                    'enabled',
                    'interventions', 
                    'lastLogin']
                    
                
        Member:
            class: Amitie\PlatformBundle\Entity\Member
            #controller: Amitie\PlatformBundle\Controller\MemberController
            list:
                fields: ['id', 'status', 'firstName', 'lastName', 'phone' ,'users']
            show:
                form:
                    fields: 
                        - { type: 'group', css_class: 'col-sm-6', label: 'Basic information' }
                        - lastName
                     
            form:
                fields:
                    - { type: 'group', css_class: 'col-sm-6', label: 'Basic information' }
                    - firstName
                    - lastName
                    - { property: gender, type: choice, type_options: { choices: {"Male": "M", "Female": "F"} } }
                    - birthDay
                    - age
                    - { property: maritalStatus, type: choice, type_options: { choices: {"Célibataire": "C", "Marié": "F", "Divorcé": "D", "Veuf": "V", "Séparé": "S"} } }
                    - diagnostics
                    - language
                    - dateOfEntry
                    - healthInsuranceNumber
                    - status
                    - users
                    - followUpHospital
                    - services
                    - { type: 'group', label: 'Contact information', icon: 'phone',
                        css_class: 'col-sm-6' }
                    - phone
                    - address
                    - city
                    - postalCode
                    - { type: 'group', label: 'Others informations', css_class: 'col-sm-6' }
                    - referredBy
                    - neighborHood
                    - housingArrangement
                    - followUpFrequency
                    - frequencyAtCenter
                    - homelessness
                    - othersLanguages
                    - sourcesOfIncome
                    
        SourceOfIncome:
            class: Amitie\PlatformBundle\Entity\SourceOfIncome
            list:
                fields: ['name']
                sort: ['name', 'ASC']

        NeighborHood:
            class: Amitie\PlatformBundle\Entity\NeighborHood
            list:
                fields: ['name']    
                sort: ['name', 'ASC']

        Language:
            class: Amitie\PlatformBundle\Entity\Language
            list:
                fields: ['name']
                sort: ['name', 'ASC']

        HousingArrangement:
            class: Amitie\PlatformBundle\Entity\HousingArrangement
            list:
                fields: ['name']
                sort: ['name', 'ASC']

        FollowUpHospital:
            class: Amitie\PlatformBundle\Entity\FollowUpHospital
            list:
                fields: ['name']
                sort: ['name', 'ASC']

        Diagnostic:
            class: Amitie\PlatformBundle\Entity\Diagnostic
            list:
                fields: ['name']
                sort: ['name', 'ASC']

        Service:
            class: Amitie\PlatformBundle\Entity\Service
            list:
                fields: ['name']
                sort: ['name', 'ASC']

        ReferredBy:
            class: Amitie\PlatformBundle\Entity\ReferredBy
            list:
                fields: ['name']
                sort: ['name', 'ASC']

        Intervention:
            controller: Amitie\PlatformBundle\Controller\InterventionController
            class: Amitie\PlatformBundle\Entity\Intervention
            list:
                fields: ['member', 'date', 'type', 'duration', 'createdBy']
                sort: ['date', 'DESC']
            form:
                fields:
                    - { type: 'group', css_class: 'col-sm-6', label: 'Basic information' }
        
        InterventionType:
            class: Amitie\PlatformBundle\Entity\InterventionType
            list:
                fields: ['name']
                sort: ['name', 'ASC']

@Pierstoval

This comment has been minimized.

Copy link
Contributor

commented Aug 2, 2017

@zkkan can you put your code in a gist or pastebin, and also show the code from your custom admin controller?

@zkkan

This comment has been minimized.

Copy link

commented Aug 2, 2017

These are my code

easy_admin_bundle.yml: https://pastebin.com/PCM4JzB0
security.yml: https://pastebin.com/QY9t1LVr
AdminController: https://pastebin.com/vqR4Q06U

I have 2 roles: ROLE_ADMIN, ROLE_USER

What I want to do is restricting some actions when login as user. example: Deleting a member, see some field of member etc

Thanks

@Pierstoval

This comment has been minimized.

Copy link
Contributor

commented Aug 2, 2017

@zkkan Do you understand that the require_permission is a parameter that was proposed, but in fact it is not implemented in EasyAdmin? This is the reason why it doesn't work.

@zkkan

This comment has been minimized.

Copy link

commented Aug 2, 2017

@Pierstoval Are there a way to do this?

@Pierstoval

This comment has been minimized.

Copy link
Contributor

commented Aug 2, 2017

Yes, follow the other recommendations in this thread, like the one by @djluza for example

@javiereguiluz

This comment has been minimized.

Copy link
Collaborator

commented Aug 2, 2017

@zkkan currently there is no official way to implement that feature with this bundle. If you need this feature and must develop your project soon, the only solution is to use instead this other bundle: SonataAdminBundle.

In any case, it's going to take us a bit before we complete this feature, so I'm going to lock this issue to prevent people adding more comments and asking about this. Thanks!

@EasyCorp EasyCorp locked and limited conversation to collaborators Aug 2, 2017

@javiereguiluz

This comment has been minimized.

Copy link
Collaborator

commented Jan 11, 2019

We intend to implement this feature sooner that later on EasyAdmin. For those needed it now, you can take a look at this community bundle that provides more features to EasyAdmin: https://github.com/alterphp/EasyAdminExtensionBundle#define-access-permissions

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
You can’t perform that action at this time.