3 +--------------------------------------------------------------------+
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2019 |
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 protected $_apiversion = 3;
40 public $DBResetRequired = FALSE;
43 public function setUp() {
45 $baoObj = new CRM_Core_DAO();
46 $baoObj->createTestObject('CRM_Pledge_BAO_Pledge', [], 1, 0);
47 $baoObj->createTestObject('CRM_Core_BAO_Phone', [], 1, 0);
48 $this->prepareForACLs();
53 * @see CiviUnitTestCase::tearDown()
55 public function tearDown() {
56 $this->cleanUpAfterACLs();
59 'civicrm_group_contact',
63 'civicrm_acl_entity_role',
64 'civicrm_acl_contact_cache',
65 'civicrm_contribution',
66 'civicrm_participant',
69 'civicrm_activity_contact',
74 $this->quickCleanup($tablesToTruncate);
78 * Function tests that an empty where hook returns no results.
80 public function testContactGetNoResultsHook() {
81 $this->hookClass
->setHook('civicrm_aclWhereClause', [
83 'aclWhereHookNoResults',
85 $result = $this->callAPISuccess('contact', 'get', [
86 'check_permissions' => 1,
87 'return' => 'display_name',
89 $this->assertEquals(0, $result['count']);
93 * Function tests that an empty where hook returns exactly 1 result with "view my contact".
95 * CRM-16512 caused contacts with Edit my contact to be able to view all records.
97 public function testContactGetOneResultHookWithViewMyContact() {
98 $this->createLoggedInUser();
99 $this->hookClass
->setHook('civicrm_aclWhereClause', [
101 'aclWhereHookNoResults',
103 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= [
107 $result = $this->callAPISuccess('contact', 'get', [
108 'check_permissions' => 1,
109 'return' => 'display_name',
111 $this->assertEquals(1, $result['count']);
115 * Function tests that a user with "edit my contact" can edit themselves.
117 public function testContactEditHookWithEditMyContact() {
118 $cid = $this->createLoggedInUser();
119 $this->hookClass
->setHook('civicrm_aclWhereClause', [
121 'aclWhereHookNoResults',
123 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= [
127 $this->callAPISuccess('contact', 'create', [
128 'check_permissions' => 1,
134 * Ensure contact permissions do not block contact-less location entities.
136 public function testAddressWithoutContactIDAccess() {
137 $ownID = $this->createLoggedInUser();
138 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= [
142 $this->callAPISuccess('Address', 'create', [
143 'city' => 'Mouseville',
144 'location_type_id' => 'Main',
145 'api.LocBlock.create' => 1,
146 'contact_id' => $ownID,
148 $this->callAPISuccessGetSingle('Address', [
149 'city' => 'Mouseville',
150 'check_permissions' => 1,
152 CRM_Core_DAO
::executeQuery('UPDATE civicrm_address SET contact_id = NULL WHERE contact_id = %1', [
158 $this->callAPISuccessGetSingle('Address', [
159 'city' => 'Mouseville',
160 'check_permissions' => 1,
165 * Ensure contact permissions extend to related entities like email
167 public function testRelatedEntityPermissions() {
168 $this->createLoggedInUser();
169 $disallowedContact = $this->individualCreate([], 0);
170 $this->allowedContactId
= $this->individualCreate([], 1);
171 $this->hookClass
->setHook('civicrm_aclWhereClause', [
175 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= ['access CiviCRM'];
177 'Email' => ['email' => 'null@nothing', 'location_type_id' => 1],
178 'Phone' => ['phone' => '123456', 'location_type_id' => 1],
179 'IM' => ['name' => 'hello', 'location_type_id' => 1],
180 'Website' => ['url' => 'http://test'],
182 'street_address' => '123 Sesame St.',
183 'location_type_id' => 1,
186 foreach ($testEntities as $entity => $params) {
188 'contact_id' => $disallowedContact,
189 'check_permissions' => 1,
191 // We should be prevented from getting or creating entities for a contact we don't have permission for
192 $this->callAPIFailure($entity, 'create', $params);
193 $this->callAPISuccess($entity, 'create', ['check_permissions' => 0] +
$params);
194 $results = $this->callAPISuccess($entity, 'get', [
195 'contact_id' => $disallowedContact,
196 'check_permissions' => 1,
198 $this->assertEquals(0, $results['count']);
200 // We should be allowed to create and get for contacts we do have permission on
201 $params['contact_id'] = $this->allowedContactId
;
202 $this->callAPISuccess($entity, 'create', $params);
203 $results = $this->callAPISuccess($entity, 'get', [
204 'contact_id' => $this->allowedContactId
,
205 'check_permissions' => 1,
207 $this->assertGreaterThan(0, $results['count']);
209 $newTag = civicrm_api3('Tag', 'create', [
213 'Note' => ['note' => 'abc'],
214 'EntityTag' => ['tag_id' => $newTag['id']],
216 foreach ($relatedEntities as $entity => $params) {
218 'entity_id' => $disallowedContact,
219 'entity_table' => 'civicrm_contact',
220 'check_permissions' => 1,
222 // We should be prevented from getting or creating entities for a contact we don't have permission for
223 $this->callAPIFailure($entity, 'create', $params);
224 $this->callAPISuccess($entity, 'create', ['check_permissions' => 0] +
$params);
225 $results = $this->callAPISuccess($entity, 'get', [
226 'entity_id' => $disallowedContact,
227 'entity_table' => 'civicrm_contact',
228 'check_permissions' => 1,
230 $this->assertEquals(0, $results['count']);
232 // We should be allowed to create and get for entities we do have permission on
233 $params['entity_id'] = $this->allowedContactId
;
234 $this->callAPISuccess($entity, 'create', $params);
235 $results = $this->callAPISuccess($entity, 'get', [
236 'entity_id' => $this->allowedContactId
,
237 'entity_table' => 'civicrm_contact',
238 'check_permissions' => 1,
240 $this->assertGreaterThan(0, $results['count']);
245 * Function tests all results are returned.
247 public function testContactGetAllResultsHook() {
248 $this->hookClass
->setHook('civicrm_aclWhereClause', [
250 'aclWhereHookAllResults',
252 $result = $this->callAPISuccess('contact', 'get', [
253 'check_permissions' => 1,
254 'return' => 'display_name',
257 $this->assertEquals(2, $result['count']);
261 * Function tests that deleted contacts are not returned.
263 public function testContactGetPermissionHookNoDeleted() {
264 $this->callAPISuccess('contact', 'create', ['id' => 2, 'is_deleted' => 1]);
265 $this->hookClass
->setHook('civicrm_aclWhereClause', [
267 'aclWhereHookAllResults',
269 $result = $this->callAPISuccess('contact', 'get', [
270 'check_permissions' => 1,
271 'return' => 'display_name',
273 $this->assertEquals(1, $result['count']);
277 * Test permissions limited by hook.
279 public function testContactGetHookLimitingHook() {
280 $this->hookClass
->setHook('civicrm_aclWhereClause', [
282 'aclWhereOnlySecond',
285 $result = $this->callAPISuccess('contact', 'get', [
286 'check_permissions' => 1,
287 'return' => 'display_name',
289 $this->assertEquals(1, $result['count']);
293 * Confirm that without check permissions we still get 2 contacts returned.
295 public function testContactGetHookLimitingHookDontCheck() {
296 $result = $this->callAPISuccess('contact', 'get', [
297 'check_permissions' => 0,
298 'return' => 'display_name',
300 $this->assertEquals(2, $result['count']);
304 * Check that id works as a filter.
306 public function testContactGetIDFilter() {
307 $this->hookClass
->setHook('civicrm_aclWhereClause', [
309 'aclWhereHookAllResults',
311 $result = $this->callAPISuccess('contact', 'get', [
314 'check_permissions' => 1,
317 $this->assertEquals(1, $result['count']);
318 $this->assertEquals(2, $result['id']);
322 * Check that address IS returned.
324 public function testContactGetAddressReturned() {
325 $this->hookClass
->setHook('civicrm_aclWhereClause', [
327 'aclWhereOnlySecond',
329 $fullresult = $this->callAPISuccess('contact', 'get', [
332 //return doesn't work for all keys - can't fix that here so let's skip ...
333 //prefix & suffix are inconsistent due to CRM-7929
334 // unsure about others but return doesn't work on them
335 $elementsReturnDoesntSupport = [
346 $expectedReturnElements = array_diff(array_keys($fullresult['values'][0]), $elementsReturnDoesntSupport);
347 $result = $this->callAPISuccess('contact', 'get', [
348 'check_permissions' => 1,
349 'return' => $expectedReturnElements,
352 $this->assertEquals(1, $result['count']);
353 foreach ($expectedReturnElements as $element) {
354 $this->assertArrayHasKey($element, $result['values'][0]);
359 * Check that pledge IS not returned.
361 public function testContactGetPledgeIDNotReturned() {
362 $this->hookClass
->setHook('civicrm_aclWhereClause', [
364 'aclWhereHookAllResults',
366 $this->callAPISuccess('contact', 'get', [
369 $result = $this->callAPISuccess('contact', 'get', [
370 'check_permissions' => 1,
371 'return' => 'pledge_id',
374 $this->assertArrayNotHasKey('pledge_id', $result['values'][0]);
378 * Check that pledge IS not an allowable filter.
380 public function testContactGetPledgeIDNotFiltered() {
381 $this->hookClass
->setHook('civicrm_aclWhereClause', [
383 'aclWhereHookAllResults',
385 $this->callAPISuccess('contact', 'get', [
388 $result = $this->callAPISuccess('contact', 'get', [
389 'check_permissions' => 1,
393 $this->assertEquals(2, $result['count']);
397 * Check that chaining doesn't bypass permissions
399 public function testContactGetPledgeNotChainable() {
400 $this->hookClass
->setHook('civicrm_aclWhereClause', [
402 'aclWhereOnlySecond',
404 $this->callAPISuccess('contact', 'get', [
407 $this->callAPIFailure('contact', 'get', [
408 'check_permissions' => 1,
409 'api.pledge.get' => 1,
412 'Error in call to Pledge_get : API permission check failed for Pledge/get call; insufficient permission: require access CiviCRM and access CiviPledge'
416 public function setupCoreACL() {
417 $this->createLoggedInUser();
418 $this->_permissionedDisabledGroup
= $this->groupCreate([
419 'title' => 'pick-me-disabled',
421 'name' => 'pick-me-disabled',
423 $this->_permissionedGroup
= $this->groupCreate([
424 'title' => 'pick-me-active',
426 'name' => 'pick-me-active',
432 * @dataProvider entities
433 * confirm that without check permissions we still get 2 contacts returned
436 public function testEntitiesGetHookLimitingHookNoCheck($entity) {
437 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= [];
438 $this->setUpEntities($entity);
439 $this->hookClass
->setHook('civicrm_aclWhereClause', [
441 'aclWhereHookNoResults',
443 $result = $this->callAPISuccess($entity, 'get', [
444 'check_permissions' => 0,
445 'return' => 'contact_id',
447 $this->assertEquals(2, $result['count']);
451 * @dataProvider entities
452 * confirm that without check permissions we still get 2 entities returned
455 public function testEntitiesGetCoreACLLimitingHookNoCheck($entity) {
456 $this->setupCoreACL();
457 //CRM_Core_Config::singleton()->userPermissionClass->permissions = array();
458 $this->setUpEntities($entity);
459 $this->hookClass
->setHook('civicrm_aclWhereClause', [
461 'aclWhereHookNoResults',
463 $result = $this->callAPISuccess($entity, 'get', [
464 'check_permissions' => 0,
465 'return' => 'contact_id',
467 $this->assertEquals(2, $result['count']);
471 * @dataProvider entities
472 * confirm that with check permissions we don't get entities
474 * @throws \PHPUnit_Framework_IncompleteTestError
476 public function testEntitiesGetCoreACLLimitingCheck($entity) {
477 $this->setupCoreACL();
478 $this->setUpEntities($entity);
479 $result = $this->callAPISuccess($entity, 'get', [
480 'check_permissions' => 1,
481 'return' => 'contact_id',
483 $this->assertEquals(0, $result['count']);
487 * @dataProvider entities
488 * Function tests that an empty where hook returns no results
489 * @param string $entity
490 * @throws \PHPUnit_Framework_IncompleteTestError
492 public function testEntityGetNoResultsHook($entity) {
493 $this->markTestIncomplete('hook acls only work with contacts so far');
494 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= [];
495 $this->setUpEntities($entity);
496 $this->hookClass
->setHook('civicrm_aclWhereClause', [
498 'aclWhereHookNoResults',
500 $result = $this->callAPISuccess($entity, 'get', [
501 'check_permission' => 1,
503 $this->assertEquals(0, $result['count']);
509 public static function entities() {
513 ];// @todo array('pledge' => 'pledge')
520 public function setUpEntities($entity) {
521 $baoObj = new CRM_Core_DAO();
522 $baoObj->createTestObject(_civicrm_api3_get_BAO($entity), [], 2, 0);
523 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= [
525 'access CiviContribute',
527 'view event participants',
532 * Basic check that an unpermissioned call keeps working and permissioned call fails.
534 public function testGetActivityNoPermissions() {
535 $this->setPermissions([]);
536 $this->callAPISuccess('Activity', 'get', []);
537 $this->callAPIFailure('Activity', 'get', ['check_permissions' => 1]);
541 * View all activities is enough regardless of contact ACLs.
543 public function testGetActivityViewAllActivitiesDoesntCutItAnymore() {
544 $activity = $this->activityCreate();
545 $this->setPermissions(['view all activities', 'access CiviCRM']);
546 $this->callAPISuccessGetCount('Activity', [
547 'check_permissions' => 1,
548 'id' => $activity['id'],
553 * View all activities is required unless id is passed in.
555 public function testGetActivityViewAllContactsEnoughWithoutID() {
556 $this->setPermissions(['view all contacts', 'access CiviCRM']);
557 $this->callAPISuccess('Activity', 'get', ['check_permissions' => 1]);
561 * Without view all activities contact level acls are used.
563 public function testGetActivityViewAllContactsEnoughWIthID() {
564 $activity = $this->activityCreate();
565 $this->setPermissions(['view all contacts', 'access CiviCRM']);
566 $this->callAPISuccess('Activity', 'getsingle', [
567 'check_permissions' => 1,
568 'id' => $activity['id'],
573 * View all activities is required unless id is passed in, in which case ACLs are used.
575 public function testGetActivityAccessCiviCRMNotEnough() {
576 $activity = $this->activityCreate();
577 $this->setPermissions(['access CiviCRM']);
578 $this->callAPIFailure('Activity', 'getsingle', [
579 'check_permissions' => 1,
580 'id' => $activity['id'],
585 * Check that component related activity filtering.
587 * If the contact does NOT have permission to 'view all contacts' but they DO have permission
588 * to view the contact in question they will only see the activities of components they have access too.
590 * (logically the same component limit should apply when they have access to view all too but....
591 * adding test for 'how it is at the moment.)
593 public function testGetActivityCheckPermissionsByComponent() {
594 $activity = $this->activityCreate(['activity_type_id' => 'Contribution']);
595 $activity2 = $this->activityCreate(['activity_type_id' => 'Pledge Reminder']);
596 $this->hookClass
->setHook('civicrm_aclWhereClause', [
598 'aclWhereHookAllResults',
600 $this->setPermissions(['access CiviCRM', 'access CiviContribute']);
601 $this->callAPISuccessGetSingle('Activity', [
602 'check_permissions' => 1,
603 'id' => ['IN' => [$activity['id'], $activity2['id']]],
605 $this->callAPISuccessGetCount('Activity', [
606 'check_permissions' => 1,
607 'id' => ['IN' => [$activity['id'], $activity2['id']]],
613 * Check that component related activity filtering works for CiviCase.
615 public function testGetActivityCheckPermissionsByCaseComponent() {
616 CRM_Core_BAO_ConfigSetting
::enableComponent('CiviCase');
617 $activity = $this->activityCreate(['activity_type_id' => 'Open Case']);
618 $activity2 = $this->activityCreate(['activity_type_id' => 'Pledge Reminder']);
619 $this->hookClass
->setHook('civicrm_aclWhereClause', [
621 'aclWhereHookAllResults',
623 $this->setPermissions([
625 'access CiviContribute',
626 'access all cases and activities',
628 $this->callAPISuccessGetSingle('Activity', [
629 'check_permissions' => 1,
630 'id' => ['IN' => [$activity['id'], $activity2['id']]],
632 $this->callAPISuccessGetCount('Activity', [
633 'check_permissions' => 1,
634 'id' => ['IN' => [$activity['id'], $activity2['id']]],
639 * Check that activities can be retrieved by ACL.
641 * The activities api applies ACLs in a very limited circumstance, if id is passed in.
642 * Otherwise it sticks with the blunt original permissions.
644 public function testGetActivityByACL() {
645 $this->setPermissions(['access CiviCRM']);
646 $activity = $this->activityCreate();
648 $this->hookClass
->setHook('civicrm_aclWhereClause', [
650 'aclWhereHookAllResults',
652 $this->callAPISuccessGetSingle('Activity', [
653 'check_permissions' => 1,
654 'id' => $activity['id'],
656 $this->callAPISuccessGetCount('Activity', [
657 'check_permissions' => 1,
658 'id' => $activity['id'],
663 * To leverage ACL permission to view an activity you must be able to see any of the contacts.
665 public function testGetActivityByAclCannotViewAllContacts() {
666 $activity = $this->activityCreate(['assignee_contact_id' => $this->individualCreate()]);
667 $contacts = $this->getActivityContacts($activity);
668 $this->setPermissions(['access CiviCRM']);
670 foreach ($contacts as $role => $contact_id) {
671 $this->allowedContactId
= $contact_id;
672 $this->hookClass
->setHook('civicrm_aclWhereClause', [
676 $this->cleanupCachedPermissions();
677 $result = $this->callAPISuccessGetSingle('Activity', [
678 'check_permissions' => 1,
679 'id' => $activity['id'],
683 'assignee_contact_id',
691 $roleKey = $roleName . '_id';
692 if ($role !== $roleKey) {
693 $this->assertTrue(empty($result[$roleKey]), "Only contact in $role is permissioned to be returned, not $roleKey");
696 $this->assertEquals([$contact_id], (array) $result[$roleKey]);
697 $this->assertTrue(!empty($result[$roleName . '_name']));
704 * To leverage ACL permission to view an activity you must be able to see any of the contacts.
706 public function testGetActivityByAclCannotViewAnyContacts() {
707 $activity = $this->activityCreate();
708 $contacts = $this->getActivityContacts($activity);
709 $this->setPermissions(['access CiviCRM']);
711 foreach ($contacts as $contact_id) {
712 $this->callAPIFailure('Activity', 'getsingle', [
713 'check_permissions' => 1,
714 'id' => $activity['id'],
720 * Check that if the source contact is deleted but we can view the others we can see the activity.
724 * @throws \CRM_Core_Exception
726 public function testGetActivityACLSourceContactDeleted() {
727 $this->setPermissions(['access CiviCRM', 'delete contacts']);
728 $activity = $this->activityCreate();
729 $contacts = $this->getActivityContacts($activity);
731 $this->hookClass
->setHook('civicrm_aclWhereClause', [
733 'aclWhereHookAllResults',
735 $this->contactDelete($contacts['source_contact_id']);
736 $this->callAPISuccess('Activity', 'getsingle', [
737 'check_permissions' => 1,
738 'id' => $activity['id'],
743 * Test get activities multiple ids with check permissions
746 public function testActivitiesGetMultipleIdsCheckPermissions() {
747 $this->createLoggedInUser();
748 $activity = $this->activityCreate();
749 $activity2 = $this->activityCreate();
750 $this->setPermissions(['access CiviCRM']);
751 $this->hookClass
->setHook('civicrm_aclWhereClause', [
753 'aclWhereHookAllResults',
755 // Get activities associated with contact $this->_contactID.
757 'id' => ['IN' => [$activity['id'], $activity2['id']]],
758 'check_permissions' => TRUE,
760 $result = $this->callAPISuccess('activity', 'get', $params);
761 $this->assertEquals(2, $result['count']);
765 * Test get activities multiple ids with check permissions
766 * Limit access to One contact
769 public function testActivitiesGetMultipleIdsCheckPermissionsLimitedACL() {
770 $this->createLoggedInUser();
771 $activity = $this->activityCreate();
772 $contacts = $this->getActivityContacts($activity);
773 $this->setPermissions(['access CiviCRM']);
774 foreach ($contacts as $contact_id) {
775 $this->allowedContacts
[] = $contact_id;
777 $this->hookClass
->setHook('civicrm_aclWhereClause', [
779 'aclWhereMultipleContacts',
781 $contact2 = $this->individualCreate();
782 $activity2 = $this->activityCreate(['source_contact_id' => $contact2]);
783 // Get activities associated with contact $this->_contactID.
785 'id' => ['IN' => [$activity['id']]],
786 'check_permissions' => TRUE,
788 $result = $this->callAPISuccess('activity', 'get', $params);
789 $this->assertEquals(1, $result['count']);
790 $this->callAPIFailure('activity', 'get', array_merge($params, [
799 * Test get activities multiple ids with check permissions
802 public function testActivitiesGetMultipleIdsCheckPermissionsNotIN() {
803 $this->createLoggedInUser();
804 $activity = $this->activityCreate();
805 $activity2 = $this->activityCreate();
806 $this->setPermissions(['access CiviCRM']);
807 $this->hookClass
->setHook('civicrm_aclWhereClause', [
809 'aclWhereHookAllResults',
811 // Get activities associated with contact $this->_contactID.
813 'id' => ['NOT IN' => [$activity['id'], $activity2['id']]],
814 'check_permissions' => TRUE,
816 $result = $this->callAPISuccess('activity', 'get', $params);
817 $this->assertEquals(0, $result['count']);
821 * Get the contacts for the activity.
826 * @throws \CRM_Core_Exception
828 protected function getActivityContacts($activity) {
831 $activityContacts = $this->callAPISuccess('ActivityContact', 'get', [
832 'activity_id' => $activity['id'],
836 $activityRecordTypes = $this->callAPISuccess('ActivityContact', 'getoptions', ['field' => 'record_type_id']);
837 foreach ($activityContacts['values'] as $activityContact) {
838 $type = $activityRecordTypes['values'][$activityContact['record_type_id']];
840 case 'Activity Source':
841 $contacts['source_contact_id'] = $activityContact['contact_id'];
844 case 'Activity Targets':
845 $contacts['target_contact_id'] = $activityContact['contact_id'];
848 case 'Activity Assignees':
849 $contacts['assignee_contact_id'] = $activityContact['contact_id'];
858 * Test that the 'everyone' group can be given access to a contact.
860 public function testGetACLEveryonePermittedEntity() {
861 $this->setupScenarioCoreACLEveryonePermittedToGroup();
862 $this->callAPISuccessGetCount('Contact', [
863 'id' => $this->scenarioIDs
['Contact']['permitted_contact'],
864 'check_permissions' => 1,
867 $this->callAPISuccessGetCount('Contact', [
868 'id' => $this->scenarioIDs
['Contact']['non_permitted_contact'],
869 'check_permissions' => 1,
872 // Also check that we can access ACLs through a path that uses the acl_contact_cache table.
873 // historically this has caused errors due to the key_constraint on that table.
874 // This is a bit of an artificial check as we have to amp up permissions to access this api.
875 // However, the lower level function is more directly accessed through the Contribution & Event & Profile
876 $dupes = $this->callAPISuccess('Contact', 'duplicatecheck', [
878 'first_name' => 'Anthony',
879 'last_name' => 'Anderson',
880 'contact_type' => 'Individual',
881 'email' => 'anthony_anderson@civicrm.org',
883 'check_permissions' => 0,
885 $this->assertEquals(2, $dupes['count']);
886 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= ['access CiviCRM'];
888 $dupes = $this->callAPISuccess('Contact', 'duplicatecheck', [
890 'first_name' => 'Anthony',
891 'last_name' => 'Anderson',
892 'contact_type' => 'Individual',
893 'email' => 'anthony_anderson@civicrm.org',
895 'check_permissions' => 1,
897 $this->assertEquals(1, $dupes['count']);