diff --git a/api/v3/Contribution.php b/api/v3/Contribution.php index 459b6849822f4592dbc67cd99fb4012a04d31264..3a72fd9f650cfb3469955f25e1d6762ece961cd6 100644 --- a/api/v3/Contribution.php +++ b/api/v3/Contribution.php @@ -15,6 +15,8 @@ * @package CiviCRM_APIv3 */ +use Civi\Api4\Contribution; + /** * Add or update a Contribution. * @@ -40,18 +42,14 @@ function civicrm_api3_contribution_create($params) { } $params['skipCleanMoney'] = TRUE; - if (!empty($params['check_permissions']) && CRM_Financial_BAO_FinancialType::isACLFinancialTypeStatus()) { - if (empty($params['id'])) { - $op = CRM_Core_Action::ADD; - } - else { - if (empty($params['financial_type_id'])) { - $params['financial_type_id'] = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_Contribution', $params['id'], 'financial_type_id'); - } - $op = CRM_Core_Action::UPDATE; - } - CRM_Financial_BAO_FinancialType::getAvailableFinancialTypes($types, $op); - if (!array_key_exists($params['financial_type_id'], $types)) { + if (!empty($params['check_permissions'])) { + // Check acls on this entity. Note that we pass in financial type id, if we have it + // since we know this is checked by acls. In v4 we do something more generic. + if (!Contribution::checkAccess() + ->setAction(empty($params['id']) ? 'create' : 'update') + ->addValue('id', $params['id'] ?? NULL) + ->addValue('financial_type_id', $params['financial_type_id'] ?? NULL) + ->execute()->first()['access']) { throw new API_Exception('You do not have permission to create this contribution'); } } diff --git a/ext/financialacls/financialacls.php b/ext/financialacls/financialacls.php index abad6279ec09b540b0b0806be045e6a9cb481c7d..a0d94540682fc6cc8be4eb0cfaefe70f3ca332d7 100644 --- a/ext/financialacls/financialacls.php +++ b/ext/financialacls/financialacls.php @@ -305,19 +305,41 @@ function _financialacls_civi_api4_authorizeContribution(\Civi\Api4\Event\Authori if (!financialacls_is_acl_limiting_enabled()) { return; } - if ($e->getActionName() === 'delete' && $e->getEntityName() === 'Contribution') { - $contributionID = $e->getRecord()['id']; - // First check contribution financial type - $financialType = CRM_Core_PseudoConstant::getName('CRM_Contribute_DAO_Contribution', 'financial_type_id', CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_Contribution', $contributionID, 'financial_type_id')); - // Now check permissioned line items & permissioned contribution - if (!CRM_Core_Permission::check('delete contributions of type ' . $financialType, $e->getUserID()) || - !CRM_Financial_BAO_FinancialType::checkPermissionedLineItems($contributionID, 'delete', FALSE, $e->getUserID()) - ) { + if ($e->getEntityName() === 'Contribution') { + $contributionID = $e->getRecord()['id'] ?? NULL; + $financialTypeID = $e->getRecord()['financial_type_id'] ?? CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_Contribution', $contributionID, 'financial_type_id'); + if (!CRM_Core_Permission::check(_financialacls_getRequiredPermission($financialTypeID, $e->getActionName()), $e->getUserID())) { $e->setAuthorized(FALSE); } + if ($e->getActionName() === 'delete') { + // First check contribution financial type + // Now check permissioned line items & permissioned contribution + if (!CRM_Financial_BAO_FinancialType::checkPermissionedLineItems($contributionID, 'delete', FALSE, $e->getUserID()) + ) { + $e->setAuthorized(FALSE); + } + } } } +/** + * Get the permission required to perform this action on this financial type. + * + * @param int $financialTypeID + * @param string $action + * + * @return string + */ +function _financialacls_getRequiredPermission(int $financialTypeID, string $action): string { + $financialType = CRM_Core_PseudoConstant::getName('CRM_Contribute_DAO_Contribution', 'financial_type_id', $financialTypeID); + $actionMap = [ + 'create' => 'add', + 'update' => 'edit', + 'delete' => 'delete', + ]; + return $actionMap[$action] . ' contributions of type ' . $financialType; +} + /** * Remove unpermitted financial types from field Options in search context. *