From db83e3a39c88bf51af26702c7eb93a4c467a73d4 Mon Sep 17 00:00:00 2001 From: Coleman Watts Date: Sun, 17 Jan 2016 16:12:39 -0500 Subject: [PATCH] CRM-17795 - Api.create/delete - support acls for contact related entities --- CRM/Core/DAO/permissions.php | 14 +++++++------- api/v3/Address.php | 3 +++ api/v3/Website.php | 10 +++++----- api/v3/utils.php | 29 ++++++++++++++++++++++++++++- 4 files changed, 43 insertions(+), 13 deletions(-) diff --git a/CRM/Core/DAO/permissions.php b/CRM/Core/DAO/permissions.php index dab7812857..45367c124c 100644 --- a/CRM/Core/DAO/permissions.php +++ b/CRM/Core/DAO/permissions.php @@ -106,21 +106,21 @@ function _civicrm_api3_permissions($entity, $action, &$params) { ); // Contact-related data permissions. - // CRM-14094 - Users can edit and delete contact-related objects using inline edit with 'edit all contacts' permission $permissions['address'] = array( // get is managed by BAO::addSelectWhereClause - 'get' => array(), - 'default' => array( - 'access CiviCRM', - 'edit all contacts', - ), + // create/delete are managed by _civicrm_api3_check_edit_permissions + 'default' => array(), ); $permissions['email'] = $permissions['address']; $permissions['phone'] = $permissions['address']; $permissions['website'] = $permissions['address']; $permissions['im'] = $permissions['address']; + // @todo - implement CRM_Core_BAO_EntityTag::addSelectWhereClause and remove this heavy-handed restriction - $permissions['entity_tag'] = array('get' => array('access CiviCRM', 'view all contacts')) + $permissions['address']; + $permissions['entity_tag'] = array( + 'get' => array('access CiviCRM', 'view all contacts'), + 'default' => array('access CiviCRM', 'edit all contacts'), + ); // @todo - ditto $permissions['note'] = $permissions['entity_tag']; diff --git a/api/v3/Address.php b/api/v3/Address.php index 4984da2384..452539c6a1 100644 --- a/api/v3/Address.php +++ b/api/v3/Address.php @@ -34,6 +34,8 @@ /** * Add an Address for a contact. * + * FIXME: Should be using basic_create util + * * @param array $params * Array per getfields metadata. * @@ -41,6 +43,7 @@ * API result array */ function civicrm_api3_address_create(&$params) { + _civicrm_api3_check_edit_permissions('CRM_Core_BAO_Address', $params); /** * If street_parsing, street_address has to be parsed into * separate parts diff --git a/api/v3/Website.php b/api/v3/Website.php index 50f80d020c..1eaedb214b 100644 --- a/api/v3/Website.php +++ b/api/v3/Website.php @@ -42,7 +42,7 @@ */ function civicrm_api3_website_create($params) { //DO NOT USE THIS FUNCTION AS THE BASIS FOR A NEW API http://wiki.civicrm.org/confluence/display/CRM/API+Architecture+Standards - + _civicrm_api3_check_edit_permissions('CRM_Core_BAO_Website', $params); $websiteBAO = CRM_Core_BAO_Website::add($params); $values = array(); _civicrm_api3_object_to_array($websiteBAO, $values[$websiteBAO->id]); @@ -74,10 +74,10 @@ function _civicrm_api3_website_create_spec(&$params) { */ function civicrm_api3_website_delete($params) { //DO NOT USE THIS FUNCTION AS THE BASIS FOR A NEW API http://wiki.civicrm.org/confluence/display/CRM/API+Architecture+Standards - $websiteID = CRM_Utils_Array::value('id', $params); - + civicrm_api3_verify_mandatory($params, NULL, array('id')); + _civicrm_api3_check_edit_permissions('CRM_Core_BAO_Website', array('id' => $params['id'])); $websiteDAO = new CRM_Core_DAO_Website(); - $websiteDAO->id = $websiteID; + $websiteDAO->id = $params['id']; if ($websiteDAO->find()) { while ($websiteDAO->fetch()) { $websiteDAO->delete(); @@ -85,7 +85,7 @@ function civicrm_api3_website_delete($params) { } } else { - throw new API_Exception('Could not delete Website with id ' . $websiteID); + throw new API_Exception('Could not delete Website with id ' . $params['id']); } } diff --git a/api/v3/utils.php b/api/v3/utils.php index ecae06f1bb..27b5183538 100644 --- a/api/v3/utils.php +++ b/api/v3/utils.php @@ -1353,9 +1353,11 @@ function _civicrm_api3_basic_get($bao_name, $params, $returnAsSuccess = TRUE, $e * Entity - pass in if entity is non-standard & required $ids array. * * @throws API_Exception + * @throws \Civi\API\Exception\UnauthorizedException * @return array */ function _civicrm_api3_basic_create($bao_name, &$params, $entity = NULL) { + _civicrm_api3_check_edit_permissions($bao_name, $params); _civicrm_api3_format_params_for_create($params, $entity); $args = array(&$params); if ($entity) { @@ -1445,10 +1447,11 @@ function _civicrm_api3_basic_create_fallback($bao_name, &$params) { * @return array * API result array * @throws API_Exception + * @throws \Civi\API\Exception\UnauthorizedException */ function _civicrm_api3_basic_delete($bao_name, &$params) { - civicrm_api3_verify_mandatory($params, NULL, array('id')); + _civicrm_api3_check_edit_permissions($bao_name, array('id' => $params['id'])); $args = array(&$params['id']); if (method_exists($bao_name, 'del')) { $bao = call_user_func_array(array($bao_name, 'del'), $args); @@ -2432,3 +2435,27 @@ function _civicrm_api3_basic_array_get($entity, $params, $records, $idCol, $fiel return civicrm_api3_create_success($matches, $params); } + +/** + * @param string $bao_name + * @param array $params + * @throws \Civi\API\Exception\UnauthorizedException + */ +function _civicrm_api3_check_edit_permissions($bao_name, $params) { + // For lack of something more clever, here's a whitelist of entities whos permissions + // are inherited from a contact record. + // Note, when adding here, also remember to modify _civicrm_api3_permissions() + $contactEntities = array( + 'CRM_Core_BAO_Email', + 'CRM_Core_BAO_Phone', + 'CRM_Core_BAO_Address', + 'CRM_Core_BAO_IM', + 'CRM_Core_BAO_Website', + ); + if (!empty($params['check_permissions']) && in_array($bao_name, $contactEntities)) { + $cid = !empty($params['contact_id']) ? $params['contact_id'] : CRM_Core_DAO::getFieldValue($bao_name, $params['id'], 'contact_id'); + if (!CRM_Contact_BAO_Contact_Permission::allow($cid, CRM_Core_Permission::EDIT)) { + throw new \Civi\API\Exception\UnauthorizedException('Permission denied to modify contact record'); + } + } +} -- 2.25.1