[Security] Removed security-acl from the core
This commit is contained in:
parent
15ff8652b8
commit
b26a449d46
@ -50,7 +50,6 @@
|
|||||||
"symfony/proxy-manager-bridge": "self.version",
|
"symfony/proxy-manager-bridge": "self.version",
|
||||||
"symfony/routing": "self.version",
|
"symfony/routing": "self.version",
|
||||||
"symfony/security": "self.version",
|
"symfony/security": "self.version",
|
||||||
"symfony/security-acl": "self.version",
|
|
||||||
"symfony/security-core": "self.version",
|
"symfony/security-core": "self.version",
|
||||||
"symfony/security-csrf": "self.version",
|
"symfony/security-csrf": "self.version",
|
||||||
"symfony/security-http": "self.version",
|
"symfony/security-http": "self.version",
|
||||||
@ -76,7 +75,8 @@
|
|||||||
"monolog/monolog": "~1.11",
|
"monolog/monolog": "~1.11",
|
||||||
"ircmaxell/password-compat": "~1.0",
|
"ircmaxell/password-compat": "~1.0",
|
||||||
"ocramius/proxy-manager": "~0.4|~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": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
|
@ -18,7 +18,8 @@
|
|||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.3.9",
|
"php": ">=5.3.9",
|
||||||
"symfony/security": "~2.8|~3.0.0",
|
"symfony/security": "~2.8|~3.0.0",
|
||||||
"symfony/http-kernel": "~2.2|~3.0.0"
|
"symfony/http-kernel": "~2.2|~3.0.0",
|
||||||
|
"symfony/security-acl": "~2.8|~3.0.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"symfony/phpunit-bridge": "~2.7|~3.0.0",
|
"symfony/phpunit-bridge": "~2.7|~3.0.0",
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
vendor/
|
|
||||||
composer.lock
|
|
||||||
phpunit.xml
|
|
@ -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 $aclNotFoundException) {
|
|
||||||
if ($result->count()) {
|
|
||||||
$partialResultException = new NotAllAclsFoundException('The provider could not find ACLs for all object identities.');
|
|
||||||
$partialResultException->setPartialResult($result);
|
|
||||||
throw $partialResultException;
|
|
||||||
} else {
|
|
||||||
throw $aclNotFoundException;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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
@ -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'));
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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 $invalid) {
|
|
||||||
throw new InvalidDomainObjectException($invalid->getMessage(), 0, $invalid);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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 $failed) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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 $noObjectAce) {
|
|
||||||
$aces = $acl->getClassAces();
|
|
||||||
|
|
||||||
if (!$aces) {
|
|
||||||
throw $noObjectAce;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->hasSufficientPermissions($acl, $aces, $masks, $sids, $administrativeMode);
|
|
||||||
}
|
|
||||||
} catch (NoAceFoundException $noClassAce) {
|
|
||||||
if ($acl->isEntriesInheriting() && null !== $parentAcl = $acl->getParentAcl()) {
|
|
||||||
return $parentAcl->isGranted($masks, $sids, $administrativeMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw $noClassAce;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@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 $noObjectAces) {
|
|
||||||
$aces = $acl->getClassFieldAces($field);
|
|
||||||
if (!$aces) {
|
|
||||||
throw $noObjectAces;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->hasSufficientPermissions($acl, $aces, $masks, $sids, $administrativeMode);
|
|
||||||
}
|
|
||||||
} catch (NoAceFoundException $noClassAces) {
|
|
||||||
if ($acl->isEntriesInheriting() && null !== $parentAcl = $acl->getParentAcl()) {
|
|
||||||
return $parentAcl->isFieldGranted($field, $masks, $sids, $administrativeMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw $noClassAces;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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));
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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 $invalid) {
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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 (empty($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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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
|
|
||||||
{
|
|
||||||
}
|
|
@ -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
|
|
||||||
{
|
|
||||||
}
|
|
@ -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
|
|
||||||
{
|
|
||||||
}
|
|
@ -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
|
|
||||||
{
|
|
||||||
}
|
|
@ -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
|
|
||||||
{
|
|
||||||
}
|
|
@ -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.');
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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
|
|
||||||
{
|
|
||||||
}
|
|
@ -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.
|
|
@ -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();
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
@ -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());
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -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 $notPredefined) {
|
|
||||||
$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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
@ -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
|
|
@ -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)));
|
|
||||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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)
|
|
@ -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());
|
|
||||||
}
|
|
||||||
}
|
|
@ -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 $ex) {
|
|
||||||
$this->assertInstanceOf('Symfony\Component\Security\Acl\Exception\AclNotFoundException', $ex);
|
|
||||||
$this->assertInstanceOf('Symfony\Component\Security\Acl\Exception\NotAllAclsFoundException', $ex);
|
|
||||||
|
|
||||||
$partialResult = $ex->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());
|
|
||||||
}
|
|
||||||
}
|
|
@ -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 $notFound) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 $notFound) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 $ex) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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');
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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');
|
|
||||||
}
|
|
||||||
}
|
|
@ -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');
|
|
||||||
}
|
|
||||||
}
|
|
@ -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';
|
|
||||||
}
|
|
||||||
}
|
|
@ -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
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
@ -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 $noAce) {
|
|
||||||
}
|
|
||||||
} 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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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));
|
|
||||||
}
|
|
||||||
}
|
|
@ -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());
|
|
||||||
}
|
|
||||||
}
|
|
@ -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,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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 $noAcl) {
|
|
||||||
if (null !== $this->logger) {
|
|
||||||
$this->logger->debug('No ACL found for the object identity. Voting to deny access.');
|
|
||||||
}
|
|
||||||
|
|
||||||
return self::ACCESS_DENIED;
|
|
||||||
} catch (NoAceFoundException $noAce) {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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>
|
|
@ -22,7 +22,6 @@
|
|||||||
"symfony/http-kernel": "~2.4|~3.0.0"
|
"symfony/http-kernel": "~2.4|~3.0.0"
|
||||||
},
|
},
|
||||||
"replace": {
|
"replace": {
|
||||||
"symfony/security-acl": "self.version",
|
|
||||||
"symfony/security-core": "self.version",
|
"symfony/security-core": "self.version",
|
||||||
"symfony/security-csrf": "self.version",
|
"symfony/security-csrf": "self.version",
|
||||||
"symfony/security-http": "self.version"
|
"symfony/security-http": "self.version"
|
||||||
|
Reference in New Issue
Block a user