feature #15013 [Security] Removed security-acl from the core (iltar)

This PR was squashed before being merged into the 2.8 branch (closes #15013).

Discussion
----------

[Security] Removed security-acl from the core

| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | part of #14718
| License       | MIT
| Doc PR        | ~

The `Security\Acl` is removed from the core and is loaded from its own repository. All tests were passing and this is fully backwards compatible. I have removed all but the Test files in the first step and added the dependency to verify the Test were still working with the package dependency. The second step was to remove the remaining test files and tests are still running for both the Bundle and the Framework. Once the Read-Only repository is a full standalone repository, this PR can be merged.

- [x] Remove component from the core
- [ ] Remove read-only from https://github.com/symfony/security-acl

Once this PR is merged, I can start working on splitting the SecurityBundle and extracting the ACL part to the AclBundle.

/cc @fabpot

Commits
-------

b26a449 [Security] Removed security-acl from the core
This commit is contained in:
Fabien Potencier 2015-08-01 09:18:32 +02:00
commit bffca95112
81 changed files with 4 additions and 9421 deletions

View File

@ -50,7 +50,6 @@
"symfony/proxy-manager-bridge": "self.version",
"symfony/routing": "self.version",
"symfony/security": "self.version",
"symfony/security-acl": "self.version",
"symfony/security-core": "self.version",
"symfony/security-csrf": "self.version",
"symfony/security-http": "self.version",
@ -76,7 +75,8 @@
"monolog/monolog": "~1.11",
"ircmaxell/password-compat": "~1.0",
"ocramius/proxy-manager": "~0.4|~1.0",
"egulias/email-validator": "~1.2"
"egulias/email-validator": "~1.2",
"symfony/security-acl": "~2.8"
},
"autoload": {
"psr-4": {

View File

@ -18,7 +18,8 @@
"require": {
"php": ">=5.3.9",
"symfony/security": "~2.8|~3.0.0",
"symfony/http-kernel": "~2.2"
"symfony/http-kernel": "~2.2|~3.0.0",
"symfony/security-acl": "~2.8|~3.0.0"
},
"require-dev": {
"symfony/phpunit-bridge": "~2.7|~3.0.0",

View File

@ -1,3 +0,0 @@
vendor/
composer.lock
phpunit.xml

View File

@ -1,695 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Dbal;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Driver\Statement;
use Symfony\Component\Security\Acl\Model\AclInterface;
use Symfony\Component\Security\Acl\Domain\Acl;
use Symfony\Component\Security\Acl\Domain\Entry;
use Symfony\Component\Security\Acl\Domain\FieldEntry;
use Symfony\Component\Security\Acl\Domain\ObjectIdentity;
use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity;
use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity;
use Symfony\Component\Security\Acl\Exception\AclNotFoundException;
use Symfony\Component\Security\Acl\Exception\NotAllAclsFoundException;
use Symfony\Component\Security\Acl\Model\AclCacheInterface;
use Symfony\Component\Security\Acl\Model\AclProviderInterface;
use Symfony\Component\Security\Acl\Model\ObjectIdentityInterface;
use Symfony\Component\Security\Acl\Model\PermissionGrantingStrategyInterface;
/**
* An ACL provider implementation.
*
* This provider assumes that all ACLs share the same PermissionGrantingStrategy.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class AclProvider implements AclProviderInterface
{
const MAX_BATCH_SIZE = 30;
/**
* @var AclCacheInterface|null
*/
protected $cache;
/**
* @var Connection
*/
protected $connection;
protected $loadedAces = array();
protected $loadedAcls = array();
protected $options;
/**
* @var PermissionGrantingStrategyInterface
*/
private $permissionGrantingStrategy;
/**
* Constructor.
*
* @param Connection $connection
* @param PermissionGrantingStrategyInterface $permissionGrantingStrategy
* @param array $options
* @param AclCacheInterface $cache
*/
public function __construct(Connection $connection, PermissionGrantingStrategyInterface $permissionGrantingStrategy, array $options, AclCacheInterface $cache = null)
{
$this->cache = $cache;
$this->connection = $connection;
$this->options = $options;
$this->permissionGrantingStrategy = $permissionGrantingStrategy;
}
/**
* {@inheritdoc}
*/
public function findChildren(ObjectIdentityInterface $parentOid, $directChildrenOnly = false)
{
$sql = $this->getFindChildrenSql($parentOid, $directChildrenOnly);
$children = array();
foreach ($this->connection->executeQuery($sql)->fetchAll() as $data) {
$children[] = new ObjectIdentity($data['object_identifier'], $data['class_type']);
}
return $children;
}
/**
* {@inheritdoc}
*/
public function findAcl(ObjectIdentityInterface $oid, array $sids = array())
{
return $this->findAcls(array($oid), $sids)->offsetGet($oid);
}
/**
* {@inheritdoc}
*/
public function findAcls(array $oids, array $sids = array())
{
$result = new \SplObjectStorage();
$currentBatch = array();
$oidLookup = array();
for ($i = 0, $c = count($oids); $i < $c; ++$i) {
$oid = $oids[$i];
$oidLookupKey = $oid->getIdentifier().$oid->getType();
$oidLookup[$oidLookupKey] = $oid;
$aclFound = false;
// check if result already contains an ACL
if ($result->contains($oid)) {
$aclFound = true;
}
// check if this ACL has already been hydrated
if (!$aclFound && isset($this->loadedAcls[$oid->getType()][$oid->getIdentifier()])) {
$acl = $this->loadedAcls[$oid->getType()][$oid->getIdentifier()];
if (!$acl->isSidLoaded($sids)) {
// FIXME: we need to load ACEs for the missing SIDs. This is never
// reached by the default implementation, since we do not
// filter by SID
throw new \RuntimeException('This is not supported by the default implementation.');
} else {
$result->attach($oid, $acl);
$aclFound = true;
}
}
// check if we can locate the ACL in the cache
if (!$aclFound && null !== $this->cache) {
$acl = $this->cache->getFromCacheByIdentity($oid);
if (null !== $acl) {
if ($acl->isSidLoaded($sids)) {
// check if any of the parents has been loaded since we need to
// ensure that there is only ever one ACL per object identity
$parentAcl = $acl->getParentAcl();
while (null !== $parentAcl) {
$parentOid = $parentAcl->getObjectIdentity();
if (isset($this->loadedAcls[$parentOid->getType()][$parentOid->getIdentifier()])) {
$acl->setParentAcl($this->loadedAcls[$parentOid->getType()][$parentOid->getIdentifier()]);
break;
} else {
$this->loadedAcls[$parentOid->getType()][$parentOid->getIdentifier()] = $parentAcl;
$this->updateAceIdentityMap($parentAcl);
}
$parentAcl = $parentAcl->getParentAcl();
}
$this->loadedAcls[$oid->getType()][$oid->getIdentifier()] = $acl;
$this->updateAceIdentityMap($acl);
$result->attach($oid, $acl);
$aclFound = true;
} else {
$this->cache->evictFromCacheByIdentity($oid);
foreach ($this->findChildren($oid) as $childOid) {
$this->cache->evictFromCacheByIdentity($childOid);
}
}
}
}
// looks like we have to load the ACL from the database
if (!$aclFound) {
$currentBatch[] = $oid;
}
// Is it time to load the current batch?
$currentBatchesCount = count($currentBatch);
if ($currentBatchesCount > 0 && (self::MAX_BATCH_SIZE === $currentBatchesCount || ($i + 1) === $c)) {
try {
$loadedBatch = $this->lookupObjectIdentities($currentBatch, $sids, $oidLookup);
} catch (AclNotFoundException $e) {
if ($result->count()) {
$partialResultException = new NotAllAclsFoundException('The provider could not find ACLs for all object identities.');
$partialResultException->setPartialResult($result);
throw $partialResultException;
} else {
throw $e;
}
}
foreach ($loadedBatch as $loadedOid) {
$loadedAcl = $loadedBatch->offsetGet($loadedOid);
if (null !== $this->cache) {
$this->cache->putInCache($loadedAcl);
}
if (isset($oidLookup[$loadedOid->getIdentifier().$loadedOid->getType()])) {
$result->attach($loadedOid, $loadedAcl);
}
}
$currentBatch = array();
}
}
// check that we got ACLs for all the identities
foreach ($oids as $oid) {
if (!$result->contains($oid)) {
if (1 === count($oids)) {
$objectName = method_exists($oid, '__toString') ? $oid : get_class($oid);
throw new AclNotFoundException(sprintf('No ACL found for %s.', $objectName));
}
$partialResultException = new NotAllAclsFoundException('The provider could not find ACLs for all object identities.');
$partialResultException->setPartialResult($result);
throw $partialResultException;
}
}
return $result;
}
/**
* Constructs the query used for looking up object identities and associated
* ACEs, and security identities.
*
* @param array $ancestorIds
*
* @return string
*/
protected function getLookupSql(array $ancestorIds)
{
// FIXME: add support for filtering by sids (right now we select all sids)
$sql = <<<SELECTCLAUSE
SELECT
o.id as acl_id,
o.object_identifier,
o.parent_object_identity_id,
o.entries_inheriting,
c.class_type,
e.id as ace_id,
e.object_identity_id,
e.field_name,
e.ace_order,
e.mask,
e.granting,
e.granting_strategy,
e.audit_success,
e.audit_failure,
s.username,
s.identifier as security_identifier
FROM
{$this->options['oid_table_name']} o
INNER JOIN {$this->options['class_table_name']} c ON c.id = o.class_id
LEFT JOIN {$this->options['entry_table_name']} e ON (
e.class_id = o.class_id AND (e.object_identity_id = o.id OR {$this->connection->getDatabasePlatform()->getIsNullExpression('e.object_identity_id')})
)
LEFT JOIN {$this->options['sid_table_name']} s ON (
s.id = e.security_identity_id
)
WHERE (o.id =
SELECTCLAUSE;
$sql .= implode(' OR o.id = ', $ancestorIds).')';
return $sql;
}
protected function getAncestorLookupSql(array $batch)
{
$sql = <<<SELECTCLAUSE
SELECT a.ancestor_id
FROM
{$this->options['oid_table_name']} o
INNER JOIN {$this->options['class_table_name']} c ON c.id = o.class_id
INNER JOIN {$this->options['oid_ancestors_table_name']} a ON a.object_identity_id = o.id
WHERE (
SELECTCLAUSE;
$types = array();
$count = count($batch);
for ($i = 0; $i < $count; ++$i) {
if (!isset($types[$batch[$i]->getType()])) {
$types[$batch[$i]->getType()] = true;
// if there is more than one type we can safely break out of the
// loop, because it is the differentiator factor on whether to
// query for only one or more class types
if (count($types) > 1) {
break;
}
}
}
if (1 === count($types)) {
$ids = array();
for ($i = 0; $i < $count; ++$i) {
$identifier = (string) $batch[$i]->getIdentifier();
$ids[] = $this->connection->quote($identifier);
}
$sql .= sprintf(
'(o.object_identifier IN (%s) AND c.class_type = %s)',
implode(',', $ids),
$this->connection->quote($batch[0]->getType())
);
} else {
$where = '(o.object_identifier = %s AND c.class_type = %s)';
for ($i = 0; $i < $count; ++$i) {
$sql .= sprintf(
$where,
$this->connection->quote($batch[$i]->getIdentifier()),
$this->connection->quote($batch[$i]->getType())
);
if ($i + 1 < $count) {
$sql .= ' OR ';
}
}
}
$sql .= ')';
return $sql;
}
/**
* Constructs the SQL for retrieving child object identities for the given
* object identities.
*
* @param ObjectIdentityInterface $oid
* @param bool $directChildrenOnly
*
* @return string
*/
protected function getFindChildrenSql(ObjectIdentityInterface $oid, $directChildrenOnly)
{
if (false === $directChildrenOnly) {
$query = <<<FINDCHILDREN
SELECT o.object_identifier, c.class_type
FROM
{$this->options['oid_table_name']} o
INNER JOIN {$this->options['class_table_name']} c ON c.id = o.class_id
INNER JOIN {$this->options['oid_ancestors_table_name']} a ON a.object_identity_id = o.id
WHERE
a.ancestor_id = %d AND a.object_identity_id != a.ancestor_id
FINDCHILDREN;
} else {
$query = <<<FINDCHILDREN
SELECT o.object_identifier, c.class_type
FROM {$this->options['oid_table_name']} o
INNER JOIN {$this->options['class_table_name']} c ON c.id = o.class_id
WHERE o.parent_object_identity_id = %d
FINDCHILDREN;
}
return sprintf($query, $this->retrieveObjectIdentityPrimaryKey($oid));
}
/**
* Constructs the SQL for retrieving the primary key of the given object
* identity.
*
* @param ObjectIdentityInterface $oid
*
* @return string
*/
protected function getSelectObjectIdentityIdSql(ObjectIdentityInterface $oid)
{
$query = <<<QUERY
SELECT o.id
FROM %s o
INNER JOIN %s c ON c.id = o.class_id
WHERE o.object_identifier = %s AND c.class_type = %s
QUERY;
return sprintf(
$query,
$this->options['oid_table_name'],
$this->options['class_table_name'],
$this->connection->quote((string) $oid->getIdentifier()),
$this->connection->quote((string) $oid->getType())
);
}
/**
* Returns the primary key of the passed object identity.
*
* @param ObjectIdentityInterface $oid
*
* @return int
*/
final protected function retrieveObjectIdentityPrimaryKey(ObjectIdentityInterface $oid)
{
return $this->connection->executeQuery($this->getSelectObjectIdentityIdSql($oid))->fetchColumn();
}
/**
* This method is called when an ACL instance is retrieved from the cache.
*
* @param AclInterface $acl
*/
private function updateAceIdentityMap(AclInterface $acl)
{
foreach (array('classAces', 'classFieldAces', 'objectAces', 'objectFieldAces') as $property) {
$reflection = new \ReflectionProperty($acl, $property);
$reflection->setAccessible(true);
$value = $reflection->getValue($acl);
if ('classAces' === $property || 'objectAces' === $property) {
$this->doUpdateAceIdentityMap($value);
} else {
foreach ($value as $field => $aces) {
$this->doUpdateAceIdentityMap($value[$field]);
}
}
$reflection->setValue($acl, $value);
$reflection->setAccessible(false);
}
}
/**
* Retrieves all the ids which need to be queried from the database
* including the ids of parent ACLs.
*
* @param array $batch
*
* @return array
*/
private function getAncestorIds(array $batch)
{
$sql = $this->getAncestorLookupSql($batch);
$ancestorIds = array();
foreach ($this->connection->executeQuery($sql)->fetchAll() as $data) {
// FIXME: skip ancestors which are cached
// Fix: Oracle returns keys in uppercase
$ancestorIds[] = reset($data);
}
return $ancestorIds;
}
/**
* Does either overwrite the passed ACE, or saves it in the global identity
* map to ensure every ACE only gets instantiated once.
*
* @param array &$aces
*/
private function doUpdateAceIdentityMap(array &$aces)
{
foreach ($aces as $index => $ace) {
if (isset($this->loadedAces[$ace->getId()])) {
$aces[$index] = $this->loadedAces[$ace->getId()];
} else {
$this->loadedAces[$ace->getId()] = $ace;
}
}
}
/**
* This method is called for object identities which could not be retrieved
* from the cache, and for which thus a database query is required.
*
* @param array $batch
* @param array $sids
* @param array $oidLookup
*
* @return \SplObjectStorage mapping object identities to ACL instances
*
* @throws AclNotFoundException
*/
private function lookupObjectIdentities(array $batch, array $sids, array $oidLookup)
{
$ancestorIds = $this->getAncestorIds($batch);
if (!$ancestorIds) {
throw new AclNotFoundException('There is no ACL for the given object identity.');
}
$sql = $this->getLookupSql($ancestorIds);
$stmt = $this->connection->executeQuery($sql);
return $this->hydrateObjectIdentities($stmt, $oidLookup, $sids);
}
/**
* This method is called to hydrate ACLs and ACEs.
*
* This method was designed for performance; thus, a lot of code has been
* inlined at the cost of readability, and maintainability.
*
* Keep in mind that changes to this method might severely reduce the
* performance of the entire ACL system.
*
* @param Statement $stmt
* @param array $oidLookup
* @param array $sids
*
* @return \SplObjectStorage
*
* @throws \RuntimeException
*/
private function hydrateObjectIdentities(Statement $stmt, array $oidLookup, array $sids)
{
$parentIdToFill = new \SplObjectStorage();
$acls = $aces = $emptyArray = array();
$oidCache = $oidLookup;
$result = new \SplObjectStorage();
$loadedAces = &$this->loadedAces;
$loadedAcls = &$this->loadedAcls;
$permissionGrantingStrategy = $this->permissionGrantingStrategy;
// we need these to set protected properties on hydrated objects
$aclReflection = new \ReflectionClass('Symfony\Component\Security\Acl\Domain\Acl');
$aclClassAcesProperty = $aclReflection->getProperty('classAces');
$aclClassAcesProperty->setAccessible(true);
$aclClassFieldAcesProperty = $aclReflection->getProperty('classFieldAces');
$aclClassFieldAcesProperty->setAccessible(true);
$aclObjectAcesProperty = $aclReflection->getProperty('objectAces');
$aclObjectAcesProperty->setAccessible(true);
$aclObjectFieldAcesProperty = $aclReflection->getProperty('objectFieldAces');
$aclObjectFieldAcesProperty->setAccessible(true);
$aclParentAclProperty = $aclReflection->getProperty('parentAcl');
$aclParentAclProperty->setAccessible(true);
// fetchAll() consumes more memory than consecutive calls to fetch(),
// but it is faster
foreach ($stmt->fetchAll(\PDO::FETCH_NUM) as $data) {
list($aclId,
$objectIdentifier,
$parentObjectIdentityId,
$entriesInheriting,
$classType,
$aceId,
$objectIdentityId,
$fieldName,
$aceOrder,
$mask,
$granting,
$grantingStrategy,
$auditSuccess,
$auditFailure,
$username,
$securityIdentifier) = array_values($data);
// has the ACL been hydrated during this hydration cycle?
if (isset($acls[$aclId])) {
$acl = $acls[$aclId];
// has the ACL been hydrated during any previous cycle, or was possibly loaded
// from cache?
} elseif (isset($loadedAcls[$classType][$objectIdentifier])) {
$acl = $loadedAcls[$classType][$objectIdentifier];
// keep reference in local array (saves us some hash calculations)
$acls[$aclId] = $acl;
// attach ACL to the result set; even though we do not enforce that every
// object identity has only one instance, we must make sure to maintain
// referential equality with the oids passed to findAcls()
$oidCacheKey = $objectIdentifier.$classType;
if (!isset($oidCache[$oidCacheKey])) {
$oidCache[$oidCacheKey] = $acl->getObjectIdentity();
}
$result->attach($oidCache[$oidCacheKey], $acl);
// so, this hasn't been hydrated yet
} else {
// create object identity if we haven't done so yet
$oidLookupKey = $objectIdentifier.$classType;
if (!isset($oidCache[$oidLookupKey])) {
$oidCache[$oidLookupKey] = new ObjectIdentity($objectIdentifier, $classType);
}
$acl = new Acl((int) $aclId, $oidCache[$oidLookupKey], $permissionGrantingStrategy, $emptyArray, !!$entriesInheriting);
// keep a local, and global reference to this ACL
$loadedAcls[$classType][$objectIdentifier] = $acl;
$acls[$aclId] = $acl;
// try to fill in parent ACL, or defer until all ACLs have been hydrated
if (null !== $parentObjectIdentityId) {
if (isset($acls[$parentObjectIdentityId])) {
$aclParentAclProperty->setValue($acl, $acls[$parentObjectIdentityId]);
} else {
$parentIdToFill->attach($acl, $parentObjectIdentityId);
}
}
$result->attach($oidCache[$oidLookupKey], $acl);
}
// check if this row contains an ACE record
if (null !== $aceId) {
// have we already hydrated ACEs for this ACL?
if (!isset($aces[$aclId])) {
$aces[$aclId] = array($emptyArray, $emptyArray, $emptyArray, $emptyArray);
}
// has this ACE already been hydrated during a previous cycle, or
// possible been loaded from cache?
// It is important to only ever have one ACE instance per actual row since
// some ACEs are shared between ACL instances
if (!isset($loadedAces[$aceId])) {
if (!isset($sids[$key = ($username ? '1' : '0').$securityIdentifier])) {
if ($username) {
$sids[$key] = new UserSecurityIdentity(
substr($securityIdentifier, 1 + $pos = strpos($securityIdentifier, '-')),
substr($securityIdentifier, 0, $pos)
);
} else {
$sids[$key] = new RoleSecurityIdentity($securityIdentifier);
}
}
if (null === $fieldName) {
$loadedAces[$aceId] = new Entry((int) $aceId, $acl, $sids[$key], $grantingStrategy, (int) $mask, !!$granting, !!$auditFailure, !!$auditSuccess);
} else {
$loadedAces[$aceId] = new FieldEntry((int) $aceId, $acl, $fieldName, $sids[$key], $grantingStrategy, (int) $mask, !!$granting, !!$auditFailure, !!$auditSuccess);
}
}
$ace = $loadedAces[$aceId];
// assign ACE to the correct property
if (null === $objectIdentityId) {
if (null === $fieldName) {
$aces[$aclId][0][$aceOrder] = $ace;
} else {
$aces[$aclId][1][$fieldName][$aceOrder] = $ace;
}
} else {
if (null === $fieldName) {
$aces[$aclId][2][$aceOrder] = $ace;
} else {
$aces[$aclId][3][$fieldName][$aceOrder] = $ace;
}
}
}
}
// We do not sort on database level since we only want certain subsets to be sorted,
// and we are going to read the entire result set anyway.
// Sorting on DB level increases query time by an order of magnitude while it is
// almost negligible when we use PHPs array sort functions.
foreach ($aces as $aclId => $aceData) {
$acl = $acls[$aclId];
ksort($aceData[0]);
$aclClassAcesProperty->setValue($acl, $aceData[0]);
foreach (array_keys($aceData[1]) as $fieldName) {
ksort($aceData[1][$fieldName]);
}
$aclClassFieldAcesProperty->setValue($acl, $aceData[1]);
ksort($aceData[2]);
$aclObjectAcesProperty->setValue($acl, $aceData[2]);
foreach (array_keys($aceData[3]) as $fieldName) {
ksort($aceData[3][$fieldName]);
}
$aclObjectFieldAcesProperty->setValue($acl, $aceData[3]);
}
// fill-in parent ACLs where this hasn't been done yet cause the parent ACL was not
// yet available
$processed = 0;
foreach ($parentIdToFill as $acl) {
$parentId = $parentIdToFill->offsetGet($acl);
// let's see if we have already hydrated this
if (isset($acls[$parentId])) {
$aclParentAclProperty->setValue($acl, $acls[$parentId]);
++$processed;
continue;
}
}
// reset reflection changes
$aclClassAcesProperty->setAccessible(false);
$aclClassFieldAcesProperty->setAccessible(false);
$aclObjectAcesProperty->setAccessible(false);
$aclObjectFieldAcesProperty->setAccessible(false);
$aclParentAclProperty->setAccessible(false);
// this should never be true if the database integrity hasn't been compromised
if ($processed < count($parentIdToFill)) {
throw new \RuntimeException('Not all parent ids were populated. This implies an integrity problem.');
}
return $result;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,154 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Dbal;
use Doctrine\DBAL\Schema\Schema as BaseSchema;
use Doctrine\DBAL\Connection;
/**
* The schema used for the ACL system.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
final class Schema extends BaseSchema
{
protected $options;
/**
* Constructor.
*
* @param array $options the names for tables
* @param Connection $connection
*/
public function __construct(array $options, Connection $connection = null)
{
$schemaConfig = null === $connection ? null : $connection->getSchemaManager()->createSchemaConfig();
parent::__construct(array(), array(), $schemaConfig);
$this->options = $options;
$this->addClassTable();
$this->addSecurityIdentitiesTable();
$this->addObjectIdentitiesTable();
$this->addObjectIdentityAncestorsTable();
$this->addEntryTable();
}
/**
* Merges ACL schema with the given schema.
*
* @param BaseSchema $schema
*/
public function addToSchema(BaseSchema $schema)
{
foreach ($this->getTables() as $table) {
$schema->_addTable($table);
}
foreach ($this->getSequences() as $sequence) {
$schema->_addSequence($sequence);
}
}
/**
* Adds the class table to the schema.
*/
protected function addClassTable()
{
$table = $this->createTable($this->options['class_table_name']);
$table->addColumn('id', 'integer', array('unsigned' => true, 'autoincrement' => 'auto'));
$table->addColumn('class_type', 'string', array('length' => 200));
$table->setPrimaryKey(array('id'));
$table->addUniqueIndex(array('class_type'));
}
/**
* Adds the entry table to the schema.
*/
protected function addEntryTable()
{
$table = $this->createTable($this->options['entry_table_name']);
$table->addColumn('id', 'integer', array('unsigned' => true, 'autoincrement' => 'auto'));
$table->addColumn('class_id', 'integer', array('unsigned' => true));
$table->addColumn('object_identity_id', 'integer', array('unsigned' => true, 'notnull' => false));
$table->addColumn('field_name', 'string', array('length' => 50, 'notnull' => false));
$table->addColumn('ace_order', 'smallint', array('unsigned' => true));
$table->addColumn('security_identity_id', 'integer', array('unsigned' => true));
$table->addColumn('mask', 'integer');
$table->addColumn('granting', 'boolean');
$table->addColumn('granting_strategy', 'string', array('length' => 30));
$table->addColumn('audit_success', 'boolean');
$table->addColumn('audit_failure', 'boolean');
$table->setPrimaryKey(array('id'));
$table->addUniqueIndex(array('class_id', 'object_identity_id', 'field_name', 'ace_order'));
$table->addIndex(array('class_id', 'object_identity_id', 'security_identity_id'));
$table->addForeignKeyConstraint($this->getTable($this->options['class_table_name']), array('class_id'), array('id'), array('onDelete' => 'CASCADE', 'onUpdate' => 'CASCADE'));
$table->addForeignKeyConstraint($this->getTable($this->options['oid_table_name']), array('object_identity_id'), array('id'), array('onDelete' => 'CASCADE', 'onUpdate' => 'CASCADE'));
$table->addForeignKeyConstraint($this->getTable($this->options['sid_table_name']), array('security_identity_id'), array('id'), array('onDelete' => 'CASCADE', 'onUpdate' => 'CASCADE'));
}
/**
* Adds the object identity table to the schema.
*/
protected function addObjectIdentitiesTable()
{
$table = $this->createTable($this->options['oid_table_name']);
$table->addColumn('id', 'integer', array('unsigned' => true, 'autoincrement' => 'auto'));
$table->addColumn('class_id', 'integer', array('unsigned' => true));
$table->addColumn('object_identifier', 'string', array('length' => 100));
$table->addColumn('parent_object_identity_id', 'integer', array('unsigned' => true, 'notnull' => false));
$table->addColumn('entries_inheriting', 'boolean');
$table->setPrimaryKey(array('id'));
$table->addUniqueIndex(array('object_identifier', 'class_id'));
$table->addIndex(array('parent_object_identity_id'));
$table->addForeignKeyConstraint($table, array('parent_object_identity_id'), array('id'));
}
/**
* Adds the object identity relation table to the schema.
*/
protected function addObjectIdentityAncestorsTable()
{
$table = $this->createTable($this->options['oid_ancestors_table_name']);
$table->addColumn('object_identity_id', 'integer', array('unsigned' => true));
$table->addColumn('ancestor_id', 'integer', array('unsigned' => true));
$table->setPrimaryKey(array('object_identity_id', 'ancestor_id'));
$oidTable = $this->getTable($this->options['oid_table_name']);
$table->addForeignKeyConstraint($oidTable, array('object_identity_id'), array('id'), array('onDelete' => 'CASCADE', 'onUpdate' => 'CASCADE'));
$table->addForeignKeyConstraint($oidTable, array('ancestor_id'), array('id'), array('onDelete' => 'CASCADE', 'onUpdate' => 'CASCADE'));
}
/**
* Adds the security identity table to the schema.
*/
protected function addSecurityIdentitiesTable()
{
$table = $this->createTable($this->options['sid_table_name']);
$table->addColumn('id', 'integer', array('unsigned' => true, 'autoincrement' => 'auto'));
$table->addColumn('identifier', 'string', array('length' => 200));
$table->addColumn('username', 'boolean');
$table->setPrimaryKey(array('id'));
$table->addUniqueIndex(array('identifier', 'username'));
}
}

View File

@ -1,667 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Domain;
use Doctrine\Common\NotifyPropertyChanged;
use Doctrine\Common\PropertyChangedListener;
use Symfony\Component\Security\Acl\Model\AclInterface;
use Symfony\Component\Security\Acl\Model\AuditableAclInterface;
use Symfony\Component\Security\Acl\Model\EntryInterface;
use Symfony\Component\Security\Acl\Model\ObjectIdentityInterface;
use Symfony\Component\Security\Acl\Model\PermissionGrantingStrategyInterface;
use Symfony\Component\Security\Acl\Model\SecurityIdentityInterface;
/**
* An ACL implementation.
*
* Each object identity has exactly one associated ACL. Each ACL can have four
* different types of ACEs (class ACEs, object ACEs, class field ACEs, object field
* ACEs).
*
* You should not iterate over the ACEs yourself, but instead use isGranted(),
* or isFieldGranted(). These will utilize an implementation of PermissionGrantingStrategy
* internally.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class Acl implements AuditableAclInterface, NotifyPropertyChanged
{
private $parentAcl;
private $permissionGrantingStrategy;
private $objectIdentity;
private $classAces = array();
private $classFieldAces = array();
private $objectAces = array();
private $objectFieldAces = array();
private $id;
private $loadedSids;
private $entriesInheriting;
private $listeners = array();
/**
* Constructor.
*
* @param int $id
* @param ObjectIdentityInterface $objectIdentity
* @param PermissionGrantingStrategyInterface $permissionGrantingStrategy
* @param array $loadedSids
* @param bool $entriesInheriting
*/
public function __construct($id, ObjectIdentityInterface $objectIdentity, PermissionGrantingStrategyInterface $permissionGrantingStrategy, array $loadedSids = array(), $entriesInheriting)
{
$this->id = $id;
$this->objectIdentity = $objectIdentity;
$this->permissionGrantingStrategy = $permissionGrantingStrategy;
$this->loadedSids = $loadedSids;
$this->entriesInheriting = $entriesInheriting;
}
/**
* Adds a property changed listener.
*
* @param PropertyChangedListener $listener
*/
public function addPropertyChangedListener(PropertyChangedListener $listener)
{
$this->listeners[] = $listener;
}
/**
* {@inheritdoc}
*/
public function deleteClassAce($index)
{
$this->deleteAce('classAces', $index);
}
/**
* {@inheritdoc}
*/
public function deleteClassFieldAce($index, $field)
{
$this->deleteFieldAce('classFieldAces', $index, $field);
}
/**
* {@inheritdoc}
*/
public function deleteObjectAce($index)
{
$this->deleteAce('objectAces', $index);
}
/**
* {@inheritdoc}
*/
public function deleteObjectFieldAce($index, $field)
{
$this->deleteFieldAce('objectFieldAces', $index, $field);
}
/**
* {@inheritdoc}
*/
public function getClassAces()
{
return $this->classAces;
}
/**
* {@inheritdoc}
*/
public function getClassFieldAces($field)
{
return isset($this->classFieldAces[$field]) ? $this->classFieldAces[$field] : array();
}
/**
* {@inheritdoc}
*/
public function getObjectAces()
{
return $this->objectAces;
}
/**
* {@inheritdoc}
*/
public function getObjectFieldAces($field)
{
return isset($this->objectFieldAces[$field]) ? $this->objectFieldAces[$field] : array();
}
/**
* {@inheritdoc}
*/
public function getId()
{
return $this->id;
}
/**
* {@inheritdoc}
*/
public function getObjectIdentity()
{
return $this->objectIdentity;
}
/**
* {@inheritdoc}
*/
public function getParentAcl()
{
return $this->parentAcl;
}
/**
* {@inheritdoc}
*/
public function insertClassAce(SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null)
{
$this->insertAce('classAces', $index, $mask, $sid, $granting, $strategy);
}
/**
* {@inheritdoc}
*/
public function insertClassFieldAce($field, SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null)
{
$this->insertFieldAce('classFieldAces', $index, $field, $mask, $sid, $granting, $strategy);
}
/**
* {@inheritdoc}
*/
public function insertObjectAce(SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null)
{
$this->insertAce('objectAces', $index, $mask, $sid, $granting, $strategy);
}
/**
* {@inheritdoc}
*/
public function insertObjectFieldAce($field, SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null)
{
$this->insertFieldAce('objectFieldAces', $index, $field, $mask, $sid, $granting, $strategy);
}
/**
* {@inheritdoc}
*/
public function isEntriesInheriting()
{
return $this->entriesInheriting;
}
/**
* {@inheritdoc}
*/
public function isFieldGranted($field, array $masks, array $securityIdentities, $administrativeMode = false)
{
return $this->permissionGrantingStrategy->isFieldGranted($this, $field, $masks, $securityIdentities, $administrativeMode);
}
/**
* {@inheritdoc}
*/
public function isGranted(array $masks, array $securityIdentities, $administrativeMode = false)
{
return $this->permissionGrantingStrategy->isGranted($this, $masks, $securityIdentities, $administrativeMode);
}
/**
* {@inheritdoc}
*/
public function isSidLoaded($sids)
{
if (!$this->loadedSids) {
return true;
}
if (!is_array($sids)) {
$sids = array($sids);
}
foreach ($sids as $sid) {
if (!$sid instanceof SecurityIdentityInterface) {
throw new \InvalidArgumentException(
'$sid must be an instance of SecurityIdentityInterface.');
}
foreach ($this->loadedSids as $loadedSid) {
if ($loadedSid->equals($sid)) {
continue 2;
}
}
return false;
}
return true;
}
/**
* Implementation for the \Serializable interface.
*
* @return string
*/
public function serialize()
{
return serialize(array(
null === $this->parentAcl ? null : $this->parentAcl->getId(),
$this->objectIdentity,
$this->classAces,
$this->classFieldAces,
$this->objectAces,
$this->objectFieldAces,
$this->id,
$this->loadedSids,
$this->entriesInheriting,
));
}
/**
* Implementation for the \Serializable interface.
*
* @param string $serialized
*/
public function unserialize($serialized)
{
list($this->parentAcl,
$this->objectIdentity,
$this->classAces,
$this->classFieldAces,
$this->objectAces,
$this->objectFieldAces,
$this->id,
$this->loadedSids,
$this->entriesInheriting
) = unserialize($serialized);
$this->listeners = array();
}
/**
* {@inheritdoc}
*/
public function setEntriesInheriting($boolean)
{
if ($this->entriesInheriting !== $boolean) {
$this->onPropertyChanged('entriesInheriting', $this->entriesInheriting, $boolean);
$this->entriesInheriting = $boolean;
}
}
/**
* {@inheritdoc}
*/
public function setParentAcl(AclInterface $acl = null)
{
if (null !== $acl && null === $acl->getId()) {
throw new \InvalidArgumentException('$acl must have an ID.');
}
if ($this->parentAcl !== $acl) {
$this->onPropertyChanged('parentAcl', $this->parentAcl, $acl);
$this->parentAcl = $acl;
}
}
/**
* {@inheritdoc}
*/
public function updateClassAce($index, $mask, $strategy = null)
{
$this->updateAce('classAces', $index, $mask, $strategy);
}
/**
* {@inheritdoc}
*/
public function updateClassFieldAce($index, $field, $mask, $strategy = null)
{
$this->updateFieldAce('classFieldAces', $index, $field, $mask, $strategy);
}
/**
* {@inheritdoc}
*/
public function updateObjectAce($index, $mask, $strategy = null)
{
$this->updateAce('objectAces', $index, $mask, $strategy);
}
/**
* {@inheritdoc}
*/
public function updateObjectFieldAce($index, $field, $mask, $strategy = null)
{
$this->updateFieldAce('objectFieldAces', $index, $field, $mask, $strategy);
}
/**
* {@inheritdoc}
*/
public function updateClassAuditing($index, $auditSuccess, $auditFailure)
{
$this->updateAuditing($this->classAces, $index, $auditSuccess, $auditFailure);
}
/**
* {@inheritdoc}
*/
public function updateClassFieldAuditing($index, $field, $auditSuccess, $auditFailure)
{
if (!isset($this->classFieldAces[$field])) {
throw new \InvalidArgumentException(sprintf('There are no ACEs for field "%s".', $field));
}
$this->updateAuditing($this->classFieldAces[$field], $index, $auditSuccess, $auditFailure);
}
/**
* {@inheritdoc}
*/
public function updateObjectAuditing($index, $auditSuccess, $auditFailure)
{
$this->updateAuditing($this->objectAces, $index, $auditSuccess, $auditFailure);
}
/**
* {@inheritdoc}
*/
public function updateObjectFieldAuditing($index, $field, $auditSuccess, $auditFailure)
{
if (!isset($this->objectFieldAces[$field])) {
throw new \InvalidArgumentException(sprintf('There are no ACEs for field "%s".', $field));
}
$this->updateAuditing($this->objectFieldAces[$field], $index, $auditSuccess, $auditFailure);
}
/**
* Deletes an ACE.
*
* @param string $property
* @param int $index
*
* @throws \OutOfBoundsException
*/
private function deleteAce($property, $index)
{
$aces = &$this->$property;
if (!isset($aces[$index])) {
throw new \OutOfBoundsException(sprintf('The index "%d" does not exist.', $index));
}
$oldValue = $this->$property;
unset($aces[$index]);
$this->$property = array_values($this->$property);
$this->onPropertyChanged($property, $oldValue, $this->$property);
for ($i = $index, $c = count($this->$property); $i < $c; ++$i) {
$this->onEntryPropertyChanged($aces[$i], 'aceOrder', $i + 1, $i);
}
}
/**
* Deletes a field-based ACE.
*
* @param string $property
* @param int $index
* @param string $field
*
* @throws \OutOfBoundsException
*/
private function deleteFieldAce($property, $index, $field)
{
$aces = &$this->$property;
if (!isset($aces[$field][$index])) {
throw new \OutOfBoundsException(sprintf('The index "%d" does not exist.', $index));
}
$oldValue = $this->$property;
unset($aces[$field][$index]);
$aces[$field] = array_values($aces[$field]);
$this->onPropertyChanged($property, $oldValue, $this->$property);
for ($i = $index, $c = count($aces[$field]); $i < $c; ++$i) {
$this->onEntryPropertyChanged($aces[$field][$i], 'aceOrder', $i + 1, $i);
}
}
/**
* Inserts an ACE.
*
* @param string $property
* @param int $index
* @param int $mask
* @param SecurityIdentityInterface $sid
* @param bool $granting
* @param string $strategy
*
* @throws \OutOfBoundsException
* @throws \InvalidArgumentException
*/
private function insertAce($property, $index, $mask, SecurityIdentityInterface $sid, $granting, $strategy = null)
{
if ($index < 0 || $index > count($this->$property)) {
throw new \OutOfBoundsException(sprintf('The index must be in the interval [0, %d].', count($this->$property)));
}
if (!is_int($mask)) {
throw new \InvalidArgumentException('$mask must be an integer.');
}
if (null === $strategy) {
if (true === $granting) {
$strategy = PermissionGrantingStrategy::ALL;
} else {
$strategy = PermissionGrantingStrategy::ANY;
}
}
$aces = &$this->$property;
$oldValue = $this->$property;
if (isset($aces[$index])) {
$this->$property = array_merge(
array_slice($this->$property, 0, $index),
array(true),
array_slice($this->$property, $index)
);
for ($i = $index, $c = count($this->$property) - 1; $i < $c; ++$i) {
$this->onEntryPropertyChanged($aces[$i + 1], 'aceOrder', $i, $i + 1);
}
}
$aces[$index] = new Entry(null, $this, $sid, $strategy, $mask, $granting, false, false);
$this->onPropertyChanged($property, $oldValue, $this->$property);
}
/**
* Inserts a field-based ACE.
*
* @param string $property
* @param int $index
* @param string $field
* @param int $mask
* @param SecurityIdentityInterface $sid
* @param bool $granting
* @param string $strategy
*
* @throws \InvalidArgumentException
* @throws \OutOfBoundsException
*/
private function insertFieldAce($property, $index, $field, $mask, SecurityIdentityInterface $sid, $granting, $strategy = null)
{
if (0 === strlen($field)) {
throw new \InvalidArgumentException('$field cannot be empty.');
}
if (!is_int($mask)) {
throw new \InvalidArgumentException('$mask must be an integer.');
}
if (null === $strategy) {
if (true === $granting) {
$strategy = PermissionGrantingStrategy::ALL;
} else {
$strategy = PermissionGrantingStrategy::ANY;
}
}
$aces = &$this->$property;
if (!isset($aces[$field])) {
$aces[$field] = array();
}
if ($index < 0 || $index > count($aces[$field])) {
throw new \OutOfBoundsException(sprintf('The index must be in the interval [0, %d].', count($this->$property)));
}
$oldValue = $aces;
if (isset($aces[$field][$index])) {
$aces[$field] = array_merge(
array_slice($aces[$field], 0, $index),
array(true),
array_slice($aces[$field], $index)
);
for ($i = $index, $c = count($aces[$field]) - 1; $i < $c; ++$i) {
$this->onEntryPropertyChanged($aces[$field][$i + 1], 'aceOrder', $i, $i + 1);
}
}
$aces[$field][$index] = new FieldEntry(null, $this, $field, $sid, $strategy, $mask, $granting, false, false);
$this->onPropertyChanged($property, $oldValue, $this->$property);
}
/**
* Updates an ACE.
*
* @param string $property
* @param int $index
* @param int $mask
* @param string $strategy
*
* @throws \OutOfBoundsException
*/
private function updateAce($property, $index, $mask, $strategy = null)
{
$aces = &$this->$property;
if (!isset($aces[$index])) {
throw new \OutOfBoundsException(sprintf('The index "%d" does not exist.', $index));
}
$ace = $aces[$index];
if ($mask !== $oldMask = $ace->getMask()) {
$this->onEntryPropertyChanged($ace, 'mask', $oldMask, $mask);
$ace->setMask($mask);
}
if (null !== $strategy && $strategy !== $oldStrategy = $ace->getStrategy()) {
$this->onEntryPropertyChanged($ace, 'strategy', $oldStrategy, $strategy);
$ace->setStrategy($strategy);
}
}
/**
* Updates auditing for an ACE.
*
* @param array &$aces
* @param int $index
* @param bool $auditSuccess
* @param bool $auditFailure
*
* @throws \OutOfBoundsException
*/
private function updateAuditing(array &$aces, $index, $auditSuccess, $auditFailure)
{
if (!isset($aces[$index])) {
throw new \OutOfBoundsException(sprintf('The index "%d" does not exist.', $index));
}
if ($auditSuccess !== $aces[$index]->isAuditSuccess()) {
$this->onEntryPropertyChanged($aces[$index], 'auditSuccess', !$auditSuccess, $auditSuccess);
$aces[$index]->setAuditSuccess($auditSuccess);
}
if ($auditFailure !== $aces[$index]->isAuditFailure()) {
$this->onEntryPropertyChanged($aces[$index], 'auditFailure', !$auditFailure, $auditFailure);
$aces[$index]->setAuditFailure($auditFailure);
}
}
/**
* Updates a field-based ACE.
*
* @param string $property
* @param int $index
* @param string $field
* @param int $mask
* @param string $strategy
*
* @throws \InvalidArgumentException
* @throws \OutOfBoundsException
*/
private function updateFieldAce($property, $index, $field, $mask, $strategy = null)
{
if (0 === strlen($field)) {
throw new \InvalidArgumentException('$field cannot be empty.');
}
$aces = &$this->$property;
if (!isset($aces[$field][$index])) {
throw new \OutOfBoundsException(sprintf('The index "%d" does not exist.', $index));
}
$ace = $aces[$field][$index];
if ($mask !== $oldMask = $ace->getMask()) {
$this->onEntryPropertyChanged($ace, 'mask', $oldMask, $mask);
$ace->setMask($mask);
}
if (null !== $strategy && $strategy !== $oldStrategy = $ace->getStrategy()) {
$this->onEntryPropertyChanged($ace, 'strategy', $oldStrategy, $strategy);
$ace->setStrategy($strategy);
}
}
/**
* Called when a property of the ACL changes.
*
* @param string $name
* @param mixed $oldValue
* @param mixed $newValue
*/
private function onPropertyChanged($name, $oldValue, $newValue)
{
foreach ($this->listeners as $listener) {
$listener->propertyChanged($this, $name, $oldValue, $newValue);
}
}
/**
* Called when a property of an ACE associated with this ACL changes.
*
* @param EntryInterface $entry
* @param string $name
* @param mixed $oldValue
* @param mixed $newValue
*/
private function onEntryPropertyChanged(EntryInterface $entry, $name, $oldValue, $newValue)
{
foreach ($this->listeners as $listener) {
$listener->propertyChanged($entry, $name, $oldValue, $newValue);
}
}
}

View File

@ -1,65 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Domain;
use Symfony\Component\Security\Acl\Model\AclProviderInterface;
use Symfony\Component\Security\Acl\Model\ObjectIdentityRetrievalStrategyInterface;
use Symfony\Component\Security\Acl\Model\SecurityIdentityRetrievalStrategyInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
/**
* This service caches ACLs for an entire collection of objects.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class AclCollectionCache
{
private $aclProvider;
private $objectIdentityRetrievalStrategy;
private $securityIdentityRetrievalStrategy;
/**
* Constructor.
*
* @param AclProviderInterface $aclProvider
* @param ObjectIdentityRetrievalStrategyInterface $oidRetrievalStrategy
* @param SecurityIdentityRetrievalStrategyInterface $sidRetrievalStrategy
*/
public function __construct(AclProviderInterface $aclProvider, ObjectIdentityRetrievalStrategyInterface $oidRetrievalStrategy, SecurityIdentityRetrievalStrategyInterface $sidRetrievalStrategy)
{
$this->aclProvider = $aclProvider;
$this->objectIdentityRetrievalStrategy = $oidRetrievalStrategy;
$this->securityIdentityRetrievalStrategy = $sidRetrievalStrategy;
}
/**
* Batch loads ACLs for an entire collection; thus, it reduces the number
* of required queries considerably.
*
* @param mixed $collection anything that can be passed to foreach()
* @param TokenInterface[] $tokens an array of TokenInterface implementations
*/
public function cache($collection, array $tokens = array())
{
$sids = array();
foreach ($tokens as $token) {
$sids = array_merge($sids, $this->securityIdentityRetrievalStrategy->getSecurityIdentities($token));
}
$oids = array();
foreach ($collection as $domainObject) {
$oids[] = $this->objectIdentityRetrievalStrategy->getObjectIdentity($domainObject);
}
$this->aclProvider->findAcls($oids, $sids);
}
}

View File

@ -1,51 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Domain;
use Symfony\Component\Security\Acl\Model\AuditableEntryInterface;
use Symfony\Component\Security\Acl\Model\EntryInterface;
use Symfony\Component\Security\Acl\Model\AuditLoggerInterface;
/**
* Base audit logger implementation.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
abstract class AuditLogger implements AuditLoggerInterface
{
/**
* Performs some checks if logging was requested.
*
* @param bool $granted
* @param EntryInterface $ace
*/
public function logIfNeeded($granted, EntryInterface $ace)
{
if (!$ace instanceof AuditableEntryInterface) {
return;
}
if ($granted && $ace->isAuditSuccess()) {
$this->doLog($granted, $ace);
} elseif (!$granted && $ace->isAuditFailure()) {
$this->doLog($granted, $ace);
}
}
/**
* This method is only called when logging is needed.
*
* @param bool $granted
* @param EntryInterface $ace
*/
abstract protected function doLog($granted, EntryInterface $ace);
}

View File

@ -1,229 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Domain;
use Doctrine\Common\Cache\Cache;
use Doctrine\Common\Cache\CacheProvider;
use Symfony\Component\Security\Acl\Model\AclCacheInterface;
use Symfony\Component\Security\Acl\Model\AclInterface;
use Symfony\Component\Security\Acl\Model\ObjectIdentityInterface;
use Symfony\Component\Security\Acl\Model\PermissionGrantingStrategyInterface;
/**
* This class is a wrapper around the actual cache implementation.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class DoctrineAclCache implements AclCacheInterface
{
const PREFIX = 'sf2_acl_';
private $cache;
private $prefix;
private $permissionGrantingStrategy;
/**
* Constructor.
*
* @param Cache $cache
* @param PermissionGrantingStrategyInterface $permissionGrantingStrategy
* @param string $prefix
*
* @throws \InvalidArgumentException
*/
public function __construct(Cache $cache, PermissionGrantingStrategyInterface $permissionGrantingStrategy, $prefix = self::PREFIX)
{
if (0 === strlen($prefix)) {
throw new \InvalidArgumentException('$prefix cannot be empty.');
}
$this->cache = $cache;
$this->permissionGrantingStrategy = $permissionGrantingStrategy;
$this->prefix = $prefix;
}
/**
* {@inheritdoc}
*/
public function clearCache()
{
if ($this->cache instanceof CacheProvider) {
$this->cache->deleteAll();
}
}
/**
* {@inheritdoc}
*/
public function evictFromCacheById($aclId)
{
$lookupKey = $this->getAliasKeyForIdentity($aclId);
if (!$this->cache->contains($lookupKey)) {
return;
}
$key = $this->cache->fetch($lookupKey);
if ($this->cache->contains($key)) {
$this->cache->delete($key);
}
$this->cache->delete($lookupKey);
}
/**
* {@inheritdoc}
*/
public function evictFromCacheByIdentity(ObjectIdentityInterface $oid)
{
$key = $this->getDataKeyByIdentity($oid);
if (!$this->cache->contains($key)) {
return;
}
$this->cache->delete($key);
}
/**
* {@inheritdoc}
*/
public function getFromCacheById($aclId)
{
$lookupKey = $this->getAliasKeyForIdentity($aclId);
if (!$this->cache->contains($lookupKey)) {
return;
}
$key = $this->cache->fetch($lookupKey);
if (!$this->cache->contains($key)) {
$this->cache->delete($lookupKey);
return;
}
return $this->unserializeAcl($this->cache->fetch($key));
}
/**
* {@inheritdoc}
*/
public function getFromCacheByIdentity(ObjectIdentityInterface $oid)
{
$key = $this->getDataKeyByIdentity($oid);
if (!$this->cache->contains($key)) {
return;
}
return $this->unserializeAcl($this->cache->fetch($key));
}
/**
* {@inheritdoc}
*/
public function putInCache(AclInterface $acl)
{
if (null === $acl->getId()) {
throw new \InvalidArgumentException('Transient ACLs cannot be cached.');
}
if (null !== $parentAcl = $acl->getParentAcl()) {
$this->putInCache($parentAcl);
}
$key = $this->getDataKeyByIdentity($acl->getObjectIdentity());
$this->cache->save($key, serialize($acl));
$this->cache->save($this->getAliasKeyForIdentity($acl->getId()), $key);
}
/**
* Unserializes the ACL.
*
* @param string $serialized
*
* @return AclInterface
*/
private function unserializeAcl($serialized)
{
$acl = unserialize($serialized);
if (null !== $parentId = $acl->getParentAcl()) {
$parentAcl = $this->getFromCacheById($parentId);
if (null === $parentAcl) {
return;
}
$acl->setParentAcl($parentAcl);
}
$reflectionProperty = new \ReflectionProperty($acl, 'permissionGrantingStrategy');
$reflectionProperty->setAccessible(true);
$reflectionProperty->setValue($acl, $this->permissionGrantingStrategy);
$reflectionProperty->setAccessible(false);
$aceAclProperty = new \ReflectionProperty('Symfony\Component\Security\Acl\Domain\Entry', 'acl');
$aceAclProperty->setAccessible(true);
foreach ($acl->getObjectAces() as $ace) {
$aceAclProperty->setValue($ace, $acl);
}
foreach ($acl->getClassAces() as $ace) {
$aceAclProperty->setValue($ace, $acl);
}
$aceClassFieldProperty = new \ReflectionProperty($acl, 'classFieldAces');
$aceClassFieldProperty->setAccessible(true);
foreach ($aceClassFieldProperty->getValue($acl) as $aces) {
foreach ($aces as $ace) {
$aceAclProperty->setValue($ace, $acl);
}
}
$aceClassFieldProperty->setAccessible(false);
$aceObjectFieldProperty = new \ReflectionProperty($acl, 'objectFieldAces');
$aceObjectFieldProperty->setAccessible(true);
foreach ($aceObjectFieldProperty->getValue($acl) as $aces) {
foreach ($aces as $ace) {
$aceAclProperty->setValue($ace, $acl);
}
}
$aceObjectFieldProperty->setAccessible(false);
$aceAclProperty->setAccessible(false);
return $acl;
}
/**
* Returns the key for the object identity.
*
* @param ObjectIdentityInterface $oid
*
* @return string
*/
private function getDataKeyByIdentity(ObjectIdentityInterface $oid)
{
return $this->prefix.md5($oid->getType()).sha1($oid->getType())
.'_'.md5($oid->getIdentifier()).sha1($oid->getIdentifier());
}
/**
* Returns the alias key for the object identity key.
*
* @param string $aclId
*
* @return string
*/
private function getAliasKeyForIdentity($aclId)
{
return $this->prefix.$aclId;
}
}

View File

@ -1,208 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Domain;
use Symfony\Component\Security\Acl\Model\AclInterface;
use Symfony\Component\Security\Acl\Model\AuditableEntryInterface;
use Symfony\Component\Security\Acl\Model\SecurityIdentityInterface;
/**
* Auditable ACE implementation.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class Entry implements AuditableEntryInterface
{
private $acl;
private $mask;
private $id;
private $securityIdentity;
private $strategy;
private $auditFailure;
private $auditSuccess;
private $granting;
/**
* Constructor.
*
* @param int $id
* @param AclInterface $acl
* @param SecurityIdentityInterface $sid
* @param string $strategy
* @param int $mask
* @param bool $granting
* @param bool $auditFailure
* @param bool $auditSuccess
*/
public function __construct($id, AclInterface $acl, SecurityIdentityInterface $sid, $strategy, $mask, $granting, $auditFailure, $auditSuccess)
{
$this->id = $id;
$this->acl = $acl;
$this->securityIdentity = $sid;
$this->strategy = $strategy;
$this->mask = $mask;
$this->granting = $granting;
$this->auditFailure = $auditFailure;
$this->auditSuccess = $auditSuccess;
}
/**
* {@inheritdoc}
*/
public function getAcl()
{
return $this->acl;
}
/**
* {@inheritdoc}
*/
public function getMask()
{
return $this->mask;
}
/**
* {@inheritdoc}
*/
public function getId()
{
return $this->id;
}
/**
* {@inheritdoc}
*/
public function getSecurityIdentity()
{
return $this->securityIdentity;
}
/**
* {@inheritdoc}
*/
public function getStrategy()
{
return $this->strategy;
}
/**
* {@inheritdoc}
*/
public function isAuditFailure()
{
return $this->auditFailure;
}
/**
* {@inheritdoc}
*/
public function isAuditSuccess()
{
return $this->auditSuccess;
}
/**
* {@inheritdoc}
*/
public function isGranting()
{
return $this->granting;
}
/**
* Turns on/off auditing on permissions denials.
*
* Do never call this method directly. Use the respective methods on the
* AclInterface instead.
*
* @param bool $boolean
*/
public function setAuditFailure($boolean)
{
$this->auditFailure = $boolean;
}
/**
* Turns on/off auditing on permission grants.
*
* Do never call this method directly. Use the respective methods on the
* AclInterface instead.
*
* @param bool $boolean
*/
public function setAuditSuccess($boolean)
{
$this->auditSuccess = $boolean;
}
/**
* Sets the permission mask.
*
* Do never call this method directly. Use the respective methods on the
* AclInterface instead.
*
* @param int $mask
*/
public function setMask($mask)
{
$this->mask = $mask;
}
/**
* Sets the mask comparison strategy.
*
* Do never call this method directly. Use the respective methods on the
* AclInterface instead.
*
* @param string $strategy
*/
public function setStrategy($strategy)
{
$this->strategy = $strategy;
}
/**
* Implementation of \Serializable.
*
* @return string
*/
public function serialize()
{
return serialize(array(
$this->mask,
$this->id,
$this->securityIdentity,
$this->strategy,
$this->auditFailure,
$this->auditSuccess,
$this->granting,
));
}
/**
* Implementation of \Serializable.
*
* @param string $serialized
*/
public function unserialize($serialized)
{
list($this->mask,
$this->id,
$this->securityIdentity,
$this->strategy,
$this->auditFailure,
$this->auditSuccess,
$this->granting
) = unserialize($serialized);
}
}

