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