简体   繁体   中英

Sonata Admin ACL hide element in list

After a lot of effort I was finally able to configure Sonata Admin with ACL following this guide:

https://sonata-project.org/bundles/admin/master/doc/reference/security.html

I wanted to users to be able to view and edit only items with the same country property as the user.

This is my config.yml:

parameters:
    locale: en
    sonata.user.admin.user.class: AppBundle\Admin\UserAdmin
    sonata.admin.security.mask.builder.class: Sonata\AdminBundle\Security\Acl\Permission\MaskBuilder

# SonataAdminBundle Configuration
sonata_admin:
    security:
        handler: sonata.admin.security.handler.acl

        role_admin: ROLE_ADMIN
        role_super_admin: ROLE_SUPER_ADMIN

        # acl security information
        information:
            GUEST:    [VIEW, LIST]
            STAFF:    [EDIT, LIST, CREATE]
            EDITOR:   [OPERATOR, EXPORT]
            ADMIN:    [MASTER]

        # permissions not related to an object instance and also to be available when objects do not exist
        # the DELETE admin permission means the user is allowed to batch delete objects
        admin_permissions: [CREATE, LIST, DELETE, UNDELETE, EXPORT, OPERATOR, MASTER]

        # permission related to the objects
        object_permissions: [VIEW, EDIT, DELETE, UNDELETE, OPERATOR, MASTER, OWNER]

I created an AclVoter in order to show/hides elements:

services:
    security.acl.voter.country_owned_permissions:
        class: AppBundle\Security\Authorization\Voter\CountryOwnedAclVoter
        arguments:
            - "@security.acl.provider"
            - "@security.acl.object_identity_retrieval_strategy"
            - "@security.acl.security_identity_retrieval_strategy"
            - "@security.acl.permission.map"
            - "@logger"
        tags:
            - { name: monolog.logger, channel: security }
            - { name: security.voter, priority: 255 }
        public: false

This is the actual class:

<?php

namespace AppBundle\Security\Authorization\Voter;

use FOS\UserBundle\Model\UserInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Acl\Voter\AclVoter;

class CountryOwnedAclVoter extends AclVoter
{
    public function supportsClass($class)
    {
        // support the Class-Scope ACL for votes with the custom permission map
        // return $class === 'Sonata\UserBundle\Admin\Entity\UserAdmin' || is_subclass_of($class, 'FOS\UserBundle\Model\UserInterface');
        // if you use php >=5.3.7 you can check the inheritance with is_a($class, 'Sonata\UserBundle\Admin\Entity\UserAdmin');
        // support the Object-Scope ACL
        return is_subclass_of($class, 'AppBundle\Model\CountryOwnedInterface');
    }

    public function supportsAttribute($attribute)
    {
        return in_array($attribute, array(
            'LIST',
            'VIEW',
            'EDIT',
            'DELETE',
            'EXPORT',
        ));
    }

    public function vote(TokenInterface $token, $object, array $attributes)
    {
        if (!$this->supportsClass(get_class($object))) {
            return self::ACCESS_ABSTAIN;
        }

        foreach ($attributes as $attribute) {
            if ($this->supportsAttribute($attribute)) {
                if ($object->getCountry() != $token->getUser()->getCountry()) {
                //if ($object->isSuperAdmin() && !$token->getUser()->isSuperAdmin()) {
                    // deny a non super admin user to edit a super admin user
                    return self::ACCESS_DENIED;
                }
            }
        }

        // use the parent vote with the custom permission map:
        // return parent::vote($token, $object, $attributes);
        // otherwise leave the permission voting to the AclVoter that is using the default permission map
        return self::ACCESS_ABSTAIN;
    }
}

It seems to work fine since a user can only edit items which have the same country as the users. The problem is that he can still view the items in the list.

What am I doing wrong?

在此处输入图片说明

As specified in the official documentation I just needed to install a specific bundle:

5.4.6. LIST FILTERING
List filtering using ACL is available as a third party bundle: CoopTilleulsAclSonataAdminExtensionBundle. When enabled, the logged in user will only see the objects for which it has the VIEW right (or superior).

This will suffice:

composer require tilleuls/acl-sonata-admin-extension-bundle

In AppKernel.php :

// ACL list filter
new CoopTilleuls\Bundle\AclSonataAdminExtensionBundle\CoopTilleulsAclSonataAdminExtensionBundle(),

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM