How to use class-scope aces in Symfony2?
you are doing it right. and according to the bottom of this page, it should work, but it does not.
the easiest way to make it work is creating an AclVoter class:
namespace Core\Security\Acl\Voter;use JMS\SecurityExtraBundle\Security\Acl\Voter\AclVoter as BaseAclVoter;use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;use Symfony\Component\Security\Acl\Domain\ObjectIdentity;use Doctrine\Common\Util\ClassUtils;class AclVoter extends BaseAclVoter{ public function vote( TokenInterface $token , $object , array $attributes ) { //vote for object first $objectVote = parent::vote( $token , $object , $attributes ); if( self::ACCESS_GRANTED === $objectVote ) { return self::ACCESS_GRANTED; } else { //then for object's class $oid = new ObjectIdentity( 'class' , ClassUtils::getRealClass( get_class( $object ) ) ); $classVote = parent::vote( $token , $oid , $attributes ); if( self::ACCESS_ABSTAIN === $objectVote ) { if( self::ACCESS_ABSTAIN === $classVote ) { return self::ACCESS_ABSTAIN; } else { return $classVote; } } else if( self::ACCESS_DENIED === $objectVote ) { if( self::ACCESS_ABSTAIN === $classVote ) { return self::ACCESS_DENIED; } else { return $classVote; } } } return self::ACCESS_ABSTAIN; }}
then in security.yml set this:
jms_security_extra: voters: disable_acl: true
and finally set up the voter as a service:
core.security.acl.voter.basic_permissions: class: Core\Security\Acl\Voter\AclVoter public: false arguments: - '@security.acl.provider' - '@security.acl.object_identity_retrieval_strategy' - '@security.acl.security_identity_retrieval_strategy' - '@security.acl.permission.map' - '@?logger' tags: - { name: security.voter , priority: 255 } - { name: monolog.logger , channel: security }
You need to ensure each object has its own ACL (use $aclProvider->createAcl($entity)
) for class-scope permissions to work correctly.
See this discussion: https://groups.google.com/forum/?fromgroups=#!topic/symfony2/pGIs0UuYKX4
If you don't have an existing entity, you can check against the objectIdentity you created.Be careful to use "double-backslashes", because of the escaping of the backslash.
$post = $postRepository->findOneBy(array('id' => 1));$securityContext = $this->get('security.context');$objectIdentity = new ObjectIdentity('class', 'Liip\\TestBundle\\Entity\\Post');// check for edit accessif (true === $securityContext->isGranted('EDIT', $objectIdentity)) { echo "Edit Access granted to: <br/><br/> "; print_r("<pre>"); print_r($post); print_r("</pre>");} else { throw new AccessDeniedException();}
That should work!
If you would check for "object-scope" you could just use $post instead of $objectIdentity in the isGranted function call.