From 511e82369b17562ca2956796d0ee964a5942d502 Mon Sep 17 00:00:00 2001 From: Christian Kuhn <lolli@schwarzbu.ch> Date: Wed, 6 Sep 2017 19:22:33 +0200 Subject: [PATCH] [TASK] Install tool: System maintainer administration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a card to the "Settings" menu to allow configuration of "System Maintainers" in the install tool writing SYS/systemMaintainers array to LocalConfiguration. Change-Id: I0219b60e9a261373befab7b846e55b61ea215e5e Resolves: #82319 Releases: master Reviewed-on: https://review.typo3.org/53931 Tested-by: TYPO3com <no-reply@typo3.com> Reviewed-by: Matthias Vogel <typo3@kanti.de> Tested-by: Matthias Vogel <typo3@kanti.de> Reviewed-by: Åukasz UznaÅ„ski <l.uznanski@macopedia.pl> Tested-by: Åukasz UznaÅ„ski <l.uznanski@macopedia.pl> Reviewed-by: Andreas Fernandez <typo3@scripting-base.de> Tested-by: Andreas Fernandez <typo3@scripting-base.de> --- .../Action/Ajax/SystemMaintainerGetList.php | 67 +++++++++ .../Action/Ajax/SystemMaintainerWrite.php | 87 +++++++++++ .../Controller/Action/Tool/Settings.php | 4 + .../Classes/Controller/AjaxController.php | 4 + .../Tool/Settings/SystemMaintainer.html | 43 ++++++ .../Templates/Action/Tool/Settings.html | 11 +- .../JavaScript/Modules/SystemMaintainer.js | 141 ++++++++++++++++++ 7 files changed, 355 insertions(+), 2 deletions(-) create mode 100644 typo3/sysext/install/Classes/Controller/Action/Ajax/SystemMaintainerGetList.php create mode 100644 typo3/sysext/install/Classes/Controller/Action/Ajax/SystemMaintainerWrite.php create mode 100644 typo3/sysext/install/Resources/Private/Partials/Action/Tool/Settings/SystemMaintainer.html create mode 100644 typo3/sysext/install/Resources/Public/JavaScript/Modules/SystemMaintainer.js diff --git a/typo3/sysext/install/Classes/Controller/Action/Ajax/SystemMaintainerGetList.php b/typo3/sysext/install/Classes/Controller/Action/Ajax/SystemMaintainerGetList.php new file mode 100644 index 000000000000..5caebd9ad97e --- /dev/null +++ b/typo3/sysext/install/Classes/Controller/Action/Ajax/SystemMaintainerGetList.php @@ -0,0 +1,67 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Install\Controller\Action\Ajax; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Database\ConnectionPool; +use TYPO3\CMS\Core\Utility\GeneralUtility; + +/** + * Get list of backend admin users with information if they are system maintainers + */ +class SystemMaintainerGetList extends AbstractAjaxAction +{ + /** + * Get backend admin user list + * + * @return array + */ + protected function executeAction(): array + { + $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class); + + // We have to respect the enable fields here by our own because no TCA is loaded in standalone mode + $queryBuilder = $connectionPool->getQueryBuilderForTable('be_users'); + $queryBuilder->getRestrictions()->removeAll(); + + $users = $queryBuilder + ->select('uid', 'username', 'disable', 'starttime', 'endtime') + ->from('be_users') + ->where( + $queryBuilder->expr()->andX( + $queryBuilder->expr()->eq('deleted', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)), + $queryBuilder->expr()->eq('admin', $queryBuilder->createNamedParameter(1, \PDO::PARAM_INT)) + ) + ) + ->orderBy('uid') + ->execute() + ->fetchAll(); + + $systemMaintainerList = $GLOBALS['TYPO3_CONF_VARS']['SYS']['systemMaintainers'] ?? []; + $currentTime = time(); + foreach ($users as &$user) { + $user['disable'] = $user['disable'] || + ((int)$user['starttime'] !== 0 && $user['starttime'] > $currentTime) || + ((int)$user['endtime'] !== 0 && $user['endtime'] < $currentTime); + $user['isSystemMaintainer'] = in_array((int)$user['uid'], $systemMaintainerList, true); + } + $this->view->assignMultiple([ + 'success' => true, + 'status' => [], + 'users' => $users, + ]); + return $this->view->render(); + } +} diff --git a/typo3/sysext/install/Classes/Controller/Action/Ajax/SystemMaintainerWrite.php b/typo3/sysext/install/Classes/Controller/Action/Ajax/SystemMaintainerWrite.php new file mode 100644 index 000000000000..ecded37708ec --- /dev/null +++ b/typo3/sysext/install/Classes/Controller/Action/Ajax/SystemMaintainerWrite.php @@ -0,0 +1,87 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Install\Controller\Action\Ajax; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Configuration\ConfigurationManager; +use TYPO3\CMS\Core\Database\Connection; +use TYPO3\CMS\Core\Database\ConnectionPool; +use TYPO3\CMS\Core\Messaging\FlashMessage; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Core\Utility\MathUtility; + +/** + * Write out system maintainer list to LocalConfiguration + */ +class SystemMaintainerWrite extends AbstractAjaxAction +{ + /** + * Write system maintainer list + * + * @return array + */ + protected function executeAction(): array + { + // Sanitize given user list and write out + $newUserList = []; + if (isset($this->postValues['users']) && is_array($this->postValues['users'])) { + foreach ($this->postValues['users'] as $uid) { + if (MathUtility::canBeInterpretedAsInteger($uid)) { + $newUserList[] = (int)$uid; + } + } + } + + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('be_users'); + $validatedUserList = $queryBuilder + ->select('uid') + ->from('be_users') + ->where( + $queryBuilder->expr()->andX( + $queryBuilder->expr()->eq('deleted', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)), + $queryBuilder->expr()->eq('admin', $queryBuilder->createNamedParameter(1, \PDO::PARAM_INT)), + $queryBuilder->expr()->in('uid', $queryBuilder->createNamedParameter($newUserList, Connection::PARAM_INT_ARRAY)) + ) + )->execute()->fetchAll(); + + $validatedUserList = array_column($validatedUserList, 'uid'); + + $configurationManager = GeneralUtility::makeInstance(ConfigurationManager::class); + $configurationManager->setLocalConfigurationValuesByPathValuePairs( + [ 'SYS/systemMaintainers' => $validatedUserList ] + ); + + $messages = []; + if (empty($validatedUserList)) { + $messages[] = new FlashMessage( + '', + 'Set system maintainer list to an empty array', + FlashMessage::INFO + ); + } else { + $messages[] = new FlashMessage( + implode(', ', $validatedUserList), + 'New system maintainer uid list', + FlashMessage::INFO + ); + } + + $this->view->assignMultiple([ + 'success' => true, + 'status' => $messages + ]); + return $this->view->render(); + } +} diff --git a/typo3/sysext/install/Classes/Controller/Action/Tool/Settings.php b/typo3/sysext/install/Classes/Controller/Action/Tool/Settings.php index 4114873a5d4e..1520e269403e 100644 --- a/typo3/sysext/install/Classes/Controller/Action/Tool/Settings.php +++ b/typo3/sysext/install/Classes/Controller/Action/Tool/Settings.php @@ -50,6 +50,7 @@ class Settings extends Action\AbstractAction $presetFeatures = $this->featureManager->getInitializedFeatures($this->postValues['values'] ?? []); $localConfigurationValueService = new LocalConfigurationValueService(); $formProtection = FormProtectionFactory::get(InstallToolFormProtection::class); + $this->view->assignMultiple([ 'changeInstallToolPasswordToken' => $formProtection->generateToken('installTool', 'changeInstallToolPassword'), @@ -59,6 +60,9 @@ class Settings extends Action\AbstractAction 'presetActivateToken' => $formProtection->generateToken('installTool', 'presetActivate'), 'presetFeatures' => $presetFeatures, + + 'systemMaintainerWriteToken' => $formProtection->generateToken('installTool', 'systemMaintainerWrite'), + 'systemMaintainerIsDevelopmentContext' => GeneralUtility::getApplicationContext()->isDevelopment(), ]); return $this->view->render(); } diff --git a/typo3/sysext/install/Classes/Controller/AjaxController.php b/typo3/sysext/install/Classes/Controller/AjaxController.php index b1d2316dff68..8631ec678f23 100644 --- a/typo3/sysext/install/Classes/Controller/AjaxController.php +++ b/typo3/sysext/install/Classes/Controller/AjaxController.php @@ -66,6 +66,10 @@ class AjaxController extends AbstractController 'mailTest', 'presetActivate', 'resetBackendUserUc', + + 'systemMaintainerGetList', + 'systemMaintainerWrite', + 'tcaExtTablesCheck', 'tcaMigrationsCheck', diff --git a/typo3/sysext/install/Resources/Private/Partials/Action/Tool/Settings/SystemMaintainer.html b/typo3/sysext/install/Resources/Private/Partials/Action/Tool/Settings/SystemMaintainer.html new file mode 100644 index 000000000000..4384385a9ded --- /dev/null +++ b/typo3/sysext/install/Resources/Private/Partials/Action/Tool/Settings/SystemMaintainer.html @@ -0,0 +1,43 @@ +<p> + Backend admin users listed here will see the system maintenance related main + module entries "Maintenance", "Settings", "Upgrade" and "Environment" in the + backend and are allowed to use them without further log in. + Note that all backend admin users see these menu entries if the system is in + development (not production) context. +</p> + +<f:if condition="{systemMaintainerIsDevelopmentContext}"> + <div class="typo3-message alert alert-info"> + <div class="message-body"> + This TYPO3 instance is set to "Development" context, all backend admin users + can see the system maintenance related main module entries. + </div> + </div> +</f:if> + +<div style="display:none;"> + <div id="t3js-systemMaintainer-write-token">{systemMaintainerWriteToken}</div> +</div> + +<div class="form-group"> + <div class="input-group t3js-systemMaintainer-chosen" style="display:none"> + <span class="input-group-addon">System Maintainer:</span> + <select + class="chosen-select t3js-systemMaintainer-chosen-select" + data-placeholder="none" + style="width:100%;" + multiple + tabindex="" + > + </select> + </div> +</div> + +<div class="t3js-systemMaintainer-output"></div> + +<button + class="btn btn-default t3js-systemMaintainer-write" + type="button" +> + Save system maintainer list +</button> diff --git a/typo3/sysext/install/Resources/Private/Templates/Action/Tool/Settings.html b/typo3/sysext/install/Resources/Private/Templates/Action/Tool/Settings.html index 55750a39e2fd..7c590df835ad 100644 --- a/typo3/sysext/install/Resources/Private/Templates/Action/Tool/Settings.html +++ b/typo3/sysext/install/Resources/Private/Templates/Action/Tool/Settings.html @@ -15,14 +15,21 @@ category: 'Access', description: 'Set a new install tool password.' }, - 1: {partial: 'Action/Tool/Settings/LocalConfiguration', + 1: {partial: 'Action/Tool/Settings/SystemMaintainer', + require: 'TYPO3/CMS/Install/SystemMaintainer', + baseClass: 't3js-systemMaintainer', + title: 'Configure system maintainer', + category: 'Access', + description: 'Backend admin users with access to install tool.' + }, + 2: {partial: 'Action/Tool/Settings/LocalConfiguration', require: 'TYPO3/CMS/Install/LocalConfiguration', baseClass: 't3js-localConfiguration', title: 'Configure Global Settings', category: 'LocalConfiguration', description: 'Modify LocalConfiguration.php settings.' }, - 2: {partial: 'Action/Tool/Settings/Presets', + 3: {partial: 'Action/Tool/Settings/Presets', require: 'TYPO3/CMS/Install/Presets', baseClass: 't3js-presets', title: 'Configure Presets', diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/SystemMaintainer.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/SystemMaintainer.js new file mode 100644 index 000000000000..8bee9736912c --- /dev/null +++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/SystemMaintainer.js @@ -0,0 +1,141 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +/** + * Module: TYPO3/CMS/Install/SystemMaintainer + */ +define([ + 'jquery', + 'TYPO3/CMS/Install/FlashMessage', + 'TYPO3/CMS/Install/ProgressBar', + 'TYPO3/CMS/Install/InfoBox', + 'TYPO3/CMS/Install/Severity', + 'bootstrap', + 'chosen' +], function($, FlashMessage, ProgressBar, InfoBox, Severity) { + 'use strict'; + + return { + selectorGridderOpener: 't3js-systemMaintainer-open', + selectorWriteTrigger: '.t3js-systemMaintainer-write', + selectorWriteToken: '#t3js-systemMaintainer-write-token', + selectorOutputContainer: '.t3js-systemMaintainer-output', + selectorChosenContainer: '.t3js-systemMaintainer-chosen', + selectorChosenField: '.t3js-systemMaintainer-chosen-select', + + initialize: function() { + var self = this; + + // Get current system maintainer list on card open + $(document).on('cardlayout:card-opened', function(event, $card) { + if ($card.hasClass(self.selectorGridderOpener)) { + self.getList(); + } + }); + + $(document).on('click', this.selectorWriteTrigger, function(e) { + e.preventDefault(); + self.write(); + }); + }, + + getList: function() { + var self = this; + var url = location.href + '&install[controller]=ajax&install[action]=systemMaintainerGetList'; + var $chosenContainer = $(this.selectorChosenContainer); + var $outputContainer = $(this.selectorOutputContainer); + var $chosenField = $(self.selectorChosenField); + var message = ProgressBar.render(Severity.loading, 'Loading...', ''); + $outputContainer.empty().append(message); + $chosenContainer.hide(); + $chosenField.empty(); + $.ajax({ + url: url, + cache: false, + success: function (data) { + if (data.success === true) { + $outputContainer.find('.alert-loading').remove(); + if (Array.isArray(data.status)) { + data.status.forEach(function(element) { + var message = InfoBox.render(element.severity, element.title, element.message); + $outputContainer.append(message); + }); + } + if (Array.isArray(data.users)) { + data.users.forEach(function(element) { + var name = element.username; + if (element.disable) { + name = '[DISABLED] ' + name; + } + var selected = ''; + if (element.isSystemMaintainer) { + selected = 'selected="selected"'; + } + $chosenField.append( + '<option value="' + element.uid + '" ' + selected + '>' + name + '</option>' + ); + }); + } + var config = { + '.chosen-select': {width: "100%", placeholder_text_multiple: "users"}, + '.chosen-select-deselect': {allow_single_deselect: true}, + '.chosen-select-width': {width: "100%"} + }; + for (var selector in config) { + $(selector).chosen(config[selector]); + } + $chosenContainer.show(); + $chosenField.trigger('chosen:updated'); + } + }, + error: function() { + var message = InfoBox.render(Severity.error, 'Something went wrong', ''); + $outputContainer.empty().html(message); + } + }); + }, + + write: function() { + var $outputContainer = $(this.selectorOutputContainer); + var selectedUsers = $(this.selectorChosenField).val(); + var message = ProgressBar.render(Severity.loading, 'Loading...', ''); + $outputContainer.append(message); + $.ajax({ + method: 'POST', + url: location.href + '&install[controller]=ajax', + data: { + 'install': { + 'users': selectedUsers, + 'token': $(this.selectorWriteToken).text(), + 'action': 'systemMaintainerWrite' + } + }, + success: function (data) { + if (data.success === true) { + $outputContainer.find('.alert-loading').remove(); + if (Array.isArray(data.status)) { + data.status.forEach(function(element) { + var message = InfoBox.render(element.severity, element.title, element.message); + $outputContainer.empty().append(message); + }); + } + } + }, + error: function() { + var message = InfoBox.render(Severity.error, 'Something went wrong', ''); + $outputContainer.empty().html(message); + } + }); + } + }; +}); -- GitLab