diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..6a6ebfc --- /dev/null +++ b/.gitattributes @@ -0,0 +1,12 @@ +# Path-based git attributes +# https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html + +# Ignore all test and documentation with "export-ignore". +/.gitattributes export-ignore +/.gitignore export-ignore +/.travis.yml export-ignore +/phpunit.xml.dist export-ignore +/.scrutinizer.yml export-ignore +/tests export-ignore +/framework export-ignore +/cms export-ignore \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..05eba4a --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +build +composer.lock +docs +framework +cms +vendor \ No newline at end of file diff --git a/.scrutinizer.yml b/.scrutinizer.yml new file mode 100644 index 0000000..2a97351 --- /dev/null +++ b/.scrutinizer.yml @@ -0,0 +1,33 @@ +filter: + excluded_paths: [tests/*] +checks: + php: + code_rating: true + remove_extra_empty_lines: true + remove_php_closing_tag: true + remove_trailing_whitespace: true + fix_use_statements: + remove_unused: true + preserve_multiple: false + preserve_blanklines: true + order_alphabetically: true + fix_php_opening_tag: true + fix_linefeed: true + fix_line_ending: true + fix_identation_4spaces: true + fix_doc_comments: true +tools: + external_code_coverage: false + php_analyzer: true + php_code_coverage: false + php_code_sniffer: + config: + standard: PSR2 + filter: + paths: ['src'] + php_loc: + enabled: true + excluded_dirs: [_config, assets, lang, templates, framework, cms, vendor, tests] + php_cpd: + enabled: true + excluded_dirs: [_config, assets, lang, templates, framework, cms, vendor, tests] \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100755 index 0000000..141dfaf --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,7 @@ +# Changelog + +All Notable changes to `studiobonito/silverstripe-security` will be documented in this file + +## [Unreleased] + +[Unreleased]: https://github.com/studiobonito/silverstripe-security/compare/1.0.0...HEAD \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100755 index 0000000..e1bccda --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,34 @@ +# Contributing + +Contributions are **welcome** and will be fully **credited**. + +We accept contributions via Pull Requests on [Github](https://github.com/studiobonito/silverstripe-security/tree/develop). + + +## Pull Requests + +- **Development branch** - You're pull request should be made against the `develop` branch. + +- **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](http://pear.php.net/package/PHP_CodeSniffer). + +- **Add tests!** - Your patch won't be accepted if it doesn't have tests. + +- **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date. + +- **Consider our release cycle** - We try to follow [SemVer v2.0.0](http://semver.org/). Randomly breaking public APIs is not an option. + +- **Create feature branches** - Don't ask us to pull from your master branch. + +- **One pull request per feature** - If you want to do more than one thing, send multiple pull requests. + +- **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please squash them before submitting. + + +## Running Tests + +``` bash +$ phpunit +``` + + +**Happy coding**! diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..904dd86 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,27 @@ +# Copyright (c) 2015, Studio Bonito Ltd. + +All rights reserved. + +> Redistribution and use in source and binary forms, with or without modification, are +> permitted provided that the following conditions are met: +> +> 1. Redistributions of source code must retain the above copyright notice, this list of +> conditions and the following disclaimer. +> +> 2. Redistributions in binary form must reproduce the above copyright notice, this list +> of conditions and the following disclaimer in the documentation and/or other materials +> provided with the distribution. +> +> THIS SOFTWARE IS PROVIDED BY STUDIO BONITO LTD "AS IS" AND ANY EXPRESS OR IMPLIED +> WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +> FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL STUDIO BONITO LTD OR +> CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +> CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +> SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +> ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +> NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +> ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +> +> The views and conclusions contained in the software and documentation are those of the +> authors and should not be interpreted as representing official policies, either expressed +> or implied, of Studio Bonito Ltd. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..82f5c4c --- /dev/null +++ b/README.md @@ -0,0 +1,62 @@ +# Security Module + +[![Latest Version on Packagist][ico-version]][link-packagist] +[![Software License][ico-license]](LICENSE.md) +[![Quality Score][ico-code-quality]][link-code-quality] +[![Total Downloads][ico-downloads]][link-downloads] + +## Overview + +Provide ModelAdmin replacement for SecurityAdmin in SilverStripe CMS. + +![Screenshot of Security Module](./assets/images/screenshot.png) + +## Requirements + +- SilverStripe 3.1.15 or newer. + +## Install + +### Via Composer + +``` bash +$ composer require studiobonito/silverstripe-security +``` + +### Manually + +Copy the 'silverstripe-security' folder to the root of your SilverStripe installation. + +## Usage + +The model provides a drop in replacement for the default 'Security' tab in the SilverStripe CMS. +Installing the module will replace the default 'Security' tab and replace it with this one. +This 'Security' tab is based on `ModelAdmin` and provides simple filtering which is good for managing sites with large numbers of users/groups. + +## Contributing + +Please see [CONTRIBUTING](CONTRIBUTING.md) for details. + +## Security + +If you discover any security related issues, please email support@studiobonito.co.uk instead of using the issue tracker. + +## Credits + +- [Tom Densham][link-author] +- [All Contributors][link-contributors] + +## License + +The BSD-2-Clause License. Please see [License File](LICENSE.md) for more information. + +[ico-version]: https://img.shields.io/github/release/studiobonito/silverstripe-security.svg?style=flat-square +[ico-license]: https://img.shields.io/badge/license-BSD-brightgreen.svg?style=flat-square +[ico-code-quality]: https://img.shields.io/scrutinizer/g/studiobonito/silverstripe-security.svg?style=flat-square +[ico-downloads]: https://img.shields.io/packagist/dt/studiobonito/silverstripe-security.svg?style=flat-square + +[link-packagist]: https://packagist.org/packages/studiobonito/silverstripe-security +[link-code-quality]: https://scrutinizer-ci.com/g/studiobonito/silverstripe-security +[link-downloads]: https://packagist.org/packages/studiobonito/silverstripe-security +[link-author]: https://github.com/nedmas +[link-contributors]: ../../contributors \ No newline at end of file diff --git a/_config/config.yml b/_config/config.yml new file mode 100644 index 0000000..a4e0171 --- /dev/null +++ b/_config/config.yml @@ -0,0 +1,9 @@ +--- +Name: security +--- +LeftAndMain: + extensions: + - StudioBonito\Security\Extensions\DisableSecurityAdminExtension +Group: + extensions: + - StudioBonito\Security\Extensions\GroupMembersFieldExtension \ No newline at end of file diff --git a/assets/images/screenshot.png b/assets/images/screenshot.png new file mode 100644 index 0000000..5be633d Binary files /dev/null and b/assets/images/screenshot.png differ diff --git a/composer.json b/composer.json new file mode 100755 index 0000000..8d3696e --- /dev/null +++ b/composer.json @@ -0,0 +1,39 @@ +{ + "name": "studiobonito/silverstripe-security", + "description": "Provide ModelAdmin replacement for SecurityAdmin in SilverStripe CMS.", + "type": "silverstripe-module", + "keywords": [ + "studiobonito", + "silverstripe-security", + "silverstripe", + "security", + "member" + ], + "homepage": "https://github.com/studiobonito/silverstripe-security", + "license": "BSD-2-Clause", + "authors": [ + { + "name": "Tom Densham", + "email": "tom.densham@studiobonito.co.uk", + "homepage": "http://www.studiobonito.co.uk", + "role": "Developer" + } + ], + "require": { + "php": ">=5.3.0", + "silverstripe/framework": "~3.1.15", + "silverstripe/cms": "~3.1.15" + }, + "require-dev": { + "scrutinizer/ocular": "~1.1" + }, + "suggest": { + "unclecheese/betterbuttons": "Improves the usability of ModelAdmin based interfaces.", + "silverstripe-australia/gridfieldextensions": "Allows better Member lookup when editing a Group." + }, + "autoload": { + "psr-4": { + "StudioBonito\\SilverStripe\\Security\\": "src" + } + } +} diff --git a/src/Controllers/MemberAdmin.php b/src/Controllers/MemberAdmin.php new file mode 100644 index 0000000..6571b8f --- /dev/null +++ b/src/Controllers/MemberAdmin.php @@ -0,0 +1,122 @@ + + * @copyright Studio Bonito Ltd. + */ +class MemberAdmin extends \ModelAdmin +{ + /** + * The current url segment. {@link LeftAndMain::$url_segment} + * + * @config + * @var string + */ + private static $url_segment = 'members'; + + /** + * The current menu title. {@link LeftAndMain::$menu_title} + * + * @config + * @var string + */ + private static $menu_title = 'Security'; + + /** + * The menu icon. + * + * @config + * @var string + */ + private static $menu_icon = 'framework/admin/images/menu-icons/16x16/community.png'; + + /** + * @config + * @var int + */ + private static $menu_priority = -1; + + /** + * List of all managed {@link DataObject}s in this interface. {@link ModelAdmin::$managed_models} + * + * @config + * @var array|string + */ + private static $managed_models = array( + 'Member', + 'Group', + 'PermissionRole', + ); + + /** + * List of all {@link DataObject}s which can be imported through a subclass of {@link BulkLoader} (mostly CSV data). + * + * @config + * @var array + */ + private static $model_importers = array( + 'Member' => 'MemberCsvBulkLoader', + 'Group' => 'GroupCsvBulkLoader', + ); + + /** + * Override managed model labels with CMS defaults for member, group and role. + * + * @return array + */ + public function getManagedModels() + { + $models = parent::getManagedModels(); + + if (isset($models['Member']) && isset($models['Member']['title'])) { + $models['Member']['title'] = _t('SecurityAdmin.Users', 'Users'); + } + + if (isset($models['Group']) && isset($models['Group']['title'])) { + $models['Group']['title'] = singleton('Group')->i18n_plural_name(); + } + + if (isset($models['PermissionRole']) && isset($models['PermissionRole']['title'])) { + $models['PermissionRole']['title'] = _t('SecurityAdmin.TABROLES', 'Roles'); + } + + return $models; + } + + /** + * Override gridfield configuration to provide a consistent UX. + * + * @param null $id + * @param null $fields + * + * @return \CMSForm + */ + public function getEditForm($id = null, $fields = null) + { + $form = parent::getEditForm($id, $fields); + + $gridField = $form->Fields()->dataFieldByName($this->sanitiseClassName($this->modelClass)); + $gridFieldConfig = $gridField->getConfig(); + + $gridFieldConfig->addComponent(new GridFieldButtonRow('after')); + + $gridFieldConfig->removeComponentsByType('GridFieldExportButton'); + + $exportButton = new GridFieldExportButton('buttons-after-left'); + $exportButton->setExportColumns($this->getExportFields()); + + $gridFieldConfig->addComponent($exportButton); + + $gridFieldConfig->removeComponentsByType('GridFieldPrintButton'); + + $gridFieldConfig->addComponent(new GridFieldPrintButton('buttons-after-left')); + + return $form; + } +} diff --git a/src/Extensions/DisableSecurityAdminExtension.php b/src/Extensions/DisableSecurityAdminExtension.php new file mode 100644 index 0000000..6fd4a1f --- /dev/null +++ b/src/Extensions/DisableSecurityAdminExtension.php @@ -0,0 +1,20 @@ + + * @copyright Studio Bonito Ltd. + */ +class DisableSecurityAdminExtension extends \Extension +{ + /** + * Disable SecurityAdmin menu item. + */ + public function init() + { + CMSMenu::remove_menu_item('SecurityAdmin'); + } +} diff --git a/src/Extensions/GroupMembersFieldExtension.php b/src/Extensions/GroupMembersFieldExtension.php new file mode 100644 index 0000000..6ce1d01 --- /dev/null +++ b/src/Extensions/GroupMembersFieldExtension.php @@ -0,0 +1,31 @@ + + * @copyright Studio Bonito Ltd. + */ +class GroupMembersFieldExtension extends \DataExtension +{ + /** + * Override default GridField config to use GridFieldAddExistingAutocompleter. + * + * @param FieldList $fields + */ + public function updateCMSFields(FieldList $fields) + { + if (class_exists('GridFieldAddExistingSearchButton')) { + $gridField = $fields->dataFieldByName('Members'); + if ($gridField instanceof GridField) { + $gridFieldConfig = $gridField->getConfig(); + $gridFieldConfig->removeComponentsByType('GridFieldAddExistingAutocompleter'); + $gridFieldConfig->addComponent(new GridFieldAddExistingSearchButton()); + } + } + } +}