Skip to content

Commit

Permalink
Merge pull request #16124 from eileenmcnaughton/acl_deadlock
Browse files Browse the repository at this point in the history
Remove function marked as deprecated & unused by core nearly a year ago
  • Loading branch information
yashodha authored Dec 20, 2019
2 parents cccd537 + 048aaef commit cbd6ceb
Showing 1 changed file with 0 additions and 232 deletions.
232 changes: 0 additions & 232 deletions CRM/ACL/BAO/ACL.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,238 +75,6 @@ public static function operation() {
return self::$_operation;
}

/**
* Construct a WHERE clause to handle permissions to $object_*
*
* @param array $tables
* Any tables that may be needed in the FROM.
* @param string $operation
* The operation being attempted.
* @param string $object_table
* The table of the object in question.
* @param int $object_id
* The ID of the object in question.
* @param int $acl_id
* If it's a grant/revoke operation, the ACL ID.
* @param bool $acl_role
* For grant operations, this flag determines if we're granting a single acl (false) or an entire group.
*
* @return string
* The WHERE clause, or 0 on failure
* @throws \CRM_Core_Exception
*
* @deprecated
*
*/
public static function permissionClause(
&$tables, $operation,
$object_table = NULL, $object_id = NULL,
$acl_id = NULL, $acl_role = FALSE
) {
CRM_Core_Error::deprecatedFunctionWarning('unknown - this is really old & not used in core');
$dao = new CRM_ACL_DAO_ACL();

$t = [
'ACL' => self::getTableName(),
'ACLRole' => 'civicrm_acl_role',
'ACLEntityRole' => CRM_ACL_DAO_EntityRole::getTableName(),
'Contact' => CRM_Contact_DAO_Contact::getTableName(),
'Group' => CRM_Contact_DAO_Group::getTableName(),
'GroupContact' => CRM_Contact_DAO_GroupContact::getTableName(),
];

$contact_id = CRM_Core_Session::getLoggedInContactID();

$where = " {$t['ACL']}.operation = '" . CRM_Utils_Type::escape($operation, 'String') . "'";

/* Include clause if we're looking for a specific table/id permission */

if (!empty($object_table)) {
$where .= " AND ( {$t['ACL']}.object_table IS null
OR ({$t['ACL']}.object_table = '" . CRM_Utils_Type::escape($object_table, 'String') . "'";
if (!empty($object_id)) {
$where .= " AND ({$t['ACL']}.object_id IS null
OR {$t['ACL']}.object_id = " . CRM_Utils_Type::escape($object_id, 'Integer') . ')';
}
$where .= '))';
}

/* Include clause if we're granting an ACL or ACL Role */

if (!empty($acl_id)) {
$where .= " AND ({$t['ACL']}.acl_id IS null
OR {$t['ACL']}.acl_id = " . CRM_Utils_Type::escape($acl_id, 'Integer') . ')';
if ($acl_role) {
$where .= " AND {$t['ACL']}.acl_table = '{$t['ACLRole']}'";
}
else {
$where .= " AND {$t['ACL']}.acl_table = '{$t['ACL']}'";
}
}

$query = [];

/* Query for permissions granted to all contacts in the domain */

$query[] = "SELECT {$t['ACL']}.*, 0 as override
FROM {$t['ACL']}
WHERE {$t['ACL']}.entity_table = '{$t['Domain']}'
AND ($where)";

/* Query for permissions granted to all contacts through an ACL group */

$query[] = "SELECT {$t['ACL']}.*, 0 as override
FROM {$t['ACL']}
INNER JOIN {$t['ACLEntityRole']}
ON ({$t['ACL']}.entity_table = '{$t['ACLRole']}'
AND {$t['ACL']}.entity_id =
{$t['ACLEntityRole']}.acl_role_id)
INNER JOIN {$t['ACLRole']}
ON {$t['ACL']}.entity_id =
{$t['ACLRole']}.id
WHERE {$t['ACLEntityRole']}.entity_table =
'{$t['Domain']}'
AND {$t['ACLRole']}.is_active = 1
AND ($where)";

/* Query for permissions granted directly to the contact */

$query[] = "SELECT {$t['ACL']}.*, 1 as override
FROM {$t['ACL']}
INNER JOIN {$t['Contact']}
ON ({$t['ACL']}.entity_table = '{$t['Contact']}'
AND {$t['ACL']}.entity_id = {$t['Contact']}.id)
WHERE {$t['Contact']}.id = $contact_id
AND ($where)";

/* Query for permissions granted to the contact through an ACL group */

$query[] = "SELECT {$t['ACL']}.*, 1 as override
FROM {$t['ACL']}
INNER JOIN {$t['ACLEntityRole']}
ON ({$t['ACL']}.entity_table = '{$t['ACLRole']}'
AND {$t['ACL']}.entity_id =
{$t['ACLEntityRole']}.acl_role_id)
INNER JOIN {$t['ACLRole']}
ON {$t['ACL']}.entity_id = {$t['ACLRole']}.id
WHERE {$t['ACLEntityRole']}.entity_table =
'{$t['Contact']}'
AND {$t['ACLRole']}.is_active = 1
AND {$t['ACLEntityRole']}.entity_id = $contact_id
AND ($where)";

/* Query for permissions granted to the contact through a group */

$query[] = "SELECT {$t['ACL']}.*, 0 as override
FROM {$t['ACL']}
INNER JOIN {$t['GroupContact']}
ON ({$t['ACL']}.entity_table = '{$t['Group']}'
AND {$t['ACL']}.entity_id =
{$t['GroupContact']}.group_id)
WHERE ($where)
AND {$t['GroupContact']}.contact_id = $contact_id
AND {$t['GroupContact']}.status = 'Added')";

/* Query for permissions granted through an ACL group to a Contact
* group */

$query[] = "SELECT {$t['ACL']}.*, 0 as override
FROM {$t['ACL']}
INNER JOIN {$t['ACLEntityRole']}
ON ({$t['ACL']}.entity_table = '{$t['ACLRole']}'
AND {$t['ACL']}.entity_id =
{$t['ACLEntityRole']}.acl_role_id)
INNER JOIN {$t['ACLRole']}
ON {$t['ACL']}.entity_id = {$t['ACLRole']}.id
INNER JOIN {$t['GroupContact']}
ON ({$t['ACLEntityRole']}.entity_table =
'{$t['Group']}'
AND {$t['ACLEntityRole']}.entity_id =
{$t['GroupContact']}.group_id)
WHERE ($where)
AND {$t['ACLRole']}.is_active = 1
AND {$t['GroupContact']}.contact_id = $contact_id
AND {$t['GroupContact']}.status = 'Added'";

$union = '(' . implode(') UNION DISTINCT (', $query) . ')';

$dao->query($union);

$allow = [0];
$deny = [0];
$override = [];

while ($dao->fetch()) {
/* Instant bypass for the following cases:
* 1) the rule governs all tables
* 2) the rule governs all objects in the table in question
* 3) the rule governs the specific object we want
*/

if (empty($dao->object_table) ||
($dao->object_table == $object_table
&& (empty($dao->object_id)
|| $dao->object_id == $object_id
)
)
) {
$clause = 1;
}
else {
/* Otherwise try to generate a clause for this rule */

$clause = self::getClause(
$dao->object_table, $dao->object_id, $tables
);

/* If the clause returned is null, then the rule is a blanket
* (id is null) on a table other than the one we're interested
* in. So skip it. */

if (empty($clause)) {
continue;
}
}

/* Now we figure out if this is an allow or deny rule, and possibly
* a contact-level override */

if ($dao->deny) {
$deny[] = $clause;
}
else {
$allow[] = $clause;

if ($dao->override) {
$override[] = $clause;
}
}
}

$allows = '(' . implode(' OR ', $allow) . ')';
$denies = '(' . implode(' OR ', $deny) . ')';
if (!empty($override)) {
$denies = '(NOT (' . implode(' OR ', $override) . ") AND $denies)";
}

return "($allows AND NOT $denies)";
}

/**
* Given a table and id pair, return the filter clause
*
Expand Down

0 comments on commit cbd6ceb

Please sign in to comment.