View File

@ -1,74 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Domain;
use Symfony\Component\Security\Acl\Model\AclInterface;
use Symfony\Component\Security\Acl\Model\FieldEntryInterface;
use Symfony\Component\Security\Acl\Model\SecurityIdentityInterface;
/**
* Field-aware ACE implementation which is auditable.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class FieldEntry extends Entry implements FieldEntryInterface
{
private $field;
/**
* Constructor.
*
* @param int $id
* @param AclInterface $acl
* @param string $field
* @param SecurityIdentityInterface $sid
* @param string $strategy
* @param int $mask
* @param bool $granting
* @param bool $auditFailure
* @param bool $auditSuccess
*/
public function __construct($id, AclInterface $acl, $field, SecurityIdentityInterface $sid, $strategy, $mask, $granting, $auditFailure, $auditSuccess)
{
parent::__construct($id, $acl, $sid, $strategy, $mask, $granting, $auditFailure, $auditSuccess);
$this->field = $field;
}
/**
* {@inheritdoc}
*/
public function getField()
{
return $this->field;
}
/**
* {@inheritdoc}
*/
public function serialize()
{
return serialize(array(
$this->field,
parent::serialize(),
));
}
/**
* {@inheritdoc}
*/
public function unserialize($serialized)
{
list($this->field, $parentStr) = unserialize($serialized);
parent::unserialize($parentStr);
}
}

View File

@ -1,114 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Domain;
use Symfony\Component\Security\Core\Util\ClassUtils;
use Symfony\Component\Security\Acl\Exception\InvalidDomainObjectException;
use Symfony\Component\Security\Acl\Model\DomainObjectInterface;
use Symfony\Component\Security\Acl\Model\ObjectIdentityInterface;
/**
* ObjectIdentity implementation.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
final class ObjectIdentity implements ObjectIdentityInterface
{
private $identifier;
private $type;
/**
* Constructor.
*
* @param string $identifier
* @param string $type
*
* @throws \InvalidArgumentException
*/
public function __construct($identifier, $type)
{
if ('' === $identifier) {
throw new \InvalidArgumentException('$identifier cannot be empty.');
}
if (empty($type)) {
throw new \InvalidArgumentException('$type cannot be empty.');
}
$this->identifier = $identifier;
$this->type = $type;
}
/**
* Constructs an ObjectIdentity for the given domain object.
*
* @param object $domainObject
*
* @throws InvalidDomainObjectException
*
* @return ObjectIdentity
*/
public static function fromDomainObject($domainObject)
{
if (!is_object($domainObject)) {
throw new InvalidDomainObjectException('$domainObject must be an object.');
}
try {
if ($domainObject instanceof DomainObjectInterface) {
return new self($domainObject->getObjectIdentifier(), ClassUtils::getRealClass($domainObject));
} elseif (method_exists($domainObject, 'getId')) {
return new self((string) $domainObject->getId(), ClassUtils::getRealClass($domainObject));
}
} catch (\InvalidArgumentException $e) {
throw new InvalidDomainObjectException($e->getMessage(), 0, $e);
}
throw new InvalidDomainObjectException('$domainObject must either implement the DomainObjectInterface, or have a method named "getId".');
}
/**
* {@inheritdoc}
*/
public function getIdentifier()
{
return $this->identifier;
}
/**
* {@inheritdoc}
*/
public function getType()
{
return $this->type;
}
/**
* {@inheritdoc}
*/
public function equals(ObjectIdentityInterface $identity)
{
// comparing the identifier with === might lead to problems, so we
// waive this restriction
return $this->identifier == $identity->getIdentifier()
&& $this->type === $identity->getType();
}
/**
* Returns a textual representation of this object identity.
*
* @return string
*/
public function __toString()
{
return sprintf('ObjectIdentity(%s, %s)', $this->identifier, $this->type);
}
}

