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( `