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
37 class api_v3_ACLPermissionTest
extends CiviUnitTestCase
{
38 protected $_apiversion = 3;
39 public $DBResetRequired = FALSE;
42 public function 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();
53 * @see CiviUnitTestCase::tearDown()
55 public function tearDown() {
56 CRM_Utils_Hook
::singleton()->reset();
57 $tablesToTruncate = array(
59 'civicrm_group_contact',
63 'civicrm_acl_entity_role',
64 'civicrm_acl_contact_cache',
65 'civicrm_contribution',
66 '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 all results are returned
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',
95 $this->assertEquals(2, $result['count']);
99 * Function tests that deleted contacts are not returned
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',
108 $this->assertEquals(1, $result['count']);
112 * Test permissions limited by hook
114 public function testContactGetHookLimitingHook() {
115 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereOnlySecond'));
117 $result = $this->callAPISuccess('contact', 'get', array(
118 'check_permissions' => 1,
119 'return' => 'display_name',
121 $this->assertEquals(1, $result['count']);
125 * Confirm that without check permissions we still get 2 contacts returned
127 public function testContactGetHookLimitingHookDontCheck() {
129 $result = $this->callAPISuccess('contact', 'get', array(
130 'check_permissions' => 0,
131 'return' => 'display_name',
133 $this->assertEquals(2, $result['count']);
137 * Check that id works as a filter
139 public function testContactGetIDFilter() {
140 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookAllResults'));
141 $result = $this->callAPISuccess('contact', 'get', array(
144 'check_permissions' => 1,
147 $this->assertEquals(1, $result['count']);
148 $this->assertEquals(2, $result['id']);
152 * Check that address IS returned
154 public function testContactGetAddressReturned() {
155 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereOnlySecond'));
156 $fullresult = $this->callAPISuccess('contact', 'get', array(
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(
173 $expectedReturnElements = array_diff(array_keys($fullresult['values'][0]), $elementsReturnDoesntSupport);
174 $result = $this->callAPISuccess('contact', 'get', array(
175 'check_permissions' => 1,
176 'return' => $expectedReturnElements,
179 $this->assertEquals(1, $result['count']);
180 foreach ($expectedReturnElements as $element) {
181 $this->assertArrayHasKey($element, $result['values'][0]);
186 * Check that pledge IS not returned
188 public function testContactGetPledgeIDNotReturned() {
189 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookAllResults'));
190 $this->callAPISuccess('contact', 'get', array(
193 $result = $this->callAPISuccess('contact', 'get', array(
194 'check_permissions' => 1,
195 'return' => 'pledge_id',
198 $this->assertArrayNotHasKey('pledge_id', $result['values'][0]);
202 * Check that pledge IS not an allowable filter
204 public function testContactGetPledgeIDNotFiltered() {
205 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookAllResults'));
206 $this->callAPISuccess('contact', 'get', array(
209 $result = $this->callAPISuccess('contact', 'get', array(
210 'check_permissions' => 1,
214 $this->assertEquals(2, $result['count']);
218 * Check that chaining doesn't bypass permissions
220 public function testContactGetPledgeNotChainable() {
221 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereOnlySecond'));
222 $this->callAPISuccess('contact', 'get', array(
225 $this->callAPIFailure('contact', 'get', array(
226 'check_permissions' => 1,
227 'api.pledge.get' => 1,
230 'Error in call to pledge_get : API permission check failed for pledge/get call; missing permission: access CiviCRM.'
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'));
241 * @dataProvider entities
242 * confirm that without check permissions we still get 2 contacts returned
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',
252 $this->assertEquals(2, $result['count']);
256 * @dataProvider entities
257 * confirm that without check permissions we still get 2 entities returned
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',
268 $this->assertEquals(2, $result['count']);
271 * @dataProvider entities
272 * confirm that with check permissions we don't get entities
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',
282 $this->assertEquals(0, $result['count']);
287 * @dataProvider entities
288 * Function tests that an empty where hook returns no results
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,
298 $this->assertEquals(0, $result['count']);
304 public static function entities() {
305 return array(array('contribution'), array('participant'));// @todo array('pledge' => 'pledge')
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(
316 'access CiviContribute',
318 'view event participants',
323 * No results returned
325 public function aclWhereHookNoResults($type, &$tables, &$whereTables, &$contactID, &$where) {
329 * All results returned
330 * @implements CRM_Utils_Hook::aclWhereClause
332 public function aclWhereHookAllResults($type, &$tables, &$whereTables, &$contactID, &$where) {
337 * Full results returned
338 * @implements CRM_Utils_Hook::aclWhereClause
340 public function aclWhereOnlySecond($type, &$tables, &$whereTables, &$contactID, &$where) {
341 $where = " contact_a.id > 1";