From 7ffbc14effcf98ade1381002375947b36af712b6 Mon Sep 17 00:00:00 2001 From: Seamus Lee Date: Tue, 12 Jan 2021 18:14:10 +1100 Subject: [PATCH] dev/wordpress#86 Ensure that the list of groups in search or on the new individual screen reflect any ACLs applied on them Move group handling code to Base file as per Eileen Fix test failures by switching to Civi:: --- CRM/Core/Permission/Base.php | 134 +++++++++++++- CRM/Core/Permission/DrupalBase.php | 186 -------------------- tests/phpunit/CRM/Contact/BAO/GroupTest.php | 1 + tests/phpunit/api/v3/ContactTest.php | 3 + tests/phpunit/api/v3/MailingTest.php | 4 +- 5 files changed, 137 insertions(+), 191 deletions(-) diff --git a/CRM/Core/Permission/Base.php b/CRM/Core/Permission/Base.php index 68c2cd53d0..1ceae88d7e 100644 --- a/CRM/Core/Permission/Base.php +++ b/CRM/Core/Permission/Base.php @@ -26,6 +26,22 @@ class CRM_Core_Permission_Base { */ public $permissions = NULL; + /** + * Is this user someone with access for the entire system. + * + * @var bool + */ + protected $_viewAdminUser = FALSE; + protected $_editAdminUser = FALSE; + + /** + * Am in in view permission or edit permission? + * + * @var bool + */ + protected $_viewPermission = FALSE; + protected $_editPermission = FALSE; + /** * Translate permission. * @@ -65,7 +81,15 @@ class CRM_Core_Permission_Base { * the permission of the user (edit or view or null) */ public function getPermission() { - return CRM_Core_Permission::EDIT; + $this->group(); + + if ($this->_editPermission) { + return CRM_Core_Permission::EDIT; + } + elseif ($this->_viewPermission) { + return CRM_Core_Permission::VIEW; + } + return NULL; } /** @@ -117,7 +141,56 @@ class CRM_Core_Permission_Base { * array reference of all groups. */ public function group($groupType = NULL, $excludeHidden = TRUE) { - return CRM_Core_PseudoConstant::allGroup($groupType, $excludeHidden); + $userId = CRM_Core_Session::getLoggedInContactID(); + $domainId = CRM_Core_Config::domainID(); + if (!isset(Civi::$statics[__CLASS__]['viewPermissionedGroups_' . $domainId . '_' . $userId])) { + Civi::$statics[__CLASS__]['viewPermissionedGroups_' . $domainId . '_' . $userId] = Civi::$statics[__CLASS__]['editPermissionedGroups_' . $domainId . '_' . $userId] = []; + } + + $groupKey = $groupType ? $groupType : 'all'; + + if (!isset(Civi::$statics[__CLASS__]['viewPermissionedGroups_' . $domainId . '_' . $userId][$groupKey])) { + Civi::$statics[__CLASS__]['viewPermissionedGroups_' . $domainId . '_' . $userId][$groupKey] = Civi::$statics[__CLASS__]['editPermissionedGroups_' . $domainId . '_' . $userId][$groupKey] = []; + + $groups = CRM_Core_PseudoConstant::allGroup($groupType, $excludeHidden); + + if ($this->check('edit all contacts')) { + // this is the most powerful permission, so we return + // immediately rather than dilute it further + $this->_editAdminUser = $this->_viewAdminUser = TRUE; + $this->_editPermission = $this->_viewPermission = TRUE; + Civi::$statics[__CLASS__]['editPermissionedGroups_' . $domainId . '_' . $userId][$groupKey] = $groups; + Civi::$statics[__CLASS__]['viewPermissionedGroups_' . $domainId . '_' . $userId][$groupKey] = $groups; + return Civi::$statics[__CLASS__]['viewPermissionedGroups_' . $domainId . '_' . $userId][$groupKey]; + } + elseif ($this->check('view all contacts')) { + $this->_viewAdminUser = TRUE; + $this->_viewPermission = TRUE; + Civi::$statics[__CLASS__]['viewPermissionedGroups_' . $domainId . '_' . $userId][$groupKey] = $groups; + } + + $ids = CRM_ACL_API::group(CRM_Core_Permission::VIEW, NULL, 'civicrm_saved_search', $groups); + if (!empty($ids)) { + foreach (array_values($ids) as $id) { + $title = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Group', $id, 'title'); + Civi::$statics[__CLASS__]['viewPermissionedGroups_' . $domainId . '_' . $userId][$groupKey][$id] = $title; + $this->_viewPermission = TRUE; + } + } + + $ids = CRM_ACL_API::group(CRM_Core_Permission::EDIT, NULL, 'civicrm_saved_search', $groups); + if (!empty($ids)) { + foreach (array_values($ids) as $id) { + $title = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Group', $id, 'title'); + Civi::$statics[__CLASS__]['editPermissionedGroups_' . $domainId . '_' . $userId][$groupKey][$id] = $title; + Civi::$statics[__CLASS__]['viewPermissionedGroups_' . $domainId . '_' . $userId][$groupKey][$id] = $title; + $this->_editPermission = TRUE; + $this->_viewPermission = TRUE; + } + } + } + + return Civi::$statics[__CLASS__]['viewPermissionedGroups_' . $domainId . '_' . $userId][$groupKey]; } /** @@ -134,7 +207,62 @@ class CRM_Core_Permission_Base { * the group where clause for this user */ public function groupClause($type, &$tables, &$whereTables) { - return ' (1) '; + $userId = CRM_Core_Session::getLoggedInContactID(); + $domainId = CRM_Core_Config::domainID(); + if (!isset(Civi::$statics[__CLASS__]['viewPermissionedGroups_' . $domainId . '_' . $userId])) { + $this->group(); + } + + // we basically get all the groups here + $groupKey = 'all'; + if ($type == CRM_Core_Permission::EDIT) { + if ($this->_editAdminUser) { + $clause = ' ( 1 ) '; + } + elseif (empty(Civi::$statics[__CLASS__]['editPermissionedGroups_' . $domainId . '_' . $userId][$groupKey])) { + $clause = ' ( 0 ) '; + } + else { + $clauses = []; + $groups = implode(', ', Civi::$statics[__CLASS__]['editPermissionedGroups_' . $domainId . '_' . $userId][$groupKey]); + $clauses[] = ' ( civicrm_group_contact.group_id IN ( ' . implode(', ', array_keys(Civi::$statics[__CLASS__]['editPermissionedGroups_' . $domainId . '_' . $userId][$groupKey])) . " ) AND civicrm_group_contact.status = 'Added' ) "; + $tables['civicrm_group_contact'] = 1; + $whereTables['civicrm_group_contact'] = 1; + + // foreach group that is potentially a saved search, add the saved search clause + foreach (array_keys(Civi::$statics[__CLASS__]['editPermissionedGroups_' . $domainId . '_' . $userId][$groupKey]) as $id) { + $group = new CRM_Contact_DAO_Group(); + $group->id = $id; + if ($group->find(TRUE) && $group->saved_search_id) { + $clause = CRM_Contact_BAO_SavedSearch::whereClause($group->saved_search_id, + $tables, + $whereTables + ); + if (trim($clause)) { + $clauses[] = $clause; + } + } + } + $clause = ' ( ' . implode(' OR ', $clauses) . ' ) '; + } + } + else { + if ($this->_viewAdminUser) { + $clause = ' ( 1 ) '; + } + elseif (empty(Civi::$statics[__CLASS__]['viewPermissionedGroups_' . $domainId . '_' . $userId][$groupKey])) { + $clause = ' ( 0 ) '; + } + else { + $clauses = []; + $groups = implode(', ', Civi::$statics[__CLASS__]['viewPermissionedGroups_' . $domainId . '_' . $userId][$groupKey]); + $clauses[] = ' civicrm_group.id IN (' . implode(', ', array_keys(Civi::$statics[__CLASS__]['viewPermissionedGroups_' . $domainId . '_' . $userId][$groupKey])) . " ) "; + $tables['civicrm_group'] = 1; + $whereTables['civicrm_group'] = 1; + $clause = ' ( ' . implode(' OR ', $clauses) . ' ) '; + } + } + return $clause; } /** diff --git a/CRM/Core/Permission/DrupalBase.php b/CRM/Core/Permission/DrupalBase.php index 23db51cae8..604a2be0b7 100644 --- a/CRM/Core/Permission/DrupalBase.php +++ b/CRM/Core/Permission/DrupalBase.php @@ -20,192 +20,6 @@ */ class CRM_Core_Permission_DrupalBase extends CRM_Core_Permission_Base { - /** - * Is this user someone with access for the entire system. - * - * @var bool - */ - protected $_viewAdminUser = FALSE; - protected $_editAdminUser = FALSE; - - /** - * Am in in view permission or edit permission? - * - * @var bool - */ - protected $_viewPermission = FALSE; - protected $_editPermission = FALSE; - - /** - * The current set of permissioned groups for the user. - * - * @var array - */ - protected $_viewPermissionedGroups; - protected $_editPermissionedGroups; - - /** - * Get all groups from database, filtered by permissions - * for this user - * - * @param string $groupType - * Type of group(Access/Mailing). - * @param bool $excludeHidden - * Exclude hidden groups. - * - * - * @return array - * array reference of all groups. - */ - public function group($groupType = NULL, $excludeHidden = TRUE) { - if (!isset($this->_viewPermissionedGroups)) { - $this->_viewPermissionedGroups = $this->_editPermissionedGroups = []; - } - - $groupKey = $groupType ? $groupType : 'all'; - - if (!isset($this->_viewPermissionedGroups[$groupKey])) { - $this->_viewPermissionedGroups[$groupKey] = $this->_editPermissionedGroups[$groupKey] = []; - - $groups = CRM_Core_PseudoConstant::allGroup($groupType, $excludeHidden); - - if ($this->check('edit all contacts')) { - // this is the most powerful permission, so we return - // immediately rather than dilute it further - $this->_editAdminUser = $this->_viewAdminUser = TRUE; - $this->_editPermission = $this->_viewPermission = TRUE; - $this->_editPermissionedGroups[$groupKey] = $groups; - $this->_viewPermissionedGroups[$groupKey] = $groups; - return $this->_viewPermissionedGroups[$groupKey]; - } - elseif ($this->check('view all contacts')) { - $this->_viewAdminUser = TRUE; - $this->_viewPermission = TRUE; - $this->_viewPermissionedGroups[$groupKey] = $groups; - } - - $ids = CRM_ACL_API::group(CRM_Core_Permission::VIEW, NULL, 'civicrm_saved_search', $groups); - if (!empty($ids)) { - foreach (array_values($ids) as $id) { - $title = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Group', $id, 'title'); - $this->_viewPermissionedGroups[$groupKey][$id] = $title; - $this->_viewPermission = TRUE; - } - } - - $ids = CRM_ACL_API::group(CRM_Core_Permission::EDIT, NULL, 'civicrm_saved_search', $groups); - if (!empty($ids)) { - foreach (array_values($ids) as $id) { - $title = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Group', $id, 'title'); - $this->_editPermissionedGroups[$groupKey][$id] = $title; - $this->_viewPermissionedGroups[$groupKey][$id] = $title; - $this->_editPermission = TRUE; - $this->_viewPermission = TRUE; - } - } - } - - return $this->_viewPermissionedGroups[$groupKey]; - } - - /** - * Get group clause for this user. The group Clause filters the - * list of groups that the user is permitted to see in a group listing. - * For example it will filter both the list on the 'Manage Groups' page - * and on the contact 'Groups' tab - * - * the aclGroup hook & configured ACLs contribute to this data. - * If the contact is allowed to see all contacts the function will return ( 1 ) - * - * @todo the history of this function is that there was some confusion as to - * whether it was filtering contacts or groups & some cruft may remain - * - * @param int $type - * The type of permission needed. - * @param array $tables - * (reference) add the tables that are needed for the select clause. - * @param array $whereTables - * (reference) add the tables that are needed for the where clause. - * - * @return string - * the clause to add to the query retrieving viewable groups - */ - public function groupClause($type, &$tables, &$whereTables) { - if (!isset($this->_viewPermissionedGroups)) { - $this->group(); - } - - // we basically get all the groups here - $groupKey = 'all'; - if ($type == CRM_Core_Permission::EDIT) { - if ($this->_editAdminUser) { - $clause = ' ( 1 ) '; - } - elseif (empty($this->_editPermissionedGroups[$groupKey])) { - $clause = ' ( 0 ) '; - } - else { - $clauses = []; - $groups = implode(', ', $this->_editPermissionedGroups[$groupKey]); - $clauses[] = ' ( civicrm_group_contact.group_id IN ( ' . implode(', ', array_keys($this->_editPermissionedGroups[$groupKey])) . " ) AND civicrm_group_contact.status = 'Added' ) "; - $tables['civicrm_group_contact'] = 1; - $whereTables['civicrm_group_contact'] = 1; - - // foreach group that is potentially a saved search, add the saved search clause - foreach (array_keys($this->_editPermissionedGroups[$groupKey]) as $id) { - $group = new CRM_Contact_DAO_Group(); - $group->id = $id; - if ($group->find(TRUE) && $group->saved_search_id) { - $clause = CRM_Contact_BAO_SavedSearch::whereClause($group->saved_search_id, - $tables, - $whereTables - ); - if (trim($clause)) { - $clauses[] = $clause; - } - } - } - $clause = ' ( ' . implode(' OR ', $clauses) . ' ) '; - } - } - else { - if ($this->_viewAdminUser) { - $clause = ' ( 1 ) '; - } - elseif (empty($this->_viewPermissionedGroups[$groupKey])) { - $clause = ' ( 0 ) '; - } - else { - $clauses = []; - $groups = implode(', ', $this->_viewPermissionedGroups[$groupKey]); - $clauses[] = ' civicrm_group.id IN (' . implode(', ', array_keys($this->_viewPermissionedGroups[$groupKey])) . " ) "; - $tables['civicrm_group'] = 1; - $whereTables['civicrm_group'] = 1; - $clause = ' ( ' . implode(' OR ', $clauses) . ' ) '; - } - } - - return $clause; - } - - /** - * Get the current permission of this user. - * - * @return string - * the permission of the user (edit or view or null) - */ - public function getPermission() { - $this->group(); - - if ($this->_editPermission) { - return CRM_Core_Permission::EDIT; - } - elseif ($this->_viewPermission) { - return CRM_Core_Permission::VIEW; - } - return NULL; - } - /** * @param $uids * diff --git a/tests/phpunit/CRM/Contact/BAO/GroupTest.php b/tests/phpunit/CRM/Contact/BAO/GroupTest.php index 3fde423765..ebd2b6cff3 100644 --- a/tests/phpunit/CRM/Contact/BAO/GroupTest.php +++ b/tests/phpunit/CRM/Contact/BAO/GroupTest.php @@ -146,6 +146,7 @@ class CRM_Contact_BAO_GroupTest extends CiviUnitTestCase { ]; $group3 = CRM_Contact_BAO_Group::create($params); + unset(Civi::$statics['CRM_Core_Permission_Base']); // Check with no group type restriction $nestedGroup = CRM_Core_PseudoConstant::nestedGroup(); $this->assertEquals([ diff --git a/tests/phpunit/api/v3/ContactTest.php b/tests/phpunit/api/v3/ContactTest.php index b7a85306e9..846f10785e 100644 --- a/tests/phpunit/api/v3/ContactTest.php +++ b/tests/phpunit/api/v3/ContactTest.php @@ -4303,6 +4303,7 @@ class api_v3_ContactTest extends CiviUnitTestCase { 'group_id' => $create_group['id'], ]; $this->callApiSuccess('GroupContact', 'create', $group_contact_params); + unset(Civi::$statics['CRM_Core_Permission_Base']); $contact_get = $this->callAPISuccess('contact', 'get', ['group' => $title, 'return' => 'group']); $this->assertEquals(1, $contact_get['count']); $this->assertEquals($created_contact_id, $contact_get['id']); @@ -4346,6 +4347,7 @@ class api_v3_ContactTest extends CiviUnitTestCase { 'created_id' => $created_contact_id, ]; $create_group = $this->callAPISuccess('Group', 'create', $group_params); + unset(Civi::$statics['CRM_Core_Permission_Base']); $createdGroupsIds[] = $create_group['id']; $createdGroupTitles[] = $title; // Add contact to the new group. @@ -4413,6 +4415,7 @@ class api_v3_ContactTest extends CiviUnitTestCase { ]; $this->callApiSuccess('GroupContact', 'create', $group_contact_params); } + unset(Civi::$statics['CRM_Core_Permission_Base']); $contact_get = $this->callAPISuccess('contact', 'get', ['group' => [$createdGroupTitles[0] => 1], 'return' => 'group']); $this->assertEquals(1, $contact_get['count']); $this->assertEquals($created_contact_id, $contact_get['id']); diff --git a/tests/phpunit/api/v3/MailingTest.php b/tests/phpunit/api/v3/MailingTest.php index 962101dc59..748a73278a 100644 --- a/tests/phpunit/api/v3/MailingTest.php +++ b/tests/phpunit/api/v3/MailingTest.php @@ -505,7 +505,7 @@ class api_v3_MailingTest extends CiviUnitTestCase { 'contact_id' => $contactIDs['carol'], ]); // END SAMPLE DATA - + unset(Civi::$statics['CRM_Core_Permission_Base']); $mail = $this->callAPISuccess('mailing', 'create', $this->_params); $deliveredInfo = $this->callAPISuccess($this->_entity, 'send_test', [ 'mailing_id' => $mail['id'], @@ -710,6 +710,7 @@ class api_v3_MailingTest extends CiviUnitTestCase { 'group_type' => 'Include', ]; $mailingGroup = $this->callAPISuccess('MailingGroup', 'create', $mgParams); + unset(Civi::$statics['CRM_Core_Permission_Base']); //Include previous mail in the mailing group. $mail2 = $this->callAPISuccess('mailing', 'create', $this->_params); @@ -728,7 +729,6 @@ class api_v3_MailingTest extends CiviUnitTestCase { $jobId = CRM_Core_DAO::getFieldValue('CRM_Mailing_DAO_MailingJob', $mail2['id'], 'id', 'mailing_id'); $hash = CRM_Core_DAO::getFieldValue('CRM_Mailing_Event_DAO_Queue', $jobId, 'hash', 'job_id'); $queueId = CRM_Core_DAO::getFieldValue('CRM_Mailing_Event_DAO_Queue', $jobId, 'id', 'job_id'); - $group = CRM_Mailing_Event_BAO_Unsubscribe::unsub_from_mailing($jobId, $queueId, $hash, TRUE); //Assert only one group returns in the unsubscribe list. $this->assertCount(1, $group); -- 2.25.1