Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
This is a basic AclManager service. It only handles ObjectAces. It provides a grant, revoke and revokeAll method.
<?php
namespace Smoovi\CoreBundle\Security;
use Symfony\Component\Security\Acl\Model\AclProviderInterface,
Symfony\Component\Security\Acl\Domain\ObjectIdentity,
Symfony\Component\Security\Acl\Domain\UserSecurityIdentity;
use Smoovi\CoreBundle\Security\Acl\Permission\MaskBuilder;
/**
* Easily work with Symfony ACL
*
* @author Brammm
*/
class AclManager {
protected $provider;
/**
* Constructor
*
* @param AclProviderInterface $provider
*/
public function __construct(AclProviderInterface $provider)
{
$this->provider = $provider;
}
/**
* Grants a permission to $user for $object
* Will check for existing permissions and update accordingly
*
* @param $object
* @param $user
* @param int $mask
*/
public function grant($object, $user, $mask = MaskBuilder::MASK_OWNER)
{
// Create identities
$oid = ObjectIdentity::fromDomainObject($object);
$sid = UserSecurityIdentity::fromAccount($user);
// Get ACL
$acl = $this->getAcl($oid);
// Try to find an ACE for the user
// If one doesn't exist, insert a new one.
list($i, $ace) = $this->getAce($acl, $sid);
if (isset($ace)) {
// We found an ACE. If the mask's the same, we just stop here
if ($ace->getMask() == $mask) {
return;
}
$newMask = $ace->getMask() & $mask; // Bitwise operator, adding the masks together
$acl->updateObjectAce($i, $newMask);
} else {
$acl->insertObjectAce($sid, $mask);
}
$this->provider->updateAcl($acl);
}
/**
* Revokes a permission to $user for $object
* Will only revoke the given permission
*
* @param $object
* @param $user
* @param $mask
*/
public function revoke($object, $user, $mask)
{
// Create identities and get ACL
$oid = ObjectIdentity::fromDomainObject($object);
$sid = UserSecurityIdentity::fromAccount($user);
$acl = $this->getAcl($oid, false);
// Get the ACE
list($i, $ace) = $this->getAce($acl, $sid);
if (isset($ace)) {
$newMask = $ace->getMask() & ~$mask;
if ($newMask === 0) {
$acl->deleteObjectAce($i);
} else {
$acl->updateObjectAce($i, $newMask);
}
$this->provider->updateAcl($acl);
}
}
/**
* Revokes all permissions to $user for $object
*
* @param $object
* @param $user
*/
public function revokeAll($object, $user)
{
// Create identities and get ACL
$oid = ObjectIdentity::fromDomainObject($object);
$sid = UserSecurityIdentity::fromAccount($user);
$acl = $this->getAcl($oid, $sid, false);
// Get the ACE
list($i, $ace) = $this->getAce($acl, $sid);
if (isset($ace)) {
$acl->deleteObjectAce($i);
$this->provider->updateAcl($acl);
}
}
/**
* Get an ACL for an object and a user
* If createEmpty is false, it will throw an error if it can't find the ACL
*
* @param $oid
* @param $sid
* @param bool $createEmpty
* @throws \Exception
* @return \Symfony\Component\Security\Acl\Model\MutableAclInterface
*/
protected function getAcl($oid, $createEmpty = true)
{
// Try to find an existing ACL
// If one doesn't exist, create one if necessary.
try {
return $this->provider->findAcl($oid);
} catch (\Exception $e) {
if ($createEmpty) {
return $this->provider->createAcl($oid);
} else {
throw $e;
}
}
}
/**
* Gets the user ACE
*
* It returns the index of the ace and the ace itself. We sadly need the index as well.
*
* @param $acl
* @param $sid
* @return array
*/
protected function getAce($acl, $sid)
{
$index = $ace = null;
foreach ($acl->getObjectAces() as $i => $maybeAce) {
if ($sid->equals($maybeAce->getSecurityIdentity())) {
$index = $i;
$ace = $maybeAce;
break; // stop the loop, we have our ace
}
}
return [$index, $ace];
}
}
@patie
Copy link

patie commented Apr 19, 2013

@Brammm
Copy link
Author

Brammm commented May 16, 2013

I based my own version off off what @CodingNinja did. However, his version kept throwing errors for me, so I wrote my own.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment