From 188fd46bb2ddf0d77dd12e11c4f33431192c9262 Mon Sep 17 00:00:00 2001 From: Coleman Watts Date: Fri, 8 Jan 2016 09:13:49 -0500 Subject: [PATCH] CRM-17795 - Add aclWhere clause to contact-related apis --- CRM/Contact/BAO/Contact/Permission.php | 31 ++++++++++++++++++-------- Civi/API/SelectQuery.php | 15 +++++++++++++ 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/CRM/Contact/BAO/Contact/Permission.php b/CRM/Contact/BAO/Contact/Permission.php index dfb82a2aa7..761b657252 100644 --- a/CRM/Contact/BAO/Contact/Permission.php +++ b/CRM/Contact/BAO/Contact/Permission.php @@ -182,11 +182,10 @@ AND $operationClause LIMIT 1"; /** * @param string $contactAlias - * @param int $contactID * * @return array */ - public static function cacheClause($contactAlias = 'contact_a', $contactID = NULL) { + public static function cacheClause($contactAlias = 'contact_a') { if (CRM_Core_Permission::check('view all contacts') || CRM_Core_Permission::check('edit all contacts') ) { @@ -204,13 +203,7 @@ AND $operationClause LIMIT 1"; } } - $session = CRM_Core_Session::singleton(); - $contactID = $session->get('userID'); - if (!$contactID) { - $contactID = 0; - } - $contactID = CRM_Utils_Type::escape($contactID, 'Integer'); - + $contactID = (int) CRM_Core_Session::getLoggedInContactID(); self::cache($contactID); if (is_array($contactAlias) && !empty($contactAlias)) { @@ -231,6 +224,26 @@ AND $operationClause LIMIT 1"; return array($fromClause, $whereClase); } + /** + * Generate acl subquery that can be placed in the WHERE clause of a query or the ON clause of a JOIN + * + * @param string $contactIdField + * Full "table_name.field_name" for the field containing a contact id + * @return string + */ + public static function cacheSubquery($contactIdField) { + $clauses = array(); + if (!CRM_Core_Permission::check(array(array('view all contacts', 'edit all contacts')))) { + $contactID = (int) CRM_Core_Session::getLoggedInContactID(); + self::cache($contactID); + $clauses[] = "$contactIdField IN (SELECT contact_id FROM civicrm_acl_contact_cache WHERE user_id = $contactID)"; + } + if (!CRM_Core_Permission::check('access deleted contacts')) { + $clauses[] = "$contactIdField NOT IN (SELECT id FROM civicrm_contact WHERE is_deleted = 1)"; + } + return $clauses ? implode(' AND ', $clauses) : '1'; + } + /** * Get the permission base on its relationship. * diff --git a/Civi/API/SelectQuery.php b/Civi/API/SelectQuery.php index ca054b4db6..cbc1cb0bb3 100644 --- a/Civi/API/SelectQuery.php +++ b/Civi/API/SelectQuery.php @@ -272,6 +272,9 @@ class SelectQuery { $this->query->limit($this->options['limit'], $this->options['offset']); } + // ACLs + $this->addAclClause(); + $result_entities = array(); $result_dao = \CRM_Core_DAO::executeQuery($this->query->toSQL()); @@ -449,4 +452,16 @@ class SelectQuery { return \Civi::service('civi_api_kernel')->runAuthorize($entity, 'get', $params); } + /** + * If this entity has a `contact_id` field, add appropriate acl clause + */ + private function addAclClause() { + if (in_array('contact_id', $this->entityFieldNames)) { + $clause = \CRM_Contact_BAO_Contact_Permission::cacheSubquery('a.contact_id'); + if ($clause !== '1') { + $this->query->where($clause); + } + } + } + } -- 2.25.1