2011-03-23 10:51:00 +01:00
|
|
|
<?php
|
2013-10-15 00:26:23 +02:00
|
|
|
|
2016-08-11 01:14:02 +02:00
|
|
|
namespace SilverStripe\Admin;
|
|
|
|
|
2016-09-09 08:43:05 +02:00
|
|
|
use SilverStripe\Control\HTTPRequest;
|
|
|
|
use SilverStripe\Control\HTTPResponse;
|
2016-08-19 00:51:35 +02:00
|
|
|
use SilverStripe\Core\Convert;
|
|
|
|
use SilverStripe\Forms\GridField\GridFieldDataColumns;
|
|
|
|
use SilverStripe\Forms\GridField\GridFieldDetailForm;
|
|
|
|
use SilverStripe\Forms\LiteralField;
|
|
|
|
use SilverStripe\Forms\Tab;
|
|
|
|
use SilverStripe\Forms\TabSet;
|
|
|
|
use SilverStripe\Forms\HiddenField;
|
|
|
|
use SilverStripe\Forms\FieldList;
|
|
|
|
use SilverStripe\Forms\HeaderField;
|
|
|
|
use SilverStripe\Forms\Form;
|
|
|
|
use SilverStripe\Forms\GridField\GridFieldConfig_RecordEditor;
|
|
|
|
use SilverStripe\Forms\GridField\GridFieldButtonRow;
|
|
|
|
use SilverStripe\Forms\GridField\GridFieldExportButton;
|
|
|
|
use SilverStripe\Forms\GridField\GridField;
|
2016-06-23 01:37:22 +02:00
|
|
|
use SilverStripe\Security\Security;
|
|
|
|
use SilverStripe\Security\Member;
|
|
|
|
use SilverStripe\Security\Group;
|
|
|
|
use SilverStripe\Security\Permission;
|
|
|
|
use SilverStripe\Security\PermissionRole;
|
|
|
|
use SilverStripe\Security\PermissionProvider;
|
2016-08-19 00:51:35 +02:00
|
|
|
use SilverStripe\View\Requirements;
|
|
|
|
use SilverStripe\View\ArrayData;
|
2016-06-23 01:37:22 +02:00
|
|
|
|
2011-03-23 10:51:00 +01:00
|
|
|
/**
|
|
|
|
* Security section of the CMS
|
|
|
|
*/
|
|
|
|
class SecurityAdmin extends LeftAndMain implements PermissionProvider {
|
|
|
|
|
2013-03-21 19:48:54 +01:00
|
|
|
private static $url_segment = 'security';
|
2016-01-06 00:34:58 +01:00
|
|
|
|
2013-03-21 19:48:54 +01:00
|
|
|
private static $url_rule = '/$Action/$ID/$OtherID';
|
2016-01-06 00:34:58 +01:00
|
|
|
|
2013-03-21 19:48:54 +01:00
|
|
|
private static $menu_title = 'Security';
|
2016-01-06 00:34:58 +01:00
|
|
|
|
2016-06-23 01:37:22 +02:00
|
|
|
private static $tree_class = 'SilverStripe\\Security\\Group';
|
2016-01-06 00:34:58 +01:00
|
|
|
|
2016-06-23 01:37:22 +02:00
|
|
|
private static $subitem_class = 'SilverStripe\\Security\\Member';
|
2016-01-06 00:34:58 +01:00
|
|
|
|
2016-08-11 01:40:23 +02:00
|
|
|
private static $required_permission_codes = 'CMS_ACCESS_SecurityAdmin';
|
|
|
|
|
2013-03-21 19:48:54 +01:00
|
|
|
private static $allowed_actions = array(
|
2011-03-23 10:51:00 +01:00
|
|
|
'EditForm',
|
|
|
|
'MemberImportForm',
|
|
|
|
'memberimport',
|
|
|
|
'GroupImportForm',
|
|
|
|
'groupimport',
|
2012-05-08 11:16:16 +02:00
|
|
|
'groups',
|
|
|
|
'users',
|
|
|
|
'roles'
|
2011-03-23 10:51:00 +01:00
|
|
|
);
|
|
|
|
|
2012-05-08 11:16:16 +02:00
|
|
|
/**
|
|
|
|
* Shortcut action for setting the correct active tab.
|
2016-06-23 01:37:22 +02:00
|
|
|
*
|
2016-09-09 08:43:05 +02:00
|
|
|
* @param HTTPRequest $request
|
|
|
|
* @return HTTPResponse
|
2012-05-08 11:16:16 +02:00
|
|
|
*/
|
|
|
|
public function users($request) {
|
|
|
|
return $this->index($request);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Shortcut action for setting the correct active tab.
|
2016-06-23 01:37:22 +02:00
|
|
|
*
|
2016-09-09 08:43:05 +02:00
|
|
|
* @param HTTPRequest $request
|
|
|
|
* @return HTTPResponse
|
2012-05-08 11:16:16 +02:00
|
|
|
*/
|
|
|
|
public function groups($request) {
|
|
|
|
return $this->index($request);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Shortcut action for setting the correct active tab.
|
2016-06-23 01:37:22 +02:00
|
|
|
*
|
2016-09-09 08:43:05 +02:00
|
|
|
* @param HTTPRequest $request
|
|
|
|
* @return HTTPResponse
|
2012-05-08 11:16:16 +02:00
|
|
|
*/
|
|
|
|
public function roles($request) {
|
|
|
|
return $this->index($request);
|
|
|
|
}
|
2016-01-06 00:34:58 +01:00
|
|
|
|
2012-01-23 17:12:49 +01:00
|
|
|
public function getEditForm($id = null, $fields = null) {
|
2011-03-23 10:51:00 +01:00
|
|
|
// TODO Duplicate record fetching (see parent implementation)
|
|
|
|
if(!$id) $id = $this->currentPageID();
|
|
|
|
$form = parent::getEditForm($id);
|
2016-01-06 00:34:58 +01:00
|
|
|
|
2011-03-23 10:51:00 +01:00
|
|
|
// TODO Duplicate record fetching (see parent implementation)
|
|
|
|
$record = $this->getRecord($id);
|
2013-10-15 00:26:23 +02:00
|
|
|
|
|
|
|
if($record && !$record->canView()) {
|
|
|
|
return Security::permissionFailure($this);
|
|
|
|
}
|
2016-01-06 00:34:58 +01:00
|
|
|
|
2012-04-04 16:59:30 +02:00
|
|
|
$memberList = GridField::create(
|
2012-05-28 01:43:47 +02:00
|
|
|
'Members',
|
2012-03-26 03:51:40 +02:00
|
|
|
false,
|
2012-05-28 11:13:42 +02:00
|
|
|
Member::get(),
|
2012-03-05 18:31:52 +01:00
|
|
|
$memberListConfig = GridFieldConfig_RecordEditor::create()
|
2013-06-21 15:22:00 +02:00
|
|
|
->addComponent(new GridFieldButtonRow('after'))
|
|
|
|
->addComponent(new GridFieldExportButton('buttons-after-left'))
|
2012-03-05 18:31:52 +01:00
|
|
|
)->addExtraClass("members_grid");
|
2013-10-16 00:29:43 +02:00
|
|
|
|
|
|
|
if($record && method_exists($record, 'getValidator')) {
|
|
|
|
$validator = $record->getValidator();
|
|
|
|
} else {
|
2016-06-23 01:37:22 +02:00
|
|
|
$validator = Member::singleton()->getValidator();
|
2013-10-16 00:29:43 +02:00
|
|
|
}
|
|
|
|
|
2016-08-19 00:51:35 +02:00
|
|
|
/** @var GridFieldDetailForm $detailForm */
|
|
|
|
$detailForm = $memberListConfig->getComponentByType('SilverStripe\\Forms\\GridField\\GridFieldDetailForm');
|
|
|
|
$detailForm
|
2013-10-16 00:29:43 +02:00
|
|
|
->setValidator($validator);
|
2012-03-05 18:31:52 +01:00
|
|
|
|
2012-04-19 01:25:37 +02:00
|
|
|
$groupList = GridField::create(
|
2012-05-28 01:43:47 +02:00
|
|
|
'Groups',
|
2012-03-26 03:51:40 +02:00
|
|
|
false,
|
2012-05-28 11:13:42 +02:00
|
|
|
Group::get(),
|
2012-03-05 18:31:52 +01:00
|
|
|
GridFieldConfig_RecordEditor::create()
|
2012-04-19 01:25:37 +02:00
|
|
|
);
|
2016-08-19 00:51:35 +02:00
|
|
|
/** @var GridFieldDataColumns $columns */
|
|
|
|
$columns = $groupList->getConfig()->getComponentByType('SilverStripe\\Forms\\GridField\\GridFieldDataColumns');
|
2012-04-19 01:25:37 +02:00
|
|
|
$columns->setDisplayFields(array(
|
2016-08-11 01:40:23 +02:00
|
|
|
'Breadcrumbs' => Group::singleton()->fieldLabel('Title')
|
2012-03-05 18:31:52 +01:00
|
|
|
));
|
2013-01-21 08:51:16 +01:00
|
|
|
$columns->setFieldFormatting(array(
|
|
|
|
'Breadcrumbs' => function($val, $item) {
|
2016-08-19 00:51:35 +02:00
|
|
|
/** @var Group $item */
|
2013-09-24 10:45:55 +02:00
|
|
|
return Convert::raw2xml($item->getBreadcrumbs(' > '));
|
2013-01-21 08:51:16 +01:00
|
|
|
}
|
|
|
|
));
|
2013-08-30 13:59:05 +02:00
|
|
|
|
2011-05-11 09:51:54 +02:00
|
|
|
$fields = new FieldList(
|
2011-10-29 04:41:40 +02:00
|
|
|
$root = new TabSet(
|
2011-03-23 10:51:00 +01:00
|
|
|
'Root',
|
2012-05-08 11:16:16 +02:00
|
|
|
$usersTab = new Tab('Users', _t('SecurityAdmin.Users', 'Users'),
|
2016-07-01 03:37:29 +02:00
|
|
|
|
2012-03-26 03:51:40 +02:00
|
|
|
new LiteralField('MembersCautionText',
|
2016-07-01 03:37:29 +02:00
|
|
|
sprintf('<div class="alert alert-warning" role="alert">%s</div>',
|
2011-03-23 10:51:00 +01:00
|
|
|
_t(
|
2016-01-06 00:34:58 +01:00
|
|
|
'SecurityAdmin.MemberListCaution',
|
2016-07-01 03:37:29 +02:00
|
|
|
'Caution: Removing members from this list will remove them from all groups and the database'
|
2011-03-23 10:51:00 +01:00
|
|
|
)
|
|
|
|
)
|
2016-07-01 03:37:29 +02:00
|
|
|
),
|
|
|
|
$memberList
|
2011-03-23 10:51:00 +01:00
|
|
|
),
|
2016-06-23 01:37:22 +02:00
|
|
|
$groupsTab = new Tab('Groups', singleton('SilverStripe\\Security\\Group')->i18n_plural_name(),
|
2013-08-30 13:59:05 +02:00
|
|
|
$groupList
|
2011-03-23 10:51:00 +01:00
|
|
|
)
|
|
|
|
),
|
|
|
|
// necessary for tree node selection in LeftAndMain.EditForm.js
|
|
|
|
new HiddenField('ID', false, 0)
|
|
|
|
);
|
2012-10-31 15:57:48 +01:00
|
|
|
|
2013-08-30 13:59:05 +02:00
|
|
|
// Add import capabilities. Limit to admin since the import logic can affect assigned permissions
|
|
|
|
if(Permission::check('ADMIN')) {
|
|
|
|
$fields->addFieldsToTab('Root.Users', array(
|
2016-08-23 04:32:26 +02:00
|
|
|
new HeaderField('ImportUsersHeader', _t('SecurityAdmin.IMPORTUSERS', 'Import users'), 3),
|
2013-08-30 13:59:05 +02:00
|
|
|
new LiteralField(
|
|
|
|
'MemberImportFormIframe',
|
|
|
|
sprintf(
|
|
|
|
'<iframe src="%s" id="MemberImportFormIframe" width="100%%" height="250px" frameBorder="0">'
|
|
|
|
. '</iframe>',
|
|
|
|
$this->Link('memberimport')
|
|
|
|
)
|
|
|
|
)
|
|
|
|
));
|
|
|
|
$fields->addFieldsToTab('Root.Groups', array(
|
2016-08-23 04:32:26 +02:00
|
|
|
new HeaderField('ImportGroupsHeader', _t('SecurityAdmin.IMPORTGROUPS', 'Import groups'), 3),
|
2013-08-30 13:59:05 +02:00
|
|
|
new LiteralField(
|
|
|
|
'GroupImportFormIframe',
|
|
|
|
sprintf(
|
|
|
|
'<iframe src="%s" id="GroupImportFormIframe" width="100%%" height="250px" frameBorder="0">'
|
|
|
|
. '</iframe>',
|
|
|
|
$this->Link('groupimport')
|
|
|
|
)
|
|
|
|
)
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2016-01-06 00:34:58 +01:00
|
|
|
// Tab nav in CMS is rendered through separate template
|
2016-08-19 00:51:35 +02:00
|
|
|
$root->setTemplate('SilverStripe\\Forms\\CMSTabSet');
|
2016-01-06 00:34:58 +01:00
|
|
|
|
2011-03-23 10:51:00 +01:00
|
|
|
// Add roles editing interface
|
2016-08-19 00:51:35 +02:00
|
|
|
$rolesTab = null;
|
2011-03-23 10:51:00 +01:00
|
|
|
if(Permission::check('APPLY_ROLES')) {
|
2012-05-28 01:46:25 +02:00
|
|
|
$rolesField = GridField::create('Roles',
|
2012-03-05 14:04:19 +01:00
|
|
|
false,
|
2012-05-28 11:13:42 +02:00
|
|
|
PermissionRole::get(),
|
2012-03-05 14:04:19 +01:00
|
|
|
GridFieldConfig_RecordEditor::create()
|
2011-03-23 10:51:00 +01:00
|
|
|
);
|
|
|
|
|
|
|
|
$rolesTab = $fields->findOrMakeTab('Root.Roles', _t('SecurityAdmin.TABROLES', 'Roles'));
|
2012-03-05 14:04:19 +01:00
|
|
|
$rolesTab->push($rolesField);
|
2011-03-23 10:51:00 +01:00
|
|
|
}
|
|
|
|
|
2015-04-30 01:04:08 +02:00
|
|
|
$actionParam = $this->getRequest()->param('Action');
|
2012-05-08 11:16:16 +02:00
|
|
|
if($actionParam == 'groups') {
|
2012-11-06 15:28:09 +01:00
|
|
|
$groupsTab->addExtraClass('ui-state-active');
|
2012-05-08 11:16:16 +02:00
|
|
|
} elseif($actionParam == 'users') {
|
2012-11-06 15:28:09 +01:00
|
|
|
$usersTab->addExtraClass('ui-state-active');
|
2016-08-19 00:51:35 +02:00
|
|
|
} elseif($actionParam == 'roles' && $rolesTab) {
|
2012-11-06 15:28:09 +01:00
|
|
|
$rolesTab->addExtraClass('ui-state-active');
|
2012-05-08 11:16:16 +02:00
|
|
|
}
|
|
|
|
|
2012-03-01 17:06:30 +01:00
|
|
|
$actions = new FieldList();
|
2016-01-06 00:34:58 +01:00
|
|
|
|
2016-03-01 04:15:15 +01:00
|
|
|
$form = Form::create(
|
2011-03-23 10:51:00 +01:00
|
|
|
$this,
|
|
|
|
'EditForm',
|
|
|
|
$fields,
|
|
|
|
$actions
|
2013-05-10 15:00:13 +02:00
|
|
|
)->setHTMLID('Form_EditForm');
|
2011-03-31 10:52:29 +02:00
|
|
|
$form->addExtraClass('cms-edit-form');
|
2012-03-06 00:59:19 +01:00
|
|
|
$form->setTemplate($this->getTemplatesWithSuffix('_EditForm'));
|
2012-10-31 15:57:48 +01:00
|
|
|
// Tab nav in CMS is rendered through separate template
|
2016-08-19 00:51:35 +02:00
|
|
|
if($form->Fields()->hasTabSet()) {
|
|
|
|
$form->Fields()->findOrMakeTab('Root')->setTemplate('SilverStripe\\Forms\\CMSTabSet');
|
2012-10-31 15:57:48 +01:00
|
|
|
}
|
2012-05-08 11:16:16 +02:00
|
|
|
$form->addExtraClass('center ss-tabset cms-tabset ' . $this->BaseCSSClasses());
|
2012-04-18 22:11:40 +02:00
|
|
|
$form->setAttribute('data-pjax-fragment', 'CurrentForm');
|
2012-03-08 18:20:11 +01:00
|
|
|
|
|
|
|
$this->extend('updateEditForm', $form);
|
2012-03-26 03:51:40 +02:00
|
|
|
|
2011-04-19 08:04:55 +02:00
|
|
|
return $form;
|
|
|
|
}
|
2016-01-06 00:34:58 +01:00
|
|
|
|
2011-03-23 10:51:00 +01:00
|
|
|
public function memberimport() {
|
|
|
|
Requirements::clear();
|
API Use Webpack
The bundle is generated by running “webpack” directly - gulp is no
longer needed as an intermediary. The resulting config is a lot shorter,
although more configuration is pushed into lib.js.
Modules are shared between javascript files as global variables.
Although this global state pollution is a bit messy, I don’t think it’s
practically any worse than the previous state, and it highlights the
heavy coupling between the different packages we have in place.
Reducing the width of the coupling between the core javascript and
add-on modules would probably be a better way of dealing with this than
replacing global variables with some other kind of global state.
The web pack execution seems roughly twice as fast - if I clear out my
framework/client/dist/js folder, it takes 13.3s to rebuild. However,
it’s not rebuilding other files inside dist, only the bundle files.
CSS files are now included from javascript and incorporated into
bundle.css by the webpack. Although the style-loader is helpful in some
dev workflows (it allows live reload), it introduces a flash of
unstyled content which makes it inappropriate for production.
Instead ExtractTextPlugin is used to write all the aggregated CSS
into a single bundle.css file. A style-loader-based configuration could
be introduced for dev environments, if we make use of the webpack live
reloader in the future.
Note that the following features have been removed as they don't appear to be
necessary when using Webpack:
- UMD module generation
- thirdparty dist file copying
LeftAndMain.js deps: Without it, ssui.core.js gets loaded too late,
which leads e.g. to buttons being initialised without this added behaviour.
2016-08-21 03:17:50 +02:00
|
|
|
Requirements::javascript(FRAMEWORK_ADMIN_DIR . '/client/dist/js/bundle-lib.js');
|
2016-04-19 11:04:43 +02:00
|
|
|
Requirements::javascript(FRAMEWORK_ADMIN_DIR . '/client/dist/js/MemberImportForm.js');
|
FIX Webpack handles images & fonts.
Responsibility for finding and referencing images and fonts is now
given to webpack. All the url references are now relative to the
component scss file, and point to font & images files in src/, rather
than assuming someone else will place them in dist.
This makes the source more modular, and makes it easier to, for
example, inline images are data URIs, or create a new build script that
builds several modules for a project in a single pass.
Workaround for bad font path in bundle.css:
ExtactTextPlugin didn’t work as well with a subfolder reference in the
filename. This is just a short-term fix and could probably be improved
to put bundle.css back in the styles subfolder.
Webpack handles images & fonts:
Responsibility for finding and referencing images and fonts is now
given to webpack. All the url references are now relative to the
component scss file, and point to font & images files in src/, rather
than assuming someone else will place them in dist.
This makes the source more modular, and makes it easier to, for
example, inline images are data URIs, or create a new build script that
builds several modules for a project in a single pass.
Clarify docs on spriting and webfonts:
We've decided to remove sprity since it comes with hundreds of dependencies,
and needs compilation within the "npm install" - dragging out the already overweight
install process, and making the resulting node_modules/ folder less portable between systems.
2016-08-26 05:37:43 +02:00
|
|
|
Requirements::css(FRAMEWORK_ADMIN_DIR . '/client/dist/styles/bundle.css');
|
API Use Webpack
The bundle is generated by running “webpack” directly - gulp is no
longer needed as an intermediary. The resulting config is a lot shorter,
although more configuration is pushed into lib.js.
Modules are shared between javascript files as global variables.
Although this global state pollution is a bit messy, I don’t think it’s
practically any worse than the previous state, and it highlights the
heavy coupling between the different packages we have in place.
Reducing the width of the coupling between the core javascript and
add-on modules would probably be a better way of dealing with this than
replacing global variables with some other kind of global state.
The web pack execution seems roughly twice as fast - if I clear out my
framework/client/dist/js folder, it takes 13.3s to rebuild. However,
it’s not rebuilding other files inside dist, only the bundle files.
CSS files are now included from javascript and incorporated into
bundle.css by the webpack. Although the style-loader is helpful in some
dev workflows (it allows live reload), it introduces a flash of
unstyled content which makes it inappropriate for production.
Instead ExtractTextPlugin is used to write all the aggregated CSS
into a single bundle.css file. A style-loader-based configuration could
be introduced for dev environments, if we make use of the webpack live
reloader in the future.
Note that the following features have been removed as they don't appear to be
necessary when using Webpack:
- UMD module generation
- thirdparty dist file copying
LeftAndMain.js deps: Without it, ssui.core.js gets loaded too late,
which leads e.g. to buttons being initialised without this added behaviour.
2016-08-21 03:17:50 +02:00
|
|
|
|
2011-03-23 10:51:00 +01:00
|
|
|
return $this->renderWith('BlankPage', array(
|
2012-04-13 15:35:46 +02:00
|
|
|
'Form' => $this->MemberImportForm()->forTemplate(),
|
2012-01-07 18:57:14 +01:00
|
|
|
'Content' => ' '
|
2011-03-23 10:51:00 +01:00
|
|
|
));
|
|
|
|
}
|
2016-01-06 00:34:58 +01:00
|
|
|
|
2011-03-23 10:51:00 +01:00
|
|
|
/**
|
|
|
|
* @see SecurityAdmin_MemberImportForm
|
2016-01-06 00:34:58 +01:00
|
|
|
*
|
2011-03-23 10:51:00 +01:00
|
|
|
* @return Form
|
|
|
|
*/
|
|
|
|
public function MemberImportForm() {
|
2016-08-19 00:51:35 +02:00
|
|
|
if(!Permission::check('ADMIN')) {
|
|
|
|
return null;
|
|
|
|
}
|
2013-08-30 13:59:05 +02:00
|
|
|
|
2016-08-19 00:51:35 +02:00
|
|
|
/** @var Group $group */
|
2011-03-23 10:51:00 +01:00
|
|
|
$group = $this->currentPage();
|
2016-08-11 01:40:23 +02:00
|
|
|
/** @skipUpgrade */
|
2011-03-23 10:51:00 +01:00
|
|
|
$form = new MemberImportForm(
|
|
|
|
$this,
|
2016-08-11 01:40:23 +02:00
|
|
|
'MemberImportForm'
|
2011-03-23 10:51:00 +01:00
|
|
|
);
|
|
|
|
$form->setGroup($group);
|
2016-01-06 00:34:58 +01:00
|
|
|
|
2011-03-23 10:51:00 +01:00
|
|
|
return $form;
|
|
|
|
}
|
2016-01-06 00:34:58 +01:00
|
|
|
|
2011-03-23 10:51:00 +01:00
|
|
|
public function groupimport() {
|
|
|
|
Requirements::clear();
|
API Use Webpack
The bundle is generated by running “webpack” directly - gulp is no
longer needed as an intermediary. The resulting config is a lot shorter,
although more configuration is pushed into lib.js.
Modules are shared between javascript files as global variables.
Although this global state pollution is a bit messy, I don’t think it’s
practically any worse than the previous state, and it highlights the
heavy coupling between the different packages we have in place.
Reducing the width of the coupling between the core javascript and
add-on modules would probably be a better way of dealing with this than
replacing global variables with some other kind of global state.
The web pack execution seems roughly twice as fast - if I clear out my
framework/client/dist/js folder, it takes 13.3s to rebuild. However,
it’s not rebuilding other files inside dist, only the bundle files.
CSS files are now included from javascript and incorporated into
bundle.css by the webpack. Although the style-loader is helpful in some
dev workflows (it allows live reload), it introduces a flash of
unstyled content which makes it inappropriate for production.
Instead ExtractTextPlugin is used to write all the aggregated CSS
into a single bundle.css file. A style-loader-based configuration could
be introduced for dev environments, if we make use of the webpack live
reloader in the future.
Note that the following features have been removed as they don't appear to be
necessary when using Webpack:
- UMD module generation
- thirdparty dist file copying
LeftAndMain.js deps: Without it, ssui.core.js gets loaded too late,
which leads e.g. to buttons being initialised without this added behaviour.
2016-08-21 03:17:50 +02:00
|
|
|
Requirements::javascript(FRAMEWORK_ADMIN_DIR . '/client/dist/js/bundle-lib.js');
|
2016-04-19 11:04:43 +02:00
|
|
|
Requirements::javascript(FRAMEWORK_ADMIN_DIR . '/client/dist/js/MemberImportForm.js');
|
FIX Webpack handles images & fonts.
Responsibility for finding and referencing images and fonts is now
given to webpack. All the url references are now relative to the
component scss file, and point to font & images files in src/, rather
than assuming someone else will place them in dist.
This makes the source more modular, and makes it easier to, for
example, inline images are data URIs, or create a new build script that
builds several modules for a project in a single pass.
Workaround for bad font path in bundle.css:
ExtactTextPlugin didn’t work as well with a subfolder reference in the
filename. This is just a short-term fix and could probably be improved
to put bundle.css back in the styles subfolder.
Webpack handles images & fonts:
Responsibility for finding and referencing images and fonts is now
given to webpack. All the url references are now relative to the
component scss file, and point to font & images files in src/, rather
than assuming someone else will place them in dist.
This makes the source more modular, and makes it easier to, for
example, inline images are data URIs, or create a new build script that
builds several modules for a project in a single pass.
Clarify docs on spriting and webfonts:
We've decided to remove sprity since it comes with hundreds of dependencies,
and needs compilation within the "npm install" - dragging out the already overweight
install process, and making the resulting node_modules/ folder less portable between systems.
2016-08-26 05:37:43 +02:00
|
|
|
Requirements::css(FRAMEWORK_ADMIN_DIR . '/client/dist/styles/bundle.css');
|
API Use Webpack
The bundle is generated by running “webpack” directly - gulp is no
longer needed as an intermediary. The resulting config is a lot shorter,
although more configuration is pushed into lib.js.
Modules are shared between javascript files as global variables.
Although this global state pollution is a bit messy, I don’t think it’s
practically any worse than the previous state, and it highlights the
heavy coupling between the different packages we have in place.
Reducing the width of the coupling between the core javascript and
add-on modules would probably be a better way of dealing with this than
replacing global variables with some other kind of global state.
The web pack execution seems roughly twice as fast - if I clear out my
framework/client/dist/js folder, it takes 13.3s to rebuild. However,
it’s not rebuilding other files inside dist, only the bundle files.
CSS files are now included from javascript and incorporated into
bundle.css by the webpack. Although the style-loader is helpful in some
dev workflows (it allows live reload), it introduces a flash of
unstyled content which makes it inappropriate for production.
Instead ExtractTextPlugin is used to write all the aggregated CSS
into a single bundle.css file. A style-loader-based configuration could
be introduced for dev environments, if we make use of the webpack live
reloader in the future.
Note that the following features have been removed as they don't appear to be
necessary when using Webpack:
- UMD module generation
- thirdparty dist file copying
LeftAndMain.js deps: Without it, ssui.core.js gets loaded too late,
which leads e.g. to buttons being initialised without this added behaviour.
2016-08-21 03:17:50 +02:00
|
|
|
|
2011-03-23 10:51:00 +01:00
|
|
|
return $this->renderWith('BlankPage', array(
|
2011-12-18 18:18:44 +01:00
|
|
|
'Content' => ' ',
|
2012-04-13 15:35:46 +02:00
|
|
|
'Form' => $this->GroupImportForm()->forTemplate()
|
2011-03-23 10:51:00 +01:00
|
|
|
));
|
|
|
|
}
|
2016-01-06 00:34:58 +01:00
|
|
|
|
2011-03-23 10:51:00 +01:00
|
|
|
/**
|
|
|
|
* @see SecurityAdmin_MemberImportForm
|
2016-01-06 00:34:58 +01:00
|
|
|
*
|
2016-08-19 00:51:35 +02:00
|
|
|
* @skipUpgrade
|
2011-03-23 10:51:00 +01:00
|
|
|
* @return Form
|
|
|
|
*/
|
|
|
|
public function GroupImportForm() {
|
2016-08-19 00:51:35 +02:00
|
|
|
if(!Permission::check('ADMIN')) {
|
|
|
|
return null;
|
|
|
|
}
|
2016-01-06 00:34:58 +01:00
|
|
|
|
2016-08-19 00:51:35 +02:00
|
|
|
$form = new GroupImportForm($this, 'GroupImportForm');
|
2011-03-23 10:51:00 +01:00
|
|
|
return $form;
|
|
|
|
}
|
|
|
|
|
2012-05-08 11:16:16 +02:00
|
|
|
/**
|
2016-01-06 00:34:58 +01:00
|
|
|
* Disable GridFieldDetailForm backlinks for this view, as its
|
2012-05-08 11:16:16 +02:00
|
|
|
*/
|
|
|
|
public function Backlink() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-03-05 18:31:52 +01:00
|
|
|
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().
|
2015-04-30 01:04:08 +02:00
|
|
|
$params = $this->getRequest()->allParams();
|
2012-03-05 18:31:52 +01:00
|
|
|
if(isset($params['FieldName'])) {
|
2012-05-08 11:16:16 +02:00
|
|
|
// 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();
|
2012-03-05 18:31:52 +01:00
|
|
|
if($params['FieldName'] == 'Groups') {
|
2012-05-08 11:16:16 +02:00
|
|
|
$crumbs->unshift(new ArrayData(array(
|
2016-08-19 00:51:35 +02:00
|
|
|
'Title' => Group::singleton()->i18n_plural_name(),
|
2012-05-08 11:16:16 +02:00
|
|
|
'Link' => $this->Link('groups')
|
|
|
|
)));
|
2012-03-05 18:31:52 +01:00
|
|
|
} elseif($params['FieldName'] == 'Users') {
|
2012-05-08 11:16:16 +02:00
|
|
|
$crumbs->unshift(new ArrayData(array(
|
|
|
|
'Title' => _t('SecurityAdmin.Users', 'Users'),
|
|
|
|
'Link' => $this->Link('users')
|
|
|
|
)));
|
2012-03-05 18:31:52 +01:00
|
|
|
} elseif($params['FieldName'] == 'Roles') {
|
2012-05-08 11:16:16 +02:00
|
|
|
$crumbs->unshift(new ArrayData(array(
|
|
|
|
'Title' => _t('SecurityAdmin.TABROLES', 'Roles'),
|
|
|
|
'Link' => $this->Link('roles')
|
|
|
|
)));
|
2012-03-05 18:31:52 +01:00
|
|
|
}
|
2012-05-08 11:16:16 +02:00
|
|
|
$crumbs->unshift($firstCrumb);
|
2016-01-06 00:34:58 +01:00
|
|
|
}
|
2011-03-23 10:51:00 +01:00
|
|
|
|
2012-03-05 18:31:52 +01:00
|
|
|
return $crumbs;
|
2011-03-23 10:51:00 +01:00
|
|
|
}
|
|
|
|
|
2012-09-19 12:07:39 +02:00
|
|
|
public function providePermissions() {
|
2016-05-02 10:57:43 +02:00
|
|
|
$title = $this->menu_title();
|
2011-03-23 10:51:00 +01:00
|
|
|
return array(
|
2012-03-05 16:07:20 +01:00
|
|
|
"CMS_ACCESS_SecurityAdmin" => array(
|
2012-05-01 21:44:54 +02:00
|
|
|
'name' => _t('CMSMain.ACCESS', "Access to '{title}' section", array('title' => $title)),
|
2012-03-05 16:07:20 +01:00
|
|
|
'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.'
|
|
|
|
)
|
|
|
|
),
|
2011-03-23 10:51:00 +01:00
|
|
|
'EDIT_PERMISSIONS' => array(
|
|
|
|
'name' => _t('SecurityAdmin.EDITPERMISSIONS', 'Manage permissions for groups'),
|
|
|
|
'category' => _t('Permissions.PERMISSIONS_CATEGORY', 'Roles and access permissions'),
|
2012-09-26 23:34:00 +02:00
|
|
|
'help' => _t('SecurityAdmin.EDITPERMISSIONS_HELP',
|
|
|
|
'Ability to edit Permissions and IP Addresses for a group.'
|
|
|
|
. ' Requires the "Access to \'Security\' section" permission.'),
|
2011-03-23 10:51:00 +01:00
|
|
|
'sort' => 0
|
|
|
|
),
|
|
|
|
'APPLY_ROLES' => array(
|
|
|
|
'name' => _t('SecurityAdmin.APPLY_ROLES', 'Apply roles to groups'),
|
|
|
|
'category' => _t('Permissions.PERMISSIONS_CATEGORY', 'Roles and access permissions'),
|
2012-09-26 23:34:00 +02:00
|
|
|
'help' => _t('SecurityAdmin.APPLY_ROLES_HELP', 'Ability to edit the roles assigned to a group.'
|
|
|
|
. ' Requires the "Access to \'Users\' section" permission.'),
|
2011-03-23 10:51:00 +01:00
|
|
|
'sort' => 0
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
2012-03-24 01:20:19 +01:00
|
|
|
}
|