View File

@ -1,35 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Domain;
use Symfony\Component\Security\Acl\Exception\InvalidDomainObjectException;
use Symfony\Component\Security\Acl\Model\ObjectIdentityRetrievalStrategyInterface;
/**
* Strategy to be used for retrieving object identities from domain objects.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class ObjectIdentityRetrievalStrategy implements ObjectIdentityRetrievalStrategyInterface
{
/**
* {@inheritdoc}
*/
public function getObjectIdentity($domainObject)
{
try {
return ObjectIdentity::fromDomainObject($domainObject);
} catch (InvalidDomainObjectException $e) {
return;
}
}
}

View File

@ -1,211 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Domain;
use Symfony\Component\Security\Acl\Exception\NoAceFoundException;
use Symfony\Component\Security\Acl\Model\AclInterface;
use Symfony\Component\Security\Acl\Model\AuditLoggerInterface;
use Symfony\Component\Security\Acl\Model\EntryInterface;
use Symfony\Component\Security\Acl\Model\PermissionGrantingStrategyInterface;
use Symfony\Component\Security\Acl\Model\SecurityIdentityInterface;
/**
* The permission granting strategy to apply to the access control list.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class PermissionGrantingStrategy implements PermissionGrantingStrategyInterface
{
const EQUAL = 'equal';
const ALL = 'all';
const ANY = 'any';
private $auditLogger;
/**
* Sets the audit logger.
*
* @param AuditLoggerInterface $auditLogger
*/
public function setAuditLogger(AuditLoggerInterface $auditLogger)
{
$this->auditLogger = $auditLogger;
}
/**
* {@inheritdoc}
*/
public function isGranted(AclInterface $acl, array $masks, array $sids, $administrativeMode = false)
{
try {
try {
$aces = $acl->getObjectAces();
if (!$aces) {
throw new NoAceFoundException();
}
return $this->hasSufficientPermissions($acl, $aces, $masks, $sids, $administrativeMode);
} catch (NoAceFoundException $e) {
$aces = $acl->getClassAces();
if (!$aces) {
throw $e;
}
return $this->hasSufficientPermissions($acl, $aces, $masks, $sids, $administrativeMode);
}
} catch (NoAceFoundException $e) {
if ($acl->isEntriesInheriting() && null !== $parentAcl = $acl->getParentAcl()) {
return $parentAcl->isGranted($masks, $sids, $administrativeMode);
}
throw $e;
}
}
/**
* {@inheritdoc}
*/
public function isFieldGranted(AclInterface $acl, $field, array $masks, array $sids, $administrativeMode = false)
{
try {
try {
$aces = $acl->getObjectFieldAces($field);
if (!$aces) {
throw new NoAceFoundException();
}
return $this->hasSufficientPermissions($acl, $aces, $masks, $sids, $administrativeMode);
} catch (NoAceFoundException $e) {
$aces = $acl->getClassFieldAces($field);
if (!$aces) {
throw $e;
}
return $this->hasSufficientPermissions($acl, $aces, $masks, $sids, $administrativeMode);
}
} catch (NoAceFoundException $e) {
if ($acl->isEntriesInheriting() && null !== $parentAcl = $acl->getParentAcl()) {
return $parentAcl->isFieldGranted($field, $masks, $sids, $administrativeMode);
}
throw $e;
}
}
/**
* Makes an authorization decision.
*
* The order of ACEs, and SIDs is significant; the order of permission masks
* not so much. It is important to note that the more specific security
* identities should be at the beginning of the SIDs array in order for this
* strategy to produce intuitive authorization decisions.
*
* First, we will iterate over permissions, then over security identities.
* For each combination of permission, and identity we will test the
* available ACEs until we find one which is applicable.
*
* The first applicable ACE will make the ultimate decision for the
* permission/identity combination. If it is granting, this method will return
* true, if it is denying, the method will continue to check the next
* permission/identity combination.
*
* This process is repeated until either a granting ACE is found, or no
* permission/identity combinations are left. Finally, we will either throw
* an NoAceFoundException, or deny access.
*
* @param AclInterface $acl
* @param EntryInterface[] $aces An array of ACE to check against
* @param array $masks An array of permission masks
* @param SecurityIdentityInterface[] $sids An array of SecurityIdentityInterface implementations
* @param bool $administrativeMode True turns off audit logging
*
* @return bool true, or false; either granting, or denying access respectively.
*
* @throws NoAceFoundException
*/
private function hasSufficientPermissions(AclInterface $acl, array $aces, array $masks, array $sids, $administrativeMode)
{
$firstRejectedAce = null;
foreach ($masks as $requiredMask) {
foreach ($sids as $sid) {
foreach ($aces as $ace) {
if ($sid->equals($ace->getSecurityIdentity()) && $this->isAceApplicable($requiredMask, $ace)) {
if ($ace->isGranting()) {
if (!$administrativeMode && null !== $this->auditLogger) {
$this->auditLogger->logIfNeeded(true, $ace);
}
return true;
}
if (null === $firstRejectedAce) {
$firstRejectedAce = $ace;
}
break 2;
}
}
}
}
if (null !== $firstRejectedAce) {
if (!$administrativeMode && null !== $this->auditLogger) {
$this->auditLogger->logIfNeeded(false, $firstRejectedAce);
}
return false;
}
throw new NoAceFoundException();
}
/**
* Determines whether the ACE is applicable to the given permission/security
* identity combination.
*
* Per default, we support three different comparison strategies.
*
* Strategy ALL:
* The ACE will be considered applicable when all the turned-on bits in the
* required mask are also turned-on in the ACE mask.
*
* Strategy ANY:
* The ACE will be considered applicable when any of the turned-on bits in
* the required mask is also turned-on the in the ACE mask.
*
* Strategy EQUAL:
* The ACE will be considered applicable when the bitmasks are equal.
*
* @param int $requiredMask
* @param EntryInterface $ace
*
* @return bool
*
* @throws \RuntimeException if the ACE strategy is not supported
*/
private function isAceApplicable($requiredMask, EntryInterface $ace)
{
$strategy = $ace->getStrategy();
if (self::ALL === $strategy) {
return $requiredMask === ($ace->getMask() & $requiredMask);
} elseif (self::ANY === $strategy) {
return 0 !== ($ace->getMask() & $requiredMask);
} elseif (self::EQUAL === $strategy) {
return $requiredMask === $ace->getMask();
}
throw new \RuntimeException(sprintf('The strategy "%s" is not supported.', $strategy));
}
}

View File

@ -1,73 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Domain;
use Symfony\Component\Security\Acl\Model\SecurityIdentityInterface;
use Symfony\Component\Security\Core\Role\Role;
/**
* A SecurityIdentity implementation for roles.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
final class RoleSecurityIdentity implements SecurityIdentityInterface
{
private $role;
/**
* Constructor.
*
* @param mixed $role a Role instance, or its string representation
*/
public function __construct($role)
{
if ($role instanceof Role) {
$role = $role->getRole();
}
$this->role = $role;
}
/**
* Returns the role name.
*
* @return string
*/
public function getRole()
{
return $this->role;
}
/**
* {@inheritdoc}
*/
public function equals(SecurityIdentityInterface $sid)
{
if (!$sid instanceof self) {
return false;
}
return $this->role === $sid->getRole();
}
/**
* Returns a textual representation of this security identity.
*
* This is solely used for debugging purposes, not to make an equality decision.
*
* @return string
*/
public function __toString()
{
return sprintf('RoleSecurityIdentity(%s)', $this->role);
}
}

View File

@ -1,78 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Domain;
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Acl\Model\SecurityIdentityRetrievalStrategyInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolver;
use Symfony\Component\Security\Core\Role\RoleHierarchyInterface;
use Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter;
/**
* Strategy for retrieving security identities.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class SecurityIdentityRetrievalStrategy implements SecurityIdentityRetrievalStrategyInterface
{
private $roleHierarchy;
private $authenticationTrustResolver;
/**
* Constructor.
*
* @param RoleHierarchyInterface $roleHierarchy
* @param AuthenticationTrustResolver $authenticationTrustResolver
*/
public function __construct(RoleHierarchyInterface $roleHierarchy, AuthenticationTrustResolver $authenticationTrustResolver)
{
$this->roleHierarchy = $roleHierarchy;
$this->authenticationTrustResolver = $authenticationTrustResolver;
}
/**
* {@inheritdoc}
*/
public function getSecurityIdentities(TokenInterface $token)
{
$sids = array();
// add user security identity
if (!$token instanceof AnonymousToken) {
try {
$sids[] = UserSecurityIdentity::fromToken($token);
} catch (\InvalidArgumentException $e) {
// ignore, user has no user security identity
}
}
// add all reachable roles
foreach ($this->roleHierarchy->getReachableRoles($token->getRoles()) as $role) {
$sids[] = new RoleSecurityIdentity($role);
}
// add built-in special roles
if ($this->authenticationTrustResolver->isFullFledged($token)) {
$sids[] = new RoleSecurityIdentity(AuthenticatedVoter::IS_AUTHENTICATED_FULLY);
$sids[] = new RoleSecurityIdentity(AuthenticatedVoter::IS_AUTHENTICATED_REMEMBERED);
$sids[] = new RoleSecurityIdentity(AuthenticatedVoter::IS_AUTHENTICATED_ANONYMOUSLY);
} elseif ($this->authenticationTrustResolver->isRememberMe($token)) {
$sids[] = new RoleSecurityIdentity(AuthenticatedVoter::IS_AUTHENTICATED_REMEMBERED);
$sids[] = new RoleSecurityIdentity(AuthenticatedVoter::IS_AUTHENTICATED_ANONYMOUSLY);
} elseif ($this->authenticationTrustResolver->isAnonymous($token)) {
$sids[] = new RoleSecurityIdentity(AuthenticatedVoter::IS_AUTHENTICATED_ANONYMOUSLY);
}
return $sids;
}
}

View File

@ -1,124 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Domain;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Util\ClassUtils;
use Symfony\Component\Security\Acl\Model\SecurityIdentityInterface;
/**
* A SecurityIdentity implementation used for actual users.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
final class UserSecurityIdentity implements SecurityIdentityInterface
{
private $username;
private $class;
/**
* Constructor.
*
* @param string $username the username representation
* @param string $class the user's fully qualified class name
*
* @throws \InvalidArgumentException
*/
public function __construct($username, $class)
{
if ('' === $username || null === $username) {
throw new \InvalidArgumentException('$username must not be empty.');
}
if (empty($class)) {
throw new \InvalidArgumentException('$class must not be empty.');
}
$this->username = (string) $username;
$this->class = $class;
}
/**
* Creates a user security identity from a UserInterface.
*
* @param UserInterface $user
*
* @return UserSecurityIdentity
*/
public static function fromAccount(UserInterface $user)
{
return new self($user->getUsername(), ClassUtils::getRealClass($user));
}
/**
* Creates a user security identity from a TokenInterface.
*
* @param TokenInterface $token
*
* @return UserSecurityIdentity
*/
public static function fromToken(TokenInterface $token)
{
$user = $token->getUser();
if ($user instanceof UserInterface) {
return self::fromAccount($user);
}
return new self((string) $user, is_object($user) ? ClassUtils::getRealClass($user) : ClassUtils::getRealClass($token));
}
/**
* Returns the username.
*
* @return string
*/
public function getUsername()
{
return $this->username;
}
/**
* Returns the user's class name.
*
* @return string
*/
public function getClass()
{
return $this->class;
}
/**
* {@inheritdoc}
*/
public function equals(SecurityIdentityInterface $sid)
{
if (!$sid instanceof self) {
return false;
}
return $this->username === $sid->getUsername()
&& $this->class === $sid->getClass();
}
/**
* A textual representation of this security identity.
*
* This is not used for equality comparison, but only for debugging.
*
* @return string
*/
public function __toString()
{
return sprintf('UserSecurityIdentity(%s, %s)', $this->username, $this->class);
}
}

View File

@ -1,22 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Exception;
/**
* This exception is thrown when someone tries to create an ACL for an object
* identity that already has one.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class AclAlreadyExistsException extends Exception
{
}

View File

@ -1,22 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Exception;
/**
* This exception is thrown when we cannot locate an ACL for a passed
* ObjectIdentity implementation.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class AclNotFoundException extends Exception
{
}

View File

@ -1,22 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Exception;
/**
* This exception is thrown whenever you change shared properties of more than
* one ACL of the same class type concurrently.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class ConcurrentModificationException extends Exception
{
}

View File

@ -1,21 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Exception;
/**
* Base ACL exception.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class Exception extends \RuntimeException
{
}

View File

@ -1,22 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Exception;
/**
* This exception is thrown when ObjectIdentity fails to construct an object
* identity from the passed domain object.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class InvalidDomainObjectException extends Exception
{
}

View File

@ -1,26 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Exception;
/**
* This exception is thrown when we cannot locate an ACE that matches the
* combination of permission masks and security identities.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class NoAceFoundException extends Exception
{
public function __construct()
{
parent::__construct('No applicable ACE was found.');
}
}

View File

@ -1,46 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Exception;
/**
* This exception is thrown when you have requested ACLs for multiple object
* identities, but the AclProvider implementation failed to find ACLs for all
* identities.
*
* This exception contains the partial result.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class NotAllAclsFoundException extends AclNotFoundException
{
private $partialResult;
/**
* Sets the partial result.
*
* @param \SplObjectStorage $result
*/
public function setPartialResult(\SplObjectStorage $result)
{
$this->partialResult = $result;
}
/**
* Returns the partial result.
*
* @return \SplObjectStorage
*/
public function getPartialResult()
{
return $this->partialResult;
}
}

View File

@ -1,22 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Exception;
/**
* This exception is thrown when ACEs for an SID are requested which has not
* been loaded from the database.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class SidNotLoadedException extends Exception
{
}

View File

@ -1,19 +0,0 @@
Copyright (c) 2004-2015 Fabien Potencier
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.

View File

@ -1,66 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Model;
/**
* AclCache Interface.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
interface AclCacheInterface
{
/**
* Removes an ACL from the cache.
*
* @param string $primaryKey a serialized primary key
*/
public function evictFromCacheById($primaryKey);
/**
* Removes an ACL from the cache.
*
* The ACL which is returned, must reference the passed object identity.
*
* @param ObjectIdentityInterface $oid
*/
public function evictFromCacheByIdentity(ObjectIdentityInterface $oid);
/**
* Retrieves an ACL for the given object identity primary key from the cache.
*
* @param int $primaryKey
*
* @return AclInterface
*/
public function getFromCacheById($primaryKey);
/**
* Retrieves an ACL for the given object identity from the cache.
*
* @param ObjectIdentityInterface $oid
*
* @return AclInterface
*/
public function getFromCacheByIdentity(ObjectIdentityInterface $oid);
/**
* Stores a new ACL in the cache.
*
* @param AclInterface $acl
*/
public function putInCache(AclInterface $acl);
/**
* Removes all ACLs from the cache.
*/
public function clearCache();
}

View File

@ -1,114 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Model;
use Symfony\Component\Security\Acl\Exception\NoAceFoundException;
/**
* This interface represents an access control list (ACL) for a domain object.
* Each domain object can have exactly one associated ACL.
*
* An ACL contains all access control entries (ACE) for a given domain object.
* In order to avoid needing references to the domain object itself, implementations
* use ObjectIdentity implementations as an additional level of indirection.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
interface AclInterface extends \Serializable
{
/**
* Returns all class-based ACEs associated with this ACL.
*
* @return array
*/
public function getClassAces();
/**
* Returns all class-field-based ACEs associated with this ACL.
*
* @param string $field
*
* @return array
*/
public function getClassFieldAces($field);
/**
* Returns all object-based ACEs associated with this ACL.
*
* @return array
*/
public function getObjectAces();
/**
* Returns all object-field-based ACEs associated with this ACL.
*
* @param string $field
*
* @return array
*/
public function getObjectFieldAces($field);
/**
* Returns the object identity associated with this ACL.
*
* @return ObjectIdentityInterface
*/
public function getObjectIdentity();
/**
* Returns the parent ACL, or null if there is none.
*
* @return AclInterface|null
*/
public function getParentAcl();
/**
* Whether this ACL is inheriting ACEs from a parent ACL.
*
* @return bool
*/
public function isEntriesInheriting();
/**
* Determines whether field access is granted.
*
* @param string $field
* @param array $masks
* @param array $securityIdentities
* @param bool $administrativeMode
*
* @return bool
*/
public function isFieldGranted($field, array $masks, array $securityIdentities, $administrativeMode = false);
/**
* Determines whether access is granted.
*
* @param array $masks
* @param array $securityIdentities
* @param bool $administrativeMode
*
* @throws NoAceFoundException when no ACE was applicable for this request
*
* @return bool
*/
public function isGranted(array $masks, array $securityIdentities, $administrativeMode = false);
/**
* Whether the ACL has loaded ACEs for all of the passed security identities.
*
* @param mixed $securityIdentities an implementation of SecurityIdentityInterface, or an array thereof
*
* @return bool
*/
public function isSidLoaded($securityIdentities);
}

View File

@ -1,56 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Model;
use Symfony\Component\Security\Acl\Exception\AclNotFoundException;
/**
* Provides a common interface for retrieving ACLs.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
interface AclProviderInterface
{
/**
* Retrieves all child object identities from the database.
*
* @param ObjectIdentityInterface $parentOid
* @param bool $directChildrenOnly
*
* @return array returns an array of child 'ObjectIdentity's
*/
public function findChildren(ObjectIdentityInterface $parentOid, $directChildrenOnly = false);
/**
* Returns the ACL that belongs to the given object identity.
*
* @param ObjectIdentityInterface $oid
* @param SecurityIdentityInterface[] $sids
*
* @return AclInterface
*
* @throws AclNotFoundException when there is no ACL
*/
public function findAcl(ObjectIdentityInterface $oid, array $sids = array());
/**
* Returns the ACLs that belong to the given object identities.
*
* @param ObjectIdentityInterface[] $oids an array of ObjectIdentityInterface implementations
* @param SecurityIdentityInterface[] $sids an array of SecurityIdentityInterface implementations
*
* @return \SplObjectStorage mapping the passed object identities to ACLs
*
* @throws AclNotFoundException when we cannot find an ACL for all identities
*/
public function findAcls(array $oids, array $sids = array());
}

View File

@ -1,29 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Model;
/**
* Interface for audit loggers.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
interface AuditLoggerInterface
{
/**
* This method is called whenever access is granted, or denied, and
* administrative mode is turned off.
*
* @param bool $granted
* @param EntryInterface $ace
*/
public function logIfNeeded($granted, EntryInterface $ace);
}

View File

@ -1,58 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Model;
/**
* This interface adds auditing capabilities to the ACL.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
interface AuditableAclInterface extends MutableAclInterface
{
/**
* Updates auditing for class-based ACE.
*
* @param int $index
* @param bool $auditSuccess
* @param bool $auditFailure
*/
public function updateClassAuditing($index, $auditSuccess, $auditFailure);
/**
* Updates auditing for class-field-based ACE.
*
* @param int $index
* @param string $field
* @param bool $auditSuccess
* @param bool $auditFailure
*/
public function updateClassFieldAuditing($index, $field, $auditSuccess, $auditFailure);
/**
* Updates auditing for object-based ACE.
*
* @param int $index
* @param bool $auditSuccess
* @param bool $auditFailure
*/
public function updateObjectAuditing($index, $auditSuccess, $auditFailure);
/**
* Updates auditing for object-field-based ACE.
*
* @param int $index
* @param string $field
* @param bool $auditSuccess
* @param bool $auditFailure
*/
public function updateObjectFieldAuditing($index, $field, $auditSuccess, $auditFailure);
}

View File

@ -1,34 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Model;
/**
* ACEs can implement this interface if they support auditing capabilities.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
interface AuditableEntryInterface extends EntryInterface
{
/**
* Whether auditing for successful grants is turned on.
*
* @return bool
*/
public function isAuditFailure();
/**
* Whether auditing for successful denies is turned on.
*
* @return bool
*/
public function isAuditSuccess();
}

View File

@ -1,29 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Model;
/**
* This method can be implemented by domain objects which you want to store
* ACLs for if they do not have a getId() method, or getId() does not return
* a unique identifier.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
interface DomainObjectInterface
{
/**
* Returns a unique identifier for this domain object.
*
* @return string
*/
public function getObjectIdentifier();
}

View File

@ -1,65 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Model;
/**
* This class represents an individual entry in the ACL list.
*
* Instances MUST be immutable, as they are returned by the ACL and should not
* allow client modification.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
interface EntryInterface extends \Serializable
{
/**
* The ACL this ACE is associated with.
*
* @return AclInterface
*/
public function getAcl();
/**
* The primary key of this ACE.
*
* @return int
*/
public function getId();
/**
* The permission mask of this ACE.
*
* @return int
*/
public function getMask();
/**
* The security identity associated with this ACE.
*
* @return SecurityIdentityInterface
*/
public function getSecurityIdentity();
/**
* The strategy for comparing masks.
*
* @return string
*/
public function getStrategy();
/**
* Returns whether this ACE is granting, or denying.
*
* @return bool
*/
public function isGranting();
}

View File

@ -1,27 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Model;
/**
* Interface for entries which are restricted to specific fields.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
interface FieldEntryInterface extends EntryInterface
{
/**
* Returns the field used for this entry.
*
* @return string
*/
public function getField();
}

View File

@ -1,158 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Model;
/**
* This interface adds mutators for the AclInterface.
*
* All changes to Access Control Entries must go through this interface. Access
* Control Entries must never be modified directly.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
interface MutableAclInterface extends AclInterface
{
/**
* Deletes a class-based ACE.
*
* @param int $index
*/
public function deleteClassAce($index);
/**
* Deletes a class-field-based ACE.
*
* @param int $index
* @param string $field
*/
public function deleteClassFieldAce($index, $field);
/**
* Deletes an object-based ACE.
*
* @param int $index
*/
public function deleteObjectAce($index);
/**
* Deletes an object-field-based ACE.
*
* @param int $index
* @param string $field
*/
public function deleteObjectFieldAce($index, $field);
/**
* Returns the primary key of this ACL.
*
* @return int
*/
public function getId();
/**
* Inserts a class-based ACE.
*
* @param SecurityIdentityInterface $sid
* @param int $mask
* @param int $index
* @param bool $granting
* @param string $strategy
*/
public function insertClassAce(SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null);
/**
* Inserts a class-field-based ACE.
*
* @param string $field
* @param SecurityIdentityInterface $sid
* @param int $mask
* @param int $index
* @param bool $granting
* @param string $strategy
*/
public function insertClassFieldAce($field, SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null);
/**
* Inserts an object-based ACE.
*
* @param SecurityIdentityInterface $sid
* @param int $mask
* @param int $index
* @param bool $granting
* @param string $strategy
*/
public function insertObjectAce(SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null);
/**
* Inserts an object-field-based ACE.
*
* @param string $field
* @param SecurityIdentityInterface $sid
* @param int $mask
* @param int $index
* @param bool $granting
* @param string $strategy
*/
public function insertObjectFieldAce($field, SecurityIdentityInterface $sid, $mask, $index = 0, $granting = true, $strategy = null);
/**
* Sets whether entries are inherited.
*
* @param bool $boolean
*/
public function setEntriesInheriting($boolean);
/**
* Sets the parent ACL.
*
* @param AclInterface|null $acl
*/
public function setParentAcl(AclInterface $acl = null);
/**
* Updates a class-based ACE.
*
* @param int $index
* @param int $mask
* @param string $strategy if null the strategy should not be changed
*/
public function updateClassAce($index, $mask, $strategy = null);
/**
* Updates a class-field-based ACE.
*
* @param int $index
* @param string $field
* @param int $mask
* @param string $strategy if null the strategy should not be changed
*/
public function updateClassFieldAce($index, $field, $mask, $strategy = null);
/**
* Updates an object-based ACE.
*
* @param int $index
* @param int $mask
* @param string $strategy if null the strategy should not be changed
*/
public function updateObjectAce($index, $mask, $strategy = null);
/**
* Updates an object-field-based ACE.
*
* @param int $index
* @param string $field
* @param int $mask
* @param string $strategy if null the strategy should not be changed
*/
public function updateObjectFieldAce($index, $field, $mask, $strategy = null);
}

View File

@ -1,54 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Model;
use Symfony\Component\Security\Acl\Exception\AclAlreadyExistsException;
/**
* Provides support for creating and storing ACL instances.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
interface MutableAclProviderInterface extends AclProviderInterface
{
/**
* Creates a new ACL for the given object identity.
*
* @param ObjectIdentityInterface $oid
*
* @throws AclAlreadyExistsException when there already is an ACL for the given
* object identity
*
* @return MutableAclInterface
*/
public function createAcl(ObjectIdentityInterface $oid);
/**
* Deletes the ACL for a given object identity.
*
* This will automatically trigger a delete for any child ACLs. If you don't
* want child ACLs to be deleted, you will have to set their parent ACL to null.
*
* @param ObjectIdentityInterface $oid
*/
public function deleteAcl(ObjectIdentityInterface $oid);
/**
* Persists any changes which were made to the ACL, or any associated
* access control entries.
*
* Changes to parent ACLs are not persisted.
*
* @param MutableAclInterface $acl
*/
public function updateAcl(MutableAclInterface $acl);
}

View File

@ -1,50 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Model;
/**
* Represents the identity of an individual domain object instance.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
interface ObjectIdentityInterface
{
/**
* We specifically require this method so we can check for object equality
* explicitly, and do not have to rely on referencial equality instead.
*
* Though in most cases, both checks should result in the same outcome.
*
* Referential Equality: $object1 === $object2
* Example for Object Equality: $object1->getId() === $object2->getId()
*
* @param ObjectIdentityInterface $identity
*
* @return bool
*/
public function equals(ObjectIdentityInterface $identity);
/**
* Obtains a unique identifier for this object. The identifier must not be
* re-used for other objects with the same type.
*
* @return string cannot return null
*/
public function getIdentifier();
/**
* Returns a type for the domain object. Typically, this is the PHP class name.
*
* @return string cannot return null
*/
public function getType();
}

View File

@ -1,29 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Model;
/**
* Retrieves the object identity for a given domain object.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
interface ObjectIdentityRetrievalStrategyInterface
{
/**
* Retrieves the object identity from a domain object.
*
* @param object $domainObject
*
* @return ObjectIdentityInterface
*/
public function getObjectIdentity($domainObject);
}

View File

@ -1,45 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Model;
/**
* Interface used by permission granting implementations.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
interface PermissionGrantingStrategyInterface
{
/**
* Determines whether access to a domain object is to be granted.
*
* @param AclInterface $acl
* @param array $masks
* @param array $sids
* @param bool $administrativeMode
*
* @return bool
*/
public function isGranted(AclInterface $acl, array $masks, array $sids, $administrativeMode = false);
/**
* Determines whether access to a domain object's field is to be granted.
*
* @param AclInterface $acl
* @param string $field
* @param array $masks
* @param array $sids
* @param bool $administrativeMode
*
* @return bool
*/
public function isFieldGranted(AclInterface $acl, $field, array $masks, array $sids, $administrativeMode = false);
}

View File

@ -1,30 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Model;
/**
* This interface provides an additional level of indirection, so that
* we can work with abstracted versions of security objects and do
* not have to save the entire objects.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
interface SecurityIdentityInterface
{
/**
* This method is used to compare two security identities in order to
* not rely on referential equality.
*
* @param SecurityIdentityInterface $identity
*/
public function equals(SecurityIdentityInterface $identity);
}

View File

@ -1,35 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Model;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
/**
* Interface for retrieving security identities from tokens.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
interface SecurityIdentityRetrievalStrategyInterface
{
/**
* Retrieves the available security identities for the given token.
*
* The order in which the security identities are returned is significant.
* Typically, security identities should be ordered from most specific to
* least specific.
*
* @param TokenInterface $token
*
* @return SecurityIdentityInterface[] An array of SecurityIdentityInterface implementations
*/
public function getSecurityIdentities(TokenInterface $token);
}

View File

@ -1,85 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Permission;
/**
* This abstract class implements nearly all the MaskBuilderInterface methods
*/
abstract class AbstractMaskBuilder implements MaskBuilderInterface
{
/**
* @var int
*/
protected $mask;
/**
* Constructor.
*
* @param int $mask optional; defaults to 0
*/
public function __construct($mask = 0)
{
$this->set($mask);
}
/**
* {@inheritdoc}
*/
public function set($mask)
{
if (!is_int($mask)) {
throw new \InvalidArgumentException('$mask must be an integer.');
}
$this->mask = $mask;
return $this;
}
/**
* {@inheritdoc}
*/
public function get()
{
return $this->mask;
}
/**
* {@inheritdoc}
*/
public function add($mask)
{
$this->mask |= $this->resolveMask($mask);
return $this;
}
/**
* {@inheritdoc}
*/
public function remove($mask)
{
$this->mask &= ~$this->resolveMask($mask);
return $this;
}
/**
* {@inheritdoc}
*/
public function reset()
{
$this->mask = 0;
return $this;
}
}

View File

