From 01c65aabe0fe7107d52db901dbf7ddd6faf451d4 Mon Sep 17 00:00:00 2001 From: Coleman Watts Date: Thu, 6 May 2021 13:39:21 -0400 Subject: [PATCH] Implement checkAccess for custom entities --- CRM/Core/BAO/CustomValue.php | 28 ++++++++++++++++++++++++++++ Civi/Api4/Utils/CoreUtil.php | 8 ++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/CRM/Core/BAO/CustomValue.php b/CRM/Core/BAO/CustomValue.php index ebf1f75aa0..e2e3034ca0 100644 --- a/CRM/Core/BAO/CustomValue.php +++ b/CRM/Core/BAO/CustomValue.php @@ -221,4 +221,32 @@ class CRM_Core_BAO_CustomValue extends CRM_Core_DAO { return $clauses; } + /** + * Special checkAccess function for multi-record custom pseudo-entities + * + * @param string $action + * @param array $record + * @param null $userID + * @param bool $granted + * @param string $groupName + * @return bool + */ + public static function checkAccess(string $action, array $record, $userID = NULL, $granted = TRUE, $groupName = NULL): bool { + if (!$groupName) { + // $groupName is required but the function signature has to match the parent. + throw new CRM_Core_Exception('Missing required $groupName in CustomValue::checkAccess'); + } + // Currently, multi-record custom data always extends Contacts + $cid = $record['entity_id'] ?? NULL; + if (!$cid) { + $tableName = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomGroup', $groupName, 'table_name', 'name'); + $cid = CRM_Core_DAO::singleValueQuery("SELECT entity_id FROM `$tableName` WHERE id = " . (int) $record['id']); + } + $granted = CRM_Contact_BAO_Contact::checkAccess(CRM_Core_Permission::EDIT, ['id' => $cid], $userID, $granted); + + // Dispatch to hook + CRM_Utils_Hook::checkAccess("Custom_$groupName", $action, $record, $userID, $granted); + return $granted; + } + } diff --git a/Civi/Api4/Utils/CoreUtil.php b/Civi/Api4/Utils/CoreUtil.php index e62bcfe007..3f984656a1 100644 --- a/Civi/Api4/Utils/CoreUtil.php +++ b/Civi/Api4/Utils/CoreUtil.php @@ -175,9 +175,13 @@ class CoreUtil { $granted = $granted && $action->addSelect('id')->addWhere('id', '=', $record['id'])->execute()->count(); } else { - $baoName = self::getBAOFromApiName($entityName); // If entity has a BAO, run the BAO::checkAccess function, which will call the hook - if ($baoName && strpos($baoName, '_BAO_')) { + $baoName = self::getBAOFromApiName($entityName); + // CustomValue also requires the name of the group + if ($baoName === 'CRM_Core_BAO_CustomValue') { + $granted = \CRM_Core_BAO_CustomValue::checkAccess($actionName, $record, NULL, $granted, substr($entityName, 7)); + } + elseif ($baoName) { $granted = $baoName::checkAccess($actionName, $record, NULL, $granted); } // Otherwise, call the hook directly -- 2.25.1