Skip to content
This repository has been archived by the owner on May 25, 2020. It is now read-only.

Commit

Permalink
Allow extra queries to bypass acl filter
Browse files Browse the repository at this point in the history
  • Loading branch information
prophet777 committed Dec 12, 2014
1 parent ecbe45b commit 078a8a1
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 7 deletions.
34 changes: 29 additions & 5 deletions ORM/AclFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

class AclFilter
{
const HINT_ACL_EXTRA_CRITERIA = 'acl_extra_criteria';

/**
* Construct AclFilter
*
Expand Down Expand Up @@ -44,13 +46,32 @@ public function apply(
$query,
array $permissions = array('VIEW'),
$identity = null,
$alias = null
$alias = null,
$extraCriteria = false
) {
if (null === $identity) {
$token = $this->securityContext->getToken();
$identity = $token->getUser();
}

if(!is_array($extraCriteria)){
$extraCriteria = array($extraCriteria);
}

$sqlQueries = [];
foreach($extraCriteria as $criteria){
if($criteria instanceof QueryBuilder) {
$sqlQueries[] = $criteria->getQuery()->getSQL();
} elseif($criteria instanceof Query){
$sqlQueries[] = $criteria->getSQL();
} else{
$sqlQueries[] = $criteria;
}
}


$query->setHint(static::HINT_ACL_EXTRA_CRITERIA, $sqlQueries);

if ($query instanceof QueryBuilder) {
$query = $this->cloneQuery($query->getQuery());
} elseif ($query instanceof Query) {
Expand All @@ -69,14 +90,18 @@ public function apply(
$metadata = $entity['metadata'];
$alias = $entity['alias'];
$table = $metadata->getQuotedTableName($this->em->getConnection()->getDatabasePlatform());

$aclQuery = $this->getExtraQuery(
$this->getClasses($metadata),
$this->getIdentifiers($identity),
$maskBuilder->get()
);

$hintAclMetadata =
(false !== $query->getHint('acl.metadata')) ? $query->getHint('acl.metadata') : array();
$hintAclMetadata = (false !== $query->getHint('acl.metadata'))
? $query->getHint('acl.metadata')
: array()
;

$hintAclMetadata[] = array('query' => $aclQuery, 'table' => $table, 'alias' => $alias);

$query->setHint('acl.metadata', $hintAclMetadata);
Expand All @@ -91,6 +116,7 @@ public function apply(
* @param array $classes
* @param array $identifiers
* @param integer $mask
* @param array $extraCriteria
* @return string
*/
private function getExtraQuery(Array $classes, Array $identifiers, $mask)
Expand Down Expand Up @@ -148,8 +174,6 @@ protected function getEntityFromAlias(AbstractQuery $query, $alias = null)
}
}
}

return;
}

/**
Expand Down
23 changes: 21 additions & 2 deletions ORM/AclWalker.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,47 @@ class AclWalker extends SqlWalker
/**
* @param $fromClause
*
* @return string
* @return string
*/
public function walkFromClause($fromClause)
{
$sql = parent::walkFromClause($fromClause);
$aclMetadata = $this->getQuery()->getHint('acl.metadata');
$extraQueries = $this->getQuery()->getHint(AclFilter::HINT_ACL_EXTRA_CRITERIA);

if ($aclMetadata) {
foreach ($aclMetadata as $key => $metadata) {
$alias = $metadata['alias'];
$query = $metadata['query'];
$table = $metadata['table'];
$tableAlias = $this->getSQLTableAlias($table, $alias);
$this->parseExtraQueries($extraQueries, $tableAlias);
$aclAlias = 'ta' . $key . '_';

$aclSql = <<<ACL_SQL
INNER JOIN ({$query}) {$aclAlias} ON {$tableAlias}.id = {$aclAlias}.id
INNER JOIN ({$query}) {$aclAlias} ON ({$tableAlias}.id = {$aclAlias}.id OR ({$this->parseExtraQueries($extraQueries, $tableAlias)}))
ACL_SQL;
$sql .= ' ' . $aclSql;
}
}

return $sql;
}

/**
* @param array $extraQueries
* @param string $tableAlias
*
* @return array
*/
protected function parseExtraQueries(Array $extraQueries, $tableAlias)
{
$clause = array();

foreach($extraQueries as $query){
$clause[] = $tableAlias.'.id IN(('.$query.'))';
}

return implode(' OR ', $clause);
}
}
47 changes: 47 additions & 0 deletions ORM/ExtraCriteria.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

namespace Problematic\AclManagerBundle\ORM;

use Doctrine\ORM\Query\Expr;

class ExtraCriteria
{
const OPERATOR_AND = 'AND';
const OPERATOR_OR = 'OR';

/**
* @var string
*/
protected $operator;

/**
* @var string
*/
protected $expression;

/**
* @param string $operator
* @param string $expression
*/
public function __construct($operator, $expression)
{
$this->operator = $operator;
$this->expression = $expression;
}

/**
* @return string
*/
public function getOperator()
{
return $this->operator;
}

/**
* @return string
*/
public function getExpression()
{
return $this->expression;
}
}

0 comments on commit 078a8a1

Please sign in to comment.