Sonata User - Security on custom field

前端 未结 2 662
逝去的感伤
逝去的感伤 2021-01-03 02:12

I used SonataUser with FOSUser to manage my users and created a custom field company to attach each one to a given company.

Now I\'d simply need to give

相关标签:
2条回答
  • 2021-01-03 02:32

    Yes ACL is the way to go. create a CompanyVoter implementing VoterInterface and check if the user is on the same company inside it's vote() method.

    the cookbook entry "How to implement your own Voter to blacklist IP Addresses" gives a good introduction.

    change your access-decision-manager's strategy to 'unanimous'. This means if only one voter denies access (e.g. the CompanyVoter), access is not granted to the end user.

    # app/config/security.yml
    security:
        access_decision_manager:
            strategy: unanimous
    

    Now create your Voter

    // src/Acme/AcmeBundle/YourBundle/Security/Authorization/Voter/CompanyVoter.php
    namespace Acme\YourBundle\Security\Authorization\Voter;
    
    use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
    use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
    
    use Acme\YourUserBundleBundle\Entity\User;
    use Symfony\Component\Security\Core\User\UserInterface;
    
    class CompanyVoter implements VoterInterface 
    {
    
        private $container;
    
        public function __construct($container) 
        {
            $this->container = $container;
        }
    
        public function supportsAttribute($attribute) 
        {
           return in_array($attribute, array(
              'EDIT',
              'ACTIVATE',
              // ...
           ));
        }
    
       public function supportsClass($class)
       {
            return in_array("FOS\UserBundle\Model\UserInterface", class_implements($class));
       }
    
       public function vote(TokenInterface $token, $object, array $attributes) 
       {
           if ( !($this->supportsClass(get_class($object))) ) {
               return VoterInterface::ACCESS_ABSTAIN;
           }
    
           foreach ($attributes as $attribute) {
               if ( !$this->supportsAttribute($attribute) ) {
                   return VoterInterface::ACCESS_ABSTAIN;
               }
           }
    
           $user = $token->getUser();
           if ( !($user instanceof UserInterface) ) {
               return VoterInterface::ACCESS_DENIED;
           }
    
           // check if the user has the same company
           if ( $user->getCompany() == $object->getCompany() ) {
               return VoterInterface::ACCESS_GRANTED;
           }
    
           return VoterInterface::ACCESS_DENIED;
       }
    
    }
    

    Finally register the voter as as a service

    # src/Acme/AcmeBundle/Resources/config/services.yml
    services:
        security.access.company_voter:
            class:      Acme\YourBundle\Security\Authorization\Voter\CompanyVoter
            public:     false
            tags:
               - { name: security.voter }
    

    ... now use it in your twig template

    {% if is_granted('EDIT', user) %}<a href="#">Edit</a>{% endif %}
    {% if is_granted('ACTIVATE', user) %}<a href="#">activate</a>{% endif %}
    

    or in your controller ...

    public function editAction(UserInterface $user)
    {
        if ( $this->get('security.context')->isGranted('EDIT',$user) ) {
            throw new \Symfony\ComponentSecurity\Core\Exception\AccessDeniedException();
        }
    }
    

    or using JMSSecurityExtraBundle ...

    /**
     * @SecureParam(name="user", permissions="EDIT")
     */
    public function editUser(UserInterface $user) 
    {  
        // ...
    }
    
    0 讨论(0)
  • 2021-01-03 02:33

    As I didn't need ACLs here, (only voters) I used the role security handler of sonata.

    But I had issues using it because its default implementation of isGranted() doesn't pass the current object to the voter.

    So I had to extend it, check my monologue in this github issue for more detail.


    By the way, my PR was accepted about this issue

    0 讨论(0)
提交回复
热议问题