3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.7 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2015 |
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',
68 $this->quickCleanup($tablesToTruncate);
69 $config = CRM_Core_Config
::singleton();
70 unset($config->userPermissionClass
->permissions
);
74 * Function tests that an empty where hook returns no results.
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',
82 $this->assertEquals(0, $result['count']);
86 * Function tests that an empty where hook returns exactly 1 result with "view my contact".
88 * CRM-16512 caused contacts with Edit my contact to be able to view all records.
90 public function testContactGetOneResultHookWithViewMyContact() {
91 $this->createLoggedInUser();
92 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookNoResults'));
93 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array('access CiviCRM', 'view my contact');
94 $result = $this->callAPISuccess('contact', 'get', array(
95 'check_permissions' => 1,
96 'return' => 'display_name',
98 $this->assertEquals(1, $result['count']);
102 * Function tests that a user with "edit my contact" can edit themselves.
104 public function testContactEditHookWithEditMyContact() {
105 $this->markTestIncomplete('api acls only work with contact get so far');
106 $cid = $this->createLoggedInUser();
107 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookNoResults'));
108 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array('access CiviCRM', 'edit my contact');
109 $this->callAPISuccess('contact', 'create', array(
110 'check_permissions' => 1,
116 * Function tests all results are returned.
118 public function testContactGetAllResultsHook() {
119 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookAllResults'));
120 $result = $this->callAPISuccess('contact', 'get', array(
121 'check_permissions' => 1,
122 'return' => 'display_name',
125 $this->assertEquals(2, $result['count']);
129 * Function tests that deleted contacts are not returned.
131 public function testContactGetPermissionHookNoDeleted() {
132 $this->callAPISuccess('contact', 'create', array('id' => 2, 'is_deleted' => 1));
133 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookAllResults'));
134 $result = $this->callAPISuccess('contact', 'get', array(
135 'check_permissions' => 1,
136 'return' => 'display_name',
138 $this->assertEquals(1, $result['count']);
142 * Test permissions limited by hook.
144 public function testContactGetHookLimitingHook() {
145 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereOnlySecond'));
147 $result = $this->callAPISuccess('contact', 'get', array(
148 'check_permissions' => 1,
149 'return' => 'display_name',
151 $this->assertEquals(1, $result['count']);
155 * Confirm that without check permissions we still get 2 contacts returned.
157 public function testContactGetHookLimitingHookDontCheck() {
158 $result = $this->callAPISuccess('contact', 'get', array(
159 'check_permissions' => 0,
160 'return' => 'display_name',
162 $this->assertEquals(2, $result['count']);
166 * Check that id works as a filter.
168 public function testContactGetIDFilter() {
169 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookAllResults'));
170 $result = $this->callAPISuccess('contact', 'get', array(
173 'check_permissions' => 1,
176 $this->assertEquals(1, $result['count']);
177 $this->assertEquals(2, $result['id']);
181 * Check that address IS returned.
183 public function testContactGetAddressReturned() {
184 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereOnlySecond'));
185 $fullresult = $this->callAPISuccess('contact', 'get', array(
188 //return doesn't work for all keys - can't fix that here so let's skip ...
189 //prefix & suffix are inconsistent due to CRM-7929
190 // unsure about others but return doesn't work on them
191 $elementsReturnDoesntSupport = array(
202 $expectedReturnElements = array_diff(array_keys($fullresult['values'][0]), $elementsReturnDoesntSupport);
203 $result = $this->callAPISuccess('contact', 'get', array(
204 'check_permissions' => 1,
205 'return' => $expectedReturnElements,
208 $this->assertEquals(1, $result['count']);
209 foreach ($expectedReturnElements as $element) {
210 $this->assertArrayHasKey($element, $result['values'][0]);
215 * Check that pledge IS not returned.
217 public function testContactGetPledgeIDNotReturned() {
218 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookAllResults'));
219 $this->callAPISuccess('contact', 'get', array(
222 $result = $this->callAPISuccess('contact', 'get', array(
223 'check_permissions' => 1,
224 'return' => 'pledge_id',
227 $this->assertArrayNotHasKey('pledge_id', $result['values'][0]);
231 * Check that pledge IS not an allowable filter.
233 public function testContactGetPledgeIDNotFiltered() {
234 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookAllResults'));
235 $this->callAPISuccess('contact', 'get', array(
238 $result = $this->callAPISuccess('contact', 'get', array(
239 'check_permissions' => 1,
243 $this->assertEquals(2, $result['count']);
247 * Check that chaining doesn't bypass permissions
249 public function testContactGetPledgeNotChainable() {
250 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereOnlySecond'));
251 $this->callAPISuccess('contact', 'get', array(
254 $this->callAPIFailure('contact', 'get', array(
255 'check_permissions' => 1,
256 'api.pledge.get' => 1,
259 'Error in call to pledge_get : API permission check failed for pledge/get call; missing permission: access CiviCRM.'
263 public function setupCoreACL() {
264 $this->createLoggedInUser();
265 $this->_permissionedDisabledGroup
= $this->groupCreate(array(
266 'title' => 'pick-me-disabled',
268 'name' => 'pick-me-disabled',
270 $this->_permissionedGroup
= $this->groupCreate(array(
271 'title' => 'pick-me-active',
273 'name' => 'pick-me-active',
279 * @dataProvider entities
280 * confirm that without check permissions we still get 2 contacts returned
283 public function testEntitiesGetHookLimitingHookNoCheck($entity) {
284 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array();
285 $this->setUpEntities($entity);
286 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookNoResults'));
287 $result = $this->callAPISuccess($entity, 'get', array(
288 'check_permissions' => 0,
289 'return' => 'contact_id',
291 $this->assertEquals(2, $result['count']);
295 * @dataProvider entities
296 * confirm that without check permissions we still get 2 entities returned
299 public function testEntitiesGetCoreACLLimitingHookNoCheck($entity) {
300 $this->setupCoreACL();
301 //CRM_Core_Config::singleton()->userPermissionClass->permissions = array();
302 $this->setUpEntities($entity);
303 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookNoResults'));
304 $result = $this->callAPISuccess($entity, 'get', array(
305 'check_permissions' => 0,
306 'return' => 'contact_id',
308 $this->assertEquals(2, $result['count']);
312 * @dataProvider entities
313 * confirm that with check permissions we don't get entities
315 * @throws \PHPUnit_Framework_IncompleteTestError
317 public function testEntitiesGetCoreACLLimitingCheck($entity) {
318 $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');
319 $this->setupCoreACL();
320 $this->setUpEntities($entity);
321 $result = $this->callAPISuccess($entity, 'get', array(
322 'check_permissions' => 1,
323 'return' => 'contact_id',
325 $this->assertEquals(0, $result['count']);
330 * @dataProvider entities
331 * Function tests that an empty where hook returns no results
332 * @param string $entity
333 * @throws \PHPUnit_Framework_IncompleteTestError
335 public function testEntityGetNoResultsHook($entity) {
336 $this->markTestIncomplete('hook acls only work with contacts so far');
337 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array();
338 $this->setUpEntities($entity);
339 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookNoResults'));
340 $result = $this->callAPISuccess($entity, 'get', array(
341 'check_permission' => 1,
343 $this->assertEquals(0, $result['count']);
349 public static function entities() {
350 return array(array('contribution'), array('participant'));// @todo array('pledge' => 'pledge')
357 public function setUpEntities($entity) {
358 $baoObj = new CRM_Core_DAO();
359 $baoObj->createTestObject(_civicrm_api3_get_BAO($entity), array(), 2, 0);
360 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array(
362 'access CiviContribute',
364 'view event participants',
369 * No results returned.
372 * @param $whereTables
376 public function aclWhereHookNoResults($type, &$tables, &$whereTables, &$contactID, &$where) {
380 * All results returned.
381 * @implements CRM_Utils_Hook::aclWhereClause
384 * @param $whereTables
388 public function aclWhereHookAllResults($type, &$tables, &$whereTables, &$contactID, &$where) {
393 * Full results returned.
394 * @implements CRM_Utils_Hook::aclWhereClause
397 * @param $whereTables
401 public function aclWhereOnlySecond($type, &$tables, &$whereTables, &$contactID, &$where) {
402 $where = " contact_a.id > 1";