Merge pull request #63 from silverstripe-security/pulls/3.6/ss-2018-001

[ss-2018-001] Restrict non-admins from being assigned to admin groups
This commit is contained in:
Robbie Averill 2018-05-10 09:25:19 +12:00 committed by GitHub
commit 65668b8b58
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 57 additions and 12 deletions

View File

@ -1042,15 +1042,24 @@ class Member extends DataObject implements TemplateGlobalProvider {
* @return boolean True if the change can be accepted
*/
public function onChangeGroups($ids) {
// Ensure none of these match disallowed list
$disallowedGroupIDs = $this->disallowedGroups();
return count(array_intersect($ids, $disallowedGroupIDs)) == 0;
}
/**
* List of group IDs this user is disallowed from
*
* @return int[] List of group IDs
*/
protected function disallowedGroups() {
// unless the current user is an admin already OR the logged in user is an admin
if(Permission::check('ADMIN') || Permission::checkMember($this, 'ADMIN')) {
return true;
if (Permission::check('ADMIN') || Permission::checkMember($this, 'ADMIN')) {
return array();
}
// If there are no admin groups in this set then it's ok
$adminGroups = Permission::get_groups_by_permission('ADMIN');
$adminGroupIDs = ($adminGroups) ? $adminGroups->column('ID') : array();
return count(array_intersect($ids, $adminGroupIDs)) == 0;
// Non-admins may not belong to admin groups
return Permission::get_groups_by_permission('ADMIN')->column('ID');
}
@ -1465,12 +1474,18 @@ class Member extends DataObject implements TemplateGlobalProvider {
$fields->removeByName('LoggedPasswords');
if(Permission::check('EDIT_PERMISSIONS')) {
$groupsMap = array();
foreach(Group::get() as $group) {
// Listboxfield values are escaped, use ASCII char instead of »
$groupsMap[$group->ID] = $group->getBreadcrumbs(' > ');
}
asort($groupsMap);
// Filter allowed groups
$groups = Group::get();
$disallowedGroupIDs = $this->disallowedGroups();
if ($disallowedGroupIDs) {
$groups = $groups->exclude('ID', $disallowedGroupIDs);
}
$groupsMap = array();
foreach ($groups as $group) {
// Listboxfield values are escaped, use ASCII char instead of »
$groupsMap[$group->ID] = $group->getBreadcrumbs(' > ');
}
asort($groupsMap);
$fields->addFieldToTab('Root.Main',
ListboxField::create('DirectGroups', singleton('Group')->i18n_plural_name())
->setMultiple(true)

View File

@ -665,6 +665,36 @@ class MemberTest extends FunctionalTest {
);
}
/**
* Ensure DirectGroups listbox disallows admin-promotion
*/
public function testAllowedGroupsListbox() {
/** @var Group $adminGroup */
$adminGroup = $this->objFromFixture('Group', 'admingroup');
/** @var Member $staffMember */
$staffMember = $this->objFromFixture('Member', 'staffmember');
/** @var Member $adminMember */
$adminMember = $this->objFromFixture('Member', 'admin');
// Ensure you can see the DirectGroups box
$this->logInWithPermission('EDIT_PERMISSIONS');
// Non-admin member field contains non-admin groups
/** @var ListboxField $staffListbox */
$staffListbox = $staffMember->getCMSFields()->dataFieldByName('DirectGroups');
$this->assertArrayNotHasKey($adminGroup->ID, $staffListbox->getSource());
// admin member field contains admin group
/** @var ListboxField $adminListbox */
$adminListbox = $adminMember->getCMSFields()->dataFieldByName('DirectGroups');
$this->assertArrayHasKey($adminGroup->ID, $adminListbox->getSource());
// If logged in as admin, staff listbox has admin group
$this->logInWithPermission('ADMIN');
$staffListbox = $staffMember->getCMSFields()->dataFieldByName('DirectGroups');
$this->assertArrayHasKey($adminGroup->ID, $staffListbox->getSource());
}
/**
* Test Member_GroupSet::add
*/