[TASK] Deprecate FrontendBackendUserAuthentication methods
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / FrontendBackendUserAuthentication.php
1 <?php
2 namespace TYPO3\CMS\Backend;
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\Context\Context;
20 use TYPO3\CMS\Core\Context\LanguageAspect;
21 use TYPO3\CMS\Core\Database\ConnectionPool;
22 use TYPO3\CMS\Core\Database\Query\QueryBuilder;
23 use TYPO3\CMS\Core\Database\Query\QueryHelper;
24 use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
25 use TYPO3\CMS\Core\Localization\LanguageService;
26 use TYPO3\CMS\Core\Type\Bitmask\Permission;
27 use TYPO3\CMS\Core\Utility\GeneralUtility;
28
29 /**
30 * TYPO3 backend user authentication in the TSFE frontend.
31 * This includes mainly functions related to the Admin Panel
32 */
33 class FrontendBackendUserAuthentication extends BackendUserAuthentication
34 {
35
36 /**
37 * Form field with login name.
38 *
39 * @var string
40 */
41 public $formfield_uname = '';
42
43 /**
44 * Form field with password.
45 *
46 * @var string
47 */
48 public $formfield_uident = '';
49
50 /**
51 * Formfield_status should be set to "". The value this->formfield_status is set to empty in order to
52 * disable login-attempts to the backend account through this script
53 *
54 * @var string
55 */
56 public $formfield_status = '';
57
58 /**
59 * Decides if the writelog() function is called at login and logout.
60 *
61 * @var bool
62 */
63 public $writeStdLog = false;
64
65 /**
66 * If the writelog() functions is called if a login-attempt has be tried without success.
67 *
68 * @var bool
69 */
70 public $writeAttemptLog = false;
71
72 /**
73 * General flag which is set if the adminpanel is enabled at all.
74 *
75 * @var bool
76 * @deprecated since TYPO3 v9, property will be removed in TYPO3 v10 - see extension "adminpanel" for new API
77 */
78 public $extAdmEnabled = false;
79
80 /**
81 * @var \TYPO3\CMS\Adminpanel\View\AdminPanelView Instance of admin panel
82 * @deprecated since TYPO3 v9, property will be removed in TYPO3 v10 - see extension "adminpanel" for new API
83 */
84 public $adminPanel;
85
86 /**
87 * @var \TYPO3\CMS\Core\FrontendEditing\FrontendEditingController
88 * @deprecated since TYPO3 v9, property will be removed in TYPO3 v10 - see extension "feedit" how the functionality could be used.
89 */
90 public $frontendEdit;
91
92 /**
93 * @var array
94 * @deprecated since TYPO3 v9, property will be removed in TYPO3 v10 - see extension "adminpanel" for new API
95 */
96 public $extAdminConfig = [];
97
98 /**
99 * Initializes the admin panel.
100 *
101 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0 - rewritten as middleware
102 */
103 public function initializeAdminPanel()
104 {
105 trigger_error('FrontendBackendUserAuthentication->initializeAdminPanel() will be removed in TYPO3 v10 - initialization is done via middleware.', E_USER_DEPRECATED);
106 }
107
108 /**
109 * Initializes frontend editing.
110 *
111 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0 - rewritten as middleware
112 */
113 public function initializeFrontendEdit()
114 {
115 trigger_error('FrontendBackendUserAuthentication->initializeFrontendEdit() will be removed in TYPO3 v10 - initialization is done via middleware.', E_USER_DEPRECATED);
116 }
117
118 /**
119 * Determines whether frontend editing is currently active.
120 *
121 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0 - see ext "feedit" for API
122 * @return bool Whether frontend editing is active
123 */
124 public function isFrontendEditingActive()
125 {
126 trigger_error('FrontendBackendUserAuthentication->isFrontendEditingActive() will be removed in TYPO3 v10 - use underlying TSFE directly.', E_USER_DEPRECATED);
127 return $this->extAdmEnabled && (
128 $this->adminPanel->isAdminModuleEnabled('edit') ||
129 (int)$GLOBALS['TSFE']->displayEditIcons === 1 ||
130 (int)$GLOBALS['TSFE']->displayFieldEditIcons === 1
131 );
132 }
133
134 /**
135 * Delegates to the appropriate view and renders the admin panel content.
136 *
137 * @deprecated since TYPO3 v9 - see ext "adminpanel" for new API
138 * @return string.
139 */
140 public function displayAdminPanel()
141 {
142 trigger_error('FrontendBackendUserAuthentication->displayAdminPanel() will be removed in TYPO3 v10 - use MainController of adminpanel extension.', E_USER_DEPRECATED);
143 return $this->adminPanel->display();
144 }
145
146 /**
147 * Determines whether the admin panel is enabled and visible.
148 *
149 * @deprecated since TYPO3 v9 - see ext "adminpanel" for new API
150 * @return bool true if the admin panel is enabled and visible
151 */
152 public function isAdminPanelVisible()
153 {
154 trigger_error('FrontendBackendUserAuthentication->isAdminPanelVisible() will be removed in TYPO3 v10 - use new adminpanel API instead.', E_USER_DEPRECATED);
155 return $this->extAdmEnabled && !$this->extAdminConfig['hide'] && $GLOBALS['TSFE']->config['config']['admPanel'];
156 }
157
158 /*****************************************************
159 *
160 * TSFE BE user Access Functions
161 *
162 ****************************************************/
163 /**
164 * Implementing the access checks that the TYPO3 CMS bootstrap script does before a user is ever logged in.
165 * Used in the frontend.
166 *
167 * @return bool Returns TRUE if access is OK
168 * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
169 */
170 public function checkBackendAccessSettingsFromInitPhp()
171 {
172 trigger_error('FrontendBackendUserAuthentication->checkBackendAccessSettingsFromInitPhp() will be removed in TYPO3 v10.0. Use a PSR-15 middleware and backendCheckLogin() instead.', E_USER_DEPRECATED);
173 // Check Hardcoded lock on BE
174 if ($GLOBALS['TYPO3_CONF_VARS']['BE']['adminOnly'] < 0) {
175 return false;
176 }
177 // Check IP
178 if (trim($GLOBALS['TYPO3_CONF_VARS']['BE']['IPmaskList'])) {
179 if (!GeneralUtility::cmpIP(GeneralUtility::getIndpEnv('REMOTE_ADDR'), $GLOBALS['TYPO3_CONF_VARS']['BE']['IPmaskList'])) {
180 return false;
181 }
182 }
183 // Check IP mask based on TSconfig
184 if (!$this->checkLockToIP()) {
185 return false;
186 }
187 // Check SSL (https)
188 if ((bool)$GLOBALS['TYPO3_CONF_VARS']['BE']['lockSSL'] && !GeneralUtility::getIndpEnv('TYPO3_SSL')) {
189 return false;
190 }
191 // Finally a check as in BackendUserAuthentication::backendCheckLogin()
192 return $this->isUserAllowedToLogin();
193 }
194
195 /**
196 * Implementing the access checks that the TYPO3 CMS bootstrap script does before a user is ever logged in.
197 * Used in the frontend.
198 *
199 * @param bool $proceedIfNoUserIsLoggedIn
200 * @return bool Returns TRUE if access is OK
201 */
202 public function backendCheckLogin($proceedIfNoUserIsLoggedIn = false)
203 {
204 if (empty($this->user['uid'])) {
205 return false;
206 }
207 // Check Hardcoded lock on BE
208 if ($GLOBALS['TYPO3_CONF_VARS']['BE']['adminOnly'] < 0) {
209 return false;
210 }
211 // Check IP mask based on TSconfig
212 if (!$this->checkLockToIP()) {
213 return false;
214 }
215 return $this->isUserAllowedToLogin();
216 }
217
218 /**
219 * Evaluates if the Backend User has read access to the input page record.
220 * The evaluation is based on both read-permission and whether the page is found in one of the users webmounts.
221 * Only if both conditions match, will the function return TRUE.
222 *
223 * Read access means that previewing is allowed etc.
224 *
225 * Used in \TYPO3\CMS\Frontend\Http\RequestHandler
226 *
227 * @param array $pageRec The page record to evaluate for
228 * @return bool TRUE if read access
229 * @deprecated since TYPO3 v9.5, will be removed in TYPO3 v10.0. Use underlying calls directly.
230 */
231 public function extPageReadAccess($pageRec)
232 {
233 trigger_error('FrontendBackendUserAuthentication->extPageReadAccess() will be removed in TYPO3 v10.0.', E_USER_DEPRECATED);
234 return $this->isInWebMount($pageRec['uid']) && $this->doesUserHaveAccess($pageRec, Permission::PAGE_SHOW);
235 }
236
237 /*****************************************************
238 *
239 * TSFE BE user Access Functions
240 *
241 ****************************************************/
242 /**
243 * Generates a list of Page-uid's from $id. List does not include $id itself
244 * The only pages excluded from the list are deleted pages.
245 *
246 * @param int $id Start page id
247 * @param int $depth Depth to traverse down the page tree.
248 * @param int $begin Is an optional integer that determines at which level in the tree to start collecting uid's. Zero means 'start right away', 1 = 'next level and out'
249 * @param string $perms_clause Perms clause
250 * @return string Returns the list with a comma in the end (if any pages selected!)
251 * @deprecated since TYPO3 v9.5, will be removed in TYPO3 v10.0.
252 */
253 public function extGetTreeList($id, $depth, $begin = 0, $perms_clause)
254 {
255 trigger_error('FrontendBackendUserAuthentication->extGetTreeList() will be removed in TYPO3 v10.0.', E_USER_DEPRECATED);
256 /** @var QueryBuilder $queryBuilder */
257 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
258 ->getQueryBuilderForTable('pages');
259
260 $queryBuilder->getRestrictions()
261 ->removeAll()
262 ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
263
264 $depth = (int)$depth;
265 $begin = (int)$begin;
266 $id = (int)$id;
267 $theList = '';
268 if ($id && $depth > 0) {
269 $result = $queryBuilder
270 ->select('uid', 'title')
271 ->from('pages')
272 ->where(
273 $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($id, \PDO::PARAM_INT)),
274 QueryHelper::stripLogicalOperatorPrefix($perms_clause)
275 )
276 ->execute();
277 while ($row = $result->fetch()) {
278 if ($begin <= 0) {
279 $theList .= $row['uid'] . ',';
280 }
281 if ($depth > 1) {
282 $theList .= $this->extGetTreeList($row['uid'], $depth - 1, $begin - 1, $perms_clause);
283 }
284 }
285 }
286 return $theList;
287 }
288
289 /**
290 * Edit Access
291 */
292
293 /**
294 * Checks whether the user has access to edit the language for the
295 * requested record.
296 *
297 * @param string $table The name of the table.
298 * @param array $currentRecord The record.
299 * @return bool
300 */
301 public function allowedToEditLanguage($table, array $currentRecord): bool
302 {
303 // If no access right to record languages, return immediately
304 /** @var LanguageAspect $languageAspect */
305 $languageAspect = GeneralUtility::makeInstance(Context::class)->getAspect('language');
306 if ($table === 'pages') {
307 $languageId = $languageAspect->getId();
308 } elseif ($table === 'tt_content') {
309 $languageId = $languageAspect->getContentId();
310 } elseif ($GLOBALS['TCA'][$table]['ctrl']['languageField']) {
311 $languageId = $currentRecord[$GLOBALS['TCA'][$table]['ctrl']['languageField']];
312 } else {
313 $languageId = -1;
314 }
315 return $this->checkLanguageAccess($languageId);
316 }
317
318 /**
319 * Checks whether the user is allowed to edit the requested table.
320 *
321 * @param string $table The name of the table.
322 * @param array $dataArray The data array.
323 * @param array $conf The configuration array for the edit panel.
324 * @param bool $checkEditAccessInternals Boolean indicating whether recordEditAccessInternals should not be checked. Defaults
325 * @return bool
326 */
327 public function allowedToEdit(string $table, array $dataArray, array $conf, bool $checkEditAccessInternals): bool
328 {
329 // Unless permissions specifically allow it, editing is not allowed.
330 $mayEdit = false;
331 if ($checkEditAccessInternals) {
332 $editAccessInternals = $this->recordEditAccessInternals($table, $dataArray, false, false);
333 } else {
334 $editAccessInternals = true;
335 }
336 if ($editAccessInternals) {
337 if ($table === 'pages') {
338 if ($this->isAdmin() || $this->doesUserHaveAccess($dataArray, Permission::PAGE_EDIT)) {
339 $mayEdit = true;
340 }
341 } else {
342 if ($this->isAdmin() || $this->doesUserHaveAccess(BackendUtility::getRecord('pages', $dataArray['pid']), Permission::CONTENT_EDIT)) {
343 $mayEdit = true;
344 }
345 }
346 if (!$conf['onlyCurrentPid'] || $dataArray['pid'] == $GLOBALS['TSFE']->id) {
347 // Permissions:
348 $perms = $this->calcPerms($GLOBALS['TSFE']->page);
349 if ($table === 'pages') {
350 $allow = $this->getAllowedEditActions($table, $conf, $dataArray['pid']);
351 // Can only display editbox if there are options in the menu
352 if (!empty($allow)) {
353 $mayEdit = true;
354 }
355 } else {
356 $types = GeneralUtility::trimExplode(',', strtolower($conf['allow']), true);
357 $allow = array_flip($types);
358 $mayEdit = !empty($allow) && $perms & Permission::CONTENT_EDIT;
359 }
360 }
361 }
362 return $mayEdit;
363 }
364
365 /**
366 * Takes an array of generally allowed actions and filters that list based on page and content permissions.
367 *
368 * @param string $table The name of the table.
369 * @param array $conf The configuration array.
370 * @param int $pid The PID where editing will occur.
371 * @return array
372 */
373 public function getAllowedEditActions($table, array $conf, $pid): array
374 {
375 $types = GeneralUtility::trimExplode(',', strtolower($conf['allow']), true);
376 $allow = array_flip($types);
377 if (!$conf['onlyCurrentPid'] || $pid == $GLOBALS['TSFE']->id) {
378 // Permissions
379 $types = GeneralUtility::trimExplode(',', strtolower($conf['allow']), true);
380 $allow = array_flip($types);
381 $perms = $this->calcPerms($GLOBALS['TSFE']->page);
382 if ($table === 'pages') {
383 // Rootpage
384 if (count($GLOBALS['TSFE']->config['rootLine']) === 1) {
385 unset($allow['move']);
386 unset($allow['hide']);
387 unset($allow['delete']);
388 }
389 if (!($perms & Permission::PAGE_EDIT) || !$this->checkLanguageAccess(0)) {
390 unset($allow['edit']);
391 unset($allow['move']);
392 unset($allow['hide']);
393 }
394 if (!($perms & Permission::PAGE_DELETE)) {
395 unset($allow['delete']);
396 }
397 if (!($perms & Permission::PAGE_NEW)) {
398 unset($allow['new']);
399 }
400 }
401 }
402 return $allow;
403 }
404
405 /*****************************************************
406 *
407 * Localization handling
408 *
409 ****************************************************/
410 /**
411 * Returns the label for key. If a translation for the language set in $this->uc['lang']
412 * is found that is returned, otherwise the default value.
413 * If the global variable $LOCAL_LANG is NOT an array (yet) then this function loads
414 * the global $LOCAL_LANG array with the content of "EXT:core/Resources/Private/Language/locallang_tsfe.xlf"
415 * such that the values therein can be used for labels in the Admin Panel
416 *
417 * @param string $key Key for a label in the $GLOBALS['LOCAL_LANG'] array of "EXT:core/Resources/Private/Language/locallang_tsfe.xlf
418 * @return string The value for the $key
419 * @deprecated since TYPO3 v9.5, will be removed in TYPO3 v10.0.
420 */
421 public function extGetLL($key)
422 {
423 trigger_error('FrontendBackendUserAuthentication->extGetLL() will be removed in TYPO3 v10.0.', E_USER_DEPRECATED);
424 if (!is_array($GLOBALS['LOCAL_LANG'])) {
425 $this->getLanguageService()->includeLLFile('EXT:core/Resources/Private/Language/locallang_tsfe.xlf');
426 if (!is_array($GLOBALS['LOCAL_LANG'])) {
427 $GLOBALS['LOCAL_LANG'] = [];
428 }
429 }
430 return htmlspecialchars($this->getLanguageService()->getLL($key));
431 }
432
433 /**
434 * @return LanguageService
435 */
436 protected function getLanguageService()
437 {
438 return $GLOBALS['LANG'];
439 }
440 }