diff --git a/typo3/sysext/beuser/Classes/Controller/BackendUserController.php b/typo3/sysext/beuser/Classes/Controller/BackendUserController.php index faeb8a03af512ae5d25d75dca8c84eebdf9c5ae8..2d8c1e87e674050d5fabaa9dcbcb1fed7f56383f 100644 --- a/typo3/sysext/beuser/Classes/Controller/BackendUserController.php +++ b/typo3/sysext/beuser/Classes/Controller/BackendUserController.php @@ -1,4 +1,5 @@ <?php + namespace TYPO3\CMS\Beuser\Controller; /* @@ -15,6 +16,11 @@ namespace TYPO3\CMS\Beuser\Controller; */ use TYPO3\CMS\Backend\Authentication\Event\SwitchUserEvent; +use TYPO3\CMS\Beuser\Domain\Repository\BackendUserGroupRepository; +use TYPO3\CMS\Beuser\Domain\Repository\BackendUserRepository; +use TYPO3\CMS\Beuser\Domain\Repository\BackendUserSessionRepository; +use TYPO3\CMS\Beuser\Service\ModuleDataStorageService; +use TYPO3\CMS\Beuser\Service\UserInformationService; use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; use TYPO3\CMS\Core\Session\Backend\SessionBackendInterface; use TYPO3\CMS\Core\Session\SessionManager; @@ -41,55 +47,42 @@ class BackendUserController extends ActionController protected $moduleData; /** - * @var \TYPO3\CMS\Beuser\Service\ModuleDataStorageService + * @var ModuleDataStorageService */ protected $moduleDataStorageService; /** - * @var \TYPO3\CMS\Beuser\Domain\Repository\BackendUserRepository + * @var BackendUserRepository */ protected $backendUserRepository; /** - * @var \TYPO3\CMS\Beuser\Domain\Repository\BackendUserGroupRepository + * @var BackendUserGroupRepository */ protected $backendUserGroupRepository; /** - * @var \TYPO3\CMS\Beuser\Domain\Repository\BackendUserSessionRepository + * @var BackendUserSessionRepository */ protected $backendUserSessionRepository; /** - * @param \TYPO3\CMS\Beuser\Service\ModuleDataStorageService $moduleDataStorageService + * @var UserInformationService */ - public function injectModuleDataStorageService(\TYPO3\CMS\Beuser\Service\ModuleDataStorageService $moduleDataStorageService) - { + protected $userInformationService; + + public function __construct( + ModuleDataStorageService $moduleDataStorageService, + BackendUserRepository $backendUserRepository, + BackendUserGroupRepository $backendUserGroupRepository, + BackendUserSessionRepository $backendUserSessionRepository, + UserInformationService $userInformationService + ) { $this->moduleDataStorageService = $moduleDataStorageService; - } - - /** - * @param \TYPO3\CMS\Beuser\Domain\Repository\BackendUserRepository $backendUserRepository - */ - public function injectBackendUserRepository(\TYPO3\CMS\Beuser\Domain\Repository\BackendUserRepository $backendUserRepository) - { $this->backendUserRepository = $backendUserRepository; - } - - /** - * @param \TYPO3\CMS\Beuser\Domain\Repository\BackendUserGroupRepository $backendUserGroupRepository - */ - public function injectBackendUserGroupRepository(\TYPO3\CMS\Beuser\Domain\Repository\BackendUserGroupRepository $backendUserGroupRepository) - { $this->backendUserGroupRepository = $backendUserGroupRepository; - } - - /** - * @param \TYPO3\CMS\Beuser\Domain\Repository\BackendUserSessionRepository $backendUserSessionRepository - */ - public function injectBackendUserSessionRepository(\TYPO3\CMS\Beuser\Domain\Repository\BackendUserSessionRepository $backendUserSessionRepository) - { $this->backendUserSessionRepository = $backendUserSessionRepository; + $this->userInformationService = $userInformationService; } /** @@ -186,6 +179,18 @@ class BackendUserController extends ActionController ]); } + /** + * @param int $uid + */ + public function showAction(int $uid = 0): void + { + $data = $this->userInformationService->get($uid); + $this->view->assignMultiple([ + 'shortcutLabel' => 'showUser', + 'data' => $data + ]); + } + /** * Compare backend users from demand */ @@ -196,9 +201,14 @@ class BackendUserController extends ActionController $this->redirect('index'); } + $compareData = []; + foreach ($compareUserList as $uid) { + $compareData[] = $this->userInformationService->get($uid); + } + $this->view->assignMultiple([ 'shortcutLabel' => 'compareUsers', - 'compareUserList' => $this->backendUserRepository->findByUidList($compareUserList), + 'compareUserList' => $compareData ]); } diff --git a/typo3/sysext/beuser/Classes/Service/UserInformationService.php b/typo3/sysext/beuser/Classes/Service/UserInformationService.php new file mode 100644 index 0000000000000000000000000000000000000000..ea2e1f976e30e9b45b96643e998f8d4688c23d0f --- /dev/null +++ b/typo3/sysext/beuser/Classes/Service/UserInformationService.php @@ -0,0 +1,145 @@ +<?php +declare(strict_types = 1); +namespace TYPO3\CMS\Beuser\Service; + +/* + * 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\Backend\Utility\BackendUtility; +use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; +use TYPO3\CMS\Core\Imaging\IconFactory; +use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; +use TYPO3\CMS\Core\Utility\GeneralUtility; + +/** + * Transform information of user and groups into better format + * @internal + */ +class UserInformationService +{ + + /** + * @var IconFactory + */ + protected $iconFactory; + + public function __construct() + { + $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class); + } + + /** + * Get all relevant information of the user + * + * @param int $userId + * @return array + */ + public function get(int $userId): array + { + $user = GeneralUtility::makeInstance(BackendUserAuthentication::class); + $user->enablecolumns = []; + $user->setBeUserByUid($userId); + $user->fetchGroupData(); + + // usergroups + $data = [ + 'user' => $user->user ?? [], + 'groups' => [ + 'inherit' => GeneralUtility::trimExplode(',', $user->groupList, true), + 'direct' => GeneralUtility::trimExplode(',', $user->user['usergroup'], true), + ], + ]; + $data['groups']['diff'] = array_diff($data['groups']['inherit'], $data['groups']['direct']); + foreach ($data['groups'] as $type => $groups) { + foreach ($groups as $key => $id) { + $data['groups'][$type][$key] = BackendUtility::getRecord('be_groups', $id); + } + } + + // languages + $languages = GeneralUtility::trimExplode(',', $user->dataLists['allowed_languages'], true); + asort($languages); + foreach ($languages as $language) { + $data['languages'][$language] = BackendUtility::getRecord('sys_language', $language); + } + + // table permissions + foreach (['tables_select', 'tables_modify'] as $tableField) { + $temp = GeneralUtility::trimExplode(',', $user->dataLists[$tableField], true); + foreach ($temp as $tableName) { + $data['tables'][$tableField][$tableName] = $GLOBALS['TCA'][$tableName]['ctrl']['title']; + } + } + $data['tables']['all'] = array_replace($data['tables']['tables_select'] ?? [], $data['tables']['tables_modify'] ?? []); + + // DB mounts + $dbMounts = GeneralUtility::trimExplode(',', $user->dataLists['webmount_list'], true); + asort($dbMounts); + foreach ($dbMounts as $mount) { + $record = BackendUtility::getRecord('pages', $mount, '*'); + if ($record) { + $data['dbMounts'][] = $record; + } + } + + // File mounts + $fileMounts = GeneralUtility::trimExplode(',', $user->dataLists['filemount_list'], true); + asort($fileMounts); + foreach ($fileMounts as $mount) { + $data['fileMounts'][] = BackendUtility::getRecord('sys_filemounts', $mount, '*'); + } + + // Modules + $modules = GeneralUtility::trimExplode(',', $user->dataLists['modList'], true); + foreach ($modules as $module) { + $data['modules'][$module] = $GLOBALS['TBE_MODULES']['_configuration'][$module]; + } + + // Categories + $categories = GeneralUtility::trimExplode(',', $user->user['category_perms'], true); + foreach ($categories as $category) { + $data['categories'][$category] = BackendUtility::getRecord('sys_category', $category); + } + + // workspaces + if (ExtensionManagementUtility::isLoaded('workspaces')) { + $data['workspaces'] = [ + 'loaded' => true, + 'record' => $user->workspaceRec + ]; + } + + // non_exclude_fields + $fieldListTmp = GeneralUtility::trimExplode(',', $user->dataLists['non_exclude_fields'], true); + $fieldList = []; + foreach ($fieldListTmp as $item) { + $split = explode(':', $item); + $fieldList[$split[0]]['label'] = $GLOBALS['TCA'][$split[0]]['ctrl']['title']; + $fieldList[$split[0]]['fields'][$split[1]] = $GLOBALS['TCA'][$split[0]]['columns'][$split[1]]['label'] ?? $split[1]; + } + $data['non_exclude_fields'] = $fieldList; + + $specialItems = $GLOBALS['TCA']['pages']['columns']['doktype']['config']['items']; + foreach ($specialItems as $specialItem) { + $value = $specialItem[1]; + if (!GeneralUtility::inList($user->dataLists['pagetypes_select'], $value)) { + continue; + } + $label = $specialItem[0]; + $icon = $this->iconFactory->mapRecordTypeToIconIdentifier('pages', ['doktype' => $specialItem[1]]); + $data['pageTypes'][] = ['label' => $label, 'value' => $value, 'icon' => $icon]; + } + + return $data; + } +} diff --git a/typo3/sysext/beuser/Classes/ViewHelpers/Display/PagesViewHelper.php b/typo3/sysext/beuser/Classes/ViewHelpers/Display/PagesViewHelper.php deleted file mode 100644 index 56138b6b231ed323f24f3a8b0aa2d2c4f5874dbc..0000000000000000000000000000000000000000 --- a/typo3/sysext/beuser/Classes/ViewHelpers/Display/PagesViewHelper.php +++ /dev/null @@ -1,88 +0,0 @@ -<?php -namespace TYPO3\CMS\Beuser\ViewHelpers\Display; - -/* - * 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\Connection; -use TYPO3\CMS\Core\Database\ConnectionPool; -use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface; -use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper; -use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic; - -/** - * Converts comma separated list of pages uids to html unordered list (<ul>) with speaking titles - * @internal - */ -class PagesViewHelper extends AbstractViewHelper -{ - use CompileWithRenderStatic; - - /** - * As this ViewHelper renders HTML, the output must not be escaped. - * - * @var bool - */ - protected $escapeOutput = false; - - /** - * Initializes the arguments - */ - public function initializeArguments() - { - $this->registerArgument('uids', 'string', '', false, ''); - } - - /** - * Render unordered list for pages - * - * @param array $arguments - * @param \Closure $renderChildrenClosure - * @param RenderingContextInterface $renderingContext - * - * @return string - */ - public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext) - { - $uids = $arguments['uids']; - if (!$uids) { - return ''; - } - - $content = ''; - - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages'); - $queryBuilder->getRestrictions()->removeAll(); - - $res = $queryBuilder - ->select('uid', 'title') - ->from('pages') - ->where( - $queryBuilder->expr()->in( - 'uid', - $queryBuilder->createNamedParameter( - GeneralUtility::intExplode(',', $uids), - Connection::PARAM_INT_ARRAY - ) - ) - ) - ->orderBy('uid', 'ASC') - ->execute(); - - while ($row = $res->fetch()) { - $content .= '<li>' . htmlspecialchars($row['title']) . ' [' . htmlspecialchars($row['uid']) . ']</li>'; - } - return '<ul>' . $content . '</ul>'; - } -} diff --git a/typo3/sysext/beuser/Classes/ViewHelpers/Display/SysFileMountsViewHelper.php b/typo3/sysext/beuser/Classes/ViewHelpers/Display/SysFileMountsViewHelper.php deleted file mode 100644 index 2faea9711066dd7d61a29e35ab32834f7485f033..0000000000000000000000000000000000000000 --- a/typo3/sysext/beuser/Classes/ViewHelpers/Display/SysFileMountsViewHelper.php +++ /dev/null @@ -1,88 +0,0 @@ -<?php -namespace TYPO3\CMS\Beuser\ViewHelpers\Display; - -/* - * 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\Connection; -use TYPO3\CMS\Core\Database\ConnectionPool; -use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface; -use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper; -use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic; - -/** - * Converts comma separated list of sys_filemounts uids to html unordered list (<ul>) with speaking titles - * @internal - */ -class SysFileMountsViewHelper extends AbstractViewHelper -{ - use CompileWithRenderStatic; - - /** - * As this ViewHelper renders HTML, the output must not be escaped. - * - * @var bool - */ - protected $escapeOutput = false; - - /** - * Initializes the arguments - */ - public function initializeArguments() - { - $this->registerArgument('uids', 'string', '', false, ''); - } - - /** - * Render unordered list for sys_filemounts - * - * @param array $arguments - * @param \Closure $renderChildrenClosure - * @param RenderingContextInterface $renderingContext - * - * @return string - */ - public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext) - { - $uids = $arguments['uids']; - if (!$uids) { - return ''; - } - - $content = ''; - - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_filemounts'); - $queryBuilder->getRestrictions()->removeAll(); - - $res = $queryBuilder - ->select('uid', 'title') - ->from('sys_filemounts') - ->where( - $queryBuilder->expr()->in( - 'uid', - $queryBuilder->createNamedParameter( - GeneralUtility::intExplode(',', $uids), - Connection::PARAM_INT_ARRAY - ) - ) - ) - ->orderBy('title', 'ASC') - ->execute(); - - while ($row = $res->fetch()) { - $content .= '<li>' . htmlspecialchars($row['title']) . ' [' . htmlspecialchars($row['uid']) . ']</li>'; - } - return '<ul>' . $content . '</ul>'; - } -} diff --git a/typo3/sysext/beuser/Classes/ViewHelpers/Display/SysLanguageViewHelper.php b/typo3/sysext/beuser/Classes/ViewHelpers/Display/SysLanguageViewHelper.php deleted file mode 100644 index 2cad5b3e9ffbef6db06c0f1646cdbe3afc8927f0..0000000000000000000000000000000000000000 --- a/typo3/sysext/beuser/Classes/ViewHelpers/Display/SysLanguageViewHelper.php +++ /dev/null @@ -1,88 +0,0 @@ -<?php -namespace TYPO3\CMS\Beuser\ViewHelpers\Display; - -/* - * 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\Connection; -use TYPO3\CMS\Core\Database\ConnectionPool; -use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface; -use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper; -use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic; - -/** - * Converts comma separated list of sys_language uids to html unordered list (<ul>) with speaking titles - * @internal - */ -class SysLanguageViewHelper extends AbstractViewHelper -{ - use CompileWithRenderStatic; - - /** - * As this ViewHelper renders HTML, the output must not be escaped. - * - * @var bool - */ - protected $escapeOutput = false; - - /** - * Initializes the arguments - */ - public function initializeArguments() - { - $this->registerArgument('uids', 'string', '', false, ''); - } - - /** - * Render unordered list for sys_language - * - * @param array $arguments - * @param \Closure $renderChildrenClosure - * @param RenderingContextInterface $renderingContext - * - * @return string - */ - public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext) - { - $uids = $arguments['uids']; - if (!$uids) { - return ''; - } - - $content = ''; - - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_language'); - $queryBuilder->getRestrictions()->removeAll(); - - $res = $queryBuilder - ->select('uid', 'title', 'flag') - ->from('sys_language') - ->where( - $queryBuilder->expr()->in( - 'uid', - $queryBuilder->createNamedParameter( - GeneralUtility::intExplode(',', $uids), - Connection::PARAM_INT_ARRAY - ) - ) - ) - ->orderBy('sorting') - ->execute(); - - while ($row = $res->fetch()) { - $content .= '<li>' . htmlspecialchars($row['title']) . ' [' . htmlspecialchars($row['uid']) . ']</li>'; - } - return '<ul>' . $content . '</ul>'; - } -} diff --git a/typo3/sysext/beuser/Classes/ViewHelpers/Display/TableAccessViewHelper.php b/typo3/sysext/beuser/Classes/ViewHelpers/Display/TableAccessViewHelper.php new file mode 100644 index 0000000000000000000000000000000000000000..86f306c2be21c0afcebf60c1a9ce43de0a0ea348 --- /dev/null +++ b/typo3/sysext/beuser/Classes/ViewHelpers/Display/TableAccessViewHelper.php @@ -0,0 +1,35 @@ +<?php +declare(strict_types = 1); +namespace TYPO3\CMS\Beuser\ViewHelpers\Display; + +/* + * 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 TYPO3Fluid\Fluid\Core\ViewHelper\AbstractConditionViewHelper; + +class TableAccessViewHelper extends AbstractConditionViewHelper +{ + public function initializeArguments(): void + { + parent::initializeArguments(); + $this->registerArgument('table', 'string', 'Tablename to be checked'); + $this->registerArgument('select', 'array', 'List of allowed tables to select', false, []); + $this->registerArgument('modify', 'array', 'List of allowed tables to modify', false, []); + } + + protected static function evaluateCondition($arguments = null): bool + { + $table = $arguments['table']; + return array_key_exists($table, $arguments['select']) || array_key_exists($table, $arguments['modify']); + } +} diff --git a/typo3/sysext/beuser/Resources/Private/Language/locallang.xlf b/typo3/sysext/beuser/Resources/Private/Language/locallang.xlf index 35eb4452249b66f082974ff42991e74e6ca57d27..40badd3844a4573883b294a084b46efde96d718f 100644 --- a/typo3/sysext/beuser/Resources/Private/Language/locallang.xlf +++ b/typo3/sysext/beuser/Resources/Private/Language/locallang.xlf @@ -174,6 +174,51 @@ <trans-unit id="visibility.unhide" resname="visibility.unhide"> <source>Un-hide</source> </trans-unit> + <trans-unit id="information.defaultLanguage" resname="information.defaultLanguage"> + <source>Default</source> + </trans-unit> + <trans-unit id="groups" resname="groups"> + <source>Groups</source> + </trans-unit> + <trans-unit id="information.groups.direct" resname="information.groups.direct"> + <source>Directly assigned</source> + </trans-unit> + <trans-unit id="information.groups.inheritance" resname="information.groups.inheritance"> + <source>Assigned through inheritance</source> + </trans-unit> + <trans-unit id="languages" resname="languages"> + <source>Languages</source> + </trans-unit> + <trans-unit id="dbMounts" resname="dbMounts"> + <source>DB Mounts</source> + </trans-unit> + <trans-unit id="fileMounts" resname="fileMounts"> + <source>File Mounts</source> + </trans-unit> + <trans-unit id="categories" resname="categories"> + <source>Categories</source> + </trans-unit> + <trans-unit id="permissions" resname="permissions"> + <source>Permissions</source> + </trans-unit> + <trans-unit id="modules" resname="modules"> + <source>Modules</source> + </trans-unit> + <trans-unit id="tableModes" resname="tableModes"> + <source>Table select/modify</source> + </trans-unit> + <trans-unit id="tableModes.select" resname="tableModes.select"> + <source>Select</source> + </trans-unit> + <trans-unit id="tableModes.modify" resname="tableModes.modify"> + <source>Modify</source> + </trans-unit> + <trans-unit id="information.defaultWorkspace" resname="information.defaultWorkspace"> + <source>Default workspace</source> + </trans-unit> + <trans-unit id="backendUser" resname="backendUser"> + <source>Backend User</source> + </trans-unit> </body> </file> </xliff> diff --git a/typo3/sysext/beuser/Resources/Private/Partials/BackendUser/IndexListRow.html b/typo3/sysext/beuser/Resources/Private/Partials/BackendUser/IndexListRow.html index 3ea508cfea32baad107d16dd0f75c19672ddfada..047966345a4c03d1cecf84e86071c8416a988d96 100644 --- a/typo3/sysext/beuser/Resources/Private/Partials/BackendUser/IndexListRow.html +++ b/typo3/sysext/beuser/Resources/Private/Partials/BackendUser/IndexListRow.html @@ -71,6 +71,9 @@ </f:if> </div> <div class="btn-group" role="group"> + <f:link.action action="show" arguments="{uid: backendUser.uid}" class="btn btn-default" title="{f:translate(key: 'details')}"> + <core:icon identifier="actions-system-options-view" size="small"/> + </f:link.action> <a class="btn btn-default" href="#" title="{f:translate(key:'info')}" onclick="top.TYPO3.InfoWindow.showItem('be_users', '{backendUser.uid}'); return false;"><core:icon identifier="actions-document-info" /></a> </div> <div class="btn-group" role="group"> diff --git a/typo3/sysext/beuser/Resources/Private/Partials/BackendUser/Information.html b/typo3/sysext/beuser/Resources/Private/Partials/BackendUser/Information.html new file mode 100644 index 0000000000000000000000000000000000000000..8a299e7f876da51a36292f259a61eddc5b777e0d --- /dev/null +++ b/typo3/sysext/beuser/Resources/Private/Partials/BackendUser/Information.html @@ -0,0 +1,126 @@ +<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers" xmlns:be="http://typo3.org/ns/TYPO3/CMS/Backend/ViewHelpers" xmlns:bu="http://typo3.org/ns/TYPO3/CMS/Beuser/ViewHelpers"> + +<f:section name="languages"> + <ul> + <f:for each="{languages}" key="languageUid" as="language"> + <li> + <f:if condition="{languageUid} ==0"> + <f:then> + <f:translate key="information.defaultLanguage" /> + </f:then> + <f:else> + <a href="#" class="t3js-contextmenutrigger" data-table="sys_language" data-uid="{language.uid}" title="id={language.uid}"> + <core:iconForRecord table="sys_language" row="{language}"/> + {language.title} [{language.uid}] + </a> + </f:else> + </f:if> + </li> + </f:for> + </ul> +</f:section> + +<f:section name="groups"> + <f:if condition="{groups.direct}"> + <strong><f:translate key="information.groups.direct" /></strong> + + <f:for each="{groups.direct}" as="group"> + <div> + <a href="#" class="t3js-contextmenutrigger" data-table="be_groups" data-uid="{group.uid}" title="id={group.uid}"> + <core:iconForRecord table="be_groups" row="{group}"/> + {group.title} + </a> + </div> + </f:for> + </f:if> + <f:if condition="{groups.diff}"> + <strong><f:translate key="information.groups.inheritance" /></strong> + + <f:for each="{groups.diff}" as="group"> + <div> + <a href="#" class="t3js-contextmenutrigger" data-table="be_groups" data-uid="{group.uid}" title="id={group.uid}"> + <core:iconForRecord table="be_groups" row="{group}"/> + {group.title} + </a> + </div> + </f:for> + </f:if> +</f:section> + +<f:section name="dbMounts"> + <f:if condition="{dbMounts}"> + <ul> + <f:for each="{dbMounts}" as="mount"> + <li> + <core:iconForRecord table="pages" row="{mount}"/> + {mount.title} [{mount.uid}] + </li> + </f:for> + </ul> + </f:if> +</f:section> + +<f:section name="fileMounts"> + <f:if condition="{fileMounts}"> + <ul> + <f:for each="{fileMounts}" as="mount"> + <li> + <a href="#" class="t3js-contextmenutrigger" data-table="sys_filemounts" data-uid="{mount.uid}" title="id={mount.uid}"> + <core:iconForRecord table="sys_filemounts" row="{mount}"/> + {mount.title} [{mount.uid}] + </a> + </li> + </f:for> + </ul> + </f:if> +</f:section> + +<f:section name="categories"> + <f:if condition="{categories}"> + <ul> + <f:for each="{categories}" as="category"> + <li> + <a href="#" class="t3js-contextmenutrigger" data-table="sys_category" data-uid="{category.uid}" title="id={category.uid}"> + <core:iconForRecord table="sys_category" row="{category}"/> + {category.title} + </a> + </li> + </f:for> + </ul> + </f:if> +</f:section> + +<f:section name="workspaces"> + <f:if condition="{workspaces}"> + <f:if condition="{workspaces.record.uid}"> + <strong><f:translate key="information.defaultWorkspace" />:</strong> + <a href="#" class="t3js-contextmenutrigger" data-table="sys_workspace" data-uid="{workspaces.record.uid}" title="id={workspaces.record.uid}"> + <core:iconForRecord table="sys_workspaces" row="{workspaces.record}"/> + {workspaces.record.title} + </a> + </f:if> + </f:if> +</f:section> + +<f:section name="pageTypes"> + <f:if condition="{pageTypes}"> + <ul> + <f:for each="{pageTypes}" as="pageType"> + <li> + <core:icon identifier="{pageType.icon}"/> + {f:translate(key:pageType.label,default:pageType.label)} + </li> + </f:for> + </ul> + </f:if> +</f:section> + + +<f:section name="yesno"> + <f:if condition="{value}"> + <f:then><span class="t3-icon change-permission fa fa-check text-success"></span>{f:translate(key:'yes')}</f:then> + <f:else><span class="t3-icon change-permission fa fa-times text-danger"></span>{f:translate(key:'no')}</f:else> + </f:if> +</f:section> + +</html> diff --git a/typo3/sysext/beuser/Resources/Private/Templates/BackendUser/Compare.html b/typo3/sysext/beuser/Resources/Private/Templates/BackendUser/Compare.html index a318e503c5faa6a534ad39db94a5538d98c2c3a9..4cfc6fbd955d0412483eac902b43ed6b59297977 100644 --- a/typo3/sysext/beuser/Resources/Private/Templates/BackendUser/Compare.html +++ b/typo3/sysext/beuser/Resources/Private/Templates/BackendUser/Compare.html @@ -14,19 +14,19 @@ </f:section> <f:section name="Content"> - <h1><f:translate key="compareBackendUsers">Compare backend users</f:translate></h1> + <h1>{f:translate(key:'compareBackendUsers')}</h1> <div class="table-fit"> - <table border="0" cellpadding="0" cellspacing="0" id="tx_beuser_compare" class="table table-striped table-bordered table-hover"> + <table id="tx_beuser_compare" class="table table-striped table-bordered table-hover"> <thead> <tr> <th></th> <f:for each="{compareUserList}" as="compareUser"> <th> - <a href="#" class="t3js-contextmenutrigger" data-table="be_users" data-uid="{compareUser.uid}" title="id={compareUser.uid}"> - <be:avatar backendUser="{compareUser.uid}" showIcon="true" /> + <a href="#" class="t3js-contextmenutrigger" data-table="be_users" data-uid="{compareUser.user.uid}" title="id={compareUser.user.uid}"> + <be:avatar backendUser="{compareUser.user.uid}" showIcon="true" /> </a> - {compareUser.userName} - <be:link.editRecord class="btn btn-default pull-right" table="be_users" uid="{compareUser.uid}" title="edit"> + {compareUser.user.username} + <be:link.editRecord class="btn btn-default pull-right" table="be_users" uid="{compareUser.user.uid}" title="edit"> <core:icon identifier="actions-open" /> </be:link.editRecord> </th> @@ -37,20 +37,10 @@ <tr> <th><f:translate key="realName" /></th> <f:for each="{compareUserList}" as="compareUser"> - <td>{compareUser.realName}</td> - </f:for> - </tr> - <tr> - <th><f:translate key="email" /></th> - <f:for each="{compareUserList}" as="compareUser"> - <td> - <f:if condition="{compareUser.email}"> - <f:then> - <f:link.email email="{compareUser.email}" /> - </f:then> - <f:else> - - - </f:else> + <td>{compareUser.user.realName} + + <f:if condition="{compareUser.user.email}"> + (<f:link.email email="{compareUser.user.email}" />) </f:if> </td> </f:for> @@ -59,10 +49,7 @@ <th><f:translate key="admin" /></th> <f:for each="{compareUserList}" as="compareUser"> <td> - <f:if condition="{compareUser.isAdministrator}"> - <f:then><f:translate key="yes" /></f:then> - <f:else><f:translate key="no" /></f:else> - </f:if> + <f:render partial="BackendUser/Information" section="yesno" arguments="{value:compareUser.user.admin}" /> </td> </f:for> </tr> @@ -70,19 +57,17 @@ <th><f:translate key="disable_compare" /></th> <f:for each="{compareUserList}" as="compareUser"> <td> - <f:if condition="{compareUser.currentlyLoggedIn} == 0"> - <f:if condition="{compareUser.isDisabled} == 1"> - <f:then> - <a class="btn btn-default" href="{be:moduleLink(route:'tce_db', query:'data[be_users][{compareUser.uid}][disable]=0', currentUrlParameterName:'redirect')}" title="{f:translate(key: 'visibility.unhide')}"> - <core:icon identifier="actions-edit-unhide" /> - </a> - </f:then> - <f:else> - <a class="btn btn-default" href="{be:moduleLink(route:'tce_db', query:'data[be_users][{compareUser.uid}][disable]=1', currentUrlParameterName:'redirect')}" title="{f:translate(key: 'visibility.hide')}"> - <core:icon identifier="actions-edit-hide" /> - </a> - </f:else> - </f:if> + <f:if condition="{compareUser.disable}"> + <f:then> + <a class="btn btn-default" href="{be:moduleLink(route:'tce_db', query:'data[be_users][{compareUser.user.uid}][disable]=0', currentUrlParameterName:'redirect')}" title="{f:translate(key: 'visibility.unhide')}"> + <core:icon identifier="actions-edit-unhide" /> + </a> + </f:then> + <f:else> + <a class="btn btn-default" href="{be:moduleLink(route:'tce_db', query:'data[be_users][{compareUser.user.uid}][disable]=1', currentUrlParameterName:'redirect')}" title="{f:translate(key: 'visibility.hide')}"> + <core:icon identifier="actions-edit-hide" /> + </a> + </f:else> </f:if> </td> </f:for> @@ -91,9 +76,9 @@ <th><f:translate key="startDateAndTime" /></th> <f:for each="{compareUserList}" as="compareUser"> <td> - <f:if condition="{compareUser.startDateAndTime}"> + <f:if condition="{compareUser.user.starttime}"> <f:then> - <f:format.date format="{dateFormat} {timeFormat}">{compareUser.startDateAndTime}</f:format.date> + <f:format.date format="{dateFormat} {timeFormat}">{compareUser.user.starttime}</f:format.date> </f:then> <f:else> - @@ -106,9 +91,9 @@ <th><f:translate key="endDateAndTime" /></th> <f:for each="{compareUserList}" as="compareUser"> <td> - <f:if condition="{compareUser.endDateAndTime}"> + <f:if condition="{compareUser.user.endtime}"> <f:then> - <f:format.date format="{dateFormat} {timeFormat}">{compareUser.endDateAndTime}</f:format.date> + <f:format.date format="{dateFormat} {timeFormat}">{compareUser.user.endtime}</f:format.date> </f:then> <f:else> - @@ -121,9 +106,9 @@ <th><f:translate key="lastLogin" /></th> <f:for each="{compareUserList}" as="compareUser"> <td> - <f:if condition="{compareUser.lastLoginDateAndTime}"> + <f:if condition="{compareUser.user.lastlogin}"> <f:then> - <f:format.date format="{dateFormat} {timeFormat}">{compareUser.lastLoginDateAndTime}</f:format.date> + <f:format.date format="{dateFormat} {timeFormat}">{compareUser.user.lastlogin}</f:format.date> </f:then> <f:else> <f:translate key="never" /> @@ -136,12 +121,8 @@ <th><f:translate key="backendUserGroups" /></th> <f:for each="{compareUserList}" as="compareUser"> <td> - <f:for each="{compareUser.BackendUserGroups}" as="backendUserGroup"> - <a href="#" class="t3js-contextmenutrigger" data-table="be_groups" data-uid="{backendUserGroup.uid}" title="id={backendUserGroup.uid}"> - <bu:spriteIconForRecord table="be_users" object="{backendUserGroup}" /> - </a> - {backendUserGroup.title}<br /> - </f:for> + <f:render partial="BackendUser/Information" section="groups" arguments="{groups:compareUser.groups}" /> + </td> </f:for> </tr> @@ -149,14 +130,7 @@ <th><f:translate key="allowedLanguages" /></th> <f:for each="{compareUserList}" as="compareUser"> <td> - <f:if condition="{compareUser.allowedLanguages}"> - <f:then> - <bu:display.sysLanguage uids="{compareUser.allowedLanguages}" /> - </f:then> - <f:else> - - - </f:else> - </f:if> + <f:render partial="BackendUser/Information" section="languages" arguments="{languages:compareUser.languages}" /> </td> </f:for> </tr> @@ -164,14 +138,7 @@ <th><f:translate key="dbMountPoints" /></th> <f:for each="{compareUserList}" as="compareUser"> <td> - <f:if condition="{compareUser.dbMountPoints}"> - <f:then> - <bu:display.pages uids="{compareUser.dbMountPoints}" /> - </f:then> - <f:else> - - - </f:else> - </f:if> + <f:render partial="BackendUser/Information" section="dbMounts" arguments="{dbMounts:compareUser.dbMounts}" /> </td> </f:for> </tr> @@ -179,25 +146,41 @@ <th><f:translate key="fileMounts" /></th> <f:for each="{compareUserList}" as="compareUser"> <td> - <f:if condition="{compareUser.fileMountPoints}"> - <f:then> - <bu:display.sysFileMounts uids="{compareUser.fileMountPoints}" /> - </f:then> - <f:else> - - - </f:else> - </f:if> + <f:render partial="BackendUser/Information" section="fileMounts" arguments="{fileMounts:compareUser.fileMounts}" /> + </td> + </f:for> + </tr> + <tr> + <th>Page types</th> + <f:for each="{compareUserList}" as="compareUser"> + <td> + <f:render partial="BackendUser/Information" section="pageTypes" arguments="{pageTypes:compareUser.pageTypes}" /> + </td> + </f:for> + </tr> + <tr> + <th>Categories</th> + <f:for each="{compareUserList}" as="compareUser"> + <td> + <f:render partial="BackendUser/Information" section="categories" arguments="{categories:compareUser.categories}"/> </td> </f:for> </tr> + <f:if condition="{compareUserList.0.workspaces}"> + <tr> + <th>Workspaces</th> + <f:for each="{compareUserList}" as="compareUser"> + <td> + <f:render partial="BackendUser/Information" section="workspaces" arguments="{workspaces:compareUser.workspaces}"/> + </td> + </f:for> + </tr> + </f:if> <tr> <th><f:translate key="disableIpLock" /></th> <f:for each="{compareUserList}" as="compareUser"> <td> - <f:if condition="{compareUser.ipLockIsDisabled} == 1"> - <f:then><f:translate key="yes" /></f:then> - <f:else><f:translate key="no" /></f:else> - </f:if> + <f:render partial="BackendUser/Information" section="yesno" arguments="{value:compareUser.user.disableIPlock}" /> </td> </f:for> </tr> diff --git a/typo3/sysext/beuser/Resources/Private/Templates/BackendUser/Show.html b/typo3/sysext/beuser/Resources/Private/Templates/BackendUser/Show.html new file mode 100644 index 0000000000000000000000000000000000000000..fe4e33b1000c9c3d52e739db7fe1296129d9fcf9 --- /dev/null +++ b/typo3/sysext/beuser/Resources/Private/Templates/BackendUser/Show.html @@ -0,0 +1,169 @@ +<html + xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" + xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers" + xmlns:be="http://typo3.org/ns/TYPO3/CMS/Backend/ViewHelpers" + xmlns:bu="http://typo3.org/ns/TYPO3/CMS/Beuser/ViewHelpers" + data-namespace-typo3-fluid="true"> + +<f:layout name="Default"/> + +<f:section name="Buttons"> + <be:moduleLayout.button.linkButton + icon="actions-add" + title="{f:translate(id: 'LLL:EXT:backend/Resources/Private/Language/locallang_layout.xlf:newRecordGeneral')}" + link="{be:uri.newRecord(table: 'be_users')}" + /> +</f:section> + +<f:section name="Content"> + <h1><f:translate key="backendUser" />: {data.user.username} [{data.user.uid}]</h1> + + <f:if condition="{data.user.description}"> + <f:be.infobox + title="{f:translate(key:'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.recordInformation')}"> + {data.user.description -> f:format.nl2br()} + </f:be.infobox> + </f:if> + + <table class="table table-striped table-bordered table-hover"> + <tr> + <th>{f:translate(key:'realName')}</th> + <td> + <a href="#" class="t3js-contextmenutrigger" data-table="be_users" data-uid="{data.user.uid}" title="id={data.user.uid}"> + <be:avatar backendUser="{data.user.uid}" showIcon="true"/> + </a> + {data.user.userName} + <be:link.editRecord class="btn btn-default pull-right" table="be_users" uid="{data.user.uid}" + title="edit"> + <core:icon identifier="actions-open"/> + </be:link.editRecord> + </td> + </tr> + <tr> + <th>{f:translate(key:'email')}</th> + <td> + <f:if condition="{data.user.email}"> + <f:link.email email="{data.user.email}"/> + </f:if> + </td> + </tr> + <tr> + <th>{f:translate(key:'startDateAndTime')}</th> + <td> + <f:if condition="{data.user.starttime}"> + <f:format.date format="{dateFormat} {timeFormat}">{data.user.starttime}</f:format.date> + </f:if> + </td> + </tr> + </table> + + <div class="row"> + <div class="col-md-4"> + <h4><f:translate key="groups" /></h4> + <f:render partial="BackendUser/Information" section="groups" arguments="{groups:data.groups}"/> + </div> + <div class="col-md-4"> + <h4><f:translate key="languages" /></h4> + <f:render partial="BackendUser/Information" section="languages" arguments="{languages:data.languages}"/> + </div> + <div class="col-md-4"> + + <h4><f:translate key="dbMounts" /></h4> + <f:render partial="BackendUser/Information" section="dbMounts" arguments="{dbMounts:data.dbMounts}"/> + + <h4><f:translate key="fileMounts" /></h4> + <f:render partial="BackendUser/Information" section="fileMounts" arguments="{fileMounts:data.fileMounts}"/> + + <h4><f:translate key="categories" /></h4> + <f:render partial="BackendUser/Information" section="categories" arguments="{categories:data.categories}"/> + </div> + </div> + + + <div class="row"> + <div class="col-md-6"> + <h2><f:translate key="permissions" /></h2> + <table class="table table-striped table-bordered table-hover"> + <thead> + <tr> + <th><f:translate key="modules" /></th> + </tr> + </thead> + <tbody> + <f:for each="{data.modules}" as="module"> + <tr> + <td> + <core:icon identifier="{module.iconIdentifier}"></core:icon> + {f:translate(key:'{module.labels}:mlang_tabs_tab')} <code>{module.name}</code> + </td> + </tr> + </f:for> + </tbody> + </table> + <table class="table table-striped table-bordered table-hover"> + <thead> + <tr> + <th><f:translate key="tableModes" /></th> + <th class="text-center"><f:translate key="tableModes.select" /></th> + <th class="text-center"><f:translate key="tableModes.modify" /></th> + </tr> + </thead> + <tbody> + <f:for each="{data.tables.all}" key="table" as="label"> + <tr> + <td> + <f:if condition="{label}"> + <f:then> + {f:translate(key:label)}<code>{table}</code> + </f:then> + <f:else> + <code>{table}</code> + </f:else> + </f:if> + </td> + <td class="text-center"> + <bu:display.tableAccess table="{table}" select="{data.tables.tables_select}"> + <f:then><span class="t3-icon change-permission fa fa-check text-success"></span> + </f:then> + <f:else><span class="t3-icon change-permission fa fa-times text-danger"></span></f:else> + </bu:display.tableAccess> + </td> + <td class="text-center"> + <bu:display.tableAccess table="{table}" select="{data.tables.tables_select}" + modify="{data.tables.tables_modify}"> + <f:then><span class="t3-icon change-permission fa fa-check text-success"></span> + </f:then> + <f:else><span class="t3-icon change-permission fa fa-times text-danger"></span></f:else> + </bu:display.tableAccess> + </td> + </tr> + </f:for> + </tbody> + </table> + </div> + <div class="col-md-6"> + <h3>ACL</h3> + <f:for each="{data.non_exclude_fields}" key="tableName" as="table"> + <table class="table table-striped table-bordered table-hover"> + <thead> + <tr> + <th>{f:translate(key:table.label)} <code>{tableName}</code></th> + </tr> + </thead> + <tbody> + <f:for each="{table.fields}" as="label" key="field"> + <tr> + <td> + {f:translate(key:label)} + <code>{field}</code> + </td> + </tr> + </f:for> + </tbody> + </table> + </f:for> + </div> + </div> +</f:section> + +</html> diff --git a/typo3/sysext/beuser/ext_tables.php b/typo3/sysext/beuser/ext_tables.php index ebffebde1d9cb0cf90d706c2d8d385283d813b09..b66597199104e6a00e3a2f12fb55f1a29b911ff4 100644 --- a/typo3/sysext/beuser/ext_tables.php +++ b/typo3/sysext/beuser/ext_tables.php @@ -8,7 +8,7 @@ defined('TYPO3_MODE') or die(); 'tx_Beuser', 'top', [ - \TYPO3\CMS\Beuser\Controller\BackendUserController::class => 'index, addToCompareList, removeFromCompareList, compare, online, terminateBackendUserSession', + \TYPO3\CMS\Beuser\Controller\BackendUserController::class => 'index, show, addToCompareList, removeFromCompareList, compare, online, terminateBackendUserSession', \TYPO3\CMS\Beuser\Controller\BackendUserGroupController::class => 'index' ], [ diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-90298-ImproveUserInfoInBeuserModule.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-90298-ImproveUserInfoInBeuserModule.rst new file mode 100644 index 0000000000000000000000000000000000000000..09b0b1bcf9cdb822fec15323395fbc15045c4fe2 --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/master/Feature-90298-ImproveUserInfoInBeuserModule.rst @@ -0,0 +1,27 @@ +.. include:: ../../Includes.txt + +===================================================== +Feature: #90298 - Improve user info in BE User module +===================================================== + +See :issue:`90298` + +Description +=========== + +The *Backend users* module has been improved by showing more details of TYPO3 +Administrators and Editors: + +- All assigned groups, including subgroups, are now evaluated +- All data which can be set in the backend user or a assigned group are now shown including allowed page types, read & write access to tables +- A new "detail view" for a TYPO3 Backend user has been added + + +Impact +====== + +Comparing users is more powerful now. It is now easier for TYPO3 Administrators +to check backend user permissions without the need to switch to the actual user +and test the behaviour. + +.. index:: Backend, ext:beuser