3 +--------------------------------------------------------------------+
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2020 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
29 * This class is intended to test ACL permission using the multisite module
31 * @package CiviCRM_APIv3
32 * @subpackage API_Contact
35 class api_v3_ACLPermissionTest
extends CiviUnitTestCase
{
37 use CRMTraits_ACL_PermissionTrait
;
39 public $DBResetRequired = FALSE;
42 public function setUp() {
44 $baoObj = new CRM_Core_DAO();
45 $baoObj->createTestObject('CRM_Pledge_BAO_Pledge', [], 1, 0);
46 $baoObj->createTestObject('CRM_Core_BAO_Phone', [], 1, 0);
47 $this->prepareForACLs();
52 * @see CiviUnitTestCase::tearDown()
54 public function tearDown() {
55 $this->cleanUpAfterACLs();
58 'civicrm_group_contact',
62 'civicrm_acl_entity_role',
63 'civicrm_acl_contact_cache',
64 'civicrm_contribution',
65 'civicrm_participant',
68 'civicrm_activity_contact',
73 $this->quickCleanup($tablesToTruncate);
77 * Function tests that an empty where hook returns no results.
79 * @dataProvider versionThreeAndFour
81 public function testContactGetNoResultsHook($version) {
82 $this->_apiversion
= $version;
83 $this->hookClass
->setHook('civicrm_aclWhereClause', [
85 'aclWhereHookNoResults',
87 $result = $this->callAPISuccess('contact', 'get', [
88 'check_permissions' => 1,
89 'return' => 'display_name',
91 $this->assertEquals(0, $result['count']);
95 * Function tests that an empty where hook returns exactly 1 result with "view my contact".
97 * CRM-16512 caused contacts with Edit my contact to be able to view all records.
99 * @dataProvider versionThreeAndFour
101 public function testContactGetOneResultHookWithViewMyContact($version) {
102 $this->_apiversion
= $version;
103 $this->createLoggedInUser();
104 $this->hookClass
->setHook('civicrm_aclWhereClause', [
106 'aclWhereHookNoResults',
108 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= [
112 $result = $this->callAPISuccess('contact', 'get', [
113 'check_permissions' => 1,
114 'return' => 'display_name',
116 $this->assertEquals(1, $result['count']);
120 * Function tests that a user with "edit my contact" can edit themselves.
121 * @param int $version
122 * @dataProvider versionThreeAndFour
124 public function testContactEditHookWithEditMyContact($version) {
125 $this->_apiversion
= $version;
126 $cid = $this->createLoggedInUser();
127 $this->hookClass
->setHook('civicrm_aclWhereClause', [
129 'aclWhereHookNoResults',
131 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= [
135 $this->callAPISuccess('contact', 'create', [
136 'check_permissions' => 1,
138 'first_name' => 'NewName',
143 * Ensure contact permissions do not block contact-less location entities.
144 * @param int $version
145 * @dataProvider versionThreeAndFour
147 public function testAddressWithoutContactIDAccess($version) {
148 $this->_apiversion
= $version;
149 $ownID = $this->createLoggedInUser();
150 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= [
154 $this->callAPISuccess('Address', 'create', [
155 'city' => 'Mouseville',
156 'location_type_id' => 'Main',
157 'api.LocBlock.create' => 1,
158 'contact_id' => $ownID,
160 $this->callAPISuccessGetSingle('Address', [
161 'city' => 'Mouseville',
162 'check_permissions' => 1,
164 CRM_Core_DAO
::executeQuery('UPDATE civicrm_address SET contact_id = NULL WHERE contact_id = %1', [
170 $this->callAPISuccessGetSingle('Address', [
171 'city' => 'Mouseville',
172 'check_permissions' => 1,
177 * Ensure contact permissions extend to related entities like email
178 * @param int $version
179 * @dataProvider versionThreeAndFour
180 * FIXME: Finish api4 part
182 public function testRelatedEntityPermissions($version) {
183 $this->_apiversion
= $version;
184 $this->createLoggedInUser();
185 $disallowedContact = $this->individualCreate([], 0);
186 $this->allowedContactId
= $this->individualCreate([], 1);
187 $this->hookClass
->setHook('civicrm_aclWhereClause', [
191 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= ['access CiviCRM'];
193 'Email' => ['email' => 'null@nothing', 'location_type_id' => 1],
194 'Phone' => ['phone' => '123456', 'location_type_id' => 1],
195 'IM' => ['name' => 'hello', 'location_type_id' => 1],
196 'Website' => ['url' => 'http://test'],
198 'street_address' => '123 Sesame St.',
199 'location_type_id' => 1,
202 foreach ($testEntities as $entity => $params) {
204 'contact_id' => $disallowedContact,
205 'check_permissions' => 1,
207 // We should be prevented from getting or creating entities for a contact we don't have permission for
208 $this->callAPIFailure($entity, 'create', $params);
209 $this->callAPISuccess($entity, 'create', ['check_permissions' => 0] +
$params);
210 $results = $this->callAPISuccess($entity, 'get', [
211 'contact_id' => $disallowedContact,
212 'check_permissions' => 1,
214 $this->assertEquals(0, $results['count']);
216 // We should be allowed to create and get for contacts we do have permission on
217 $params['contact_id'] = $this->allowedContactId
;
218 $this->callAPISuccess($entity, 'create', $params);
219 $results = $this->callAPISuccess($entity, 'get', [
220 'contact_id' => $this->allowedContactId
,
221 'check_permissions' => 1,
223 $this->assertGreaterThan(0, $results['count']);
226 $this->markTestIncomplete('Skipping entity_id related perms in api4 for now.');
228 $newTag = civicrm_api3('Tag', 'create', [
232 'Note' => ['note' => 'abc'],
233 'EntityTag' => ['tag_id' => $newTag['id']],
235 foreach ($relatedEntities as $entity => $params) {
237 'entity_id' => $disallowedContact,
238 'entity_table' => 'civicrm_contact',
239 'check_permissions' => 1,
241 // We should be prevented from getting or creating entities for a contact we don't have permission for
242 $this->callAPIFailure($entity, 'create', $params);
243 $this->callAPISuccess($entity, 'create', ['check_permissions' => 0] +
$params);
244 $results = $this->callAPISuccess($entity, 'get', [
245 'entity_id' => $disallowedContact,
246 'entity_table' => 'civicrm_contact',
247 'check_permissions' => 1,
249 $this->assertEquals(0, $results['count']);
251 // We should be allowed to create and get for entities we do have permission on
252 $params['entity_id'] = $this->allowedContactId
;
253 $this->callAPISuccess($entity, 'create', $params);
254 $results = $this->callAPISuccess($entity, 'get', [
255 'entity_id' => $this->allowedContactId
,
256 'entity_table' => 'civicrm_contact',
257 'check_permissions' => 1,
259 $this->assertGreaterThan(0, $results['count']);
264 * Function tests all results are returned.
265 * @param int $version
266 * @dataProvider versionThreeAndFour
268 public function testContactGetAllResultsHook($version) {
269 $this->_apiversion
= $version;
270 $this->hookClass
->setHook('civicrm_aclWhereClause', [
272 'aclWhereHookAllResults',
274 $result = $this->callAPISuccess('contact', 'get', [
275 'check_permissions' => 1,
276 'return' => 'display_name',
279 $this->assertEquals(2, $result['count']);
283 * Function tests that deleted contacts are not returned.
284 * @param int $version
285 * @dataProvider versionThreeAndFour
287 public function testContactGetPermissionHookNoDeleted($version) {
288 $this->_apiversion
= $version;
289 $this->callAPISuccess('contact', 'create', ['id' => 2, 'is_deleted' => 1]);
290 $this->hookClass
->setHook('civicrm_aclWhereClause', [
292 'aclWhereHookAllResults',
294 $result = $this->callAPISuccess('contact', 'get', [
295 'check_permissions' => 1,
296 'return' => 'display_name',
298 $this->assertEquals(1, $result['count']);
302 * Test permissions limited by hook.
303 * @param int $version
304 * @dataProvider versionThreeAndFour
306 public function testContactGetHookLimitingHook($version) {
307 $this->_apiversion
= $version;
308 $this->hookClass
->setHook('civicrm_aclWhereClause', [
310 'aclWhereOnlySecond',
313 $result = $this->callAPISuccess('contact', 'get', [
314 'check_permissions' => 1,
315 'return' => 'display_name',
317 $this->assertEquals(1, $result['count']);
321 * Confirm that without check permissions we still get 2 contacts returned.
322 * @param int $version
323 * @dataProvider versionThreeAndFour
325 public function testContactGetHookLimitingHookDontCheck($version) {
326 $this->_apiversion
= $version;
327 $result = $this->callAPISuccess('contact', 'get', [
328 'check_permissions' => 0,
329 'return' => 'display_name',
331 $this->assertEquals(2, $result['count']);
335 * Check that id works as a filter.
336 * @param int $version
337 * @dataProvider versionThreeAndFour
339 public function testContactGetIDFilter($version) {
340 $this->_apiversion
= $version;
341 $this->hookClass
->setHook('civicrm_aclWhereClause', [
343 'aclWhereHookAllResults',
345 $result = $this->callAPISuccess('contact', 'get', [
348 'check_permissions' => 1,
351 $this->assertEquals(1, $result['count']);
352 $this->assertEquals(2, $result['id']);
356 * Check that address IS returned.
358 public function testContactGetAddressReturned() {
359 $this->hookClass
->setHook('civicrm_aclWhereClause', [
361 'aclWhereOnlySecond',
363 $fullresult = $this->callAPISuccess('contact', 'get', [
366 //return doesn't work for all keys - can't fix that here so let's skip ...
367 //prefix & suffix are inconsistent due to CRM-7929
368 // unsure about others but return doesn't work on them
369 $elementsReturnDoesntSupport = [
380 $expectedReturnElements = array_diff(array_keys($fullresult['values'][0]), $elementsReturnDoesntSupport);
381 $result = $this->callAPISuccess('contact', 'get', [
382 'check_permissions' => 1,
383 'return' => $expectedReturnElements,
386 $this->assertEquals(1, $result['count']);
387 foreach ($expectedReturnElements as $element) {
388 $this->assertArrayHasKey($element, $result['values'][0]);
393 * Check that pledge IS not returned.
394 * @param int $version
395 * @dataProvider versionThreeAndFour
397 public function testContactGetPledgeIDNotReturned($version) {
398 $this->_apiversion
= $version;
399 $this->hookClass
->setHook('civicrm_aclWhereClause', [
401 'aclWhereHookAllResults',
403 $this->callAPISuccess('contact', 'get', [
406 $result = $this->callAPISuccess('contact', 'get', [
407 'check_permissions' => 1,
408 'return' => 'pledge_id',
411 $this->assertArrayNotHasKey('pledge_id', $result['values'][0]);
415 * Check that pledge IS not an allowable filter.
417 public function testContactGetPledgeIDNotFiltered() {
418 $this->hookClass
->setHook('civicrm_aclWhereClause', [
420 'aclWhereHookAllResults',
422 $this->callAPISuccess('contact', 'get', [
425 $result = $this->callAPISuccess('contact', 'get', [
426 'check_permissions' => 1,
430 $this->assertEquals(2, $result['count']);
434 * Check that chaining doesn't bypass permissions
435 * @param int $version
436 * @dataProvider versionThreeAndFour
438 public function testContactGetPledgeNotChainable($version) {
439 $this->_apiversion
= $version;
440 $this->hookClass
->setHook('civicrm_aclWhereClause', [
442 'aclWhereOnlySecond',
444 $this->callAPISuccess('contact', 'get', [
447 $this->callAPIFailure('contact', 'get', [
448 'check_permissions' => 1,
449 'api.pledge.get' => 1,
452 'Error in call to Pledge_get : API permission check failed for Pledge/get call; insufficient permission: require access CiviCRM and access CiviPledge'
456 public function setupCoreACL() {
457 $this->createLoggedInUser();
458 $this->_permissionedDisabledGroup
= $this->groupCreate([
459 'title' => 'pick-me-disabled',
461 'name' => 'pick-me-disabled',
463 $this->_permissionedGroup
= $this->groupCreate([
464 'title' => 'pick-me-active',
466 'name' => 'pick-me-active',
472 * @dataProvider entities
473 * confirm that without check permissions we still get 2 contacts returned
476 public function testEntitiesGetHookLimitingHookNoCheck($entity) {
477 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= [];
478 $this->setUpEntities($entity);
479 $this->hookClass
->setHook('civicrm_aclWhereClause', [
481 'aclWhereHookNoResults',
483 $result = $this->callAPISuccess($entity, 'get', [
484 'check_permissions' => 0,
485 'return' => 'contact_id',
487 $this->assertEquals(2, $result['count']);
491 * @dataProvider entities
492 * confirm that without check permissions we still get 2 entities returned
495 public function testEntitiesGetCoreACLLimitingHookNoCheck($entity) {
496 $this->setupCoreACL();
497 //CRM_Core_Config::singleton()->userPermissionClass->permissions = array();
498 $this->setUpEntities($entity);
499 $this->hookClass
->setHook('civicrm_aclWhereClause', [
501 'aclWhereHookNoResults',
503 $result = $this->callAPISuccess($entity, 'get', [
504 'check_permissions' => 0,
505 'return' => 'contact_id',
507 $this->assertEquals(2, $result['count']);
511 * @dataProvider entities
512 * confirm that with check permissions we don't get entities
514 * @throws \PHPUnit\Framework\IncompleteTestError
516 public function testEntitiesGetCoreACLLimitingCheck($entity) {
517 $this->setupCoreACL();
518 $this->setUpEntities($entity);
519 $result = $this->callAPISuccess($entity, 'get', [
520 'check_permissions' => 1,
521 'return' => 'contact_id',
523 $this->assertEquals(0, $result['count']);
527 * @dataProvider entities
528 * Function tests that an empty where hook returns no results
529 * @param string $entity
530 * @throws \PHPUnit\Framework\IncompleteTestError
532 public function testEntityGetNoResultsHook($entity) {
533 $this->markTestIncomplete('hook acls only work with contacts so far');
534 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= [];
535 $this->setUpEntities($entity);
536 $this->hookClass
->setHook('civicrm_aclWhereClause', [
538 'aclWhereHookNoResults',
540 $result = $this->callAPISuccess($entity, 'get', [
541 'check_permission' => 1,
543 $this->assertEquals(0, $result['count']);
549 public static function entities() {
553 // @todo array('pledge' => 'pledge')
561 public function setUpEntities($entity) {
562 $baoObj = new CRM_Core_DAO();
563 $baoObj->createTestObject(_civicrm_api3_get_BAO($entity), [], 2, 0);
564 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= [
566 'access CiviContribute',
568 'view event participants',
573 * Basic check that an unpermissioned call keeps working and permissioned call fails.
574 * @param int $version
575 * @dataProvider versionThreeAndFour
577 public function testGetActivityNoPermissions($version) {
578 $this->_apiversion
= $version;
579 $this->setPermissions([]);
580 $this->callAPISuccess('Activity', 'get', []);
581 $this->callAPIFailure('Activity', 'get', ['check_permissions' => 1]);
585 * View all activities is enough regardless of contact ACLs.
586 * @param int $version
587 * @dataProvider versionThreeAndFour
589 public function testGetActivityViewAllActivitiesDoesntCutItAnymore($version) {
590 $this->_apiversion
= $version;
591 $activity = $this->activityCreate();
592 $this->setPermissions(['view all activities', 'access CiviCRM']);
593 $this->callAPISuccessGetCount('Activity', [
594 'check_permissions' => 1,
595 'id' => $activity['id'],
600 * View all activities is required unless id is passed in.
601 * @param int $version
602 * @dataProvider versionThreeAndFour
604 public function testGetActivityViewAllContactsEnoughWithoutID($version) {
605 $this->_apiversion
= $version;
606 $this->setPermissions(['view all contacts', 'access CiviCRM']);
607 $this->callAPISuccess('Activity', 'get', ['check_permissions' => 1]);
611 * Without view all activities contact level acls are used.
612 * @param int $version
613 * @dataProvider versionThreeAndFour
615 public function testGetActivityViewAllContactsEnoughWIthID($version) {
616 $this->_apiversion
= $version;
617 $activity = $this->activityCreate();
618 $this->setPermissions(['view all contacts', 'access CiviCRM']);
619 $this->callAPISuccess('Activity', 'getsingle', [
620 'check_permissions' => 1,
621 'id' => $activity['id'],
626 * Check the error message is not a permission error.
627 * @param int $version
628 * @dataProvider versionThreeAndFour
630 public function testGetActivityAccessCiviCRMEnough($version) {
631 $this->_apiversion
= $version;
632 $activity = $this->activityCreate();
633 $this->setPermissions(['access CiviCRM']);
634 $this->callAPIFailure('Activity', 'getsingle', [
635 'check_permissions' => 1,
636 'id' => $activity['id'],
637 ], 'Expected one Activity but found 0');
638 $this->callAPISuccessGetCount('Activity', [
639 'check_permissions' => 1,
640 'id' => $activity['id'],
645 * Check that component related activity filtering.
647 * If the contact does NOT have permission to 'view all contacts' but they DO have permission
648 * to view the contact in question they will only see the activities of components they have access too.
650 * (logically the same component limit should apply when they have access to view all too but....
651 * adding test for 'how it is at the moment.)
652 * @param int $version
653 * @dataProvider versionThreeAndFour
655 public function testGetActivityCheckPermissionsByComponent($version) {
656 $this->_apiversion
= $version;
657 $activity = $this->activityCreate(['activity_type_id' => 'Contribution']);
658 $activity2 = $this->activityCreate(['activity_type_id' => 'Pledge Reminder']);
659 $this->hookClass
->setHook('civicrm_aclWhereClause', [
661 'aclWhereHookAllResults',
663 $this->setPermissions(['access CiviCRM', 'access CiviContribute']);
664 $this->callAPISuccessGetSingle('Activity', [
665 'check_permissions' => 1,
666 'id' => ['IN' => [$activity['id'], $activity2['id']]],
668 $this->callAPISuccessGetCount('Activity', [
669 'check_permissions' => 1,
670 'id' => ['IN' => [$activity['id'], $activity2['id']]],
676 * Check that component related activity filtering works for CiviCase.
677 * @param int $version
678 * @dataProvider versionThreeAndFour
680 public function testGetActivityCheckPermissionsByCaseComponent($version) {
681 $this->_apiversion
= $version;
682 CRM_Core_BAO_ConfigSetting
::enableComponent('CiviCase');
683 $activity = $this->activityCreate(['activity_type_id' => 'Open Case']);
684 $activity2 = $this->activityCreate(['activity_type_id' => 'Pledge Reminder']);
685 $this->hookClass
->setHook('civicrm_aclWhereClause', [
687 'aclWhereHookAllResults',
689 $this->setPermissions([
691 'access CiviContribute',
692 'access all cases and activities',
694 $this->callAPISuccessGetSingle('Activity', [
695 'check_permissions' => 1,
696 'id' => ['IN' => [$activity['id'], $activity2['id']]],
698 $this->callAPISuccessGetCount('Activity', [
699 'check_permissions' => 1,
700 'id' => ['IN' => [$activity['id'], $activity2['id']]],
705 * Check that activities can be retrieved by ACL.
707 * The activities api applies ACLs in a very limited circumstance, if id is passed in.
708 * Otherwise it sticks with the blunt original permissions.
709 * @param int $version
710 * @dataProvider versionThreeAndFour
712 public function testGetActivityByACL($version) {
713 $this->_apiversion
= $version;
714 $this->setPermissions(['access CiviCRM']);
715 $activity = $this->activityCreate();
717 $this->hookClass
->setHook('civicrm_aclWhereClause', [
719 'aclWhereHookAllResults',
721 $this->callAPISuccessGetSingle('Activity', [
722 'check_permissions' => 1,
723 'id' => $activity['id'],
725 $this->callAPISuccessGetCount('Activity', [
726 'check_permissions' => 1,
727 'id' => $activity['id'],
732 * To leverage ACL permission to view an activity you must be able to see any of the contacts.
735 public function testGetActivityByAclCannotViewAllContacts() {
736 $activity = $this->activityCreate(['assignee_contact_id' => $this->individualCreate()]);
737 $contacts = $this->getActivityContacts($activity);
738 $this->setPermissions(['access CiviCRM']);
740 foreach ($contacts as $role => $contact_id) {
741 $this->allowedContactId
= $contact_id;
742 $this->hookClass
->setHook('civicrm_aclWhereClause', [
746 $this->cleanupCachedPermissions();
747 $result = $this->callAPISuccessGetSingle('Activity', [
748 'check_permissions' => 1,
749 'id' => $activity['id'],
753 'assignee_contact_id',
761 $roleKey = $roleName . '_id';
762 if ($role !== $roleKey) {
763 $this->assertTrue(empty($result[$roleKey]), "Only contact in $role is permissioned to be returned, not $roleKey");
766 $this->assertEquals([$contact_id], (array) $result[$roleKey]);
767 $this->assertTrue(!empty($result[$roleName . '_name']));
774 * To leverage ACL permission to view an activity you must be able to see any of the contacts.
775 * @param int $version
776 * @dataProvider versionThreeAndFour
778 public function testGetActivityByAclCannotViewAnyContacts($version) {
779 $this->_apiversion
= $version;
780 $activity = $this->activityCreate();
781 $contacts = $this->getActivityContacts($activity);
782 $this->setPermissions(['access CiviCRM']);
784 foreach ($contacts as $contact_id) {
785 $this->callAPIFailure('Activity', 'getsingle', [
786 'check_permissions' => 1,
787 'id' => $activity['id'],
793 * Check that if the source contact is deleted but we can view the others we can see the activity.
797 * @throws \CRM_Core_Exception
798 * @param int $version
799 * @dataProvider versionThreeAndFour
801 public function testGetActivityACLSourceContactDeleted($version) {
802 $this->_apiversion
= $version;
803 $this->setPermissions(['access CiviCRM', 'delete contacts']);
804 $activity = $this->activityCreate();
805 $contacts = $this->getActivityContacts($activity);
807 $this->hookClass
->setHook('civicrm_aclWhereClause', [
809 'aclWhereHookAllResults',
811 $this->contactDelete($contacts['source_contact_id']);
812 $this->callAPISuccess('Activity', 'getsingle', [
813 'check_permissions' => 1,
814 'id' => $activity['id'],
819 * Test get activities multiple ids with check permissions
821 * @param int $version
822 * @dataProvider versionThreeAndFour
824 public function testActivitiesGetMultipleIdsCheckPermissions($version) {
825 $this->_apiversion
= $version;
826 $this->createLoggedInUser();
827 $activity = $this->activityCreate();
828 $activity2 = $this->activityCreate();
829 $this->setPermissions(['access CiviCRM']);
830 $this->hookClass
->setHook('civicrm_aclWhereClause', [
832 'aclWhereHookAllResults',
834 // Get activities associated with contact $this->_contactID.
836 'id' => ['IN' => [$activity['id'], $activity2['id']]],
837 'check_permissions' => TRUE,
839 $result = $this->callAPISuccess('activity', 'get', $params);
840 $this->assertEquals(2, $result['count']);
844 * Test get activities multiple ids with check permissions
845 * Limit access to One contact
847 * @param int $version
848 * @dataProvider versionThreeAndFour
850 public function testActivitiesGetMultipleIdsCheckPermissionsLimitedACL($version) {
851 $this->_apiversion
= $version;
852 $this->createLoggedInUser();
853 $activity = $this->activityCreate();
854 $contacts = $this->getActivityContacts($activity);
855 $this->setPermissions(['access CiviCRM']);
856 foreach ($contacts as $contact_id) {
857 $this->allowedContacts
[] = $contact_id;
859 $this->hookClass
->setHook('civicrm_aclWhereClause', [
861 'aclWhereMultipleContacts',
863 $contact2 = $this->individualCreate();
864 $activity2 = $this->activityCreate(['source_contact_id' => $contact2]);
865 // Get activities associated with contact $this->_contactID.
867 'id' => ['IN' => [$activity['id']]],
868 'check_permissions' => TRUE,
870 $result = $this->callAPISuccess('activity', 'get', $params);
871 $this->assertEquals(1, $result['count']);
872 $this->callAPIFailure('activity', 'getsingle', array_merge($params, [
881 * Test get activities multiple ids with check permissions
883 * @param int $version
884 * @dataProvider versionThreeAndFour
886 public function testActivitiesGetMultipleIdsCheckPermissionsNotIN($version) {
887 $this->_apiversion
= $version;
888 $this->createLoggedInUser();
889 $activity = $this->activityCreate();
890 $activity2 = $this->activityCreate();
891 $this->setPermissions(['access CiviCRM']);
892 $this->hookClass
->setHook('civicrm_aclWhereClause', [
894 'aclWhereHookAllResults',
896 // Get activities associated with contact $this->_contactID.
898 'id' => ['NOT IN' => [$activity['id'], $activity2['id']]],
899 'check_permissions' => TRUE,
901 $result = $this->callAPISuccess('activity', 'get', $params);
902 $this->assertEquals(0, $result['count']);
906 * Get the contacts for the activity.
911 * @throws \CRM_Core_Exception
913 protected function getActivityContacts($activity) {
916 $activityContacts = $this->callAPISuccess('ActivityContact', 'get', [
917 'activity_id' => $activity['id'],
920 $activityRecordTypes = $this->callAPISuccess('ActivityContact', 'getoptions', ['field' => 'record_type_id']);
921 foreach ($activityContacts['values'] as $activityContact) {
922 $type = $activityRecordTypes['values'][$activityContact['record_type_id']];
924 case 'Activity Source':
925 $contacts['source_contact_id'] = $activityContact['contact_id'];
928 case 'Activity Targets':
929 $contacts['target_contact_id'] = $activityContact['contact_id'];
932 case 'Activity Assignees':
933 $contacts['assignee_contact_id'] = $activityContact['contact_id'];
942 * Test that the 'everyone' group can be given access to a contact.
945 public function testGetACLEveryonePermittedEntity() {
946 $this->setupScenarioCoreACLEveryonePermittedToGroup();
947 $this->callAPISuccessGetCount('Contact', [
948 'id' => $this->scenarioIDs
['Contact']['permitted_contact'],
949 'check_permissions' => 1,
952 $this->callAPISuccessGetCount('Contact', [
953 'id' => $this->scenarioIDs
['Contact']['non_permitted_contact'],
954 'check_permissions' => 1,
957 // Also check that we can access ACLs through a path that uses the acl_contact_cache table.
958 // historically this has caused errors due to the key_constraint on that table.
959 // This is a bit of an artificial check as we have to amp up permissions to access this api.
960 // However, the lower level function is more directly accessed through the Contribution & Event & Profile
961 $dupes = $this->callAPISuccess('Contact', 'duplicatecheck', [
963 'first_name' => 'Anthony',
964 'last_name' => 'Anderson',
965 'contact_type' => 'Individual',
966 'email' => 'anthony_anderson@civicrm.org',
968 'check_permissions' => 0,
970 $this->assertEquals(2, $dupes['count']);
971 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= ['access CiviCRM'];
973 $dupes = $this->callAPISuccess('Contact', 'duplicatecheck', [
975 'first_name' => 'Anthony',
976 'last_name' => 'Anderson',
977 'contact_type' => 'Individual',
978 'email' => 'anthony_anderson@civicrm.org',
980 'check_permissions' => 1,
982 $this->assertEquals(1, $dupes['count']);