‪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;
39 use ‪TYPO3\CMS\Core\SysLog\Error as SystemLogErrorClassification;
41 use ‪TYPO3\CMS\Core\SysLog\Type as SystemLogType;
50 use TYPO3\CMS\Install\Service\SessionService;
51 
60 {
61  public const ‪ROLE_SYSTEMMAINTAINER = 'systemMaintainer';
62 
67  public ‪$usergroup_column = 'usergroup';
68 
73  public ‪$usergroup_table = 'be_groups';
74 
80  public ‪$groupData = [
81  'allowed_languages' => '',
82  'tables_select' => '',
83  'tables_modify' => '',
84  'pagetypes_select' => '',
85  'non_exclude_fields' => '',
86  'explicit_allowdeny' => '',
87  'custom_options' => '',
88  'file_permissions' => '',
89  ];
90 
95  public ‪$userGroupsUID = [];
96 
103  public int ‪$workspace = -99;
104 
109  public ‪$workspaceRec = [];
110 
111  protected ?‪UserTsConfig ‪$userTsConfig = null;
112 
117  protected bool ‪$userTSUpdated = false;
118 
124  public ‪$errorMsg = '';
125 
131 
135  protected ‪$fileStorages;
136 
140  protected ‪$filePermissions;
141 
146  public ‪$user_table = 'be_users';
147 
152  public ‪$username_column = 'username';
153 
158  public ‪$userident_column = 'password';
159 
164  public ‪$userid_column = 'uid';
165 
169  public ‪$lastLogin_column = 'lastlogin';
170 
175  public ‪$enablecolumns = [
176  'rootLevel' => 1,
177  'deleted' => 'deleted',
178  'disabled' => 'disable',
179  'starttime' => 'starttime',
180  'endtime' => 'endtime',
181  ];
182 
188  protected ‪$formfield_uname = 'username';
189 
195  protected ‪$formfield_uident = 'userident';
196 
202  protected ‪$formfield_status = 'login_status';
203 
208  public ‪$writeStdLog = true;
209 
214  public ‪$writeAttemptLog = true;
215 
220  public ‪$firstMainGroup = 0;
221 
232  public ‪$uc_default = [
233  // serialized content that is used to store interface pane and menu positions. Set by the logout.php-script
234  'moduleData' => [],
235  // user-data for the modules
236  'emailMeAtLogin' => 0,
237  'titleLen' => 50,
238  'edit_docModuleUpload' => '1',
239  ];
240 
245  public ‪$loginType = 'BE';
246 
250  public function ‪__construct()
251  {
252  $this->name = ‪self::getCookieName();
253  parent::__construct();
254  }
255 
262  public function ‪isAdmin()
263  {
264  return is_array($this->user) && (($this->user['admin'] ?? 0) & 1) == 1;
265  }
266 
274  protected function ‪isMemberOfGroup(int $groupId): bool
275  {
276  if (!empty($this->userGroupsUID) && $groupId) {
277  return in_array($groupId, $this->userGroupsUID, true);
278  }
279  return false;
280  }
281 
297  public function ‪doesUserHaveAccess($row, $perms)
298  {
299  $userPerms = $this->‪calcPerms($row);
300  return ($userPerms & $perms) == $perms;
301  }
302 
317  public function ‪isInWebMount($idOrRow, $readPerms = '')
318  {
319  if ($this->‪isAdmin()) {
320  return 1;
321  }
322  $checkRec = [];
323  $fetchPageFromDatabase = true;
324  if (is_array($idOrRow)) {
325  if (!isset($idOrRow['uid'])) {
326  throw new \RuntimeException('The given page record is invalid. Missing uid.', 1578950324);
327  }
328  $checkRec = $idOrRow;
329  $id = (int)$idOrRow['uid'];
330  // ensure the required fields are present on the record
331  if (isset($checkRec['t3ver_oid'], $checkRec[‪$GLOBALS['TCA']['pages']['ctrl']['languageField']], $checkRec[‪$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField']])) {
332  $fetchPageFromDatabase = false;
333  }
334  } else {
335  $id = (int)$idOrRow;
336  }
337  if ($fetchPageFromDatabase) {
338  // Check if input id is an offline version page in which case we will map id to the online version:
339  $checkRec = BackendUtility::getRecord(
340  'pages',
341  $id,
342  't3ver_oid,'
343  . ‪$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'] . ','
344  . ‪$GLOBALS['TCA']['pages']['ctrl']['languageField']
345  );
346  }
347  if ((int)($checkRec['t3ver_oid'] ?? 0) > 0) {
348  $id = (int)$checkRec['t3ver_oid'];
349  }
350  // if current rec is a translation then get uid from l10n_parent instead
351  // because web mounts point to pages in default language and rootline returns uids of default languages
352  if ((int)($checkRec[‪$GLOBALS['TCA']['pages']['ctrl']['languageField'] ?? null] ?? 0) !== 0
353  && (int)($checkRec[‪$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'] ?? null] ?? 0) !== 0
354  ) {
355  $id = (int)$checkRec[‪$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField']];
356  }
357  if (!$readPerms) {
358  $readPerms = $this->‪getPagePermsClause(‪Permission::PAGE_SHOW);
359  }
360  if ($id > 0) {
361  $wM = $this->‪returnWebmounts();
362  $rL = BackendUtility::BEgetRootLine($id, ' AND ' . $readPerms, true);
363  foreach ($rL as $v) {
364  if ($v['uid'] && in_array($v['uid'], $wM)) {
365  return $v['uid'];
366  }
367  }
368  }
369  return null;
370  }
371 
377  public function ‪isSystemMaintainer(): bool
378  {
379  if (!$this->‪isAdmin()) {
380  return false;
381  }
382 
384  return false;
385  }
386  if (‪Environment::getContext()->isDevelopment()) {
387  return true;
388  }
389  $systemMaintainers = ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['systemMaintainers'] ?? [];
390  $systemMaintainers = array_map(intval(...), $systemMaintainers);
391  if (!empty($systemMaintainers)) {
392  return in_array((int)$this->user['uid'], $systemMaintainers, true);
393  }
394  // No system maintainers set up yet, so any admin is allowed to access the modules
395  // but explicitly no system maintainers allowed (empty string in TYPO3_CONF_VARS).
396  // @todo: this needs to be adjusted once system maintainers can log into the install tool with their credentials
397  if (isset(‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['systemMaintainers'])
398  && empty(‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['systemMaintainers'])) {
399  return false;
400  }
401  return true;
402  }
403 
420  public function ‪getPagePermsClause($perms)
421  {
422  if (is_array($this->user)) {
423  if ($this->‪isAdmin()) {
424  return ' 1=1';
425  }
426  // Make sure it's integer.
427  $perms = (int)$perms;
428  $expressionBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
429  ->getQueryBuilderForTable('pages')
430  ->expr();
431 
432  // User
433  $constraint = $expressionBuilder->or(
434  $expressionBuilder->comparison(
435  $expressionBuilder->bitAnd('pages.perms_everybody', $perms),
437  $perms
438  ),
439  $expressionBuilder->and(
440  $expressionBuilder->eq('pages.perms_userid', (int)$this->user['uid']),
441  $expressionBuilder->comparison(
442  $expressionBuilder->bitAnd('pages.perms_user', $perms),
444  $perms
445  )
446  )
447  );
448 
449  // Group (if any is set)
450  if (!empty($this->userGroupsUID)) {
451  $constraint = $constraint->with(
452  $expressionBuilder->and(
453  $expressionBuilder->in(
454  'pages.perms_groupid',
455  $this->userGroupsUID
456  ),
457  $expressionBuilder->comparison(
458  $expressionBuilder->bitAnd('pages.perms_group', $perms),
460  $perms
461  )
462  )
463  );
464  }
465 
466  $constraint = ' (' . (string)$constraint . ')';
467 
468  // ****************
469  // getPagePermsClause-HOOK
470  // ****************
471  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauthgroup.php']['getPagePermsClause'] ?? [] as $_funcRef) {
472  $_params = ['currentClause' => $constraint, 'perms' => $perms];
473  $constraint = GeneralUtility::callUserFunction($_funcRef, $_params, $this);
474  }
475  return $constraint;
476  }
477  return ' 1=0';
478  }
479 
489  public function ‪calcPerms($row)
490  {
491  // Return 31 for admin users.
492  if ($this->‪isAdmin()) {
493  return ‪Permission::ALL;
494  }
495  // Return 0 if page is not within the allowed web mount
496  if (!$this->‪isInWebMount($row)) {
497  return ‪Permission::NOTHING;
498  }
499  $out = ‪Permission::NOTHING;
500  if (
501  isset($row['perms_userid']) && isset($row['perms_user']) && isset($row['perms_groupid'])
502  && isset($row['perms_group']) && isset($row['perms_everybody']) && !empty($this->userGroupsUID)
503  ) {
504  if ($this->user['uid'] == $row['perms_userid']) {
505  $out |= $row['perms_user'];
506  }
507  if ($this->‪isMemberOfGroup((int)$row['perms_groupid'])) {
508  $out |= $row['perms_group'];
509  }
510  $out |= $row['perms_everybody'];
511  }
512  // ****************
513  // CALCPERMS hook
514  // ****************
515  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauthgroup.php']['calcPerms'] ?? [] as $_funcRef) {
516  $_params = [
517  'row' => $row,
518  'outputPermissions' => $out,
519  ];
520  $out = GeneralUtility::callUserFunction($_funcRef, $_params, $this);
521  }
522  return $out;
523  }
524 
534  public function ‪check($type, $value)
535  {
536  return isset($this->groupData[$type])
537  && ($this->‪isAdmin() || ‪GeneralUtility::inList($this->groupData[$type], (string)$value));
538  }
539 
548  public function ‪checkAuthMode($table, $field, $value)
549  {
550  // Admin users can do anything:
551  if ($this->‪isAdmin()) {
552  return true;
553  }
554  // Allow all blank values:
555  if ((string)$value === '') {
556  return true;
557  }
558  // Allow dividers:
559  if ($value === '--div--') {
560  return true;
561  }
562  // Certain characters are not allowed in the value
563  if (preg_match('/[:|,]/', $value)) {
564  return false;
565  }
566  // Initialize:
567  $testValue = $table . ':' . $field . ':' . $value;
568  $out = true;
569  if (!‪GeneralUtility::inList($this->groupData['explicit_allowdeny'], $testValue)) {
570  $out = false;
571  }
572  return $out;
573  }
574 
581  public function ‪checkLanguageAccess($langValue)
582  {
583  // The users language list must be non-blank - otherwise all languages are allowed.
584  if (trim($this->groupData['allowed_languages']) !== '') {
585  $langValue = (int)$langValue;
586  // Language must either be explicitly allowed OR the lang Value be "-1" (all languages)
587  if ($langValue != -1 && !$this->‪check('allowed_languages', (string)$langValue)) {
588  return false;
589  }
590  }
591  return true;
592  }
593 
601  public function ‪checkFullLanguagesAccess($table, ‪$record)
602  {
603  if (!$this->‪checkLanguageAccess(0)) {
604  return false;
605  }
606 
607  if (BackendUtility::isTableLocalizable($table)) {
608  $pointerField = ‪$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'];
609  $pointerValue = ‪$record[$pointerField] > 0 ? ‪$record[$pointerField] : ‪$record['uid'];
610  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
611  $queryBuilder->getRestrictions()
612  ->removeAll()
613  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
614  ->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, $this->workspace));
615  $recordLocalizations = $queryBuilder->select('*')
616  ->from($table)
617  ->where(
618  $queryBuilder->expr()->eq(
619  $pointerField,
620  $queryBuilder->createNamedParameter($pointerValue, ‪Connection::PARAM_INT)
621  )
622  )
623  ->executeQuery()
624  ->fetchAllAssociative();
625 
626  foreach ($recordLocalizations as $recordLocalization) {
627  if (!$this->‪checkLanguageAccess($recordLocalization[‪$GLOBALS['TCA'][$table]['ctrl']['languageField']])) {
628  return false;
629  }
630  }
631  }
632  return true;
633  }
634 
651  public function ‪recordEditAccessInternals($table, $idOrRow, $newRecord = false, $deletedRecord = false, $checkFullLanguageAccess = false): bool
652  {
653  if (!isset(‪$GLOBALS['TCA'][$table])) {
654  return false;
655  }
656  // Always return TRUE for Admin users.
657  if ($this->‪isAdmin()) {
658  return true;
659  }
660  // Fetching the record if the $idOrRow variable was not an array on input:
661  if (!is_array($idOrRow)) {
662  if ($deletedRecord) {
663  $idOrRow = BackendUtility::getRecord($table, $idOrRow, '*', '', false);
664  } else {
665  $idOrRow = BackendUtility::getRecord($table, $idOrRow);
666  }
667  if (!is_array($idOrRow)) {
668  $this->errorMsg = 'ERROR: Record could not be fetched.';
669  return false;
670  }
671  }
672  // Checking languages:
673  if ($table === 'pages' && $checkFullLanguageAccess && !$this->‪checkFullLanguagesAccess($table, $idOrRow)) {
674  return false;
675  }
676  if (‪$GLOBALS['TCA'][$table]['ctrl']['languageField'] ?? false) {
677  // Language field must be found in input row - otherwise it does not make sense.
678  if (isset($idOrRow[‪$GLOBALS['TCA'][$table]['ctrl']['languageField']])) {
679  if (!$this->‪checkLanguageAccess($idOrRow[‪$GLOBALS['TCA'][$table]['ctrl']['languageField']])) {
680  $this->errorMsg = 'ERROR: Language was not allowed.';
681  return false;
682  }
683  if (
684  $checkFullLanguageAccess && $idOrRow[‪$GLOBALS['TCA'][$table]['ctrl']['languageField']] == 0
685  && !$this->‪checkFullLanguagesAccess($table, $idOrRow)
686  ) {
687  $this->errorMsg = 'ERROR: Related/affected language was not allowed.';
688  return false;
689  }
690  } else {
691  $this->errorMsg = 'ERROR: The "languageField" field named "'
692  . ‪$GLOBALS['TCA'][$table]['ctrl']['languageField'] . '" was not found in testing record!';
693  return false;
694  }
695  }
696  // Checking authMode fields:
697  if (is_array(‪$GLOBALS['TCA'][$table]['columns'])) {
698  foreach (‪$GLOBALS['TCA'][$table]['columns'] as $fieldName => $fieldValue) {
699  if (isset($idOrRow[$fieldName])
700  && ($fieldValue['config']['type'] ?? '') === 'select'
701  && ($fieldValue['config']['authMode'] ?? false)
702  && !$this->‪checkAuthMode($table, $fieldName, $idOrRow[$fieldName])) {
703  $this->errorMsg = 'ERROR: authMode "' . $fieldValue['config']['authMode']
704  . '" failed for field "' . $fieldName . '" with value "'
705  . $idOrRow[$fieldName] . '" evaluated';
706  return false;
707  }
708  }
709  }
710  // Checking "editlock" feature (doesn't apply to new records)
711  if (!$newRecord && (‪$GLOBALS['TCA'][$table]['ctrl']['editlock'] ?? false)) {
712  if (isset($idOrRow[‪$GLOBALS['TCA'][$table]['ctrl']['editlock']])) {
713  if ($idOrRow[‪$GLOBALS['TCA'][$table]['ctrl']['editlock']]) {
714  $this->errorMsg = 'ERROR: Record was locked for editing. Only admin users can change this state.';
715  return false;
716  }
717  } else {
718  $this->errorMsg = 'ERROR: The "editLock" field named "' . ‪$GLOBALS['TCA'][$table]['ctrl']['editlock']
719  . '" was not found in testing record!';
720  return false;
721  }
722  }
723  // Checking record permissions
724  // THIS is where we can include a check for "perms_" fields for other records than pages...
725  // Process any hooks
726  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauthgroup.php']['recordEditAccessInternals'] ?? [] as $funcRef) {
727  $params = [
728  'table' => $table,
729  'idOrRow' => $idOrRow,
730  'newRecord' => $newRecord,
731  ];
732  if (!GeneralUtility::callUserFunction($funcRef, $params, $this)) {
733  return false;
734  }
735  }
736  // Finally, return TRUE if all is well.
737  return true;
738  }
739 
745  public function ‪mayMakeShortcut()
746  {
747  return ($this->‪getTSConfig()['options.']['enableBookmarks'] ?? false)
748  && !($this->‪getTSConfig()['options.']['mayNotCreateEditBookmarks'] ?? false);
749  }
750 
758  public function ‪workspaceAllowsLiveEditingInTable(string $table): bool
759  {
760  // In live workspace the record can be added/modified
761  if ($this->workspace === 0) {
762  return true;
763  }
764  // Workspace setting allows to "live edit" records of tables without versioning
765  if (($this->workspaceRec['live_edit'] ?? false)
766  && !BackendUtility::isTableWorkspaceEnabled($table)
767  ) {
768  return true;
769  }
770  // Always for Live workspace AND if live-edit is enabled
771  // and tables are completely without versioning it is ok as well.
772  if (‪$GLOBALS['TCA'][$table]['ctrl']['versioningWS_alwaysAllowLiveEdit'] ?? false) {
773  return true;
774  }
775  // If the answer is FALSE it means the only valid way to create or edit records by creating records in the workspace
776  return false;
777  }
778 
787  public function ‪workspaceCanCreateNewRecord(string $table): bool
788  {
789  // If LIVE records cannot be created due to workspace restrictions, prepare creation of placeholder-record
790  if (!$this->‪workspaceAllowsLiveEditingInTable($table) && !BackendUtility::isTableWorkspaceEnabled($table)) {
791  return false;
792  }
793  return true;
794  }
795 
806  public function ‪workspaceCheckStageForCurrent($stage)
807  {
808  // Always allow for admins
809  if ($this->‪isAdmin()) {
810  return true;
811  }
812  // Always OK for live workspace
813  if ($this->workspace === 0 || !‪ExtensionManagementUtility::isLoaded('workspaces')) {
814  return true;
815  }
816  $stage = (int)$stage;
817  $stat = $this->‪checkWorkspaceCurrent();
818  $accessType = $stat['_ACCESS'];
819  // Workspace owners are always allowed for stage change
820  if ($accessType === 'owner') {
821  return true;
822  }
823 
824  // Check if custom staging is activated
825  ‪$workspaceRec = BackendUtility::getRecord('sys_workspace', $stat['uid']);
826  if (‪$workspaceRec['custom_stages'] > 0 && $stage !== 0 && $stage !== -10) {
827  // Get custom stage record
828  $workspaceStageRec = BackendUtility::getRecord('sys_workspace_stage', $stage);
829  // Check if the user is responsible for the current stage
830  if (
831  $accessType === 'member'
832  && ‪GeneralUtility::inList($workspaceStageRec['responsible_persons'] ?? '', 'be_users_' . $this->user['uid'])
833  ) {
834  return true;
835  }
836  // Check if the user is in a group which is responsible for the current stage
837  foreach ($this->userGroupsUID as $groupUid) {
838  if (
839  $accessType === 'member'
840  && ‪GeneralUtility::inList($workspaceStageRec['responsible_persons'] ?? '', 'be_groups_' . $groupUid)
841  ) {
842  return true;
843  }
844  }
845  } elseif ($stage === -10 || $stage === -20) {
846  // Nobody is allowed to do that except the owner (which was checked above)
847  return false;
848  } elseif (
849  $accessType === 'reviewer' && $stage <= 1
850  || $accessType === 'member' && $stage <= 0
851  ) {
852  return true;
853  }
854  return false;
855  }
856 
872  public function ‪getTSConfig(): array
873  {
874  return $this->‪getUserTsConfig()?->getUserTsConfigArray() ?? [];
875  }
876 
883  {
884  return ‪$this->userTsConfig;
885  }
886 
894  public function ‪returnWebmounts()
895  {
896  return (string)$this->groupData['webmounts'] != '' ? explode(',', $this->groupData['webmounts']) : [];
897  }
898 
905  public function ‪setWebmounts(array $mountPointUids, $append = false)
906  {
907  if (empty($mountPointUids)) {
908  return;
909  }
910  if ($append) {
911  $currentWebMounts = GeneralUtility::intExplode(',', (string)($this->groupData['webmounts'] ?? ''));
912  $mountPointUids = array_merge($currentWebMounts, $mountPointUids);
913  }
914  $this->groupData['webmounts'] = implode(',', array_unique($mountPointUids));
915  }
916 
929  {
930  $alternativeWebmountPoint = (int)$this->‪getSessionData('pageTree_temporaryMountPoint');
931  if ($alternativeWebmountPoint) {
932  $alternativeWebmountPoint = GeneralUtility::intExplode(',', (string)$alternativeWebmountPoint);
933  $this->‪setWebmounts($alternativeWebmountPoint);
934  return;
935  }
936 
937  $alternativeWebmountPoints = trim($this->‪getTSConfig()['options.']['pageTree.']['altElementBrowserMountPoints'] ?? '');
938  $appendAlternativeWebmountPoints = $this->‪getTSConfig()['options.']['pageTree.']['altElementBrowserMountPoints.']['append'] ?? '';
939  if ($alternativeWebmountPoints) {
940  $alternativeWebmountPoints = GeneralUtility::intExplode(',', $alternativeWebmountPoints);
941  $this->‪setWebmounts($alternativeWebmountPoints, $appendAlternativeWebmountPoints);
942  }
943  }
944 
953  public function ‪jsConfirmation(int $bitmask): bool
954  {
955  $alertPopupsSetting = trim((string)($this->‪getTSConfig()['options.']['alertPopups'] ?? ''));
956  $alertPopupsSetting = ‪MathUtility::canBeInterpretedAsInteger($alertPopupsSetting)
957  ? ‪MathUtility::forceIntegerInRange((int)$alertPopupsSetting, 0, ‪JsConfirmation::ALL)
958  : JsConfirmation::ALL;
959 
960  return (new JsConfirmation($alertPopupsSetting))->get($bitmask);
961  }
962 
971  public function ‪fetchGroupData()
972  {
973  if ($this->user['uid']) {
974  // Get lists for the be_user record and set them as default/primary values.
975  // Enabled Backend Modules
976  $this->groupData['modules'] = $this->user['userMods'] ?? '';
977  // Add available widgets
978  $this->groupData['available_widgets'] = $this->user['available_widgets'] ?? '';
979  // Add allowed mfa providers
980  $this->groupData['mfa_providers'] = $this->user['mfa_providers'] ?? '';
981  // Add Allowed Languages
982  $this->groupData['allowed_languages'] = $this->user['allowed_languages'] ?? '';
983  // Set user value for workspace permissions.
984  $this->groupData['workspace_perms'] = $this->user['workspace_perms'] ?? 0;
985  // Database mountpoints
986  $this->groupData['webmounts'] = $this->user['db_mountpoints'] ?? '';
987  // File mountpoints
988  $this->groupData['filemounts'] = $this->user['file_mountpoints'] ?? '';
989  // Fileoperation permissions
990  $this->groupData['file_permissions'] = $this->user['file_permissions'] ?? '';
991 
992  // Get the groups and accumulate their permission settings
993  $mountOptions = new BackendGroupMountOption((int)($this->user['options'] ?? 0));
994  $groupResolver = GeneralUtility::makeInstance(GroupResolver::class);
995  $resolvedGroups = $groupResolver->resolveGroupsForUser($this->user, $this->usergroup_table);
996  foreach ($resolvedGroups as $groupInfo) {
997  $groupInfo += [
998  'uid' => 0,
999  'db_mountpoints' => '',
1000  'file_mountpoints' => '',
1001  'groupMods' => '',
1002  'availableWidgets' => '',
1003  'mfa_providers' => '',
1004  'tables_select' => '',
1005  'tables_modify' => '',
1006  'pagetypes_select' => '',
1007  'non_exclude_fields' => '',
1008  'explicit_allowdeny' => '',
1009  'allowed_languages' => '',
1010  'custom_options' => '',
1011  'file_permissions' => '',
1012  'workspace_perms' => 0, // Bitflag.
1013  ];
1014  // Add the group uid to internal arrays.
1015  $this->userGroupsUID[] = (int)$groupInfo['uid'];
1016  $this->userGroups[(int)$groupInfo['uid']] = $groupInfo;
1017  // Mount group database-mounts
1018  if ($mountOptions->shouldUserIncludePageMountsFromAssociatedGroups()) {
1019  $this->groupData['webmounts'] .= ',' . $groupInfo['db_mountpoints'];
1020  }
1021  // Mount group file-mounts
1022  if ($mountOptions->shouldUserIncludeFileMountsFromAssociatedGroups()) {
1023  $this->groupData['filemounts'] .= ',' . $groupInfo['file_mountpoints'];
1024  }
1025  // Gather permission detail fields
1026  $this->groupData['modules'] .= ',' . $groupInfo['groupMods'];
1027  $this->groupData['available_widgets'] .= ',' . $groupInfo['availableWidgets'];
1028  $this->groupData['mfa_providers'] .= ',' . $groupInfo['mfa_providers'];
1029  $this->groupData['tables_select'] .= ',' . $groupInfo['tables_select'];
1030  $this->groupData['tables_modify'] .= ',' . $groupInfo['tables_modify'];
1031  $this->groupData['pagetypes_select'] .= ',' . $groupInfo['pagetypes_select'];
1032  $this->groupData['non_exclude_fields'] .= ',' . $groupInfo['non_exclude_fields'];
1033  $this->groupData['explicit_allowdeny'] .= ',' . $groupInfo['explicit_allowdeny'];
1034  $this->groupData['allowed_languages'] .= ',' . $groupInfo['allowed_languages'];
1035  $this->groupData['custom_options'] .= ',' . $groupInfo['custom_options'];
1036  $this->groupData['file_permissions'] .= ',' . $groupInfo['file_permissions'];
1037  // Setting workspace permissions:
1038  $this->groupData['workspace_perms'] |= $groupInfo['workspace_perms'];
1039  if (!$this->firstMainGroup) {
1040  $this->firstMainGroup = (int)$groupInfo['uid'];
1041  }
1042  }
1043 
1044  // Populating the $this->userGroupsUID -array with the groups in the order in which they were LAST included.
1045  // Finally, this is the list of group_uid's in the order they are parsed (including subgroups)
1046  // and without duplicates (duplicates are presented with their last entrance in the list,
1047  // which thus reflects the order of the TypoScript in TSconfig)
1048  $this->userGroupsUID = array_reverse(array_unique(array_reverse($this->userGroupsUID)));
1049 
1050  $this->‪prepareUserTsConfig();
1051 
1052  // Processing webmounts
1053  // Admin's always have the root mounted
1054  if ($this->‪isAdmin() && !($this->‪getTSConfig()['options.']['dontMountAdminMounts'] ?? false)) {
1055  $this->groupData['webmounts'] = '0,' . $this->groupData['webmounts'];
1056  }
1057  // The lists are cleaned for duplicates
1058  $this->groupData['webmounts'] = ‪StringUtility::uniqueList($this->groupData['webmounts'] ?? '');
1059  $this->groupData['pagetypes_select'] = ‪StringUtility::uniqueList($this->groupData['pagetypes_select'] ?? '');
1060  $this->groupData['tables_select'] = ‪StringUtility::uniqueList(($this->groupData['tables_modify'] ?? '') . ',' . ($this->groupData['tables_select'] ?? ''));
1061  $this->groupData['tables_modify'] = ‪StringUtility::uniqueList($this->groupData['tables_modify'] ?? '');
1062  $this->groupData['non_exclude_fields'] = ‪StringUtility::uniqueList($this->groupData['non_exclude_fields'] ?? '');
1063  $this->groupData['explicit_allowdeny'] = ‪StringUtility::uniqueList($this->groupData['explicit_allowdeny'] ?? '');
1064  $this->groupData['allowed_languages'] = ‪StringUtility::uniqueList($this->groupData['allowed_languages'] ?? '');
1065  $this->groupData['custom_options'] = ‪StringUtility::uniqueList($this->groupData['custom_options'] ?? '');
1066  $this->groupData['modules'] = ‪StringUtility::uniqueList($this->groupData['modules'] ?? '');
1067  $this->groupData['available_widgets'] = ‪StringUtility::uniqueList($this->groupData['available_widgets'] ?? '');
1068  $this->groupData['mfa_providers'] = ‪StringUtility::uniqueList($this->groupData['mfa_providers'] ?? '');
1069  $this->groupData['file_permissions'] = ‪StringUtility::uniqueList($this->groupData['file_permissions'] ?? '');
1070 
1071  // Check if the user access to all web mounts set
1072  if (!empty(trim($this->groupData['webmounts']))) {
1073  $validWebMounts = $this->‪filterValidWebMounts($this->groupData['webmounts']);
1074  $this->groupData['webmounts'] = implode(',', $validWebMounts);
1075  }
1076  // Setting up workspace situation (after webmounts are processed!):
1077  $this->‪workspaceInit();
1078  }
1079  }
1080 
1089  protected function ‪filterValidWebMounts(string $listOfWebMounts): array
1090  {
1091  // Checking read access to web mounts if there are mounts points (not empty string, false or 0)
1092  $allWebMounts = explode(',', $listOfWebMounts);
1093  // Selecting all web mounts with permission clause for reading
1094  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
1095  $queryBuilder->getRestrictions()
1096  ->removeAll()
1097  ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
1098 
1099  $readablePagesOfWebMounts = $queryBuilder->select('uid')
1100  ->from('pages')
1101  // @todo DOCTRINE: check how to make getPagePermsClause() portable
1102  ->where(
1104  $queryBuilder->expr()->in(
1105  'uid',
1106  $queryBuilder->createNamedParameter(
1107  GeneralUtility::intExplode(',', $listOfWebMounts),
1108  Connection::PARAM_INT_ARRAY
1109  )
1110  )
1111  )
1112  ->executeQuery()
1113  ->fetchAllAssociative();
1114  $readablePagesOfWebMounts = array_column(($readablePagesOfWebMounts ?: []), 'uid', 'uid');
1115  foreach ($allWebMounts as $key => $mountPointUid) {
1116  // If the mount ID is NOT found among selected pages, unset it:
1117  if ($mountPointUid > 0 && !isset($readablePagesOfWebMounts[$mountPointUid])) {
1118  unset($allWebMounts[$key]);
1119  }
1120  }
1121  return $allWebMounts;
1122  }
1123 
1127  protected function ‪prepareUserTsConfig(): void
1128  {
1129  $tsConfigFactory = GeneralUtility::makeInstance(UserTsConfigFactory::class);
1130  $this->userTsConfig = $tsConfigFactory->create($this);
1131  if (!empty($this->‪getUserTsConfig()->getUserTsConfigArray()['setup.']['override.'])) {
1132  // @todo: This logic is ugly. user TSconfig "setup.override." is used to force options
1133  // in the user settings module, along with "setup.fields." and "setup.default.".
1134  // See the docs about this.
1135  // The fun part is, this is merged into user UC. As such, whenever these setup
1136  // options are used, user UC has to be updated. The toggle below triggers this
1137  // and initiates an update query of this users UC.
1138  // Before v12, this was only triggered if user TSconfig could not be fetched from
1139  // cache, but this was flawed, too: When two users had the same user TSconfig, UC
1140  // of one user would be updated, but not UC of the other user if caches were not
1141  // cleared in between their two calls.
1142  // This toggle and UC overriding should vanish altogether: It would be better if
1143  // user TSconfig no longer overlays UC, instead the settings / setup module
1144  // controller should look at user TSconfig "setup." on the fly when rendering, and
1145  // consumers that access user setup / settings values should get values overloaded
1146  // on the fly as well using some helper or a late init logic or similar.
1147  $this->userTSUpdated = true;
1148  }
1149  }
1150 
1155  protected function ‪initializeFileStorages()
1156  {
1157  $this->fileStorages = [];
1158  $storageRepository = GeneralUtility::makeInstance(StorageRepository::class);
1159  // Admin users have all file storages visible, without any filters
1160  if ($this->‪isAdmin()) {
1161  $storageObjects = $storageRepository->findAll();
1162  foreach ($storageObjects as $storageObject) {
1163  $this->fileStorages[$storageObject->getUid()] = $storageObject;
1164  }
1165  } else {
1166  // Regular users only have storages that are defined in their filemounts
1167  // Permissions and file mounts for the storage are added in StoragePermissionAspect
1168  foreach ($this->‪getFileMountRecords() as $row) {
1169  if (!str_contains($row['identifier'] ?? '', ':')) {
1170  // Skip record since the file mount identifier is invalid, this usually happens
1171  // when file storages are selected. file mounts and groupHomePath and userHomePath should go through
1172  continue;
1173  }
1174  [$base] = GeneralUtility::trimExplode(':', $row['identifier'], true);
1175  $base = (int)$base;
1176  if (!array_key_exists($base, $this->fileStorages)) {
1177  $storageObject = $storageRepository->findByUid($base);
1178  if ($storageObject) {
1179  $this->fileStorages[$storageObject->getUid()] = $storageObject;
1180  }
1181  }
1182  }
1183  }
1184 
1185  // This has to be called always in order to set certain filters
1187  }
1188 
1195  public function ‪getCategoryMountPoints()
1196  {
1197  $categoryMountPoints = '';
1198 
1199  // Category mounts of the groups
1200  if (is_array($this->userGroups)) {
1201  foreach ($this->userGroups as $group) {
1202  if ($group['category_perms']) {
1203  $categoryMountPoints .= ',' . $group['category_perms'];
1204  }
1205  }
1206  }
1207 
1208  // Category mounts of the user record
1209  if ($this->user['category_perms']) {
1210  $categoryMountPoints .= ',' . $this->user['category_perms'];
1211  }
1212 
1213  // Make the ids unique
1214  $categoryMountPoints = GeneralUtility::trimExplode(',', $categoryMountPoints);
1215  $categoryMountPoints = array_filter($categoryMountPoints); // remove empty value
1216  $categoryMountPoints = array_unique($categoryMountPoints); // remove unique value
1217 
1218  return $categoryMountPoints;
1219  }
1220 
1228  public function ‪getFileMountRecords()
1229  {
1230  $runtimeCache = GeneralUtility::makeInstance(CacheManager::class)->getCache('runtime');
1231  $fileMountRecordCache = $runtimeCache->get('backendUserAuthenticationFileMountRecords') ?: [];
1232 
1233  if (!empty($fileMountRecordCache)) {
1234  return $fileMountRecordCache;
1235  }
1236 
1237  $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
1238 
1239  // Processing file mounts (both from the user and the groups)
1240  $fileMounts = array_unique(GeneralUtility::intExplode(',', (string)($this->groupData['filemounts'] ?? ''), true));
1241 
1242  // Limit file mounts if set in workspace record
1243  if ($this->workspace > 0 && !empty($this->workspaceRec['file_mountpoints'])) {
1244  $workspaceFileMounts = GeneralUtility::intExplode(',', (string)$this->workspaceRec['file_mountpoints'], true);
1245  $fileMounts = array_intersect($fileMounts, $workspaceFileMounts);
1246  }
1247 
1248  if (!empty($fileMounts)) {
1249  $orderBy = ‪$GLOBALS['TCA']['sys_filemounts']['ctrl']['default_sortby'] ?? 'sorting';
1250 
1251  $queryBuilder = $connectionPool->getQueryBuilderForTable('sys_filemounts');
1252  $queryBuilder->getRestrictions()
1253  ->removeAll()
1254  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
1255  ->add(GeneralUtility::makeInstance(HiddenRestriction::class))
1256  ->add(GeneralUtility::makeInstance(RootLevelRestriction::class));
1257 
1258  $queryBuilder->select('*')
1259  ->from('sys_filemounts')
1260  ->where(
1261  $queryBuilder->expr()->in('uid', $queryBuilder->createNamedParameter($fileMounts, Connection::PARAM_INT_ARRAY))
1262  );
1263 
1264  foreach (‪QueryHelper::parseOrderBy($orderBy) as $fieldAndDirection) {
1265  $queryBuilder->addOrderBy(...$fieldAndDirection);
1266  }
1267 
1268  $fileMountRecords = $queryBuilder->executeQuery()->fetchAllAssociative();
1269  if ($fileMountRecords !== false) {
1270  foreach ($fileMountRecords as $fileMount) {
1271  $readOnlySuffix = (bool)$fileMount['read_only'] ? '-readonly' : '';
1272  $fileMountRecordCache[$fileMount['identifier'] . $readOnlySuffix] = $fileMount;
1273  }
1274  }
1275  }
1276 
1277  // Read-only file mounts
1278  $readOnlyMountPoints = trim($this->‪getTSConfig()['options.']['folderTree.']['altElementBrowserMountPoints'] ?? '');
1279  if ($readOnlyMountPoints) {
1280  // We cannot use the API here but need to fetch the default storage record directly
1281  // to not instantiate it (which directly applies mount points) before all mount points are resolved!
1282  $queryBuilder = $connectionPool->getQueryBuilderForTable('sys_file_storage');
1283  $defaultStorageRow = $queryBuilder->select('uid')
1284  ->from('sys_file_storage')
1285  ->where(
1286  $queryBuilder->expr()->eq('is_default', $queryBuilder->createNamedParameter(1, ‪Connection::PARAM_INT))
1287  )
1288  ->setMaxResults(1)
1289  ->executeQuery()
1290  ->fetchAssociative();
1291 
1292  $readOnlyMountPointArray = GeneralUtility::trimExplode(',', $readOnlyMountPoints);
1293  foreach ($readOnlyMountPointArray as $readOnlyMountPoint) {
1294  $readOnlyMountPointConfiguration = GeneralUtility::trimExplode(':', $readOnlyMountPoint);
1295  if (count($readOnlyMountPointConfiguration) === 2) {
1296  // A storage is passed in the configuration
1297  $storageUid = (int)$readOnlyMountPointConfiguration[0];
1298  $path = $readOnlyMountPointConfiguration[1];
1299  } else {
1300  if (empty($defaultStorageRow)) {
1301  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);
1302  }
1303  // Backwards compatibility: If no storage is passed, we use the default storage
1304  $storageUid = $defaultStorageRow['uid'];
1305  $path = $readOnlyMountPointConfiguration[0];
1306  }
1307  $fileMountRecordCache[$storageUid . $path . '-readonly'] = [
1308  'base' => $storageUid,
1309  'title' => $path,
1310  'path' => $path,
1311  'read_only' => true,
1312  ];
1313  }
1314  }
1315 
1316  // Personal or Group filemounts are not accessible if file mount list is set in workspace record
1317  if ($this->workspace <= 0 || empty($this->workspaceRec['file_mountpoints'])) {
1318  // If userHomePath is set, we attempt to mount it
1319  if (‪$GLOBALS['TYPO3_CONF_VARS']['BE']['userHomePath'] ?? false) {
1320  [$userHomeStorageUid, $userHomeFilter] = explode(':', ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['userHomePath'], 2);
1321  $userHomeStorageUid = (int)$userHomeStorageUid;
1322  $userHomeFilter = '/' . ltrim($userHomeFilter, '/');
1323  if ($userHomeStorageUid > 0) {
1324  // Try and mount with [uid]_[username]
1325  $path = $userHomeFilter . $this->user['uid'] . '_' . $this->user['username'] . ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['userUploadDir'];
1326  $fileMountRecordCache[$userHomeStorageUid . $path] = [
1327  'base' => $userHomeStorageUid,
1328  'identifier' => $userHomeStorageUid . ':' . $path,
1329  'title' => $this->user['username'],
1330  'path' => $path,
1331  'read_only' => false,
1332  'user_mount' => true,
1333  ];
1334  // Try and mount with only [uid]
1335  $path = $userHomeFilter . $this->user['uid'] . ‪$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  }
1345  }
1346 
1347  // Mount group home-dirs
1348  $mountOptions = new BackendGroupMountOption((int)($this->user['options'] ?? 0));
1349  if ((‪$GLOBALS['TYPO3_CONF_VARS']['BE']['groupHomePath'] ?? '') !== '' && $mountOptions->shouldUserIncludeFileMountsFromAssociatedGroups()) {
1350  // If groupHomePath is set, we attempt to mount it
1351  [$groupHomeStorageUid, $groupHomeFilter] = explode(':', ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['groupHomePath'], 2);
1352  $groupHomeStorageUid = (int)$groupHomeStorageUid;
1353  $groupHomeFilter = '/' . ltrim($groupHomeFilter, '/');
1354  if ($groupHomeStorageUid > 0) {
1355  foreach ($this->userGroups as ‪$groupData) {
1356  $path = $groupHomeFilter . ‪$groupData['uid'];
1357  $fileMountRecordCache[$groupHomeStorageUid . $path] = [
1358  'base' => $groupHomeStorageUid,
1359  'identifier' => $groupHomeStorageUid . ':' . $path,
1360  'title' => ‪$groupData['title'],
1361  'path' => $path,
1362  'read_only' => false,
1363  'user_mount' => true,
1364  ];
1365  }
1366  }
1367  }
1368  }
1369 
1370  $runtimeCache->set('backendUserAuthenticationFileMountRecords', $fileMountRecordCache);
1371  return $fileMountRecordCache;
1372  }
1373 
1381  public function ‪getFileStorages()
1382  {
1383  // Initializing file mounts after the groups are fetched
1384  if ($this->fileStorages === null) {
1385  $this->‪initializeFileStorages();
1386  }
1387  return ‪$this->fileStorages;
1388  }
1389 
1396  {
1397  // Add the option for also displaying the non-hidden files
1398  if ($this->uc['showHiddenFilesAndFolders'] ?? false) {
1400  }
1401  }
1402 
1436  public function ‪getFilePermissions(): array
1437  {
1438  if ($this->filePermissions === null) {
1440  // File permissions
1441  'addFile' => false,
1442  'readFile' => false,
1443  'writeFile' => false,
1444  'copyFile' => false,
1445  'moveFile' => false,
1446  'renameFile' => false,
1447  'deleteFile' => false,
1448  // Folder permissions
1449  'addFolder' => false,
1450  'readFolder' => false,
1451  'writeFolder' => false,
1452  'copyFolder' => false,
1453  'moveFolder' => false,
1454  'renameFolder' => false,
1455  'deleteFolder' => false,
1456  'recursivedeleteFolder' => false,
1457  ];
1458  if ($this->‪isAdmin()) {
1459  ‪$filePermissions = array_map(is_bool(...), ‪$filePermissions);
1460  } else {
1461  $userGroupRecordPermissions = GeneralUtility::trimExplode(',', $this->groupData['file_permissions'] ?? '', true);
1462  array_walk(
1463  $userGroupRecordPermissions,
1464  static function (string $permission) use (&‪$filePermissions): void {
1465  ‪$filePermissions[$permission] = true;
1466  }
1467  );
1469  // Finally overlay any user TSconfig
1470  $permissionsTsConfig = $this->‪getTSConfig()['permissions.']['file.']['default.'] ?? [];
1471  if (!empty($permissionsTsConfig)) {
1472  array_walk(
1473  $permissionsTsConfig,
1474  static function (string $value, string $permission) use (&‪$filePermissions): void {
1475  ‪$filePermissions[$permission] = (bool)$value;
1476  }
1477  );
1478  }
1479  }
1480  $this->filePermissions = ‪$filePermissions;
1481  }
1483  }
1484 
1491  protected function ‪workspaceInit(): void
1492  {
1493  // Initializing workspace by evaluating and setting the workspace, possibly updating it in the user record!
1494  $this->‪setWorkspace($this->user['workspace_id']);
1495  // Limiting the DB mountpoints if there any selected in the workspace record
1497  $allowed_languages = (string)($this->‪getTSConfig()['options.']['workspaces.']['allowed_languages.'][‪$this->workspace] ?? '');
1498  if ($allowed_languages !== '') {
1499  $this->groupData['allowed_languages'] = ‪StringUtility::uniqueList($allowed_languages);
1500  }
1501  }
1502 
1506  protected function ‪initializeDbMountpointsInWorkspace()
1507  {
1508  $dbMountpoints = trim($this->workspaceRec['db_mountpoints'] ?? '');
1509  if ($this->workspace > 0 && $dbMountpoints != '') {
1510  $filteredDbMountpoints = [];
1511  // Notice: We cannot call $this->getPagePermsClause(1);
1512  // as usual because the group-list is not available at this point.
1513  // But bypassing is fine because all we want here is check if the
1514  // workspace mounts are inside the current webmounts rootline.
1515  // The actual permission checking on page level is done elsewhere
1516  // as usual anyway before the page tree is rendered.
1517  $readPerms = '1=1';
1518  // Traverse mount points of the workspace, add them,
1519  // but make sure they match against the users' DB mounts
1520 
1521  $workspaceWebMounts = GeneralUtility::intExplode(',', $dbMountpoints);
1522  $webMountsOfUser = GeneralUtility::intExplode(',', (string)($this->groupData['webmounts'] ?? ''));
1523  $webMountsOfUser = array_combine($webMountsOfUser, $webMountsOfUser) ?: [];
1524 
1525  $entryPointRootLineUids = [];
1526  foreach ($webMountsOfUser as $webMountPageId) {
1527  $rootLine = BackendUtility::BEgetRootLine($webMountPageId, '', true);
1528  $entryPointRootLineUids[$webMountPageId] = array_map(intval(...), array_column($rootLine, 'uid'));
1529  }
1530  foreach ($entryPointRootLineUids as $webMountOfUser => $uidsOfRootLine) {
1531  // Remove the DB mounts of the user if the DB mount is not in the list of
1532  // workspace mounts
1533  foreach ($workspaceWebMounts as $webmountOfWorkspace) {
1534  // This workspace DB mount is somewhere in the rootline of the users' web mount,
1535  // so this is "OK" to be included
1536  if (in_array($webmountOfWorkspace, $uidsOfRootLine, true)) {
1537  continue;
1538  }
1539  // Remove the user's DB Mount (possible via array_combine, see above)
1540  unset($webMountsOfUser[$webMountOfUser]);
1541  }
1542  }
1543  $dbMountpoints = array_merge($workspaceWebMounts, $webMountsOfUser);
1544  $dbMountpoints = array_unique($dbMountpoints);
1545  foreach ($dbMountpoints as $mpId) {
1546  if ($this->‪isInWebMount($mpId, $readPerms)) {
1547  $filteredDbMountpoints[] = $mpId;
1548  }
1549  }
1550  // Re-insert webmounts
1551  $this->groupData['webmounts'] = implode(',', $filteredDbMountpoints);
1552  }
1553  }
1554 
1562  public function ‪checkWorkspace(int|array $wsRec): array|false
1563  {
1564  // If not array, look up workspace record
1565  if (!is_array($wsRec)) {
1566  if ($wsRec === 0) {
1567  $wsRec = ['uid' => 0];
1568  } elseif (‪ExtensionManagementUtility::isLoaded('workspaces')) {
1569  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_workspace');
1570  $queryBuilder->getRestrictions()->add(GeneralUtility::makeInstance(RootLevelRestriction::class));
1571  $wsRec = $queryBuilder
1572  ->select('*')
1573  ->from('sys_workspace')
1574  ->where($queryBuilder->expr()->eq(
1575  'uid',
1576  $queryBuilder->createNamedParameter($wsRec, ‪Connection::PARAM_INT)
1577  ))
1578  ->executeQuery()
1579  ->fetchAssociative();
1580  }
1581  }
1582  // If wsRec is set to an array, evaluate it, otherwise return false
1583  if (!is_array($wsRec)) {
1584  return false;
1585  }
1586  if ($this->‪isAdmin()) {
1587  return array_merge($wsRec, ['_ACCESS' => 'admin']);
1588  }
1589  // User is in live, and be_groups.workspace_perms has bitmask=1 included
1590  if ($wsRec['uid'] === 0) {
1591  return $this->‪hasEditAccessToLiveWorkspace()
1592  ? array_merge($wsRec, ['_ACCESS' => 'online'])
1593  : false;
1594  }
1595  // Checking if the person is workspace owner
1596  if (‪GeneralUtility::inList($wsRec['adminusers'], 'be_users_' . $this->user['uid'])) {
1597  return array_merge($wsRec, ['_ACCESS' => 'owner']);
1598  }
1599  // Checking if the editor is owner through an included user group
1600  foreach ($this->userGroupsUID as $groupUid) {
1601  if (‪GeneralUtility::inList($wsRec['adminusers'], 'be_groups_' . $groupUid)) {
1602  return array_merge($wsRec, ['_ACCESS' => 'owner']);
1603  }
1604  }
1605  // Checking if the user is member of the workspace
1606  if (‪GeneralUtility::inList($wsRec['members'], 'be_users_' . $this->user['uid'])) {
1607  return array_merge($wsRec, ['_ACCESS' => 'member']);
1608  }
1609  // Checking if the user is member through an included user group
1610  foreach ($this->userGroupsUID as $groupUid) {
1611  if (‪GeneralUtility::inList($wsRec['members'], 'be_groups_' . $groupUid)) {
1612  return array_merge($wsRec, ['_ACCESS' => 'member']);
1613  }
1614  }
1615  return false;
1616  }
1617 
1622  protected function ‪hasEditAccessToLiveWorkspace(): bool
1623  {
1624  return (bool)(($this->groupData['workspace_perms'] ?? 0) & 1);
1625  }
1626 
1634  protected function ‪checkWorkspaceCurrent(): false|array|null
1635  {
1636  if (!isset($this->checkWorkspaceCurrent_cache)) {
1637  $this->checkWorkspaceCurrent_cache = $this->‪checkWorkspace($this->workspace);
1638  }
1640  }
1641 
1648  public function ‪setWorkspace($workspaceId)
1649  {
1650  // Check workspace validity and if not found, revert to default workspace.
1651  if (!$this->‪setTemporaryWorkspace($workspaceId)) {
1653  }
1654  // Unset access cache:
1655  $this->checkWorkspaceCurrent_cache = null;
1656  // If ID is different from the stored one, change it:
1657  if ((int)$this->workspace !== (int)$this->user['workspace_id']) {
1658  $this->user['workspace_id'] = ‪$this->workspace;
1659  GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('be_users')->update(
1660  'be_users',
1661  ['workspace_id' => $this->user['workspace_id']],
1662  ['uid' => (int)$this->user['uid']]
1663  );
1664  $this->‪writelog(SystemLogType::EXTENSION, SystemLogGenericAction::UNDEFINED, SystemLogErrorClassification::MESSAGE, 0, 'User changed workspace to "{workspace}"', ['workspace' => $this->workspace]);
1665  }
1666  }
1667 
1675  public function ‪setTemporaryWorkspace($workspaceId)
1676  {
1677  $workspaceRecord = $this->‪checkWorkspace((int)$workspaceId);
1678 
1679  if ($workspaceRecord) {
1680  $this->workspaceRec = $workspaceRecord;
1681  $this->workspace = (int)$workspaceId;
1682  return true;
1683  }
1684  return false;
1685  }
1686 
1691  protected function ‪setDefaultWorkspace(): void
1692  {
1693  $this->workspace = $this->‪getDefaultWorkspace();
1694  $this->workspaceRec = $this->‪checkWorkspace($this->workspace);
1695  }
1696 
1705  protected function ‪getDefaultWorkspace(): int
1706  {
1707  if (!‪ExtensionManagementUtility::isLoaded('workspaces')) {
1708  return 0;
1709  }
1710  // Online is default
1711  if ($this->‪checkWorkspace(0)) {
1712  return 0;
1713  }
1714  // Traverse all workspaces
1715  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_workspace');
1716  $queryBuilder->getRestrictions()->add(GeneralUtility::makeInstance(RootLevelRestriction::class));
1717  $result = $queryBuilder->select('*')
1718  ->from('sys_workspace')
1719  ->orderBy('title')
1720  ->executeQuery();
1721  while ($workspaceRecord = $result->fetchAssociative()) {
1722  if ($this->‪checkWorkspace($workspaceRecord)) {
1723  return (int)$workspaceRecord['uid'];
1724  }
1725  }
1726  // Otherwise -99 is the fallback
1727  return -99;
1728  }
1729 
1748  public function ‪writelog($type, $action, $error, $details_nr, ‪$details, $data, $tablename = '', $recuid = '', $recpid = '', $event_pid = -1, $NEWid = '', $userId = 0)
1749  {
1750  if (!$userId && !empty($this->user['uid'])) {
1751  $userId = $this->user['uid'];
1752  }
1753 
1754  if ($backuserid = $this->‪getOriginalUserIdWhenInSwitchUserMode()) {
1755  if (empty($data)) {
1756  $data = [];
1757  }
1758  $data['originalUser'] = $backuserid;
1759  }
1760 
1761  // @todo Remove this once this method is properly typed.
1762  $type = (int)$type;
1763 
1764  ‪$fields = [
1765  'userid' => (int)$userId,
1766  'type' => $type,
1767  'channel' => ‪Type::toChannel($type),
1768  'level' => ‪Type::toLevel($type),
1769  'action' => (int)$action,
1770  'error' => (int)$error,
1771  'details_nr' => (int)$details_nr,
1772  'details' => ‪$details,
1773  'log_data' => empty($data) ? '' : json_encode($data),
1774  'tablename' => $tablename,
1775  'recuid' => (int)$recuid,
1776  'IP' => (string)GeneralUtility::getIndpEnv('REMOTE_ADDR'),
1777  'tstamp' => ‪$GLOBALS['EXEC_TIME'] ?? time(),
1778  'event_pid' => (int)$event_pid,
1779  'NEWid' => $NEWid,
1780  'workspace' => $this->workspace,
1781  ];
1782 
1783  $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('sys_log');
1784  $connection->insert(
1785  'sys_log',
1786  ‪$fields,
1787  [
1804  ]
1805  );
1806 
1807  return (int)$connection->lastInsertId('sys_log');
1808  }
1809 
1816  public static function ‪getCookieName()
1817  {
1818  $configuredCookieName = trim(‪$GLOBALS['TYPO3_CONF_VARS']['BE']['cookieName']);
1819  if (empty($configuredCookieName)) {
1820  $configuredCookieName = 'be_typo_user';
1821  }
1822  return $configuredCookieName;
1823  }
1824 
1834  public function ‪backendCheckLogin(ServerRequestInterface $request = null)
1835  {
1836  if (empty($this->user['uid'])) {
1837  // @todo: throw a proper AccessDeniedException in TYPO3 v12.0. and handle this functionality in the calling code
1838  $entryPointResolver = GeneralUtility::makeInstance(BackendEntryPointResolver::class);
1839  ‪$url = $entryPointResolver->getUriFromRequest(‪$GLOBALS['TYPO3_REQUEST']);
1840  throw new ImmediateResponseException(new RedirectResponse(‪$url, 303), 1607271747);
1841  }
1842  if ($this->‪isUserAllowedToLogin()) {
1843  $this->‪initializeBackendLogin($request);
1844  } else {
1845  // @todo: throw a proper AccessDeniedException in TYPO3 v12.0.
1846  throw new \RuntimeException('Login Error: TYPO3 is in maintenance mode at the moment. Only administrators are allowed access.', 1294585860);
1847  }
1848  }
1849 
1853  public function ‪initializeBackendLogin(ServerRequestInterface $request = null): void
1854  {
1855  // The groups are fetched and ready for permission checking in this initialization.
1856  // Tables.php must be read before this because stuff like the modules has impact in this
1857  $this->‪fetchGroupData();
1858  // Setting the UC array. It's needed with fetchGroupData first, due to default/overriding of values.
1859  $this->‪backendSetUC();
1860  if ($this->loginSessionStarted && !($this->‪getSessionData('mfa') ?? false)) {
1861  // Handling user logged in. By checking for the mfa session key, it's ensured, the
1862  // handling is only done once, since MfaController does the handling on its own.
1863  $this->‪handleUserLoggedIn();
1864  }
1865  }
1866 
1873  public function ‪handleUserLoggedIn(ServerRequestInterface $request = null): void
1874  {
1875  // Also, if there is a recovery link set, unset it now
1876  // this will be moved into its own Event at a later stage.
1877  // If a token was set previously, this is now unset, as it was now possible to log-in
1878  if ($this->user['password_reset_token'] ?? '') {
1879  GeneralUtility::makeInstance(ConnectionPool::class)
1880  ->getConnectionForTable($this->user_table)
1881  ->update($this->user_table, ['password_reset_token' => ''], ['uid' => $this->user['uid']]);
1882  }
1883 
1884  $event = new AfterUserLoggedInEvent($this, $request);
1885  GeneralUtility::makeInstance(EventDispatcherInterface::class)->dispatch($event);
1886  }
1887 
1895  public function ‪backendSetUC()
1896  {
1897  // Setting defaults if uc is empty
1898  $updated = false;
1899  if (empty($this->uc)) {
1900  $this->uc = array_merge(
1901  $this->uc_default,
1902  (array)‪$GLOBALS['TYPO3_CONF_VARS']['BE']['defaultUC'],
1903  GeneralUtility::removeDotsFromTS((array)($this->‪getTSConfig()['setup.']['default.'] ?? []))
1904  );
1905  $this->‪overrideUC();
1906  $updated = true;
1907  }
1908  // If TSconfig is updated, update the defaultUC.
1909  if ($this->userTSUpdated) {
1910  $this->‪overrideUC();
1911  $updated = true;
1912  }
1913  // Saving if updated.
1914  if ($updated) {
1915  $this->‪writeUC();
1916  }
1917  }
1918 
1925  public function ‪overrideUC()
1926  {
1927  $this->uc = array_merge($this->uc, (array)($this->‪getTSConfig()['setup.']['override.'] ?? []));
1928  }
1929 
1935  public function ‪resetUC()
1936  {
1937  $this->user['uc'] = '';
1938  $this->uc = [];
1939  $this->‪backendSetUC();
1940  }
1941 
1954  public function ‪isUserAllowedToLogin()
1955  {
1956  $isUserAllowedToLogin = false;
1957  $adminOnlyMode = (int)‪$GLOBALS['TYPO3_CONF_VARS']['BE']['adminOnly'];
1958  // Backend user is allowed if adminOnly is not set or user is an admin:
1959  if (!$adminOnlyMode || $this->‪isAdmin()) {
1960  $isUserAllowedToLogin = true;
1961  } elseif ($backUserId = $this->‪getOriginalUserIdWhenInSwitchUserMode()) {
1962  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('be_users');
1963  $isUserAllowedToLogin = (bool)$queryBuilder->count('uid')
1964  ->from('be_users')
1965  ->where(
1966  $queryBuilder->expr()->eq(
1967  'uid',
1968  $queryBuilder->createNamedParameter($backUserId, ‪Connection::PARAM_INT)
1969  ),
1970  $queryBuilder->expr()->eq('admin', $queryBuilder->createNamedParameter(1, ‪Connection::PARAM_INT))
1971  )
1972  ->executeQuery()
1973  ->fetchOne();
1974  }
1975  return $isUserAllowedToLogin;
1976  }
1977 
1981  public function ‪logoff()
1982  {
1983  if (isset(‪$GLOBALS['BE_USER'])
1984  && ‪$GLOBALS['BE_USER'] instanceof self
1985  && isset(‪$GLOBALS['BE_USER']->user['uid'])
1986  ) {
1987  GeneralUtility::makeInstance(FormProtectionFactory::class)->createForType('backend')->clean();
1988  // Release the locked records
1989  $this->‪releaseLockedRecords((int)$GLOBALS['BE_USER']->user['uid']);
1990 
1991  if ($this->‪isSystemMaintainer()) {
1992  // If user is system maintainer, destroy its possibly valid install tool session.
1993  $session = new SessionService();
1994  $session->destroySession(‪$GLOBALS['TYPO3_REQUEST'] ?? null);
1995  }
1996  }
1997  parent::logoff();
1998  }
2003  protected function ‪releaseLockedRecords(int $userId)
2004  {
2005  if ($userId > 0) {
2006  GeneralUtility::makeInstance(ConnectionPool::class)
2007  ->getConnectionForTable('sys_lockedrecords')
2008  ->delete(
2009  'sys_lockedrecords',
2010  ['userid' => $userId]
2011  );
2012  }
2013  }
2014 
2022  public function ‪getOriginalUserIdWhenInSwitchUserMode(): ?int
2023  {
2024  $originalUserId = $this->‪getSessionData('backuserid');
2025  return $originalUserId ? (int)$originalUserId : null;
2026  }
2027 
2031  protected function ‪evaluateMfaRequirements(): void
2032  {
2033  // In case the current session is a "switch-user" session, MFA is not required
2034  if ($this->‪getOriginalUserIdWhenInSwitchUserMode() !== null) {
2035  $this->logger->debug('MFA is skipped in switch user mode', [
2036  $this->userid_column => $this->user[$this->userid_column],
2037  $this->username_column => $this->user[$this->username_column],
2038  ]);
2039  return;
2040  }
2041  parent::evaluateMfaRequirements();
2042  }
2043 
2049  public function ‪isMfaSetupRequired(): bool
2050  {
2051  $authConfig = $this->‪getTSConfig()['auth.']['mfa.'] ?? [];
2052 
2053  if (isset($authConfig['required'])) {
2054  // user TSconfig overrules global configuration
2055  return (bool)$authConfig['required'];
2056  }
2057 
2058  $globalConfig = (int)(‪$GLOBALS['TYPO3_CONF_VARS']['BE']['requireMfa'] ?? 0);
2059  if ($globalConfig <= 1) {
2060  // 0 and 1 can directly be used by type-casting to boolean
2061  return (bool)$globalConfig;
2062  }
2063 
2064  // check the system maintainer / admin / non-admin options
2065  $isAdmin = $this->‪isAdmin();
2066  return ($globalConfig === 2 && !$isAdmin)
2067  || ($globalConfig === 3 && $isAdmin)
2068  || ($globalConfig === 4 && $this->‪isSystemMaintainer());
2069  }
2070 
2076  public function ‪isImportEnabled(): bool
2077  {
2078  return $this->‪isAdmin()
2079  || ($this->‪getTSConfig()['options.']['impexp.']['enableImportForNonAdminUser'] ?? false);
2080  }
2081 
2087  public function ‪isExportEnabled(): bool
2088  {
2089  return $this->‪isAdmin()
2090  || ($this->‪getTSConfig()['options.']['impexp.']['enableExportForNonAdminUser'] ?? false);
2091  }
2092 
2098  public function ‪shallDisplayDebugInformation(): bool
2099  {
2100  return (‪$GLOBALS['TYPO3_CONF_VARS']['BE']['debug'] ?? false) && $this->‪isAdmin();
2101  }
2102 }
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\returnWebmounts
‪array returnWebmounts()
Definition: BackendUserAuthentication.php:871
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\evaluateUserSpecificFileFilterSettings
‪evaluateUserSpecificFileFilterSettings()
Definition: BackendUserAuthentication.php:1372
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\isMemberOfGroup
‪isMemberOfGroup(int $groupId)
Definition: BackendUserAuthentication.php:251
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\isSystemMaintainer
‪isSystemMaintainer()
Definition: BackendUserAuthentication.php:354
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\handleUserLoggedIn
‪handleUserLoggedIn(ServerRequestInterface $request=null)
Definition: BackendUserAuthentication.php:1850
‪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:628
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getUserTsConfig
‪getUserTsConfig()
Definition: BackendUserAuthentication.php:859
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$usergroup_table
‪string $usergroup_table
Definition: BackendUserAuthentication.php:71
‪TYPO3\CMS\Core\Database\Connection\PARAM_INT
‪const PARAM_INT
Definition: Connection.php:50
‪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:882
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\EQ
‪const EQ
Definition: ExpressionBuilder.php:41
‪TYPO3\CMS\Core\SysLog\Action
Definition: Cache.php:18
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$formfield_status
‪string $formfield_status
Definition: BackendUserAuthentication.php:184
‪TYPO3\CMS\Core\TypoScript\UserTsConfig
Definition: UserTsConfig.php:28
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getPagePermsClause
‪string getPagePermsClause($perms)
Definition: BackendUserAuthentication.php:397
‪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:1483
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\initializeFileStorages
‪initializeFileStorages()
Definition: BackendUserAuthentication.php:1132
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$formfield_uname
‪string $formfield_uname
Definition: BackendUserAuthentication.php:172
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\calcPerms
‪int calcPerms($row)
Definition: BackendUserAuthentication.php:466
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\workspaceAllowsLiveEditingInTable
‪workspaceAllowsLiveEditingInTable(string $table)
Definition: BackendUserAuthentication.php:735
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\checkAuthMode
‪bool checkAuthMode($table, $field, $value)
Definition: BackendUserAuthentication.php:525
‪TYPO3\CMS\Core\Authentication
Definition: AbstractAuthenticationService.php:16
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\prepareUserTsConfig
‪prepareUserTsConfig()
Definition: BackendUserAuthentication.php:1104
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$usergroup_column
‪string $usergroup_column
Definition: BackendUserAuthentication.php:66
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getTSConfig
‪array getTSConfig()
Definition: BackendUserAuthentication.php:849
‪TYPO3\CMS\Core\Type\Bitmask\Permission\NOTHING
‪const NOTHING
Definition: Permission.php:30
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$firstMainGroup
‪int $firstMainGroup
Definition: BackendUserAuthentication.php:199
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\isAdmin
‪bool isAdmin()
Definition: BackendUserAuthentication.php:239
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$uc_default
‪array $uc_default
Definition: BackendUserAuthentication.php:210
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\check
‪bool check($type, $value)
Definition: BackendUserAuthentication.php:511
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\fetchGroupData
‪fetchGroupData()
Definition: BackendUserAuthentication.php:948
‪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\setDefaultWorkspace
‪setDefaultWorkspace()
Definition: BackendUserAuthentication.php:1668
‪$fields
‪$fields
Definition: pages.php:5
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$writeAttemptLog
‪bool $writeAttemptLog
Definition: BackendUserAuthentication.php:194
‪TYPO3\CMS\Core\Database\Connection\PARAM_STR
‪const PARAM_STR
Definition: Connection.php:55
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getFileStorages
‪TYPO3 CMS Core Resource ResourceStorage[] getFileStorages()
Definition: BackendUserAuthentication.php:1358
‪TYPO3\CMS\Core\Type\Bitmask\Permission
Definition: Permission.php:26
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\isLoaded
‪static isLoaded(string $key)
Definition: ExtensionManagementUtility.php:54
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\backendCheckLogin
‪backendCheckLogin(ServerRequestInterface $request=null)
Definition: BackendUserAuthentication.php:1811
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\checkWorkspace
‪array false checkWorkspace(int|array $wsRec)
Definition: BackendUserAuthentication.php:1539
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$formfield_uident
‪string $formfield_uident
Definition: BackendUserAuthentication.php:178
‪TYPO3\CMS\Core\SysLog\Type\toChannel
‪static toChannel(int $type)
Definition: Type.php:76
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility
Definition: ExtensionManagementUtility.php:31
‪TYPO3\CMS\Core\Type\Bitmask\BackendGroupMountOption
Definition: BackendGroupMountOption.php:27
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\isInWebMount
‪int null isInWebMount($idOrRow, $readPerms='')
Definition: BackendUserAuthentication.php:294
‪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:1172
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\isMfaSetupRequired
‪isMfaSetupRequired()
Definition: BackendUserAuthentication.php:2026
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getCookieName
‪static string getCookieName()
Definition: BackendUserAuthentication.php:1793
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getFileMountRecords
‪array getFileMountRecords()
Definition: BackendUserAuthentication.php:1205
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\jsConfirmation
‪bool jsConfirmation(int $bitmask)
Definition: BackendUserAuthentication.php:930
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\mayMakeShortcut
‪bool mayMakeShortcut()
Definition: BackendUserAuthentication.php:722
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\resetUC
‪resetUC()
Definition: BackendUserAuthentication.php:1912
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getFilePermissions
‪getFilePermissions()
Definition: BackendUserAuthentication.php:1413
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$userid_column
‪string $userid_column
Definition: BackendUserAuthentication.php:151
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$filePermissions
‪array null $filePermissions
Definition: BackendUserAuthentication.php:131
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$user_table
‪string $user_table
Definition: BackendUserAuthentication.php:136
‪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:1066
‪TYPO3\CMS\Core\Database\Query\Restriction\RootLevelRestriction
Definition: RootLevelRestriction.php:27
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\evaluateMfaRequirements
‪evaluateMfaRequirements()
Definition: BackendUserAuthentication.php:2008
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\shallDisplayDebugInformation
‪shallDisplayDebugInformation()
Definition: BackendUserAuthentication.php:2075
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\setWorkspace
‪setWorkspace($workspaceId)
Definition: BackendUserAuthentication.php:1625
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getOriginalUserIdWhenInSwitchUserMode
‪int null getOriginalUserIdWhenInSwitchUserMode()
Definition: BackendUserAuthentication.php:1999
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$userTSUpdated
‪bool $userTSUpdated
Definition: BackendUserAuthentication.php:112
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\backendSetUC
‪backendSetUC()
Definition: BackendUserAuthentication.php:1872
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\ROLE_SYSTEMMAINTAINER
‪const ROLE_SYSTEMMAINTAINER
Definition: BackendUserAuthentication.php:61
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\isUserAllowedToLogin
‪bool isUserAllowedToLogin()
Definition: BackendUserAuthentication.php:1931
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\hasEditAccessToLiveWorkspace
‪hasEditAccessToLiveWorkspace()
Definition: BackendUserAuthentication.php:1599
‪TYPO3\CMS\Core\Resource\StorageRepository
Definition: StorageRepository.php:38
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$groupData
‪array $groupData
Definition: BackendUserAuthentication.php:77
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\doesUserHaveAccess
‪bool doesUserHaveAccess($row, $perms)
Definition: BackendUserAuthentication.php:274
‪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:141
‪TYPO3\CMS\Core\SysLog\Error
Definition: Error.php:24
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\getSessionData
‪mixed getSessionData($key)
Definition: AbstractUserAuthentication.php:1001
‪TYPO3\CMS\Core\Cache\CacheManager
Definition: CacheManager.php:36
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\checkLanguageAccess
‪bool checkLanguageAccess($langValue)
Definition: BackendUserAuthentication.php:558
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:60
‪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:1830
‪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:123
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$userGroupsUID
‪array $userGroupsUID
Definition: BackendUserAuthentication.php:91
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$userTsConfig
‪UserTsConfig $userTsConfig
Definition: BackendUserAuthentication.php:106
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\overrideUC
‪overrideUC()
Definition: BackendUserAuthentication.php:1902
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$enablecolumns
‪array $enablecolumns
Definition: BackendUserAuthentication.php:160
‪TYPO3\CMS\Core\TypoScript\UserTsConfigFactory
Definition: UserTsConfigFactory.php:38
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$loginType
‪string $loginType
Definition: BackendUserAuthentication.php:222
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\logoff
‪logoff()
Definition: BackendUserAuthentication.php:1958
‪TYPO3\CMS\Core\Http\RedirectResponse
Definition: RedirectResponse.php:30
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\__construct
‪__construct()
Definition: BackendUserAuthentication.php:227
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\releaseLockedRecords
‪releaseLockedRecords(int $userId)
Definition: BackendUserAuthentication.php:1980
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:39
‪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:155
‪TYPO3\CMS\Core\FormProtection\FormProtectionFactory
Definition: FormProtectionFactory.php:44
‪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:1725
‪$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:2064
‪TYPO3\CMS\Core\Utility\GeneralUtility\inList
‪static bool inList($list, $item)
Definition: GeneralUtility.php:421
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$workspace
‪int $workspace
Definition: BackendUserAuthentication.php:99
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\workspaceInit
‪workspaceInit()
Definition: BackendUserAuthentication.php:1468
‪TYPO3\CMS\Core\Resource\Filter\FileNameFilter
Definition: FileNameFilter.php:24
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:48
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\initializeWebmountsForElementBrowser
‪initializeWebmountsForElementBrowser()
Definition: BackendUserAuthentication.php:905
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$userident_column
‪string $userident_column
Definition: BackendUserAuthentication.php:146
‪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:51
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\setTemporaryWorkspace
‪bool setTemporaryWorkspace($workspaceId)
Definition: BackendUserAuthentication.php:1652
‪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:104
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\checkWorkspaceCurrent
‪checkWorkspaceCurrent()
Definition: BackendUserAuthentication.php:1611
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\checkFullLanguagesAccess
‪bool checkFullLanguagesAccess($table, $record)
Definition: BackendUserAuthentication.php:578
‪TYPO3\CMS\Core\Routing\BackendEntryPointResolver
Definition: BackendEntryPointResolver.php:29
‪TYPO3\CMS\Core\Core\Environment\getContext
‪static getContext()
Definition: Environment.php:128
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\workspaceCheckStageForCurrent
‪bool workspaceCheckStageForCurrent($stage)
Definition: BackendUserAuthentication.php:783
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\workspaceCanCreateNewRecord
‪workspaceCanCreateNewRecord(string $table)
Definition: BackendUserAuthentication.php:764
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\isImportEnabled
‪isImportEnabled()
Definition: BackendUserAuthentication.php:2053
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$fileStorages
‪TYPO3 CMS Core Resource ResourceStorage[] $fileStorages
Definition: BackendUserAuthentication.php:127
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$writeStdLog
‪bool $writeStdLog
Definition: BackendUserAuthentication.php:189
‪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:64
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getDefaultWorkspace
‪int getDefaultWorkspace()
Definition: BackendUserAuthentication.php:1682
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\writeUC
‪writeUC()
Definition: AbstractUserAuthentication.php:921
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$errorMsg
‪string $errorMsg
Definition: BackendUserAuthentication.php:118
‪TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction
Definition: WorkspaceRestriction.php:39