@ -1,116 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Permission;
/**
* This is basic permission map complements the masks which have been defined
* on the standard implementation of the MaskBuilder.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class BasicPermissionMap implements PermissionMapInterface, MaskBuilderRetrievalInterface
{
const PERMISSION_VIEW = 'VIEW';
const PERMISSION_EDIT = 'EDIT';
const PERMISSION_CREATE = 'CREATE';
const PERMISSION_DELETE = 'DELETE';
const PERMISSION_UNDELETE = 'UNDELETE';
const PERMISSION_OPERATOR = 'OPERATOR';
const PERMISSION_MASTER = 'MASTER';
const PERMISSION_OWNER = 'OWNER';
protected $map;
public function __construct()
{
$this->map = array(
self::PERMISSION_VIEW => array(
MaskBuilder::MASK_VIEW,
MaskBuilder::MASK_EDIT,
MaskBuilder::MASK_OPERATOR,
MaskBuilder::MASK_MASTER,
MaskBuilder::MASK_OWNER,
),
self::PERMISSION_EDIT => array(
MaskBuilder::MASK_EDIT,
MaskBuilder::MASK_OPERATOR,
MaskBuilder::MASK_MASTER,
MaskBuilder::MASK_OWNER,
),
self::PERMISSION_CREATE => array(
MaskBuilder::MASK_CREATE,
MaskBuilder::MASK_OPERATOR,
MaskBuilder::MASK_MASTER,
MaskBuilder::MASK_OWNER,
),
self::PERMISSION_DELETE => array(
MaskBuilder::MASK_DELETE,
MaskBuilder::MASK_OPERATOR,
MaskBuilder::MASK_MASTER,
MaskBuilder::MASK_OWNER,
),
self::PERMISSION_UNDELETE => array(
MaskBuilder::MASK_UNDELETE,
MaskBuilder::MASK_OPERATOR,
MaskBuilder::MASK_MASTER,
MaskBuilder::MASK_OWNER,
),
self::PERMISSION_OPERATOR => array(
MaskBuilder::MASK_OPERATOR,
MaskBuilder::MASK_MASTER,
MaskBuilder::MASK_OWNER,
),
self::PERMISSION_MASTER => array(
MaskBuilder::MASK_MASTER,
MaskBuilder::MASK_OWNER,
),
self::PERMISSION_OWNER => array(
MaskBuilder::MASK_OWNER,
),
);
}
/**
* {@inheritdoc}
*/
public function getMasks($permission, $object)
{
if (!isset($this->map[$permission])) {
return;
}
return $this->map[$permission];
}
/**
* {@inheritdoc}
*/
public function contains($permission)
{
return isset($this->map[$permission]);
}
/**
* {@inheritdoc}
*/
public function getMaskBuilder()
{
return new MaskBuilder();
}
}

View File

@ -1,151 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Permission;
/**
* This class allows you to build cumulative permissions easily, or convert
* masks to a human-readable format.
*
* <code>
* $builder = new MaskBuilder();
* $builder
* ->add('view')
* ->add('create')
* ->add('edit')
* ;
* var_dump($builder->get()); // int(7)
* var_dump($builder->getPattern()); // string(32) ".............................ECV"
* </code>
*
* We have defined some commonly used base permissions which you can use:
* - VIEW: the SID is allowed to view the domain object / field
* - CREATE: the SID is allowed to create new instances of the domain object / fields
* - EDIT: the SID is allowed to edit existing instances of the domain object / field
* - DELETE: the SID is allowed to delete domain objects
* - UNDELETE: the SID is allowed to recover domain objects from trash
* - OPERATOR: the SID is allowed to perform any action on the domain object
* except for granting others permissions
* - MASTER: the SID is allowed to perform any action on the domain object,
* and is allowed to grant other SIDs any permission except for
* MASTER and OWNER permissions
* - OWNER: the SID is owning the domain object in question and can perform any
* action on the domain object as well as grant any permission
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class MaskBuilder extends AbstractMaskBuilder
{
const MASK_VIEW = 1; // 1 << 0
const MASK_CREATE = 2; // 1 << 1
const MASK_EDIT = 4; // 1 << 2
const MASK_DELETE = 8; // 1 << 3
const MASK_UNDELETE = 16; // 1 << 4
const MASK_OPERATOR = 32; // 1 << 5
const MASK_MASTER = 64; // 1 << 6
const MASK_OWNER = 128; // 1 << 7
const MASK_IDDQD = 1073741823; // 1 << 0 | 1 << 1 | ... | 1 << 30
const CODE_VIEW = 'V';
const CODE_CREATE = 'C';
const CODE_EDIT = 'E';
const CODE_DELETE = 'D';
const CODE_UNDELETE = 'U';
const CODE_OPERATOR = 'O';
const CODE_MASTER = 'M';
const CODE_OWNER = 'N';
const ALL_OFF = '................................';
const OFF = '.';
const ON = '*';
/**
* Returns a human-readable representation of the permission.
*
* @return string
*/
public function getPattern()
{
$pattern = self::ALL_OFF;
$length = strlen($pattern);
$bitmask = str_pad(decbin($this->mask), $length, '0', STR_PAD_LEFT);
for ($i = $length - 1; $i >= 0; --$i) {
if ('1' === $bitmask[$i]) {
try {
$pattern[$i] = self::getCode(1 << ($length - $i - 1));
} catch (\Exception $e) {
$pattern[$i] = self::ON;
}
}
}
return $pattern;
}
/**
* Returns the code for the passed mask.
*
* @param int $mask
*
* @throws \InvalidArgumentException
* @throws \RuntimeException
*
* @return string
*/
public static function getCode($mask)
{
if (!is_int($mask)) {
throw new \InvalidArgumentException('$mask must be an integer.');
}
$reflection = new \ReflectionClass(get_called_class());
foreach ($reflection->getConstants() as $name => $cMask) {
if (0 !== strpos($name, 'MASK_') || $mask !== $cMask) {
continue;
}
if (!defined($cName = 'static::CODE_'.substr($name, 5))) {
throw new \RuntimeException('There was no code defined for this mask.');
}
return constant($cName);
}
throw new \InvalidArgumentException(sprintf('The mask "%d" is not supported.', $mask));
}
/**
* Returns the mask for the passed code
*
* @param mixed $code
*
* @return int
*
* @throws \InvalidArgumentException
*/
public function resolveMask($code)
{
if (is_string($code)) {
if (!defined($name = sprintf('static::MASK_%s', strtoupper($code)))) {
throw new \InvalidArgumentException(sprintf('The code "%s" is not supported', $code));
}
return constant($name);
}
if (!is_int($code)) {
throw new \InvalidArgumentException('$code must be an integer.');
}
return $code;
}
}

View File

@ -1,75 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Permission;
/**
* This is the interface that must be implemented by mask builders.
*/
interface MaskBuilderInterface
{
/**
* Set the mask of this permission
*
* @param int $mask
*
* @return MaskBuilderInterface
* @throws \InvalidArgumentException if $mask is not an integer
*/
public function set($mask);
/**
* Returns the mask of this permission.
*
* @return int
*/
public function get();
/**
* Adds a mask to the permission.
*
* @param mixed $mask
*
* @return MaskBuilderInterface
*
* @throws \InvalidArgumentException
*/
public function add($mask);
/**
* Removes a mask from the permission.
*
* @param mixed $mask
*
* @return MaskBuilderInterface
*
* @throws \InvalidArgumentException
*/
public function remove($mask);
/**
* Resets the PermissionBuilder.
*
* @return MaskBuilderInterface
*/
public function reset();
/**
* Returns the mask for the passed code
*
* @param mixed $code
*
* @return int
*
* @throws \InvalidArgumentException
*/
public function resolveMask($code);
}

View File

@ -1,25 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Permission;
/**
* Retrieves the MaskBuilder
*/
interface MaskBuilderRetrievalInterface
{
/**
* Returns a new instance of the MaskBuilder used in the permissionMap
*
* @return MaskBuilderInterface
*/
public function getMaskBuilder();
}

View File

@ -1,42 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Permission;
/**
* This is the interface that must be implemented by permission maps.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
interface PermissionMapInterface
{
/**
* Returns an array of bitmasks.
*
* The security identity must have been granted access to at least one of
* these bitmasks.
*
* @param string $permission
* @param object $object
*
* @return array may return null if permission/object combination is not supported
*/
public function getMasks($permission, $object);
/**
* Whether this map contains the given permission.
*
* @param string $permission
*
* @return bool
*/
public function contains($permission);
}

View File

@ -1,23 +0,0 @@
Security Component - ACL (Access Control List)
==============================================
Security provides an infrastructure for sophisticated authorization systems,
which makes it possible to easily separate the actual authorization logic from
so called user providers that hold the users credentials. It is inspired by
the Java Spring framework.
Resources
---------
Documentation:
https://symfony.com/doc/2.8/book/security.html
Tests
-----
You can run the unit tests with the following command:
$ cd path/to/Symfony/Component/Security/Acl/
$ composer.phar install --dev
$ phpunit

View File

@ -1,51 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require_once __DIR__.'/../../../../ClassLoader/ClassLoader.php';
use Symfony\Component\ClassLoader\ClassLoader;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Security\Acl\Dbal\Schema;
$loader = new ClassLoader();
$loader->addPrefixes(array(
'Symfony' => __DIR__.'/../../../../../..',
'Doctrine\\Common' => __DIR__.'/../../../../../../../vendor/doctrine-common/lib',
'Doctrine\\DBAL\\Migrations' => __DIR__.'/../../../../../../../vendor/doctrine-migrations/lib',
'Doctrine\\DBAL' => __DIR__.'/../../../../../../../vendor/doctrine/dbal/lib',
'Doctrine' => __DIR__.'/../../../../../../../vendor/doctrine/lib',
));
$loader->register();
$schema = new Schema(array(
'class_table_name' => 'acl_classes',
'entry_table_name' => 'acl_entries',
'oid_table_name' => 'acl_object_identities',
'oid_ancestors_table_name' => 'acl_object_identity_ancestors',
'sid_table_name' => 'acl_security_identities',
));
$reflection = new ReflectionClass('Doctrine\\DBAL\\Platforms\\AbstractPlatform');
$finder = new Finder();
$finder->name('*Platform.php')->in(dirname($reflection->getFileName()));
foreach ($finder as $file) {
require_once $file->getPathName();
$className = 'Doctrine\\DBAL\\Platforms\\'.$file->getBasename('.php');
$reflection = new ReflectionClass($className);
if ($reflection->isAbstract()) {
continue;
}
$platform = $reflection->newInstance();
$targetFile = sprintf(__DIR__.'/../schema/%s.sql', $platform->getName());
file_put_contents($targetFile, implode("\n\n", $schema->toSql($platform)));
}

View File

