Created
December 30, 2011 13:09
-
-
Save CodingNinja/1539784 to your computer and use it in GitHub Desktop.
Grant / Revoke ACL Permissions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
* Copyright (C) 2011 David Mann | |
* | |
* Permission is hereby granted, free of charge, to any person obtaining a copy of | |
* this software and associated documentation files (the "Software"), to deal in | |
* the Software without restriction, including without limitation the rights to | |
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies | |
* of the Software, and to permit persons to whom the Software is furnished to do | |
* so, subject to the following conditions: | |
* | |
* The above copyright notice and this permission notice shall be included in all | |
* copies or substantial portions of the Software. | |
* | |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
* SOFTWARE. | |
*/ | |
namespace ApplicationBundle\Security; | |
use Symfony\Component\Security\Acl\Domain\Entry; | |
use Symfony\Component\Security\Acl\Domain\Acl; | |
use Symfony\Component\Security\Acl\Dbal\MutableAclProvider; | |
use Symfony\Component\Security\Core\SecurityContextInterface; | |
use Symfony\Component\Security\Acl\Model\AclProviderInterface; | |
use Symfony\Component\Security\Acl\Domain\ObjectIdentity; | |
use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity; | |
use ApplicationBundle\Security\MaskBuilder; | |
/** | |
* Easily work with Symfony ACL | |
* | |
* This class abstracts some of the ACL layer and | |
* gives you very easy "Grant" and "Revoke" methods | |
* which will update existing ACL's and create new ones | |
* when required | |
* | |
* @author CodinNinja | |
*/ | |
class Manager { | |
protected $provider; | |
protected $context; | |
/** | |
* Constructor | |
* | |
* @param AclProviderInterface $provider | |
* @param SecurityContextInterface $context | |
*/ | |
public function __construct(AclProviderInterface $provider, SecurityContextInterface $context) { | |
$this->provider = $provider; | |
$this->context = $context; | |
} | |
/** | |
* Grant a permission | |
* | |
* @param Object $entity The DomainObject to add the permissions for | |
* @param integer|string $mask The initial mask | |
* @return Object The original Entity | |
*/ | |
public function grant($entity, $mask = MaskBuilder::MASK_OWNER) { | |
$acl = $this->getAcl($entity); | |
// retrieving the security identity of the currently logged-in user | |
$securityContext = $this->context; | |
$user = $securityContext->getToken()->getUser(); | |
$securityIdentity = UserSecurityIdentity::fromAccount($user); | |
// grant owner access | |
$this->addMask($securityIdentity, $mask, $acl); | |
return $entity; | |
} | |
/** | |
* Get or create an ACL object | |
* | |
* @param object $entity The Domain Object to get the ACL for | |
* | |
* @return Acl The found / craeted ACL | |
*/ | |
protected function getAcl($entity) { | |
// creating the ACL | |
$aclProvider = $this->provider; | |
$objectIdentity = ObjectIdentity::fromDomainObject($entity); | |
try { | |
$acl = $aclProvider->createAcl($objectIdentity); | |
}catch(\Exception $e) { | |
$acl = $aclProvider->findAcl($objectIdentity); | |
} | |
return $acl; | |
} | |
/** | |
* Revoke a permission | |
* | |
* <pre> | |
* $manager->revoke($myDomainObject, 'delete'); // Remove "delete" permission for the $myDomainObject | |
* </pre> | |
* | |
* @param Object $entity The DomainObject that we are revoking the permission for | |
* @param int|string $mask The mask to revoke | |
* | |
* @return \ApplicationBundle\Security\Manager Reference to $this for fluent interface | |
*/ | |
public function revoke($entity, $mask = MaskBuilder::MASK_OWNER) { | |
$acl = $this->getAcl($entity); | |
$aces = $acl->getObjectAces(); | |
$user = $this->context->getToken()->getUser(); | |
$securityIdentity = UserSecurityIdentity::fromAccount($user); | |
foreach($aces as $i => $ace) { | |
if($securityIdentity->equals($ace->getSecurityIdentity())) { | |
$this->revokeMask($i, $acl, $ace, $mask); | |
} | |
} | |
$this->provider->updateAcl($acl); | |
return $this; | |
} | |
/** | |
* Remove a mask | |
* | |
* @param Acl $acl The ACL to update | |
* @param Entry $ace The ACE to remove the mask from | |
* @param unknown_type $mask The mask to remove | |
* | |
* @return \ApplicationBundle\Security\Manager Reference to $this for fluent interface | |
*/ | |
protected function revokeMask($index, Acl $acl, Entry $ace, $mask) { | |
$acl->updateObjectAce($index, $ace->getMask() & ~$mask); | |
return $this; | |
} | |
/** | |
* Add a mask | |
* | |
* @param SecurityIdentityInterface $securityIdentity The ACE to add | |
* @param integer|string $mask The initial mask to set | |
* @param ACL $acl The ACL to update | |
* | |
* @return \ApplicationBundle\Security\Manager Reference to $this for fluent interface | |
*/ | |
protected function addMask($securityIdentity, $mask, $acl) { | |
$acl->insertObjectAce($securityIdentity, $mask); | |
$this->provider->updateAcl($acl); | |
return $this; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" ?> | |
<container xmlns="http://symfony.com/schema/dic/services" | |
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> | |
<parameters> | |
<parameter key="application.acl_manager.class">ApplicationBundle\Security\Manager</parameter> | |
</parameters> | |
<services> | |
<service id="application.acl_manager" class="%application.acl_manager.class%"> | |
<argument type="service" id="security.acl.provider" /> | |
<argument type="service" id="security.context" /> | |
</service> | |
</services> | |
</container> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
* Copyright (C) 2011 David Mann | |
* | |
* Permission is hereby granted, free of charge, to any person obtaining a copy of | |
* this software and associated documentation files (the "Software"), to deal in | |
* the Software without restriction, including without limitation the rights to | |
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies | |
* of the Software, and to permit persons to whom the Software is furnished to do | |
* so, subject to the following conditions: | |
* | |
* The above copyright notice and this permission notice shall be included in all | |
* copies or substantial portions of the Software. | |
* | |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
* SOFTWARE. | |
*/ | |
namespace ApplicationBundle\Controller; | |
use ApplicationBundle\Security\MaskBuilder; | |
use ApplicationBundle\Entity\Entity; | |
use JMS\SecurityExtraBundle\Annotation as Secure; | |
use Symfony\Bundle\FrameworkBundle\Controller\Controller; | |
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | |
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; | |
class TestController extends Controller | |
{ | |
/** | |
* @param Entity $entity | |
* @Template() | |
* @Route("/test/{id}/join", name="test_grant") | |
* @Secure\Secure(roles="ROLE_USER") | |
*/ | |
public function grantAction(Entity $trip) { | |
$this->get('application.acl_manager')->grant($trip, MaskBuilder::MASK_VIEW); | |
} | |
/** | |
* @param Entity $entity | |
* @Template() | |
* @Route("/test/{id}/leave", name="test_leave") | |
* @Secure\SecureParam(name="entity", permissions="VIEW") | |
*/ | |
public function revokeAction(Entity $entity) { | |
$this->get('application.acl_manager')->revoke($entity, MaskBuilder::MASK_VIEW); | |
} | |
} |
I had to change the function "addMask" to the following function, or else i would get an error when I tried to change the permissions of an existing ACE.
protected function addMask($securityIdentity, $mask, $acl)
{
$updated = false;
foreach($acl->getObjectAces() as $index=>$ace)
{
if($ace->getSecurityIdentity() == $securityIdentity)
{
$acl->updateObjectAce($index, $mask, null);
$updated = true;
}
}
if(!$updated)
{
$acl->insertObjectAce($securityIdentity, $mask);
}
$this->provider->updateAcl($acl);
return $this;
}
What if I also want to delete the object identity object when deleting my domain object? How to do that?
Do you have an example how to add ACE for class scopes as defined here : http://symfony.com/doc/current/cookbook/security/acl_advanced.html
I could able to store the ACE but its not reflecting on permission.
Function to delete ACL entity from database
/**
* Delete ACL entity
*
* @param $entity
* @return $this
* @throws \Symfony\Component\Security\Acl\Exception\InvalidDomainObjectException
*/
public function clean($entity)
{
$objectIdentity = ObjectIdentity::fromDomainObject($entity);
$this->provider->deleteAcl($objectIdentity);
return $this;
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You can revoke using deleteObjectAce instead of updating :