Merge pull request #13445 from seamuslee001/dev-656
[civicrm-core.git] / tests / phpunit / api / v3 / ACLPermissionTest.php
CommitLineData
6a488035 1<?php
6a488035
TO
2/*
3 +--------------------------------------------------------------------+
2fe49090 4 | CiviCRM version 5 |
6a488035 5 +--------------------------------------------------------------------+
6b83d5bd 6 | Copyright CiviCRM LLC (c) 2004-2019 |
6a488035
TO
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
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. |
13 | |
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. |
18 | |
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 +--------------------------------------------------------------------+
26 */
27
6a488035
TO
28/**
29 * This class is intended to test ACL permission using the multisite module
30 *
7884d958 31 * @package CiviCRM_APIv3
32 * @subpackage API_Contact
acb109b7 33 * @group headless
6a488035 34 */
6a488035 35class api_v3_ACLPermissionTest extends CiviUnitTestCase {
2af6f0c0 36
37 use CRMTraits_ACL_PermissionTrait;
38
4e420887 39 protected $_apiversion = 3;
4e420887 40 public $DBResetRequired = FALSE;
430ae6dd
TO
41 protected $_entity;
42
00be9182 43 public function setUp() {
6a488035
TO
44 parent::setUp();
45 $baoObj = new CRM_Core_DAO();
46 $baoObj->createTestObject('CRM_Pledge_BAO_Pledge', array(), 1, 0);
47 $baoObj->createTestObject('CRM_Core_BAO_Phone', array(), 1, 0);
5e8daa54 48 $this->prepareForACLs();
6a488035 49 }
7884d958 50
51 /**
52 * (non-PHPdoc)
53 * @see CiviUnitTestCase::tearDown()
54 */
00be9182 55 public function tearDown() {
5e8daa54 56 $this->cleanUpAfterACLs();
6a488035 57 $tablesToTruncate = array(
7884d958 58 'civicrm_contact',
ae4bb4c9
EM
59 'civicrm_group_contact',
60 'civicrm_group',
61 'civicrm_acl',
62 'civicrm_acl_cache',
63 'civicrm_acl_entity_role',
64 'civicrm_acl_contact_cache',
65 'civicrm_contribution',
66 'civicrm_participant',
225d474b 67 'civicrm_uf_match',
bbd2743b 68 'civicrm_activity',
69 'civicrm_activity_contact',
c6835264
CW
70 'civicrm_note',
71 'civicrm_entity_tag',
72 'civicrm_tag',
6a488035
TO
73 );
74 $this->quickCleanup($tablesToTruncate);
6a488035 75 }
7884d958 76
77 /**
eceb18cc 78 * Function tests that an empty where hook returns no results.
7884d958 79 */
00be9182 80 public function testContactGetNoResultsHook() {
6a488035 81 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookNoResults'));
4e420887 82 $result = $this->callAPISuccess('contact', 'get', array(
6a488035
TO
83 'check_permissions' => 1,
84 'return' => 'display_name',
85 ));
6a488035
TO
86 $this->assertEquals(0, $result['count']);
87 }
88
1028f75e 89 /**
1a4651ba 90 * Function tests that an empty where hook returns exactly 1 result with "view my contact".
1028f75e 91 *
92 * CRM-16512 caused contacts with Edit my contact to be able to view all records.
93 */
1a4651ba 94 public function testContactGetOneResultHookWithViewMyContact() {
1028f75e 95 $this->createLoggedInUser();
96 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookNoResults'));
97 CRM_Core_Config::singleton()->userPermissionClass->permissions = array('access CiviCRM', 'view my contact');
98 $result = $this->callAPISuccess('contact', 'get', array(
99 'check_permissions' => 1,
100 'return' => 'display_name',
101 ));
1a4651ba
CW
102 $this->assertEquals(1, $result['count']);
103 }
104
105 /**
106 * Function tests that a user with "edit my contact" can edit themselves.
107 */
108 public function testContactEditHookWithEditMyContact() {
1a4651ba
CW
109 $cid = $this->createLoggedInUser();
110 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookNoResults'));
111 CRM_Core_Config::singleton()->userPermissionClass->permissions = array('access CiviCRM', 'edit my contact');
112 $this->callAPISuccess('contact', 'create', array(
113 'check_permissions' => 1,
114 'id' => $cid,
115 ));
1028f75e 116 }
117
52ed95a8 118 /**
119 * Ensure contact permissions do not block contact-less location entities.
120 */
121 public function testAddressWithoutContactIDAccess() {
122 $ownID = $this->createLoggedInUser();
123 CRM_Core_Config::singleton()->userPermissionClass->permissions = array('access CiviCRM', 'view all contacts');
124 $this->callAPISuccess('Address', 'create', array(
125 'city' => 'Mouseville',
126 'location_type_id' => 'Main',
127 'api.LocBlock.create' => 1,
128 'contact_id' => $ownID,
129 ));
130 $this->callAPISuccessGetSingle('Address', array('city' => 'Mouseville', 'check_permissions' => 1));
131 CRM_Core_DAO::executeQuery('UPDATE civicrm_address SET contact_id = NULL WHERE contact_id = %1', array(1 => array($ownID, 'Integer')));
132 $this->callAPISuccessGetSingle('Address', array('city' => 'Mouseville', 'check_permissions' => 1));
133 }
134
c16ed19b
CW
135 /**
136 * Ensure contact permissions extend to related entities like email
137 */
138 public function testRelatedEntityPermissions() {
0a61b6e2 139 $this->createLoggedInUser();
c16ed19b
CW
140 $disallowedContact = $this->individualCreate(array(), 0);
141 $this->allowedContactId = $this->individualCreate(array(), 1);
142 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereOnlyOne'));
143 CRM_Core_Config::singleton()->userPermissionClass->permissions = array('access CiviCRM');
144 $testEntities = array(
0a61b6e2
CW
145 'Email' => array('email' => 'null@nothing', 'location_type_id' => 1),
146 'Phone' => array('phone' => '123456', 'location_type_id' => 1),
147 'IM' => array('name' => 'hello', 'location_type_id' => 1),
c16ed19b 148 'Website' => array('url' => 'http://test'),
0a61b6e2 149 'Address' => array('street_address' => '123 Sesame St.', 'location_type_id' => 1),
c16ed19b
CW
150 );
151 foreach ($testEntities as $entity => $params) {
152 $params += array(
153 'contact_id' => $disallowedContact,
154 'check_permissions' => 1,
155 );
156 // We should be prevented from getting or creating entities for a contact we don't have permission for
157 $this->callAPIFailure($entity, 'create', $params);
c6835264 158 $this->callAPISuccess($entity, 'create', array('check_permissions' => 0) + $params);
c16ed19b
CW
159 $results = $this->callAPISuccess($entity, 'get', array('contact_id' => $disallowedContact, 'check_permissions' => 1));
160 $this->assertEquals(0, $results['count']);
161
162 // We should be allowed to create and get for contacts we do have permission on
163 $params['contact_id'] = $this->allowedContactId;
164 $this->callAPISuccess($entity, 'create', $params);
165 $results = $this->callAPISuccess($entity, 'get', array('contact_id' => $this->allowedContactId, 'check_permissions' => 1));
166 $this->assertGreaterThan(0, $results['count']);
167 }
c6835264
CW
168 $newTag = civicrm_api3('Tag', 'create', array(
169 'name' => 'Foo123',
170 ));
171 $relatedEntities = array(
172 'Note' => array('note' => 'abc'),
173 'EntityTag' => array('tag_id' => $newTag['id']),
174 );
175 foreach ($relatedEntities as $entity => $params) {
176 $params += array(
177 'entity_id' => $disallowedContact,
178 'entity_table' => 'civicrm_contact',
179 'check_permissions' => 1,
180 );
181 // We should be prevented from getting or creating entities for a contact we don't have permission for
182 $this->callAPIFailure($entity, 'create', $params);
183 $this->callAPISuccess($entity, 'create', array('check_permissions' => 0) + $params);
184 $results = $this->callAPISuccess($entity, 'get', array('entity_id' => $disallowedContact, 'entity_table' => 'civicrm_contact', 'check_permissions' => 1));
185 $this->assertEquals(0, $results['count']);
186
187 // We should be allowed to create and get for entities we do have permission on
188 $params['entity_id'] = $this->allowedContactId;
189 $this->callAPISuccess($entity, 'create', $params);
190 $results = $this->callAPISuccess($entity, 'get', array('entity_id' => $this->allowedContactId, 'entity_table' => 'civicrm_contact', 'check_permissions' => 1));
191 $this->assertGreaterThan(0, $results['count']);
192 }
c16ed19b
CW
193 }
194
6a488035 195 /**
eceb18cc 196 * Function tests all results are returned.
7884d958 197 */
00be9182 198 public function testContactGetAllResultsHook() {
6a488035 199 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookAllResults'));
4e420887 200 $result = $this->callAPISuccess('contact', 'get', array(
7884d958 201 'check_permissions' => 1,
202 'return' => 'display_name',
6a488035
TO
203 ));
204
6a488035
TO
205 $this->assertEquals(2, $result['count']);
206 }
7884d958 207
6a488035 208 /**
eceb18cc 209 * Function tests that deleted contacts are not returned.
7884d958 210 */
00be9182 211 public function testContactGetPermissionHookNoDeleted() {
f5052d4d 212 $this->callAPISuccess('contact', 'create', array('id' => 2, 'is_deleted' => 1));
6a488035 213 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookAllResults'));
4e420887 214 $result = $this->callAPISuccess('contact', 'get', array(
7884d958 215 'check_permissions' => 1,
216 'return' => 'display_name',
6a488035 217 ));
6a488035
TO
218 $this->assertEquals(1, $result['count']);
219 }
220
221 /**
eceb18cc 222 * Test permissions limited by hook.
6a488035 223 */
00be9182 224 public function testContactGetHookLimitingHook() {
6a488035
TO
225 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereOnlySecond'));
226
4e420887 227 $result = $this->callAPISuccess('contact', 'get', array(
6a488035
TO
228 'check_permissions' => 1,
229 'return' => 'display_name',
7884d958 230 ));
6a488035
TO
231 $this->assertEquals(1, $result['count']);
232 }
233
7884d958 234 /**
1028f75e 235 * Confirm that without check permissions we still get 2 contacts returned.
7884d958 236 */
00be9182 237 public function testContactGetHookLimitingHookDontCheck() {
4e420887 238 $result = $this->callAPISuccess('contact', 'get', array(
239 'check_permissions' => 0,
240 'return' => 'display_name',
6a488035 241 ));
6a488035
TO
242 $this->assertEquals(2, $result['count']);
243 }
7884d958 244
6a488035 245 /**
eceb18cc 246 * Check that id works as a filter.
6a488035 247 */
00be9182 248 public function testContactGetIDFilter() {
6a488035 249 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookAllResults'));
4e420887 250 $result = $this->callAPISuccess('contact', 'get', array(
6a488035
TO
251 'sequential' => 1,
252 'id' => 2,
253 'check_permissions' => 1,
254 ));
255
6a488035
TO
256 $this->assertEquals(1, $result['count']);
257 $this->assertEquals(2, $result['id']);
258 }
259
7884d958 260 /**
eceb18cc 261 * Check that address IS returned.
7884d958 262 */
00be9182 263 public function testContactGetAddressReturned() {
7884d958 264 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereOnlySecond'));
265 $fullresult = $this->callAPISuccess('contact', 'get', array(
266 'sequential' => 1,
267 ));
268 //return doesn't work for all keys - can't fix that here so let's skip ...
269 //prefix & suffix are inconsistent due to CRM-7929
270 // unsure about others but return doesn't work on them
271 $elementsReturnDoesntSupport = array(
7884d958 272 'prefix',
7884d958 273 'suffix',
7884d958 274 'gender',
275 'current_employer',
276 'phone_id',
277 'phone_type_id',
278 'phone',
279 'worldregion_id',
21dfd5f5 280 'world_region',
7884d958 281 );
282 $expectedReturnElements = array_diff(array_keys($fullresult['values'][0]), $elementsReturnDoesntSupport);
283 $result = $this->callAPISuccess('contact', 'get', array(
284 'check_permissions' => 1,
285 'return' => $expectedReturnElements,
286 'sequential' => 1,
287 ));
288 $this->assertEquals(1, $result['count']);
289 foreach ($expectedReturnElements as $element) {
290 $this->assertArrayHasKey($element, $result['values'][0]);
6a488035 291 }
7884d958 292 }
293
294 /**
eceb18cc 295 * Check that pledge IS not returned.
7884d958 296 */
00be9182 297 public function testContactGetPledgeIDNotReturned() {
7884d958 298 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookAllResults'));
f5052d4d 299 $this->callAPISuccess('contact', 'get', array(
7884d958 300 'sequential' => 1,
301 ));
302 $result = $this->callAPISuccess('contact', 'get', array(
303 'check_permissions' => 1,
304 'return' => 'pledge_id',
305 'sequential' => 1,
306 ));
307 $this->assertArrayNotHasKey('pledge_id', $result['values'][0]);
308 }
6a488035 309
7884d958 310 /**
eceb18cc 311 * Check that pledge IS not an allowable filter.
7884d958 312 */
00be9182 313 public function testContactGetPledgeIDNotFiltered() {
7884d958 314 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookAllResults'));
f5052d4d 315 $this->callAPISuccess('contact', 'get', array(
7884d958 316 'sequential' => 1,
317 ));
318 $result = $this->callAPISuccess('contact', 'get', array(
319 'check_permissions' => 1,
320 'pledge_id' => 1,
321 'sequential' => 1,
322 ));
323 $this->assertEquals(2, $result['count']);
324 }
325
326 /**
327 * Check that chaining doesn't bypass permissions
328 */
00be9182 329 public function testContactGetPledgeNotChainable() {
7884d958 330 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereOnlySecond'));
f5052d4d 331 $this->callAPISuccess('contact', 'get', array(
7884d958 332 'sequential' => 1,
333 ));
f5052d4d 334 $this->callAPIFailure('contact', 'get', array(
6a488035 335 'check_permissions' => 1,
7884d958 336 'api.pledge.get' => 1,
6a488035 337 'sequential' => 1,
4e420887 338 ),
d235daf6 339 'Error in call to Pledge_get : API permission check failed for Pledge/get call; insufficient permission: require access CiviCRM and access CiviPledge'
7884d958 340 );
341 }
6a488035 342
00be9182 343 public function setupCoreACL() {
ae4bb4c9 344 $this->createLoggedInUser();
5896d037 345 $this->_permissionedDisabledGroup = $this->groupCreate(array(
92915c55
TO
346 'title' => 'pick-me-disabled',
347 'is_active' => 0,
348 'name' => 'pick-me-disabled',
349 ));
5896d037 350 $this->_permissionedGroup = $this->groupCreate(array(
92915c55
TO
351 'title' => 'pick-me-active',
352 'is_active' => 1,
353 'name' => 'pick-me-active',
354 ));
ae4bb4c9
EM
355 $this->setupACL();
356 }
5896d037 357
ae4bb4c9
EM
358 /**
359 * @dataProvider entities
360 * confirm that without check permissions we still get 2 contacts returned
1e1fdcf6 361 * @param $entity
ae4bb4c9 362 */
00be9182 363 public function testEntitiesGetHookLimitingHookNoCheck($entity) {
ae4bb4c9
EM
364 CRM_Core_Config::singleton()->userPermissionClass->permissions = array();
365 $this->setUpEntities($entity);
366 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookNoResults'));
367 $result = $this->callAPISuccess($entity, 'get', array(
368 'check_permissions' => 0,
369 'return' => 'contact_id',
370 ));
371 $this->assertEquals(2, $result['count']);
372 }
373
374 /**
375 * @dataProvider entities
376 * confirm that without check permissions we still get 2 entities returned
1e1fdcf6 377 * @param $entity
ae4bb4c9 378 */
00be9182 379 public function testEntitiesGetCoreACLLimitingHookNoCheck($entity) {
ae4bb4c9
EM
380 $this->setupCoreACL();
381 //CRM_Core_Config::singleton()->userPermissionClass->permissions = array();
382 $this->setUpEntities($entity);
383 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookNoResults'));
384 $result = $this->callAPISuccess($entity, 'get', array(
385 'check_permissions' => 0,
386 'return' => 'contact_id',
387 ));
388 $this->assertEquals(2, $result['count']);
389 }
5896d037 390
ae4bb4c9
EM
391 /**
392 * @dataProvider entities
393 * confirm that with check permissions we don't get entities
1e1fdcf6
EM
394 * @param $entity
395 * @throws \PHPUnit_Framework_IncompleteTestError
ae4bb4c9 396 */
00be9182 397 public function testEntitiesGetCoreACLLimitingCheck($entity) {
ae4bb4c9
EM
398 $this->setupCoreACL();
399 $this->setUpEntities($entity);
ae4bb4c9
EM
400 $result = $this->callAPISuccess($entity, 'get', array(
401 'check_permissions' => 1,
402 'return' => 'contact_id',
403 ));
404 $this->assertEquals(0, $result['count']);
405 }
406
ae4bb4c9
EM
407 /**
408 * @dataProvider entities
409 * Function tests that an empty where hook returns no results
1028f75e 410 * @param string $entity
1e1fdcf6 411 * @throws \PHPUnit_Framework_IncompleteTestError
ae4bb4c9 412 */
00be9182 413 public function testEntityGetNoResultsHook($entity) {
ae4bb4c9
EM
414 $this->markTestIncomplete('hook acls only work with contacts so far');
415 CRM_Core_Config::singleton()->userPermissionClass->permissions = array();
416 $this->setUpEntities($entity);
417 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookNoResults'));
418 $result = $this->callAPISuccess($entity, 'get', array(
419 'check_permission' => 1,
420 ));
421 $this->assertEquals(0, $result['count']);
422 }
423
424 /**
425 * @return array
426 */
427 public static function entities() {
6c6e6187 428 return array(array('contribution'), array('participant'));// @todo array('pledge' => 'pledge')
ae4bb4c9
EM
429 }
430
431 /**
432 * Create 2 entities
1e1fdcf6 433 * @param $entity
ae4bb4c9
EM
434 */
435 public function setUpEntities($entity) {
436 $baoObj = new CRM_Core_DAO();
5896d037 437 $baoObj->createTestObject(_civicrm_api3_get_BAO($entity), array(), 2, 0);
ae4bb4c9
EM
438 CRM_Core_Config::singleton()->userPermissionClass->permissions = array(
439 'access CiviCRM',
440 'access CiviContribute',
441 'access CiviEvent',
442 'view event participants',
443 );
444 }
445
bbd2743b 446 /**
447 * Basic check that an unpermissioned call keeps working and permissioned call fails.
448 */
449 public function testGetActivityNoPermissions() {
450 $this->setPermissions(array());
451 $this->callAPISuccess('Activity', 'get', array());
452 $this->callAPIFailure('Activity', 'get', array('check_permissions' => 1));
453 }
454
455 /**
456 * View all activities is enough regardless of contact ACLs.
457 */
458 public function testGetActivityViewAllActivitiesEnoughWithOrWithoutID() {
459 $activity = $this->activityCreate();
460 $this->setPermissions(array('view all activities', 'access CiviCRM'));
461 $this->callAPISuccess('Activity', 'getsingle', array('check_permissions' => 1, 'id' => $activity['id']));
462 $this->callAPISuccess('Activity', 'getsingle', array('check_permissions' => 1));
463 }
464
465 /**
466 * View all activities is required unless id is passed in.
467 */
3c9d67b0 468 public function testGetActivityViewAllContactsEnoughWIthoutID() {
bbd2743b 469 $this->setPermissions(array('view all contacts', 'access CiviCRM'));
3c9d67b0 470 $this->callAPISuccess('Activity', 'get', array('check_permissions' => 1));
bbd2743b 471 }
472
473 /**
3af8de9f 474 * Without view all activities contact level acls are used.
bbd2743b 475 */
476 public function testGetActivityViewAllContactsEnoughWIthID() {
477 $activity = $this->activityCreate();
478 $this->setPermissions(array('view all contacts', 'access CiviCRM'));
479 $this->callAPISuccess('Activity', 'getsingle', array('check_permissions' => 1, 'id' => $activity['id']));
480 }
481
482 /**
483 * View all activities is required unless id is passed in, in which case ACLs are used.
484 */
485 public function testGetActivityAccessCiviCRMNotEnough() {
486 $activity = $this->activityCreate();
487 $this->setPermissions(array('access CiviCRM'));
488 $this->callAPIFailure('Activity', 'getsingle', array('check_permissions' => 1, 'id' => $activity['id']));
489 }
490
3af8de9f 491 /**
492 * Check that component related activity filtering.
493 *
494 * If the contact does NOT have permission to 'view all contacts' but they DO have permission
495 * to view the contact in question they will only see the activities of components they have access too.
496 *
497 * (logically the same component limit should apply when they have access to view all too but....
498 * adding test for 'how it is at the moment.)
499 */
500 public function testGetActivityCheckPermissionsByComponent() {
501 $activity = $this->activityCreate(['activity_type_id' => 'Contribution']);
502 $activity2 = $this->activityCreate(['activity_type_id' => 'Pledge Reminder']);
503 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookAllResults'));
504 $this->setPermissions(['access CiviCRM', 'access CiviContribute']);
505 $this->callAPISuccessGetSingle('Activity', ['check_permissions' => 1, 'id' => ['IN' => [$activity['id'], $activity2['id']]]]);
506 }
507
c4937fe9 508 /**
509 * Check that component related activity filtering works for CiviCase.
510 */
511 public function testGetActivityCheckPermissionsByCaseComponent() {
512 CRM_Core_BAO_ConfigSetting::enableComponent('CiviCase');
513 $activity = $this->activityCreate(['activity_type_id' => 'Open Case']);
514 $activity2 = $this->activityCreate(['activity_type_id' => 'Pledge Reminder']);
515 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookAllResults'));
516 $this->setPermissions(['access CiviCRM', 'access CiviContribute', 'access all cases and activities']);
517 $this->callAPISuccessGetSingle('Activity', ['check_permissions' => 1, 'id' => ['IN' => [$activity['id'], $activity2['id']]]]);
518 }
519
bbd2743b 520 /**
521 * Check that activities can be retrieved by ACL.
522 *
523 * The activities api applies ACLs in a very limited circumstance, if id is passed in.
524 * Otherwise it sticks with the blunt original permissions.
525 */
526 public function testGetActivityByACL() {
527 $this->setPermissions(array('access CiviCRM'));
528 $activity = $this->activityCreate();
529
530 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookAllResults'));
531 $this->callAPISuccess('Activity', 'getsingle', array('check_permissions' => 1, 'id' => $activity['id']));
532 }
533
534 /**
535 * To leverage ACL permission to view an activity you must be able to see all of the contacts.
536 */
537 public function testGetActivityByAclCannotViewAllContacts() {
538 $activity = $this->activityCreate();
539 $contacts = $this->getActivityContacts($activity);
540 $this->setPermissions(array('access CiviCRM'));
541
542 foreach ($contacts as $contact_id) {
543 $this->allowedContactId = $contact_id;
544 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereOnlyOne'));
545 $this->callAPIFailure('Activity', 'getsingle', array('check_permissions' => 1, 'id' => $activity['id']));
546 }
547 }
548
549 /**
550 * Check that if the source contact is deleted but we can view the others we can see the activity.
551 *
552 * CRM-18409.
553 *
554 * @throws \CRM_Core_Exception
555 */
556 public function testGetActivityACLSourceContactDeleted() {
557 $this->setPermissions(array('access CiviCRM', 'delete contacts'));
558 $activity = $this->activityCreate();
559 $contacts = $this->getActivityContacts($activity);
560
561 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookAllResults'));
562 $this->contactDelete($contacts['source_contact_id']);
563 $this->callAPISuccess('Activity', 'getsingle', array('check_permissions' => 1, 'id' => $activity['id']));
564 }
565
f404486e
SL
566 /**
567 * Test get activities multiple ids with check permissions
568 * CRM-20441
569 */
570 public function testActivitiesGetMultipleIdsCheckPermissions() {
571 $this->createLoggedInUser();
572 $activity = $this->activityCreate();
573 $activity2 = $this->activityCreate();
574 $this->setPermissions(array('access CiviCRM'));
575 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookAllResults'));
576 // Get activities associated with contact $this->_contactID.
577 $params = array(
578 'id' => array('IN' => array($activity['id'], $activity2['id'])),
579 'check_permissions' => TRUE,
580 );
581 $result = $this->callAPISuccess('activity', 'get', $params);
582 $this->assertEquals(2, $result['count']);
583 }
584
585 /**
586 * Test get activities multiple ids with check permissions
587 * Limit access to One contact
588 * CRM-20441
589 */
590 public function testActivitiesGetMultipleIdsCheckPermissionsLimitedACL() {
591 $this->createLoggedInUser();
592 $activity = $this->activityCreate();
593 $contacts = $this->getActivityContacts($activity);
594 $this->setPermissions(array('access CiviCRM'));
595 foreach ($contacts as $contact_id) {
596 $this->allowedContacts[] = $contact_id;
597 }
598 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereMultipleContacts'));
599 $contact2 = $this->individualCreate();
600 $activity2 = $this->activityCreate(array('source_contact_id' => $contact2));
601 // Get activities associated with contact $this->_contactID.
602 $params = array(
603 'id' => array('IN' => array($activity['id'])),
604 'check_permissions' => TRUE,
605 );
606 $result = $this->callAPISuccess('activity', 'get', $params);
607 $this->assertEquals(1, $result['count']);
608 $this->callAPIFailure('activity', 'get', array_merge($params, array('id' => array('IN', array($activity2['id'])))));
609 }
610
dfe0e2e1
SL
611 /**
612 * Test get activities multiple ids with check permissions
613 * CRM-20441
614 */
615 public function testActivitiesGetMultipleIdsCheckPermissionsNotIN() {
616 $this->createLoggedInUser();
617 $activity = $this->activityCreate();
618 $activity2 = $this->activityCreate();
619 $this->setPermissions(array('access CiviCRM'));
620 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookAllResults'));
621 // Get activities associated with contact $this->_contactID.
622 $params = array(
623 'id' => array('NOT IN' => array($activity['id'], $activity2['id'])),
624 'check_permissions' => TRUE,
625 );
3c9d67b0 626 $result = $this->callAPISuccess('activity', 'get', $params);
627 $this->assertEquals(0, $result['count']);
dfe0e2e1
SL
628 }
629
bbd2743b 630 /**
631 * Get the contacts for the activity.
632 *
633 * @param $activity
634 *
635 * @return array
636 * @throws \CRM_Core_Exception
637 */
638 protected function getActivityContacts($activity) {
639 $contacts = array();
640
641 $activityContacts = $this->callAPISuccess('ActivityContact', 'get', array(
642 'activity_id' => $activity['id'],
643 )
644 );
645
646 $activityRecordTypes = $this->callAPISuccess('ActivityContact', 'getoptions', array('field' => 'record_type_id'));
647 foreach ($activityContacts['values'] as $activityContact) {
648 $type = $activityRecordTypes['values'][$activityContact['record_type_id']];
649 switch ($type) {
650 case 'Activity Source':
651 $contacts['source_contact_id'] = $activityContact['contact_id'];
652 break;
653
654 case 'Activity Targets':
655 $contacts['target_contact_id'] = $activityContact['contact_id'];
656 break;
657
658 case 'Activity Assignees':
659 $contacts['assignee_contact_id'] = $activityContact['contact_id'];
660 break;
661
662 }
663 }
664 return $contacts;
665 }
666
6a488035 667}