10eba5b6f5e616b4c41ca3b628015d10f56bb2a8
[Packages/TYPO3.CMS.git] / typo3 / sysext / beuser / Classes / Controller / BackendUserController.php
1 <?php
2 namespace TYPO3\CMS\Beuser\Controller;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Backend\Utility\BackendUtility;
18 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
19 use TYPO3\CMS\Core\Localization\LanguageService;
20 use TYPO3\CMS\Core\Session\Backend\SessionBackendInterface;
21 use TYPO3\CMS\Core\Session\SessionManager;
22 use TYPO3\CMS\Core\Utility\GeneralUtility;
23 use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
24
25 /**
26 * Backend module user administration controller
27 */
28 class BackendUserController extends BackendUserActionController
29 {
30 /**
31 * @var int
32 */
33 const RECENT_USERS_LIMIT = 3;
34
35 /**
36 * @var \TYPO3\CMS\Beuser\Domain\Model\ModuleData
37 */
38 protected $moduleData;
39
40 /**
41 * @var \TYPO3\CMS\Beuser\Service\ModuleDataStorageService
42 */
43 protected $moduleDataStorageService;
44
45 /**
46 * @var \TYPO3\CMS\Beuser\Domain\Repository\BackendUserRepository
47 */
48 protected $backendUserRepository;
49
50 /**
51 * @var \TYPO3\CMS\Beuser\Domain\Repository\BackendUserGroupRepository
52 */
53 protected $backendUserGroupRepository;
54
55 /**
56 * @var \TYPO3\CMS\Beuser\Domain\Repository\BackendUserSessionRepository
57 */
58 protected $backendUserSessionRepository;
59
60 /**
61 * @param \TYPO3\CMS\Beuser\Service\ModuleDataStorageService $moduleDataStorageService
62 */
63 public function injectModuleDataStorageService(\TYPO3\CMS\Beuser\Service\ModuleDataStorageService $moduleDataStorageService)
64 {
65 $this->moduleDataStorageService = $moduleDataStorageService;
66 }
67
68 /**
69 * @param \TYPO3\CMS\Beuser\Domain\Repository\BackendUserRepository $backendUserRepository
70 */
71 public function injectBackendUserRepository(\TYPO3\CMS\Beuser\Domain\Repository\BackendUserRepository $backendUserRepository)
72 {
73 $this->backendUserRepository = $backendUserRepository;
74 }
75
76 /**
77 * @param \TYPO3\CMS\Beuser\Domain\Repository\BackendUserGroupRepository $backendUserGroupRepository
78 */
79 public function injectBackendUserGroupRepository(\TYPO3\CMS\Beuser\Domain\Repository\BackendUserGroupRepository $backendUserGroupRepository)
80 {
81 $this->backendUserGroupRepository = $backendUserGroupRepository;
82 }
83
84 /**
85 * @param \TYPO3\CMS\Beuser\Domain\Repository\BackendUserSessionRepository $backendUserSessionRepository
86 */
87 public function injectBackendUserSessionRepository(\TYPO3\CMS\Beuser\Domain\Repository\BackendUserSessionRepository $backendUserSessionRepository)
88 {
89 $this->backendUserSessionRepository = $backendUserSessionRepository;
90 }
91
92 /**
93 * Load and persist module data
94 *
95 * @param \TYPO3\CMS\Extbase\Mvc\RequestInterface $request
96 * @param \TYPO3\CMS\Extbase\Mvc\ResponseInterface $response
97 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException
98 */
99 public function processRequest(\TYPO3\CMS\Extbase\Mvc\RequestInterface $request, \TYPO3\CMS\Extbase\Mvc\ResponseInterface $response)
100 {
101 $this->moduleData = $this->moduleDataStorageService->loadModuleData();
102 // We "finally" persist the module data.
103 try {
104 parent::processRequest($request, $response);
105 $this->moduleDataStorageService->persistModuleData($this->moduleData);
106 } catch (\TYPO3\CMS\Extbase\Mvc\Exception\StopActionException $e) {
107 $this->moduleDataStorageService->persistModuleData($this->moduleData);
108 throw $e;
109 }
110 }
111
112 /**
113 * Initialize actions
114 *
115 * @throws \RuntimeException
116 */
117 public function initializeAction()
118 {
119 // @TODO: Extbase backend modules relies on frontend TypoScript for view, persistence
120 // and settings. Thus, we need a TypoScript root template, that then loads the
121 // ext_typoscript_setup.txt file of this module. This is nasty, but can not be
122 // circumvented until there is a better solution in extbase.
123 // For now we throw an exception if no settings are detected.
124 if (empty($this->settings)) {
125 throw new \RuntimeException('No settings detected. This module can not work then. This usually happens if there is no frontend TypoScript template with root flag set. ' . 'Please create a frontend page with a TypoScript root template.', 1344375003);
126 }
127 }
128
129 /**
130 * Displays all BackendUsers
131 * - Switch session to different user
132 *
133 * @param \TYPO3\CMS\Beuser\Domain\Model\Demand $demand
134 */
135 public function indexAction(\TYPO3\CMS\Beuser\Domain\Model\Demand $demand = null)
136 {
137 if ($demand === null) {
138 $demand = $this->moduleData->getDemand();
139 } else {
140 $this->moduleData->setDemand($demand);
141 }
142 // Switch user until logout
143 $switchUser = (int)GeneralUtility::_GP('SwitchUser');
144 if ($switchUser > 0) {
145 $this->switchUser($switchUser);
146 }
147 $compareUserList = $this->moduleData->getCompareUserList();
148
149 // Create online user list for easy parsing
150 $onlineUsers = $this->backendUserSessionRepository->findAllActive();
151 $onlineBackendUsers = [];
152 if (is_array($onlineUsers)) {
153 foreach ($onlineUsers as $onlineUser) {
154 $onlineBackendUsers[$onlineUser['ses_userid']] = true;
155 }
156 }
157 $this->view->assign('onlineBackendUsers', $onlineBackendUsers);
158
159 $this->view->assign('demand', $demand);
160 $this->view->assign('returnUrl', rawurlencode(BackendUtility::getModuleUrl('system_BeuserTxBeuser')));
161 $this->view->assign('dateFormat', $GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy']);
162 $this->view->assign('timeFormat', $GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm']);
163 $this->view->assign('backendUsers', $this->backendUserRepository->findDemanded($demand));
164 $this->view->assign('backendUserGroups', array_merge([''], $this->backendUserGroupRepository->findAll()->toArray()));
165 $this->view->assign('compareUserUidList', array_map(function ($item) {
166 return true;
167 }, array_flip((array)$compareUserList)));
168 $this->view->assign('compareUserList', !empty($compareUserList) ? $this->backendUserRepository->findByUidList($compareUserList) : '');
169 }
170
171 /**
172 * Views all currently logged in BackendUsers and their sessions
173 */
174 public function onlineAction()
175 {
176 $onlineUsersAndSessions = [];
177 $onlineUsers = $this->backendUserRepository->findOnline();
178 foreach ($onlineUsers as $onlineUser) {
179 $onlineUsersAndSessions[] = [
180 'backendUser' => $onlineUser,
181 'sessions' => $this->backendUserSessionRepository->findByBackendUser($onlineUser)
182 ];
183 }
184 $this->view->assign('dateFormat', $GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy']);
185 $this->view->assign('timeFormat', $GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm']);
186 $this->view->assign('onlineUsersAndSessions', $onlineUsersAndSessions);
187 $this->view->assign('currentSessionId', $this->getBackendUserAuthentication()->user['ses_id']);
188 }
189
190 /**
191 * Compare backend users from demand
192 */
193 public function compareAction()
194 {
195 $compareUserList = $this->moduleData->getCompareUserList();
196 $this->view->assign('dateFormat', $GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy']);
197 $this->view->assign('timeFormat', $GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm']);
198 $returnUrl = BackendUtility::getModuleUrl(
199 'system_BeuserTxBeuser',
200 [
201 'tx_beuser_system_beusertxbeuser[action]' => 'compare',
202 'tx_beuser_system_beusertxbeuser[controller]' => 'BackendUser'
203 ]
204 );
205 $this->view->assign('returnUrl', rawurlencode($returnUrl));
206 $this->view->assign('compareUserList', !empty($compareUserList) ? $this->backendUserRepository->findByUidList($compareUserList) : '');
207 }
208
209 /**
210 * Attaches one backend user to the compare list
211 *
212 * @param int $uid
213 */
214 public function addToCompareListAction($uid)
215 {
216 $this->moduleData->attachUidCompareUser($uid);
217 $this->moduleDataStorageService->persistModuleData($this->moduleData);
218 $this->forward('index');
219 }
220
221 /**
222 * Removes given backend user to the compare list
223 *
224 * @param int $uid
225 */
226 public function removeFromCompareListAction($uid)
227 {
228 $this->moduleData->detachUidCompareUser($uid);
229 $this->moduleDataStorageService->persistModuleData($this->moduleData);
230 $this->forward('index');
231 }
232
233 /**
234 * Terminate BackendUser session and logout corresponding client
235 * Redirects to onlineAction with message
236 *
237 * @param \TYPO3\CMS\Beuser\Domain\Model\BackendUser $backendUser
238 * @param string $sessionId
239 */
240 protected function terminateBackendUserSessionAction(\TYPO3\CMS\Beuser\Domain\Model\BackendUser $backendUser, $sessionId)
241 {
242 $sessionBackend = $this->getSessionBackend();
243 $success = $sessionBackend->remove($sessionId);
244
245 if ($success) {
246 $this->addFlashMessage(LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang.xlf:terminateSessionSuccess', 'beuser'));
247 }
248 $this->forward('online');
249 }
250
251 /**
252 * Switches to a given user (SU-mode) and then redirects to the start page of the backend to refresh the navigation etc.
253 *
254 * @param string $switchUser BE-user record that will be switched to
255 */
256 protected function switchUser($switchUser)
257 {
258 $targetUser = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecord('be_users', $switchUser);
259 if (is_array($targetUser) && $this->getBackendUserAuthentication()->isAdmin()) {
260 // Set backend user listing module as starting module for switchback
261 $this->getBackendUserAuthentication()->uc['startModuleOnFirstLogin'] = 'system_BeuserTxBeuser';
262 $this->getBackendUserAuthentication()->uc['recentSwitchedToUsers'] = $this->generateListOfMostRecentSwitchedUsers($targetUser['uid']);
263 $this->getBackendUserAuthentication()->writeUC();
264
265 $sessionBackend = $this->getSessionBackend();
266 $sessionBackend->update(
267 $this->getBackendUserAuthentication()->getSessionId(),
268 [
269 'ses_userid' => (int)$targetUser['uid'],
270 'ses_backuserid' => (int)$this->getBackendUserAuthentication()->user['uid']
271 ]
272 );
273
274 $redirectUrl = 'index.php' . ($GLOBALS['TYPO3_CONF_VARS']['BE']['interfaces'] ? '' : '?commandLI=1');
275 \TYPO3\CMS\Core\Utility\HttpUtility::redirect($redirectUrl);
276 }
277 }
278
279 /**
280 * Generates a list of users to whom where switched in the past. This is limited by RECENT_USERS_LIMIT.
281 *
282 * @param int $targetUserUid
283 * @return int[]
284 */
285 protected function generateListOfMostRecentSwitchedUsers(int $targetUserUid): array
286 {
287 $latestUserUids = [];
288 $backendUser = $this->getBackendUserAuthentication();
289
290 if (isset($backendUser->uc['recentSwitchedToUsers']) && is_array($backendUser->uc['recentSwitchedToUsers'])) {
291 $latestUserUids = $backendUser->uc['recentSwitchedToUsers'];
292 }
293
294 // Remove potentially existing user in that list
295 $index = array_search($targetUserUid, $latestUserUids, true);
296 if ($index !== false) {
297 unset($latestUserUids[$index]);
298 }
299
300 array_unshift($latestUserUids, $targetUserUid);
301 $latestUserUids = array_slice($latestUserUids, 0, static::RECENT_USERS_LIMIT);
302
303 return $latestUserUids;
304 }
305
306 /**
307 * @return BackendUserAuthentication
308 */
309 protected function getBackendUserAuthentication()
310 {
311 return $GLOBALS['BE_USER'];
312 }
313
314 /**
315 * @return LanguageService
316 */
317 protected function getLanguageService()
318 {
319 return $GLOBALS['LANG'];
320 }
321
322 /**
323 * @return SessionBackendInterface
324 */
325 protected function getSessionBackend()
326 {
327 $loginType = $this->getBackendUserAuthentication()->getLoginType();
328 return GeneralUtility::makeInstance(SessionManager::class)->getSessionBackend($loginType);
329 }
330 }