2a8489036903f9c9d71e59d22f1ec842e0ac9844
[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\Core\Authentication\BackendUserAuthentication;
18 use TYPO3\CMS\Core\Session\Backend\SessionBackendInterface;
19 use TYPO3\CMS\Core\Session\SessionManager;
20 use TYPO3\CMS\Core\Utility\GeneralUtility;
21 use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
22 use TYPO3\CMS\Extbase\Mvc\View\ViewInterface;
23 use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
24
25 /**
26 * Backend module user administration controller
27 */
28 class BackendUserController extends ActionController
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 * Assign default variables to view
114 */
115 public function initializeView(ViewInterface $view)
116 {
117 $view->assignMultiple([
118 'shortcutLabel' => 'backendUsers',
119 'dateFormat' => $GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'],
120 'timeFormat' => $GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm'],
121 ]);
122 }
123
124 /**
125 * Displays all BackendUsers
126 * - Switch session to different user
127 *
128 * @param \TYPO3\CMS\Beuser\Domain\Model\Demand $demand
129 */
130 public function indexAction(\TYPO3\CMS\Beuser\Domain\Model\Demand $demand = null)
131 {
132 if ($demand === null) {
133 $demand = $this->moduleData->getDemand();
134 } else {
135 $this->moduleData->setDemand($demand);
136 }
137 // Switch user until logout
138 $switchUser = (int)GeneralUtility::_GP('SwitchUser');
139 if ($switchUser > 0) {
140 $this->switchUser($switchUser);
141 }
142 $compareUserList = $this->moduleData->getCompareUserList();
143
144 // Create online user list for easy parsing
145 $onlineUsers = $this->backendUserSessionRepository->findAllActive();
146 $onlineBackendUsers = [];
147 if (is_array($onlineUsers)) {
148 foreach ($onlineUsers as $onlineUser) {
149 $onlineBackendUsers[$onlineUser['ses_userid']] = true;
150 }
151 }
152
153 $this->view->assignMultiple([
154 'onlineBackendUsers' => $onlineBackendUsers,
155 'demand' => $demand,
156 'backendUsers' => $this->backendUserRepository->findDemanded($demand),
157 'backendUserGroups' => array_merge([''], $this->backendUserGroupRepository->findAll()->toArray()),
158 'compareUserUidList' => array_combine(array_keys($compareUserList), array_fill(0, count($compareUserList), true)),
159 'currentUserUid' => $this->getBackendUserAuthentication()->user['uid'],
160 'compareUserList' => !empty($compareUserList) ? $this->backendUserRepository->findByUidList($compareUserList) : '',
161 ]);
162 }
163
164 /**
165 * Views all currently logged in BackendUsers and their sessions
166 */
167 public function onlineAction()
168 {
169 $onlineUsersAndSessions = [];
170 $onlineUsers = $this->backendUserRepository->findOnline();
171 foreach ($onlineUsers as $onlineUser) {
172 $onlineUsersAndSessions[] = [
173 'backendUser' => $onlineUser,
174 'sessions' => $this->backendUserSessionRepository->findByBackendUser($onlineUser)
175 ];
176 }
177
178 $this->view->assignMultiple([
179 'shortcutLabel' => 'onlineUsers',
180 'onlineUsersAndSessions' => $onlineUsersAndSessions,
181 'currentSessionId' => $this->getBackendUserAuthentication()->user['ses_id'],
182 ]);
183 }
184
185 /**
186 * Compare backend users from demand
187 */
188 public function compareAction()
189 {
190 $compareUserList = $this->moduleData->getCompareUserList();
191 if (empty($compareUserList)) {
192 $this->redirect('index');
193 }
194
195 $this->view->assignMultiple([
196 'shortcutLabel' => 'compareUsers',
197 'compareUserList' => $this->backendUserRepository->findByUidList($compareUserList),
198 ]);
199 }
200
201 /**
202 * Attaches one backend user to the compare list
203 *
204 * @param int $uid
205 */
206 public function addToCompareListAction($uid)
207 {
208 $this->moduleData->attachUidCompareUser($uid);
209 $this->moduleDataStorageService->persistModuleData($this->moduleData);
210 $this->forward('index');
211 }
212
213 /**
214 * Removes given backend user to the compare list
215 *
216 * @param int $uid
217 */
218 public function removeFromCompareListAction($uid)
219 {
220 $this->moduleData->detachUidCompareUser($uid);
221 $this->moduleDataStorageService->persistModuleData($this->moduleData);
222 $this->forward('index');
223 }
224
225 /**
226 * Terminate BackendUser session and logout corresponding client
227 * Redirects to onlineAction with message
228 *
229 * @param \TYPO3\CMS\Beuser\Domain\Model\BackendUser $backendUser
230 * @param string $sessionId
231 */
232 protected function terminateBackendUserSessionAction(\TYPO3\CMS\Beuser\Domain\Model\BackendUser $backendUser, $sessionId)
233 {
234 $sessionBackend = $this->getSessionBackend();
235 $success = $sessionBackend->remove($sessionId);
236
237 if ($success) {
238 $this->addFlashMessage(LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang.xlf:terminateSessionSuccess', 'beuser'));
239 }
240 $this->forward('online');
241 }
242
243 /**
244 * Switches to a given user (SU-mode) and then redirects to the start page of the backend to refresh the navigation etc.
245 *
246 * @param string $switchUser BE-user record that will be switched to
247 */
248 protected function switchUser($switchUser)
249 {
250 $targetUser = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecord('be_users', $switchUser);
251 if (is_array($targetUser) && $this->getBackendUserAuthentication()->isAdmin()) {
252 // Set backend user listing module as starting module for switchback
253 $this->getBackendUserAuthentication()->uc['startModuleOnFirstLogin'] = 'system_BeuserTxBeuser';
254 $this->getBackendUserAuthentication()->uc['recentSwitchedToUsers'] = $this->generateListOfMostRecentSwitchedUsers($targetUser['uid']);
255 $this->getBackendUserAuthentication()->writeUC();
256
257 $sessionBackend = $this->getSessionBackend();
258 $sessionBackend->update(
259 $this->getBackendUserAuthentication()->getSessionId(),
260 [
261 'ses_userid' => (int)$targetUser['uid'],
262 'ses_backuserid' => (int)$this->getBackendUserAuthentication()->user['uid']
263 ]
264 );
265
266 $this->emitSwitchUserSignal($targetUser);
267
268 $redirectUrl = 'index.php' . ($GLOBALS['TYPO3_CONF_VARS']['BE']['interfaces'] ? '' : '?commandLI=1');
269 \TYPO3\CMS\Core\Utility\HttpUtility::redirect($redirectUrl);
270 }
271 }
272
273 /**
274 * Generates a list of users to whom where switched in the past. This is limited by RECENT_USERS_LIMIT.
275 *
276 * @param int $targetUserUid
277 * @return int[]
278 */
279 protected function generateListOfMostRecentSwitchedUsers(int $targetUserUid): array
280 {
281 $latestUserUids = [];
282 $backendUser = $this->getBackendUserAuthentication();
283
284 if (isset($backendUser->uc['recentSwitchedToUsers']) && is_array($backendUser->uc['recentSwitchedToUsers'])) {
285 $latestUserUids = $backendUser->uc['recentSwitchedToUsers'];
286 }
287
288 // Remove potentially existing user in that list
289 $index = array_search($targetUserUid, $latestUserUids, true);
290 if ($index !== false) {
291 unset($latestUserUids[$index]);
292 }
293
294 array_unshift($latestUserUids, $targetUserUid);
295 $latestUserUids = array_slice($latestUserUids, 0, static::RECENT_USERS_LIMIT);
296
297 return $latestUserUids;
298 }
299
300 /**
301 * Emit a signal when using the "switch to user" functionality
302 *
303 * @param array $targetUser
304 */
305 protected function emitSwitchUserSignal(array $targetUser)
306 {
307 $this->signalSlotDispatcher->dispatch(__CLASS__, 'switchUser', [$targetUser]);
308 }
309
310 /**
311 * @return BackendUserAuthentication
312 */
313 protected function getBackendUserAuthentication(): BackendUserAuthentication
314 {
315 return $GLOBALS['BE_USER'];
316 }
317
318 /**
319 * @return SessionBackendInterface
320 */
321 protected function getSessionBackend()
322 {
323 $loginType = $this->getBackendUserAuthentication()->getLoginType();
324 return GeneralUtility::makeInstance(SessionManager::class)->getSessionBackend($loginType);
325 }
326 }