3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2014 |
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 +--------------------------------------------------------------------+
28 require_once 'CiviTest/CiviUnitTestCase.php';
31 * This class is intended to test ACL permission using the multisite module
33 * @package CiviCRM_APIv3
34 * @subpackage API_Contact
37 class api_v3_ACLPermissionTest
extends CiviUnitTestCase
{
38 protected $_apiversion = 3;
42 * @var CRM_Utils_Hook_UnitTests
44 protected $hookClass = NULL;
45 public $DBResetRequired = FALSE;
53 $baoObj = new CRM_Core_DAO();
54 $baoObj->createTestObject('CRM_Pledge_BAO_Pledge', array(), 1, 0);
55 $baoObj->createTestObject('CRM_Core_BAO_Phone', array(), 1, 0);
56 $this->hookClass
= CRM_Utils_Hook
::singleton();
57 $config = CRM_Core_Config
::singleton();
58 $config->userPermissionClass
->permissions
= array();
63 * @see CiviUnitTestCase::tearDown()
66 CRM_Utils_Hook
::singleton()->reset();
67 $tablesToTruncate = array(
69 'civicrm_group_contact',
73 'civicrm_acl_entity_role',
74 'civicrm_acl_contact_cache',
75 'civicrm_contribution',
76 'civicrm_participant',
78 $this->quickCleanup($tablesToTruncate);
79 $config = CRM_Core_Config
::singleton();
80 unset($config->userPermissionClass
->permissions
);
84 * Function tests that an empty where hook returns no results
86 function testContactGetNoResultsHook() {
87 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookNoResults'));
88 $result = $this->callAPISuccess('contact', 'get', array(
89 'check_permissions' => 1,
90 'return' => 'display_name',
92 $this->assertEquals(0, $result['count']);
96 * Function tests all results are returned
98 function testContactGetAllResultsHook() {
99 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookAllResults'));
100 $result = $this->callAPISuccess('contact', 'get', array(
101 'check_permissions' => 1,
102 'return' => 'display_name',
105 $this->assertEquals(2, $result['count']);
109 * Function tests that deleted contacts are not returned
111 function testContactGetPermissionHookNoDeleted() {
112 $this->callAPISuccess('contact', 'create', array('id' => 2, 'is_deleted' => 1));
113 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookAllResults'));
114 $result = $this->callAPISuccess('contact', 'get', array(
115 'check_permissions' => 1,
116 'return' => 'display_name',
118 $this->assertEquals(1, $result['count']);
122 * Test permissions limited by hook
124 function testContactGetHookLimitingHook() {
125 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereOnlySecond'));
127 $result = $this->callAPISuccess('contact', 'get', array(
128 'check_permissions' => 1,
129 'return' => 'display_name',
131 $this->assertEquals(1, $result['count']);
135 * Confirm that without check permissions we still get 2 contacts returned
137 function testContactGetHookLimitingHookDontCheck() {
139 $result = $this->callAPISuccess('contact', 'get', array(
140 'check_permissions' => 0,
141 'return' => 'display_name',
143 $this->assertEquals(2, $result['count']);
147 * Check that id works as a filter
149 function testContactGetIDFilter() {
150 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookAllResults'));
151 $result = $this->callAPISuccess('contact', 'get', array(
154 'check_permissions' => 1,
157 $this->assertEquals(1, $result['count']);
158 $this->assertEquals(2, $result['id']);
162 * Check that address IS returned
164 function testContactGetAddressReturned() {
165 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereOnlySecond'));
166 $fullresult = $this->callAPISuccess('contact', 'get', array(
169 //return doesn't work for all keys - can't fix that here so let's skip ...
170 //prefix & suffix are inconsistent due to CRM-7929
171 // unsure about others but return doesn't work on them
172 $elementsReturnDoesntSupport = array(
183 $expectedReturnElements = array_diff(array_keys($fullresult['values'][0]), $elementsReturnDoesntSupport);
184 $result = $this->callAPISuccess('contact', 'get', array(
185 'check_permissions' => 1,
186 'return' => $expectedReturnElements,
189 $this->assertEquals(1, $result['count']);
190 foreach ($expectedReturnElements as $element) {
191 $this->assertArrayHasKey($element, $result['values'][0]);
196 * Check that pledge IS not returned
198 function testContactGetPledgeIDNotReturned() {
199 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookAllResults'));
200 $this->callAPISuccess('contact', 'get', array(
203 $result = $this->callAPISuccess('contact', 'get', array(
204 'check_permissions' => 1,
205 'return' => 'pledge_id',
208 $this->assertArrayNotHasKey('pledge_id', $result['values'][0]);
212 * Check that pledge IS not an allowable filter
214 function testContactGetPledgeIDNotFiltered() {
215 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookAllResults'));
216 $this->callAPISuccess('contact', 'get', array(
219 $result = $this->callAPISuccess('contact', 'get', array(
220 'check_permissions' => 1,
224 $this->assertEquals(2, $result['count']);
228 * Check that chaining doesn't bypass permissions
230 function testContactGetPledgeNotChainable() {
231 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereOnlySecond'));
232 $this->callAPISuccess('contact', 'get', array(
235 $this->callAPIFailure('contact', 'get', array(
236 'check_permissions' => 1,
237 'api.pledge.get' => 1,
240 'Error in call to pledge_get : API permission check failed for pledge/get call; missing permission: access CiviCRM.'
244 function setupCoreACL() {
245 $this->createLoggedInUser();
246 $this->_permissionedDisabledGroup
= $this->groupCreate(array('title' => 'pick-me-disabled', 'is_active' => 0, 'name' => 'pick-me-disabled'));
247 $this->_permissionedGroup
= $this->groupCreate(array('title' => 'pick-me-active', 'is_active' => 1, 'name' => 'pick-me-active'));
251 * @dataProvider entities
252 * confirm that without check permissions we still get 2 contacts returned
254 function testEntitiesGetHookLimitingHookNoCheck($entity) {
255 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array();
256 $this->setUpEntities($entity);
257 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookNoResults'));
258 $result = $this->callAPISuccess($entity, 'get', array(
259 'check_permissions' => 0,
260 'return' => 'contact_id',
262 $this->assertEquals(2, $result['count']);
266 * @dataProvider entities
267 * confirm that without check permissions we still get 2 entities returned
269 function testEntitiesGetCoreACLLimitingHookNoCheck($entity) {
270 $this->setupCoreACL();
271 //CRM_Core_Config::singleton()->userPermissionClass->permissions = array();
272 $this->setUpEntities($entity);
273 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookNoResults'));
274 $result = $this->callAPISuccess($entity, 'get', array(
275 'check_permissions' => 0,
276 'return' => 'contact_id',
278 $this->assertEquals(2, $result['count']);
281 * @dataProvider entities
282 * confirm that with check permissions we don't get entities
284 function testEntitiesGetCoreACLLimitingCheck($entity) {
285 $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');
286 $this->setupCoreACL();
287 $this->setUpEntities($entity);
288 $result = $this->callAPISuccess($entity, 'get', array(
289 'check_permissions' => 1,
290 'return' => 'contact_id',
292 $this->assertEquals(0, $result['count']);
297 * @dataProvider entities
298 * Function tests that an empty where hook returns no results
300 function testEntityGetNoResultsHook($entity) {
301 $this->markTestIncomplete('hook acls only work with contacts so far');
302 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array();
303 $this->setUpEntities($entity);
304 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookNoResults'));
305 $result = $this->callAPISuccess($entity, 'get', array(
306 'check_permission' => 1,
308 $this->assertEquals(0, $result['count']);
314 public static function entities() {
315 return array(array('contribution'), array('participant'),);// @todo array('pledge' => 'pledge')
321 public function setUpEntities($entity) {
322 $baoObj = new CRM_Core_DAO();
323 $baoObj->createTestObject( _civicrm_api3_get_BAO($entity), array(), 2, 0);
324 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array(
326 'access CiviContribute',
328 'view event participants',
333 * No results returned
335 function aclWhereHookNoResults($type, &$tables, &$whereTables, &$contactID, &$where) {
339 * All results returned
340 * @implements CRM_Utils_Hook::aclWhereClause
342 function aclWhereHookAllResults($type, &$tables, &$whereTables, &$contactID, &$where) {
347 * Full results returned
348 * @implements CRM_Utils_Hook::aclWhereClause
350 function aclWhereOnlySecond($type, &$tables, &$whereTables, &$contactID, &$where) {
351 $where = " contact_a.id > 1";