From 5915831ab369a20647ca36c864ffbfc0875f8747 Mon Sep 17 00:00:00 2001 From: sebalis Date: Sat, 9 Sep 2023 02:56:50 +0200 Subject: [PATCH] dev/core#4542 Fix priority handling in ACLs when dealing with objects other than contacts, and remove code duplication Co-authored-by: Seamus Lee --- CRM/ACL/BAO/ACL.php | 117 ++++++++++++++++++++++---------------------- 1 file changed, 59 insertions(+), 58 deletions(-) diff --git a/CRM/ACL/BAO/ACL.php b/CRM/ACL/BAO/ACL.php index ab6495a157..be0673a50a 100644 --- a/CRM/ACL/BAO/ACL.php +++ b/CRM/ACL/BAO/ACL.php @@ -222,31 +222,13 @@ SELECT count( a.id ) * @return null|string */ public static function whereClause($type, &$tables, &$whereTables, $contactID = NULL) { - $acls = CRM_ACL_BAO_Cache::build($contactID); $whereClause = NULL; $allInclude = $allExclude = FALSE; $clauses = []; - if (!empty($acls)) { - $aclKeys = array_keys($acls); - $aclKeys = implode(',', $aclKeys); - $orderBy = 'a.object_id'; - if (array_key_exists('priority', CRM_ACL_BAO_ACL::getSupportedFields())) { - $orderBy .= ',a.priority'; - } - $query = " -SELECT a.operation, a.object_id,a.deny - FROM civicrm_acl_cache c, civicrm_acl a - WHERE c.acl_id = a.id - AND a.is_active = 1 - AND a.object_table = 'civicrm_group' - AND a.id IN ( $aclKeys ) -ORDER BY {$orderBy} -"; - - $dao = CRM_Core_DAO::executeQuery($query); - + $dao = self::getOrderedActiveACLs($contactID, 'civicrm_group'); + if ($dao !== NULL) { // do an or of all the where clauses u see $ids = $excludeIds = []; while ($dao->fetch()) { @@ -451,54 +433,73 @@ ORDER BY {$orderBy} */ protected static function loadPermittedIDs(int $contactID, string $tableName, int $type, $allGroups): array { $ids = []; - $acls = CRM_ACL_BAO_Cache::build($contactID); - $aclKeys = array_keys($acls); - $aclKeys = implode(',', $aclKeys); - $orderBy = 'a.object_id'; - if (array_key_exists('priority', CRM_ACL_BAO_ACL::getSupportedFields())) { - $orderBy .= ',a.priority'; - } - $query = " -SELECT a.operation,a.object_id,a.deny - FROM civicrm_acl_cache c, civicrm_acl a - WHERE c.acl_id = a.id - AND a.is_active = 1 - AND a.object_table = %1 - AND a.id IN ( $aclKeys ) -ORDER BY {$orderBy} -"; - $params = [1 => [$tableName, 'String']]; - $dao = CRM_Core_DAO::executeQuery($query, $params); - while ($dao->fetch()) { - if ($dao->object_id) { - if (self::matchType($type, $dao->operation)) { - if (!$dao->deny) { - $ids[] = $dao->object_id; - } - else { - $ids = array_diff($ids, [$dao->object_id]); + $dao = self::getOrderedActiveACLs($contactID, $tableName); + if ($dao !== NULL) { + while ($dao->fetch()) { + if ($dao->object_id) { + if (self::matchType($type, $dao->operation)) { + if (!$dao->deny) { + $ids[] = $dao->object_id; + } + else { + $ids = array_diff($ids, [$dao->object_id]); + } } } - } - else { - // this user has got the permission for all objects of this type - // check if the type matches - if (self::matchType($type, $dao->operation)) { - if (!$dao->deny) { - foreach ($allGroups as $id => $dontCare) { - $ids[] = $id; + else { + // this user has got the permission for all objects of this type + // check if the type matches + if (self::matchType($type, $dao->operation)) { + if (!$dao->deny) { + foreach ($allGroups as $id => $dontCare) { + $ids[] = $id; + } + } + else { + $ids = array_diff($ids, array_keys($allGroups)); } - } - else { - $ids = array_diff($ids, array_keys($allGroups)); } } - break; } } return $ids; } + /** + * Execute a query to find active ACLs for a contact, ordered by priority (if supported) and object ID. + * The query returns the 'operation', 'object_id' and 'deny' properties. + * Returns NULL if CRM_ACL_BAO_Cache::build (effectively, CRM_ACL_BAO_ACL::getAllByContact) + * returns no ACLs (active or not) for the contact. + * + * @param string $contactID + * @param string $tableName + * @return NULL|CRM_Core_DAO|object + */ + private static function getOrderedActiveACLs(string $contactID, string $tableName) { + $dao = NULL; + $acls = CRM_ACL_BAO_Cache::build($contactID); + if (!empty($acls)) { + $aclKeys = array_keys($acls); + $aclKeys = implode(',', $aclKeys); + $orderBy = 'a.object_id'; + if (array_key_exists('priority', CRM_ACL_BAO_ACL::getSupportedFields())) { + $orderBy = "a.priority, $orderBy"; + } + $query = " +SELECT a.operation, a.object_id, a.deny + FROM civicrm_acl_cache c, civicrm_acl a + WHERE c.acl_id = a.id + AND a.is_active = 1 + AND a.object_table = %1 + AND a.id IN ({$aclKeys}) +ORDER BY {$orderBy} +"; + $params = [1 => [$tableName, 'String']]; + $dao = CRM_Core_DAO::executeQuery($query, $params); + } + return $dao; + } + private static function getGroupClause(array $groupIDs, string $operation): string { $ids = implode(',', $groupIDs); $query = " -- 2.25.1