3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.6 |
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
36 class api_v3_ACLPermissionTest
extends CiviUnitTestCase
{
37 protected $_apiversion = 3;
38 public $DBResetRequired = FALSE;
41 public function 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);
46 $config = CRM_Core_Config
::singleton();
47 $config->userPermissionClass
->permissions
= array();
52 * @see CiviUnitTestCase::tearDown()
54 public function tearDown() {
55 CRM_Utils_Hook
::singleton()->reset();
56 $tablesToTruncate = array(
58 'civicrm_group_contact',
62 'civicrm_acl_entity_role',
63 'civicrm_acl_contact_cache',
64 'civicrm_contribution',
65 'civicrm_participant',
67 $this->quickCleanup($tablesToTruncate);
68 $config = CRM_Core_Config
::singleton();
69 unset($config->userPermissionClass
->permissions
);
73 * Function tests that an empty where hook returns no results
75 public function testContactGetNoResultsHook() {
76 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookNoResults'));
77 $result = $this->callAPISuccess('contact', 'get', array(
78 'check_permissions' => 1,
79 'return' => 'display_name',
81 $this->assertEquals(0, $result['count']);
85 * Function tests all results are returned
87 public function testContactGetAllResultsHook() {
88 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookAllResults'));
89 $result = $this->callAPISuccess('contact', 'get', array(
90 'check_permissions' => 1,
91 'return' => 'display_name',
94 $this->assertEquals(2, $result['count']);
98 * Function tests that deleted contacts are not returned
100 public function testContactGetPermissionHookNoDeleted() {
101 $this->callAPISuccess('contact', 'create', array('id' => 2, 'is_deleted' => 1));
102 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookAllResults'));
103 $result = $this->callAPISuccess('contact', 'get', array(
104 'check_permissions' => 1,
105 'return' => 'display_name',
107 $this->assertEquals(1, $result['count']);
111 * Test permissions limited by hook
113 public function testContactGetHookLimitingHook() {
114 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereOnlySecond'));
116 $result = $this->callAPISuccess('contact', 'get', array(
117 'check_permissions' => 1,
118 'return' => 'display_name',
120 $this->assertEquals(1, $result['count']);
124 * Confirm that without check permissions we still get 2 contacts returned
126 public function testContactGetHookLimitingHookDontCheck() {
127 $result = $this->callAPISuccess('contact', 'get', array(
128 'check_permissions' => 0,
129 'return' => 'display_name',
131 $this->assertEquals(2, $result['count']);
135 * Check that id works as a filter
137 public function testContactGetIDFilter() {
138 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookAllResults'));
139 $result = $this->callAPISuccess('contact', 'get', array(
142 'check_permissions' => 1,
145 $this->assertEquals(1, $result['count']);
146 $this->assertEquals(2, $result['id']);
150 * Check that address IS returned
152 public function testContactGetAddressReturned() {
153 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereOnlySecond'));
154 $fullresult = $this->callAPISuccess('contact', 'get', array(
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(
171 $expectedReturnElements = array_diff(array_keys($fullresult['values'][0]), $elementsReturnDoesntSupport);
172 $result = $this->callAPISuccess('contact', 'get', array(
173 'check_permissions' => 1,
174 'return' => $expectedReturnElements,
177 $this->assertEquals(1, $result['count']);
178 foreach ($expectedReturnElements as $element) {
179 $this->assertArrayHasKey($element, $result['values'][0]);
184 * Check that pledge IS not returned
186 public function testContactGetPledgeIDNotReturned() {
187 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookAllResults'));
188 $this->callAPISuccess('contact', 'get', array(
191 $result = $this->callAPISuccess('contact', 'get', array(
192 'check_permissions' => 1,
193 'return' => 'pledge_id',
196 $this->assertArrayNotHasKey('pledge_id', $result['values'][0]);
200 * Check that pledge IS not an allowable filter
202 public function testContactGetPledgeIDNotFiltered() {
203 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookAllResults'));
204 $this->callAPISuccess('contact', 'get', array(
207 $result = $this->callAPISuccess('contact', 'get', array(
208 'check_permissions' => 1,
212 $this->assertEquals(2, $result['count']);
216 * Check that chaining doesn't bypass permissions
218 public function testContactGetPledgeNotChainable() {
219 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereOnlySecond'));
220 $this->callAPISuccess('contact', 'get', array(
223 $this->callAPIFailure('contact', 'get', array(
224 'check_permissions' => 1,
225 'api.pledge.get' => 1,
228 'Error in call to pledge_get : API permission check failed for pledge/get call; missing permission: access CiviCRM.'
232 public function setupCoreACL() {
233 $this->createLoggedInUser();
234 $this->_permissionedDisabledGroup
= $this->groupCreate(array(
235 'title' => 'pick-me-disabled',
237 'name' => 'pick-me-disabled',
239 $this->_permissionedGroup
= $this->groupCreate(array(
240 'title' => 'pick-me-active',
242 'name' => 'pick-me-active',
248 * @dataProvider entities
249 * confirm that without check permissions we still get 2 contacts returned
252 public function testEntitiesGetHookLimitingHookNoCheck($entity) {
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',
260 $this->assertEquals(2, $result['count']);
264 * @dataProvider entities
265 * confirm that without check permissions we still get 2 entities returned
268 public function testEntitiesGetCoreACLLimitingHookNoCheck($entity) {
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',
277 $this->assertEquals(2, $result['count']);
281 * @dataProvider entities
282 * confirm that with check permissions we don't get entities
284 * @throws \PHPUnit_Framework_IncompleteTestError
286 public function testEntitiesGetCoreACLLimitingCheck($entity) {
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');
288 $this->setupCoreACL();
289 $this->setUpEntities($entity);
290 $result = $this->callAPISuccess($entity, 'get', array(
291 'check_permissions' => 1,
292 'return' => 'contact_id',
294 $this->assertEquals(0, $result['count']);
299 * @dataProvider entities
300 * Function tests that an empty where hook returns no results
302 * @throws \PHPUnit_Framework_IncompleteTestError
304 public function testEntityGetNoResultsHook($entity) {
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,
312 $this->assertEquals(0, $result['count']);
318 public static function entities() {
319 return array(array('contribution'), array('participant'));// @todo array('pledge' => 'pledge')
326 public function setUpEntities($entity) {
327 $baoObj = new CRM_Core_DAO();
328 $baoObj->createTestObject(_civicrm_api3_get_BAO($entity), array(), 2, 0);
329 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array(
331 'access CiviContribute',
333 'view event participants',
338 * No results returned
341 * @param $whereTables
345 public function aclWhereHookNoResults($type, &$tables, &$whereTables, &$contactID, &$where) {
349 * All results returned
350 * @implements CRM_Utils_Hook::aclWhereClause
353 * @param $whereTables
357 public function aclWhereHookAllResults($type, &$tables, &$whereTables, &$contactID, &$where) {
362 * Full results returned
363 * @implements CRM_Utils_Hook::aclWhereClause
366 * @param $whereTables
370 public function aclWhereOnlySecond($type, &$tables, &$whereTables, &$contactID, &$where) {
371 $where = " contact_a.id > 1";