silverstripe-framework/admin/code/SecurityAdmin.php
Damian Mooyman 59efd280ad Fix issues with CMS permission codes
Standardise template locations
Move CMSSettingsController class to SiteConfig module
Fix CMSMenu behaviour for namespaced admin sections
Split classes into one per file
Manual fixes and cleanup
2016-08-17 11:19:14 +12:00

366 lines
10 KiB
PHP
Executable File

<?php
namespace SilverStripe\Admin;
use SilverStripe\Security\Security;
use SilverStripe\Security\Member;
use SilverStripe\Security\Group;
use SilverStripe\Security\Permission;
use SilverStripe\Security\PermissionRole;
use SilverStripe\Security\PermissionProvider;
use Requirements;
use GridField;
use GridFieldConfig_RecordEditor;
use GridFieldButtonRow;
use GridFieldExportButton;
use Convert;
use FieldList;
use TabSet;
use Tab;
use LiteralField;
use HiddenField;
use HeaderField;
use Form;
use ArrayData;
use Deprecation;
use Config;
/**
* Security section of the CMS
*
* @package framework
* @subpackage admin
*/
class SecurityAdmin extends LeftAndMain implements PermissionProvider {
private static $url_segment = 'security';
private static $url_rule = '/$Action/$ID/$OtherID';
private static $menu_title = 'Security';
private static $tree_class = 'SilverStripe\\Security\\Group';
private static $subitem_class = 'SilverStripe\\Security\\Member';
private static $required_permission_codes = 'CMS_ACCESS_SecurityAdmin';
private static $allowed_actions = array(
'EditForm',
'MemberImportForm',
'memberimport',
'GroupImportForm',
'groupimport',
'groups',
'users',
'roles'
);
protected function init() {
parent::init();
Requirements::javascript(FRAMEWORK_ADMIN_DIR . '/client/dist/js/SecurityAdmin.js');
}
/**
* Shortcut action for setting the correct active tab.
*
* @param SS_HTTPRequest $request
* @return SS_HTTPResponse
*/
public function users($request) {
return $this->index($request);
}
/**
* Shortcut action for setting the correct active tab.
*
* @param SS_HTTPRequest $request
* @return SS_HTTPResponse
*/
public function groups($request) {
return $this->index($request);
}
/**
* Shortcut action for setting the correct active tab.
*
* @param SS_HTTPRequest $request
* @return SS_HTTPResponse
*/
public function roles($request) {
return $this->index($request);
}
public function getEditForm($id = null, $fields = null) {
// TODO Duplicate record fetching (see parent implementation)
if(!$id) $id = $this->currentPageID();
$form = parent::getEditForm($id);
// TODO Duplicate record fetching (see parent implementation)
$record = $this->getRecord($id);
if($record && !$record->canView()) {
return Security::permissionFailure($this);
}
$memberList = GridField::create(
'Members',
false,
Member::get(),
$memberListConfig = GridFieldConfig_RecordEditor::create()
->addComponent(new GridFieldButtonRow('after'))
->addComponent(new GridFieldExportButton('buttons-after-left'))
)->addExtraClass("members_grid");
if($record && method_exists($record, 'getValidator')) {
$validator = $record->getValidator();
} else {
$validator = Member::singleton()->getValidator();
}
$memberListConfig
->getComponentByType('GridFieldDetailForm')
->setValidator($validator);
$groupList = GridField::create(
'Groups',
false,
Group::get(),
GridFieldConfig_RecordEditor::create()
);
$columns = $groupList->getConfig()->getComponentByType('GridFieldDataColumns');
$columns->setDisplayFields(array(
'Breadcrumbs' => Group::singleton()->fieldLabel('Title')
));
$columns->setFieldFormatting(array(
'Breadcrumbs' => function($val, $item) {
return Convert::raw2xml($item->getBreadcrumbs(' > '));
}
));
$fields = new FieldList(
$root = new TabSet(
'Root',
$usersTab = new Tab('Users', _t('SecurityAdmin.Users', 'Users'),
new LiteralField('MembersCautionText',
sprintf('<div class="alert alert-warning" role="alert">%s</div>',
_t(
'SecurityAdmin.MemberListCaution',
'Caution: Removing members from this list will remove them from all groups and the database'
)
)
),
$memberList
),
$groupsTab = new Tab('Groups', singleton('SilverStripe\\Security\\Group')->i18n_plural_name(),
$groupList
)
),
// necessary for tree node selection in LeftAndMain.EditForm.js
new HiddenField('ID', false, 0)
);
// Add import capabilities. Limit to admin since the import logic can affect assigned permissions
if(Permission::check('ADMIN')) {
$fields->addFieldsToTab('Root.Users', array(
new HeaderField(_t('SecurityAdmin.IMPORTUSERS', 'Import users'), 3),
new LiteralField(
'MemberImportFormIframe',
sprintf(
'<iframe src="%s" id="MemberImportFormIframe" width="100%%" height="250px" frameBorder="0">'
. '</iframe>',
$this->Link('memberimport')
)
)
));
$fields->addFieldsToTab('Root.Groups', array(
new HeaderField(_t('SecurityAdmin.IMPORTGROUPS', 'Import groups'), 3),
new LiteralField(
'GroupImportFormIframe',
sprintf(
'<iframe src="%s" id="GroupImportFormIframe" width="100%%" height="250px" frameBorder="0">'
. '</iframe>',
$this->Link('groupimport')
)
)
));
}
// Tab nav in CMS is rendered through separate template
$root->setTemplate('CMSTabSet');
// Add roles editing interface
if(Permission::check('APPLY_ROLES')) {
$rolesField = GridField::create('Roles',
false,
PermissionRole::get(),
GridFieldConfig_RecordEditor::create()
);
$rolesTab = $fields->findOrMakeTab('Root.Roles', _t('SecurityAdmin.TABROLES', 'Roles'));
$rolesTab->push($rolesField);
}
$actionParam = $this->getRequest()->param('Action');
if($actionParam == 'groups') {
$groupsTab->addExtraClass('ui-state-active');
} elseif($actionParam == 'users') {
$usersTab->addExtraClass('ui-state-active');
} elseif($actionParam == 'roles') {
$rolesTab->addExtraClass('ui-state-active');
}
$actions = new FieldList();
$form = Form::create(
$this,
'EditForm',
$fields,
$actions
)->setHTMLID('Form_EditForm');
$form->addExtraClass('cms-edit-form');
$form->setTemplate($this->getTemplatesWithSuffix('_EditForm'));
// Tab nav in CMS is rendered through separate template
if($form->Fields()->hasTabset()) {
$form->Fields()->findOrMakeTab('Root')->setTemplate('CMSTabSet');
}
$form->addExtraClass('center ss-tabset cms-tabset ' . $this->BaseCSSClasses());
$form->setAttribute('data-pjax-fragment', 'CurrentForm');
$this->extend('updateEditForm', $form);
return $form;
}
public function memberimport() {
Requirements::clear();
Requirements::css(FRAMEWORK_ADMIN_DIR . '/client/dist/styles/bundle.css');
Requirements::javascript(THIRDPARTY_DIR . '/jquery/jquery.js');
Requirements::javascript(FRAMEWORK_DIR . '/thirdparty/jquery-entwine/dist/jquery.entwine-dist.js');
Requirements::javascript(FRAMEWORK_ADMIN_DIR . '/client/dist/js/MemberImportForm.js');
return $this->renderWith('BlankPage', array(
'Form' => $this->MemberImportForm()->forTemplate(),
'Content' => ' '
));
}
/**
* @see SecurityAdmin_MemberImportForm
*
* @return Form
*/
public function MemberImportForm() {
if(!Permission::check('ADMIN')) return false;
$group = $this->currentPage();
/** @skipUpgrade */
$form = new MemberImportForm(
$this,
'MemberImportForm'
);
$form->setGroup($group);
return $form;
}
public function groupimport() {
Requirements::clear();
Requirements::css(FRAMEWORK_ADMIN_DIR . '/client/dist/styles/bundle.css');
Requirements::javascript(THIRDPARTY_DIR . '/jquery/jquery.js');
Requirements::javascript(FRAMEWORK_DIR . '/thirdparty/jquery-entwine/dist/jquery.entwine-dist.js');
Requirements::javascript(FRAMEWORK_ADMIN_DIR . '/client/dist/js/MemberImportForm.js');
return $this->renderWith('BlankPage', array(
'Content' => ' ',
'Form' => $this->GroupImportForm()->forTemplate()
));
}
/**
* @see SecurityAdmin_MemberImportForm
*
* @return Form
*/
public function GroupImportForm() {
if(!Permission::check('ADMIN')) return false;
$form = new GroupImportForm(
$this,
'SilverStripe\\Admin\\GroupImportForm'
);
return $form;
}
/**
* Disable GridFieldDetailForm backlinks for this view, as its
*/
public function Backlink() {
return false;
}
public function Breadcrumbs($unlinked = false) {
$crumbs = parent::Breadcrumbs($unlinked);
// Name root breadcrumb based on which record is edited,
// which can only be determined by looking for the fieldname of the GridField.
// Note: Titles should be same titles as tabs in RootForm().
$params = $this->getRequest()->allParams();
if(isset($params['FieldName'])) {
// TODO FieldName param gets overwritten by nested GridFields,
// so shows "Members" rather than "Groups" for the following URL:
// admin/security/EditForm/field/Groups/item/2/ItemEditForm/field/Members/item/1/edit
$firstCrumb = $crumbs->shift();
if($params['FieldName'] == 'Groups') {
$crumbs->unshift(new ArrayData(array(
'Title' => singleton('SilverStripe\\Security\\Group')->i18n_plural_name(),
'Link' => $this->Link('groups')
)));
} elseif($params['FieldName'] == 'Users') {
$crumbs->unshift(new ArrayData(array(
'Title' => _t('SecurityAdmin.Users', 'Users'),
'Link' => $this->Link('users')
)));
} elseif($params['FieldName'] == 'Roles') {
$crumbs->unshift(new ArrayData(array(
'Title' => _t('SecurityAdmin.TABROLES', 'Roles'),
'Link' => $this->Link('roles')
)));
}
$crumbs->unshift($firstCrumb);
}
return $crumbs;
}
public function providePermissions() {
$title = $this->menu_title();
return array(
"CMS_ACCESS_SecurityAdmin" => array(
'name' => _t('CMSMain.ACCESS', "Access to '{title}' section", array('title' => $title)),
'category' => _t('Permission.CMS_ACCESS_CATEGORY', 'CMS Access'),
'help' => _t(
'SecurityAdmin.ACCESS_HELP',
'Allow viewing, adding and editing users, as well as assigning permissions and roles to them.'
)
),
'EDIT_PERMISSIONS' => array(
'name' => _t('SecurityAdmin.EDITPERMISSIONS', 'Manage permissions for groups'),
'category' => _t('Permissions.PERMISSIONS_CATEGORY', 'Roles and access permissions'),
'help' => _t('SecurityAdmin.EDITPERMISSIONS_HELP',
'Ability to edit Permissions and IP Addresses for a group.'
. ' Requires the "Access to \'Security\' section" permission.'),
'sort' => 0
),
'APPLY_ROLES' => array(
'name' => _t('SecurityAdmin.APPLY_ROLES', 'Apply roles to groups'),
'category' => _t('Permissions.PERMISSIONS_CATEGORY', 'Roles and access permissions'),
'help' => _t('SecurityAdmin.APPLY_ROLES_HELP', 'Ability to edit the roles assigned to a group.'
. ' Requires the "Access to \'Users\' section" permission.'),
'sort' => 0
)
);
}
}