add more tests for (Mutable)AclProvider

* fix usage of existing database entries
This commit is contained in:
Toni Uebernickel 2012-02-03 18:21:16 +01:00
parent babf3bf203
commit 2231df621c
3 changed files with 227 additions and 13 deletions

View file

@ -32,7 +32,10 @@ use Propel\PropelBundle\Security\Acl\Domain\Entry;
use Symfony\Component\Security\Acl\Exception\AclAlreadyExistsException;
use Symfony\Component\Security\Acl\Exception\Exception as AclException;
use Symfony\Component\Security\Acl\Domain\FieldEntry;
use Symfony\Component\Security\Acl\Model\AclInterface;
use Symfony\Component\Security\Acl\Model\EntryInterface;
use Symfony\Component\Security\Acl\Model\FieldEntryInterface;
use Symfony\Component\Security\Acl\Model\AclCacheInterface;
use Symfony\Component\Security\Acl\Model\MutableAclInterface;
@ -58,9 +61,11 @@ class MutableAclProvider extends AclProvider implements MutableAclProviderInterf
*/
public function __construct(PermissionGrantingStrategyInterface $permissionGrantingStrategy, PropelPDO $connection = null, AclCacheInterface $cache = null)
{
// @codeCoverageIgnoreStart
if (null === $connection) {
$connection = Propel::getConnection(EntryPeer::DATABASE_NAME, Propel::CONNECTION_WRITE);
}
// @codeCoverageIgnoreEnd
parent::__construct($permissionGrantingStrategy, $connection, $cache);
}
@ -135,9 +140,11 @@ class MutableAclProvider extends AclProvider implements MutableAclProviderInterf
$this->connection->commit();
return true;
// @codeCoverageIgnoreStart
} catch (Exception $e) {
throw new AclException('An error occurred while deleting the ACL.', 1, $e);
}
// @codeCoverageIgnoreEnd
}
/**
@ -159,6 +166,7 @@ class MutableAclProvider extends AclProvider implements MutableAclProviderInterf
try {
$modelEntries = EntryQuery::create()->findByAclIdentity($acl->getObjectIdentity(), array(), $this->connection);
$objectIdentity = ObjectIdentityQuery::create()->findOneByAclObjectIdentity($acl->getObjectIdentity(), $this->connection);
$this->connection->beginTransaction();
@ -196,11 +204,13 @@ class MutableAclProvider extends AclProvider implements MutableAclProviderInterf
$this->connection->commit();
return true;
// @codeCoverageIgnoreStart
} catch (Exception $e) {
$this->connection->rollBack();
throw new AclException('An error occurred while updating the ACL.', 0, $e);
}
// @codeCoverageIgnoreEnd
}
/**
@ -219,7 +229,11 @@ class MutableAclProvider extends AclProvider implements MutableAclProviderInterf
/* @var $eachAce \Symfony\Component\Security\Acl\Model\EntryInterface */
foreach ($accessControlEntries as $order => $eachAce) {
// If the given ACE has never been persisted, create a new one.
if (null === $entry = $this->getPersistedAce($eachAce)) {
if (null === $entry = $this->getPersistedAce($eachAce, $objectIdentity, $object)) {
$entry = new ModelEntry();
}
if (in_array($entry->getId(), $entries)) {
$entry = new ModelEntry();
}
@ -253,24 +267,42 @@ class MutableAclProvider extends AclProvider implements MutableAclProviderInterf
*
* If none is given, null is returned.
*
* @param Entry $ace
* @param EntryInterface $ace
*
* @return ModelEntry|null
*/
protected function getPersistedAce(Entry $ace)
protected function getPersistedAce(EntryInterface $ace, ObjectIdentity $objectIdentity, $object = false)
{
if (null === $ace->getId()) {
return null;
if (null !== $ace->getId() and null !== $entry = EntryQuery::create()->findPk($ace->getId(), $this->connection)) {
$entry->reload(true, $this->connection);
return $entry;
}
if (null === $entry = EntryQuery::create()->findPk($ace->getId(), $this->connection)) {
return null;
/*
* The id is not set, but there may be an ACE in the database.
*
* This happens if the ACL has created new ACEs, but was not reloaded.
* We try to retrieve one by the unique key.
*/
$ukQuery = EntryQuery::create()
->filterByAclClass($objectIdentity->getAclClass($this->connection))
->filterBySecurityIdentity(SecurityIdentity::fromAclIdentity($ace->getSecurityIdentity(), $this->connection))
;
if (true === $object) {
$ukQuery->filterByObjectIdentity($objectIdentity);
} else {
$ukQuery->filterByObjectIdentityId(null, Criteria::ISNULL);
}
// Retrieve fresh data from the database not from any caching.
$entry->reload(false, $this->connection);
if ($ace instanceof FieldEntryInterface) {
$ukQuery->filterByFieldName($ace->getField());
} else {
$ukQuery->filterByFieldName(null, Criteria::ISNULL);
}
return $entry;
return $ukQuery->findOne($this->connection);
}
/**

View file

@ -73,6 +73,43 @@ class AclProviderTest extends AclTestCase
$acl->isGranted(array(128), array($this->getRoleSecurityIdentity('ROLE_USER')));
}
/**
* @depends testFindAclWithEntries
*/
public function testFindAclWithParent()
{
$parent = $this->createModelObjectIdentity(1);
$entry = $this->createEntry();
$entry
->setSecurityIdentity(SecurityIdentity::fromAclIdentity($this->getRoleSecurityIdentity('ROLE_USER')))
->setAclClass($parent->getAclClass())
->setMask(128)
;
$parent->addEntry($entry)->save($this->con);
$obj = $this->createModelObjectIdentity(2);
$obj->setObjectIdentityRelatedByParentObjectIdentityId($parent);
$entry = $this->createEntry();
$entry
->setSecurityIdentity(SecurityIdentity::fromAclIdentity($this->getRoleSecurityIdentity('ROLE_USER')))
->setAclClass($obj->getAclClass())
->setMask(64)
;
$obj->addEntry($entry)->save($this->con);
$acl = $this->getAclProvider()->findAcl($this->getAclObjectIdentity(2), array($this->getRoleSecurityIdentity('ROLE_USER')));
$parent = $acl->getParentAcl();
$this->assertInstanceOf('Propel\PropelBundle\Security\Acl\Domain\Acl', $acl);
$this->assertInstanceOf('Propel\PropelBundle\Security\Acl\Domain\Acl', $parent);
$aces = $acl->getObjectAces();
$parentAces = $parent->getObjectAces();
$this->assertEquals(64, $aces[0]->getMask());
$this->assertEquals(128, $parentAces[0]->getMask());
}
/**
* @depends testFindAclWithEntries
*/

View file

@ -10,6 +10,8 @@
namespace Propel\PropelBundle\Tests\Security\Acl;
use Criteria;
use Propel\PropelBundle\Model\Acl\EntryQuery;
use Propel\PropelBundle\Model\Acl\ObjectIdentityQuery;
@ -71,6 +73,125 @@ class MutableAclProviderTest extends AclTestCase
$this->assertEquals($this->getRoleSecurityIdentity('ROLE_ADMIN'), $entry->getSecurityIdentity());
}
/**
* @depends testUpdateAclCreatesInsertedAces
*/
public function testCreateAclAlreadyExists()
{
$acl = $this->getAclProvider()->createAcl($this->getAclObjectIdentity(1));
$acl->insertObjectAce($this->getRoleSecurityIdentity(), 64);
$this->getAclProvider()->updateAcl($acl);
$this->setExpectedException('Symfony\Component\Security\Acl\Exception\AclAlreadyExistsException');
$this->getAclProvider()->createAcl($this->getAclObjectIdentity(1));
}
/**
* @depends testUpdateAclCreatesInsertedAces
*/
public function testCreateAclWithParent()
{
$parentAcl = $this->getAclProvider()->createAcl($this->getAclObjectIdentity(1));
$parentAcl->insertObjectAce($this->getRoleSecurityIdentity(), 64);
$this->getAclProvider()->updateAcl($parentAcl);
$acl = $this->getAclProvider()->createAcl($this->getAclObjectIdentity(2));
$acl->insertObjectAce($this->getRoleSecurityIdentity(), 128);
$acl->setParentAcl($parentAcl);
$this->getAclProvider()->updateAcl($acl);
$entries = ObjectIdentityQuery::create()->orderById(Criteria::ASC)->find($this->con);
$this->assertCount(2, $entries);
$this->assertNull($entries[0]->getParentObjectIdentityId());
$this->assertEquals($entries[0]->getId(), $entries[1]->getParentObjectIdentityId());
}
public function testUpdateAclInvalidAcl()
{
$acl = $this->getMock('Symfony\Component\Security\Acl\Model\MutableAclInterface');
$this->setExpectedException('InvalidArgumentException');
$this->getAclProvider()->updateAcl($acl);
}
/**
* @depends testUpdateAclCreatesInsertedAces
*/
public function testUpdateAclRemovesDeletedEntries()
{
$acl = $this->getAclProvider()->createAcl($this->getAclObjectIdentity(1));
$acl->insertObjectFieldAce('name', $this->getRoleSecurityIdentity(), 4);
$acl->insertObjectFieldAce('slug', $this->getRoleSecurityIdentity(), 1);
$this->getAclProvider()->updateAcl($acl);
$this->assertEquals(2, EntryQuery::create()->count($this->con));
$acl->deleteObjectFieldAce(0, 'slug');
$this->getAclProvider()->updateAcl($acl);
$this->assertEquals(1, EntryQuery::create()->count($this->con));
$entry = EntryQuery::create()->findOne($this->con);
$this->assertEquals('name', $entry->getFieldName());
$this->assertEquals(4, $entry->getMask());
}
/**
* @depends testUpdateAclCreatesInsertedAces
*/
public function testUpdateAclCreatesMultipleAces()
{
$acl = $this->getAclProvider()->createAcl($this->getAclObjectIdentity(1));
$acl->insertObjectFieldAce('name', $this->getRoleSecurityIdentity(), 16, 0, true, 'all');
$acl->insertObjectFieldAce('name', $this->getRoleSecurityIdentity(), 4);
$acl->insertObjectFieldAce('slug', $this->getRoleSecurityIdentity(), 1);
$this->assertCount(2, $acl->getObjectFieldAces('name'));
$this->getAclProvider()->updateAcl($acl);
$entries = EntryQuery::create()->orderByMask(Criteria::ASC)->find($this->con);
$this->assertCount(3, $entries);
$slugAce = $entries[0];
$this->assertEquals('slug', $slugAce->getFieldName());
$this->assertEquals(1, $slugAce->getMask());
$nameRead = $entries[1];
$this->assertEquals('name', $nameRead->getFieldName());
$this->assertEquals(0, $nameRead->getAceOrder());
$this->assertEquals(4, $nameRead->getMask());
$this->assertEquals('all', $nameRead->getGrantingStrategy());
$nameUndelete = $entries[2];
$this->assertEquals('name', $nameUndelete->getFieldName());
$this->assertEquals(1, $nameUndelete->getAceOrder());
$this->assertEquals(16, $nameUndelete->getMask());
$this->assertEquals('all', $nameUndelete->getGrantingStrategy());
}
/**
* @depends testUpdateAclCreatesInsertedAces
*/
public function testUpdateAclReadsExistingAce()
{
$acl = $this->getAclProvider()->createAcl($this->getAclObjectIdentity(1));
$acl->insertObjectAce($this->getRoleSecurityIdentity(), 64);
$this->getAclProvider()->updateAcl($acl);
$entry = EntryQuery::create()->findOne($this->con);
$acl = $this->getAclProvider()->findAcl($this->getAclObjectIdentity(1));
$acl->updateObjectAce(0, 128);
$this->getAclProvider()->updateAcl($acl);
$updatedEntry = clone $entry;
$updatedEntry->reload(false, $this->con);
$this->assertEquals($entry->getId(), $updatedEntry->getId());
$this->assertEquals(128, $updatedEntry->getMask());
}
public function testDeleteAclNotExisting()
{
$this->assertTrue($this->getAclProvider()->deleteAcl($this->getAclObjectIdentity()));
@ -91,11 +212,35 @@ class MutableAclProviderTest extends AclTestCase
$this->assertEquals(0, EntryQuery::create()->count($this->con));
}
public function testUpdateAclInvalidAcl()
/**
* @depends testCreateAclWithParent
*/
public function testDeleteAclRemovesChildAcl()
{
$acl = $this->getMock('Symfony\Component\Security\Acl\Model\MutableAclInterface');
$parentAcl = $this->getAclProvider()->createAcl($this->getAclObjectIdentity(1));
$parentAcl->insertObjectAce($this->getRoleSecurityIdentity(), 64);
$this->getAclProvider()->updateAcl($parentAcl);
$this->setExpectedException('InvalidArgumentException');
$acl = $this->getAclProvider()->createAcl($this->getAclObjectIdentity(2));
$acl->insertObjectAce($this->getRoleSecurityIdentity(), 128);
$acl->setParentAcl($parentAcl);
$this->getAclProvider()->updateAcl($acl);
$this->getAclProvider()->deleteAcl($this->getAclObjectIdentity(1));
$this->assertEquals(0, ObjectIdentityQuery::create()->count($this->con));
}
/**
* @depends testDeleteAcl
*/
public function testDeleteAclRemovesClassEntriesIfLastObject()
{
$acl = $this->getAclProvider()->createAcl($this->getAclObjectIdentity(1));
$acl->insertClassAce($this->getRoleSecurityIdentity(), 128);
$this->getAclProvider()->updateAcl($acl);
$this->getAclProvider()->deleteAcl($this->getAclObjectIdentity(1));
$this->assertEquals(0, EntryQuery::create()->count($this->con));
}
}