From f34ad7461853120f853beff4c42f7cafd365fdea Mon Sep 17 00:00:00 2001 From: Coleman Watts Date: Fri, 24 Mar 2023 21:39:24 -0400 Subject: [PATCH] APIv4 - Enforce custom group permissions when loading metadata --- Civi/Api4/Action/Entity/Get.php | 14 ++++++++++++-- Civi/Api4/Generic/DAOGetFieldsAction.php | 2 +- Civi/Api4/Service/Spec/SpecGatherer.php | 18 ++++++++++++++---- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/Civi/Api4/Action/Entity/Get.php b/Civi/Api4/Action/Entity/Get.php index a7fa82d762..d6e80485c9 100644 --- a/Civi/Api4/Action/Entity/Get.php +++ b/Civi/Api4/Action/Entity/Get.php @@ -34,8 +34,18 @@ class Get extends \Civi\Api4\Generic\BasicGetAction { $provider = \Civi::service('action_object_provider'); return array_filter($provider->getEntities(), function($entity) { // Only include DAO entities from enabled components - $daoName = $entity['dao'] ?? NULL; - return (!$daoName || $daoName::isComponentEnabled()); + if (!empty($entity['dao']) && !$entity['dao']::isComponentEnabled()) { + return FALSE; + } + // Check custom group permissions + if ($this->checkPermissions && in_array('CustomValue', $entity['type']) && !\CRM_Core_Permission::customGroupAdmin()) { + // Hack to get the id from the "view" url. If that url changes tests should catch it and we'll think of a better way to get that id + $params = []; + parse_str(parse_url($entity['paths']['view'])['query'], $params); + $gid = $params['gid']; + return in_array($gid, \CRM_Core_Permission::customGroup()); + } + return TRUE; }); } diff --git a/Civi/Api4/Generic/DAOGetFieldsAction.php b/Civi/Api4/Generic/DAOGetFieldsAction.php index ab29f0306e..97f75e6cce 100644 --- a/Civi/Api4/Generic/DAOGetFieldsAction.php +++ b/Civi/Api4/Generic/DAOGetFieldsAction.php @@ -40,7 +40,7 @@ class DAOGetFieldsAction extends BasicGetFieldsAction { $includeCustom = strpos(implode('', $fieldsToGet), '.') !== FALSE; } $this->formatValues(); - $spec = $gatherer->getSpec($this->getEntityName(), $this->getAction(), $includeCustom, $this->values); + $spec = $gatherer->getSpec($this->getEntityName(), $this->getAction(), $includeCustom, $this->values, $this->checkPermissions); $fields = $this->specToArray($spec->getFields($fieldsToGet)); foreach ($fieldsToGet ?? [] as $fieldName) { if (empty($fields[$fieldName]) && strpos($fieldName, '.') !== FALSE) { diff --git a/Civi/Api4/Service/Spec/SpecGatherer.php b/Civi/Api4/Service/Spec/SpecGatherer.php index 9433a1b11e..b59426551a 100644 --- a/Civi/Api4/Service/Spec/SpecGatherer.php +++ b/Civi/Api4/Service/Spec/SpecGatherer.php @@ -37,20 +37,20 @@ class SpecGatherer extends AutoService { * @param string $action * @param bool $includeCustom * @param array $values + * @param bool $checkPermissions * * @return \Civi\Api4\Service\Spec\RequestSpec * @throws \CRM_Core_Exception * @see \Civi\Api4\Service\Spec\Provider\CustomFieldCreationSpecProvider - * */ - public function getSpec(string $entity, string $action, bool $includeCustom, array $values = []): RequestSpec { + public function getSpec(string $entity, string $action, bool $includeCustom, array $values = [], bool $checkPermissions = FALSE): RequestSpec { $specification = new RequestSpec($entity, $action, $values); // Real entities if (strpos($entity, 'Custom_') !== 0) { $this->addDAOFields($entity, $action, $specification, $values); if ($includeCustom) { - $this->addCustomFields($entity, $specification); + $this->addCustomFields($entity, $specification, $checkPermissions); } } // Custom pseudo-entities @@ -140,10 +140,11 @@ class SpecGatherer extends AutoService { * * @param string $entity * @param \Civi\Api4\Service\Spec\RequestSpec $spec + * @param bool $checkPermissions * @throws \CRM_Core_Exception * @see \CRM_Core_SelectValues::customGroupExtends */ - private function addCustomFields($entity, RequestSpec $spec) { + private function addCustomFields(string $entity, RequestSpec $spec, bool $checkPermissions) { $customInfo = \Civi\Api4\Utils\CoreUtil::getCustomGroupExtends($entity); if (!$customInfo) { return; @@ -158,6 +159,15 @@ class SpecGatherer extends AutoService { ->addWhere('custom_group_id.is_active', '=', TRUE) ->addWhere('custom_group_id.is_multiple', '=', FALSE); + // Enforce permissions + if ($checkPermissions && !\CRM_Core_Permission::customGroupAdmin()) { + $allowedGroups = \CRM_Core_Permission::customGroup(); + if (!$allowedGroups) { + return; + } + $query->addWhere('custom_group_id', 'IN', $allowedGroups); + } + // Contact custom groups are extra complicated because contact_type can be a value for extends if ($entity === 'Contact') { if (array_key_exists('contact_type', $values)) { -- 2.25.1