@ -1,43 +0,0 @@
CREATE TABLE acl_classes (id INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL, class_type VARCHAR(200) NOT NULL, PRIMARY KEY(id))
CREATE UNIQUE INDEX UNIQ_69DD750638A36066 ON acl_classes (class_type)
CREATE TABLE acl_security_identities (id INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL, identifier VARCHAR(200) NOT NULL, username SMALLINT NOT NULL, PRIMARY KEY(id))
CREATE UNIQUE INDEX UNIQ_8835EE78772E836AF85E0677 ON acl_security_identities (identifier, username)
CREATE TABLE acl_object_identities (id INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL, parent_object_identity_id INTEGER DEFAULT NULL, class_id INTEGER NOT NULL, object_identifier VARCHAR(100) NOT NULL, entries_inheriting SMALLINT NOT NULL, PRIMARY KEY(id))
CREATE UNIQUE INDEX UNIQ_9407E5494B12AD6EA000B10 ON acl_object_identities (object_identifier, class_id)
CREATE INDEX IDX_9407E54977FA751A ON acl_object_identities (parent_object_identity_id)
CREATE TABLE acl_object_identity_ancestors (object_identity_id INTEGER NOT NULL, ancestor_id INTEGER NOT NULL, PRIMARY KEY(object_identity_id, ancestor_id))
CREATE INDEX IDX_825DE2993D9AB4A6 ON acl_object_identity_ancestors (object_identity_id)
CREATE INDEX IDX_825DE299C671CEA1 ON acl_object_identity_ancestors (ancestor_id)
CREATE TABLE acl_entries (id INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL, class_id INTEGER NOT NULL, object_identity_id INTEGER DEFAULT NULL, security_identity_id INTEGER NOT NULL, field_name VARCHAR(50) DEFAULT NULL, ace_order SMALLINT NOT NULL, mask INTEGER NOT NULL, granting SMALLINT NOT NULL, granting_strategy VARCHAR(30) NOT NULL, audit_success SMALLINT NOT NULL, audit_failure SMALLINT NOT NULL, PRIMARY KEY(id))
CREATE UNIQUE INDEX UNIQ_46C8B806EA000B103D9AB4A64DEF17BCE4289BF4 ON acl_entries (class_id, object_identity_id, field_name, ace_order)
CREATE INDEX IDX_46C8B806EA000B103D9AB4A6DF9183C9 ON acl_entries (class_id, object_identity_id, security_identity_id)
CREATE INDEX IDX_46C8B806EA000B10 ON acl_entries (class_id)
CREATE INDEX IDX_46C8B8063D9AB4A6 ON acl_entries (object_identity_id)
CREATE INDEX IDX_46C8B806DF9183C9 ON acl_entries (security_identity_id)
ALTER TABLE acl_object_identities ADD CONSTRAINT FK_9407E54977FA751A FOREIGN KEY (parent_object_identity_id) REFERENCES acl_object_identities (id)
ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE2993D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE
ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE299C671CEA1 FOREIGN KEY (ancestor_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE
ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806EA000B10 FOREIGN KEY (class_id) REFERENCES acl_classes (id) ON UPDATE CASCADE ON DELETE CASCADE
ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B8063D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE
ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806DF9183C9 FOREIGN KEY (security_identity_id) REFERENCES acl_security_identities (id) ON UPDATE CASCADE ON DELETE CASCADE

View File

@ -1,21 +0,0 @@
CREATE TABLE acl_classes (id INT AUTO_INCREMENT NOT NULL, class_type VARCHAR(200) NOT NULL, UNIQUE INDEX UNIQ_69DD750638A36066 (class_type), PRIMARY KEY(id)) COLLATE utf8_unicode_ci ENGINE = InnoDB
CREATE TABLE acl_security_identities (id INT AUTO_INCREMENT NOT NULL, identifier VARCHAR(200) NOT NULL, username BOOLEAN NOT NULL, UNIQUE INDEX UNIQ_8835EE78772E836AF85E0677 (identifier, username), PRIMARY KEY(id)) COLLATE utf8_unicode_ci ENGINE = InnoDB
CREATE TABLE acl_object_identities (id INT AUTO_INCREMENT NOT NULL, parent_object_identity_id INT DEFAULT NULL, class_id INT NOT NULL, object_identifier VARCHAR(100) NOT NULL, entries_inheriting BOOLEAN NOT NULL, UNIQUE INDEX UNIQ_9407E5494B12AD6EA000B10 (object_identifier, class_id), INDEX IDX_9407E54977FA751A (parent_object_identity_id), PRIMARY KEY(id)) COLLATE utf8_unicode_ci ENGINE = InnoDB
CREATE TABLE acl_object_identity_ancestors (object_identity_id INT NOT NULL, ancestor_id INT NOT NULL, INDEX IDX_825DE2993D9AB4A6 (object_identity_id), INDEX IDX_825DE299C671CEA1 (ancestor_id), PRIMARY KEY(object_identity_id, ancestor_id)) COLLATE utf8_unicode_ci ENGINE = InnoDB
CREATE TABLE acl_entries (id INT AUTO_INCREMENT NOT NULL, class_id INT NOT NULL, object_identity_id INT DEFAULT NULL, security_identity_id INT NOT NULL, field_name VARCHAR(50) DEFAULT NULL, ace_order INT NOT NULL, mask INT NOT NULL, granting BOOLEAN NOT NULL, granting_strategy VARCHAR(30) NOT NULL, audit_success BOOLEAN NOT NULL, audit_failure BOOLEAN NOT NULL, UNIQUE INDEX UNIQ_46C8B806EA000B103D9AB4A64DEF17BCE4289BF4 (class_id, object_identity_id, field_name, ace_order), INDEX IDX_46C8B806EA000B103D9AB4A6DF9183C9 (class_id, object_identity_id, security_identity_id), INDEX IDX_46C8B806EA000B10 (class_id), INDEX IDX_46C8B8063D9AB4A6 (object_identity_id), INDEX IDX_46C8B806DF9183C9 (security_identity_id), PRIMARY KEY(id)) COLLATE utf8_unicode_ci ENGINE = InnoDB
ALTER TABLE acl_object_identities ADD CONSTRAINT FK_9407E54977FA751A FOREIGN KEY (parent_object_identity_id) REFERENCES acl_object_identities (id)
ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE2993D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE
ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE299C671CEA1 FOREIGN KEY (ancestor_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE
ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806EA000B10 FOREIGN KEY (class_id) REFERENCES acl_classes (id) ON UPDATE CASCADE ON DELETE CASCADE
ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B8063D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE
ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806DF9183C9 FOREIGN KEY (security_identity_id) REFERENCES acl_security_identities (id) ON UPDATE CASCADE ON DELETE CASCADE

View File

@ -1,43 +0,0 @@
CREATE TABLE acl_classes (id INT IDENTITY NOT NULL, class_type NVARCHAR(200) NOT NULL, PRIMARY KEY (id))
CREATE UNIQUE INDEX UNIQ_69DD750638A36066 ON acl_classes (class_type) WHERE class_type IS NOT NULL
CREATE TABLE acl_security_identities (id INT IDENTITY NOT NULL, identifier NVARCHAR(200) NOT NULL, username BIT NOT NULL, PRIMARY KEY (id))
CREATE UNIQUE INDEX UNIQ_8835EE78772E836AF85E0677 ON acl_security_identities (identifier, username) WHERE identifier IS NOT NULL AND username IS NOT NULL
CREATE TABLE acl_object_identities (id INT IDENTITY NOT NULL, parent_object_identity_id INT, class_id INT NOT NULL, object_identifier NVARCHAR(100) NOT NULL, entries_inheriting BIT NOT NULL, PRIMARY KEY (id))
CREATE UNIQUE INDEX UNIQ_9407E5494B12AD6EA000B10 ON acl_object_identities (object_identifier, class_id) WHERE object_identifier IS NOT NULL AND class_id IS NOT NULL
CREATE INDEX IDX_9407E54977FA751A ON acl_object_identities (parent_object_identity_id)
CREATE TABLE acl_object_identity_ancestors (object_identity_id INT NOT NULL, ancestor_id INT NOT NULL, PRIMARY KEY (object_identity_id, ancestor_id))
CREATE INDEX IDX_825DE2993D9AB4A6 ON acl_object_identity_ancestors (object_identity_id)
CREATE INDEX IDX_825DE299C671CEA1 ON acl_object_identity_ancestors (ancestor_id)
CREATE TABLE acl_entries (id INT IDENTITY NOT NULL, class_id INT NOT NULL, object_identity_id INT, security_identity_id INT NOT NULL, field_name NVARCHAR(50), ace_order SMALLINT NOT NULL, mask INT NOT NULL, granting BIT NOT NULL, granting_strategy NVARCHAR(30) NOT NULL, audit_success BIT NOT NULL, audit_failure BIT NOT NULL, PRIMARY KEY (id))
CREATE UNIQUE INDEX UNIQ_46C8B806EA000B103D9AB4A64DEF17BCE4289BF4 ON acl_entries (class_id, object_identity_id, field_name, ace_order) WHERE class_id IS NOT NULL AND object_identity_id IS NOT NULL AND field_name IS NOT NULL AND ace_order IS NOT NULL
CREATE INDEX IDX_46C8B806EA000B103D9AB4A6DF9183C9 ON acl_entries (class_id, object_identity_id, security_identity_id)
CREATE INDEX IDX_46C8B806EA000B10 ON acl_entries (class_id)
CREATE INDEX IDX_46C8B8063D9AB4A6 ON acl_entries (object_identity_id)
CREATE INDEX IDX_46C8B806DF9183C9 ON acl_entries (security_identity_id)
ALTER TABLE acl_object_identities ADD CONSTRAINT FK_9407E54977FA751A FOREIGN KEY (parent_object_identity_id) REFERENCES acl_object_identities (id)
ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE2993D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE
ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE299C671CEA1 FOREIGN KEY (ancestor_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE
ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806EA000B10 FOREIGN KEY (class_id) REFERENCES acl_classes (id) ON UPDATE CASCADE ON DELETE CASCADE
ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B8063D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE
ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806DF9183C9 FOREIGN KEY (security_identity_id) REFERENCES acl_security_identities (id) ON UPDATE CASCADE ON DELETE CASCADE

View File

@ -1,21 +0,0 @@
CREATE TABLE acl_classes (id INT UNSIGNED AUTO_INCREMENT NOT NULL, class_type VARCHAR(200) NOT NULL, UNIQUE INDEX UNIQ_69DD750638A36066 (class_type), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB
CREATE TABLE acl_security_identities (id INT UNSIGNED AUTO_INCREMENT NOT NULL, identifier VARCHAR(200) NOT NULL, username TINYINT(1) NOT NULL, UNIQUE INDEX UNIQ_8835EE78772E836AF85E0677 (identifier, username), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB
CREATE TABLE acl_object_identities (id INT UNSIGNED AUTO_INCREMENT NOT NULL, parent_object_identity_id INT UNSIGNED DEFAULT NULL, class_id INT UNSIGNED NOT NULL, object_identifier VARCHAR(100) NOT NULL, entries_inheriting TINYINT(1) NOT NULL, UNIQUE INDEX UNIQ_9407E5494B12AD6EA000B10 (object_identifier, class_id), INDEX IDX_9407E54977FA751A (parent_object_identity_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB
CREATE TABLE acl_object_identity_ancestors (object_identity_id INT UNSIGNED NOT NULL, ancestor_id INT UNSIGNED NOT NULL, INDEX IDX_825DE2993D9AB4A6 (object_identity_id), INDEX IDX_825DE299C671CEA1 (ancestor_id), PRIMARY KEY(object_identity_id, ancestor_id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB
CREATE TABLE acl_entries (id INT UNSIGNED AUTO_INCREMENT NOT NULL, class_id INT UNSIGNED NOT NULL, object_identity_id INT UNSIGNED DEFAULT NULL, security_identity_id INT UNSIGNED NOT NULL, field_name VARCHAR(50) DEFAULT NULL, ace_order SMALLINT UNSIGNED NOT NULL, mask INT NOT NULL, granting TINYINT(1) NOT NULL, granting_strategy VARCHAR(30) NOT NULL, audit_success TINYINT(1) NOT NULL, audit_failure TINYINT(1) NOT NULL, UNIQUE INDEX UNIQ_46C8B806EA000B103D9AB4A64DEF17BCE4289BF4 (class_id, object_identity_id, field_name, ace_order), INDEX IDX_46C8B806EA000B103D9AB4A6DF9183C9 (class_id, object_identity_id, security_identity_id), INDEX IDX_46C8B806EA000B10 (class_id), INDEX IDX_46C8B8063D9AB4A6 (object_identity_id), INDEX IDX_46C8B806DF9183C9 (security_identity_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB
ALTER TABLE acl_object_identities ADD CONSTRAINT FK_9407E54977FA751A FOREIGN KEY (parent_object_identity_id) REFERENCES acl_object_identities (id)
ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE2993D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE
ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE299C671CEA1 FOREIGN KEY (ancestor_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE
ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806EA000B10 FOREIGN KEY (class_id) REFERENCES acl_classes (id) ON UPDATE CASCADE ON DELETE CASCADE
ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B8063D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE
ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806DF9183C9 FOREIGN KEY (security_identity_id) REFERENCES acl_security_identities (id) ON UPDATE CASCADE ON DELETE CASCADE

View File

@ -1,175 +0,0 @@
CREATE TABLE acl_classes (id NUMBER(10) NOT NULL, class_type VARCHAR2(200) NOT NULL, PRIMARY KEY(id))
DECLARE
constraints_Count NUMBER;
BEGIN
SELECT COUNT(CONSTRAINT_NAME) INTO constraints_Count FROM USER_CONSTRAINTS WHERE TABLE_NAME = 'ACL_CLASSES' AND CONSTRAINT_TYPE = 'P';
IF constraints_Count = 0 OR constraints_Count = '' THEN
EXECUTE IMMEDIATE 'ALTER TABLE ACL_CLASSES ADD CONSTRAINT ACL_CLASSES_AI_PK PRIMARY KEY (ID)';
END IF;
END;
CREATE SEQUENCE ACL_CLASSES_SEQ START WITH 1 MINVALUE 1 INCREMENT BY 1
CREATE TRIGGER ACL_CLASSES_AI_PK
BEFORE INSERT
ON ACL_CLASSES
FOR EACH ROW
DECLARE
last_Sequence NUMBER;
last_InsertID NUMBER;
BEGIN
SELECT ACL_CLASSES_SEQ.NEXTVAL INTO :NEW.ID FROM DUAL;
IF (:NEW.ID IS NULL OR :NEW.ID = 0) THEN
SELECT ACL_CLASSES_SEQ.NEXTVAL INTO :NEW.ID FROM DUAL;
ELSE
SELECT NVL(Last_Number, 0) INTO last_Sequence
FROM User_Sequences
WHERE Sequence_Name = 'ACL_CLASSES_SEQ';
SELECT :NEW.ID INTO last_InsertID FROM DUAL;
WHILE (last_InsertID > last_Sequence) LOOP
SELECT ACL_CLASSES_SEQ.NEXTVAL INTO last_Sequence FROM DUAL;
END LOOP;
END IF;
END;
CREATE UNIQUE INDEX UNIQ_69DD750638A36066 ON acl_classes (class_type)
CREATE TABLE acl_security_identities (id NUMBER(10) NOT NULL, identifier VARCHAR2(200) NOT NULL, username NUMBER(1) NOT NULL, PRIMARY KEY(id))
DECLARE
constraints_Count NUMBER;
BEGIN
SELECT COUNT(CONSTRAINT_NAME) INTO constraints_Count FROM USER_CONSTRAINTS WHERE TABLE_NAME = 'ACL_SECURITY_IDENTITIES' AND CONSTRAINT_TYPE = 'P';
IF constraints_Count = 0 OR constraints_Count = '' THEN
EXECUTE IMMEDIATE 'ALTER TABLE ACL_SECURITY_IDENTITIES ADD CONSTRAINT ACL_SECURITY_IDENTITIES_AI_PK PRIMARY KEY (ID)';
END IF;
END;
CREATE SEQUENCE ACL_SECURITY_IDENTITIES_SEQ START WITH 1 MINVALUE 1 INCREMENT BY 1
CREATE TRIGGER ACL_SECURITY_IDENTITIES_AI_PK
BEFORE INSERT
ON ACL_SECURITY_IDENTITIES
FOR EACH ROW
DECLARE
last_Sequence NUMBER;
last_InsertID NUMBER;
BEGIN
SELECT ACL_SECURITY_IDENTITIES_SEQ.NEXTVAL INTO :NEW.ID FROM DUAL;
IF (:NEW.ID IS NULL OR :NEW.ID = 0) THEN
SELECT ACL_SECURITY_IDENTITIES_SEQ.NEXTVAL INTO :NEW.ID FROM DUAL;
ELSE
SELECT NVL(Last_Number, 0) INTO last_Sequence
FROM User_Sequences
WHERE Sequence_Name = 'ACL_SECURITY_IDENTITIES_SEQ';
SELECT :NEW.ID INTO last_InsertID FROM DUAL;
WHILE (last_InsertID > last_Sequence) LOOP
SELECT ACL_SECURITY_IDENTITIES_SEQ.NEXTVAL INTO last_Sequence FROM DUAL;
END LOOP;
END IF;
END;
CREATE UNIQUE INDEX UNIQ_8835EE78772E836AF85E0677 ON acl_security_identities (identifier, username)
CREATE TABLE acl_object_identities (id NUMBER(10) NOT NULL, parent_object_identity_id NUMBER(10) DEFAULT NULL NULL, class_id NUMBER(10) NOT NULL, object_identifier VARCHAR2(100) NOT NULL, entries_inheriting NUMBER(1) NOT NULL, PRIMARY KEY(id))
DECLARE
constraints_Count NUMBER;
BEGIN
SELECT COUNT(CONSTRAINT_NAME) INTO constraints_Count FROM USER_CONSTRAINTS WHERE TABLE_NAME = 'ACL_OBJECT_IDENTITIES' AND CONSTRAINT_TYPE = 'P';
IF constraints_Count = 0 OR constraints_Count = '' THEN
EXECUTE IMMEDIATE 'ALTER TABLE ACL_OBJECT_IDENTITIES ADD CONSTRAINT ACL_OBJECT_IDENTITIES_AI_PK PRIMARY KEY (ID)';
END IF;
END;
CREATE SEQUENCE ACL_OBJECT_IDENTITIES_SEQ START WITH 1 MINVALUE 1 INCREMENT BY 1
CREATE TRIGGER ACL_OBJECT_IDENTITIES_AI_PK
BEFORE INSERT
ON ACL_OBJECT_IDENTITIES
FOR EACH ROW
DECLARE
last_Sequence NUMBER;
last_InsertID NUMBER;
BEGIN
SELECT ACL_OBJECT_IDENTITIES_SEQ.NEXTVAL INTO :NEW.ID FROM DUAL;
IF (:NEW.ID IS NULL OR :NEW.ID = 0) THEN
SELECT ACL_OBJECT_IDENTITIES_SEQ.NEXTVAL INTO :NEW.ID FROM DUAL;
ELSE
SELECT NVL(Last_Number, 0) INTO last_Sequence
FROM User_Sequences
WHERE Sequence_Name = 'ACL_OBJECT_IDENTITIES_SEQ';
SELECT :NEW.ID INTO last_InsertID FROM DUAL;
WHILE (last_InsertID > last_Sequence) LOOP
SELECT ACL_OBJECT_IDENTITIES_SEQ.NEXTVAL INTO last_Sequence FROM DUAL;
END LOOP;
END IF;
END;
CREATE UNIQUE INDEX UNIQ_9407E5494B12AD6EA000B10 ON acl_object_identities (object_identifier, class_id)
CREATE INDEX IDX_9407E54977FA751A ON acl_object_identities (parent_object_identity_id)
CREATE TABLE acl_object_identity_ancestors (object_identity_id NUMBER(10) NOT NULL, ancestor_id NUMBER(10) NOT NULL, PRIMARY KEY(object_identity_id, ancestor_id))
CREATE INDEX IDX_825DE2993D9AB4A6 ON acl_object_identity_ancestors (object_identity_id)
CREATE INDEX IDX_825DE299C671CEA1 ON acl_object_identity_ancestors (ancestor_id)
CREATE TABLE acl_entries (id NUMBER(10) NOT NULL, class_id NUMBER(10) NOT NULL, object_identity_id NUMBER(10) DEFAULT NULL NULL, security_identity_id NUMBER(10) NOT NULL, field_name VARCHAR2(50) DEFAULT NULL NULL, ace_order NUMBER(5) NOT NULL, mask NUMBER(10) NOT NULL, granting NUMBER(1) NOT NULL, granting_strategy VARCHAR2(30) NOT NULL, audit_success NUMBER(1) NOT NULL, audit_failure NUMBER(1) NOT NULL, PRIMARY KEY(id))
DECLARE
constraints_Count NUMBER;
BEGIN
SELECT COUNT(CONSTRAINT_NAME) INTO constraints_Count FROM USER_CONSTRAINTS WHERE TABLE_NAME = 'ACL_ENTRIES' AND CONSTRAINT_TYPE = 'P';
IF constraints_Count = 0 OR constraints_Count = '' THEN
EXECUTE IMMEDIATE 'ALTER TABLE ACL_ENTRIES ADD CONSTRAINT ACL_ENTRIES_AI_PK PRIMARY KEY (ID)';
END IF;
END;
CREATE SEQUENCE ACL_ENTRIES_SEQ START WITH 1 MINVALUE 1 INCREMENT BY 1
CREATE TRIGGER ACL_ENTRIES_AI_PK
BEFORE INSERT
ON ACL_ENTRIES
FOR EACH ROW
DECLARE
last_Sequence NUMBER;
last_InsertID NUMBER;
BEGIN
SELECT ACL_ENTRIES_SEQ.NEXTVAL INTO :NEW.ID FROM DUAL;
IF (:NEW.ID IS NULL OR :NEW.ID = 0) THEN
SELECT ACL_ENTRIES_SEQ.NEXTVAL INTO :NEW.ID FROM DUAL;
ELSE
SELECT NVL(Last_Number, 0) INTO last_Sequence
FROM User_Sequences
WHERE Sequence_Name = 'ACL_ENTRIES_SEQ';
SELECT :NEW.ID INTO last_InsertID FROM DUAL;
WHILE (last_InsertID > last_Sequence) LOOP
SELECT ACL_ENTRIES_SEQ.NEXTVAL INTO last_Sequence FROM DUAL;
END LOOP;
END IF;
END;
CREATE UNIQUE INDEX UNIQ_46C8B806EA000B103D9AB4A64DEF17BCE4289BF4 ON acl_entries (class_id, object_identity_id, field_name, ace_order)
CREATE INDEX IDX_46C8B806EA000B103D9AB4A6DF9183C9 ON acl_entries (class_id, object_identity_id, security_identity_id)
CREATE INDEX IDX_46C8B806EA000B10 ON acl_entries (class_id)
CREATE INDEX IDX_46C8B8063D9AB4A6 ON acl_entries (object_identity_id)
CREATE INDEX IDX_46C8B806DF9183C9 ON acl_entries (security_identity_id)
ALTER TABLE acl_object_identities ADD CONSTRAINT FK_9407E54977FA751A FOREIGN KEY (parent_object_identity_id) REFERENCES acl_object_identities (id)
ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE2993D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON DELETE CASCADE
ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE299C671CEA1 FOREIGN KEY (ancestor_id) REFERENCES acl_object_identities (id) ON DELETE CASCADE
ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806EA000B10 FOREIGN KEY (class_id) REFERENCES acl_classes (id) ON DELETE CASCADE
ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B8063D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON DELETE CASCADE
ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806DF9183C9 FOREIGN KEY (security_identity_id) REFERENCES acl_security_identities (id) ON DELETE CASCADE

View File

@ -1,43 +0,0 @@
CREATE TABLE acl_classes (id SERIAL NOT NULL, class_type VARCHAR(200) NOT NULL, PRIMARY KEY(id))
CREATE UNIQUE INDEX UNIQ_69DD750638A36066 ON acl_classes (class_type)
CREATE TABLE acl_security_identities (id SERIAL NOT NULL, identifier VARCHAR(200) NOT NULL, username BOOLEAN NOT NULL, PRIMARY KEY(id))
CREATE UNIQUE INDEX UNIQ_8835EE78772E836AF85E0677 ON acl_security_identities (identifier, username)
CREATE TABLE acl_object_identities (id SERIAL NOT NULL, parent_object_identity_id INT DEFAULT NULL, class_id INT NOT NULL, object_identifier VARCHAR(100) NOT NULL, entries_inheriting BOOLEAN NOT NULL, PRIMARY KEY(id))
CREATE UNIQUE INDEX UNIQ_9407E5494B12AD6EA000B10 ON acl_object_identities (object_identifier, class_id)
CREATE INDEX IDX_9407E54977FA751A ON acl_object_identities (parent_object_identity_id)
CREATE TABLE acl_object_identity_ancestors (object_identity_id INT NOT NULL, ancestor_id INT NOT NULL, PRIMARY KEY(object_identity_id, ancestor_id))
CREATE INDEX IDX_825DE2993D9AB4A6 ON acl_object_identity_ancestors (object_identity_id)
CREATE INDEX IDX_825DE299C671CEA1 ON acl_object_identity_ancestors (ancestor_id)
CREATE TABLE acl_entries (id SERIAL NOT NULL, class_id INT NOT NULL, object_identity_id INT DEFAULT NULL, security_identity_id INT NOT NULL, field_name VARCHAR(50) DEFAULT NULL, ace_order SMALLINT NOT NULL, mask INT NOT NULL, granting BOOLEAN NOT NULL, granting_strategy VARCHAR(30) NOT NULL, audit_success BOOLEAN NOT NULL, audit_failure BOOLEAN NOT NULL, PRIMARY KEY(id))
CREATE UNIQUE INDEX UNIQ_46C8B806EA000B103D9AB4A64DEF17BCE4289BF4 ON acl_entries (class_id, object_identity_id, field_name, ace_order)
CREATE INDEX IDX_46C8B806EA000B103D9AB4A6DF9183C9 ON acl_entries (class_id, object_identity_id, security_identity_id)
CREATE INDEX IDX_46C8B806EA000B10 ON acl_entries (class_id)
CREATE INDEX IDX_46C8B8063D9AB4A6 ON acl_entries (object_identity_id)
CREATE INDEX IDX_46C8B806DF9183C9 ON acl_entries (security_identity_id)
ALTER TABLE acl_object_identities ADD CONSTRAINT FK_9407E54977FA751A FOREIGN KEY (parent_object_identity_id) REFERENCES acl_object_identities (id) NOT DEFERRABLE INITIALLY IMMEDIATE
ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE2993D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE
ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE299C671CEA1 FOREIGN KEY (ancestor_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE
ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806EA000B10 FOREIGN KEY (class_id) REFERENCES acl_classes (id) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE
ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B8063D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE
ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806DF9183C9 FOREIGN KEY (security_identity_id) REFERENCES acl_security_identities (id) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE

View File

@ -1,43 +0,0 @@
CREATE TABLE acl_classes (id UNSIGNED INT IDENTITY NOT NULL, class_type VARCHAR(200) NOT NULL, PRIMARY KEY (id))
CREATE UNIQUE INDEX UNIQ_69DD750638A36066 ON acl_classes (class_type)
CREATE TABLE acl_security_identities (id UNSIGNED INT IDENTITY NOT NULL, identifier VARCHAR(200) NOT NULL, username BIT NOT NULL, PRIMARY KEY (id))
CREATE UNIQUE INDEX UNIQ_8835EE78772E836AF85E0677 ON acl_security_identities (identifier, username)
CREATE TABLE acl_object_identities (id UNSIGNED INT IDENTITY NOT NULL, parent_object_identity_id UNSIGNED INT DEFAULT NULL, class_id UNSIGNED INT NOT NULL, object_identifier VARCHAR(100) NOT NULL, entries_inheriting BIT NOT NULL, PRIMARY KEY (id))
CREATE UNIQUE INDEX UNIQ_9407E5494B12AD6EA000B10 ON acl_object_identities (object_identifier, class_id)
CREATE INDEX IDX_9407E54977FA751A ON acl_object_identities (parent_object_identity_id)
CREATE TABLE acl_object_identity_ancestors (object_identity_id UNSIGNED INT NOT NULL, ancestor_id UNSIGNED INT NOT NULL, PRIMARY KEY (object_identity_id, ancestor_id))
CREATE INDEX IDX_825DE2993D9AB4A6 ON acl_object_identity_ancestors (object_identity_id)
CREATE INDEX IDX_825DE299C671CEA1 ON acl_object_identity_ancestors (ancestor_id)
CREATE TABLE acl_entries (id UNSIGNED INT IDENTITY NOT NULL, class_id UNSIGNED INT NOT NULL, object_identity_id UNSIGNED INT DEFAULT NULL, security_identity_id UNSIGNED INT NOT NULL, field_name VARCHAR(50) DEFAULT NULL, ace_order UNSIGNED SMALLINT NOT NULL, mask INT NOT NULL, granting BIT NOT NULL, granting_strategy VARCHAR(30) NOT NULL, audit_success BIT NOT NULL, audit_failure BIT NOT NULL, PRIMARY KEY (id))
CREATE UNIQUE INDEX UNIQ_46C8B806EA000B103D9AB4A64DEF17BCE4289BF4 ON acl_entries (class_id, object_identity_id, field_name, ace_order)
CREATE INDEX IDX_46C8B806EA000B103D9AB4A6DF9183C9 ON acl_entries (class_id, object_identity_id, security_identity_id)
CREATE INDEX IDX_46C8B806EA000B10 ON acl_entries (class_id)
CREATE INDEX IDX_46C8B8063D9AB4A6 ON acl_entries (object_identity_id)
CREATE INDEX IDX_46C8B806DF9183C9 ON acl_entries (security_identity_id)
ALTER TABLE acl_object_identities ADD CONSTRAINT FK_9407E54977FA751A FOREIGN KEY (parent_object_identity_id) REFERENCES acl_object_identities (id)
ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE2993D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE
ALTER TABLE acl_object_identity_ancestors ADD CONSTRAINT FK_825DE299C671CEA1 FOREIGN KEY (ancestor_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE
ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806EA000B10 FOREIGN KEY (class_id) REFERENCES acl_classes (id) ON UPDATE CASCADE ON DELETE CASCADE
ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B8063D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON UPDATE CASCADE ON DELETE CASCADE
ALTER TABLE acl_entries ADD CONSTRAINT FK_46C8B806DF9183C9 FOREIGN KEY (security_identity_id) REFERENCES acl_security_identities (id) ON UPDATE CASCADE ON DELETE CASCADE

View File

@ -1,31 +0,0 @@
CREATE TABLE acl_classes (id INTEGER NOT NULL, class_type VARCHAR(200) NOT NULL, PRIMARY KEY(id))
CREATE UNIQUE INDEX UNIQ_69DD750638A36066 ON acl_classes (class_type)
CREATE TABLE acl_security_identities (id INTEGER NOT NULL, identifier VARCHAR(200) NOT NULL, username BOOLEAN NOT NULL, PRIMARY KEY(id))
CREATE UNIQUE INDEX UNIQ_8835EE78772E836AF85E0677 ON acl_security_identities (identifier, username)
CREATE TABLE acl_object_identities (id INTEGER NOT NULL, parent_object_identity_id INTEGER UNSIGNED DEFAULT NULL, class_id INTEGER UNSIGNED NOT NULL, object_identifier VARCHAR(100) NOT NULL, entries_inheriting BOOLEAN NOT NULL, PRIMARY KEY(id), CONSTRAINT FK_9407E54977FA751A FOREIGN KEY (parent_object_identity_id) REFERENCES acl_object_identities (id) NOT DEFERRABLE INITIALLY IMMEDIATE)
CREATE UNIQUE INDEX UNIQ_9407E5494B12AD6EA000B10 ON acl_object_identities (object_identifier, class_id)
CREATE INDEX IDX_9407E54977FA751A ON acl_object_identities (parent_object_identity_id)
CREATE TABLE acl_object_identity_ancestors (object_identity_id INTEGER UNSIGNED NOT NULL, ancestor_id INTEGER UNSIGNED NOT NULL, PRIMARY KEY(object_identity_id, ancestor_id), CONSTRAINT FK_825DE2993D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_825DE299C671CEA1 FOREIGN KEY (ancestor_id) REFERENCES acl_object_identities (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE)
CREATE INDEX IDX_825DE2993D9AB4A6 ON acl_object_identity_ancestors (object_identity_id)
CREATE INDEX IDX_825DE299C671CEA1 ON acl_object_identity_ancestors (ancestor_id)
CREATE TABLE acl_entries (id INTEGER NOT NULL, class_id INTEGER UNSIGNED NOT NULL, object_identity_id INTEGER UNSIGNED DEFAULT NULL, security_identity_id INTEGER UNSIGNED NOT NULL, field_name VARCHAR(50) DEFAULT NULL, ace_order SMALLINT UNSIGNED NOT NULL, mask INTEGER NOT NULL, granting BOOLEAN NOT NULL, granting_strategy VARCHAR(30) NOT NULL, audit_success BOOLEAN NOT NULL, audit_failure BOOLEAN NOT NULL, PRIMARY KEY(id), CONSTRAINT FK_46C8B806EA000B10 FOREIGN KEY (class_id) REFERENCES acl_classes (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_46C8B8063D9AB4A6 FOREIGN KEY (object_identity_id) REFERENCES acl_object_identities (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_46C8B806DF9183C9 FOREIGN KEY (security_identity_id) REFERENCES acl_security_identities (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE)
CREATE UNIQUE INDEX UNIQ_46C8B806EA000B103D9AB4A64DEF17BCE4289BF4 ON acl_entries (class_id, object_identity_id, field_name, ace_order)
CREATE INDEX IDX_46C8B806EA000B103D9AB4A6DF9183C9 ON acl_entries (class_id, object_identity_id, security_identity_id)
CREATE INDEX IDX_46C8B806EA000B10 ON acl_entries (class_id)
CREATE INDEX IDX_46C8B8063D9AB4A6 ON acl_entries (object_identity_id)
CREATE INDEX IDX_46C8B806DF9183C9 ON acl_entries (security_identity_id)

View File

@ -1,267 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Tests\Dbal;
use Symfony\Component\Security\Acl\Dbal\AclProvider;
use Symfony\Component\Security\Acl\Domain\PermissionGrantingStrategy;
use Symfony\Component\Security\Acl\Domain\ObjectIdentity;
use Symfony\Component\Security\Acl\Dbal\Schema;
use Doctrine\DBAL\DriverManager;
/**
* @group benchmark
*/
class AclProviderBenchmarkTest extends \PHPUnit_Framework_TestCase
{
/** @var \Doctrine\DBAL\Connection */
protected $con;
protected $insertClassStmt;
protected $insertSidStmt;
protected $insertOidAncestorStmt;
protected $insertOidStmt;
protected $insertEntryStmt;
protected function setUp()
{
try {
$this->con = DriverManager::getConnection(array(
'driver' => 'pdo_mysql',
'host' => 'localhost',
'user' => 'root',
'dbname' => 'testdb',
));
$this->con->connect();
} catch (\Exception $e) {
$this->markTestSkipped('Unable to connect to the database: '.$e->getMessage());
}
}
protected function tearDown()
{
$this->con = null;
}
public function testFindAcls()
{
// $this->generateTestData();
// get some random test object identities from the database
$oids = array();
$stmt = $this->con->executeQuery('SELECT object_identifier, class_type FROM acl_object_identities o INNER JOIN acl_classes c ON c.id = o.class_id ORDER BY RAND() LIMIT 25');
foreach ($stmt->fetchAll() as $oid) {
$oids[] = new ObjectIdentity($oid['object_identifier'], $oid['class_type']);
}
$provider = $this->getProvider();
$start = microtime(true);
$provider->findAcls($oids);
$time = microtime(true) - $start;
echo 'Total Time: '.$time."s\n";
}
/**
* This generates a huge amount of test data to be used mainly for benchmarking
* purposes, not so much for testing. That's why it's not called by default.
*/
protected function generateTestData()
{
$sm = $this->con->getSchemaManager();
$sm->dropAndCreateDatabase('testdb');
$this->con->exec('USE testdb');
// import the schema
$schema = new Schema($options = $this->getOptions());
foreach ($schema->toSql($this->con->getDatabasePlatform()) as $sql) {
$this->con->exec($sql);
}
// setup prepared statements
$this->insertClassStmt = $this->con->prepare('INSERT INTO acl_classes (id, class_type) VALUES (?, ?)');
$this->insertSidStmt = $this->con->prepare('INSERT INTO acl_security_identities (id, identifier, username) VALUES (?, ?, ?)');
$this->insertOidStmt = $this->con->prepare('INSERT INTO acl_object_identities (id, class_id, object_identifier, parent_object_identity_id, entries_inheriting) VALUES (?, ?, ?, ?, ?)');
$this->insertEntryStmt = $this->con->prepare('INSERT INTO acl_entries (id, class_id, object_identity_id, field_name, ace_order, security_identity_id, mask, granting, granting_strategy, audit_success, audit_failure) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)');
$this->insertOidAncestorStmt = $this->con->prepare('INSERT INTO acl_object_identity_ancestors (object_identity_id, ancestor_id) VALUES (?, ?)');
for ($i = 0; $i < 40000; ++$i) {
$this->generateAclHierarchy();
}
}
protected function generateAclHierarchy()
{
$rootId = $this->generateAcl($this->chooseClassId(), null, array());
$this->generateAclLevel(rand(1, 15), $rootId, array($rootId));
}
protected function generateAclLevel($depth, $parentId, $ancestors)
{
$level = count($ancestors);
for ($i = 0, $t = rand(1, 10); $i < $t; ++$i) {
$id = $this->generateAcl($this->chooseClassId(), $parentId, $ancestors);
if ($level < $depth) {
$this->generateAclLevel($depth, $id, array_merge($ancestors, array($id)));
}
}
}
protected function chooseClassId()
{
static $id = 1000;
if ($id === 1000 || ($id < 1500 && rand(0, 1))) {
$this->insertClassStmt->execute(array($id, $this->getRandomString(rand(20, 100), 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\\_')));
++$id;
return $id - 1;
} else {
return rand(1000, $id - 1);
}
}
protected function generateAcl($classId, $parentId, $ancestors)
{
static $id = 1000;
$this->insertOidStmt->execute(array(
$id,
$classId,
$this->getRandomString(rand(20, 50)),
$parentId,
rand(0, 1),
));
$this->insertOidAncestorStmt->execute(array($id, $id));
foreach ($ancestors as $ancestor) {
$this->insertOidAncestorStmt->execute(array($id, $ancestor));
}
$this->generateAces($classId, $id);
++$id;
return $id - 1;
}
protected function chooseSid()
{
static $id = 1000;
if ($id === 1000 || ($id < 11000 && rand(0, 1))) {
$this->insertSidStmt->execute(array(
$id,
$this->getRandomString(rand(5, 30)),
rand(0, 1),
));
++$id;
return $id - 1;
} else {
return rand(1000, $id - 1);
}
}
protected function generateAces($classId, $objectId)
{
static $id = 1000;
$sids = array();
$fieldOrder = array();
for ($i = 0; $i <= 30; ++$i) {
$fieldName = rand(0, 1) ? null : $this->getRandomString(rand(10, 20));
do {
$sid = $this->chooseSid();
} while (array_key_exists($sid, $sids) && in_array($fieldName, $sids[$sid], true));
$fieldOrder[$fieldName] = array_key_exists($fieldName, $fieldOrder) ? $fieldOrder[$fieldName] + 1 : 0;
if (!isset($sids[$sid])) {
$sids[$sid] = array();
}
$sids[$sid][] = $fieldName;
$strategy = rand(0, 2);
if ($strategy === 0) {
$strategy = PermissionGrantingStrategy::ALL;
} elseif ($strategy === 1) {
$strategy = PermissionGrantingStrategy::ANY;
} else {
$strategy = PermissionGrantingStrategy::EQUAL;
}
// id, cid, oid, field, order, sid, mask, granting, strategy, a success, a failure
$this->insertEntryStmt->execute(array(
$id,
$classId,
rand(0, 5) ? $objectId : null,
$fieldName,
$fieldOrder[$fieldName],
$sid,
$this->generateMask(),
rand(0, 1),
$strategy,
rand(0, 1),
rand(0, 1),
));
++$id;
}
}
protected function generateMask()
{
$i = rand(1, 30);
$mask = 0;
while ($i <= 30) {
$mask |= 1 << rand(0, 30);
++$i;
}
return $mask;
}
protected function getRandomString($length, $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789')
{
$s = '';
$cLength = strlen($chars);
while (strlen($s) < $length) {
$s .= $chars[mt_rand(0, $cLength - 1)];
}
return $s;
}
protected function getOptions()
{
return array(
'oid_table_name' => 'acl_object_identities',
'oid_ancestors_table_name' => 'acl_object_identity_ancestors',
'class_table_name' => 'acl_classes',
'sid_table_name' => 'acl_security_identities',
'entry_table_name' => 'acl_entries',
);
}
protected function getStrategy()
{
return new PermissionGrantingStrategy();
}
protected function getProvider()
{
return new AclProvider($this->con, $this->getStrategy(), $this->getOptions());
}
}

View File

@ -1,281 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Tests\Dbal;
use Symfony\Component\Security\Acl\Dbal\AclProvider;
use Symfony\Component\Security\Acl\Domain\PermissionGrantingStrategy;
use Symfony\Component\Security\Acl\Domain\ObjectIdentity;
use Symfony\Component\Security\Acl\Dbal\Schema;
use Doctrine\DBAL\DriverManager;
class AclProviderTest extends \PHPUnit_Framework_TestCase
{
protected $con;
protected $insertClassStmt;
protected $insertEntryStmt;
protected $insertOidStmt;
protected $insertOidAncestorStmt;
protected $insertSidStmt;
/**
* @expectedException \Symfony\Component\Security\Acl\Exception\AclNotFoundException
* @expectedMessage There is no ACL for the given object identity.
*/
public function testFindAclThrowsExceptionWhenNoAclExists()
{
$this->getProvider()->findAcl(new ObjectIdentity('foo', 'foo'));
}
public function testFindAclsThrowsExceptionUnlessAnACLIsFoundForEveryOID()
{
$oids = array();
$oids[] = new ObjectIdentity('1', 'foo');
$oids[] = new ObjectIdentity('foo', 'foo');
try {
$this->getProvider()->findAcls($oids);
$this->fail('Provider did not throw an expected exception.');
} catch (\Exception $e) {
$this->assertInstanceOf('Symfony\Component\Security\Acl\Exception\AclNotFoundException', $e);
$this->assertInstanceOf('Symfony\Component\Security\Acl\Exception\NotAllAclsFoundException', $e);
$partialResult = $e->getPartialResult();
$this->assertTrue($partialResult->contains($oids[0]));
$this->assertFalse($partialResult->contains($oids[1]));
}
}
public function testFindAcls()
{
$oids = array();
$oids[] = new ObjectIdentity('1', 'foo');
$oids[] = new ObjectIdentity('2', 'foo');
$provider = $this->getProvider();
$acls = $provider->findAcls($oids);
$this->assertInstanceOf('SplObjectStorage', $acls);
$this->assertCount(2, $acls);
$this->assertInstanceOf('Symfony\Component\Security\Acl\Domain\Acl', $acl0 = $acls->offsetGet($oids[0]));
$this->assertInstanceOf('Symfony\Component\Security\Acl\Domain\Acl', $acl1 = $acls->offsetGet($oids[1]));
$this->assertTrue($oids[0]->equals($acl0->getObjectIdentity()));
$this->assertTrue($oids[1]->equals($acl1->getObjectIdentity()));
}
public function testFindAclsWithDifferentTypes()
{
$oids = array();
$oids[] = new ObjectIdentity('123', 'Bundle\SomeVendor\MyBundle\Entity\SomeEntity');
$oids[] = new ObjectIdentity('123', 'Bundle\MyBundle\Entity\AnotherEntity');
$provider = $this->getProvider();
$acls = $provider->findAcls($oids);
$this->assertInstanceOf('SplObjectStorage', $acls);
$this->assertCount(2, $acls);
$this->assertInstanceOf('Symfony\Component\Security\Acl\Domain\Acl', $acl0 = $acls->offsetGet($oids[0]));
$this->assertInstanceOf('Symfony\Component\Security\Acl\Domain\Acl', $acl1 = $acls->offsetGet($oids[1]));
$this->assertTrue($oids[0]->equals($acl0->getObjectIdentity()));
$this->assertTrue($oids[1]->equals($acl1->getObjectIdentity()));
}
public function testFindAclCachesAclInMemory()
{
$oid = new ObjectIdentity('1', 'foo');
$provider = $this->getProvider();
$acl = $provider->findAcl($oid);
$this->assertSame($acl, $cAcl = $provider->findAcl($oid));
$cAces = $cAcl->getObjectAces();
foreach ($acl->getObjectAces() as $index => $ace) {
$this->assertSame($ace, $cAces[$index]);
}
}
public function testFindAcl()
{
$oid = new ObjectIdentity('1', 'foo');
$provider = $this->getProvider();
$acl = $provider->findAcl($oid);
$this->assertInstanceOf('Symfony\Component\Security\Acl\Domain\Acl', $acl);
$this->assertTrue($oid->equals($acl->getObjectIdentity()));
$this->assertEquals(4, $acl->getId());
$this->assertCount(0, $acl->getClassAces());
$this->assertCount(0, $this->getField($acl, 'classFieldAces'));
$this->assertCount(3, $acl->getObjectAces());
$this->assertCount(0, $this->getField($acl, 'objectFieldAces'));
$aces = $acl->getObjectAces();
$this->assertInstanceOf('Symfony\Component\Security\Acl\Domain\Entry', $aces[0]);
$this->assertTrue($aces[0]->isGranting());
$this->assertTrue($aces[0]->isAuditSuccess());
$this->assertTrue($aces[0]->isAuditFailure());
$this->assertEquals('all', $aces[0]->getStrategy());
$this->assertSame(2, $aces[0]->getMask());
// check ACE are in correct order
$i = 0;
foreach ($aces as $index => $ace) {
$this->assertEquals($i, $index);
++$i;
}
$sid = $aces[0]->getSecurityIdentity();
$this->assertInstanceOf('Symfony\Component\Security\Acl\Domain\UserSecurityIdentity', $sid);
$this->assertEquals('john.doe', $sid->getUsername());
$this->assertEquals('SomeClass', $sid->getClass());
}
protected function setUp()
{
if (!class_exists('PDO') || !in_array('sqlite', \PDO::getAvailableDrivers())) {
self::markTestSkipped('This test requires SQLite support in your environment');
}
$this->con = DriverManager::getConnection(array(
'driver' => 'pdo_sqlite',
'memory' => true,
));
// import the schema
$schema = new Schema($options = $this->getOptions());
foreach ($schema->toSql($this->con->getDatabasePlatform()) as $sql) {
$this->con->exec($sql);
}
// populate the schema with some test data
$this->insertClassStmt = $this->con->prepare('INSERT INTO acl_classes (id, class_type) VALUES (?, ?)');
foreach ($this->getClassData() as $data) {
$this->insertClassStmt->execute($data);
}
$this->insertSidStmt = $this->con->prepare('INSERT INTO acl_security_identities (id, identifier, username) VALUES (?, ?, ?)');
foreach ($this->getSidData() as $data) {
$this->insertSidStmt->execute($data);
}
$this->insertOidStmt = $this->con->prepare('INSERT INTO acl_object_identities (id, class_id, object_identifier, parent_object_identity_id, entries_inheriting) VALUES (?, ?, ?, ?, ?)');
foreach ($this->getOidData() as $data) {
$this->insertOidStmt->execute($data);
}
$this->insertEntryStmt = $this->con->prepare('INSERT INTO acl_entries (id, class_id, object_identity_id, field_name, ace_order, security_identity_id, mask, granting, granting_strategy, audit_success, audit_failure) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)');
foreach ($this->getEntryData() as $data) {
$this->insertEntryStmt->execute($data);
}
$this->insertOidAncestorStmt = $this->con->prepare('INSERT INTO acl_object_identity_ancestors (object_identity_id, ancestor_id) VALUES (?, ?)');
foreach ($this->getOidAncestorData() as $data) {
$this->insertOidAncestorStmt->execute($data);
}
}
protected function tearDown()
{
$this->con = null;
}
protected function getField($object, $field)
{
$reflection = new \ReflectionProperty($object, $field);
$reflection->setAccessible(true);
return $reflection->getValue($object);
}
protected function getEntryData()
{
// id, cid, oid, field, order, sid, mask, granting, strategy, a success, a failure
return array(
array(1, 1, 1, null, 0, 1, 1, 1, 'all', 1, 1),
array(2, 1, 1, null, 1, 2, 1 << 2 | 1 << 1, 0, 'any', 0, 0),
array(3, 3, 4, null, 0, 1, 2, 1, 'all', 1, 1),
array(4, 3, 4, null, 2, 2, 1, 1, 'all', 1, 1),
array(5, 3, 4, null, 1, 3, 1, 1, 'all', 1, 1),
);
}
protected function getOidData()
{
// id, cid, oid, parent_oid, entries_inheriting
return array(
array(1, 1, '123', null, 1),
array(2, 2, '123', 1, 1),
array(3, 2, 'i:3:123', 1, 1),
array(4, 3, '1', 2, 1),
array(5, 3, '2', 2, 1),
);
}
protected function getOidAncestorData()
{
return array(
array(1, 1),
array(2, 1),
array(2, 2),
array(3, 1),
array(3, 3),
array(4, 2),
array(4, 1),
array(4, 4),
array(5, 2),
array(5, 1),
array(5, 5),
);
}
protected function getSidData()
{
return array(
array(1, 'SomeClass-john.doe', 1),
array(2, 'MyClass-john.doe@foo.com', 1),
array(3, 'FooClass-123', 1),
array(4, 'MooClass-ROLE_USER', 1),
array(5, 'ROLE_USER', 0),
array(6, 'IS_AUTHENTICATED_FULLY', 0),
);
}
protected function getClassData()
{
return array(
array(1, 'Bundle\SomeVendor\MyBundle\Entity\SomeEntity'),
array(2, 'Bundle\MyBundle\Entity\AnotherEntity'),
array(3, 'foo'),
);
}
protected function getOptions()
{
return array(
'oid_table_name' => 'acl_object_identities',
'oid_ancestors_table_name' => 'acl_object_identity_ancestors',
'class_table_name' => 'acl_classes',
'sid_table_name' => 'acl_security_identities',
'entry_table_name' => 'acl_entries',
);
}
protected function getStrategy()
{
return new PermissionGrantingStrategy();
}
protected function getProvider()
{
return new AclProvider($this->con, $this->getStrategy(), $this->getOptions());
}
}

View File

@ -1,573 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Tests\Dbal;
use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity;
use Symfony\Component\Security\Acl\Model\FieldEntryInterface;
use Symfony\Component\Security\Acl\Model\AuditableEntryInterface;
use Symfony\Component\Security\Acl\Model\EntryInterface;
use Symfony\Component\Security\Acl\Domain\Entry;
use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity;
use Symfony\Component\Security\Acl\Domain\Acl;
use Symfony\Component\Security\Acl\Exception\AclNotFoundException;
use Symfony\Component\Security\Acl\Exception\ConcurrentModificationException;
use Symfony\Component\Security\Acl\Dbal\AclProvider;
use Symfony\Component\Security\Acl\Domain\PermissionGrantingStrategy;
use Symfony\Component\Security\Acl\Dbal\MutableAclProvider;
use Symfony\Component\Security\Acl\Dbal\Schema;
use Doctrine\DBAL\DriverManager;
use Symfony\Component\Security\Acl\Domain\ObjectIdentity;
class MutableAclProviderTest extends \PHPUnit_Framework_TestCase
{
protected $con;
public static function assertAceEquals(EntryInterface $a, EntryInterface $b)
{
self::assertInstanceOf(get_class($a), $b);
foreach (array('getId', 'getMask', 'getStrategy', 'isGranting') as $getter) {
self::assertSame($a->$getter(), $b->$getter());
}
self::assertTrue($a->getSecurityIdentity()->equals($b->getSecurityIdentity()));
self::assertSame($a->getAcl()->getId(), $b->getAcl()->getId());
if ($a instanceof AuditableEntryInterface) {
self::assertSame($a->isAuditSuccess(), $b->isAuditSuccess());
self::assertSame($a->isAuditFailure(), $b->isAuditFailure());
}
if ($a instanceof FieldEntryInterface) {
self::assertSame($a->getField(), $b->getField());
}
}
/**
* @expectedException \Symfony\Component\Security\Acl\Exception\AclAlreadyExistsException
*/
public function testCreateAclThrowsExceptionWhenAclAlreadyExists()
{
$provider = $this->getProvider();
$oid = new ObjectIdentity('123456', 'FOO');
$provider->createAcl($oid);
$provider->createAcl($oid);
}
public function testCreateAcl()
{
$provider = $this->getProvider();
$oid = new ObjectIdentity('123456', 'FOO');
$acl = $provider->createAcl($oid);
$cachedAcl = $provider->findAcl($oid);
$this->assertInstanceOf('Symfony\Component\Security\Acl\Domain\Acl', $acl);
$this->assertSame($acl, $cachedAcl);
$this->assertTrue($acl->getObjectIdentity()->equals($oid));
}
public function testDeleteAcl()
{
$provider = $this->getProvider();
$oid = new ObjectIdentity(1, 'Foo');
$acl = $provider->createAcl($oid);
$provider->deleteAcl($oid);
$loadedAcls = $this->getField($provider, 'loadedAcls');
$this->assertCount(0, $loadedAcls['Foo']);
try {
$provider->findAcl($oid);
$this->fail('ACL has not been properly deleted.');
} catch (AclNotFoundException $e) {
}
}
public function testDeleteAclDeletesChildren()
{
$provider = $this->getProvider();
$acl = $provider->createAcl(new ObjectIdentity(1, 'Foo'));
$parentAcl = $provider->createAcl(new ObjectIdentity(2, 'Foo'));
$acl->setParentAcl($parentAcl);
$provider->updateAcl($acl);
$provider->deleteAcl($parentAcl->getObjectIdentity());
try {
$provider->findAcl(new ObjectIdentity(1, 'Foo'));
$this->fail('Child-ACLs have not been deleted.');
} catch (AclNotFoundException $e) {
}
}
public function testFindAclsAddsPropertyListener()
{
$provider = $this->getProvider();
$acl = $provider->createAcl(new ObjectIdentity(1, 'Foo'));
$propertyChanges = $this->getField($provider, 'propertyChanges');
$this->assertCount(1, $propertyChanges);
$this->assertTrue($propertyChanges->contains($acl));
$this->assertEquals(array(), $propertyChanges->offsetGet($acl));
$listeners = $this->getField($acl, 'listeners');
$this->assertSame($provider, $listeners[0]);
}
public function testFindAclsAddsPropertyListenerOnlyOnce()
{
$provider = $this->getProvider();
$acl = $provider->createAcl(new ObjectIdentity(1, 'Foo'));
$acl = $provider->findAcl(new ObjectIdentity(1, 'Foo'));
$propertyChanges = $this->getField($provider, 'propertyChanges');
$this->assertCount(1, $propertyChanges);
$this->assertTrue($propertyChanges->contains($acl));
$this->assertEquals(array(), $propertyChanges->offsetGet($acl));
$listeners = $this->getField($acl, 'listeners');
$this->assertCount(1, $listeners);
$this->assertSame($provider, $listeners[0]);
}
public function testFindAclsAddsPropertyListenerToParentAcls()
{
$provider = $this->getProvider();
$this->importAcls($provider, array(
'main' => array(
'object_identifier' => '1',
'class_type' => 'foo',
'parent_acl' => 'parent',
),
'parent' => array(
'object_identifier' => '1',
'class_type' => 'anotherFoo',
),
));
$propertyChanges = $this->getField($provider, 'propertyChanges');
$this->assertCount(0, $propertyChanges);
$acl = $provider->findAcl(new ObjectIdentity('1', 'foo'));
$this->assertCount(2, $propertyChanges);
$this->assertTrue($propertyChanges->contains($acl));
$this->assertTrue($propertyChanges->contains($acl->getParentAcl()));
}
/**
* @expectedException \InvalidArgumentException
*/
public function testPropertyChangedDoesNotTrackUnmanagedAcls()
{
$provider = $this->getProvider();
$acl = new Acl(1, new ObjectIdentity(1, 'foo'), new PermissionGrantingStrategy(), array(), false);
$provider->propertyChanged($acl, 'classAces', array(), array('foo'));
}
public function testPropertyChangedTracksChangesToAclProperties()
{
$provider = $this->getProvider();
$acl = $provider->createAcl(new ObjectIdentity(1, 'Foo'));
$propertyChanges = $this->getField($provider, 'propertyChanges');
$provider->propertyChanged($acl, 'entriesInheriting', false, true);
$changes = $propertyChanges->offsetGet($acl);
$this->assertTrue(isset($changes['entriesInheriting']));
$this->assertFalse($changes['entriesInheriting'][0]);
$this->assertTrue($changes['entriesInheriting'][1]);
$provider->propertyChanged($acl, 'entriesInheriting', true, false);
$provider->propertyChanged($acl, 'entriesInheriting', false, true);
$provider->propertyChanged($acl, 'entriesInheriting', true, false);
$changes = $propertyChanges->offsetGet($acl);
$this->assertFalse(isset($changes['entriesInheriting']));
}
public function testPropertyChangedTracksChangesToAceProperties()
{
$provider = $this->getProvider();
$acl = $provider->createAcl(new ObjectIdentity(1, 'Foo'));
$ace = new Entry(1, $acl, new UserSecurityIdentity('foo', 'FooClass'), 'all', 1, true, true, true);
$ace2 = new Entry(2, $acl, new UserSecurityIdentity('foo', 'FooClass'), 'all', 1, true, true, true);
$propertyChanges = $this->getField($provider, 'propertyChanges');
$provider->propertyChanged($ace, 'mask', 1, 3);
$changes = $propertyChanges->offsetGet($acl);
$this->assertTrue(isset($changes['aces']));
$this->assertInstanceOf('\SplObjectStorage', $changes['aces']);
$this->assertTrue($changes['aces']->contains($ace));
$aceChanges = $changes['aces']->offsetGet($ace);
$this->assertTrue(isset($aceChanges['mask']));
$this->assertEquals(1, $aceChanges['mask'][0]);
$this->assertEquals(3, $aceChanges['mask'][1]);
$provider->propertyChanged($ace, 'strategy', 'all', 'any');
$changes = $propertyChanges->offsetGet($acl);
$this->assertTrue(isset($changes['aces']));
$this->assertInstanceOf('\SplObjectStorage', $changes['aces']);
$this->assertTrue($changes['aces']->contains($ace));
$aceChanges = $changes['aces']->offsetGet($ace);
$this->assertTrue(isset($aceChanges['mask']));
$this->assertTrue(isset($aceChanges['strategy']));
$this->assertEquals('all', $aceChanges['strategy'][0]);
$this->assertEquals('any', $aceChanges['strategy'][1]);
$provider->propertyChanged($ace, 'mask', 3, 1);
$changes = $propertyChanges->offsetGet($acl);
$aceChanges = $changes['aces']->offsetGet($ace);
$this->assertFalse(isset($aceChanges['mask']));
$this->assertTrue(isset($aceChanges['strategy']));
$provider->propertyChanged($ace2, 'mask', 1, 3);
$provider->propertyChanged($ace, 'strategy', 'any', 'all');
$changes = $propertyChanges->offsetGet($acl);
$this->assertTrue(isset($changes['aces']));
$this->assertFalse($changes['aces']->contains($ace));
$this->assertTrue($changes['aces']->contains($ace2));
$provider->propertyChanged($ace2, 'mask', 3, 4);
$provider->propertyChanged($ace2, 'mask', 4, 1);
$changes = $propertyChanges->offsetGet($acl);
$this->assertFalse(isset($changes['aces']));
}
/**
* @expectedException \InvalidArgumentException
*/
public function testUpdateAclDoesNotAcceptUntrackedAcls()
{
$provider = $this->getProvider();
$acl = new Acl(1, new ObjectIdentity(1, 'Foo'), new PermissionGrantingStrategy(), array(), true);
$provider->updateAcl($acl);
}
public function testUpdateDoesNothingWhenThereAreNoChanges()
{
$con = $this->getMock('Doctrine\DBAL\Connection', array(), array(), '', false);
$con
->expects($this->never())
->method('beginTransaction')
;
$con
->expects($this->never())
->method('executeQuery')
;
$provider = new MutableAclProvider($con, new PermissionGrantingStrategy(), array());
$acl = new Acl(1, new ObjectIdentity(1, 'Foo'), new PermissionGrantingStrategy(), array(), true);
$propertyChanges = $this->getField($provider, 'propertyChanges');
$propertyChanges->offsetSet($acl, array());
$provider->updateAcl($acl);
}
public function testUpdateAclThrowsExceptionOnConcurrentModificationOfSharedProperties()
{
$provider = $this->getProvider();
$acl1 = $provider->createAcl(new ObjectIdentity(1, 'Foo'));
$acl2 = $provider->createAcl(new ObjectIdentity(2, 'Foo'));
$acl3 = $provider->createAcl(new ObjectIdentity(1, 'AnotherFoo'));
$sid = new RoleSecurityIdentity('ROLE_FOO');
$acl1->insertClassAce($sid, 1);
$acl3->insertClassAce($sid, 1);
$provider->updateAcl($acl1);
$provider->updateAcl($acl3);
$acl2->insertClassAce($sid, 16);
$provider->updateAcl($acl2);
$acl1->insertClassAce($sid, 3);
$acl2->insertClassAce($sid, 5);
try {
$provider->updateAcl($acl1);
$this->fail('Provider failed to detect a concurrent modification.');
} catch (ConcurrentModificationException $e) {
}
}
public function testUpdateAcl()
{
$provider = $this->getProvider();
$acl = $provider->createAcl(new ObjectIdentity(1, 'Foo'));
$sid = new UserSecurityIdentity('johannes', 'FooClass');
$acl->setEntriesInheriting(!$acl->isEntriesInheriting());
$acl->insertObjectAce($sid, 1);
$acl->insertClassAce($sid, 5, 0, false);
$acl->insertObjectAce($sid, 2, 1, true);
$acl->insertClassFieldAce('field', $sid, 2, 0, true);
$provider->updateAcl($acl);
$acl->updateObjectAce(0, 3);
$acl->deleteObjectAce(1);
$acl->updateObjectAuditing(0, true, false);
$acl->updateClassFieldAce(0, 'field', 15);
$provider->updateAcl($acl);
$reloadProvider = $this->getProvider();
$reloadedAcl = $reloadProvider->findAcl(new ObjectIdentity(1, 'Foo'));
$this->assertNotSame($acl, $reloadedAcl);
$this->assertSame($acl->isEntriesInheriting(), $reloadedAcl->isEntriesInheriting());
$aces = $acl->getObjectAces();
$reloadedAces = $reloadedAcl->getObjectAces();
$this->assertEquals(count($aces), count($reloadedAces));
foreach ($aces as $index => $ace) {
$this->assertAceEquals($ace, $reloadedAces[$index]);
}
}
public function testUpdateAclWorksForChangingTheParentAcl()
{
$provider = $this->getProvider();
$acl = $provider->createAcl(new ObjectIdentity(1, 'Foo'));
$parentAcl = $provider->createAcl(new ObjectIdentity(1, 'AnotherFoo'));
$acl->setParentAcl($parentAcl);
$provider->updateAcl($acl);
$reloadProvider = $this->getProvider();
$reloadedAcl = $reloadProvider->findAcl(new ObjectIdentity(1, 'Foo'));
$this->assertNotSame($acl, $reloadedAcl);
$this->assertSame($parentAcl->getId(), $reloadedAcl->getParentAcl()->getId());
}
public function testUpdateAclUpdatesChildAclsCorrectly()
{
$provider = $this->getProvider();
$acl = $provider->createAcl(new ObjectIdentity(1, 'Foo'));
$parentAcl = $provider->createAcl(new ObjectIdentity(1, 'Bar'));
$acl->setParentAcl($parentAcl);
$provider->updateAcl($acl);
$parentParentAcl = $provider->createAcl(new ObjectIdentity(1, 'Baz'));
$parentAcl->setParentAcl($parentParentAcl);
$provider->updateAcl($parentAcl);
$newParentParentAcl = $provider->createAcl(new ObjectIdentity(2, 'Baz'));
$parentAcl->setParentAcl($newParentParentAcl);
$provider->updateAcl($parentAcl);
$reloadProvider = $this->getProvider();
$reloadedAcl = $reloadProvider->findAcl(new ObjectIdentity(1, 'Foo'));
$this->assertEquals($newParentParentAcl->getId(), $reloadedAcl->getParentAcl()->getParentAcl()->getId());
}
public function testUpdateAclInsertingMultipleObjectFieldAcesThrowsDBConstraintViolations()
{
$provider = $this->getProvider();
$oid = new ObjectIdentity(1, 'Foo');
$sid1 = new UserSecurityIdentity('johannes', 'FooClass');
$sid2 = new UserSecurityIdentity('guilro', 'FooClass');
$sid3 = new UserSecurityIdentity('bmaz', 'FooClass');
$fieldName = 'fieldName';
$acl = $provider->createAcl($oid);
$acl->insertObjectFieldAce($fieldName, $sid1, 4);
$provider->updateAcl($acl);
$acl = $provider->findAcl($oid);
$acl->insertObjectFieldAce($fieldName, $sid2, 4);
$provider->updateAcl($acl);
$acl = $provider->findAcl($oid);
$acl->insertObjectFieldAce($fieldName, $sid3, 4);
$provider->updateAcl($acl);
}
public function testUpdateAclDeletingObjectFieldAcesThrowsDBConstraintViolations()
{
$provider = $this->getProvider();
$oid = new ObjectIdentity(1, 'Foo');
$sid1 = new UserSecurityIdentity('johannes', 'FooClass');
$sid2 = new UserSecurityIdentity('guilro', 'FooClass');
$sid3 = new UserSecurityIdentity('bmaz', 'FooClass');
$fieldName = 'fieldName';
$acl = $provider->createAcl($oid);
$acl->insertObjectFieldAce($fieldName, $sid1, 4);
$provider->updateAcl($acl);
$acl = $provider->findAcl($oid);
$acl->insertObjectFieldAce($fieldName, $sid2, 4);
$provider->updateAcl($acl);
$index = 0;
$acl->deleteObjectFieldAce($index, $fieldName);
$provider->updateAcl($acl);
$acl = $provider->findAcl($oid);
$acl->insertObjectFieldAce($fieldName, $sid3, 4);
$provider->updateAcl($acl);
}
public function testUpdateUserSecurityIdentity()
{
$provider = $this->getProvider();
$acl = $provider->createAcl(new ObjectIdentity(1, 'Foo'));
$sid = new UserSecurityIdentity('johannes', 'FooClass');
$acl->setEntriesInheriting(!$acl->isEntriesInheriting());
$acl->insertObjectAce($sid, 1);
$acl->insertClassAce($sid, 5, 0, false);
$acl->insertObjectAce($sid, 2, 1, true);
$acl->insertClassFieldAce('field', $sid, 2, 0, true);
$provider->updateAcl($acl);
$newSid = new UserSecurityIdentity('mathieu', 'FooClass');
$provider->updateUserSecurityIdentity($newSid, 'johannes');
$reloadProvider = $this->getProvider();
$reloadedAcl = $reloadProvider->findAcl(new ObjectIdentity(1, 'Foo'));
$this->assertNotSame($acl, $reloadedAcl);
$this->assertSame($acl->isEntriesInheriting(), $reloadedAcl->isEntriesInheriting());
$aces = $acl->getObjectAces();
$reloadedAces = $reloadedAcl->getObjectAces();
$this->assertEquals(count($aces), count($reloadedAces));
foreach ($reloadedAces as $ace) {
$this->assertTrue($ace->getSecurityIdentity()->equals($newSid));
}
}
/**
* Imports acls.
*
* Data must have the following format:
* array(
* *name* => array(
* 'object_identifier' => *required*
* 'class_type' => *required*,
* 'parent_acl' => *name (optional)*
* ),
* )
*
* @param AclProvider $provider
* @param array $data
*
* @throws \InvalidArgumentException
* @throws \Exception
*/
protected function importAcls(AclProvider $provider, array $data)
{
$aclIds = $parentAcls = array();
$con = $this->getField($provider, 'connection');
$con->beginTransaction();
try {
foreach ($data as $name => $aclData) {
if (!isset($aclData['object_identifier'], $aclData['class_type'])) {
throw new \InvalidArgumentException('"object_identifier", and "class_type" must be present.');
}
$this->callMethod($provider, 'createObjectIdentity', array(new ObjectIdentity($aclData['object_identifier'], $aclData['class_type'])));
$aclId = $con->lastInsertId();
$aclIds[$name] = $aclId;
$sql = $this->callMethod($provider, 'getInsertObjectIdentityRelationSql', array($aclId, $aclId));
$con->executeQuery($sql);
if (isset($aclData['parent_acl'])) {
if (isset($aclIds[$aclData['parent_acl']])) {
$con->executeQuery('UPDATE acl_object_identities SET parent_object_identity_id = '.$aclIds[$aclData['parent_acl']].' WHERE id = '.$aclId);
$con->executeQuery($this->callMethod($provider, 'getInsertObjectIdentityRelationSql', array($aclId, $aclIds[$aclData['parent_acl']])));
} else {
$parentAcls[$aclId] = $aclData['parent_acl'];
}
}
}
foreach ($parentAcls as $aclId => $name) {
if (!isset($aclIds[$name])) {
throw new \InvalidArgumentException(sprintf('"%s" does not exist.', $name));
}
$con->executeQuery(sprintf('UPDATE acl_object_identities SET parent_object_identity_id = %d WHERE id = %d', $aclIds[$name], $aclId));
$con->executeQuery($this->callMethod($provider, 'getInsertObjectIdentityRelationSql', array($aclId, $aclIds[$name])));
}
$con->commit();
} catch (\Exception $e) {
$con->rollBack();
throw $e;
}
}
protected function callMethod($object, $method, array $args)
{
$method = new \ReflectionMethod($object, $method);
$method->setAccessible(true);
return $method->invokeArgs($object, $args);
}
protected function setUp()
{
if (!class_exists('PDO') || !in_array('sqlite', \PDO::getAvailableDrivers())) {
self::markTestSkipped('This test requires SQLite support in your environment');
}
$this->con = DriverManager::getConnection(array(
'driver' => 'pdo_sqlite',
'memory' => true,
));
// import the schema
$schema = new Schema($this->getOptions());
foreach ($schema->toSql($this->con->getDatabasePlatform()) as $sql) {
$this->con->exec($sql);
}
}
protected function tearDown()
{
$this->con = null;
}
protected function getField($object, $field)
{
$reflection = new \ReflectionProperty($object, $field);
$reflection->setAccessible(true);
return $reflection->getValue($object);
}
public function setField($object, $field, $value)
{
$reflection = new \ReflectionProperty($object, $field);
$reflection->setAccessible(true);
$reflection->setValue($object, $value);
$reflection->setAccessible(false);
}
protected function getOptions()
{
return array(
'oid_table_name' => 'acl_object_identities',
'oid_ancestors_table_name' => 'acl_object_identity_ancestors',
'class_table_name' => 'acl_classes',
'sid_table_name' => 'acl_security_identities',
'entry_table_name' => 'acl_entries',
);
}
protected function getStrategy()
{
return new PermissionGrantingStrategy();
}
protected function getProvider($cache = null)
{
return new MutableAclProvider($this->con, $this->getStrategy(), $this->getOptions(), $cache);
}
}

View File

@ -1,513 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Tests\Domain;
use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity;
use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity;
use Symfony\Component\Security\Acl\Domain\PermissionGrantingStrategy;
use Symfony\Component\Security\Acl\Domain\ObjectIdentity;
use Symfony\Component\Security\Acl\Domain\Acl;
class AclTest extends \PHPUnit_Framework_TestCase
{
public function testConstructor()
{
$acl = new Acl(1, $oid = new ObjectIdentity('foo', 'foo'), $permissionStrategy = new PermissionGrantingStrategy(), array(), true);
$this->assertSame(1, $acl->getId());
$this->assertSame($oid, $acl->getObjectIdentity());
$this->assertNull($acl->getParentAcl());
$this->assertTrue($acl->isEntriesInheriting());
}
/**
* @expectedException \OutOfBoundsException
* @dataProvider getDeleteAceTests
*/
public function testDeleteAceThrowsExceptionOnInvalidIndex($type)
{
$acl = $this->getAcl();
$acl->{'delete'.$type.'Ace'}(0);
}
/**
* @dataProvider getDeleteAceTests
*/
public function testDeleteAce($type)
{
$acl = $this->getAcl();
$acl->{'insert'.$type.'Ace'}(new RoleSecurityIdentity('foo'), 1);
$acl->{'insert'.$type.'Ace'}(new RoleSecurityIdentity('foo'), 2, 1);
$acl->{'insert'.$type.'Ace'}(new RoleSecurityIdentity('foo'), 3, 2);
$listener = $this->getListener(array(
$type.'Aces', 'aceOrder', 'aceOrder', $type.'Aces',
));
$acl->addPropertyChangedListener($listener);
$this->assertCount(3, $acl->{'get'.$type.'Aces'}());
$acl->{'delete'.$type.'Ace'}(0);
$this->assertCount(2, $aces = $acl->{'get'.$type.'Aces'}());
$this->assertEquals(2, $aces[0]->getMask());
$this->assertEquals(3, $aces[1]->getMask());
$acl->{'delete'.$type.'Ace'}(1);
$this->assertCount(1, $aces = $acl->{'get'.$type.'Aces'}());
$this->assertEquals(2, $aces[0]->getMask());
}
public function getDeleteAceTests()
{
return array(
array('class'),
array('object'),
);
}
/**
* @expectedException \OutOfBoundsException
* @dataProvider getDeleteFieldAceTests
*/
public function testDeleteFieldAceThrowsExceptionOnInvalidIndex($type)
{
$acl = $this->getAcl();
$acl->{'delete'.$type.'Ace'}('foo', 0);
}
/**
* @dataProvider getDeleteFieldAceTests
*/
public function testDeleteFieldAce($type)
{
$acl = $this->getAcl();
$acl->{'insert'.$type.'Ace'}('foo', new RoleSecurityIdentity('foo'), 1, 0);
$acl->{'insert'.$type.'Ace'}('foo', new RoleSecurityIdentity('foo'), 2, 1);
$acl->{'insert'.$type.'Ace'}('foo', new RoleSecurityIdentity('foo'), 3, 2);
$listener = $this->getListener(array(
$type.'Aces', 'aceOrder', 'aceOrder', $type.'Aces',
));
$acl->addPropertyChangedListener($listener);
$this->assertCount(3, $acl->{'get'.$type.'Aces'}('foo'));
$acl->{'delete'.$type.'Ace'}(0, 'foo');
$this->assertCount(2, $aces = $acl->{'get'.$type.'Aces'}('foo'));
$this->assertEquals(2, $aces[0]->getMask());
$this->assertEquals(3, $aces[1]->getMask());
$acl->{'delete'.$type.'Ace'}(1, 'foo');
$this->assertCount(1, $aces = $acl->{'get'.$type.'Aces'}('foo'));
$this->assertEquals(2, $aces[0]->getMask());
}
public function getDeleteFieldAceTests()
{
return array(
array('classField'),
array('objectField'),
);
}
/**
* @dataProvider getInsertAceTests
*/
public function testInsertAce($property, $method)
{
$acl = $this->getAcl();
$listener = $this->getListener(array(
$property, 'aceOrder', $property, 'aceOrder', $property,
));
$acl->addPropertyChangedListener($listener);
$sid = new RoleSecurityIdentity('foo');
$acl->$method($sid, 1);
$acl->$method($sid, 2);
$acl->$method($sid, 3, 1, false);
$this->assertCount(3, $aces = $acl->{'get'.$property}());
$this->assertEquals(2, $aces[0]->getMask());
$this->assertEquals(3, $aces[1]->getMask());
$this->assertEquals(1, $aces[2]->getMask());
}
/**
* @expectedException \OutOfBoundsException
* @dataProvider getInsertAceTests
*/
public function testInsertClassAceThrowsExceptionOnInvalidIndex($property, $method)
{
$acl = $this->getAcl();
$acl->$method(new RoleSecurityIdentity('foo'), 1, 1);
}
public function getInsertAceTests()
{
return array(
array('classAces', 'insertClassAce'),
array('objectAces', 'insertObjectAce'),
);
}
/**
* @dataProvider getInsertFieldAceTests
*/
public function testInsertClassFieldAce($property, $method)
{
$acl = $this->getAcl();
$listener = $this->getListener(array(
$property, $property, 'aceOrder', $property,
'aceOrder', 'aceOrder', $property,
));
$acl->addPropertyChangedListener($listener);
$sid = new RoleSecurityIdentity('foo');
$acl->$method('foo', $sid, 1);
$acl->$method('foo2', $sid, 1);
$acl->$method('foo', $sid, 3);
$acl->$method('foo', $sid, 2);
$this->assertCount(3, $aces = $acl->{'get'.$property}('foo'));
$this->assertCount(1, $acl->{'get'.$property}('foo2'));
$this->assertEquals(2, $aces[0]->getMask());
$this->assertEquals(3, $aces[1]->getMask());
$this->assertEquals(1, $aces[2]->getMask());
}
/**
* @expectedException \OutOfBoundsException
* @dataProvider getInsertFieldAceTests
*/
public function testInsertClassFieldAceThrowsExceptionOnInvalidIndex($property, $method)
{
$acl = $this->getAcl();
$acl->$method('foo', new RoleSecurityIdentity('foo'), 1, 1);
}
public function getInsertFieldAceTests()
{
return array(
array('classFieldAces', 'insertClassFieldAce'),
array('objectFieldAces', 'insertObjectFieldAce'),
);
}
public function testIsFieldGranted()
{
$sids = array(new RoleSecurityIdentity('ROLE_FOO'), new RoleSecurityIdentity('ROLE_IDDQD'));
$masks = array(1, 2, 4);
$strategy = $this->getMock('Symfony\Component\Security\Acl\Model\PermissionGrantingStrategyInterface');
$acl = new Acl(1, new ObjectIdentity(1, 'foo'), $strategy, array(), true);
$strategy
->expects($this->once())
->method('isFieldGranted')
->with($this->equalTo($acl), $this->equalTo('foo'), $this->equalTo($masks), $this->equalTo($sids), $this->isTrue())
->will($this->returnValue(true))
;
$this->assertTrue($acl->isFieldGranted('foo', $masks, $sids, true));
}
public function testIsGranted()
{
$sids = array(new RoleSecurityIdentity('ROLE_FOO'), new RoleSecurityIdentity('ROLE_IDDQD'));
$masks = array(1, 2, 4);
$strategy = $this->getMock('Symfony\Component\Security\Acl\Model\PermissionGrantingStrategyInterface');
$acl = new Acl(1, new ObjectIdentity(1, 'foo'), $strategy, array(), true);
$strategy
->expects($this->once())
->method('isGranted')
->with($this->equalTo($acl), $this->equalTo($masks), $this->equalTo($sids), $this->isTrue())
->will($this->returnValue(true))
;
$this->assertTrue($acl->isGranted($masks, $sids, true));
}
public function testSetGetParentAcl()
{
$acl = $this->getAcl();
$parentAcl = $this->getAcl();
$listener = $this->getListener(array('parentAcl'));
$acl->addPropertyChangedListener($listener);
$this->assertNull($acl->getParentAcl());
$acl->setParentAcl($parentAcl);
$this->assertSame($parentAcl, $acl->getParentAcl());
$acl->setParentAcl(null);
$this->assertNull($acl->getParentAcl());
}
public function testSetIsEntriesInheriting()
{
$acl = $this->getAcl();
$listener = $this->getListener(array('entriesInheriting'));
$acl->addPropertyChangedListener($listener);
$this->assertTrue($acl->isEntriesInheriting());
$acl->setEntriesInheriting(false);
$this->assertFalse($acl->isEntriesInheriting());
}
public function testIsSidLoadedWhenAllSidsAreLoaded()
{
$acl = $this->getAcl();
$this->assertTrue($acl->isSidLoaded(new UserSecurityIdentity('foo', 'Foo')));
$this->assertTrue($acl->isSidLoaded(new RoleSecurityIdentity('ROLE_FOO', 'Foo')));
}
public function testIsSidLoaded()
{
$acl = new Acl(1, new ObjectIdentity('1', 'foo'), new PermissionGrantingStrategy(), array(new UserSecurityIdentity('foo', 'Foo'), new UserSecurityIdentity('johannes', 'Bar')), true);
$this->assertTrue($acl->isSidLoaded(new UserSecurityIdentity('foo', 'Foo')));
$this->assertTrue($acl->isSidLoaded(new UserSecurityIdentity('johannes', 'Bar')));
$this->assertTrue($acl->isSidLoaded(array(
new UserSecurityIdentity('foo', 'Foo'),
new UserSecurityIdentity('johannes', 'Bar'),
)));
$this->assertFalse($acl->isSidLoaded(new RoleSecurityIdentity('ROLE_FOO')));
$this->assertFalse($acl->isSidLoaded(new UserSecurityIdentity('schmittjoh@gmail.com', 'Moo')));
$this->assertFalse($acl->isSidLoaded(array(
new UserSecurityIdentity('foo', 'Foo'),
new UserSecurityIdentity('johannes', 'Bar'),
new RoleSecurityIdentity('ROLE_FOO'),
)));
}
/**
* @dataProvider getUpdateAceTests
* @expectedException \OutOfBoundsException
*/
public function testUpdateAceThrowsOutOfBoundsExceptionOnInvalidIndex($type)
{
$acl = $this->getAcl();
$acl->{'update'.$type}(0, 1);
}
/**
* @dataProvider getUpdateAceTests
*/
public function testUpdateAce($type)
{
$acl = $this->getAcl();
$acl->{'insert'.$type}(new RoleSecurityIdentity('foo'), 1);
$listener = $this->getListener(array(
'mask', 'mask', 'strategy',
));
$acl->addPropertyChangedListener($listener);
$aces = $acl->{'get'.$type.'s'}();
$ace = reset($aces);
$this->assertEquals(1, $ace->getMask());
$this->assertEquals('all', $ace->getStrategy());
$acl->{'update'.$type}(0, 3);
$this->assertEquals(3, $ace->getMask());
$this->assertEquals('all', $ace->getStrategy());
$acl->{'update'.$type}(0, 1, 'foo');
$this->assertEquals(1, $ace->getMask());
$this->assertEquals('foo', $ace->getStrategy());
}
public function getUpdateAceTests()
{
return array(
array('classAce'),
array('objectAce'),
);
}
/**
* @dataProvider getUpdateFieldAceTests
* @expectedException \OutOfBoundsException
*/
public function testUpdateFieldAceThrowsExceptionOnInvalidIndex($type)
{
$acl = $this->getAcl();
$acl->{'update'.$type}(0, 'foo', 1);
}
/**
* @dataProvider getUpdateFieldAceTests
*/
public function testUpdateFieldAce($type)
{
$acl = $this->getAcl();
$acl->{'insert'.$type}('foo', new UserSecurityIdentity('foo', 'Foo'), 1);
$listener = $this->getListener(array(
'mask', 'mask', 'strategy',
));
$acl->addPropertyChangedListener($listener);
$aces = $acl->{'get'.$type.'s'}('foo');
$ace = reset($aces);
$this->assertEquals(1, $ace->getMask());
$this->assertEquals('all', $ace->getStrategy());
$acl->{'update'.$type}(0, 'foo', 3);
$this->assertEquals(3, $ace->getMask());
$this->assertEquals('all', $ace->getStrategy());
$acl->{'update'.$type}(0, 'foo', 1, 'foo');
$this->assertEquals(1, $ace->getMask());
$this->assertEquals('foo', $ace->getStrategy());
}
public function getUpdateFieldAceTests()
{
return array(
array('classFieldAce'),
array('objectFieldAce'),
);
}
/**
* @dataProvider getUpdateAuditingTests
* @expectedException \OutOfBoundsException
*/
public function testUpdateAuditingThrowsExceptionOnInvalidIndex($type)
{
$acl = $this->getAcl();
$acl->{'update'.$type.'Auditing'}(0, true, false);
}
/**
* @dataProvider getUpdateAuditingTests
*/
public function testUpdateAuditing($type)
{
$acl = $this->getAcl();
$acl->{'insert'.$type.'Ace'}(new RoleSecurityIdentity('foo'), 1);
$listener = $this->getListener(array(
'auditFailure', 'auditSuccess', 'auditFailure',
));
$acl->addPropertyChangedListener($listener);
$aces = $acl->{'get'.$type.'Aces'}();
$ace = reset($aces);
$this->assertFalse($ace->isAuditSuccess());
$this->assertFalse($ace->isAuditFailure());
$acl->{'update'.$type.'Auditing'}(0, false, true);
$this->assertFalse($ace->isAuditSuccess());
$this->assertTrue($ace->isAuditFailure());
$acl->{'update'.$type.'Auditing'}(0, true, false);
$this->assertTrue($ace->isAuditSuccess());
$this->assertFalse($ace->isAuditFailure());
}
public function getUpdateAuditingTests()
{
return array(
array('class'),
array('object'),
);
}
/**
* @expectedException \InvalidArgumentException
* @dataProvider getUpdateFieldAuditingTests
*/
public function testUpdateFieldAuditingThrowsExceptionOnInvalidField($type)
{
$acl = $this->getAcl();
$acl->{'update'.$type.'Auditing'}(0, 'foo', true, true);
}
/**
* @expectedException \OutOfBoundsException
* @dataProvider getUpdateFieldAuditingTests
*/
public function testUpdateFieldAuditingThrowsExceptionOnInvalidIndex($type)
{
$acl = $this->getAcl();
$acl->{'insert'.$type.'Ace'}('foo', new RoleSecurityIdentity('foo'), 1);
$acl->{'update'.$type.'Auditing'}(1, 'foo', true, false);
}
/**
* @dataProvider getUpdateFieldAuditingTests
*/
public function testUpdateFieldAuditing($type)
{
$acl = $this->getAcl();
$acl->{'insert'.$type.'Ace'}('foo', new RoleSecurityIdentity('foo'), 1);
$listener = $this->getListener(array(
'auditSuccess', 'auditSuccess', 'auditFailure',
));
$acl->addPropertyChangedListener($listener);
$aces = $acl->{'get'.$type.'Aces'}('foo');
$ace = reset($aces);
$this->assertFalse($ace->isAuditSuccess());
$this->assertFalse($ace->isAuditFailure());
$acl->{'update'.$type.'Auditing'}(0, 'foo', true, false);
$this->assertTrue($ace->isAuditSuccess());
$this->assertFalse($ace->isAuditFailure());
$acl->{'update'.$type.'Auditing'}(0, 'foo', false, true);
$this->assertFalse($ace->isAuditSuccess());
$this->assertTrue($ace->isAuditFailure());
}
public function getUpdateFieldAuditingTests()
{
return array(
array('classField'),
array('objectField'),
);
}
protected function getListener($expectedChanges)
{
$aceProperties = array('aceOrder', 'mask', 'strategy', 'auditSuccess', 'auditFailure');
$listener = $this->getMock('Doctrine\Common\PropertyChangedListener');
foreach ($expectedChanges as $index => $property) {
if (in_array($property, $aceProperties)) {
$class = 'Symfony\Component\Security\Acl\Domain\Entry';
} else {
$class = 'Symfony\Component\Security\Acl\Domain\Acl';
}
$listener
->expects($this->at($index))
->method('propertyChanged')
->with($this->isInstanceOf($class), $this->equalTo($property))
;
}
return $listener;
}
protected function getAcl()
{
return new Acl(1, new ObjectIdentity(1, 'foo'), new PermissionGrantingStrategy(), array(), true);
}
}

View File

@ -1,83 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Tests\Domain;
class AuditLoggerTest extends \PHPUnit_Framework_TestCase
{
/**
* @dataProvider getTestLogData
*/
public function testLogIfNeeded($granting, $audit)
{
$logger = $this->getLogger();
$ace = $this->getEntry();
if (true === $granting) {
$ace
->expects($this->once())
->method('isAuditSuccess')
->will($this->returnValue($audit))
;
$ace
->expects($this->never())
->method('isAuditFailure')
;
} else {
$ace
->expects($this->never())
->method('isAuditSuccess')
;
$ace
->expects($this->once())
->method('isAuditFailure')
->will($this->returnValue($audit))
;
}
if (true === $audit) {
$logger
->expects($this->once())
->method('doLog')
->with($this->equalTo($granting), $this->equalTo($ace))
;
} else {
$logger
->expects($this->never())
->method('doLog')
;
}
$logger->logIfNeeded($granting, $ace);
}
public function getTestLogData()
{
return array(
array(true, false),
array(true, true),
array(false, false),
array(false, true),
);
}
protected function getEntry()
{
return $this->getMock('Symfony\Component\Security\Acl\Model\AuditableEntryInterface');
}
protected function getLogger()
{
return $this->getMockForAbstractClass('Symfony\Component\Security\Acl\Domain\AuditLogger');
}
}

View File

@ -1,101 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Tests\Domain;
use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity;
use Symfony\Component\Security\Acl\Domain\ObjectIdentity;
use Symfony\Component\Security\Acl\Domain\PermissionGrantingStrategy;
use Symfony\Component\Security\Acl\Domain\Acl;
use Symfony\Component\Security\Acl\Domain\DoctrineAclCache;
use Doctrine\Common\Cache\ArrayCache;
class DoctrineAclCacheTest extends \PHPUnit_Framework_TestCase
{
protected $permissionGrantingStrategy;
/**
* @expectedException \InvalidArgumentException
* @dataProvider getEmptyValue
*/
public function testConstructorDoesNotAcceptEmptyPrefix($empty)
{
new DoctrineAclCache(new ArrayCache(), $this->getPermissionGrantingStrategy(), $empty);
}
public function getEmptyValue()
{
return array(
array(null),
array(false),
array(''),
);
}
public function test()
{
$cache = $this->getCache();
$aclWithParent = $this->getAcl(1);
$acl = $this->getAcl();
$cache->putInCache($aclWithParent);
$cache->putInCache($acl);
$cachedAcl = $cache->getFromCacheByIdentity($acl->getObjectIdentity());
$this->assertEquals($acl->getId(), $cachedAcl->getId());
$this->assertNull($acl->getParentAcl());
$cachedAclWithParent = $cache->getFromCacheByIdentity($aclWithParent->getObjectIdentity());
$this->assertEquals($aclWithParent->getId(), $cachedAclWithParent->getId());
$this->assertNotNull($cachedParentAcl = $cachedAclWithParent->getParentAcl());
$this->assertEquals($aclWithParent->getParentAcl()->getId(), $cachedParentAcl->getId());
}
protected function getAcl($depth = 0)
{
static $id = 1;
$acl = new Acl($id, new ObjectIdentity($id, 'foo'), $this->getPermissionGrantingStrategy(), array(), $depth > 0);
// insert some ACEs
$sid = new UserSecurityIdentity('johannes', 'Foo');
$acl->insertClassAce($sid, 1);
$acl->insertClassFieldAce('foo', $sid, 1);
$acl->insertObjectAce($sid, 1);
$acl->insertObjectFieldAce('foo', $sid, 1);
++$id;
if ($depth > 0) {
$acl->setParentAcl($this->getAcl($depth - 1));
}
return $acl;
}
protected function getPermissionGrantingStrategy()
{
if (null === $this->permissionGrantingStrategy) {
$this->permissionGrantingStrategy = new PermissionGrantingStrategy();
}
return $this->permissionGrantingStrategy;
}
protected function getCache($cacheDriver = null, $prefix = DoctrineAclCache::PREFIX)
{
if (null === $cacheDriver) {
$cacheDriver = new ArrayCache();
}
return new DoctrineAclCache($cacheDriver, $this->getPermissionGrantingStrategy(), $prefix);
}
}

View File

@ -1,119 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Tests\Domain;
use Symfony\Component\Security\Acl\Domain\Entry;
class EntryTest extends \PHPUnit_Framework_TestCase
{
public function testConstructor()
{
$ace = $this->getAce($acl = $this->getAcl(), $sid = $this->getSid());
$this->assertEquals(123, $ace->getId());
$this->assertSame($acl, $ace->getAcl());
$this->assertSame($sid, $ace->getSecurityIdentity());
$this->assertEquals('foostrat', $ace->getStrategy());
$this->assertEquals(123456, $ace->getMask());
$this->assertTrue($ace->isGranting());
$this->assertTrue($ace->isAuditSuccess());
$this->assertFalse($ace->isAuditFailure());
}
public function testSetAuditSuccess()
{
$ace = $this->getAce();
$this->assertTrue($ace->isAuditSuccess());
$ace->setAuditSuccess(false);
$this->assertFalse($ace->isAuditSuccess());
$ace->setAuditSuccess(true);
$this->assertTrue($ace->isAuditSuccess());
}
public function testSetAuditFailure()
{
$ace = $this->getAce();
$this->assertFalse($ace->isAuditFailure());
$ace->setAuditFailure(true);
$this->assertTrue($ace->isAuditFailure());
$ace->setAuditFailure(false);
$this->assertFalse($ace->isAuditFailure());
}
public function testSetMask()
{
$ace = $this->getAce();
$this->assertEquals(123456, $ace->getMask());
$ace->setMask(4321);
$this->assertEquals(4321, $ace->getMask());
}
public function testSetStrategy()
{
$ace = $this->getAce();
$this->assertEquals('foostrat', $ace->getStrategy());
$ace->setStrategy('foo');
$this->assertEquals('foo', $ace->getStrategy());
}
public function testSerializeUnserialize()
{
$ace = $this->getAce();
$serialized = serialize($ace);
$uAce = unserialize($serialized);
$this->assertNull($uAce->getAcl());
$this->assertInstanceOf('Symfony\Component\Security\Acl\Model\SecurityIdentityInterface', $uAce->getSecurityIdentity());
$this->assertEquals($ace->getId(), $uAce->getId());
$this->assertEquals($ace->getMask(), $uAce->getMask());
$this->assertEquals($ace->getStrategy(), $uAce->getStrategy());
$this->assertEquals($ace->isGranting(), $uAce->isGranting());
$this->assertEquals($ace->isAuditSuccess(), $uAce->isAuditSuccess());
$this->assertEquals($ace->isAuditFailure(), $uAce->isAuditFailure());
}
protected function getAce($acl = null, $sid = null)
{
if (null === $acl) {
$acl = $this->getAcl();
}
if (null === $sid) {
$sid = $this->getSid();
}
return new Entry(
123,
$acl,
$sid,
'foostrat',
123456,
true,
false,
true
);
}
protected function getAcl()
{
return $this->getMock('Symfony\Component\Security\Acl\Model\AclInterface');
}
protected function getSid()
{
return $this->getMock('Symfony\Component\Security\Acl\Model\SecurityIdentityInterface');
}
}

View File

@ -1,74 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Tests\Domain;
use Symfony\Component\Security\Acl\Domain\FieldEntry;
class FieldEntryTest extends \PHPUnit_Framework_TestCase
{
public function testConstructor()
{
$ace = $this->getAce();
$this->assertEquals('foo', $ace->getField());
}
public function testSerializeUnserialize()
{
$ace = $this->getAce();
$serialized = serialize($ace);
$uAce = unserialize($serialized);
$this->assertNull($uAce->getAcl());
$this->assertInstanceOf('Symfony\Component\Security\Acl\Model\SecurityIdentityInterface', $uAce->getSecurityIdentity());
$this->assertEquals($ace->getId(), $uAce->getId());
$this->assertEquals($ace->getField(), $uAce->getField());
$this->assertEquals($ace->getMask(), $uAce->getMask());
$this->assertEquals($ace->getStrategy(), $uAce->getStrategy());
$this->assertEquals($ace->isGranting(), $uAce->isGranting());
$this->assertEquals($ace->isAuditSuccess(), $uAce->isAuditSuccess());
$this->assertEquals($ace->isAuditFailure(), $uAce->isAuditFailure());
}
protected function getAce($acl = null, $sid = null)
{
if (null === $acl) {
$acl = $this->getAcl();
}
if (null === $sid) {
$sid = $this->getSid();
}
return new FieldEntry(
123,
$acl,
'foo',
$sid,
'foostrat',
123456,
true,
false,
true
);
}
protected function getAcl()
{
return $this->getMock('Symfony\Component\Security\Acl\Model\AclInterface');
}
protected function getSid()
{
return $this->getMock('Symfony\Component\Security\Acl\Model\SecurityIdentityInterface');
}
}

View File

@ -1,41 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Tests\Domain;
use Symfony\Component\Security\Acl\Domain\ObjectIdentityRetrievalStrategy;
class ObjectIdentityRetrievalStrategyTest extends \PHPUnit_Framework_TestCase
{
public function testGetObjectIdentityReturnsNullForInvalidDomainObject()
{
$strategy = new ObjectIdentityRetrievalStrategy();
$this->assertNull($strategy->getObjectIdentity('foo'));
}
public function testGetObjectIdentity()
{
$strategy = new ObjectIdentityRetrievalStrategy();
$domainObject = new DomainObject();
$objectIdentity = $strategy->getObjectIdentity($domainObject);
$this->assertEquals($domainObject->getId(), $objectIdentity->getIdentifier());
$this->assertEquals(get_class($domainObject), $objectIdentity->getType());
}
}
class DomainObject
{
public function getId()
{
return 'foo';
}
}

View File

@ -1,131 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Tests\Domain
{
use Symfony\Component\Security\Acl\Domain\ObjectIdentity;
class ObjectIdentityTest extends \PHPUnit_Framework_TestCase
{
public function testConstructor()
{
$id = new ObjectIdentity('fooid', 'footype');
$this->assertEquals('fooid', $id->getIdentifier());
$this->assertEquals('footype', $id->getType());
}
// Test that constructor never changes passed type, even with proxies
public function testConstructorWithProxy()
{
$id = new ObjectIdentity('fooid', 'Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Acl\Tests\Domain\TestDomainObject');
$this->assertEquals('fooid', $id->getIdentifier());
$this->assertEquals('Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Acl\Tests\Domain\TestDomainObject', $id->getType());
}
public function testFromDomainObjectPrefersInterfaceOverGetId()
{
$domainObject = $this->getMock('Symfony\Component\Security\Acl\Model\DomainObjectInterface');
$domainObject
->expects($this->once())
->method('getObjectIdentifier')
->will($this->returnValue('getObjectIdentifier()'))
;
$domainObject
->expects($this->never())
->method('getId')
->will($this->returnValue('getId()'))
;
$id = ObjectIdentity::fromDomainObject($domainObject);
$this->assertEquals('getObjectIdentifier()', $id->getIdentifier());
}
public function testFromDomainObjectWithoutInterface()
{
$id = ObjectIdentity::fromDomainObject(new TestDomainObject());
$this->assertEquals('getId()', $id->getIdentifier());
$this->assertEquals('Symfony\Component\Security\Acl\Tests\Domain\TestDomainObject', $id->getType());
}
public function testFromDomainObjectWithProxy()
{
$id = ObjectIdentity::fromDomainObject(new \Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Acl\Tests\Domain\TestDomainObject());
$this->assertEquals('getId()', $id->getIdentifier());
$this->assertEquals('Symfony\Component\Security\Acl\Tests\Domain\TestDomainObject', $id->getType());
}
public function testFromDomainObjectWithoutInterfaceEnforcesStringIdentifier()
{
$domainObject = new TestDomainObject();
$domainObject->id = 1;
$id = ObjectIdentity::fromDomainObject($domainObject);
$this->assertSame('1', $id->getIdentifier());
$this->assertEquals('Symfony\Component\Security\Acl\Tests\Domain\TestDomainObject', $id->getType());
}
public function testFromDomainObjectWithoutInterfaceAllowsZeroAsIdentifier()
{
$domainObject = new TestDomainObject();
$domainObject->id = '0';
$id = ObjectIdentity::fromDomainObject($domainObject);
$this->assertSame('0', $id->getIdentifier());
$this->assertEquals('Symfony\Component\Security\Acl\Tests\Domain\TestDomainObject', $id->getType());
}
/**
* @dataProvider getCompareData
*/
public function testEquals($oid1, $oid2, $equal)
{
if ($equal) {
$this->assertTrue($oid1->equals($oid2));
} else {
$this->assertFalse($oid1->equals($oid2));
}
}
public function getCompareData()
{
return array(
array(new ObjectIdentity('123', 'foo'), new ObjectIdentity('123', 'foo'), true),
array(new ObjectIdentity('123', 'foo'), new ObjectIdentity(123, 'foo'), true),
array(new ObjectIdentity('1', 'foo'), new ObjectIdentity('2', 'foo'), false),
array(new ObjectIdentity('1', 'bla'), new ObjectIdentity('1', 'blub'), false),
);
}
}
class TestDomainObject
{
public $id = 'getId()';
public function getObjectIdentifier()
{
return 'getObjectIdentifier()';
}
public function getId()
{
return $this->id;
}
}
}
namespace Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Acl\Tests\Domain
{
class TestDomainObject extends \Symfony\Component\Security\Acl\Tests\Domain\TestDomainObject
{
}
}

View File

@ -1,186 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Tests\Domain;
use Symfony\Component\Security\Acl\Domain\ObjectIdentity;
use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity;
use Symfony\Component\Security\Acl\Domain\Acl;
use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity;
use Symfony\Component\Security\Acl\Domain\PermissionGrantingStrategy;
use Symfony\Component\Security\Acl\Exception\NoAceFoundException;
class PermissionGrantingStrategyTest extends \PHPUnit_Framework_TestCase
{
public function testIsGrantedObjectAcesHavePriority()
{
$strategy = new PermissionGrantingStrategy();
$acl = $this->getAcl($strategy);
$sid = new UserSecurityIdentity('johannes', 'Foo');
$acl->insertClassAce($sid, 1);
$acl->insertObjectAce($sid, 1, 0, false);
$this->assertFalse($strategy->isGranted($acl, array(1), array($sid)));
}
public function testIsGrantedFallsBackToClassAcesIfNoApplicableObjectAceWasFound()
{
$strategy = new PermissionGrantingStrategy();
$acl = $this->getAcl($strategy);
$sid = new UserSecurityIdentity('johannes', 'Foo');
$acl->insertClassAce($sid, 1);
$this->assertTrue($strategy->isGranted($acl, array(1), array($sid)));
}
public function testIsGrantedFavorsLocalAcesOverParentAclAces()
{
$strategy = new PermissionGrantingStrategy();
$sid = new UserSecurityIdentity('johannes', 'Foo');
$acl = $this->getAcl($strategy);
$acl->insertClassAce($sid, 1);
$parentAcl = $this->getAcl($strategy);
$acl->setParentAcl($parentAcl);
$parentAcl->insertClassAce($sid, 1, 0, false);
$this->assertTrue($strategy->isGranted($acl, array(1), array($sid)));
}
public function testIsGrantedFallsBackToParentAcesIfNoLocalAcesAreApplicable()
{
$strategy = new PermissionGrantingStrategy();
$sid = new UserSecurityIdentity('johannes', 'Foo');
$anotherSid = new UserSecurityIdentity('ROLE_USER', 'Foo');
$acl = $this->getAcl($strategy);
$acl->insertClassAce($anotherSid, 1, 0, false);
$parentAcl = $this->getAcl($strategy);
$acl->setParentAcl($parentAcl);
$parentAcl->insertClassAce($sid, 1);
$this->assertTrue($strategy->isGranted($acl, array(1), array($sid)));
}
/**
* @expectedException \Symfony\Component\Security\Acl\Exception\NoAceFoundException
*/
public function testIsGrantedReturnsExceptionIfNoAceIsFound()
{
$strategy = new PermissionGrantingStrategy();
$acl = $this->getAcl($strategy);
$sid = new UserSecurityIdentity('johannes', 'Foo');
$strategy->isGranted($acl, array(1), array($sid));
}
public function testIsGrantedFirstApplicableEntryMakesUltimateDecisionForPermissionIdentityCombination()
{
$strategy = new PermissionGrantingStrategy();
$acl = $this->getAcl($strategy);
$sid = new UserSecurityIdentity('johannes', 'Foo');
$aSid = new RoleSecurityIdentity('ROLE_USER');
$acl->insertClassAce($aSid, 1);
$acl->insertClassAce($sid, 1, 1, false);
$acl->insertClassAce($sid, 1, 2);
$this->assertFalse($strategy->isGranted($acl, array(1), array($sid, $aSid)));
$acl->insertObjectAce($sid, 1, 0, false);
$acl->insertObjectAce($aSid, 1, 1);
$this->assertFalse($strategy->isGranted($acl, array(1), array($sid, $aSid)));
}
public function testIsGrantedCallsAuditLoggerOnGrant()
{
$strategy = new PermissionGrantingStrategy();
$acl = $this->getAcl($strategy);
$sid = new UserSecurityIdentity('johannes', 'Foo');
$logger = $this->getMock('Symfony\Component\Security\Acl\Model\AuditLoggerInterface');
$logger
->expects($this->once())
->method('logIfNeeded')
;
$strategy->setAuditLogger($logger);
$acl->insertObjectAce($sid, 1);
$acl->updateObjectAuditing(0, true, false);
$this->assertTrue($strategy->isGranted($acl, array(1), array($sid)));
}
public function testIsGrantedCallsAuditLoggerOnDeny()
{
$strategy = new PermissionGrantingStrategy();
$acl = $this->getAcl($strategy);
$sid = new UserSecurityIdentity('johannes', 'Foo');
$logger = $this->getMock('Symfony\Component\Security\Acl\Model\AuditLoggerInterface');
$logger
->expects($this->once())
->method('logIfNeeded')
;
$strategy->setAuditLogger($logger);
$acl->insertObjectAce($sid, 1, 0, false);
$acl->updateObjectAuditing(0, false, true);
$this->assertFalse($strategy->isGranted($acl, array(1), array($sid)));
}
/**
* @dataProvider getAllStrategyTests
*/
public function testIsGrantedStrategies($maskStrategy, $aceMask, $requiredMask, $result)
{
$strategy = new PermissionGrantingStrategy();
$acl = $this->getAcl($strategy);
$sid = new UserSecurityIdentity('johannes', 'Foo');
$acl->insertObjectAce($sid, $aceMask, 0, true, $maskStrategy);
if (false === $result) {
try {
$strategy->isGranted($acl, array($requiredMask), array($sid));
$this->fail('The ACE is not supposed to match.');
} catch (NoAceFoundException $e) {
}
} else {
$this->assertTrue($strategy->isGranted($acl, array($requiredMask), array($sid)));
}
}
public function getAllStrategyTests()
{
return array(
array('all', 1 << 0 | 1 << 1, 1 << 0, true),
array('all', 1 << 0 | 1 << 1, 1 << 2, false),
array('all', 1 << 0 | 1 << 10, 1 << 0 | 1 << 10, true),
array('all', 1 << 0 | 1 << 1, 1 << 0 | 1 << 1 || 1 << 2, false),
array('any', 1 << 0 | 1 << 1, 1 << 0, true),
array('any', 1 << 0 | 1 << 1, 1 << 0 | 1 << 2, true),
array('any', 1 << 0 | 1 << 1, 1 << 2, false),
array('equal', 1 << 0 | 1 << 1, 1 << 0, false),
array('equal', 1 << 0 | 1 << 1, 1 << 1, false),
array('equal', 1 << 0 | 1 << 1, 1 << 0 | 1 << 1, true),
);
}
protected function getAcl($strategy)
{
static $id = 1;
return new Acl($id++, new ObjectIdentity(1, 'Foo'), $strategy, array(), true);
}
}

View File

@ -1,55 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Tests\Domain;
use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity;
use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity;
class RoleSecurityIdentityTest extends \PHPUnit_Framework_TestCase
{
public function testConstructor()
{
$id = new RoleSecurityIdentity('ROLE_FOO');
$this->assertEquals('ROLE_FOO', $id->getRole());
}
public function testConstructorWithRoleInstance()
{
$id = new RoleSecurityIdentity(new Role('ROLE_FOO'));
$this->assertEquals('ROLE_FOO', $id->getRole());
}
/**
* @dataProvider getCompareData
*/
public function testEquals($id1, $id2, $equal)
{
if ($equal) {
$this->assertTrue($id1->equals($id2));
} else {
$this->assertFalse($id1->equals($id2));
}
}
public function getCompareData()
{
return array(
array(new RoleSecurityIdentity('ROLE_FOO'), new RoleSecurityIdentity('ROLE_FOO'), true),
array(new RoleSecurityIdentity('ROLE_FOO'), new RoleSecurityIdentity(new Role('ROLE_FOO')), true),
array(new RoleSecurityIdentity('ROLE_USER'), new RoleSecurityIdentity('ROLE_FOO'), false),
array(new RoleSecurityIdentity('ROLE_FOO'), new UserSecurityIdentity('ROLE_FOO', 'Foo'), false),
);
}
}

View File

@ -1,196 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Tests\Domain;
use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity;
use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity;
use Symfony\Component\Security\Acl\Domain\SecurityIdentityRetrievalStrategy;
class SecurityIdentityRetrievalStrategyTest extends \PHPUnit_Framework_TestCase
{
/**
* @dataProvider getSecurityIdentityRetrievalTests
*/
public function testGetSecurityIdentities($user, array $roles, $authenticationStatus, array $sids)
{
$strategy = $this->getStrategy($roles, $authenticationStatus);
if ('anonymous' === $authenticationStatus) {
$token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\AnonymousToken')
->disableOriginalConstructor()
->getMock();
} else {
$class = '';
if (is_string($user)) {
$class = 'MyCustomTokenImpl';
}
$token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')
->setMockClassName($class)
->getMock();
}
$token
->expects($this->once())
->method('getRoles')
->will($this->returnValue(array('foo')))
;
if ('anonymous' === $authenticationStatus) {
$token
->expects($this->never())
->method('getUser')
;
} else {
$token
->expects($this->once())
->method('getUser')
->will($this->returnValue($user))
;
}
$extractedSids = $strategy->getSecurityIdentities($token);
foreach ($extractedSids as $index => $extractedSid) {
if (!isset($sids[$index])) {
$this->fail(sprintf('Expected SID at index %d, but there was none.', true));
}
if (false === $sids[$index]->equals($extractedSid)) {
$this->fail(sprintf('Index: %d, expected SID "%s", but got "%s".', $index, $sids[$index], $extractedSid));
}
}
}
public function getSecurityIdentityRetrievalTests()
{
return array(
array($this->getAccount('johannes', 'FooUser'), array('ROLE_USER', 'ROLE_SUPERADMIN'), 'fullFledged', array(
new UserSecurityIdentity('johannes', 'FooUser'),
new RoleSecurityIdentity('ROLE_USER'),
new RoleSecurityIdentity('ROLE_SUPERADMIN'),
new RoleSecurityIdentity('IS_AUTHENTICATED_FULLY'),
new RoleSecurityIdentity('IS_AUTHENTICATED_REMEMBERED'),
new RoleSecurityIdentity('IS_AUTHENTICATED_ANONYMOUSLY'),
)),
array('johannes', array('ROLE_FOO'), 'fullFledged', array(
new UserSecurityIdentity('johannes', 'MyCustomTokenImpl'),
new RoleSecurityIdentity('ROLE_FOO'),
new RoleSecurityIdentity('IS_AUTHENTICATED_FULLY'),
new RoleSecurityIdentity('IS_AUTHENTICATED_REMEMBERED'),
new RoleSecurityIdentity('IS_AUTHENTICATED_ANONYMOUSLY'),
)),
array(new CustomUserImpl('johannes'), array('ROLE_FOO'), 'fullFledged', array(
new UserSecurityIdentity('johannes', 'Symfony\Component\Security\Acl\Tests\Domain\CustomUserImpl'),
new RoleSecurityIdentity('ROLE_FOO'),
new RoleSecurityIdentity('IS_AUTHENTICATED_FULLY'),
new RoleSecurityIdentity('IS_AUTHENTICATED_REMEMBERED'),
new RoleSecurityIdentity('IS_AUTHENTICATED_ANONYMOUSLY'),
)),
array($this->getAccount('foo', 'FooBarUser'), array('ROLE_FOO'), 'rememberMe', array(
new UserSecurityIdentity('foo', 'FooBarUser'),
new RoleSecurityIdentity('ROLE_FOO'),
new RoleSecurityIdentity('IS_AUTHENTICATED_REMEMBERED'),
new RoleSecurityIdentity('IS_AUTHENTICATED_ANONYMOUSLY'),
)),
array('guest', array('ROLE_FOO'), 'anonymous', array(
new RoleSecurityIdentity('ROLE_FOO'),
new RoleSecurityIdentity('IS_AUTHENTICATED_ANONYMOUSLY'),
)),
);
}
protected function getAccount($username, $class)
{
$account = $this->getMock('Symfony\Component\Security\Core\User\UserInterface', array(), array(), $class);
$account
->expects($this->any())
->method('getUsername')
->will($this->returnValue($username))
;
return $account;
}
protected function getStrategy(array $roles = array(), $authenticationStatus = 'fullFledged')
{
$roleHierarchy = $this->getMock('Symfony\Component\Security\Core\Role\RoleHierarchyInterface');
$roleHierarchy
->expects($this->once())
->method('getReachableRoles')
->with($this->equalTo(array('foo')))
->will($this->returnValue($roles))
;
$trustResolver = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolver', array(), array('', ''));
$trustResolver
->expects($this->at(0))
->method('isAnonymous')
->will($this->returnValue('anonymous' === $authenticationStatus))
;
if ('fullFledged' === $authenticationStatus) {
$trustResolver
->expects($this->once())
->method('isFullFledged')
->will($this->returnValue(true))
;
$trustResolver
->expects($this->never())
->method('isRememberMe')
;
} elseif ('rememberMe' === $authenticationStatus) {
$trustResolver
->expects($this->once())
->method('isFullFledged')
->will($this->returnValue(false))
;
$trustResolver
->expects($this->once())
->method('isRememberMe')
->will($this->returnValue(true))
;
} else {
$trustResolver
->expects($this->at(1))
->method('isAnonymous')
->will($this->returnValue(true))
;
$trustResolver
->expects($this->once())
->method('isFullFledged')
->will($this->returnValue(false))
;
$trustResolver
->expects($this->once())
->method('isRememberMe')
->will($this->returnValue(false))
;
}
return new SecurityIdentityRetrievalStrategy($roleHierarchy, $trustResolver);
}
}
class CustomUserImpl
{
protected $name;
public function __construct($name)
{
$this->name = $name;
}
public function __toString()
{
return $this->name;
}
}

View File

@ -1,73 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Tests\Domain;
use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity;
use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity;
class UserSecurityIdentityTest extends \PHPUnit_Framework_TestCase
{
public function testConstructor()
{
$id = new UserSecurityIdentity('foo', 'Foo');
$this->assertEquals('foo', $id->getUsername());
$this->assertEquals('Foo', $id->getClass());
}
// Test that constructor never changes the type, even for proxies
public function testConstructorWithProxy()
{
$id = new UserSecurityIdentity('foo', 'Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Acl\Tests\Domain\Foo');
$this->assertEquals('foo', $id->getUsername());
$this->assertEquals('Acme\DemoBundle\Proxy\__CG__\Symfony\Component\Security\Acl\Tests\Domain\Foo', $id->getClass());
}
/**
* @dataProvider getCompareData
*/
public function testEquals($id1, $id2, $equal)
{
$this->assertSame($equal, $id1->equals($id2));
}
public function getCompareData()
{
$account = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')
->setMockClassName('USI_AccountImpl')
->getMock();
$account
->expects($this->any())
->method('getUsername')
->will($this->returnValue('foo'))
;
$token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
$token
->expects($this->any())
->method('getUser')
->will($this->returnValue($account))
;
return array(
array(new UserSecurityIdentity('foo', 'Foo'), new UserSecurityIdentity('foo', 'Foo'), true),
array(new UserSecurityIdentity('foo', 'Bar'), new UserSecurityIdentity('foo', 'Foo'), false),
array(new UserSecurityIdentity('foo', 'Foo'), new UserSecurityIdentity('bar', 'Foo'), false),
array(new UserSecurityIdentity('foo', 'Foo'), UserSecurityIdentity::fromAccount($account), false),
array(new UserSecurityIdentity('bla', 'Foo'), new UserSecurityIdentity('blub', 'Foo'), false),
array(new UserSecurityIdentity('foo', 'Foo'), new RoleSecurityIdentity('foo'), false),
array(new UserSecurityIdentity('foo', 'Foo'), UserSecurityIdentity::fromToken($token), false),
array(new UserSecurityIdentity('foo', 'USI_AccountImpl'), UserSecurityIdentity::fromToken($token), true),
);
}
}

View File

@ -1,23 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Tests\Permission;
use Symfony\Component\Security\Acl\Permission\BasicPermissionMap;
class BasicPermissionMapTest extends \PHPUnit_Framework_TestCase
{
public function testGetMasksReturnsNullWhenNotSupportedMask()
{
$map = new BasicPermissionMap();
$this->assertNull($map->getMasks('IS_AUTHENTICATED_REMEMBERED', null));
}
}

View File

@ -1,103 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Tests\Permission;
use Symfony\Component\Security\Acl\Permission\MaskBuilder;
class MaskBuilderTest extends \PHPUnit_Framework_TestCase
{
/**
* @expectedException \InvalidArgumentException
* @dataProvider getInvalidConstructorData
*/
public function testConstructorWithNonInteger($invalidMask)
{
new MaskBuilder($invalidMask);
}
public function getInvalidConstructorData()
{
return array(
array(234.463),
array('asdgasdf'),
array(array()),
array(new \stdClass()),
);
}
public function testConstructorWithoutArguments()
{
$builder = new MaskBuilder();
$this->assertEquals(0, $builder->get());
}
public function testConstructor()
{
$builder = new MaskBuilder(123456);
$this->assertEquals(123456, $builder->get());
}
public function testAddAndRemove()
{
$builder = new MaskBuilder();
$builder
->add('view')
->add('eDiT')
->add('ownEr')
;
$mask = $builder->get();
$this->assertEquals(MaskBuilder::MASK_VIEW, $mask & MaskBuilder::MASK_VIEW);
$this->assertEquals(MaskBuilder::MASK_EDIT, $mask & MaskBuilder::MASK_EDIT);
$this->assertEquals(MaskBuilder::MASK_OWNER, $mask & MaskBuilder::MASK_OWNER);
$this->assertEquals(0, $mask & MaskBuilder::MASK_MASTER);
$this->assertEquals(0, $mask & MaskBuilder::MASK_CREATE);
$this->assertEquals(0, $mask & MaskBuilder::MASK_DELETE);
$this->assertEquals(0, $mask & MaskBuilder::MASK_UNDELETE);
$builder->remove('edit')->remove('OWner');
$mask = $builder->get();
$this->assertEquals(0, $mask & MaskBuilder::MASK_EDIT);
$this->assertEquals(0, $mask & MaskBuilder::MASK_OWNER);
$this->assertEquals(MaskBuilder::MASK_VIEW, $mask & MaskBuilder::MASK_VIEW);
}
public function testGetPattern()
{
$builder = new MaskBuilder();
$this->assertEquals(MaskBuilder::ALL_OFF, $builder->getPattern());
$builder->add('view');
$this->assertEquals(str_repeat('.', 31).'V', $builder->getPattern());
$builder->add('owner');
$this->assertEquals(str_repeat('.', 24).'N......V', $builder->getPattern());
$builder->add(1 << 10);
$this->assertEquals(str_repeat('.', 21).MaskBuilder::ON.'..N......V', $builder->getPattern());
}
public function testReset()
{
$builder = new MaskBuilder();
$this->assertEquals(0, $builder->get());
$builder->add('view');
$this->assertTrue($builder->get() > 0);
$builder->reset();
$this->assertEquals(0, $builder->get());
}
}

View File

@ -1,432 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Tests\Voter;
use Symfony\Component\Security\Acl\Exception\NoAceFoundException;
use Symfony\Component\Security\Acl\Voter\FieldVote;
use Symfony\Component\Security\Acl\Exception\AclNotFoundException;
use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity;
use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity;
use Symfony\Component\Security\Acl\Domain\ObjectIdentity;
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
use Symfony\Component\Security\Acl\Voter\AclVoter;
class AclVoterTest extends \PHPUnit_Framework_TestCase
{
/**
* @dataProvider getSupportsAttributeTests
*/
public function testSupportsAttribute($attribute, $supported)
{
list($voter, , $permissionMap) = $this->getVoter(true, false);
$permissionMap
->expects($this->once())
->method('contains')
->with($this->identicalTo($attribute))
->will($this->returnValue($supported))
;
$this->assertSame($supported, $voter->supportsAttribute($attribute));
}
/**
* @dataProvider getSupportsAttributeNonStringTests
*/
public function testSupportsAttributeNonString($attribute)
{
list($voter) = $this->getVoter(true, false);
$this->assertFalse($voter->supportsAttribute($attribute));
}
public function getSupportsAttributeTests()
{
return array(
array('foo', true),
array('foo', false),
);
}
public function getSupportsAttributeNonStringTests()
{
return array(
array(new \stdClass()),
array(1),
array(true),
array(array()),
);
}
/**
* @dataProvider getSupportsClassTests
*/
public function testSupportsClass($class)
{
list($voter) = $this->getVoter();
$this->assertTrue($voter->supportsClass($class));
}
public function getSupportsClassTests()
{
return array(
array('foo'),
array('bar'),
array('moo'),
);
}
public function testVote()
{
list($voter, , $permissionMap) = $this->getVoter();
$permissionMap
->expects($this->atLeastOnce())
->method('getMasks')
->will($this->returnValue(null))
;
$this->assertSame(VoterInterface::ACCESS_ABSTAIN, $voter->vote($this->getToken(), null, array('VIEW', 'EDIT', 'DELETE')));
}
/**
* @dataProvider getTrueFalseTests
*/
public function testVoteWhenNoObjectIsPassed($allowIfObjectIdentityUnavailable)
{
list($voter, , $permissionMap) = $this->getVoter($allowIfObjectIdentityUnavailable);
$permissionMap
->expects($this->once())
->method('getMasks')
->will($this->returnValue(array()))
;
if ($allowIfObjectIdentityUnavailable) {
$vote = VoterInterface::ACCESS_GRANTED;
} else {
$vote = VoterInterface::ACCESS_ABSTAIN;
}
$this->assertSame($vote, $voter->vote($this->getToken(), null, array('VIEW')));
}
/**
* @dataProvider getTrueFalseTests
*/
public function testVoteWhenOidStrategyReturnsNull($allowIfUnavailable)
{
list($voter, , $permissionMap, $oidStrategy) = $this->getVoter($allowIfUnavailable);
$permissionMap
->expects($this->once())
->method('getMasks')
->will($this->returnValue(array()))
;
$oidStrategy
->expects($this->once())
->method('getObjectIdentity')
->will($this->returnValue(null))
;
if ($allowIfUnavailable) {
$vote = VoterInterface::ACCESS_GRANTED;
} else {
$vote = VoterInterface::ACCESS_ABSTAIN;
}
$this->assertSame($vote, $voter->vote($this->getToken(), new \stdClass(), array('VIEW')));
}
public function getTrueFalseTests()
{
return array(array(true), array(false));
}
public function testVoteNoAclFound()
{
list($voter, $provider, $permissionMap, $oidStrategy, $sidStrategy) = $this->getVoter();
$permissionMap
->expects($this->once())
->method('getMasks')
->will($this->returnValue(array()))
;
$oidStrategy
->expects($this->once())
->method('getObjectIdentity')
->will($this->returnValue($oid = new ObjectIdentity('1', 'Foo')))
;
$sidStrategy
->expects($this->once())
->method('getSecurityIdentities')
->will($this->returnValue($sids = array(new UserSecurityIdentity('johannes', 'Foo'), new RoleSecurityIdentity('ROLE_FOO'))))
;
$provider
->expects($this->once())
->method('findAcl')
->with($this->equalTo($oid), $this->equalTo($sids))
->will($this->throwException(new AclNotFoundException('Not found.')))
;
$this->assertSame(VoterInterface::ACCESS_DENIED, $voter->vote($this->getToken(), new \stdClass(), array('VIEW')));
}
/**
* @dataProvider getTrueFalseTests
*/
public function testVoteGrantsAccess($grant)
{
list($voter, $provider, $permissionMap, $oidStrategy, $sidStrategy) = $this->getVoter();
$permissionMap
->expects($this->once())
->method('getMasks')
->with($this->equalTo('VIEW'))
->will($this->returnValue($masks = array(1, 2, 3)))
;
$oidStrategy
->expects($this->once())
->method('getObjectIdentity')
->will($this->returnValue($oid = new ObjectIdentity('1', 'Foo')))
;
$sidStrategy
->expects($this->once())
->method('getSecurityIdentities')
->will($this->returnValue($sids = array(new UserSecurityIdentity('johannes', 'Foo'), new RoleSecurityIdentity('ROLE_FOO'))))
;
$provider
->expects($this->once())
->method('findAcl')
->with($this->equalTo($oid), $this->equalTo($sids))
->will($this->returnValue($acl = $this->getMock('Symfony\Component\Security\Acl\Model\AclInterface')))
;
$acl
->expects($this->once())
->method('isGranted')
->with($this->identicalTo($masks), $this->equalTo($sids), $this->isFalse())
->will($this->returnValue($grant))
;
if ($grant) {
$vote = VoterInterface::ACCESS_GRANTED;
} else {
$vote = VoterInterface::ACCESS_DENIED;
}
$this->assertSame($vote, $voter->vote($this->getToken(), new \stdClass(), array('VIEW')));
}
public function testVoteNoAceFound()
{
list($voter, $provider, $permissionMap, $oidStrategy, $sidStrategy) = $this->getVoter();
$permissionMap
->expects($this->once())
->method('getMasks')
->with($this->equalTo('VIEW'))
->will($this->returnValue($masks = array(1, 2, 3)))
;
$oidStrategy
->expects($this->once())
->method('getObjectIdentity')
->will($this->returnValue($oid = new ObjectIdentity('1', 'Foo')))
;
$sidStrategy
->expects($this->once())
->method('getSecurityIdentities')
->will($this->returnValue($sids = array(new UserSecurityIdentity('johannes', 'Foo'), new RoleSecurityIdentity('ROLE_FOO'))))
;
$provider
->expects($this->once())
->method('findAcl')
->with($this->equalTo($oid), $this->equalTo($sids))
->will($this->returnValue($acl = $this->getMock('Symfony\Component\Security\Acl\Model\AclInterface')))
;
$acl
->expects($this->once())
->method('isGranted')
->with($this->identicalTo($masks), $this->equalTo($sids), $this->isFalse())
->will($this->throwException(new NoAceFoundException('No ACE')))
;
$this->assertSame(VoterInterface::ACCESS_DENIED, $voter->vote($this->getToken(), new \stdClass(), array('VIEW')));
}
/**
* @dataProvider getTrueFalseTests
*/
public function testVoteGrantsFieldAccess($grant)
{
list($voter, $provider, $permissionMap, $oidStrategy, $sidStrategy) = $this->getVoter();
$permissionMap
->expects($this->once())
->method('getMasks')
->with($this->equalTo('VIEW'))
->will($this->returnValue($masks = array(1, 2, 3)))
;
$oidStrategy
->expects($this->once())
->method('getObjectIdentity')
->will($this->returnValue($oid = new ObjectIdentity('1', 'Foo')))
;
$sidStrategy
->expects($this->once())
->method('getSecurityIdentities')
->will($this->returnValue($sids = array(new UserSecurityIdentity('johannes', 'Foo'), new RoleSecurityIdentity('ROLE_FOO'))))
;
$provider
->expects($this->once())
->method('findAcl')
->with($this->equalTo($oid), $this->equalTo($sids))
->will($this->returnValue($acl = $this->getMock('Symfony\Component\Security\Acl\Model\AclInterface')))
;
$acl
->expects($this->once())
->method('isFieldGranted')
->with($this->identicalTo('foo'), $this->identicalTo($masks), $this->equalTo($sids), $this->isFalse())
->will($this->returnValue($grant))
;
if ($grant) {
$vote = VoterInterface::ACCESS_GRANTED;
} else {
$vote = VoterInterface::ACCESS_DENIED;
}
$this->assertSame($vote, $voter->vote($this->getToken(), new FieldVote(new \stdClass(), 'foo'), array('VIEW')));
}
public function testVoteNoFieldAceFound()
{
list($voter, $provider, $permissionMap, $oidStrategy, $sidStrategy) = $this->getVoter();
$permissionMap
->expects($this->once())
->method('getMasks')
->with($this->equalTo('VIEW'))
->will($this->returnValue($masks = array(1, 2, 3)))
;
$oidStrategy
->expects($this->once())
->method('getObjectIdentity')
->will($this->returnValue($oid = new ObjectIdentity('1', 'Foo')))
;
$sidStrategy
->expects($this->once())
->method('getSecurityIdentities')
->will($this->returnValue($sids = array(new UserSecurityIdentity('johannes', 'Foo'), new RoleSecurityIdentity('ROLE_FOO'))))
;
$provider
->expects($this->once())
->method('findAcl')
->with($this->equalTo($oid), $this->equalTo($sids))
->will($this->returnValue($acl = $this->getMock('Symfony\Component\Security\Acl\Model\AclInterface')))
;
$acl
->expects($this->once())
->method('isFieldGranted')
->with($this->identicalTo('foo'), $this->identicalTo($masks), $this->equalTo($sids), $this->isFalse())
->will($this->throwException(new NoAceFoundException('No ACE')))
;
$this->assertSame(VoterInterface::ACCESS_DENIED, $voter->vote($this->getToken(), new FieldVote(new \stdClass(), 'foo'), array('VIEW')));
}
public function testWhenReceivingAnObjectIdentityInterfaceWeDontRetrieveANewObjectIdentity()
{
list($voter, $provider, $permissionMap, $oidStrategy, $sidStrategy) = $this->getVoter();
$oid = new ObjectIdentity('someID', 'someType');
$permissionMap
->expects($this->once())
->method('getMasks')
->with($this->equalTo('VIEW'))
->will($this->returnValue($masks = array(1, 2, 3)))
;
$oidStrategy
->expects($this->never())
->method('getObjectIdentity')
;
$sidStrategy
->expects($this->once())
->method('getSecurityIdentities')
->will($this->returnValue($sids = array(new UserSecurityIdentity('johannes', 'Foo'), new RoleSecurityIdentity('ROLE_FOO'))))
;
$provider
->expects($this->once())
->method('findAcl')
->with($this->equalTo($oid), $this->equalTo($sids))
->will($this->returnValue($acl = $this->getMock('Symfony\Component\Security\Acl\Model\AclInterface')))
;
$acl
->expects($this->once())
->method('isGranted')
->with($this->identicalTo($masks), $this->equalTo($sids), $this->isFalse())
->will($this->throwException(new NoAceFoundException('No ACE')))
;
$voter->vote($this->getToken(), $oid, array('VIEW'));
}
protected function getToken()
{
return $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
}
protected function getVoter($allowIfObjectIdentityUnavailable = true, $alwaysContains = true)
{
$provider = $this->getMock('Symfony\Component\Security\Acl\Model\AclProviderInterface');
$permissionMap = $this->getMock('Symfony\Component\Security\Acl\Permission\PermissionMapInterface');
$oidStrategy = $this->getMock('Symfony\Component\Security\Acl\Model\ObjectIdentityRetrievalStrategyInterface');
$sidStrategy = $this->getMock('Symfony\Component\Security\Acl\Model\SecurityIdentityRetrievalStrategyInterface');
if ($alwaysContains) {
$permissionMap
->expects($this->any())
->method('contains')
->will($this->returnValue(true));
}
return array(
new AclVoter($provider, $oidStrategy, $sidStrategy, $permissionMap, null, $allowIfObjectIdentityUnavailable),
$provider,
$permissionMap,
$oidStrategy,
$sidStrategy,
);
}
}

View File

@ -1,147 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Voter;
use Psr\Log\LoggerInterface;
use Symfony\Component\Security\Acl\Exception\NoAceFoundException;
use Symfony\Component\Security\Acl\Exception\AclNotFoundException;
use Symfony\Component\Security\Acl\Model\AclProviderInterface;
use Symfony\Component\Security\Acl\Model\ObjectIdentityInterface;
use Symfony\Component\Security\Acl\Permission\PermissionMapInterface;
use Symfony\Component\Security\Acl\Model\SecurityIdentityRetrievalStrategyInterface;
use Symfony\Component\Security\Acl\Model\ObjectIdentityRetrievalStrategyInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
/**
* This voter can be used as a base class for implementing your own permissions.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class AclVoter implements VoterInterface
{
private $aclProvider;
private $permissionMap;
private $objectIdentityRetrievalStrategy;
private $securityIdentityRetrievalStrategy;
private $allowIfObjectIdentityUnavailable;
private $logger;
public function __construct(AclProviderInterface $aclProvider, ObjectIdentityRetrievalStrategyInterface $oidRetrievalStrategy, SecurityIdentityRetrievalStrategyInterface $sidRetrievalStrategy, PermissionMapInterface $permissionMap, LoggerInterface $logger = null, $allowIfObjectIdentityUnavailable = true)
{
$this->aclProvider = $aclProvider;
$this->permissionMap = $permissionMap;
$this->objectIdentityRetrievalStrategy = $oidRetrievalStrategy;
$this->securityIdentityRetrievalStrategy = $sidRetrievalStrategy;
$this->logger = $logger;
$this->allowIfObjectIdentityUnavailable = $allowIfObjectIdentityUnavailable;
}
public function supportsAttribute($attribute)
{
return is_string($attribute) && $this->permissionMap->contains($attribute);
}
public function vote(TokenInterface $token, $object, array $attributes)
{
foreach ($attributes as $attribute) {
if (!$this->supportsAttribute($attribute)) {
continue;
}
if (null === $masks = $this->permissionMap->getMasks($attribute, $object)) {
continue;
}
if (null === $object) {
if (null !== $this->logger) {
$this->logger->debug(sprintf('Object identity unavailable. Voting to %s.', $this->allowIfObjectIdentityUnavailable ? 'grant access' : 'abstain'));
}
return $this->allowIfObjectIdentityUnavailable ? self::ACCESS_GRANTED : self::ACCESS_ABSTAIN;
} elseif ($object instanceof FieldVote) {
$field = $object->getField();
$object = $object->getDomainObject();
} else {
$field = null;
}
if ($object instanceof ObjectIdentityInterface) {
$oid = $object;
} elseif (null === $oid = $this->objectIdentityRetrievalStrategy->getObjectIdentity($object)) {
if (null !== $this->logger) {
$this->logger->debug(sprintf('Object identity unavailable. Voting to %s.', $this->allowIfObjectIdentityUnavailable ? 'grant access' : 'abstain'));
}
return $this->allowIfObjectIdentityUnavailable ? self::ACCESS_GRANTED : self::ACCESS_ABSTAIN;
}
if (!$this->supportsClass($oid->getType())) {
return self::ACCESS_ABSTAIN;
}
$sids = $this->securityIdentityRetrievalStrategy->getSecurityIdentities($token);
try {
$acl = $this->aclProvider->findAcl($oid, $sids);
if (null === $field && $acl->isGranted($masks, $sids, false)) {
if (null !== $this->logger) {
$this->logger->debug('ACL found, permission granted. Voting to grant access.');
}
return self::ACCESS_GRANTED;
} elseif (null !== $field && $acl->isFieldGranted($field, $masks, $sids, false)) {
if (null !== $this->logger) {
$this->logger->debug('ACL found, permission granted. Voting to grant access.');
}
return self::ACCESS_GRANTED;
}
if (null !== $this->logger) {
$this->logger->debug('ACL found, insufficient permissions. Voting to deny access.');
}
return self::ACCESS_DENIED;
} catch (AclNotFoundException $e) {
if (null !== $this->logger) {
$this->logger->debug('No ACL found for the object identity. Voting to deny access.');
}
return self::ACCESS_DENIED;
} catch (NoAceFoundException $e) {
if (null !== $this->logger) {
$this->logger->debug('ACL found, no ACE applicable. Voting to deny access.');
}
return self::ACCESS_DENIED;
}
}
// no attribute was supported
return self::ACCESS_ABSTAIN;
}
/**
* You can override this method when writing a voter for a specific domain
* class.
*
* @param string $class The class name
*
* @return bool
*/
public function supportsClass($class)
{
return true;
}
}

View File

@ -1,40 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Acl\Voter;
/**
* This class is a lightweight wrapper around field vote requests which does
* not violate any interface contracts.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class FieldVote
{
private $domainObject;
private $field;
public function __construct($domainObject, $field)
{
$this->domainObject = $domainObject;
$this->field = $field;
}
public function getDomainObject()
{
return $this->domainObject;
}
public function getField()
{
return $this->field;
}
}

View File

@ -1,42 +0,0 @@
{
"name": "symfony/security-acl",
"type": "library",
"description": "Symfony Security Component - ACL (Access Control List)",
"keywords": [],
"homepage": "https://symfony.com",
"license": "MIT",
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"require": {
"php": ">=5.3.9",
"symfony/security-core": "~2.4|~3.0.0"
},
"require-dev": {
"symfony/phpunit-bridge": "~2.7|~3.0.0",
"doctrine/common": "~2.2",
"doctrine/dbal": "~2.2",
"psr/log": "~1.0"
},
"suggest": {
"symfony/class-loader": "For using the ACL generateSql script",
"symfony/finder": "For using the ACL generateSql script",
"doctrine/dbal": "For using the built-in ACL implementation"
},
"autoload": {
"psr-4": { "Symfony\\Component\\Security\\Acl\\": "" }
},
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "2.8-dev"
}
}
}

View File

@ -1,33 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false"
bootstrap="vendor/autoload.php"
>
<php>
<ini name="error_reporting" value="-1" />
</php>
<testsuites>
<testsuite name="Symfony Security Component ACL Test Suite">
<directory>./Tests/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>./</directory>
<exclude>
<directory>./vendor</directory>
<directory>./Tests</directory>
</exclude>
</whitelist>
</filter>
</phpunit>

View File

@ -22,7 +22,6 @@
"symfony/http-kernel": "~2.4|~3.0.0"
},
"replace": {
"symfony/security-acl": "self.version",
"symfony/security-core": "self.version",
"symfony/security-csrf": "self.version",
"symfony/security-http": "self.version"