Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Respect ACL for multi-value custom field #15347

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion CRM/ACL/BAO/ACL.php
Expand Up @@ -852,7 +852,7 @@ public static function group(
$aclKeys = array_keys($acls);
$aclKeys = implode(',', $aclKeys);

$cacheKey = CRM_Utils_Cache::cleanKey("$tableName-$aclKeys");
$cacheKey = CRM_Utils_Cache::cleanKey("{$tableName}-{$type}-{$aclKeys}");
$cache = CRM_Utils_Cache::singleton();
$ids = $cache->get($cacheKey);
if (!$ids) {
Expand Down
8 changes: 8 additions & 0 deletions CRM/Contact/Form/CustomData.php
Expand Up @@ -125,6 +125,14 @@ public function preProcess() {
$this->_groupID = CRM_Utils_Request::retrieve('groupID', 'Positive', $this);
$this->_tableID = $this->_entityId;
$this->_contactType = CRM_Contact_BAO_Contact::getContactType($this->_tableID);

// check if the user has permission to edit the custom data for the contact.
if (!CRM_Core_BAO_CustomGroup::isCustomGroupAllowed(
$this->_groupID, $entityId, CRM_Core_Permission::EDIT
)) {
CRM_Core_Error::statusBounce(ts('You do not have the necessary permission to add/edit this contact\'s custom data.'));
}

$mode = CRM_Utils_Request::retrieve('mode', 'String', $this);
$hasReachedMax = CRM_Core_BAO_CustomGroup::hasReachedMaxLimit($this->_groupID, $this->_tableID);
if ($hasReachedMax && $mode == 'add') {
Expand Down
5 changes: 5 additions & 0 deletions CRM/Contact/Page/AJAX.php
Expand Up @@ -310,6 +310,11 @@ public static function deleteCustomValue() {
$customValueID = CRM_Utils_Type::escape($_REQUEST['valueID'], 'Positive');
$customGroupID = CRM_Utils_Type::escape($_REQUEST['groupID'], 'Positive');
$contactId = CRM_Utils_Request::retrieve('contactId', 'Positive');
if (!CRM_Core_BAO_CustomGroup::isCustomGroupAllowed(
$customGroupID, $contactId, CRM_Core_Permission::EDIT
)) {
CRM_Utils_System::permissionDenied();
}
CRM_Core_BAO_CustomValue::deleteCustomValue($customValueID, $customGroupID);
if ($contactId) {
echo CRM_Contact_BAO_Contact::getCountComponent('custom_' . $customGroupID, $contactId);
Expand Down
16 changes: 10 additions & 6 deletions CRM/Core/BAO/CustomField.php
Expand Up @@ -314,6 +314,7 @@ public function getOptions($context = NULL) {
* Return only custom data for subtype.
* @param bool $checkPermission
* If false, do not include permissioning clause.
* @param int $permissionType
*
* @return array
* an array of active custom fields.
Expand All @@ -326,7 +327,8 @@ public static function &getFields(
$customDataSubName = NULL,
$onlyParent = FALSE,
$onlySubType = FALSE,
$checkPermission = TRUE
$checkPermission = TRUE,
$permissionType = CRM_Core_Permission::VIEW
) {
if (empty($customDataType)) {
$customDataType = array('Contact', 'Individual', 'Organization', 'Household');
Expand Down Expand Up @@ -375,7 +377,7 @@ public static function &getFields(

// also get the permission stuff here
if ($checkPermission) {
$permissionClause = CRM_Core_Permission::customGroupClause(CRM_Core_Permission::VIEW,
$permissionClause = CRM_Core_Permission::customGroupClause($permissionType,
"{$cgTable}."
);
}
Expand Down Expand Up @@ -486,7 +488,7 @@ public static function &getFields(

// also get the permission stuff here
if ($checkPermission) {
$permissionClause = CRM_Core_Permission::customGroupClause(CRM_Core_Permission::VIEW,
$permissionClause = CRM_Core_Permission::customGroupClause($permissionType,
"{$cgTable}.", TRUE
);
}
Expand Down Expand Up @@ -563,8 +565,8 @@ public static function &getFields(
* When called from search and multiple records need to be returned.
* @param bool $checkPermission
* If false, do not include permissioning clause.
*
* @param bool $withMultiple
* @param int $permissionType
*
* @return array
*/
Expand All @@ -574,7 +576,8 @@ public static function getFieldsForImport(
$onlyParent = FALSE,
$search = FALSE,
$checkPermission = TRUE,
$withMultiple = FALSE
$withMultiple = FALSE,
$permissionType = CRM_Core_Permission::VIEW
) {
// Note: there are situations when we want getFieldsForImport() return fields related
// ONLY to basic contact types, but NOT subtypes. And thats where $onlyParent is helpful
Expand All @@ -585,7 +588,8 @@ public static function getFieldsForImport(
NULL,
$onlyParent,
FALSE,
$checkPermission
$checkPermission,
$permissionType
);

$importableFields = [];
Expand Down
19 changes: 19 additions & 0 deletions CRM/Core/BAO/CustomGroup.php
Expand Up @@ -2233,4 +2233,23 @@ private static function buildGroupTree($entityType, $toReturn, $subTypes, $query
return [$multipleFieldGroups, $groupTree];
}

/**
* Check if user has permission for CRUD operation on custom data.
*
* @param int $customGroupId
* @param int $contactId
* @param int $permissionType
*
* @return bool
*/
public static function isCustomGroupAllowed($customGroupId, $contactId, $permissionType) {
if (CRM_Contact_BAO_Contact_Permission::allow($contactId, CRM_Core_Permission::EDIT)
&& $customGroupId && in_array($customGroupId,
CRM_Core_Permission::customGroup($permissionType)
)) {
return TRUE;
}
return FALSE;
}

}
11 changes: 8 additions & 3 deletions CRM/Core/BAO/UFGroup.php
Expand Up @@ -736,14 +736,19 @@ public static function getLocationFields() {
}

/**
* @param $ctype
* @param string $ctype
* @param int $permissionType
*
* @return mixed
*/
protected static function getCustomFields($ctype) {
protected static function getCustomFields($ctype, $permissionType = CRM_Core_Permission::VIEW) {
static $customFieldCache = [];
if (!isset($customFieldCache[$ctype])) {
$customFields = CRM_Core_BAO_CustomField::getFieldsForImport($ctype, FALSE, FALSE, FALSE, TRUE, TRUE);
// Only Edit and View is supported in ACL for custom field.
if ($permissionType == CRM_Core_Permission::CREATE) {
$permissionType = CRM_Core_Permission::EDIT;
}
$customFields = CRM_Core_BAO_CustomField::getFieldsForImport($ctype, FALSE, FALSE, FALSE, TRUE, TRUE, $permissionType);

// hack to add custom data for components
$components = ['Contribution', 'Participant', 'Membership', 'Activity', 'Case'];
Expand Down
13 changes: 13 additions & 0 deletions CRM/Profile/Page/MultipleRecordFieldsListing.php
Expand Up @@ -260,6 +260,12 @@ public function browse() {
}

if (!empty($fieldIDs) && $this->_contactId) {
// Do not show Edit, Delete, Copy options if user don't have permission.
if (!CRM_Core_BAO_CustomGroup::isCustomGroupAllowed(
$customGroupId, $this->_contactId, CRM_Core_Permission::EDIT
)) {
$linkAction -= (CRM_Core_Action::COPY + CRM_Core_Action::UPDATE + CRM_Core_Action::DELETE);
}
$DTparams = !empty($this->_DTparams) ? $this->_DTparams : NULL;
// commonly used for both views i.e profile listing view (profileDataView) and custom data listing view (customDataView)
$result = CRM_Core_BAO_CustomValueTable::getEntityValues($this->_contactId, NULL, $fieldIDs, TRUE, $DTparams);
Expand Down Expand Up @@ -449,6 +455,13 @@ public function browse() {
}
}
}

if (CRM_Core_BAO_CustomGroup::isCustomGroupAllowed(
$customGroupId, $this->_contactId, CRM_Core_Permission::EDIT
)) {
$this->assign('showAddButton', TRUE);
}

$this->assign('dateFields', $dateFields);
$this->assign('dateFieldsVals', $dateFieldsVals);
$this->assign('cgcount', $cgcount);
Expand Down
2 changes: 1 addition & 1 deletion templates/CRM/Profile/Page/MultipleRecordFieldsListing.tpl
Expand Up @@ -114,7 +114,7 @@
<div id='{$dialogId}' class="hiddenElement"></div>
{/if}

{if !$reachedMax}
{if !$reachedMax && $showAddButton}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could this create an e-notice if the showAddButton is not assigned at all?

<div class="action-link">
{if $pageViewType eq 'customDataView'}
<br/><a accesskey="N" title="{ts 1=$customGroupTitle}Add %1 Record{/ts}" href="{crmURL p='civicrm/contact/view/cd/edit' q="reset=1&type=$ctype&groupID=$customGroupId&entityID=$contactId&cgcount=$newCgCount&multiRecordDisplay=single&mode=add"}"
Expand Down