Skip to content

Commit

Permalink
Fix Joomla4-CiviCRM ACL page
Browse files Browse the repository at this point in the history
  • Loading branch information
monishdeb committed Jan 9, 2023
1 parent 90ad294 commit 7c0a752
Showing 1 changed file with 82 additions and 50 deletions.
132 changes: 82 additions & 50 deletions libraries/joomla/form/fields/civiperms.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@

defined('JPATH_PLATFORM') or die;

// for some reason Joomla doesn't autoload JFormFieldRules in this context
require_once JPATH_SITE . '/libraries/joomla/form/fields/rules.php';
if (version_compare(JVERSION, '4.0.0', 'lt') && file_exists(JPATH_SITE . '/libraries/joomla/form/fields/rules.php')) {
require_once JPATH_SITE . '/libraries/joomla/form/fields/rules.php';
}

use Joomla\CMS\Access\Access;
use Joomla\CMS\Language\Text;

class JFormFieldCiviperms extends JFormFieldRules {

Expand Down Expand Up @@ -49,34 +53,24 @@ protected function getInput() {
// Add Javascript for permission change
JHtml::_('script', 'system/permissions.js', array('version' => 'auto', 'relative' => true));
// Load JavaScript message titles
JText::script('ERROR');
JText::script('WARNING');
JText::script('NOTICE');
JText::script('MESSAGE');
Text::script('ERROR');
Text::script('WARNING');
Text::script('NOTICE');
Text::script('MESSAGE');
// Add strings for JavaScript error translations.
JText::script('JLIB_JS_AJAX_ERROR_CONNECTION_ABORT');
JText::script('JLIB_JS_AJAX_ERROR_NO_CONTENT');
JText::script('JLIB_JS_AJAX_ERROR_OTHER');
JText::script('JLIB_JS_AJAX_ERROR_PARSE');
JText::script('JLIB_JS_AJAX_ERROR_TIMEOUT');
Text::script('JLIB_JS_AJAX_ERROR_CONNECTION_ABORT');
Text::script('JLIB_JS_AJAX_ERROR_NO_CONTENT');
Text::script('JLIB_JS_AJAX_ERROR_OTHER');
Text::script('JLIB_JS_AJAX_ERROR_PARSE');
Text::script('JLIB_JS_AJAX_ERROR_TIMEOUT');
// Initialise some field attributes.
$section = $this->section;
$assetField = $this->assetField;
$component = empty($this->component) ? 'root.1' : $this->component;
// Current view is global config?
$isGlobalConfig = $component === 'root.1';
// CRM-12059: Get the list of permissions for CiviCRM core and extensions.
$actions = self::getCiviperms($component, $section);
// Iterate over the children and add to the actions.
foreach ($this->element->children() as $el) {
if ($el->getName() == 'action') {
$actions[] = (object) array(
'name' => (string) $el['name'],
'title' => (string) $el['title'],
'description' => (string) $el['description'],
);
}
}
$actions = self::getCiviperms($component, $section, $this->element->children());
// Get the asset id.
// Note that for global configuration, com_config injects asset_id = 1 into the form.
$assetId = $this->form->getValue($assetField);
Expand Down Expand Up @@ -112,15 +106,36 @@ protected function getInput() {
}
// Full width format.
// Get the rules for just this asset (non-recursive).
$assetRules = JAccess::getAssetRules($assetId, false, false);
$assetRules = Access::getAssetRules($assetId, false, false);
// Get the available user groups.
$groups = $this->getUserGroups();

if (version_compare(JVERSION, '4.0.0', 'ge')) {
$extraData = array(
'groups',
'section',
'actions',
'assetId',
'newItem',
'assetRules',
'isGlobalConfig',
'parentAssetId',
'component',
);
foreach ($extraData as $data) {
$this->$data = $$data;
}
// Trim the trailing line in the layout file
return trim($this->getRenderer($this->layout)->render($this->getLayoutData()));
}

// Ajax request data.
$ajaxUri = JRoute::_('index.php?option=com_config&task=config.store&format=json&' . JSession::getFormToken() . '=1');

// Prepare output
$html = array();
// Description
$html[] = '<p class="rule-desc">' . JText::_('JLIB_RULES_SETTINGS_DESC') . '</p>';
$html[] = '<p class="rule-desc">' . Text::_('JLIB_RULES_SETTINGS_DESC') . '</p>';
// Begin tabs
$html[] = '<div class="tabbable tabs-left" data-ajaxuri="' . $ajaxUri . '" id="permissions-sliders">';
// Building tab nav
Expand All @@ -145,32 +160,32 @@ protected function getInput() {
$html[] = '<thead>';
$html[] = '<tr>';
$html[] = '<th class="actions" id="actions-th' . $group->value . '">';
$html[] = '<span class="acl-action">' . JText::_('JLIB_RULES_ACTION') . '</span>';
$html[] = '<span class="acl-action">' . Text::_('JLIB_RULES_ACTION') . '</span>';
$html[] = '</th>';
$html[] = '<th class="settings" id="settings-th' . $group->value . '">';
$html[] = '<span class="acl-action">' . JText::_('JLIB_RULES_SELECT_SETTING') . '</span>';
$html[] = '<span class="acl-action">' . Text::_('JLIB_RULES_SELECT_SETTING') . '</span>';
$html[] = '</th>';
$html[] = '<th id="aclactionth' . $group->value . '">';
$html[] = '<span class="acl-action">' . JText::_('JLIB_RULES_CALCULATED_SETTING') . '</span>';
$html[] = '<span class="acl-action">' . Text::_('JLIB_RULES_CALCULATED_SETTING') . '</span>';
$html[] = '</th>';
$html[] = '</tr>';
$html[] = '</thead>';
$html[] = '<tbody>';
// Check if this group has super user permissions
$isSuperUserGroup = JAccess::checkGroup($group->value, 'core.admin');
$isSuperUserGroup = Access::checkGroup($group->value, 'core.admin');
foreach ($actions as $action) {
$html[] = '<tr>';
$html[] = '<td headers="actions-th' . $group->value . '">';
$html[] = '<label for="' . $this->id . '_' . $action->name . '_' . $group->value . '" class="hasTooltip" title="'
. JHtml::_('tooltipText', $action->title, $action->description) . '">';
$html[] = JText::_($action->title);
$html[] = Text::_($action->title);
$html[] = '</label>';
$html[] = '</td>';
$html[] = '<td headers="settings-th' . $group->value . '">';
$html[] = '<select onchange="sendPermissions.call(this, event)" data-chosen="true" class="input-small novalidate"'
. ' name="' . $this->name . '[' . $action->name . '][' . $group->value . ']"'
. ' id="' . $this->id . '_' . $action->name . '_' . $group->value . '"'
. ' title="' . strip_tags(JText::sprintf('JLIB_RULES_SELECT_ALLOW_DENY_GROUP', JText::_($action->title), trim($group->text))) . '">';
. ' title="' . strip_tags(Text::sprintf('JLIB_RULES_SELECT_ALLOW_DENY_GROUP', Text::_($action->title), trim($group->text))) . '">';
/**
* Possible values:
* null = not set means inherited
Expand All @@ -182,10 +197,10 @@ protected function getInput() {
// Build the dropdowns for the permissions sliders
// The parent group has "Not Set", all children can rightly "Inherit" from that.
$html[] = '<option value=""' . ($assetRule === null ? ' selected="selected"' : '') . '>'
. JText::_(empty($group->parent_id) && $isGlobalConfig ? 'JLIB_RULES_NOT_SET' : 'JLIB_RULES_INHERITED') . '</option>';
$html[] = '<option value="1"' . ($assetRule === true ? ' selected="selected"' : '') . '>' . JText::_('JLIB_RULES_ALLOWED')
. Text::_(empty($group->parent_id) && $isGlobalConfig ? 'JLIB_RULES_NOT_SET' : 'JLIB_RULES_INHERITED') . '</option>';
$html[] = '<option value="1"' . ($assetRule === true ? ' selected="selected"' : '') . '>' . Text::_('JLIB_RULES_ALLOWED')
. '</option>';
$html[] = '<option value="0"' . ($assetRule === false ? ' selected="selected"' : '') . '>' . JText::_('JLIB_RULES_DENIED')
$html[] = '<option value="0"' . ($assetRule === false ? ' selected="selected"' : '') . '>' . Text::_('JLIB_RULES_DENIED')
. '</option>';
$html[] = '</select>&#160; ';
$html[] = '<span id="icon_' . $this->id . '_' . $action->name . '_' . $group->value . '"' . '></span>';
Expand All @@ -194,26 +209,26 @@ protected function getInput() {
$html[] = '<td headers="aclactionth' . $group->value . '">';
$result = array();
// Get the group, group parent id, and group global config recursive calculated permission for the chosen action.
$inheritedGroupRule = JAccess::checkGroup((int) $group->value, $action->name, $assetId);
$inheritedGroupParentAssetRule = !empty($parentAssetId) ? JAccess::checkGroup($group->value, $action->name, $parentAssetId) : null;
$inheritedParentGroupRule = !empty($group->parent_id) ? JAccess::checkGroup($group->parent_id, $action->name, $assetId) : null;
$inheritedGroupRule = Access::checkGroup((int) $group->value, $action->name, $assetId);
$inheritedGroupParentAssetRule = !empty($parentAssetId) ? Access::checkGroup($group->value, $action->name, $parentAssetId) : null;
$inheritedParentGroupRule = !empty($group->parent_id) ? Access::checkGroup($group->parent_id, $action->name, $assetId) : null;
// Current group is a Super User group, so calculated setting is "Allowed (Super User)".
if ($isSuperUserGroup) {
$result['class'] = 'label label-success';
$result['text'] = '<span class="icon-lock icon-white"></span>' . JText::_('JLIB_RULES_ALLOWED_ADMIN');
$result['text'] = '<span class="icon-lock icon-white"></span>' . Text::_('JLIB_RULES_ALLOWED_ADMIN');
}
// Not super user.
else {
// First get the real recursive calculated setting and add (Inherited) to it.
// If recursive calculated setting is "Denied" or null. Calculated permission is "Not Allowed (Inherited)".
if ($inheritedGroupRule === null || $inheritedGroupRule === false) {
$result['class'] = 'label label-important';
$result['text'] = JText::_('JLIB_RULES_NOT_ALLOWED_INHERITED');
$result['text'] = Text::_('JLIB_RULES_NOT_ALLOWED_INHERITED');
}
// If recursive calculated setting is "Allowed". Calculated permission is "Allowed (Inherited)".
else {
$result['class'] = 'label label-success';
$result['text'] = JText::_('JLIB_RULES_ALLOWED_INHERITED');
$result['text'] = Text::_('JLIB_RULES_ALLOWED_INHERITED');
}
// Second part: Overwrite the calculated permissions labels if there is an explicit permission in the current group.
/**
Expand All @@ -224,18 +239,18 @@ protected function getInput() {
// If there is an explicit permission "Not Allowed". Calculated permission is "Not Allowed".
if ($assetRule === false) {
$result['class'] = 'label label-important';
$result['text'] = JText::_('JLIB_RULES_NOT_ALLOWED');
$result['text'] = Text::_('JLIB_RULES_NOT_ALLOWED');
}
// If there is an explicit permission is "Allowed". Calculated permission is "Allowed".
elseif ($assetRule === true) {
$result['class'] = 'label label-success';
$result['text'] = JText::_('JLIB_RULES_ALLOWED');
$result['text'] = Text::_('JLIB_RULES_ALLOWED');
}
// Third part: Overwrite the calculated permissions labels for special cases.
// Global configuration with "Not Set" permission. Calculated permission is "Not Allowed (Default)".
if (empty($group->parent_id) && $isGlobalConfig === true && $assetRule === null) {
$result['class'] = 'label label-important';
$result['text'] = JText::_('JLIB_RULES_NOT_ALLOWED_DEFAULT');
$result['text'] = Text::_('JLIB_RULES_NOT_ALLOWED_DEFAULT');
}
/**
* Component/Item with explicit "Denied" permission at parent Asset (Category, Component or Global config) configuration.
Expand All @@ -244,7 +259,7 @@ protected function getInput() {
*/
elseif ($inheritedGroupParentAssetRule === false || $inheritedParentGroupRule === false) {
$result['class'] = 'label label-important';
$result['text'] = '<span class="icon-lock icon-white"></span>' . JText::_('JLIB_RULES_NOT_ALLOWED_LOCKED');
$result['text'] = '<span class="icon-lock icon-white"></span>' . Text::_('JLIB_RULES_NOT_ALLOWED_LOCKED');
}
}
$html[] = '<span class="' . $result['class'] . '">' . $result['text'] . '</span>';
Expand All @@ -258,26 +273,31 @@ protected function getInput() {
$html[] = '<div class="clr"></div>';
$html[] = '<div class="alert">';
if ($section === 'component' || !$section) {
$html[] = JText::_('JLIB_RULES_SETTING_NOTES');
$html[] = Text::_('JLIB_RULES_SETTING_NOTES');
}
else {
$html[] = JText::_('JLIB_RULES_SETTING_NOTES_ITEM');
$html[] = Text::_('JLIB_RULES_SETTING_NOTES_ITEM');
}
$html[] = '</div>';
return implode("\n", $html);
}

/**
* Wrapper around JAccess::getActions() to retrieve CiviCRM extension as well
* Wrapper around Access::getActionsFromFile() in Joomla 4 / Access::getActions in Joomla 3 to retrieve CiviCRM extension as well
* as core permissions.
*
* @param type $component
* @see JAccess::getActions()
* @see Access::getActions()
* @param type $section
* @see JAccess::getActions()
* @see Access::getActions()
*/
private static function getCiviperms($component, $section) {
$actions = JAccess::getActions($component, $section);
private static function getCiviperms($component, $section, $elements) {
if (version_compare(JVERSION, '4.0.0', 'ge')) {
$actions = Access::getActionsFromFile(JPATH_ADMINISTRATOR . "/components/{$component}/access.xml", "/access/section[@name='{$section}']/");
}
else {
$actions = Access::getActions($component, $section);
}

$extPerms = self::$civiConfig->userPermissionClass->getAllModulePermissions(TRUE);
foreach ($extPerms as $key => $perm) {
Expand All @@ -288,6 +308,18 @@ private static function getCiviperms($component, $section) {
'description' => $perm[1],
);
}

// Iterate over the children and add to the actions.
foreach ($elements as $el) {
if ($el->getName() == 'action') {
$actions[] = (object) array(
'name' => (string) $el['name'],
'title' => (string) $el['title'],
'description' => (string) $el['description'],
);
}
}

return $actions;
}

Expand Down

0 comments on commit 7c0a752

Please sign in to comment.