Code cleanup - Batch #9
[civicrm-core.git] / tests / phpunit / api / v3 / ACLPermissionTest.php
CommitLineData
6a488035 1<?php
6a488035
TO
2/*
3 +--------------------------------------------------------------------+
39de6fd5 4 | CiviCRM version 4.6 |
6a488035 5 +--------------------------------------------------------------------+
06a1bc01 6 | Copyright CiviCRM LLC (c) 2004-2014 |
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
28require_once 'CiviTest/CiviUnitTestCase.php';
29
30/**
31 * This class is intended to test ACL permission using the multisite module
32 *
7884d958 33 * @package CiviCRM_APIv3
34 * @subpackage API_Contact
6a488035 35 */
6a488035 36class api_v3_ACLPermissionTest extends CiviUnitTestCase {
4e420887 37 protected $_apiversion = 3;
4e420887 38 public $DBResetRequired = FALSE;
430ae6dd
TO
39 protected $_entity;
40
00be9182 41 public function setUp() {
6a488035
TO
42 parent::setUp();
43 $baoObj = new CRM_Core_DAO();
44 $baoObj->createTestObject('CRM_Pledge_BAO_Pledge', array(), 1, 0);
45 $baoObj->createTestObject('CRM_Core_BAO_Phone', array(), 1, 0);
6a488035
TO
46 $config = CRM_Core_Config::singleton();
47 $config->userPermissionClass->permissions = array();
48 }
7884d958 49
50 /**
51 * (non-PHPdoc)
52 * @see CiviUnitTestCase::tearDown()
53 */
00be9182 54 public function tearDown() {
e182b859 55 CRM_Utils_Hook::singleton()->reset();
6a488035 56 $tablesToTruncate = array(
7884d958 57 'civicrm_contact',
ae4bb4c9
EM
58 'civicrm_group_contact',
59 'civicrm_group',
60 'civicrm_acl',
61 'civicrm_acl_cache',
62 'civicrm_acl_entity_role',
63 'civicrm_acl_contact_cache',
64 'civicrm_contribution',
65 'civicrm_participant',
6a488035
TO
66 );
67 $this->quickCleanup($tablesToTruncate);
68 $config = CRM_Core_Config::singleton();
69 unset($config->userPermissionClass->permissions);
70 }
7884d958 71
72 /**
73 * Function tests that an empty where hook returns no results
74 */
00be9182 75 public function testContactGetNoResultsHook() {
6a488035 76 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookNoResults'));
4e420887 77 $result = $this->callAPISuccess('contact', 'get', array(
6a488035
TO
78 'check_permissions' => 1,
79 'return' => 'display_name',
80 ));
6a488035
TO
81 $this->assertEquals(0, $result['count']);
82 }
83
84 /**
85 * Function tests all results are returned
7884d958 86 */
00be9182 87 public function testContactGetAllResultsHook() {
6a488035 88 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookAllResults'));
4e420887 89 $result = $this->callAPISuccess('contact', 'get', array(
7884d958 90 'check_permissions' => 1,
91 'return' => 'display_name',
6a488035
TO
92 ));
93
6a488035
TO
94 $this->assertEquals(2, $result['count']);
95 }
7884d958 96
6a488035 97 /**
5d3b3d60 98 * Function tests that deleted contacts are not returned
7884d958 99 */
00be9182 100 public function testContactGetPermissionHookNoDeleted() {
f5052d4d 101 $this->callAPISuccess('contact', 'create', array('id' => 2, 'is_deleted' => 1));
6a488035 102 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookAllResults'));
4e420887 103 $result = $this->callAPISuccess('contact', 'get', array(
7884d958 104 'check_permissions' => 1,
105 'return' => 'display_name',
6a488035 106 ));
6a488035
TO
107 $this->assertEquals(1, $result['count']);
108 }
109
110 /**
100fef9d 111 * Test permissions limited by hook
6a488035 112 */
00be9182 113 public function testContactGetHookLimitingHook() {
6a488035
TO
114 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereOnlySecond'));
115
4e420887 116 $result = $this->callAPISuccess('contact', 'get', array(
6a488035
TO
117 'check_permissions' => 1,
118 'return' => 'display_name',
7884d958 119 ));
6a488035
TO
120 $this->assertEquals(1, $result['count']);
121 }
122
7884d958 123 /**
100fef9d 124 * Confirm that without check permissions we still get 2 contacts returned
7884d958 125 */
00be9182 126 public function testContactGetHookLimitingHookDontCheck() {
4e420887 127 $result = $this->callAPISuccess('contact', 'get', array(
128 'check_permissions' => 0,
129 'return' => 'display_name',
6a488035 130 ));
6a488035
TO
131 $this->assertEquals(2, $result['count']);
132 }
7884d958 133
6a488035
TO
134 /**
135 * Check that id works as a filter
136 */
00be9182 137 public function testContactGetIDFilter() {
6a488035 138 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookAllResults'));
4e420887 139 $result = $this->callAPISuccess('contact', 'get', array(
6a488035
TO
140 'sequential' => 1,
141 'id' => 2,
142 'check_permissions' => 1,
143 ));
144
6a488035
TO
145 $this->assertEquals(1, $result['count']);
146 $this->assertEquals(2, $result['id']);
147 }
148
7884d958 149 /**
150 * Check that address IS returned
151 */
00be9182 152 public function testContactGetAddressReturned() {
7884d958 153 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereOnlySecond'));
154 $fullresult = $this->callAPISuccess('contact', 'get', array(
155 'sequential' => 1,
156 ));
157 //return doesn't work for all keys - can't fix that here so let's skip ...
158 //prefix & suffix are inconsistent due to CRM-7929
159 // unsure about others but return doesn't work on them
160 $elementsReturnDoesntSupport = array(
7884d958 161 'prefix',
7884d958 162 'suffix',
7884d958 163 'gender',
164 'current_employer',
165 'phone_id',
166 'phone_type_id',
167 'phone',
168 'worldregion_id',
21dfd5f5 169 'world_region',
7884d958 170 );
171 $expectedReturnElements = array_diff(array_keys($fullresult['values'][0]), $elementsReturnDoesntSupport);
172 $result = $this->callAPISuccess('contact', 'get', array(
173 'check_permissions' => 1,
174 'return' => $expectedReturnElements,
175 'sequential' => 1,
176 ));
177 $this->assertEquals(1, $result['count']);
178 foreach ($expectedReturnElements as $element) {
179 $this->assertArrayHasKey($element, $result['values'][0]);
6a488035 180 }
7884d958 181 }
182
183 /**
184 * Check that pledge IS not returned
185 */
00be9182 186 public function testContactGetPledgeIDNotReturned() {
7884d958 187 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookAllResults'));
f5052d4d 188 $this->callAPISuccess('contact', 'get', array(
7884d958 189 'sequential' => 1,
190 ));
191 $result = $this->callAPISuccess('contact', 'get', array(
192 'check_permissions' => 1,
193 'return' => 'pledge_id',
194 'sequential' => 1,
195 ));
196 $this->assertArrayNotHasKey('pledge_id', $result['values'][0]);
197 }
6a488035 198
7884d958 199 /**
200 * Check that pledge IS not an allowable filter
201 */
00be9182 202 public function testContactGetPledgeIDNotFiltered() {
7884d958 203 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookAllResults'));
f5052d4d 204 $this->callAPISuccess('contact', 'get', array(
7884d958 205 'sequential' => 1,
206 ));
207 $result = $this->callAPISuccess('contact', 'get', array(
208 'check_permissions' => 1,
209 'pledge_id' => 1,
210 'sequential' => 1,
211 ));
212 $this->assertEquals(2, $result['count']);
213 }
214
215 /**
216 * Check that chaining doesn't bypass permissions
217 */
00be9182 218 public function testContactGetPledgeNotChainable() {
7884d958 219 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereOnlySecond'));
f5052d4d 220 $this->callAPISuccess('contact', 'get', array(
7884d958 221 'sequential' => 1,
222 ));
f5052d4d 223 $this->callAPIFailure('contact', 'get', array(
6a488035 224 'check_permissions' => 1,
7884d958 225 'api.pledge.get' => 1,
6a488035 226 'sequential' => 1,
4e420887 227 ),
228 'Error in call to pledge_get : API permission check failed for pledge/get call; missing permission: access CiviCRM.'
7884d958 229 );
230 }
6a488035 231
00be9182 232 public function setupCoreACL() {
ae4bb4c9 233 $this->createLoggedInUser();
5896d037 234 $this->_permissionedDisabledGroup = $this->groupCreate(array(
92915c55
TO
235 'title' => 'pick-me-disabled',
236 'is_active' => 0,
237 'name' => 'pick-me-disabled',
238 ));
5896d037 239 $this->_permissionedGroup = $this->groupCreate(array(
92915c55
TO
240 'title' => 'pick-me-active',
241 'is_active' => 1,
242 'name' => 'pick-me-active',
243 ));
ae4bb4c9
EM
244 $this->setupACL();
245 }
5896d037 246
ae4bb4c9
EM
247 /**
248 * @dataProvider entities
249 * confirm that without check permissions we still get 2 contacts returned
1e1fdcf6 250 * @param $entity
ae4bb4c9 251 */
00be9182 252 public function testEntitiesGetHookLimitingHookNoCheck($entity) {
ae4bb4c9
EM
253 CRM_Core_Config::singleton()->userPermissionClass->permissions = array();
254 $this->setUpEntities($entity);
255 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookNoResults'));
256 $result = $this->callAPISuccess($entity, 'get', array(
257 'check_permissions' => 0,
258 'return' => 'contact_id',
259 ));
260 $this->assertEquals(2, $result['count']);
261 }
262
263 /**
264 * @dataProvider entities
265 * confirm that without check permissions we still get 2 entities returned
1e1fdcf6 266 * @param $entity
ae4bb4c9 267 */
00be9182 268 public function testEntitiesGetCoreACLLimitingHookNoCheck($entity) {
ae4bb4c9
EM
269 $this->setupCoreACL();
270 //CRM_Core_Config::singleton()->userPermissionClass->permissions = array();
271 $this->setUpEntities($entity);
272 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookNoResults'));
273 $result = $this->callAPISuccess($entity, 'get', array(
274 'check_permissions' => 0,
275 'return' => 'contact_id',
276 ));
277 $this->assertEquals(2, $result['count']);
278 }
5896d037 279
ae4bb4c9
EM
280 /**
281 * @dataProvider entities
282 * confirm that with check permissions we don't get entities
1e1fdcf6
EM
283 * @param $entity
284 * @throws \PHPUnit_Framework_IncompleteTestError
ae4bb4c9 285 */
00be9182 286 public function testEntitiesGetCoreACLLimitingCheck($entity) {
9730e9e3 287 $this->markTestIncomplete('this does not work in 4.4 but can be enabled in 4.5 or a security release of 4.4 including the important security fix CRM-14877');
ae4bb4c9
EM
288 $this->setupCoreACL();
289 $this->setUpEntities($entity);
ae4bb4c9
EM
290 $result = $this->callAPISuccess($entity, 'get', array(
291 'check_permissions' => 1,
292 'return' => 'contact_id',
293 ));
294 $this->assertEquals(0, $result['count']);
295 }
296
297
298 /**
299 * @dataProvider entities
300 * Function tests that an empty where hook returns no results
1e1fdcf6
EM
301 * @param $entity
302 * @throws \PHPUnit_Framework_IncompleteTestError
ae4bb4c9 303 */
00be9182 304 public function testEntityGetNoResultsHook($entity) {
ae4bb4c9
EM
305 $this->markTestIncomplete('hook acls only work with contacts so far');
306 CRM_Core_Config::singleton()->userPermissionClass->permissions = array();
307 $this->setUpEntities($entity);
308 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookNoResults'));
309 $result = $this->callAPISuccess($entity, 'get', array(
310 'check_permission' => 1,
311 ));
312 $this->assertEquals(0, $result['count']);
313 }
314
315 /**
316 * @return array
317 */
318 public static function entities() {
6c6e6187 319 return array(array('contribution'), array('participant'));// @todo array('pledge' => 'pledge')
ae4bb4c9
EM
320 }
321
322 /**
323 * Create 2 entities
1e1fdcf6 324 * @param $entity
ae4bb4c9
EM
325 */
326 public function setUpEntities($entity) {
327 $baoObj = new CRM_Core_DAO();
5896d037 328 $baoObj->createTestObject(_civicrm_api3_get_BAO($entity), array(), 2, 0);
ae4bb4c9
EM
329 CRM_Core_Config::singleton()->userPermissionClass->permissions = array(
330 'access CiviCRM',
331 'access CiviContribute',
332 'access CiviEvent',
333 'view event participants',
334 );
335 }
336
6a488035 337 /**
100fef9d 338 * No results returned
1e1fdcf6
EM
339 * @param $type
340 * @param $tables
341 * @param $whereTables
342 * @param $contactID
343 * @param $where
6a488035 344 */
00be9182 345 public function aclWhereHookNoResults($type, &$tables, &$whereTables, &$contactID, &$where) {
6a488035 346 }
7884d958 347
6a488035 348 /**
100fef9d 349 * All results returned
f5052d4d 350 * @implements CRM_Utils_Hook::aclWhereClause
1e1fdcf6
EM
351 * @param $type
352 * @param $tables
353 * @param $whereTables
354 * @param $contactID
355 * @param $where
7884d958 356 */
00be9182 357 public function aclWhereHookAllResults($type, &$tables, &$whereTables, &$contactID, &$where) {
6a488035
TO
358 $where = " (1) ";
359 }
7884d958 360
6a488035 361 /**
100fef9d 362 * Full results returned
f5052d4d 363 * @implements CRM_Utils_Hook::aclWhereClause
1e1fdcf6
EM
364 * @param $type
365 * @param $tables
366 * @param $whereTables
367 * @param $contactID
368 * @param $where
7884d958 369 */
00be9182 370 public function aclWhereOnlySecond($type, &$tables, &$whereTables, &$contactID, &$where) {
6a488035
TO
371 $where = " contact_a.id > 1";
372 }
6a488035 373}