From c16ed19b9fe2bee60f971b55603a19d9565fcfa0 Mon Sep 17 00:00:00 2001 From: Coleman Watts Date: Mon, 18 Jan 2016 13:06:26 -0500 Subject: [PATCH] CRM-17795 - Api.contact.create/delete - support acls for contacts --- CRM/Core/DAO/permissions.php | 6 +-- api/v3/Contact.php | 12 ++++- tests/phpunit/api/v3/ACLPermissionTest.php | 51 +++++++++++++++++++++- 3 files changed, 61 insertions(+), 8 deletions(-) diff --git a/CRM/Core/DAO/permissions.php b/CRM/Core/DAO/permissions.php index 45367c124c..11af708f3a 100644 --- a/CRM/Core/DAO/permissions.php +++ b/CRM/Core/DAO/permissions.php @@ -86,10 +86,8 @@ function _civicrm_api3_permissions($entity, $action, &$params) { ), // managed by query object 'get' => array(), - 'update' => array( - 'access CiviCRM', - 'edit all contacts', - ), + // managed by _civicrm_api3_check_edit_permissions + 'update' => array(), 'getquick' => array( array('access CiviCRM', 'access AJAX API'), ), diff --git a/api/v3/Contact.php b/api/v3/Contact.php index c0b08bdde9..3dfe80f5a7 100644 --- a/api/v3/Contact.php +++ b/api/v3/Contact.php @@ -49,8 +49,12 @@ * API Result Array */ function civicrm_api3_contact_create($params) { - $contactID = CRM_Utils_Array::value('contact_id', $params, CRM_Utils_Array::value('id', $params)); + + if ($contactID && !empty($params['check_permissions']) && !CRM_Contact_BAO_Contact_Permission::allow($contactID, CRM_Core_Permission::EDIT)) { + throw new \Civi\API\Exception\UnauthorizedException('Permission denied to modify contact record'); + } + $dupeCheck = CRM_Utils_Array::value('dupe_check', $params, FALSE); $values = _civicrm_api3_contact_check_params($params, $dupeCheck); if ($values) { @@ -368,13 +372,17 @@ function _civicrm_api3_contact_get_supportanomalies(&$params, &$options) { * @param array $params * input parameters per getfields * + * @throws \Civi\API\Exception\UnauthorizedException * @return array * API Result Array */ function civicrm_api3_contact_delete($params) { - $contactID = CRM_Utils_Array::value('id', $params); + if (!empty($params['check_permissions']) && !CRM_Contact_BAO_Contact_Permission::allow($contactID, CRM_Core_Permission::DELETE)) { + throw new \Civi\API\Exception\UnauthorizedException('Permission denied to modify contact record'); + } + $session = CRM_Core_Session::singleton(); if ($contactID == $session->get('userID')) { return civicrm_api3_create_error('This contact record is linked to the currently logged in user account - and cannot be deleted.'); diff --git a/tests/phpunit/api/v3/ACLPermissionTest.php b/tests/phpunit/api/v3/ACLPermissionTest.php index f74de1077b..065e567a70 100644 --- a/tests/phpunit/api/v3/ACLPermissionTest.php +++ b/tests/phpunit/api/v3/ACLPermissionTest.php @@ -37,6 +37,7 @@ class api_v3_ACLPermissionTest extends CiviUnitTestCase { protected $_apiversion = 3; public $DBResetRequired = FALSE; protected $_entity; + protected $allowedContactId = 0; public function setUp() { parent::setUp(); @@ -102,7 +103,6 @@ class api_v3_ACLPermissionTest extends CiviUnitTestCase { * Function tests that a user with "edit my contact" can edit themselves. */ public function testContactEditHookWithEditMyContact() { - $this->markTestIncomplete('api acls only work with contact get so far'); $cid = $this->createLoggedInUser(); $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookNoResults')); CRM_Core_Config::singleton()->userPermissionClass->permissions = array('access CiviCRM', 'edit my contact'); @@ -112,6 +112,39 @@ class api_v3_ACLPermissionTest extends CiviUnitTestCase { )); } + /** + * Ensure contact permissions extend to related entities like email + */ + public function testRelatedEntityPermissions() { + $disallowedContact = $this->individualCreate(array(), 0); + $this->allowedContactId = $this->individualCreate(array(), 1); + $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereOnlyOne')); + CRM_Core_Config::singleton()->userPermissionClass->permissions = array('access CiviCRM'); + $testEntities = array( + 'Email' => array('email' => 'null@nothing'), + 'Phone' => array('phone' => '123456'), + 'IM' => array('name' => 'hello'), + 'Website' => array('url' => 'http://test'), + 'Address' => array('street_address' => '123 Sesame St.'), + ); + foreach ($testEntities as $entity => $params) { + $params += array( + 'contact_id' => $disallowedContact, + 'check_permissions' => 1, + ); + // We should be prevented from getting or creating entities for a contact we don't have permission for + $this->callAPIFailure($entity, 'create', $params); + $results = $this->callAPISuccess($entity, 'get', array('contact_id' => $disallowedContact, 'check_permissions' => 1)); + $this->assertEquals(0, $results['count']); + + // We should be allowed to create and get for contacts we do have permission on + $params['contact_id'] = $this->allowedContactId; + $this->callAPISuccess($entity, 'create', $params); + $results = $this->callAPISuccess($entity, 'get', array('contact_id' => $this->allowedContactId, 'check_permissions' => 1)); + $this->assertGreaterThan(0, $results['count']); + } + } + /** * Function tests all results are returned. */ @@ -367,6 +400,7 @@ class api_v3_ACLPermissionTest extends CiviUnitTestCase { /** * No results returned. + * @implements CRM_Utils_Hook::aclWhereClause * @param $type * @param $tables * @param $whereTables @@ -390,7 +424,7 @@ class api_v3_ACLPermissionTest extends CiviUnitTestCase { } /** - * Full results returned. + * All but first results returned. * @implements CRM_Utils_Hook::aclWhereClause * @param $type * @param $tables @@ -402,4 +436,17 @@ class api_v3_ACLPermissionTest extends CiviUnitTestCase { $where = " contact_a.id > 1"; } + /** + * Only specified contact returned. + * @implements CRM_Utils_Hook::aclWhereClause + * @param $type + * @param $tables + * @param $whereTables + * @param $contactID + * @param $where + */ + public function aclWhereOnlyOne($type, &$tables, &$whereTables, &$contactID, &$where) { + $where = " contact_a.id = " . $this->allowedContactId; + } + } -- 2.25.1