‪TYPO3CMS  ‪main
BackendUserAuthentication.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
17 
18 use Psr\EventDispatcher\EventDispatcherInterface;
19 use Psr\Http\Message\ServerRequestInterface;
20 use TYPO3\CMS\Backend\Utility\BackendUtility;
35 use TYPO3\CMS\Core\Package\PackageManager;
41 use ‪TYPO3\CMS\Core\SysLog\Error as SystemLogErrorClassification;
43 use ‪TYPO3\CMS\Core\SysLog\Type as SystemLogType;
52 use TYPO3\CMS\Install\Service\SessionService;
53 
62 {
63  public const ‪ROLE_SYSTEMMAINTAINER = 'systemMaintainer';
64 
69  public ‪$usergroup_column = 'usergroup';
70 
75  public ‪$usergroup_table = 'be_groups';
76 
82  public ‪$groupData = [
83  'allowed_languages' => '',
84  'tables_select' => '',
85  'tables_modify' => '',
86  'pagetypes_select' => '',
87  'non_exclude_fields' => '',
88  'explicit_allowdeny' => '',
89  'custom_options' => '',
90  'file_permissions' => '',
91  ];
92 
97  public ‪$userGroupsUID = [];
98 
105  public int ‪$workspace = -99;
106 
111  public ‪$workspaceRec = [];
112 
113  protected ?‪UserTsConfig ‪$userTsConfig = null;
114 
119  protected bool ‪$userTSUpdated = false;
120 
126  public ‪$errorMsg = '';
127 
133 
137  protected ‪$fileStorages;
138 
142  protected ‪$filePermissions;
143 
148  public ‪$user_table = 'be_users';
149 
154  public ‪$username_column = 'username';
155 
160  public ‪$userident_column = 'password';
161 
166  public ‪$userid_column = 'uid';
167 
171  public ‪$lastLogin_column = 'lastlogin';
172 
177  public ‪$enablecolumns = [
178  'rootLevel' => 1,
179  'deleted' => 'deleted',
180  'disabled' => 'disable',
181  'starttime' => 'starttime',
182  'endtime' => 'endtime',
183  ];
184 
190  protected ‪$formfield_uname = 'username';
191 
197  protected ‪$formfield_uident = 'userident';
198 
204  protected ‪$formfield_status = 'login_status';
205 
210  public ‪$writeStdLog = true;
211 
216  public ‪$writeAttemptLog = true;
217 
222  public ‪$firstMainGroup = 0;
223 
234  public ‪$uc_default = [
235  // serialized content that is used to store interface pane and menu positions. Set by the logout.php-script
236  'moduleData' => [],
237  // user-data for the modules
238  'emailMeAtLogin' => 0,
239  'titleLen' => 50,
240  'edit_docModuleUpload' => '1',
241  ];
242 
247  public ‪$loginType = 'BE';
248 
252  public function ‪__construct()
253  {
254  $this->name = ‪self::getCookieName();
255  parent::__construct();
256  }
257 
264  public function ‪isAdmin()
265  {
266  return is_array($this->user) && (($this->user['admin'] ?? 0) & 1) == 1;
267  }
268 
276  protected function ‪isMemberOfGroup(int $groupId): bool
277  {
278  if (!empty($this->userGroupsUID) && $groupId) {
279  return in_array($groupId, $this->userGroupsUID, true);
280  }
281  return false;
282  }
283 
299  public function ‪doesUserHaveAccess($row, $perms)
300  {
301  $userPerms = $this->‪calcPerms($row);
302  return ($userPerms & $perms) == $perms;
303  }
304 
319  public function ‪isInWebMount($idOrRow, $readPerms = '')
320  {
321  if ($this->‪isAdmin()) {
322  return 1;
323  }
324  $checkRec = [];
325  $fetchPageFromDatabase = true;
326  if (is_array($idOrRow)) {
327  if (!isset($idOrRow['uid'])) {
328  throw new \RuntimeException('The given page record is invalid. Missing uid.', 1578950324);
329  }
330  $checkRec = $idOrRow;
331  $id = (int)$idOrRow['uid'];
332  // ensure the required fields are present on the record
333  if (isset($checkRec['t3ver_oid'], $checkRec[‪$GLOBALS['TCA']['pages']['ctrl']['languageField']], $checkRec[‪$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField']])) {
334  $fetchPageFromDatabase = false;
335  }
336  } else {
337  $id = (int)$idOrRow;
338  }
339  if ($fetchPageFromDatabase) {
340  // Check if input id is an offline version page in which case we will map id to the online version:
341  $checkRec = BackendUtility::getRecord(
342  'pages',
343  $id,
344  't3ver_oid,'
345  . ‪$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'] . ','
346  . ‪$GLOBALS['TCA']['pages']['ctrl']['languageField']
347  );
348  }
349  if ((int)($checkRec['t3ver_oid'] ?? 0) > 0) {
350  $id = (int)$checkRec['t3ver_oid'];
351  }
352  // if current rec is a translation then get uid from l10n_parent instead
353  // because web mounts point to pages in default language and rootline returns uids of default languages
354  if ((int)($checkRec[‪$GLOBALS['TCA']['pages']['ctrl']['languageField'] ?? null] ?? 0) !== 0
355  && (int)($checkRec[‪$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'] ?? null] ?? 0) !== 0
356  ) {
357  $id = (int)$checkRec[‪$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField']];
358  }
359  if (!$readPerms) {
360  $readPerms = $this->‪getPagePermsClause(‪Permission::PAGE_SHOW);
361  }
362  if ($id > 0) {
363  $wM = $this->‪returnWebmounts();
364  $rL = BackendUtility::BEgetRootLine($id, ' AND ' . $readPerms, true);
365  foreach ($rL as $v) {
366  if ($v['uid'] && in_array($v['uid'], $wM)) {
367  return $v['uid'];
368  }
369  }
370  }
371  return null;
372  }
373 
381  public function ‪isSystemMaintainer(bool $pure = false): bool
382  {
383  if (!$this->‪isAdmin()) {
384  return false;
385  }
386 
387  if (!$pure && ‪$GLOBALS['BE_USER']->‪getOriginalUserIdWhenInSwitchUserMode()) {
388  return false;
389  }
390  if (!$pure && ‪Environment::getContext()->isDevelopment()) {
391  return true;
392  }
393  $systemMaintainers = ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['systemMaintainers'] ?? [];
394  $systemMaintainers = array_map(intval(...), $systemMaintainers);
395  if (!empty($systemMaintainers)) {
396  return in_array((int)$this->user['uid'], $systemMaintainers, true);
397  }
398  // No system maintainers set up yet, so any admin is allowed to access the modules
399  // but explicitly no system maintainers allowed (empty string in TYPO3_CONF_VARS).
400  // @todo: this needs to be adjusted once system maintainers can log into the install tool with their credentials
401  if (!$pure && !isset(‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['systemMaintainers'])) {
402  return true;
403  }
404  return false;
405  }
406 
423  public function ‪getPagePermsClause($perms)
424  {
425  if (is_array($this->user)) {
426  if ($this->‪isAdmin()) {
427  return ' 1=1';
428  }
429  // Make sure it's integer.
430  $perms = (int)$perms;
431  $expressionBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
432  ->getQueryBuilderForTable('pages')
433  ->expr();
434 
435  // User
436  $constraint = $expressionBuilder->or(
437  $expressionBuilder->comparison(
438  $expressionBuilder->bitAnd('pages.perms_everybody', $perms),
439  ExpressionBuilder::EQ,
440  $perms
441  ),
442  $expressionBuilder->and(
443  $expressionBuilder->eq('pages.perms_userid', (int)$this->user['uid']),
444  $expressionBuilder->comparison(
445  $expressionBuilder->bitAnd('pages.perms_user', $perms),
446  ExpressionBuilder::EQ,
447  $perms
448  )
449  )
450  );
451 
452  // Group (if any is set)
453  if (!empty($this->userGroupsUID)) {
454  $constraint = $constraint->with(
455  $expressionBuilder->and(
456  $expressionBuilder->in(
457  'pages.perms_groupid',
458  $this->userGroupsUID
459  ),
460  $expressionBuilder->comparison(
461  $expressionBuilder->bitAnd('pages.perms_group', $perms),
462  ExpressionBuilder::EQ,
463  $perms
464  )
465  )
466  );
467  }
468 
469  $constraint = ' (' . (string)$constraint . ')';
470 
471  // ****************
472  // getPagePermsClause-HOOK
473  // ****************
474  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauthgroup.php']['getPagePermsClause'] ?? [] as $_funcRef) {
475  $_params = ['currentClause' => $constraint, 'perms' => $perms];
476  $constraint = GeneralUtility::callUserFunction($_funcRef, $_params, $this);
477  }
478  return $constraint;
479  }
480  return ' 1=0';
481  }
482 
492  public function ‪calcPerms($row)
493  {
494  // Return 31 for admin users.
495  if ($this->‪isAdmin()) {
496  return ‪Permission::ALL;
497  }
498  // Return 0 if page is not within the allowed web mount
499  if (!$this->‪isInWebMount($row)) {
500  return ‪Permission::NOTHING;
501  }
502  $out = ‪Permission::NOTHING;
503  if (
504  isset($row['perms_userid']) && isset($row['perms_user']) && isset($row['perms_groupid'])
505  && isset($row['perms_group']) && isset($row['perms_everybody']) && !empty($this->userGroupsUID)
506  ) {
507  if ($this->user['uid'] == $row['perms_userid']) {
508  $out |= $row['perms_user'];
509  }
510  if ($this->‪isMemberOfGroup((int)$row['perms_groupid'])) {
511  $out |= $row['perms_group'];
512  }
513  $out |= $row['perms_everybody'];
514  }
515  // ****************
516  // CALCPERMS hook
517  // ****************
518  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauthgroup.php']['calcPerms'] ?? [] as $_funcRef) {
519  $_params = [
520  'row' => $row,
521  'outputPermissions' => $out,
522  ];
523  $out = GeneralUtility::callUserFunction($_funcRef, $_params, $this);
524  }
525  return $out;
526  }
527 
537  public function ‪check($type, $value)
538  {
539  return isset($this->groupData[$type])
540  && ($this->‪isAdmin() || ‪GeneralUtility::inList($this->groupData[$type], (string)$value));
541  }
542 
551  public function ‪checkAuthMode($table, $field, $value)
552  {
553  // Admin users can do anything:
554  if ($this->‪isAdmin()) {
555  return true;
556  }
557  // Allow all blank values:
558  if ((string)$value === '') {
559  return true;
560  }
561  // Allow dividers:
562  if ($value === '--div--') {
563  return true;
564  }
565  // Certain characters are not allowed in the value
566  if (preg_match('/[:|,]/', $value)) {
567  return false;
568  }
569  // Initialize:
570  $testValue = $table . ':' . $field . ':' . $value;
571  $out = true;
572  if (!‪GeneralUtility::inList($this->groupData['explicit_allowdeny'], $testValue)) {
573  $out = false;
574  }
575  return $out;
576  }
577 
584  public function ‪checkLanguageAccess($langValue)
585  {
586  // The users language list must be non-blank - otherwise all languages are allowed.
587  if (trim($this->groupData['allowed_languages']) === '') {
588  return true;
589  }
590  if ($langValue instanceof ‪SiteLanguage) {
591  $langValue = $langValue->getLanguageId();
592  } else {
593  $langValue = (int)$langValue;
594  }
595  // Language must either be explicitly allowed OR the lang Value be "-1" (all languages)
596  if ($langValue !== -1 && !$this->‪check('allowed_languages', (string)$langValue)) {
597  return false;
598  }
599  return true;
600  }
601 
609  public function ‪checkFullLanguagesAccess($table, ‪$record)
610  {
611  if (!$this->‪checkLanguageAccess(0)) {
612  return false;
613  }
614 
615  if (BackendUtility::isTableLocalizable($table)) {
616  $pointerField = ‪$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'];
617  $pointerValue = ‪$record[$pointerField] > 0 ? ‪$record[$pointerField] : ‪$record['uid'];
618  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
619  $queryBuilder->getRestrictions()
620  ->removeAll()
621  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
622  ->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, $this->workspace));
623  $recordLocalizations = $queryBuilder->select('*')
624  ->from($table)
625  ->where(
626  $queryBuilder->expr()->eq(
627  $pointerField,
628  $queryBuilder->createNamedParameter($pointerValue, ‪Connection::PARAM_INT)
629  )
630  )
631  ->executeQuery()
632  ->fetchAllAssociative();
633 
634  foreach ($recordLocalizations as $recordLocalization) {
635  if (!$this->‪checkLanguageAccess($recordLocalization[‪$GLOBALS['TCA'][$table]['ctrl']['languageField']])) {
636  return false;
637  }
638  }
639  }
640  return true;
641  }
642 
659  public function ‪recordEditAccessInternals($table, $idOrRow, $newRecord = false, $deletedRecord = false, $checkFullLanguageAccess = false): bool
660  {
661  if (!isset(‪$GLOBALS['TCA'][$table])) {
662  return false;
663  }
664  // Always return TRUE for Admin users.
665  if ($this->‪isAdmin()) {
666  return true;
667  }
668  // Fetching the record if the $idOrRow variable was not an array on input:
669  if (!is_array($idOrRow)) {
670  if ($deletedRecord) {
671  $idOrRow = BackendUtility::getRecord($table, $idOrRow, '*', '', false);
672  } else {
673  $idOrRow = BackendUtility::getRecord($table, $idOrRow);
674  }
675  if (!is_array($idOrRow)) {
676  $this->errorMsg = 'ERROR: Record could not be fetched.';
677  return false;
678  }
679  }
680  // Checking languages:
681  if ($table === 'pages' && $checkFullLanguageAccess && !$this->‪checkFullLanguagesAccess($table, $idOrRow)) {
682  return false;
683  }
684  if (‪$GLOBALS['TCA'][$table]['ctrl']['languageField'] ?? false) {
685  // Language field must be found in input row - otherwise it does not make sense.
686  if (isset($idOrRow[‪$GLOBALS['TCA'][$table]['ctrl']['languageField']])) {
687  if (!$this->‪checkLanguageAccess($idOrRow[‪$GLOBALS['TCA'][$table]['ctrl']['languageField']])) {
688  $this->errorMsg = 'ERROR: Language was not allowed.';
689  return false;
690  }
691  if (
692  $checkFullLanguageAccess && $idOrRow[‪$GLOBALS['TCA'][$table]['ctrl']['languageField']] == 0
693  && !$this->‪checkFullLanguagesAccess($table, $idOrRow)
694  ) {
695  $this->errorMsg = 'ERROR: Related/affected language was not allowed.';
696  return false;
697  }
698  } else {
699  $this->errorMsg = 'ERROR: The "languageField" field named "'
700  . ‪$GLOBALS['TCA'][$table]['ctrl']['languageField'] . '" was not found in testing record!';
701  return false;
702  }
703  }
704  // Checking authMode fields:
705  if (is_array(‪$GLOBALS['TCA'][$table]['columns'])) {
706  foreach (‪$GLOBALS['TCA'][$table]['columns'] as $fieldName => $fieldValue) {
707  if (isset($idOrRow[$fieldName])
708  && ($fieldValue['config']['type'] ?? '') === 'select'
709  && ($fieldValue['config']['authMode'] ?? false)
710  && !$this->‪checkAuthMode($table, $fieldName, $idOrRow[$fieldName])) {
711  $this->errorMsg = 'ERROR: authMode "' . $fieldValue['config']['authMode']
712  . '" failed for field "' . $fieldName . '" with value "'
713  . $idOrRow[$fieldName] . '" evaluated';
714  return false;
715  }
716  }
717  }
718  // Checking "editlock" feature (doesn't apply to new records)
719  if (!$newRecord && (‪$GLOBALS['TCA'][$table]['ctrl']['editlock'] ?? false)) {
720  if (isset($idOrRow[‪$GLOBALS['TCA'][$table]['ctrl']['editlock']])) {
721  if ($idOrRow[‪$GLOBALS['TCA'][$table]['ctrl']['editlock']]) {
722  $this->errorMsg = 'ERROR: Record was locked for editing. Only admin users can change this state.';
723  return false;
724  }
725  } else {
726  $this->errorMsg = 'ERROR: The "editLock" field named "' . ‪$GLOBALS['TCA'][$table]['ctrl']['editlock']
727  . '" was not found in testing record!';
728  return false;
729  }
730  }
731  // Checking record permissions
732  // THIS is where we can include a check for "perms_" fields for other records than pages...
733  // Process any hooks
734  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauthgroup.php']['recordEditAccessInternals'] ?? [] as $funcRef) {
735  $params = [
736  'table' => $table,
737  'idOrRow' => $idOrRow,
738  'newRecord' => $newRecord,
739  ];
740  if (!GeneralUtility::callUserFunction($funcRef, $params, $this)) {
741  return false;
742  }
743  }
744  // Finally, return TRUE if all is well.
745  return true;
746  }
747 
753  public function ‪mayMakeShortcut()
754  {
755  return ($this->‪getTSConfig()['options.']['enableBookmarks'] ?? false)
756  && !($this->‪getTSConfig()['options.']['mayNotCreateEditBookmarks'] ?? false);
757  }
758 
766  public function ‪workspaceAllowsLiveEditingInTable(string $table): bool
767  {
768  // In live workspace the record can be added/modified
769  if ($this->workspace === 0) {
770  return true;
771  }
772  // Workspace setting allows to "live edit" records of tables without versioning
773  if (($this->workspaceRec['live_edit'] ?? false)
774  && !BackendUtility::isTableWorkspaceEnabled($table)
775  ) {
776  return true;
777  }
778  // Always for Live workspace AND if live-edit is enabled
779  // and tables are completely without versioning it is ok as well.
780  if (‪$GLOBALS['TCA'][$table]['ctrl']['versioningWS_alwaysAllowLiveEdit'] ?? false) {
781  return true;
782  }
783  // If the answer is FALSE it means the only valid way to create or edit records by creating records in the workspace
784  return false;
785  }
786 
795  public function ‪workspaceCanCreateNewRecord(string $table): bool
796  {
797  // If LIVE records cannot be created due to workspace restrictions, prepare creation of placeholder-record
798  if (!$this->‪workspaceAllowsLiveEditingInTable($table) && !BackendUtility::isTableWorkspaceEnabled($table)) {
799  return false;
800  }
801  return true;
802  }
803 
814  public function ‪workspaceCheckStageForCurrent($stage)
815  {
816  // Always allow for admins
817  if ($this->‪isAdmin()) {
818  return true;
819  }
820  // Always OK for live workspace
821  if ($this->workspace === 0 || !‪ExtensionManagementUtility::isLoaded('workspaces')) {
822  return true;
823  }
824  $stage = (int)$stage;
825  $stat = $this->‪checkWorkspaceCurrent();
826  $accessType = $stat['_ACCESS'];
827  // Workspace owners are always allowed for stage change
828  if ($accessType === 'owner') {
829  return true;
830  }
831 
832  // Check if custom staging is activated
833  ‪$workspaceRec = BackendUtility::getRecord('sys_workspace', $stat['uid']);
834  if (‪$workspaceRec['custom_stages'] > 0 && $stage !== 0 && $stage !== -10) {
835  // Get custom stage record
836  $workspaceStageRec = BackendUtility::getRecord('sys_workspace_stage', $stage);
837  // Check if the user is responsible for the current stage
838  if (
839  $accessType === 'member'
840  && ‪GeneralUtility::inList($workspaceStageRec['responsible_persons'] ?? '', 'be_users_' . $this->user['uid'])
841  ) {
842  return true;
843  }
844  // Check if the user is in a group which is responsible for the current stage
845  foreach ($this->userGroupsUID as $groupUid) {
846  if (
847  $accessType === 'member'
848  && ‪GeneralUtility::inList($workspaceStageRec['responsible_persons'] ?? '', 'be_groups_' . $groupUid)
849  ) {
850  return true;
851  }
852  }
853  } elseif ($stage === -10 || $stage === -20) {
854  // Nobody is allowed to do that except the owner (which was checked above)
855  return false;
856  } elseif (
857  $accessType === 'reviewer' && $stage <= 1
858  || $accessType === 'member' && $stage <= 0
859  ) {
860  return true;
861  }
862  return false;
863  }
864 
880  public function ‪getTSConfig(): array
881  {
882  return $this->‪getUserTsConfig()?->getUserTsConfigArray() ?? [];
883  }
884 
891  {
892  return ‪$this->userTsConfig;
893  }
894 
902  public function ‪returnWebmounts()
903  {
904  return (string)$this->groupData['webmounts'] != '' ? explode(',', $this->groupData['webmounts']) : [];
905  }
906 
913  public function ‪setWebmounts(array $mountPointUids, $append = false)
914  {
915  if (empty($mountPointUids)) {
916  return;
917  }
918  if ($append) {
919  $currentWebMounts = ‪GeneralUtility::intExplode(',', (string)($this->groupData['webmounts'] ?? ''));
920  $mountPointUids = array_merge($currentWebMounts, $mountPointUids);
921  }
922  $this->groupData['webmounts'] = implode(',', array_unique($mountPointUids));
923  }
924 
937  {
938  $alternativeWebmountPoint = (int)$this->‪getSessionData('pageTree_temporaryMountPoint');
939  if ($alternativeWebmountPoint) {
940  $alternativeWebmountPoint = ‪GeneralUtility::intExplode(',', (string)$alternativeWebmountPoint);
941  $this->‪setWebmounts($alternativeWebmountPoint);
942  return;
943  }
944 
945  $alternativeWebmountPoints = trim($this->‪getTSConfig()['options.']['pageTree.']['altElementBrowserMountPoints'] ?? '');
946  $appendAlternativeWebmountPoints = $this->‪getTSConfig()['options.']['pageTree.']['altElementBrowserMountPoints.']['append'] ?? '';
947  if ($alternativeWebmountPoints) {
948  $alternativeWebmountPoints = ‪GeneralUtility::intExplode(',', $alternativeWebmountPoints);
949  $this->‪setWebmounts($alternativeWebmountPoints, $appendAlternativeWebmountPoints);
950  }
951  }
952 
961  public function ‪jsConfirmation(int $bitmask): bool
962  {
963  $alertPopupsSetting = trim((string)($this->‪getTSConfig()['options.']['alertPopups'] ?? ''));
964  $alertPopupsSetting = ‪MathUtility::canBeInterpretedAsInteger($alertPopupsSetting)
965  ? ‪MathUtility::forceIntegerInRange((int)$alertPopupsSetting, 0, ‪JsConfirmation::ALL)
966  : JsConfirmation::ALL;
967 
968  return (new JsConfirmation($alertPopupsSetting))->get($bitmask);
969  }
970 
979  public function ‪fetchGroupData()
980  {
981  if ($this->user['uid']) {
982  // Get lists for the be_user record and set them as default/primary values.
983  // Enabled Backend Modules
984  $this->groupData['modules'] = $this->user['userMods'] ?? '';
985  // Add available widgets
986  $this->groupData['available_widgets'] = $this->user['available_widgets'] ?? '';
987  // Add allowed mfa providers
988  $this->groupData['mfa_providers'] = $this->user['mfa_providers'] ?? '';
989  // Add Allowed Languages
990  $this->groupData['allowed_languages'] = $this->user['allowed_languages'] ?? '';
991  // Set user value for workspace permissions.
992  $this->groupData['workspace_perms'] = $this->user['workspace_perms'] ?? 0;
993  // Database mountpoints
994  $this->groupData['webmounts'] = $this->user['db_mountpoints'] ?? '';
995  // File mountpoints
996  $this->groupData['filemounts'] = $this->user['file_mountpoints'] ?? '';
997  // Fileoperation permissions
998  $this->groupData['file_permissions'] = $this->user['file_permissions'] ?? '';
999 
1000  // Get the groups and accumulate their permission settings
1001  $mountOptions = new BackendGroupMountOption((int)($this->user['options'] ?? 0));
1002  $groupResolver = GeneralUtility::makeInstance(GroupResolver::class);
1003  $resolvedGroups = $groupResolver->resolveGroupsForUser($this->user, $this->usergroup_table);
1004  foreach ($resolvedGroups as $groupInfo) {
1005  $groupInfo += [
1006  'uid' => 0,
1007  'db_mountpoints' => '',
1008  'file_mountpoints' => '',
1009  'groupMods' => '',
1010  'availableWidgets' => '',
1011  'mfa_providers' => '',
1012  'tables_select' => '',
1013  'tables_modify' => '',
1014  'pagetypes_select' => '',
1015  'non_exclude_fields' => '',
1016  'explicit_allowdeny' => '',
1017  'allowed_languages' => '',
1018  'custom_options' => '',
1019  'file_permissions' => '',
1020  'workspace_perms' => 0, // Bitflag.
1021  ];
1022  // Add the group uid to internal arrays.
1023  $this->userGroupsUID[] = (int)$groupInfo['uid'];
1024  $this->userGroups[(int)$groupInfo['uid']] = $groupInfo;
1025  // Mount group database-mounts
1026  if ($mountOptions->shouldUserIncludePageMountsFromAssociatedGroups()) {
1027  $this->groupData['webmounts'] .= ',' . $groupInfo['db_mountpoints'];
1028  }
1029  // Mount group file-mounts
1030  if ($mountOptions->shouldUserIncludeFileMountsFromAssociatedGroups()) {
1031  $this->groupData['filemounts'] .= ',' . $groupInfo['file_mountpoints'];
1032  }
1033  // Gather permission detail fields
1034  $this->groupData['modules'] .= ',' . $groupInfo['groupMods'];
1035  $this->groupData['available_widgets'] .= ',' . $groupInfo['availableWidgets'];
1036  $this->groupData['mfa_providers'] .= ',' . $groupInfo['mfa_providers'];
1037  $this->groupData['tables_select'] .= ',' . $groupInfo['tables_select'];
1038  $this->groupData['tables_modify'] .= ',' . $groupInfo['tables_modify'];
1039  $this->groupData['pagetypes_select'] .= ',' . $groupInfo['pagetypes_select'];
1040  $this->groupData['non_exclude_fields'] .= ',' . $groupInfo['non_exclude_fields'];
1041  $this->groupData['explicit_allowdeny'] .= ',' . $groupInfo['explicit_allowdeny'];
1042  $this->groupData['allowed_languages'] .= ',' . $groupInfo['allowed_languages'];
1043  $this->groupData['custom_options'] .= ',' . $groupInfo['custom_options'];
1044  $this->groupData['file_permissions'] .= ',' . $groupInfo['file_permissions'];
1045  // Setting workspace permissions:
1046  $this->groupData['workspace_perms'] |= $groupInfo['workspace_perms'];
1047  if (!$this->firstMainGroup) {
1048  $this->firstMainGroup = (int)$groupInfo['uid'];
1049  }
1050  }
1051 
1052  // Populating the $this->userGroupsUID -array with the groups in the order in which they were LAST included.
1053  // Finally, this is the list of group_uid's in the order they are parsed (including subgroups)
1054  // and without duplicates (duplicates are presented with their last entrance in the list,
1055  // which thus reflects the order of the TypoScript in TSconfig)
1056  $this->userGroupsUID = array_reverse(array_unique(array_reverse($this->userGroupsUID)));
1057 
1058  $this->‪prepareUserTsConfig();
1059 
1060  // Processing webmounts
1061  // Admin's always have the root mounted
1062  if ($this->‪isAdmin() && !($this->‪getTSConfig()['options.']['dontMountAdminMounts'] ?? false)) {
1063  $this->groupData['webmounts'] = '0,' . $this->groupData['webmounts'];
1064  }
1065  // The lists are cleaned for duplicates
1066  $this->groupData['webmounts'] = ‪StringUtility::uniqueList($this->groupData['webmounts'] ?? '');
1067  $this->groupData['filemounts'] = ‪StringUtility::uniqueList($this->groupData['filemounts'] ?? '');
1068  $this->groupData['pagetypes_select'] = ‪StringUtility::uniqueList($this->groupData['pagetypes_select'] ?? '');
1069  $this->groupData['tables_select'] = ‪StringUtility::uniqueList(($this->groupData['tables_modify'] ?? '') . ',' . ($this->groupData['tables_select'] ?? ''));
1070  $this->groupData['tables_modify'] = ‪StringUtility::uniqueList($this->groupData['tables_modify'] ?? '');
1071  $this->groupData['non_exclude_fields'] = ‪StringUtility::uniqueList($this->groupData['non_exclude_fields'] ?? '');
1072  $this->groupData['explicit_allowdeny'] = ‪StringUtility::uniqueList($this->groupData['explicit_allowdeny'] ?? '');
1073  $this->groupData['allowed_languages'] = ‪StringUtility::uniqueList($this->groupData['allowed_languages'] ?? '');
1074  $this->groupData['custom_options'] = ‪StringUtility::uniqueList($this->groupData['custom_options'] ?? '');
1075  $this->groupData['modules'] = ‪StringUtility::uniqueList($this->groupData['modules'] ?? '');
1076  $this->groupData['available_widgets'] = ‪StringUtility::uniqueList($this->groupData['available_widgets'] ?? '');
1077  $this->groupData['mfa_providers'] = ‪StringUtility::uniqueList($this->groupData['mfa_providers'] ?? '');
1078  $this->groupData['file_permissions'] = ‪StringUtility::uniqueList($this->groupData['file_permissions'] ?? '');
1079 
1080  // Check if the user access to all web mounts set
1081  if (!empty(trim($this->groupData['webmounts']))) {
1082  $validWebMounts = $this->‪filterValidWebMounts($this->groupData['webmounts']);
1083  $this->groupData['webmounts'] = implode(',', $validWebMounts);
1084  }
1085  // Setting up workspace situation (after webmounts are processed!):
1086  $this->‪workspaceInit();
1087  }
1088  }
1089 
1098  protected function ‪filterValidWebMounts(string $listOfWebMounts): array
1099  {
1100  // Checking read access to web mounts if there are mounts points (not empty string, false or 0)
1101  $allWebMounts = explode(',', $listOfWebMounts);
1102  // Selecting all web mounts with permission clause for reading
1103  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
1104  $queryBuilder->getRestrictions()
1105  ->removeAll()
1106  ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
1107 
1108  $readablePagesOfWebMounts = $queryBuilder->select('uid')
1109  ->from('pages')
1110  // @todo DOCTRINE: check how to make getPagePermsClause() portable
1111  ->where(
1113  $queryBuilder->expr()->in(
1114  'uid',
1115  $queryBuilder->createNamedParameter(
1116  ‪GeneralUtility::intExplode(',', $listOfWebMounts),
1118  )
1119  )
1120  )
1121  ->executeQuery()
1122  ->fetchAllAssociative();
1123  $readablePagesOfWebMounts = array_column(($readablePagesOfWebMounts ?: []), 'uid', 'uid');
1124  foreach ($allWebMounts as $key => $mountPointUid) {
1125  // If the mount ID is NOT found among selected pages, unset it:
1126  if ($mountPointUid > 0 && !isset($readablePagesOfWebMounts[$mountPointUid])) {
1127  unset($allWebMounts[$key]);
1128  }
1129  }
1130  return $allWebMounts;
1131  }
1132 
1136  protected function ‪prepareUserTsConfig(): void
1137  {
1138  $tsConfigFactory = GeneralUtility::makeInstance(UserTsConfigFactory::class);
1139  $this->userTsConfig = $tsConfigFactory->create($this);
1140  if (!empty($this->‪getUserTsConfig()->getUserTsConfigArray()['setup.']['override.'])) {
1141  // @todo: This logic is ugly. user TSconfig "setup.override." is used to force options
1142  // in the user settings module, along with "setup.fields." and "setup.default.".
1143  // See the docs about this.
1144  // The fun part is, this is merged into user UC. As such, whenever these setup
1145  // options are used, user UC has to be updated. The toggle below triggers this
1146  // and initiates an update query of this users UC.
1147  // Before v12, this was only triggered if user TSconfig could not be fetched from
1148  // cache, but this was flawed, too: When two users had the same user TSconfig, UC
1149  // of one user would be updated, but not UC of the other user if caches were not
1150  // cleared in between their two calls.
1151  // This toggle and UC overriding should vanish altogether: It would be better if
1152  // user TSconfig no longer overlays UC, instead the settings / setup module
1153  // controller should look at user TSconfig "setup." on the fly when rendering, and
1154  // consumers that access user setup / settings values should get values overloaded
1155  // on the fly as well using some helper or a late init logic or similar.
1156  $this->userTSUpdated = true;
1157  }
1158  }
1159 
1164  protected function ‪initializeFileStorages()
1165  {
1166  $this->fileStorages = [];
1167  $storageRepository = GeneralUtility::makeInstance(StorageRepository::class);
1168  // Admin users have all file storages visible, without any filters
1169  if ($this->‪isAdmin()) {
1170  $storageObjects = $storageRepository->findAll();
1171  foreach ($storageObjects as $storageObject) {
1172  $this->fileStorages[$storageObject->getUid()] = $storageObject;
1173  }
1174  } else {
1175  // Regular users only have storages that are defined in their filemounts
1176  // Permissions and file mounts for the storage are added in StoragePermissionAspect
1177  foreach ($this->‪getFileMountRecords() as $row) {
1178  if (!str_contains($row['identifier'] ?? '', ':')) {
1179  // Skip record since the file mount identifier is invalid, this usually happens
1180  // when file storages are selected. file mounts and groupHomePath and userHomePath should go through
1181  continue;
1182  }
1183  [$base] = ‪GeneralUtility::trimExplode(':', $row['identifier'], true);
1184  $base = (int)$base;
1185  if (!array_key_exists($base, $this->fileStorages)) {
1186  $storageObject = $storageRepository->findByUid($base);
1187  if ($storageObject) {
1188  $this->fileStorages[$storageObject->getUid()] = $storageObject;
1189  }
1190  }
1191  }
1192  }
1193 
1194  // This has to be called always in order to set certain filters
1196  }
1197 
1204  public function ‪getCategoryMountPoints()
1205  {
1206  $categoryMountPoints = '';
1207 
1208  // Category mounts of the groups
1209  if (is_array($this->userGroups)) {
1210  foreach ($this->userGroups as $group) {
1211  if ($group['category_perms']) {
1212  $categoryMountPoints .= ',' . $group['category_perms'];
1213  }
1214  }
1215  }
1216 
1217  // Category mounts of the user record
1218  if ($this->user['category_perms']) {
1219  $categoryMountPoints .= ',' . $this->user['category_perms'];
1220  }
1221 
1222  // Make the ids unique
1223  $categoryMountPoints = ‪GeneralUtility::trimExplode(',', $categoryMountPoints);
1224  $categoryMountPoints = array_filter($categoryMountPoints); // remove empty value
1225  $categoryMountPoints = array_unique($categoryMountPoints); // remove unique value
1226 
1227  return $categoryMountPoints;
1228  }
1229 
1237  public function ‪getFileMountRecords()
1238  {
1239  $runtimeCache = GeneralUtility::makeInstance(CacheManager::class)->getCache('runtime');
1240  $fileMountRecordCache = $runtimeCache->get('backendUserAuthenticationFileMountRecords') ?: [];
1241 
1242  if (!empty($fileMountRecordCache)) {
1243  return $fileMountRecordCache;
1244  }
1245 
1246  $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
1247 
1248  // Processing file mounts (both from the user and the groups)
1249  $fileMounts = array_unique(‪GeneralUtility::intExplode(',', (string)($this->groupData['filemounts'] ?? ''), true));
1250 
1251  // Limit file mounts if set in workspace record
1252  if ($this->workspace > 0 && !empty($this->workspaceRec['file_mountpoints'])) {
1253  $workspaceFileMounts = ‪GeneralUtility::intExplode(',', (string)$this->workspaceRec['file_mountpoints'], true);
1254  $fileMounts = array_intersect($fileMounts, $workspaceFileMounts);
1255  }
1256 
1257  if (!empty($fileMounts)) {
1258  $orderBy = ‪$GLOBALS['TCA']['sys_filemounts']['ctrl']['default_sortby'] ?? 'sorting';
1259 
1260  $queryBuilder = $connectionPool->getQueryBuilderForTable('sys_filemounts');
1261  $queryBuilder->getRestrictions()
1262  ->removeAll()
1263  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
1264  ->add(GeneralUtility::makeInstance(HiddenRestriction::class))
1265  ->add(GeneralUtility::makeInstance(RootLevelRestriction::class));
1266 
1267  $queryBuilder->select('*')
1268  ->from('sys_filemounts')
1269  ->where(
1270  $queryBuilder->expr()->in('uid', $queryBuilder->createNamedParameter($fileMounts, ‪Connection::PARAM_INT_ARRAY))
1271  );
1272 
1273  foreach (‪QueryHelper::parseOrderBy($orderBy) as $fieldAndDirection) {
1274  $queryBuilder->addOrderBy(...$fieldAndDirection);
1275  }
1276 
1277  $fileMountRecords = $queryBuilder->executeQuery()->fetchAllAssociative();
1278  if ($fileMountRecords !== false) {
1279  foreach ($fileMountRecords as $fileMount) {
1280  $readOnlySuffix = (bool)$fileMount['read_only'] ? '-readonly' : '';
1281  $fileMountRecordCache[$fileMount['identifier'] . $readOnlySuffix] = $fileMount;
1282  }
1283  }
1284  }
1285 
1286  // Read-only file mounts
1287  $readOnlyMountPoints = trim($this->‪getTSConfig()['options.']['folderTree.']['altElementBrowserMountPoints'] ?? '');
1288  if ($readOnlyMountPoints) {
1289  // We cannot use the API here but need to fetch the default storage record directly
1290  // to not instantiate it (which directly applies mount points) before all mount points are resolved!
1291  $queryBuilder = $connectionPool->getQueryBuilderForTable('sys_file_storage');
1292  $defaultStorageRow = $queryBuilder->select('uid')
1293  ->from('sys_file_storage')
1294  ->where(
1295  $queryBuilder->expr()->eq('is_default', $queryBuilder->createNamedParameter(1, ‪Connection::PARAM_INT))
1296  )
1297  ->setMaxResults(1)
1298  ->executeQuery()
1299  ->fetchAssociative();
1300 
1301  $readOnlyMountPointArray = ‪GeneralUtility::trimExplode(',', $readOnlyMountPoints);
1302  foreach ($readOnlyMountPointArray as $readOnlyMountPoint) {
1303  $readOnlyMountPointConfiguration = ‪GeneralUtility::trimExplode(':', $readOnlyMountPoint);
1304  if (count($readOnlyMountPointConfiguration) === 2) {
1305  // A storage is passed in the configuration
1306  $storageUid = (int)$readOnlyMountPointConfiguration[0];
1307  $path = $readOnlyMountPointConfiguration[1];
1308  } else {
1309  if (empty($defaultStorageRow)) {
1310  throw new \RuntimeException('Read only mount points have been defined in user TSconfig without specific storage, but a default storage could not be resolved.', 1404472382);
1311  }
1312  // Backwards compatibility: If no storage is passed, we use the default storage
1313  $storageUid = $defaultStorageRow['uid'];
1314  $path = $readOnlyMountPointConfiguration[0];
1315  }
1316  $fileMountRecordCache[$storageUid . $path . '-readonly'] = [
1317  'base' => $storageUid,
1318  'identifier' => $storageUid . ':' . $path,
1319  'title' => $path,
1320  'path' => $path,
1321  'read_only' => true,
1322  ];
1323  }
1324  }
1325 
1326  // Personal or Group filemounts are not accessible if file mount list is set in workspace record
1327  if ($this->workspace <= 0 || empty($this->workspaceRec['file_mountpoints'])) {
1328  // If userHomePath is set, we attempt to mount it
1329  if (‪$GLOBALS['TYPO3_CONF_VARS']['BE']['userHomePath'] ?? false) {
1330  [$userHomeStorageUid, $userHomeFilter] = explode(':', ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['userHomePath'], 2);
1331  $userHomeStorageUid = (int)$userHomeStorageUid;
1332  $userHomeFilter = '/' . ltrim($userHomeFilter, '/');
1333  if ($userHomeStorageUid > 0) {
1334  // Try and mount with [uid]_[username]
1335  $path = $userHomeFilter . $this->user['uid'] . '_' . $this->user['username'] . ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['userUploadDir'];
1336  $fileMountRecordCache[$userHomeStorageUid . $path] = [
1337  'base' => $userHomeStorageUid,
1338  'identifier' => $userHomeStorageUid . ':' . $path,
1339  'title' => $this->user['username'],
1340  'path' => $path,
1341  'read_only' => false,
1342  'user_mount' => true,
1343  ];
1344  // Try and mount with only [uid]
1345  $path = $userHomeFilter . $this->user['uid'] . ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['userUploadDir'];
1346  $fileMountRecordCache[$userHomeStorageUid . $path] = [
1347  'base' => $userHomeStorageUid,
1348  'identifier' => $userHomeStorageUid . ':' . $path,
1349  'title' => $this->user['username'],
1350  'path' => $path,
1351  'read_only' => false,
1352  'user_mount' => true,
1353  ];
1354  }
1355  }
1356 
1357  // Mount group home-dirs
1358  $mountOptions = new BackendGroupMountOption((int)($this->user['options'] ?? 0));
1359  if ((‪$GLOBALS['TYPO3_CONF_VARS']['BE']['groupHomePath'] ?? '') !== '' && $mountOptions->shouldUserIncludeFileMountsFromAssociatedGroups()) {
1360  // If groupHomePath is set, we attempt to mount it
1361  [$groupHomeStorageUid, $groupHomeFilter] = explode(':', ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['groupHomePath'], 2);
1362  $groupHomeStorageUid = (int)$groupHomeStorageUid;
1363  $groupHomeFilter = '/' . ltrim($groupHomeFilter, '/');
1364  if ($groupHomeStorageUid > 0) {
1365  foreach ($this->userGroups as ‪$groupData) {
1366  $path = $groupHomeFilter . ‪$groupData['uid'];
1367  $fileMountRecordCache[$groupHomeStorageUid . $path] = [
1368  'base' => $groupHomeStorageUid,
1369  'identifier' => $groupHomeStorageUid . ':' . $path,
1370  'title' => ‪$groupData['title'],
1371  'path' => $path,
1372  'read_only' => false,
1373  'user_mount' => true,
1374  ];
1375  }
1376  }
1377  }
1378  }
1379 
1380  $runtimeCache->set('backendUserAuthenticationFileMountRecords', $fileMountRecordCache);
1381  return $fileMountRecordCache;
1382  }
1383 
1391  public function ‪getFileStorages()
1392  {
1393  // Initializing file mounts after the groups are fetched
1394  if ($this->fileStorages === null) {
1395  $this->‪initializeFileStorages();
1396  }
1397  return ‪$this->fileStorages;
1398  }
1399 
1406  {
1407  // Add the option for also displaying the non-hidden files
1408  if ($this->uc['showHiddenFilesAndFolders'] ?? false) {
1410  }
1411  }
1412 
1446  public function ‪getFilePermissions(): array
1447  {
1448  if ($this->filePermissions === null) {
1450  // File permissions
1451  'addFile' => false,
1452  'readFile' => false,
1453  'writeFile' => false,
1454  'copyFile' => false,
1455  'moveFile' => false,
1456  'renameFile' => false,
1457  'deleteFile' => false,
1458  // Folder permissions
1459  'addFolder' => false,
1460  'readFolder' => false,
1461  'writeFolder' => false,
1462  'copyFolder' => false,
1463  'moveFolder' => false,
1464  'renameFolder' => false,
1465  'deleteFolder' => false,
1466  'recursivedeleteFolder' => false,
1467  ];
1468  if ($this->‪isAdmin()) {
1469  ‪$filePermissions = array_map(is_bool(...), ‪$filePermissions);
1470  } else {
1471  $userGroupRecordPermissions = ‪GeneralUtility::trimExplode(',', $this->groupData['file_permissions'] ?? '', true);
1472  array_walk(
1473  $userGroupRecordPermissions,
1474  static function (string $permission) use (&‪$filePermissions): void {
1475  ‪$filePermissions[$permission] = true;
1476  }
1477  );
1479  // Finally overlay any user TSconfig
1480  $permissionsTsConfig = $this->‪getTSConfig()['permissions.']['file.']['default.'] ?? [];
1481  if (!empty($permissionsTsConfig)) {
1482  array_walk(
1483  $permissionsTsConfig,
1484  static function (string $value, string $permission) use (&‪$filePermissions): void {
1485  ‪$filePermissions[$permission] = (bool)$value;
1486  }
1487  );
1488  }
1489  }
1490  $this->filePermissions = ‪$filePermissions;
1491  }
1493  }
1494 
1501  protected function ‪workspaceInit(): void
1502  {
1503  // Initializing workspace by evaluating and setting the workspace, possibly updating it in the user record!
1504  $this->‪setWorkspace($this->user['workspace_id']);
1505  // Limiting the DB mountpoints if there any selected in the workspace record
1507  $allowed_languages = (string)($this->‪getTSConfig()['options.']['workspaces.']['allowed_languages.'][‪$this->workspace] ?? '');
1508  if ($allowed_languages !== '') {
1509  $this->groupData['allowed_languages'] = ‪StringUtility::uniqueList($allowed_languages);
1510  }
1511  }
1512 
1516  protected function ‪initializeDbMountpointsInWorkspace()
1517  {
1518  $dbMountpoints = trim($this->workspaceRec['db_mountpoints'] ?? '');
1519  if ($this->workspace > 0 && $dbMountpoints != '') {
1520  $filteredDbMountpoints = [];
1521  // Notice: We cannot call $this->getPagePermsClause(1);
1522  // as usual because the group-list is not available at this point.
1523  // But bypassing is fine because all we want here is check if the
1524  // workspace mounts are inside the current webmounts rootline.
1525  // The actual permission checking on page level is done elsewhere
1526  // as usual anyway before the page tree is rendered.
1527  $readPerms = '1=1';
1528  // Traverse mount points of the workspace, add them,
1529  // but make sure they match against the users' DB mounts
1530 
1531  $workspaceWebMounts = ‪GeneralUtility::intExplode(',', $dbMountpoints);
1532  $webMountsOfUser = ‪GeneralUtility::intExplode(',', (string)($this->groupData['webmounts'] ?? ''));
1533  $webMountsOfUser = array_combine($webMountsOfUser, $webMountsOfUser) ?: [];
1534 
1535  $entryPointRootLineUids = [];
1536  foreach ($webMountsOfUser as $webMountPageId) {
1537  $rootLine = BackendUtility::BEgetRootLine($webMountPageId, '', true);
1538  $entryPointRootLineUids[$webMountPageId] = array_map(intval(...), array_column($rootLine, 'uid'));
1539  }
1540  foreach ($entryPointRootLineUids as $webMountOfUser => $uidsOfRootLine) {
1541  // Remove the DB mounts of the user if the DB mount is not in the list of
1542  // workspace mounts
1543  foreach ($workspaceWebMounts as $webmountOfWorkspace) {
1544  // This workspace DB mount is somewhere in the rootline of the users' web mount,
1545  // so this is "OK" to be included
1546  if (in_array($webmountOfWorkspace, $uidsOfRootLine, true)) {
1547  continue;
1548  }
1549  // Remove the user's DB Mount (possible via array_combine, see above)
1550  unset($webMountsOfUser[$webMountOfUser]);
1551  }
1552  }
1553  $dbMountpoints = array_merge($workspaceWebMounts, $webMountsOfUser);
1554  $dbMountpoints = array_unique($dbMountpoints);
1555  foreach ($dbMountpoints as $mpId) {
1556  if ($this->‪isInWebMount($mpId, $readPerms)) {
1557  $filteredDbMountpoints[] = $mpId;
1558  }
1559  }
1560  // Re-insert webmounts
1561  $this->groupData['webmounts'] = implode(',', $filteredDbMountpoints);
1562  }
1563  }
1564 
1572  public function ‪checkWorkspace(int|array $wsRec): array|false
1573  {
1574  // If not array, look up workspace record
1575  if (!is_array($wsRec)) {
1576  if ($wsRec === 0) {
1577  $wsRec = ['uid' => 0];
1578  } elseif (‪ExtensionManagementUtility::isLoaded('workspaces')) {
1579  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_workspace');
1580  $queryBuilder->getRestrictions()->add(GeneralUtility::makeInstance(RootLevelRestriction::class));
1581  $wsRec = $queryBuilder
1582  ->select('*')
1583  ->from('sys_workspace')
1584  ->where($queryBuilder->expr()->eq(
1585  'uid',
1586  $queryBuilder->createNamedParameter($wsRec, ‪Connection::PARAM_INT)
1587  ))
1588  ->executeQuery()
1589  ->fetchAssociative();
1590  }
1591  }
1592  // If wsRec is set to an array, evaluate it, otherwise return false
1593  if (!is_array($wsRec)) {
1594  return false;
1595  }
1596  if ($this->‪isAdmin()) {
1597  return array_merge($wsRec, ['_ACCESS' => 'admin']);
1598  }
1599  // User is in live, and be_groups.workspace_perms has bitmask=1 included
1600  if ($wsRec['uid'] === 0) {
1601  return $this->‪hasEditAccessToLiveWorkspace()
1602  ? array_merge($wsRec, ['_ACCESS' => 'online'])
1603  : false;
1604  }
1605  // Checking if the person is workspace owner
1606  if (‪GeneralUtility::inList($wsRec['adminusers'], 'be_users_' . $this->user['uid'])) {
1607  return array_merge($wsRec, ['_ACCESS' => 'owner']);
1608  }
1609  // Checking if the editor is owner through an included user group
1610  foreach ($this->userGroupsUID as $groupUid) {
1611  if (‪GeneralUtility::inList($wsRec['adminusers'], 'be_groups_' . $groupUid)) {
1612  return array_merge($wsRec, ['_ACCESS' => 'owner']);
1613  }
1614  }
1615  // Checking if the user is member of the workspace
1616  if (‪GeneralUtility::inList($wsRec['members'], 'be_users_' . $this->user['uid'])) {
1617  return array_merge($wsRec, ['_ACCESS' => 'member']);
1618  }
1619  // Checking if the user is member through an included user group
1620  foreach ($this->userGroupsUID as $groupUid) {
1621  if (‪GeneralUtility::inList($wsRec['members'], 'be_groups_' . $groupUid)) {
1622  return array_merge($wsRec, ['_ACCESS' => 'member']);
1623  }
1624  }
1625  return false;
1626  }
1627 
1632  protected function ‪hasEditAccessToLiveWorkspace(): bool
1633  {
1634  return (bool)(($this->groupData['workspace_perms'] ?? 0) & 1);
1635  }
1636 
1644  protected function ‪checkWorkspaceCurrent(): false|array|null
1645  {
1646  if (!isset($this->checkWorkspaceCurrent_cache)) {
1647  $this->checkWorkspaceCurrent_cache = $this->‪checkWorkspace($this->workspace);
1648  }
1650  }
1651 
1658  public function ‪setWorkspace($workspaceId)
1659  {
1660  // Check workspace validity and if not found, revert to default workspace.
1661  if (!$this->‪setTemporaryWorkspace($workspaceId)) {
1663  }
1664  // Unset access cache:
1665  $this->checkWorkspaceCurrent_cache = null;
1666  // If ID is different from the stored one, change it:
1667  if ((int)$this->workspace !== (int)$this->user['workspace_id']) {
1668  $this->user['workspace_id'] = ‪$this->workspace;
1669  GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('be_users')->update(
1670  'be_users',
1671  ['workspace_id' => $this->user['workspace_id']],
1672  ['uid' => (int)$this->user['uid']]
1673  );
1674  $this->‪writelog(SystemLogType::EXTENSION, SystemLogGenericAction::UNDEFINED, SystemLogErrorClassification::MESSAGE, 0, 'User changed workspace to "{workspace}"', ['workspace' => $this->workspace]);
1675  }
1676  }
1677 
1685  public function ‪setTemporaryWorkspace($workspaceId)
1686  {
1687  $workspaceRecord = $this->‪checkWorkspace((int)$workspaceId);
1688 
1689  if ($workspaceRecord) {
1690  $this->workspaceRec = $workspaceRecord;
1691  $this->workspace = (int)$workspaceId;
1692  return true;
1693  }
1694  return false;
1695  }
1696 
1701  protected function ‪setDefaultWorkspace(): void
1702  {
1703  $this->workspace = $this->‪getDefaultWorkspace();
1704  $this->workspaceRec = $this->‪checkWorkspace($this->workspace);
1705  }
1706 
1715  protected function ‪getDefaultWorkspace(): int
1716  {
1717  if (!‪ExtensionManagementUtility::isLoaded('workspaces')) {
1718  return 0;
1719  }
1720  // Online is default
1721  if ($this->‪checkWorkspace(0)) {
1722  return 0;
1723  }
1724  // Traverse all workspaces
1725  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_workspace');
1726  $queryBuilder->getRestrictions()->add(GeneralUtility::makeInstance(RootLevelRestriction::class));
1727  $result = $queryBuilder->select('*')
1728  ->from('sys_workspace')
1729  ->orderBy('title')
1730  ->executeQuery();
1731  while ($workspaceRecord = $result->fetchAssociative()) {
1732  if ($this->‪checkWorkspace($workspaceRecord)) {
1733  return (int)$workspaceRecord['uid'];
1734  }
1735  }
1736  // Otherwise -99 is the fallback
1737  return -99;
1738  }
1739 
1758  public function ‪writelog($type, $action, $error, $details_nr, ‪$details, $data, $tablename = '', $recuid = '', $recpid = '', $event_pid = -1, $NEWid = '', $userId = 0)
1759  {
1760  if (!$userId && !empty($this->user['uid'])) {
1761  $userId = $this->user['uid'];
1762  }
1763 
1764  if ($backuserid = $this->‪getOriginalUserIdWhenInSwitchUserMode()) {
1765  if (empty($data)) {
1766  $data = [];
1767  }
1768  $data['originalUser'] = $backuserid;
1769  }
1770 
1771  // @todo Remove this once this method is properly typed.
1772  $type = (int)$type;
1773 
1774  ‪$fields = [
1775  'userid' => (int)$userId,
1776  'type' => $type,
1777  'channel' => ‪Type::toChannel($type),
1778  'level' => ‪Type::toLevel($type),
1779  'action' => (int)$action,
1780  'error' => (int)$error,
1781  'details_nr' => (int)$details_nr,
1782  'details' => ‪$details,
1783  'log_data' => empty($data) ? '' : json_encode($data),
1784  'tablename' => $tablename,
1785  'recuid' => (int)$recuid,
1786  'IP' => (string)GeneralUtility::getIndpEnv('REMOTE_ADDR'),
1787  'tstamp' => ‪$GLOBALS['EXEC_TIME'] ?? time(),
1788  'event_pid' => (int)$event_pid,
1789  'NEWid' => $NEWid,
1790  'workspace' => $this->workspace,
1791  ];
1792 
1793  $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('sys_log');
1794  $connection->insert(
1795  'sys_log',
1796  ‪$fields,
1797  [
1814  ]
1815  );
1816 
1817  return (int)$connection->lastInsertId();
1818  }
1819 
1823  public static function ‪getCookieName(): string
1824  {
1825  $configuredCookieName = trim((string)(‪$GLOBALS['TYPO3_CONF_VARS']['BE']['cookieName'] ?? ''));
1826  return $configuredCookieName !== '' ? $configuredCookieName : 'be_typo_user';
1827  }
1828 
1838  public function ‪backendCheckLogin(ServerRequestInterface $request = null)
1839  {
1840  if (empty($this->user['uid'])) {
1841  // @todo: throw a proper AccessDeniedException in TYPO3 v12.0. and handle this functionality in the calling code
1842  $entryPointResolver = GeneralUtility::makeInstance(BackendEntryPointResolver::class);
1843  ‪$url = $entryPointResolver->getUriFromRequest(‪$GLOBALS['TYPO3_REQUEST']);
1844  throw new ImmediateResponseException(new RedirectResponse(‪$url, 303), 1607271747);
1845  }
1846  if ($this->‪isUserAllowedToLogin()) {
1847  $this->‪initializeBackendLogin($request);
1848  } else {
1849  // @todo: throw a proper AccessDeniedException in TYPO3 v12.0.
1850  throw new \RuntimeException('Login Error: TYPO3 is in maintenance mode at the moment. Only administrators are allowed access.', 1294585860);
1851  }
1852  }
1853 
1857  public function ‪initializeBackendLogin(ServerRequestInterface $request = null): void
1858  {
1859  // The groups are fetched and ready for permission checking in this initialization.
1860  // Tables.php must be read before this because stuff like the modules has impact in this
1861  $this->‪fetchGroupData();
1862  // Setting the UC array. It's needed with fetchGroupData first, due to default/overriding of values.
1863  $this->‪backendSetUC();
1864  if ($this->loginSessionStarted && !($this->‪getSessionData('mfa') ?? false)) {
1865  // Handling user logged in. By checking for the mfa session key, it's ensured, the
1866  // handling is only done once, since MfaController does the handling on its own.
1867  $this->‪handleUserLoggedIn();
1868  }
1869  }
1870 
1877  public function ‪handleUserLoggedIn(ServerRequestInterface $request = null): void
1878  {
1879  // Also, if there is a recovery link set, unset it now
1880  // this will be moved into its own Event at a later stage.
1881  // If a token was set previously, this is now unset, as it was now possible to log-in
1882  if ($this->user['password_reset_token'] ?? '') {
1883  GeneralUtility::makeInstance(ConnectionPool::class)
1884  ->getConnectionForTable($this->user_table)
1885  ->update($this->user_table, ['password_reset_token' => ''], ['uid' => $this->user['uid']]);
1886  }
1887 
1888  $event = new AfterUserLoggedInEvent($this, $request);
1889  GeneralUtility::makeInstance(EventDispatcherInterface::class)->dispatch($event);
1890  }
1891 
1899  public function ‪backendSetUC()
1900  {
1901  // Setting defaults if uc is empty
1902  $updated = false;
1903  if (empty($this->uc)) {
1904  $this->uc = array_merge(
1905  $this->uc_default,
1906  (array)‪$GLOBALS['TYPO3_CONF_VARS']['BE']['defaultUC'],
1907  GeneralUtility::removeDotsFromTS((array)($this->‪getTSConfig()['setup.']['default.'] ?? []))
1908  );
1909  $this->‪overrideUC();
1910  $updated = true;
1911  }
1912  // If TSconfig is updated, update the defaultUC.
1913  if ($this->userTSUpdated) {
1914  $this->‪overrideUC();
1915  $updated = true;
1916  }
1917  // Saving if updated.
1918  if ($updated) {
1919  $this->‪writeUC();
1920  }
1921  }
1922 
1929  public function ‪overrideUC()
1930  {
1931  $this->uc = array_merge($this->uc, (array)($this->‪getTSConfig()['setup.']['override.'] ?? []));
1932  }
1933 
1939  public function ‪resetUC()
1940  {
1941  $this->user['uc'] = '';
1942  $this->uc = [];
1943  $this->‪backendSetUC();
1944  }
1945 
1958  public function ‪isUserAllowedToLogin()
1959  {
1960  $isUserAllowedToLogin = false;
1961  $adminOnlyMode = (int)‪$GLOBALS['TYPO3_CONF_VARS']['BE']['adminOnly'];
1962  // Backend user is allowed if adminOnly is not set or user is an admin:
1963  if (!$adminOnlyMode || $this->‪isAdmin()) {
1964  $isUserAllowedToLogin = true;
1965  } elseif ($backUserId = $this->‪getOriginalUserIdWhenInSwitchUserMode()) {
1966  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('be_users');
1967  $isUserAllowedToLogin = (bool)$queryBuilder->count('uid')
1968  ->from('be_users')
1969  ->where(
1970  $queryBuilder->expr()->eq(
1971  'uid',
1972  $queryBuilder->createNamedParameter($backUserId, ‪Connection::PARAM_INT)
1973  ),
1974  $queryBuilder->expr()->eq('admin', $queryBuilder->createNamedParameter(1, ‪Connection::PARAM_INT))
1975  )
1976  ->executeQuery()
1977  ->fetchOne();
1978  }
1979  return $isUserAllowedToLogin;
1980  }
1981 
1985  public function ‪logoff()
1986  {
1987  if (isset(‪$GLOBALS['BE_USER'])
1988  && ‪$GLOBALS['BE_USER'] instanceof self
1989  && isset(‪$GLOBALS['BE_USER']->user['uid'])
1990  ) {
1991  GeneralUtility::makeInstance(FormProtectionFactory::class)->createForType('backend')->clean();
1992  // Release the locked records
1993  $this->‪releaseLockedRecords((int)$GLOBALS['BE_USER']->user['uid']);
1995  if ($this->‪isSystemMaintainer()) {
1996  // @todo: This should be turned into a dispatched event EXT:install can listen on.
1997  // This might be useful for others as well. The reasons this has not been
1998  // implemented yet, is, that the method should be refactored to at least
1999  // receive Request and probably be-user object correctly, instead of
2000  // fetching it from globals, before creating API with an event.
2001  $packageManager = GeneralUtility::makeInstance(PackageManager::class);
2002  if ($packageManager->isPackageActive('install')) {
2003  // If user is system maintainer, destroy its possibly valid install tool session.
2004  $session = GeneralUtility::makeInstance(SessionService::class);
2005  // @todo: It's kinda fishy installSessionHandler() is called here. We should be able to skip this.
2006  $session->installSessionHandler();
2007  $session->destroySession(‪$GLOBALS['TYPO3_REQUEST'] ?? null);
2008  }
2009  }
2010  }
2011  parent::logoff();
2012  }
2017  protected function ‪releaseLockedRecords(int $userId)
2018  {
2019  if ($userId > 0) {
2020  GeneralUtility::makeInstance(ConnectionPool::class)
2021  ->getConnectionForTable('sys_lockedrecords')
2022  ->delete(
2023  'sys_lockedrecords',
2024  ['userid' => $userId]
2025  );
2026  }
2027  }
2028 
2036  public function ‪getOriginalUserIdWhenInSwitchUserMode(): ?int
2037  {
2038  $originalUserId = $this->‪getSessionData('backuserid');
2039  return $originalUserId ? (int)$originalUserId : null;
2040  }
2041 
2045  protected function ‪evaluateMfaRequirements(): void
2046  {
2047  // In case the current session is a "switch-user" session, MFA is not required
2048  if ($this->‪getOriginalUserIdWhenInSwitchUserMode() !== null) {
2049  $this->logger->debug('MFA is skipped in switch user mode', [
2050  $this->userid_column => $this->‪getUserId(),
2051  $this->username_column => $this->‪getUserName(),
2052  ]);
2053  return;
2054  }
2055  parent::evaluateMfaRequirements();
2056  }
2057 
2063  public function ‪isMfaSetupRequired(): bool
2064  {
2065  $authConfig = $this->‪getTSConfig()['auth.']['mfa.'] ?? [];
2066 
2067  if (isset($authConfig['required'])) {
2068  // user TSconfig overrules global configuration
2069  return (bool)$authConfig['required'];
2070  }
2071 
2072  $globalConfig = (int)(‪$GLOBALS['TYPO3_CONF_VARS']['BE']['requireMfa'] ?? 0);
2073  if ($globalConfig <= 1) {
2074  // 0 and 1 can directly be used by type-casting to boolean
2075  return (bool)$globalConfig;
2076  }
2077 
2078  // check the system maintainer / admin / non-admin options
2079  $isAdmin = $this->‪isAdmin();
2080  return ($globalConfig === 2 && !$isAdmin)
2081  || ($globalConfig === 3 && $isAdmin)
2082  || ($globalConfig === 4 && $this->‪isSystemMaintainer());
2083  }
2084 
2090  public function ‪isImportEnabled(): bool
2091  {
2092  return $this->‪isAdmin()
2093  || ($this->‪getTSConfig()['options.']['impexp.']['enableImportForNonAdminUser'] ?? false);
2094  }
2095 
2101  public function ‪isExportEnabled(): bool
2102  {
2103  return $this->‪isAdmin()
2104  || ($this->‪getTSConfig()['options.']['impexp.']['enableExportForNonAdminUser'] ?? false);
2105  }
2106 
2112  public function ‪shallDisplayDebugInformation(): bool
2113  {
2114  return (‪$GLOBALS['TYPO3_CONF_VARS']['BE']['debug'] ?? false) && $this->‪isAdmin();
2115  }
2116 }
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\returnWebmounts
‪array returnWebmounts()
Definition: BackendUserAuthentication.php:879
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\evaluateUserSpecificFileFilterSettings
‪evaluateUserSpecificFileFilterSettings()
Definition: BackendUserAuthentication.php:1382
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\isMemberOfGroup
‪isMemberOfGroup(int $groupId)
Definition: BackendUserAuthentication.php:253
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\handleUserLoggedIn
‪handleUserLoggedIn(ServerRequestInterface $request=null)
Definition: BackendUserAuthentication.php:1854
‪TYPO3\CMS\Core\Database\Query\QueryHelper\parseOrderBy
‪static array array[] parseOrderBy(string $input)
Definition: QueryHelper.php:44
‪TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction
Definition: HiddenRestriction.php:27
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\recordEditAccessInternals
‪bool recordEditAccessInternals($table, $idOrRow, $newRecord=false, $deletedRecord=false, $checkFullLanguageAccess=false)
Definition: BackendUserAuthentication.php:636
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getUserTsConfig
‪getUserTsConfig()
Definition: BackendUserAuthentication.php:867
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$usergroup_table
‪string $usergroup_table
Definition: BackendUserAuthentication.php:73
‪TYPO3\CMS\Core\Database\Connection\PARAM_INT
‪const PARAM_INT
Definition: Connection.php:52
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder
Definition: ExpressionBuilder.php:40
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\setWebmounts
‪setWebmounts(array $mountPointUids, $append=false)
Definition: BackendUserAuthentication.php:890
‪TYPO3\CMS\Core\SysLog\Action
Definition: Cache.php:18
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$formfield_status
‪string $formfield_status
Definition: BackendUserAuthentication.php:186
‪TYPO3\CMS\Core\TypoScript\UserTsConfig
Definition: UserTsConfig.php:28
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getPagePermsClause
‪string getPagePermsClause($perms)
Definition: BackendUserAuthentication.php:400
‪TYPO3\CMS\Webhooks\Message\$details
‪identifier readonly UriInterface readonly array $details
Definition: MfaVerificationErrorOccurredMessage.php:37
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\initializeDbMountpointsInWorkspace
‪initializeDbMountpointsInWorkspace()
Definition: BackendUserAuthentication.php:1493
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\initializeFileStorages
‪initializeFileStorages()
Definition: BackendUserAuthentication.php:1141
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$formfield_uname
‪string $formfield_uname
Definition: BackendUserAuthentication.php:174
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\calcPerms
‪int calcPerms($row)
Definition: BackendUserAuthentication.php:469
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\workspaceAllowsLiveEditingInTable
‪workspaceAllowsLiveEditingInTable(string $table)
Definition: BackendUserAuthentication.php:743
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\checkAuthMode
‪bool checkAuthMode($table, $field, $value)
Definition: BackendUserAuthentication.php:528
‪TYPO3\CMS\Core\Authentication
Definition: AbstractAuthenticationService.php:16
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\prepareUserTsConfig
‪prepareUserTsConfig()
Definition: BackendUserAuthentication.php:1113
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$usergroup_column
‪string $usergroup_column
Definition: BackendUserAuthentication.php:68
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getTSConfig
‪array getTSConfig()
Definition: BackendUserAuthentication.php:857
‪TYPO3\CMS\Core\Type\Bitmask\Permission\NOTHING
‪const NOTHING
Definition: Permission.php:30
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\getUserName
‪getUserName()
Definition: AbstractUserAuthentication.php:1245
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$firstMainGroup
‪int $firstMainGroup
Definition: BackendUserAuthentication.php:201
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\isAdmin
‪bool isAdmin()
Definition: BackendUserAuthentication.php:241
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$uc_default
‪array $uc_default
Definition: BackendUserAuthentication.php:212
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\check
‪bool check($type, $value)
Definition: BackendUserAuthentication.php:514
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\getUserId
‪getUserId()
Definition: AbstractUserAuthentication.php:1237
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\fetchGroupData
‪fetchGroupData()
Definition: BackendUserAuthentication.php:956
‪TYPO3\CMS\Core\Authentication\JsConfirmation
Definition: JsConfirmation.php:28
‪TYPO3\CMS\Core\Utility\StringUtility\uniqueList
‪static string uniqueList(string $list)
Definition: StringUtility.php:122
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getCookieName
‪static getCookieName()
Definition: BackendUserAuthentication.php:1800
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\setDefaultWorkspace
‪setDefaultWorkspace()
Definition: BackendUserAuthentication.php:1678
‪$fields
‪$fields
Definition: pages.php:5
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$writeAttemptLog
‪bool $writeAttemptLog
Definition: BackendUserAuthentication.php:196
‪TYPO3\CMS\Core\Database\Connection\PARAM_STR
‪const PARAM_STR
Definition: Connection.php:57
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getFileStorages
‪TYPO3 CMS Core Resource ResourceStorage[] getFileStorages()
Definition: BackendUserAuthentication.php:1368
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\isSystemMaintainer
‪isSystemMaintainer(bool $pure=false)
Definition: BackendUserAuthentication.php:358
‪TYPO3\CMS\Core\Type\Bitmask\Permission
Definition: Permission.php:26
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\isLoaded
‪static isLoaded(string $key)
Definition: ExtensionManagementUtility.php:55
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\backendCheckLogin
‪backendCheckLogin(ServerRequestInterface $request=null)
Definition: BackendUserAuthentication.php:1815
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\checkWorkspace
‪array false checkWorkspace(int|array $wsRec)
Definition: BackendUserAuthentication.php:1549
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$formfield_uident
‪string $formfield_uident
Definition: BackendUserAuthentication.php:180
‪TYPO3\CMS\Core\SysLog\Type\toChannel
‪static toChannel(int $type)
Definition: Type.php:76
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility
Definition: ExtensionManagementUtility.php:32
‪TYPO3\CMS\Core\Type\Bitmask\BackendGroupMountOption
Definition: BackendGroupMountOption.php:27
‪TYPO3\CMS\Core\Site\Entity\SiteLanguage
Definition: SiteLanguage.php:27
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\isInWebMount
‪int null isInWebMount($idOrRow, $readPerms='')
Definition: BackendUserAuthentication.php:296
‪TYPO3\CMS\Core\Utility\MathUtility\canBeInterpretedAsInteger
‪static bool canBeInterpretedAsInteger(mixed $var)
Definition: MathUtility.php:69
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getCategoryMountPoints
‪array getCategoryMountPoints()
Definition: BackendUserAuthentication.php:1181
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\isMfaSetupRequired
‪isMfaSetupRequired()
Definition: BackendUserAuthentication.php:2040
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getFileMountRecords
‪array getFileMountRecords()
Definition: BackendUserAuthentication.php:1214
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\jsConfirmation
‪bool jsConfirmation(int $bitmask)
Definition: BackendUserAuthentication.php:938
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\mayMakeShortcut
‪bool mayMakeShortcut()
Definition: BackendUserAuthentication.php:730
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\resetUC
‪resetUC()
Definition: BackendUserAuthentication.php:1916
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getFilePermissions
‪getFilePermissions()
Definition: BackendUserAuthentication.php:1423
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$userid_column
‪string $userid_column
Definition: BackendUserAuthentication.php:153
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$filePermissions
‪array null $filePermissions
Definition: BackendUserAuthentication.php:133
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$user_table
‪string $user_table
Definition: BackendUserAuthentication.php:138
‪TYPO3\CMS\Core\Database\Query\QueryHelper
Definition: QueryHelper.php:32
‪TYPO3\CMS\Core\Type\Bitmask\Permission\ALL
‪const ALL
Definition: Permission.php:60
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\filterValidWebMounts
‪array filterValidWebMounts(string $listOfWebMounts)
Definition: BackendUserAuthentication.php:1075
‪TYPO3\CMS\Core\Database\Query\Restriction\RootLevelRestriction
Definition: RootLevelRestriction.php:27
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\evaluateMfaRequirements
‪evaluateMfaRequirements()
Definition: BackendUserAuthentication.php:2022
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\shallDisplayDebugInformation
‪shallDisplayDebugInformation()
Definition: BackendUserAuthentication.php:2089
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\setWorkspace
‪setWorkspace($workspaceId)
Definition: BackendUserAuthentication.php:1635
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getOriginalUserIdWhenInSwitchUserMode
‪int null getOriginalUserIdWhenInSwitchUserMode()
Definition: BackendUserAuthentication.php:2013
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$userTSUpdated
‪bool $userTSUpdated
Definition: BackendUserAuthentication.php:114
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\backendSetUC
‪backendSetUC()
Definition: BackendUserAuthentication.php:1876
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\ROLE_SYSTEMMAINTAINER
‪const ROLE_SYSTEMMAINTAINER
Definition: BackendUserAuthentication.php:63
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\isUserAllowedToLogin
‪bool isUserAllowedToLogin()
Definition: BackendUserAuthentication.php:1935
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\hasEditAccessToLiveWorkspace
‪hasEditAccessToLiveWorkspace()
Definition: BackendUserAuthentication.php:1609
‪TYPO3\CMS\Core\Resource\StorageRepository
Definition: StorageRepository.php:38
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$groupData
‪array $groupData
Definition: BackendUserAuthentication.php:79
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\doesUserHaveAccess
‪bool doesUserHaveAccess($row, $perms)
Definition: BackendUserAuthentication.php:276
‪TYPO3\CMS\Webhooks\Message\$record
‪identifier readonly int readonly array $record
Definition: PageModificationMessage.php:36
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$username_column
‪string $username_column
Definition: BackendUserAuthentication.php:143
‪TYPO3\CMS\Core\SysLog\Error
Definition: Error.php:24
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\getSessionData
‪mixed getSessionData($key)
Definition: AbstractUserAuthentication.php:1005
‪TYPO3\CMS\Core\Cache\CacheManager
Definition: CacheManager.php:36
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\checkLanguageAccess
‪bool checkLanguageAccess($langValue)
Definition: BackendUserAuthentication.php:561
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:62
‪TYPO3\CMS\Core\Type\Bitmask\Permission\PAGE_SHOW
‪const PAGE_SHOW
Definition: Permission.php:35
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\initializeBackendLogin
‪initializeBackendLogin(ServerRequestInterface $request=null)
Definition: BackendUserAuthentication.php:1834
‪TYPO3\CMS\Core\Resource\Filter\FileNameFilter\setShowHiddenFilesAndFolders
‪static bool setShowHiddenFilesAndFolders($showHiddenFilesAndFolders)
Definition: FileNameFilter.php:71
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$checkWorkspaceCurrent_cache
‪array null $checkWorkspaceCurrent_cache
Definition: BackendUserAuthentication.php:125
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$userGroupsUID
‪array $userGroupsUID
Definition: BackendUserAuthentication.php:93
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$userTsConfig
‪UserTsConfig $userTsConfig
Definition: BackendUserAuthentication.php:108
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\overrideUC
‪overrideUC()
Definition: BackendUserAuthentication.php:1906
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$enablecolumns
‪array $enablecolumns
Definition: BackendUserAuthentication.php:162
‪TYPO3\CMS\Core\TypoScript\UserTsConfigFactory
Definition: UserTsConfigFactory.php:38
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$loginType
‪string $loginType
Definition: BackendUserAuthentication.php:224
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\logoff
‪logoff()
Definition: BackendUserAuthentication.php:1962
‪TYPO3\CMS\Core\Http\RedirectResponse
Definition: RedirectResponse.php:30
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\__construct
‪__construct()
Definition: BackendUserAuthentication.php:229
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\releaseLockedRecords
‪releaseLockedRecords(int $userId)
Definition: BackendUserAuthentication.php:1994
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:41
‪TYPO3\CMS\Webhooks\Message\$url
‪identifier readonly UriInterface $url
Definition: LoginErrorOccurredMessage.php:36
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$lastLogin_column
‪string $lastLogin_column
Definition: BackendUserAuthentication.php:157
‪TYPO3\CMS\Core\FormProtection\FormProtectionFactory
Definition: FormProtectionFactory.php:43
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\writelog
‪int writelog($type, $action, $error, $details_nr, $details, $data, $tablename='', $recuid='', $recpid='', $event_pid=-1, $NEWid='', $userId=0)
Definition: BackendUserAuthentication.php:1735
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction
Definition: DeletedRestriction.php:28
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:41
‪TYPO3\CMS\Core\Authentication\JsConfirmation\ALL
‪const ALL
Definition: JsConfirmation.php:37
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:24
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\isExportEnabled
‪isExportEnabled()
Definition: BackendUserAuthentication.php:2078
‪TYPO3\CMS\Core\Utility\GeneralUtility\inList
‪static bool inList($list, $item)
Definition: GeneralUtility.php:422
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$workspace
‪int $workspace
Definition: BackendUserAuthentication.php:101
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\workspaceInit
‪workspaceInit()
Definition: BackendUserAuthentication.php:1478
‪TYPO3\CMS\Core\Resource\Filter\FileNameFilter
Definition: FileNameFilter.php:24
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\initializeWebmountsForElementBrowser
‪initializeWebmountsForElementBrowser()
Definition: BackendUserAuthentication.php:913
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$userident_column
‪string $userident_column
Definition: BackendUserAuthentication.php:148
‪TYPO3\CMS\Core\Utility\MathUtility\forceIntegerInRange
‪static int forceIntegerInRange(mixed $theInt, int $min, int $max=2000000000, int $defaultValue=0)
Definition: MathUtility.php:34
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\setTemporaryWorkspace
‪bool setTemporaryWorkspace($workspaceId)
Definition: BackendUserAuthentication.php:1662
‪TYPO3\CMS\Core\Utility\StringUtility
Definition: StringUtility.php:24
‪TYPO3\CMS\Core\Authentication\Event\AfterUserLoggedInEvent
Definition: AfterUserLoggedInEvent.php:27
‪TYPO3\CMS\Core\Http\ImmediateResponseException
Definition: ImmediateResponseException.php:35
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$workspaceRec
‪array $workspaceRec
Definition: BackendUserAuthentication.php:106
‪TYPO3\CMS\Core\Utility\GeneralUtility\intExplode
‪static list< int > intExplode(string $delimiter, string $string, bool $removeEmptyValues=false)
Definition: GeneralUtility.php:756
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\checkWorkspaceCurrent
‪checkWorkspaceCurrent()
Definition: BackendUserAuthentication.php:1621
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\checkFullLanguagesAccess
‪bool checkFullLanguagesAccess($table, $record)
Definition: BackendUserAuthentication.php:586
‪TYPO3\CMS\Core\Routing\BackendEntryPointResolver
Definition: BackendEntryPointResolver.php:29
‪TYPO3\CMS\Core\Database\Connection\PARAM_INT_ARRAY
‪const PARAM_INT_ARRAY
Definition: Connection.php:72
‪TYPO3\CMS\Core\Core\Environment\getContext
‪static getContext()
Definition: Environment.php:128
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\workspaceCheckStageForCurrent
‪bool workspaceCheckStageForCurrent($stage)
Definition: BackendUserAuthentication.php:791
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\workspaceCanCreateNewRecord
‪workspaceCanCreateNewRecord(string $table)
Definition: BackendUserAuthentication.php:772
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\isImportEnabled
‪isImportEnabled()
Definition: BackendUserAuthentication.php:2067
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$fileStorages
‪TYPO3 CMS Core Resource ResourceStorage[] $fileStorages
Definition: BackendUserAuthentication.php:129
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$writeStdLog
‪bool $writeStdLog
Definition: BackendUserAuthentication.php:191
‪TYPO3\CMS\Core\Utility\GeneralUtility\trimExplode
‪static list< string > trimExplode(string $delim, string $string, bool $removeEmptyValues=false, int $limit=0)
Definition: GeneralUtility.php:822
‪TYPO3\CMS\Core\SysLog\Type\toLevel
‪static toLevel(int $type)
Definition: Type.php:81
‪TYPO3\CMS\Core\SysLog\Type
Definition: Type.php:28
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication
Definition: AbstractUserAuthentication.php:65
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getDefaultWorkspace
‪int getDefaultWorkspace()
Definition: BackendUserAuthentication.php:1692
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\writeUC
‪writeUC()
Definition: AbstractUserAuthentication.php:922
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$errorMsg
‪string $errorMsg
Definition: BackendUserAuthentication.php:120
‪TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction
Definition: WorkspaceRestriction.php:39