diff --git a/core/src/Revolution/Processors/Security/Access/UserGroup/AccessNamespace/GetList.php b/core/src/Revolution/Processors/Security/Access/UserGroup/AccessNamespace/GetList.php index 10ed7a3fd00..02361ce4679 100644 --- a/core/src/Revolution/Processors/Security/Access/UserGroup/AccessNamespace/GetList.php +++ b/core/src/Revolution/Processors/Security/Access/UserGroup/AccessNamespace/GetList.php @@ -42,6 +42,13 @@ class GetList extends GetListProcessor /** @var modUserGroup $userGroup */ public $userGroup; + /** @var bool $canCreate Whether user can assign a new Category ACL entry for a given User Group */ + public $canCreate = false; + /** @var bool $canEdit Whether user can change a Category ACL entry for a given User Group */ + public $canEdit = false; + /** @var bool $canRemove Whether user can remove a Category ACL entry for a given User Group */ + public $canRemove = false; + /** * @return bool */ @@ -64,6 +71,15 @@ public function initialize() if ($this->getProperty('sort') == 'role_display') { $this->setProperty('sort', 'authority'); } + /* + Currently, all actions essentially relate to editing a User Group. + Nonetheless, we maintain each separately to remain consistent with how permissions + are relayed throughout the MODX app + */ + $canChange = $this->modx->hasPermission('usergroup_edit') && $this->modx->hasPermission('usergroup_save'); + $this->canCreate = $canChange; + $this->canEdit = $canChange; + $this->canRemove = $canChange; return $initialized; } @@ -142,33 +158,31 @@ public function useSecondaryGroupCondition(string $sortBy, string $groupBy, stri */ public function prepareRow(xPDOObject $object) { - $objectArray = $object->toArray(); - if (empty($objectArray['name'])) { - $objectArray['name'] = '(' . $this->modx->lexicon('none') . ')'; + $permissions = [ + 'create' => $this->canCreate, + 'update' => $this->canEdit, + 'delete' => $this->canRemove + ]; + + $aclData = $object->toArray(); + if (empty($aclData['name'])) { + $aclData['name'] = '(' . $this->modx->lexicon('none') . ')'; } - $objectArray['authority_name'] = !empty($objectArray['role_name']) - ? $objectArray['role_name'] . ' - ' . $objectArray['authority'] - : $objectArray['authority'] + $aclData['authority_name'] = !empty($aclData['role_name']) + ? $aclData['role_name'] . ' - ' . $aclData['authority'] + : $aclData['authority'] ; /* get permissions list */ - $data = $objectArray['policy_data']; - unset($objectArray['policy_data']); + $aclData['policyPermissions'] = []; + $data = $aclData['policy_data']; + unset($aclData['policy_data']); $data = $this->modx->fromJSON($data); if (!empty($data)) { - $permissions = []; - foreach ($data as $permission => $enabled) { - if (!$enabled) { - continue; - } - $permissions[] = $permission; - } - $objectArray['permissions'] = implode(', ', $permissions); + $aclData['policyPermissions'] = array_keys($data, 1); } + $aclData['permissions'] = $permissions; - $cls = 'pedit premove'; - $objectArray['cls'] = $cls; - - return $objectArray; + return $aclData; } } diff --git a/core/src/Revolution/Processors/Security/Access/UserGroup/Category/GetList.php b/core/src/Revolution/Processors/Security/Access/UserGroup/Category/GetList.php index a65e1f1198f..ccfdf0ff795 100644 --- a/core/src/Revolution/Processors/Security/Access/UserGroup/Category/GetList.php +++ b/core/src/Revolution/Processors/Security/Access/UserGroup/Category/GetList.php @@ -43,6 +43,13 @@ class GetList extends GetListProcessor /** @var modUserGroup $userGroup */ public $userGroup; + /** @var bool $canCreate Whether user can assign a new Category ACL entry for a given User Group */ + public $canCreate = false; + /** @var bool $canEdit Whether user can change a Category ACL entry for a given User Group */ + public $canEdit = false; + /** @var bool $canRemove Whether user can remove a Category ACL entry for a given User Group */ + public $canRemove = false; + /** * @return bool */ @@ -65,6 +72,15 @@ public function initialize() if ($this->getProperty('sort') == 'role_display') { $this->setProperty('sort', 'authority'); } + /* + Currently, all actions essentially relate to editing a User Group. + Nonetheless, we maintain each separately to remain consistent with how permissions + are relayed throughout the MODX app + */ + $canChange = $this->modx->hasPermission('usergroup_edit') && $this->modx->hasPermission('usergroup_save'); + $this->canCreate = $canChange; + $this->canEdit = $canChange; + $this->canRemove = $canChange; return $initialized; } @@ -143,33 +159,35 @@ public function useSecondaryGroupCondition(string $sortBy, string $groupBy, stri */ public function prepareRow(xPDOObject $object) { - $objectArray = $object->toArray(); - if (empty($objectArray['name'])) { - $objectArray['name'] = '(' . $this->modx->lexicon('none') . ')'; + $permissions = [ + 'create' => $this->canCreate, + 'update' => $this->canEdit, + 'delete' => $this->canRemove + ]; + + $aclData = $object->toArray(); + if (empty($aclData['name'])) { + $aclData['name'] = '(' . $this->modx->lexicon('none') . ')'; } /* get permissions list */ - $data = $objectArray['policy_data']; - unset($objectArray['policy_data']); + $aclData['policyPermissions'] = []; + $data = $aclData['policy_data']; + unset($aclData['policy_data']); $data = $this->modx->fromJSON($data); if (!empty($data)) { - $permissions = []; - foreach ($data as $permission => $enabled) { - if (!$enabled) { - continue; - } - $permissions[] = $permission; - } - $objectArray['permissions'] = implode(', ', $permissions); + $aclData['policyPermissions'] = array_keys($data, 1); } - - $cls = ''; - if (($objectArray['target'] === 'web' || $objectArray['target'] === 'mgr') && $objectArray['policy_name'] === 'Administrator' && ($this->userGroup && $this->userGroup->get('name') === 'Administrator')) { - } else { - $cls .= 'pedit premove'; + if ( + in_array($aclData['target'], ['web', 'mgr']) + && $aclData['policy_name'] === 'Administrator' + && ($this->userGroup && $this->userGroup->get('name') === 'Administrator') + ) { + $permissions['edit'] = false; + $permissions['delete'] = false; } - $objectArray['cls'] = $cls; + $aclData['permissions'] = $permissions; - return $objectArray; + return $aclData; } } diff --git a/core/src/Revolution/Processors/Security/Access/UserGroup/Context/GetList.php b/core/src/Revolution/Processors/Security/Access/UserGroup/Context/GetList.php index 26ced21f3b9..ea97f0989ea 100644 --- a/core/src/Revolution/Processors/Security/Access/UserGroup/Context/GetList.php +++ b/core/src/Revolution/Processors/Security/Access/UserGroup/Context/GetList.php @@ -41,6 +41,13 @@ class GetList extends GetListProcessor /** @var modUserGroup $userGroup */ public $userGroup; + /** @var bool $canCreate Whether user can assign a new Context ACL entry for a given User Group */ + public $canCreate = false; + /** @var bool $canEdit Whether user can change a Context ACL entry for a given User Group */ + public $canEdit = false; + /** @var bool $canRemove Whether user can remove a Context ACL entry for a given User Group */ + public $canRemove = false; + /** * @return mixed */ @@ -63,6 +70,15 @@ public function initialize() if ($this->getProperty('sort') == 'role_display') { $this->setProperty('sort', 'authority'); } + /* + Currently, all actions essentially relate to editing a User Group. + Nonetheless, we maintain each separately to remain consistent with how permissions + are relayed throughout the MODX app + */ + $canChange = $this->modx->hasPermission('usergroup_edit') && $this->modx->hasPermission('usergroup_save'); + $this->canCreate = $canChange; + $this->canEdit = $canChange; + $this->canRemove = $canChange; return $initialized; } @@ -135,37 +151,35 @@ public function useSecondaryGroupCondition(string $sortBy, string $groupBy, stri */ public function prepareRow(xPDOObject $object) { - $objectArray = $object->toArray(); - if (empty($objectArray['name'])) { - $objectArray['name'] = '(' . $this->modx->lexicon('none') . ')'; + $permissions = [ + 'create' => $this->canCreate, + 'update' => $this->canEdit, + 'delete' => $this->canRemove + ]; + + $aclData = $object->toArray(); + if (empty($aclData['name'])) { + $aclData['name'] = '(' . $this->modx->lexicon('none') . ')'; } /* get permissions list */ - $data = $objectArray['policy_data']; - unset($objectArray['policy_data']); + $aclData['policyPermissions'] = []; + $data = $aclData['policy_data']; + unset($aclData['policy_data']); $data = $this->modx->fromJSON($data); if (!empty($data)) { - $permissions = []; - foreach ($data as $permission => $enabled) { - if (!$enabled) { - continue; - } - $permissions[] = $permission; - } - $objectArray['permissions'] = implode(', ', $permissions); + $aclData['policyPermissions'] = array_keys($data, 1); } - - $cls = ''; if ( - ($objectArray['target'] === 'web' || $objectArray['target'] === 'mgr') - && $objectArray['policy_name'] === 'Administrator' + in_array($aclData['target'], ['web', 'mgr']) + && $aclData['policy_name'] === 'Administrator' && ($this->userGroup && $this->userGroup->get('name') === 'Administrator') ) { - } else { - $cls .= 'pedit premove'; + $permissions['edit'] = false; + $permissions['delete'] = false; } - $objectArray['cls'] = $cls; + $aclData['permissions'] = $permissions; - return $objectArray; + return $aclData; } } diff --git a/core/src/Revolution/Processors/Security/Access/UserGroup/ResourceGroup/GetList.php b/core/src/Revolution/Processors/Security/Access/UserGroup/ResourceGroup/GetList.php index 2b951b2392a..2e49ace8927 100644 --- a/core/src/Revolution/Processors/Security/Access/UserGroup/ResourceGroup/GetList.php +++ b/core/src/Revolution/Processors/Security/Access/UserGroup/ResourceGroup/GetList.php @@ -43,6 +43,13 @@ class GetList extends GetListProcessor /** @var modUserGroup $userGroup */ public $userGroup; + /** @var bool $canCreate Whether user can assign a new Resource Group ACL entry for a given User Group */ + public $canCreate = false; + /** @var bool $canEdit Whether user can change a Resource Group ACL entry for a given User Group */ + public $canEdit = false; + /** @var bool $canRemove Whether user can remove a Resource Group ACL entry for a given User Group */ + public $canRemove = false; + /** * @return bool */ @@ -65,6 +72,16 @@ public function initialize() if ($this->getProperty('sort') == 'role_display') { $this->setProperty('sort', 'authority'); } + /* + Currently, all actions essentially relate to editing a User Group. + Nonetheless, we maintain each separately to remain consistent with how permissions + are relayed throughout the MODX app + */ + $canChange = $this->modx->hasPermission('usergroup_edit') && $this->modx->hasPermission('usergroup_save'); + $this->canCreate = $canChange; + $this->canEdit = $canChange; + $this->canRemove = $canChange; + return $initialized; } @@ -143,36 +160,35 @@ public function useSecondaryGroupCondition(string $sortBy, string $groupBy, stri */ public function prepareRow(xPDOObject $object) { - $objectArray = $object->toArray(); - if (empty($objectArray['name'])) { - $objectArray['name'] = '(' . $this->modx->lexicon('none') . ')'; + $permissions = [ + 'create' => $this->canCreate, + 'update' => $this->canEdit, + 'delete' => $this->canRemove + ]; + + $aclData = $object->toArray(); + if (empty($aclData['name'])) { + $aclData['name'] = '(' . $this->modx->lexicon('none') . ')'; } /* get permissions list */ - $data = $objectArray['policy_data']; - unset($objectArray['policy_data']); + $aclData['policyPermissions'] = []; + $data = $aclData['policy_data']; + unset($aclData['policy_data']); $data = $this->modx->fromJSON($data); if (!empty($data)) { - foreach ($data as $permission => $enabled) { - if (!$enabled) { - continue; - } - $permissions[] = $permission; - } - $objectArray['permissions'] = implode(', ', $permissions); + $aclData['policyPermissions'] = array_keys($data, 1); } - - $cls = ''; if ( - ($objectArray['target'] === 'web' || $objectArray['target'] == 'mgr') - && $objectArray['policy_name'] === 'Administrator' + in_array($aclData['target'], ['web', 'mgr']) + && $aclData['policy_name'] === 'Administrator' && ($this->userGroup && $this->userGroup->get('name') === 'Administrator') ) { - } else { - $cls .= 'pedit premove'; + $permissions['edit'] = false; + $permissions['delete'] = false; } - $objectArray['cls'] = $cls; + $aclData['permissions'] = $permissions; - return $objectArray; + return $aclData; } } diff --git a/core/src/Revolution/Processors/Security/Access/UserGroup/Source/GetList.php b/core/src/Revolution/Processors/Security/Access/UserGroup/Source/GetList.php index dc3269c4ad9..a77f844e89a 100644 --- a/core/src/Revolution/Processors/Security/Access/UserGroup/Source/GetList.php +++ b/core/src/Revolution/Processors/Security/Access/UserGroup/Source/GetList.php @@ -42,6 +42,13 @@ class GetList extends GetListProcessor /** @var modUserGroup $userGroup */ public $userGroup; + /** @var bool $canCreate Whether user can assign a new Category ACL entry for a given User Group */ + public $canCreate = false; + /** @var bool $canEdit Whether user can change a Category ACL entry for a given User Group */ + public $canEdit = false; + /** @var bool $canRemove Whether user can remove a Category ACL entry for a given User Group */ + public $canRemove = false; + /** * @return mixed */ @@ -64,6 +71,15 @@ public function initialize() if ($this->getProperty('sort') == 'role_display') { $this->setProperty('sort', 'authority'); } + /* + Currently, all actions essentially relate to editing a User Group. + Nonetheless, we maintain each separately to remain consistent with how permissions + are relayed throughout the MODX app + */ + $canChange = $this->modx->hasPermission('usergroup_edit') && $this->modx->hasPermission('usergroup_save'); + $this->canCreate = $canChange; + $this->canEdit = $canChange; + $this->canRemove = $canChange; return $initialized; } @@ -149,41 +165,39 @@ public function useSecondaryGroupCondition(string $sortBy, string $groupBy, stri */ public function prepareRow(xPDOObject $object) { - $objectArray = $object->toArray(); - if (empty($objectArray['name'])) { - $objectArray['name'] = '(' . $this->modx->lexicon('none') . ')'; + $permissions = [ + 'create' => $this->canCreate, + 'update' => $this->canEdit, + 'delete' => $this->canRemove + ]; + + $aclData = $object->toArray(); + if (empty($aclData['name'])) { + $aclData['name'] = '(' . $this->modx->lexicon('none') . ')'; } - $objectArray['authority_name'] = !empty($objectArray['role_name']) - ? $objectArray['role_name'] . ' - ' . $objectArray['authority'] - : $objectArray['authority'] + $aclData['authority_name'] = !empty($aclData['role_name']) + ? $aclData['role_name'] . ' - ' . $aclData['authority'] + : $aclData['authority'] ; /* get permissions list */ - $data = $objectArray['policy_data']; - unset($objectArray['policy_data']); + $aclData['policyPermissions'] = []; + $data = $aclData['policy_data']; + unset($aclData['policy_data']); $data = $this->modx->fromJSON($data); if (!empty($data)) { - $permissions = []; - foreach ($data as $permission => $enabled) { - if (!$enabled) { - continue; - } - $permissions[] = $permission; - } - $objectArray['permissions'] = implode(', ', $permissions); + $aclData['policyPermissions'] = array_keys($data, 1); } - - $cls = ''; if ( - ($objectArray['target'] === 'web' || $objectArray['target'] === 'mgr') - && $objectArray['policy_name'] === 'Administrator' + in_array($aclData['target'], ['web', 'mgr']) + && $aclData['policy_name'] === 'Administrator' && ($this->userGroup && $this->userGroup->get('name') === 'Administrator') ) { - } else { - $cls .= 'pedit premove'; + $permissions['edit'] = false; + $permissions['delete'] = false; } - $objectArray['cls'] = $cls; + $aclData['permissions'] = $permissions; - return $objectArray; + return $aclData; } } diff --git a/core/src/Revolution/Processors/Security/Group/User/GetList.php b/core/src/Revolution/Processors/Security/Group/User/GetList.php index 628b8cf32d6..20920c2e896 100644 --- a/core/src/Revolution/Processors/Security/Group/User/GetList.php +++ b/core/src/Revolution/Processors/Security/Group/User/GetList.php @@ -35,6 +35,11 @@ class GetList extends GetListProcessor public $permission = 'usergroup_user_list'; public $languageTopics = ['user']; + protected $canEditGroups = false; + protected $canEditGroupUsers = false; + protected $canEditRoles = false; + protected $canEditUsers = false; + /** * @return bool */ @@ -44,6 +49,10 @@ public function initialize() 'usergroup' => false, 'query' => '' ]); + $this->canEditGroups = $this->modx->hasPermission('usergroup_edit') && $this->modx->hasPermission('usergroup_save'); + $this->canEditGroupUsers = $this->modx->hasPermission('usergroup_user_edit'); + $this->canEditRoles = $this->modx->hasPermission('edit_role') && $this->modx->hasPermission('save_role'); + $this->canEditUsers = $this->modx->hasPermission('edit_user') && $this->modx->hasPermission('save_user'); return parent::initialize(); } @@ -99,9 +108,15 @@ public function prepareQueryAfterCount(xPDOQuery $c) */ public function prepareRow(xPDOObject $object) { - $objectArray = $object->toArray('', false, true); - $objectArray['role_name'] .= ' - ' . $objectArray['authority']; + $groupUserData = $object->toArray('', false, true); + $groupUserData['role_name'] .= ' - ' . $groupUserData['authority']; + $groupUserData['permissions'] = [ + 'updateGroups' => $this->canEditGroups, + 'updateGroupUsers' => $this->canEditGroupUsers, + 'updateRoles' => $this->canEditRoles, + 'updateUsers' => $this->canEditUsers + ]; - return $objectArray; + return $groupUserData; } } diff --git a/manager/assets/modext/widgets/security/modx.grid.user.group.base.js b/manager/assets/modext/widgets/security/modx.grid.user.group.base.js index 1a025ae3678..ef78bf52cb1 100644 --- a/manager/assets/modext/widgets/security/modx.grid.user.group.base.js +++ b/manager/assets/modext/widgets/security/modx.grid.user.group.base.js @@ -55,6 +55,14 @@ MODx.grid.UserGroupBase = function UserGroupBase(config = {}) { MODx.grid.UserGroupBase.superclass.constructor.call(this, config); + this.gridMenuActions = ['edit', 'delete']; + + this.setUserCanEdit(['usergroup_edit', 'usergroup_save']); + this.userCanEditAcls = this.userCanEdit; + this.setUserCanCreate(['usergroup_create', 'usergroup_save']); + this.setUserCanDelete(['usergroup_delete']); + this.setShowActionsMenu(); + this.addEvents('createAcl', 'updateAcl'); this.on({ @@ -80,7 +88,9 @@ Ext.extend(MODx.grid.UserGroupBase, MODx.grid.Grid, { tpl: new Ext.XTemplate( `
` ), @@ -90,33 +100,23 @@ Ext.extend(MODx.grid.UserGroupBase, MODx.grid.Grid, { return [this.rowExpander, ...columns]; }, getMenu: function() { - const record = this.getSelectionModel().getSelected(), - permissions = record.data.cls, - menu = [] - ; + const menu = []; if (this.getSelectionModel().getCount() > 1) { // Currently not allowing bulk actions for this grid - } else { - if (permissions.indexOf('pedit') !== -1) { - menu.push({ - text: _(`access_${this.aclType}_update`), - handler: this.updateAcl - }); - } - if (permissions.indexOf('premove') !== -1) { - if (menu.length > 0) { - menu.push('-'); - } - menu.push({ - text: _(`access_${this.aclType}_remove`), - handler: this.remove.createDelegate(this, ['confirm_remove', ACL_TYPES_CONFIG[this.aclType].actions.remove]) - }); + } else if (this.userCanEditAcls) { + menu.push({ + text: _(`access_${this.aclType}_update`), + handler: this.updateAcl + }); + if (menu.length > 0) { + menu.push('-'); } + menu.push({ + text: _(`access_${this.aclType}_remove`), + handler: this.remove.createDelegate(this, ['confirm_remove', ACL_TYPES_CONFIG[this.aclType].actions.remove]) + }); } - - if (menu.length > 0) { - this.addContextMenuItem(menu); - } + return menu; }, /** @@ -371,7 +371,7 @@ Ext.extend(MODx.window.UserGroupAclBase, MODx.Window, { */ getPermissionsList: function(window, record = {}) { const - permissions = record?.data?.permissions || window.record.permissions, + permissions = record?.json?.policyPermissions || window.record.policyPermissions, permissionsListContainer = window.fp?.getComponent(`${this.idPrefix}-permissions`), permissionsListCmp = permissionsListContainer?.getComponent(`${this.idPrefix}-permissions-list`), permissionsListLabelCmp = permissionsListContainer?.getComponent(`${this.idPrefix}-permissions-list-label`) diff --git a/manager/assets/modext/widgets/security/modx.grid.user.group.category.js b/manager/assets/modext/widgets/security/modx.grid.user.group.category.js index 189576c9d87..733263cd95d 100644 --- a/manager/assets/modext/widgets/security/modx.grid.user.group.category.js +++ b/manager/assets/modext/widgets/security/modx.grid.user.group.category.js @@ -29,8 +29,7 @@ MODx.grid.UserGroupCategory = function UserGroupCategory(config = {}) { 'policy', 'policy_name', 'context_key', - 'permissions', - 'cls' + 'policyPermissions' ], columns: this.getColumns([ { diff --git a/manager/assets/modext/widgets/security/modx.grid.user.group.context.js b/manager/assets/modext/widgets/security/modx.grid.user.group.context.js index f977aa85172..5ebd9a811bb 100644 --- a/manager/assets/modext/widgets/security/modx.grid.user.group.context.js +++ b/manager/assets/modext/widgets/security/modx.grid.user.group.context.js @@ -27,8 +27,7 @@ MODx.grid.UserGroupContext = function UserGroupContext(config = {}) { 'role_display', 'policy', 'policy_name', - 'permissions', - 'cls' + 'policyPermissions' ], sortBy: 'target', columns: this.getColumns([ diff --git a/manager/assets/modext/widgets/security/modx.grid.user.group.js b/manager/assets/modext/widgets/security/modx.grid.user.group.js index 7b4cec3ccd4..8cc52f1a18f 100644 --- a/manager/assets/modext/widgets/security/modx.grid.user.group.js +++ b/manager/assets/modext/widgets/security/modx.grid.user.group.js @@ -32,10 +32,7 @@ MODx.grid.UserGroups = function(config = {}) { 'rolename', 'primary_group', 'rank', - 'user_group_desc', - 'canEditGroups', - 'canEditGroupUsers', - 'canEditRoles' + 'user_group_desc' ], cls: 'modx-grid modx-grid-draggable', columns: [ @@ -46,7 +43,7 @@ MODx.grid.UserGroups = function(config = {}) { width: 175, renderer: { fn: function(value, metaData, record) { - return record.data.canEditGroups + return this.userCanEditGroups ? this.renderLink(value, { href: `?a=security/usergroup/update&id=${record.data.usergroup}`, target: '_blank' @@ -62,7 +59,7 @@ MODx.grid.UserGroups = function(config = {}) { width: 175, renderer: { fn: function(value, metaData, record) { - return record.data.canEditRoles + return this.userCanEditRoles ? this.renderLink(value, { href: `?a=security/permission&tab=1&role=${record.data.role}`, target: '_blank' @@ -89,8 +86,10 @@ MODx.grid.UserGroups = function(config = {}) { ] }); - this.userCanEditGroups = MODx.perm.usergroup_edit; - this.userCanEditGroupUsers = MODx.perm.usergroup_user_edit; + this.gridMenuActions = ['editGroupUsers']; + this.setUserHasPermissions('editGroups', ['usergroup_edit', 'usergroup_save']); + this.setUserHasPermissions('editGroupUsers', ['usergroup_user_edit']); + this.setUserHasPermissions('editRoles', ['edit_role', 'save_role']); if (this.userCanEditGroupUsers) { config.plugins.push( @@ -134,12 +133,7 @@ MODx.grid.UserGroups = function(config = {}) { 'afterReorderGroup' ); - /** - * Implementing alternate usage for applying grid permissions, as this grid - * displays data and assigns values from/to different object types - * (User, User Groups, Roles) - */ - this.setShowActionsMenu(['usergroup_edit', 'usergroup_user_edit']); + this.setShowActionsMenu(); }; Ext.extend(MODx.grid.UserGroups, MODx.grid.LocalGrid, { getMenu: function() { @@ -150,11 +144,7 @@ Ext.extend(MODx.grid.UserGroups, MODx.grid.LocalGrid, { handler: this.updateRole, scope: this }); - } - if (this.userCanEditGroups) { - if (menu.length > 0) { - menu.push('-'); - } + menu.push('-'); menu.push({ text: _('user_group_user_remove'), handler: this.remove.createDelegate(this, [{ diff --git a/manager/assets/modext/widgets/security/modx.grid.user.group.namespace.js b/manager/assets/modext/widgets/security/modx.grid.user.group.namespace.js index 3a796ab6b67..a36ec9673ac 100644 --- a/manager/assets/modext/widgets/security/modx.grid.user.group.namespace.js +++ b/manager/assets/modext/widgets/security/modx.grid.user.group.namespace.js @@ -29,8 +29,7 @@ MODx.grid.UserGroupNamespace = function UserGroupNamespace(config = {}) { 'policy', 'policy_name', 'context_key', - 'permissions', - 'cls' + 'policyPermissions' ], columns: this.getColumns([ { diff --git a/manager/assets/modext/widgets/security/modx.grid.user.group.resource.js b/manager/assets/modext/widgets/security/modx.grid.user.group.resource.js index 2154cb852fc..5f984528d9b 100644 --- a/manager/assets/modext/widgets/security/modx.grid.user.group.resource.js +++ b/manager/assets/modext/widgets/security/modx.grid.user.group.resource.js @@ -29,8 +29,7 @@ MODx.grid.UserGroupResourceGroup = function UserGroupResourceGroup(config = {}) 'policy', 'policy_name', 'context_key', - 'permissions', - 'cls' + 'policyPermissions' ], columns: this.getColumns([ { diff --git a/manager/assets/modext/widgets/security/modx.grid.user.group.source.js b/manager/assets/modext/widgets/security/modx.grid.user.group.source.js index 46ba574666a..f7502c2b9e9 100644 --- a/manager/assets/modext/widgets/security/modx.grid.user.group.source.js +++ b/manager/assets/modext/widgets/security/modx.grid.user.group.source.js @@ -29,8 +29,7 @@ MODx.grid.UserGroupSource = function UserGroupSource(config = {}) { 'policy', 'policy_name', 'context_key', - 'permissions', - 'cls' + 'policyPermissions' ], columns: this.getColumns([ { diff --git a/manager/assets/modext/widgets/security/modx.panel.user.group.js b/manager/assets/modext/widgets/security/modx.panel.user.group.js index 0b9ae461418..da842026514 100644 --- a/manager/assets/modext/widgets/security/modx.panel.user.group.js +++ b/manager/assets/modext/widgets/security/modx.panel.user.group.js @@ -375,10 +375,13 @@ MODx.grid.UserGroupUsers = function(config = {}) { sortable: true, renderer: { fn: function(value, metaData, record) { - return this.renderLink(value, { - href: `?a=security/user/update&id=${record.data.id}`, - target: '_blank' - }); + return this.userCanEditUsers + ? this.renderLink(value, { + href: `?a=security/user/update&id=${record.id}`, + target: '_blank' + }) + : value + ; }, scope: this } @@ -389,25 +392,33 @@ MODx.grid.UserGroupUsers = function(config = {}) { sortable: true, renderer: { fn: function(value, metaData, record) { - return this.renderLink(value, { - href: '?a=security/permission', - target: '_blank' - }); + return this.userCanEditRoles + ? this.renderLink(value, { + href: `?a=security/permission&tab=1&role=${record.json.role}`, + target: '_blank' + }) + : value + ; }, scope: this } }], tbar: [ + /* + Because visibility of these buttons is determined by non-standard + and differing create permissions, not using base method getCreateButton() + here; controlled by render listener below + */ { text: _('user_group_update'), + id: 'modx-btn-user-group-edit', cls: 'primary-button', - handler: this.updateUserGroup, - hidden: (MODx.perm.usergroup_edit === 0 || config.ownerCt.id !== 'modx-tree-panel-usergroup') + handler: this.updateUserGroup }, { text: _('user_group_user_add'), + id: 'modx-btn-user-group-add-user', cls: 'primary-button', - handler: this.addUser, - hidden: MODx.perm.usergroup_user_edit === 0 + handler: this.addUser }, '->', this.getQueryFilterField(`filter-query-users:${queryValue}`, 'user-group-users'), @@ -416,11 +427,33 @@ MODx.grid.UserGroupUsers = function(config = {}) { }); MODx.grid.UserGroupUsers.superclass.constructor.call(this, config); this.addEvents('updateRole', 'addUser'); + + this.gridMenuActions = ['editGroupUsers']; + this.setUserHasPermissions('editGroups', ['usergroup_edit', 'usergroup_save']); + this.setUserHasPermissions('editGroupUsers', ['usergroup_user_edit']); + this.setUserHasPermissions('editRoles', ['edit_role', 'save_role']); + this.setUserHasPermissions('editUsers', ['edit_user', 'save_user']); + this.setShowActionsMenu(); + + this.on({ + render: grid => { + const buttonsToHide = []; + if (!this.userCanEditGroups || grid.ownerCt.id !== 'modx-tree-panel-usergroup') { + buttonsToHide.push('modx-btn-user-group-edit'); + } + if (!this.userCanEditGroupUsers) { + buttonsToHide.push('modx-btn-user-group-add-user'); + } + if (buttonsToHide.length > 0) { + buttonsToHide.forEach(btnId => Ext.getCmp(btnId)?.hide()); + } + } + }); }; Ext.extend(MODx.grid.UserGroupUsers, MODx.grid.Grid, { getMenu: function() { const menu = []; - if (MODx.perm.usergroup_user_edit) { + if (this.userCanEditGroupUsers) { menu.push({ text: _('user_role_update'), handler: this.updateRole