‪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;
21 use TYPO3\CMS\Backend\Utility\BackendUtility;
44 use ‪TYPO3\CMS\Core\SysLog\Error as SystemLogErrorClassification;
46 use ‪TYPO3\CMS\Core\SysLog\Type as SystemLogType;
56 use TYPO3\CMS\Install\Service\SessionService;
57 
66 {
67  public const ‪ROLE_SYSTEMMAINTAINER = 'systemMaintainer';
68 
73  public ‪$usergroup_column = 'usergroup';
74 
79  public ‪$usergroup_table = 'be_groups';
80 
86  public ‪$groupData = [
87  'allowed_languages' => '',
88  'tables_select' => '',
89  'tables_modify' => '',
90  'pagetypes_select' => '',
91  'non_exclude_fields' => '',
92  'explicit_allowdeny' => '',
93  'custom_options' => '',
94  'file_permissions' => '',
95  ];
96 
101  public ‪$userGroupsUID = [];
102 
109  public int ‪$workspace = -99;
110 
115  public ‪$workspaceRec = [];
116 
117  protected ?‪UserTsConfig ‪$userTsConfig = null;
118 
123  protected bool ‪$userTSUpdated = false;
124 
130  public ‪$errorMsg = '';
131 
137 
141  protected ‪$fileStorages;
142 
146  protected ‪$filePermissions;
147 
152  public ‪$user_table = 'be_users';
153 
158  public ‪$username_column = 'username';
159 
164  public ‪$userident_column = 'password';
165 
170  public ‪$userid_column = 'uid';
171 
175  public ‪$lastLogin_column = 'lastlogin';
176 
181  public ‪$enablecolumns = [
182  'rootLevel' => 1,
183  'deleted' => 'deleted',
184  'disabled' => 'disable',
185  'starttime' => 'starttime',
186  'endtime' => 'endtime',
187  ];
188 
193  public ‪$formfield_uname = 'username';
194 
199  public ‪$formfield_uident = 'userident';
200 
205  public ‪$formfield_status = 'login_status';
206 
211  public ‪$writeStdLog = true;
212 
217  public ‪$writeAttemptLog = true;
218 
223  public ‪$firstMainGroup = 0;
224 
235  public ‪$uc_default = [
236  // serialized content that is used to store interface pane and menu positions. Set by the logout.php-script
237  'moduleData' => [],
238  // user-data for the modules
239  'emailMeAtLogin' => 0,
240  'titleLen' => 50,
241  'edit_RTE' => '1',
242  'edit_docModuleUpload' => '1',
243  ];
244 
249  public ‪$loginType = 'BE';
250 
254  public function ‪__construct()
255  {
256  $this->name = ‪self::getCookieName();
257  parent::__construct();
258  }
259 
266  public function ‪isAdmin()
267  {
268  return is_array($this->user) && (($this->user['admin'] ?? 0) & 1) == 1;
269  }
270 
280  public function ‪isMemberOfGroup($groupId)
281  {
282  $groupId = (int)$groupId;
283  if (!empty($this->userGroupsUID) && $groupId) {
284  return in_array($groupId, $this->userGroupsUID, true);
285  }
286  return false;
287  }
288 
304  public function ‪doesUserHaveAccess($row, $perms)
305  {
306  $userPerms = $this->‪calcPerms($row);
307  return ($userPerms & $perms) == $perms;
308  }
309 
324  public function ‪isInWebMount($idOrRow, $readPerms = '')
325  {
326  if ($this->‪isAdmin()) {
327  return 1;
328  }
329  $checkRec = [];
330  $fetchPageFromDatabase = true;
331  if (is_array($idOrRow)) {
332  if (!isset($idOrRow['uid'])) {
333  throw new \RuntimeException('The given page record is invalid. Missing uid.', 1578950324);
334  }
335  $checkRec = $idOrRow;
336  $id = (int)$idOrRow['uid'];
337  // ensure the required fields are present on the record
338  if (isset($checkRec['t3ver_oid'], $checkRec[‪$GLOBALS['TCA']['pages']['ctrl']['languageField']], $checkRec[‪$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField']])) {
339  $fetchPageFromDatabase = false;
340  }
341  } else {
342  $id = (int)$idOrRow;
343  }
344  if ($fetchPageFromDatabase) {
345  // Check if input id is an offline version page in which case we will map id to the online version:
346  $checkRec = BackendUtility::getRecord(
347  'pages',
348  $id,
349  't3ver_oid,'
350  . ‪$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'] . ','
351  . ‪$GLOBALS['TCA']['pages']['ctrl']['languageField']
352  );
353  }
354  if ((int)($checkRec['t3ver_oid'] ?? 0) > 0) {
355  $id = (int)$checkRec['t3ver_oid'];
356  }
357  // if current rec is a translation then get uid from l10n_parent instead
358  // because web mounts point to pages in default language and rootline returns uids of default languages
359  if ((int)($checkRec[‪$GLOBALS['TCA']['pages']['ctrl']['languageField'] ?? null] ?? 0) !== 0
360  && (int)($checkRec[‪$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'] ?? null] ?? 0) !== 0
361  ) {
362  $id = (int)$checkRec[‪$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField']];
363  }
364  if (!$readPerms) {
365  $readPerms = $this->‪getPagePermsClause(‪Permission::PAGE_SHOW);
366  }
367  if ($id > 0) {
368  $wM = $this->‪returnWebmounts();
369  $rL = BackendUtility::BEgetRootLine($id, ' AND ' . $readPerms, true);
370  foreach ($rL as $v) {
371  if ($v['uid'] && in_array($v['uid'], $wM)) {
372  return $v['uid'];
373  }
374  }
375  }
376  return null;
377  }
378 
387  public function ‪modAccess($conf)
388  {
389  trigger_error(
390  'BackendUserAuthentication->modAccess() will be removed in TYPO3 v13.0. Use the ModuleProvider API instead.',
391  E_USER_DEPRECATED
392  );
393 
394  $moduleName = $conf['name'] ?? '';
395  if (!GeneralUtility::makeInstance(ModuleProvider::class)->isModuleRegistered($moduleName)) {
396  throw new \RuntimeException('Fatal Error: This module "' . $moduleName . '" is not registered.', 1294586446);
397  }
398  // Workspaces check:
399  if (
400  !empty($conf['workspaces'])
402  && ($this->workspace !== 0 || !‪GeneralUtility::inList($conf['workspaces'], 'online'))
403  && ($this->workspace <= 0 || !‪GeneralUtility::inList($conf['workspaces'], 'custom'))
404  ) {
405  throw new \RuntimeException('Workspace Error: This module "' . $moduleName . '" is not available under the current workspace', 1294586447);
406  }
407  // Throws exception if conf[access] is set to system maintainer and the user is no system maintainer
408  if (str_contains($conf['access'] ?? '', self::ROLE_SYSTEMMAINTAINER) && !$this->‪isSystemMaintainer()) {
409  throw new \RuntimeException('This module "' . $moduleName . '" is only available as system maintainer', 1504804727);
410  }
411  // Returns TRUE if conf[access] is not set at all or if the user is admin
412  if (!($conf['access'] ?? false) || $this->‪isAdmin()) {
413  return true;
414  }
415  // If $conf['access'] is set but not with 'admin' then we return TRUE, if the module is found in the modList
416  $acs = false;
417  if ($moduleName && !str_contains($conf['access'] ?? '', 'admin')) {
418  $acs = $this->‪check('modules', $moduleName);
419  }
420  if (!$acs) {
421  throw new \RuntimeException('Access Error: You don\'t have access to this module.', 1294586448);
422  }
423  // User has access (Otherwise an exception would haven been thrown)
424  return true;
425  }
426 
432  public function ‪isSystemMaintainer(): bool
433  {
434  if (!$this->‪isAdmin()) {
435  return false;
436  }
437 
439  return false;
440  }
441  if (‪Environment::getContext()->isDevelopment()) {
442  return true;
443  }
444  $systemMaintainers = ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['systemMaintainers'] ?? [];
445  $systemMaintainers = array_map('intval', $systemMaintainers);
446  if (!empty($systemMaintainers)) {
447  return in_array((int)$this->user['uid'], $systemMaintainers, true);
448  }
449  // No system maintainers set up yet, so any admin is allowed to access the modules
450  // but explicitly no system maintainers allowed (empty string in TYPO3_CONF_VARS).
451  // @todo: this needs to be adjusted once system maintainers can log into the install tool with their credentials
452  if (isset(‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['systemMaintainers'])
453  && empty(‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['systemMaintainers'])) {
454  return false;
455  }
456  return true;
457  }
458 
475  public function ‪getPagePermsClause($perms)
476  {
477  if (is_array($this->user)) {
478  if ($this->‪isAdmin()) {
479  return ' 1=1';
480  }
481  // Make sure it's integer.
482  $perms = (int)$perms;
483  $expressionBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
484  ->getQueryBuilderForTable('pages')
485  ->expr();
486 
487  // User
488  $constraint = $expressionBuilder->or(
489  $expressionBuilder->comparison(
490  $expressionBuilder->bitAnd('pages.perms_everybody', $perms),
492  $perms
493  ),
494  $expressionBuilder->and(
495  $expressionBuilder->eq('pages.perms_userid', (int)$this->user['uid']),
496  $expressionBuilder->comparison(
497  $expressionBuilder->bitAnd('pages.perms_user', $perms),
499  $perms
500  )
501  )
502  );
503 
504  // Group (if any is set)
505  if (!empty($this->userGroupsUID)) {
506  $constraint = $constraint->with(
507  $expressionBuilder->and(
508  $expressionBuilder->in(
509  'pages.perms_groupid',
510  $this->userGroupsUID
511  ),
512  $expressionBuilder->comparison(
513  $expressionBuilder->bitAnd('pages.perms_group', $perms),
515  $perms
516  )
517  )
518  );
519  }
520 
521  $constraint = ' (' . (string)$constraint . ')';
522 
523  // ****************
524  // getPagePermsClause-HOOK
525  // ****************
526  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauthgroup.php']['getPagePermsClause'] ?? [] as $_funcRef) {
527  $_params = ['currentClause' => $constraint, 'perms' => $perms];
528  $constraint = GeneralUtility::callUserFunction($_funcRef, $_params, $this);
529  }
530  return $constraint;
531  }
532  return ' 1=0';
533  }
534 
544  public function ‪calcPerms($row)
545  {
546  // Return 31 for admin users.
547  if ($this->‪isAdmin()) {
548  return ‪Permission::ALL;
549  }
550  // Return 0 if page is not within the allowed web mount
551  if (!$this->‪isInWebMount($row)) {
552  return ‪Permission::NOTHING;
553  }
554  $out = ‪Permission::NOTHING;
555  if (
556  isset($row['perms_userid']) && isset($row['perms_user']) && isset($row['perms_groupid'])
557  && isset($row['perms_group']) && isset($row['perms_everybody']) && !empty($this->userGroupsUID)
558  ) {
559  if ($this->user['uid'] == $row['perms_userid']) {
560  $out |= $row['perms_user'];
561  }
562  if ($this->‪isMemberOfGroup($row['perms_groupid'])) {
563  $out |= $row['perms_group'];
564  }
565  $out |= $row['perms_everybody'];
566  }
567  // ****************
568  // CALCPERMS hook
569  // ****************
570  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauthgroup.php']['calcPerms'] ?? [] as $_funcRef) {
571  $_params = [
572  'row' => $row,
573  'outputPermissions' => $out,
574  ];
575  $out = GeneralUtility::callUserFunction($_funcRef, $_params, $this);
576  }
577  return $out;
578  }
579 
585  public function ‪isRTE(): bool
586  {
587  return (bool)($this->uc['edit_RTE'] ?? false);
588  }
589 
599  public function ‪check($type, $value)
600  {
601  return isset($this->groupData[$type])
602  && ($this->‪isAdmin() || ‪GeneralUtility::inList($this->groupData[$type], $value));
603  }
604 
613  public function ‪checkAuthMode($table, $field, $value)
614  {
615  // Admin users can do anything:
616  if ($this->‪isAdmin()) {
617  return true;
618  }
619  // Allow all blank values:
620  if ((string)$value === '') {
621  return true;
622  }
623  // Allow dividers:
624  if ($value === '--div--') {
625  return true;
626  }
627  // Certain characters are not allowed in the value
628  if (preg_match('/[:|,]/', $value)) {
629  return false;
630  }
631  // Initialize:
632  $testValue = $table . ':' . $field . ':' . $value;
633  $out = true;
634  if (!‪GeneralUtility::inList($this->groupData['explicit_allowdeny'], $testValue)) {
635  $out = false;
636  }
637  return $out;
638  }
639 
646  public function ‪checkLanguageAccess($langValue)
647  {
648  // The users language list must be non-blank - otherwise all languages are allowed.
649  if (trim($this->groupData['allowed_languages']) !== '') {
650  $langValue = (int)$langValue;
651  // Language must either be explicitly allowed OR the lang Value be "-1" (all languages)
652  if ($langValue != -1 && !$this->‪check('allowed_languages', (string)$langValue)) {
653  return false;
654  }
655  }
656  return true;
657  }
658 
666  public function ‪checkFullLanguagesAccess($table, ‪$record)
667  {
668  if (!$this->‪checkLanguageAccess(0)) {
669  return false;
670  }
671 
672  if (BackendUtility::isTableLocalizable($table)) {
673  $pointerField = ‪$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'];
674  $pointerValue = ‪$record[$pointerField] > 0 ? ‪$record[$pointerField] : ‪$record['uid'];
675  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
676  $queryBuilder->getRestrictions()
677  ->removeAll()
678  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
679  ->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, $this->workspace));
680  $recordLocalizations = $queryBuilder->select('*')
681  ->from($table)
682  ->where(
683  $queryBuilder->expr()->eq(
684  $pointerField,
685  $queryBuilder->createNamedParameter($pointerValue, ‪Connection::PARAM_INT)
686  )
687  )
688  ->executeQuery()
689  ->fetchAllAssociative();
690 
691  foreach ($recordLocalizations as $recordLocalization) {
692  if (!$this->‪checkLanguageAccess($recordLocalization[‪$GLOBALS['TCA'][$table]['ctrl']['languageField']])) {
693  return false;
694  }
695  }
696  }
697  return true;
698  }
699 
716  public function ‪recordEditAccessInternals($table, $idOrRow, $newRecord = false, $deletedRecord = false, $checkFullLanguageAccess = false): bool
717  {
718  if (!isset(‪$GLOBALS['TCA'][$table])) {
719  return false;
720  }
721  // Always return TRUE for Admin users.
722  if ($this->‪isAdmin()) {
723  return true;
724  }
725  // Fetching the record if the $idOrRow variable was not an array on input:
726  if (!is_array($idOrRow)) {
727  if ($deletedRecord) {
728  $idOrRow = BackendUtility::getRecord($table, $idOrRow, '*', '', false);
729  } else {
730  $idOrRow = BackendUtility::getRecord($table, $idOrRow);
731  }
732  if (!is_array($idOrRow)) {
733  $this->errorMsg = 'ERROR: Record could not be fetched.';
734  return false;
735  }
736  }
737  // Checking languages:
738  if ($table === 'pages' && $checkFullLanguageAccess && !$this->‪checkFullLanguagesAccess($table, $idOrRow)) {
739  return false;
740  }
741  if (‪$GLOBALS['TCA'][$table]['ctrl']['languageField'] ?? false) {
742  // Language field must be found in input row - otherwise it does not make sense.
743  if (isset($idOrRow[‪$GLOBALS['TCA'][$table]['ctrl']['languageField']])) {
744  if (!$this->‪checkLanguageAccess($idOrRow[‪$GLOBALS['TCA'][$table]['ctrl']['languageField']])) {
745  $this->errorMsg = 'ERROR: Language was not allowed.';
746  return false;
747  }
748  if (
749  $checkFullLanguageAccess && $idOrRow[‪$GLOBALS['TCA'][$table]['ctrl']['languageField']] == 0
750  && !$this->‪checkFullLanguagesAccess($table, $idOrRow)
751  ) {
752  $this->errorMsg = 'ERROR: Related/affected language was not allowed.';
753  return false;
754  }
755  } else {
756  $this->errorMsg = 'ERROR: The "languageField" field named "'
757  . ‪$GLOBALS['TCA'][$table]['ctrl']['languageField'] . '" was not found in testing record!';
758  return false;
759  }
760  }
761  // Checking authMode fields:
762  if (is_array(‪$GLOBALS['TCA'][$table]['columns'])) {
763  foreach (‪$GLOBALS['TCA'][$table]['columns'] as $fieldName => $fieldValue) {
764  if (isset($idOrRow[$fieldName])
765  && ($fieldValue['config']['type'] ?? '') === 'select'
766  && ($fieldValue['config']['authMode'] ?? false)
767  && !$this->‪checkAuthMode($table, $fieldName, $idOrRow[$fieldName])) {
768  $this->errorMsg = 'ERROR: authMode "' . $fieldValue['config']['authMode']
769  . '" failed for field "' . $fieldName . '" with value "'
770  . $idOrRow[$fieldName] . '" evaluated';
771  return false;
772  }
773  }
774  }
775  // Checking "editlock" feature (doesn't apply to new records)
776  if (!$newRecord && (‪$GLOBALS['TCA'][$table]['ctrl']['editlock'] ?? false)) {
777  if (isset($idOrRow[‪$GLOBALS['TCA'][$table]['ctrl']['editlock']])) {
778  if ($idOrRow[‪$GLOBALS['TCA'][$table]['ctrl']['editlock']]) {
779  $this->errorMsg = 'ERROR: Record was locked for editing. Only admin users can change this state.';
780  return false;
781  }
782  } else {
783  $this->errorMsg = 'ERROR: The "editLock" field named "' . ‪$GLOBALS['TCA'][$table]['ctrl']['editlock']
784  . '" was not found in testing record!';
785  return false;
786  }
787  }
788  // Checking record permissions
789  // THIS is where we can include a check for "perms_" fields for other records than pages...
790  // Process any hooks
791  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauthgroup.php']['recordEditAccessInternals'] ?? [] as $funcRef) {
792  $params = [
793  'table' => $table,
794  'idOrRow' => $idOrRow,
795  'newRecord' => $newRecord,
796  ];
797  if (!GeneralUtility::callUserFunction($funcRef, $params, $this)) {
798  return false;
799  }
800  }
801  // Finally, return TRUE if all is well.
802  return true;
803  }
804 
810  public function ‪mayMakeShortcut()
811  {
812  return ($this->‪getTSConfig()['options.']['enableBookmarks'] ?? false)
813  && !($this->‪getTSConfig()['options.']['mayNotCreateEditBookmarks'] ?? false);
814  }
815 
823  public function ‪workspaceAllowsLiveEditingInTable(string $table): bool
824  {
825  // In live workspace the record can be added/modified
826  if ($this->workspace === 0) {
827  return true;
828  }
829  // Workspace setting allows to "live edit" records of tables without versioning
830  if (($this->workspaceRec['live_edit'] ?? false)
831  && !BackendUtility::isTableWorkspaceEnabled($table)
832  ) {
833  return true;
834  }
835  // Always for Live workspace AND if live-edit is enabled
836  // and tables are completely without versioning it is ok as well.
837  if (‪$GLOBALS['TCA'][$table]['ctrl']['versioningWS_alwaysAllowLiveEdit'] ?? false) {
838  return true;
839  }
840  // If the answer is FALSE it means the only valid way to create or edit records by creating records in the workspace
841  return false;
842  }
843 
852  public function ‪workspaceCanCreateNewRecord(string $table): bool
853  {
854  // If LIVE records cannot be created due to workspace restrictions, prepare creation of placeholder-record
855  if (!$this->‪workspaceAllowsLiveEditingInTable($table) && !BackendUtility::isTableWorkspaceEnabled($table)) {
856  return false;
857  }
858  return true;
859  }
860 
871  public function ‪workspaceCheckStageForCurrent($stage)
872  {
873  // Always allow for admins
874  if ($this->‪isAdmin()) {
875  return true;
876  }
877  // Always OK for live workspace
878  if ($this->workspace === 0 || !‪ExtensionManagementUtility::isLoaded('workspaces')) {
879  return true;
880  }
881  $stage = (int)$stage;
882  $stat = $this->‪checkWorkspaceCurrent();
883  $accessType = $stat['_ACCESS'];
884  // Workspace owners are always allowed for stage change
885  if ($accessType === 'owner') {
886  return true;
887  }
888 
889  // Check if custom staging is activated
890  ‪$workspaceRec = BackendUtility::getRecord('sys_workspace', $stat['uid']);
891  if (‪$workspaceRec['custom_stages'] > 0 && $stage !== 0 && $stage !== -10) {
892  // Get custom stage record
893  $workspaceStageRec = BackendUtility::getRecord('sys_workspace_stage', $stage);
894  // Check if the user is responsible for the current stage
895  if (
896  $accessType === 'member'
897  && ‪GeneralUtility::inList($workspaceStageRec['responsible_persons'] ?? '', 'be_users_' . $this->user['uid'])
898  ) {
899  return true;
900  }
901  // Check if the user is in a group which is responsible for the current stage
902  foreach ($this->userGroupsUID as $groupUid) {
903  if (
904  $accessType === 'member'
905  && ‪GeneralUtility::inList($workspaceStageRec['responsible_persons'] ?? '', 'be_groups_' . $groupUid)
906  ) {
907  return true;
908  }
909  }
910  } elseif ($stage === -10 || $stage === -20) {
911  // Nobody is allowed to do that except the owner (which was checked above)
912  return false;
913  } elseif (
914  $accessType === 'reviewer' && $stage <= 1
915  || $accessType === 'member' && $stage <= 0
916  ) {
917  return true;
918  }
919  return false;
920  }
921 
933  public function ‪workspacePublishAccess($wsid)
934  {
935  if ($this->‪isAdmin()) {
936  return true;
937  }
938  $wsAccess = $this->‪checkWorkspace($wsid);
939  // If no access to workspace, of course you cannot publish!
940  if ($wsAccess === false) {
941  return false;
942  }
943  if ((int)$wsAccess['uid'] === 0) {
944  // If access to Live workspace, no problem.
945  return true;
946  }
947  // Custom workspaces
948  // 1. Owners can always publish
949  if ($wsAccess['_ACCESS'] === 'owner') {
950  return true;
951  }
952  // 2. User has access to online workspace which is OK as well as long as publishing
953  // access is not limited by workspace option.
954  return $this->‪checkWorkspace(0) && !($wsAccess['publish_access'] & 2);
955  }
956 
972  public function ‪getTSConfig(): array
973  {
974  return $this->‪getUserTsConfig()?->getUserTsConfigArray() ?? [];
975  }
976 
983  {
984  return ‪$this->userTsConfig;
985  }
986 
994  public function ‪returnWebmounts()
995  {
996  return (string)$this->groupData['webmounts'] != '' ? explode(',', $this->groupData['webmounts']) : [];
997  }
998 
1005  public function ‪setWebmounts(array $mountPointUids, $append = false)
1006  {
1007  if (empty($mountPointUids)) {
1008  return;
1009  }
1010  if ($append) {
1011  $currentWebMounts = ‪GeneralUtility::intExplode(',', (string)($this->groupData['webmounts'] ?? ''));
1012  $mountPointUids = array_merge($currentWebMounts, $mountPointUids);
1013  }
1014  $this->groupData['webmounts'] = implode(',', array_unique($mountPointUids));
1015  }
1016 
1028  public function ‪initializeWebmountsForElementBrowser()
1029  {
1030  $alternativeWebmountPoint = (int)$this->‪getSessionData('pageTree_temporaryMountPoint');
1031  if ($alternativeWebmountPoint) {
1032  $alternativeWebmountPoint = ‪GeneralUtility::intExplode(',', (string)$alternativeWebmountPoint);
1033  $this->‪setWebmounts($alternativeWebmountPoint);
1034  return;
1035  }
1036 
1037  $alternativeWebmountPoints = trim($this->‪getTSConfig()['options.']['pageTree.']['altElementBrowserMountPoints'] ?? '');
1038  $appendAlternativeWebmountPoints = $this->‪getTSConfig()['options.']['pageTree.']['altElementBrowserMountPoints.']['append'] ?? '';
1039  if ($alternativeWebmountPoints) {
1040  $alternativeWebmountPoints = ‪GeneralUtility::intExplode(',', $alternativeWebmountPoints);
1041  $this->‪setWebmounts($alternativeWebmountPoints, $appendAlternativeWebmountPoints);
1042  }
1043  }
1044 
1053  public function ‪jsConfirmation($bitmask)
1054  {
1055  try {
1056  $alertPopupsSetting = trim((string)($this->‪getTSConfig()['options.']['alertPopups'] ?? ''));
1057  $alertPopup = ‪JsConfirmation::cast($alertPopupsSetting === '' ? null : (int)$alertPopupsSetting);
1058  } catch (InvalidEnumerationValueException $e) {
1059  $alertPopup = new JsConfirmation();
1060  }
1061 
1062  return ‪JsConfirmation::cast($bitmask)->matches($alertPopup);
1063  }
1064 
1073  public function ‪fetchGroupData()
1074  {
1075  if ($this->user['uid']) {
1076  // Get lists for the be_user record and set them as default/primary values.
1077  // Enabled Backend Modules
1078  $this->groupData['modules'] = $this->user['userMods'] ?? '';
1079  // Add available widgets
1080  $this->groupData['available_widgets'] = $this->user['available_widgets'] ?? '';
1081  // Add allowed mfa providers
1082  $this->groupData['mfa_providers'] = $this->user['mfa_providers'] ?? '';
1083  // Add Allowed Languages
1084  $this->groupData['allowed_languages'] = $this->user['allowed_languages'] ?? '';
1085  // Set user value for workspace permissions.
1086  $this->groupData['workspace_perms'] = $this->user['workspace_perms'] ?? 0;
1087  // Database mountpoints
1088  $this->groupData['webmounts'] = $this->user['db_mountpoints'] ?? '';
1089  // File mountpoints
1090  $this->groupData['filemounts'] = $this->user['file_mountpoints'] ?? '';
1091  // Fileoperation permissions
1092  $this->groupData['file_permissions'] = $this->user['file_permissions'] ?? '';
1093 
1094  // Get the groups and accumulate their permission settings
1095  $mountOptions = new BackendGroupMountOption((int)($this->user['options'] ?? 0));
1096  $groupResolver = GeneralUtility::makeInstance(GroupResolver::class);
1097  $resolvedGroups = $groupResolver->resolveGroupsForUser($this->user, $this->usergroup_table);
1098  foreach ($resolvedGroups as $groupInfo) {
1099  $groupInfo += [
1100  'uid' => 0,
1101  'db_mountpoints' => '',
1102  'file_mountpoints' => '',
1103  'groupMods' => '',
1104  'availableWidgets' => '',
1105  'mfa_providers' => '',
1106  'tables_select' => '',
1107  'tables_modify' => '',
1108  'pagetypes_select' => '',
1109  'non_exclude_fields' => '',
1110  'explicit_allowdeny' => '',
1111  'allowed_languages' => '',
1112  'custom_options' => '',
1113  'file_permissions' => '',
1114  'workspace_perms' => 0, // Bitflag.
1115  ];
1116  // Add the group uid to internal arrays.
1117  $this->userGroupsUID[] = (int)$groupInfo['uid'];
1118  $this->userGroups[(int)$groupInfo['uid']] = $groupInfo;
1119  // Mount group database-mounts
1120  if ($mountOptions->shouldUserIncludePageMountsFromAssociatedGroups()) {
1121  $this->groupData['webmounts'] .= ',' . $groupInfo['db_mountpoints'];
1122  }
1123  // Mount group file-mounts
1124  if ($mountOptions->shouldUserIncludeFileMountsFromAssociatedGroups()) {
1125  $this->groupData['filemounts'] .= ',' . $groupInfo['file_mountpoints'];
1126  }
1127  // Gather permission detail fields
1128  $this->groupData['modules'] .= ',' . $groupInfo['groupMods'];
1129  $this->groupData['available_widgets'] .= ',' . $groupInfo['availableWidgets'];
1130  $this->groupData['mfa_providers'] .= ',' . $groupInfo['mfa_providers'];
1131  $this->groupData['tables_select'] .= ',' . $groupInfo['tables_select'];
1132  $this->groupData['tables_modify'] .= ',' . $groupInfo['tables_modify'];
1133  $this->groupData['pagetypes_select'] .= ',' . $groupInfo['pagetypes_select'];
1134  $this->groupData['non_exclude_fields'] .= ',' . $groupInfo['non_exclude_fields'];
1135  $this->groupData['explicit_allowdeny'] .= ',' . $groupInfo['explicit_allowdeny'];
1136  $this->groupData['allowed_languages'] .= ',' . $groupInfo['allowed_languages'];
1137  $this->groupData['custom_options'] .= ',' . $groupInfo['custom_options'];
1138  $this->groupData['file_permissions'] .= ',' . $groupInfo['file_permissions'];
1139  // Setting workspace permissions:
1140  $this->groupData['workspace_perms'] |= $groupInfo['workspace_perms'];
1141  if (!$this->firstMainGroup) {
1142  $this->firstMainGroup = (int)$groupInfo['uid'];
1143  }
1144  }
1145 
1146  // Populating the $this->userGroupsUID -array with the groups in the order in which they were LAST included.
1147  // Finally, this is the list of group_uid's in the order they are parsed (including subgroups)
1148  // and without duplicates (duplicates are presented with their last entrance in the list,
1149  // which thus reflects the order of the TypoScript in TSconfig)
1150  $this->userGroupsUID = array_reverse(array_unique(array_reverse($this->userGroupsUID)));
1151 
1152  $this->‪prepareUserTsConfig();
1153 
1154  // Processing webmounts
1155  // Admin's always have the root mounted
1156  if ($this->‪isAdmin() && !($this->‪getTSConfig()['options.']['dontMountAdminMounts'] ?? false)) {
1157  $this->groupData['webmounts'] = '0,' . $this->groupData['webmounts'];
1158  }
1159  // The lists are cleaned for duplicates
1160  $this->groupData['webmounts'] = ‪StringUtility::uniqueList($this->groupData['webmounts'] ?? '');
1161  $this->groupData['pagetypes_select'] = ‪StringUtility::uniqueList($this->groupData['pagetypes_select'] ?? '');
1162  $this->groupData['tables_select'] = ‪StringUtility::uniqueList(($this->groupData['tables_modify'] ?? '') . ',' . ($this->groupData['tables_select'] ?? ''));
1163  $this->groupData['tables_modify'] = ‪StringUtility::uniqueList($this->groupData['tables_modify'] ?? '');
1164  $this->groupData['non_exclude_fields'] = ‪StringUtility::uniqueList($this->groupData['non_exclude_fields'] ?? '');
1165  $this->groupData['explicit_allowdeny'] = ‪StringUtility::uniqueList($this->groupData['explicit_allowdeny'] ?? '');
1166  $this->groupData['allowed_languages'] = ‪StringUtility::uniqueList($this->groupData['allowed_languages'] ?? '');
1167  $this->groupData['custom_options'] = ‪StringUtility::uniqueList($this->groupData['custom_options'] ?? '');
1168  $this->groupData['modules'] = ‪StringUtility::uniqueList($this->groupData['modules'] ?? '');
1169  $this->groupData['available_widgets'] = ‪StringUtility::uniqueList($this->groupData['available_widgets'] ?? '');
1170  $this->groupData['mfa_providers'] = ‪StringUtility::uniqueList($this->groupData['mfa_providers'] ?? '');
1171  $this->groupData['file_permissions'] = ‪StringUtility::uniqueList($this->groupData['file_permissions'] ?? '');
1172 
1173  // Check if the user access to all web mounts set
1174  if (!empty(trim($this->groupData['webmounts']))) {
1175  $validWebMounts = $this->‪filterValidWebMounts($this->groupData['webmounts']);
1176  $this->groupData['webmounts'] = implode(',', $validWebMounts);
1177  }
1178  // Setting up workspace situation (after webmounts are processed!):
1179  $this->‪workspaceInit();
1180  }
1181  }
1182 
1191  protected function ‪filterValidWebMounts(string $listOfWebMounts): array
1192  {
1193  // Checking read access to web mounts if there are mounts points (not empty string, false or 0)
1194  $allWebMounts = explode(',', $listOfWebMounts);
1195  // Selecting all web mounts with permission clause for reading
1196  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
1197  $queryBuilder->getRestrictions()
1198  ->removeAll()
1199  ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
1200 
1201  $readablePagesOfWebMounts = $queryBuilder->select('uid')
1202  ->from('pages')
1203  // @todo DOCTRINE: check how to make getPagePermsClause() portable
1204  ->where(
1206  $queryBuilder->expr()->in(
1207  'uid',
1208  $queryBuilder->createNamedParameter(
1209  ‪GeneralUtility::intExplode(',', $listOfWebMounts),
1210  Connection::PARAM_INT_ARRAY
1211  )
1212  )
1213  )
1214  ->executeQuery()
1215  ->fetchAllAssociative();
1216  $readablePagesOfWebMounts = array_column(($readablePagesOfWebMounts ?: []), 'uid', 'uid');
1217  foreach ($allWebMounts as $key => $mountPointUid) {
1218  // If the mount ID is NOT found among selected pages, unset it:
1219  if ($mountPointUid > 0 && !isset($readablePagesOfWebMounts[$mountPointUid])) {
1220  unset($allWebMounts[$key]);
1221  }
1222  }
1223  return $allWebMounts;
1224  }
1225 
1229  protected function ‪prepareUserTsConfig(): void
1230  {
1231  $tsConfigFactory = GeneralUtility::makeInstance(UserTsConfigFactory::class);
1232  $this->userTsConfig = $tsConfigFactory->create($this);
1233  if (!empty($this->‪getUserTsConfig()->getUserTsConfigArray()['setup.']['override.'])) {
1234  // @todo: This logic is ugly. user TSconfig "setup.override." is used to force options
1235  // in the user settings module, along with "setup.fields." and "setup.default.".
1236  // See the docs about this.
1237  // The fun part is, this is merged into user UC. As such, whenever these setup
1238  // options are used, user UC has to be updated. The toggle below triggers this
1239  // and initiates an update query of this users UC.
1240  // Before v12, this was only triggered if user TSconfig could not be fetched from
1241  // cache, but this was flawed, too: When two users had the same user TSconfig, UC
1242  // of one user would be updated, but not UC of the other user if caches were not
1243  // cleared in between their two calls.
1244  // This toggle and UC overriding should vanish altogether: It would be better if
1245  // user TSconfig no longer overlays UC, instead the settings / setup module
1246  // controller should look at user TSconfig "setup." on the fly when rendering, and
1247  // consumers that access user setup / settings values should get values overloaded
1248  // on the fly as well using some helper or a late init logic or similar.
1249  $this->userTSUpdated = true;
1250  }
1251  }
1252 
1257  protected function ‪initializeFileStorages()
1258  {
1259  $this->fileStorages = [];
1260  $storageRepository = GeneralUtility::makeInstance(StorageRepository::class);
1261  // Admin users have all file storages visible, without any filters
1262  if ($this->‪isAdmin()) {
1263  $storageObjects = $storageRepository->findAll();
1264  foreach ($storageObjects as $storageObject) {
1265  $this->fileStorages[$storageObject->getUid()] = $storageObject;
1266  }
1267  } else {
1268  // Regular users only have storages that are defined in their filemounts
1269  // Permissions and file mounts for the storage are added in StoragePermissionAspect
1270  foreach ($this->‪getFileMountRecords() as $row) {
1271  if (!str_contains($row['identifier'], ':')) {
1272  // Skip record since the file mount identifier is invalid
1273  continue;
1274  }
1275  [$base] = ‪GeneralUtility::trimExplode(':', $row['identifier'], true);
1276  $base = (int)$base;
1277  if (!array_key_exists($base, $this->fileStorages)) {
1278  $storageObject = $storageRepository->findByUid($base);
1279  if ($storageObject) {
1280  $this->fileStorages[$storageObject->getUid()] = $storageObject;
1281  }
1282  }
1283  }
1284  }
1285 
1286  // This has to be called always in order to set certain filters
1288  }
1289 
1296  public function ‪getCategoryMountPoints()
1297  {
1298  $categoryMountPoints = '';
1299 
1300  // Category mounts of the groups
1301  if (is_array($this->userGroups)) {
1302  foreach ($this->userGroups as $group) {
1303  if ($group['category_perms']) {
1304  $categoryMountPoints .= ',' . $group['category_perms'];
1305  }
1306  }
1307  }
1308 
1309  // Category mounts of the user record
1310  if ($this->user['category_perms']) {
1311  $categoryMountPoints .= ',' . $this->user['category_perms'];
1312  }
1313 
1314  // Make the ids unique
1315  $categoryMountPoints = ‪GeneralUtility::trimExplode(',', $categoryMountPoints);
1316  $categoryMountPoints = array_filter($categoryMountPoints); // remove empty value
1317  $categoryMountPoints = array_unique($categoryMountPoints); // remove unique value
1318 
1319  return $categoryMountPoints;
1320  }
1321 
1329  public function ‪getFileMountRecords()
1330  {
1331  $runtimeCache = GeneralUtility::makeInstance(CacheManager::class)->getCache('runtime');
1332  $fileMountRecordCache = $runtimeCache->get('backendUserAuthenticationFileMountRecords') ?: [];
1333 
1334  if (!empty($fileMountRecordCache)) {
1335  return $fileMountRecordCache;
1336  }
1337 
1338  $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
1339 
1340  // Processing file mounts (both from the user and the groups)
1341  $fileMounts = array_unique(‪GeneralUtility::intExplode(',', (string)($this->groupData['filemounts'] ?? ''), true));
1342 
1343  // Limit file mounts if set in workspace record
1344  if ($this->workspace > 0 && !empty($this->workspaceRec['file_mountpoints'])) {
1345  $workspaceFileMounts = ‪GeneralUtility::intExplode(',', (string)$this->workspaceRec['file_mountpoints'], true);
1346  $fileMounts = array_intersect($fileMounts, $workspaceFileMounts);
1347  }
1348 
1349  if (!empty($fileMounts)) {
1350  $orderBy = ‪$GLOBALS['TCA']['sys_filemounts']['ctrl']['default_sortby'] ?? 'sorting';
1351 
1352  $queryBuilder = $connectionPool->getQueryBuilderForTable('sys_filemounts');
1353  $queryBuilder->getRestrictions()
1354  ->removeAll()
1355  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
1356  ->add(GeneralUtility::makeInstance(HiddenRestriction::class))
1357  ->add(GeneralUtility::makeInstance(RootLevelRestriction::class));
1358 
1359  $queryBuilder->select('*')
1360  ->from('sys_filemounts')
1361  ->where(
1362  $queryBuilder->expr()->in('uid', $queryBuilder->createNamedParameter($fileMounts, Connection::PARAM_INT_ARRAY))
1363  );
1364 
1365  foreach (‪QueryHelper::parseOrderBy($orderBy) as $fieldAndDirection) {
1366  $queryBuilder->addOrderBy(...$fieldAndDirection);
1367  }
1368 
1369  $fileMountRecords = $queryBuilder->executeQuery()->fetchAllAssociative();
1370  if ($fileMountRecords !== false) {
1371  foreach ($fileMountRecords as $fileMount) {
1372  $fileMountRecordCache[$fileMount['identifier']] = $fileMount;
1373  }
1374  }
1375  }
1376 
1377  // Read-only file mounts
1378  $readOnlyMountPoints = \trim($this->‪getTSConfig()['options.']['folderTree.']['altElementBrowserMountPoints'] ?? '');
1379  if ($readOnlyMountPoints) {
1380  // We cannot use the API here but need to fetch the default storage record directly
1381  // to not instantiate it (which directly applies mount points) before all mount points are resolved!
1382  $queryBuilder = $connectionPool->getQueryBuilderForTable('sys_file_storage');
1383  $defaultStorageRow = $queryBuilder->select('uid')
1384  ->from('sys_file_storage')
1385  ->where(
1386  $queryBuilder->expr()->eq('is_default', $queryBuilder->createNamedParameter(1, ‪Connection::PARAM_INT))
1387  )
1388  ->setMaxResults(1)
1389  ->executeQuery()
1390  ->fetchAssociative();
1391 
1392  $readOnlyMountPointArray = ‪GeneralUtility::trimExplode(',', $readOnlyMountPoints);
1393  foreach ($readOnlyMountPointArray as $readOnlyMountPoint) {
1394  $readOnlyMountPointConfiguration = ‪GeneralUtility::trimExplode(':', $readOnlyMountPoint);
1395  if (count($readOnlyMountPointConfiguration) === 2) {
1396  // A storage is passed in the configuration
1397  $storageUid = (int)$readOnlyMountPointConfiguration[0];
1398  $path = $readOnlyMountPointConfiguration[1];
1399  } else {
1400  if (empty($defaultStorageRow)) {
1401  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);
1402  }
1403  // Backwards compatibility: If no storage is passed, we use the default storage
1404  $storageUid = $defaultStorageRow['uid'];
1405  $path = $readOnlyMountPointConfiguration[0];
1406  }
1407  $fileMountRecordCache[$storageUid . $path] = [
1408  'base' => $storageUid,
1409  'title' => $path,
1410  'path' => $path,
1411  'read_only' => true,
1412  ];
1413  }
1414  }
1415 
1416  // Personal or Group filemounts are not accessible if file mount list is set in workspace record
1417  if ($this->workspace <= 0 || empty($this->workspaceRec['file_mountpoints'])) {
1418  // If userHomePath is set, we attempt to mount it
1419  if (‪$GLOBALS['TYPO3_CONF_VARS']['BE']['userHomePath']) {
1420  [$userHomeStorageUid, $userHomeFilter] = explode(':', ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['userHomePath'], 2);
1421  $userHomeStorageUid = (int)$userHomeStorageUid;
1422  $userHomeFilter = '/' . ltrim($userHomeFilter, '/');
1423  if ($userHomeStorageUid > 0) {
1424  // Try and mount with [uid]_[username]
1425  $path = $userHomeFilter . $this->user['uid'] . '_' . $this->user['username'] . ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['userUploadDir'];
1426  $fileMountRecordCache[$userHomeStorageUid . $path] = [
1427  'base' => $userHomeStorageUid,
1428  'title' => $this->user['username'],
1429  'path' => $path,
1430  'read_only' => false,
1431  'user_mount' => true,
1432  ];
1433  // Try and mount with only [uid]
1434  $path = $userHomeFilter . $this->user['uid'] . ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['userUploadDir'];
1435  $fileMountRecordCache[$userHomeStorageUid . $path] = [
1436  'base' => $userHomeStorageUid,
1437  'title' => $this->user['username'],
1438  'path' => $path,
1439  'read_only' => false,
1440  'user_mount' => true,
1441  ];
1442  }
1443  }
1444 
1445  // Mount group home-dirs
1446  $mountOptions = new BackendGroupMountOption((int)($this->user['options'] ?? 0));
1447  if (‪$GLOBALS['TYPO3_CONF_VARS']['BE']['groupHomePath'] !== '' && $mountOptions->shouldUserIncludeFileMountsFromAssociatedGroups()) {
1448  // If groupHomePath is set, we attempt to mount it
1449  [$groupHomeStorageUid, $groupHomeFilter] = explode(':', ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['groupHomePath'], 2);
1450  $groupHomeStorageUid = (int)$groupHomeStorageUid;
1451  $groupHomeFilter = '/' . ltrim($groupHomeFilter, '/');
1452  if ($groupHomeStorageUid > 0) {
1453  foreach ($this->userGroups as ‪$groupData) {
1454  $path = $groupHomeFilter . ‪$groupData['uid'];
1455  $fileMountRecordCache[$groupHomeStorageUid . $path] = [
1456  'base' => $groupHomeStorageUid,
1457  'title' => ‪$groupData['title'],
1458  'path' => $path,
1459  'read_only' => false,
1460  'user_mount' => true,
1461  ];
1462  }
1463  }
1464  }
1465  }
1466 
1467  $runtimeCache->set('backendUserAuthenticationFileMountRecords', $fileMountRecordCache);
1468  return $fileMountRecordCache;
1469  }
1470 
1478  public function ‪getFileStorages()
1479  {
1480  // Initializing file mounts after the groups are fetched
1481  if ($this->fileStorages === null) {
1482  $this->‪initializeFileStorages();
1483  }
1484  return ‪$this->fileStorages;
1485  }
1486 
1493  {
1494  // Add the option for also displaying the non-hidden files
1495  if ($this->uc['showHiddenFilesAndFolders'] ?? false) {
1497  }
1498  }
1499 
1535  public function ‪getFilePermissions()
1536  {
1537  if (!isset($this->filePermissions)) {
1539  // File permissions
1540  'addFile' => false,
1541  'readFile' => false,
1542  'writeFile' => false,
1543  'copyFile' => false,
1544  'moveFile' => false,
1545  'renameFile' => false,
1546  'deleteFile' => false,
1547  // Folder permissions
1548  'addFolder' => false,
1549  'readFolder' => false,
1550  'writeFolder' => false,
1551  'copyFolder' => false,
1552  'moveFolder' => false,
1553  'renameFolder' => false,
1554  'deleteFolder' => false,
1555  'recursivedeleteFolder' => false,
1556  ];
1557  if ($this->‪isAdmin()) {
1558  ‪$filePermissions = array_map('is_bool', ‪$filePermissions);
1559  } else {
1560  $userGroupRecordPermissions = ‪GeneralUtility::trimExplode(',', $this->groupData['file_permissions'] ?? '', true);
1561  array_walk(
1562  $userGroupRecordPermissions,
1563  static function ($permission) use (&‪$filePermissions) {
1564  ‪$filePermissions[$permission] = true;
1565  }
1566  );
1567 
1568  // Finally overlay any user TSconfig
1569  $permissionsTsConfig = $this->‪getTSConfig()['permissions.']['file.']['default.'] ?? [];
1570  if (!empty($permissionsTsConfig)) {
1571  array_walk(
1572  $permissionsTsConfig,
1573  static function ($value, $permission) use (&‪$filePermissions) {
1574  ‪$filePermissions[$permission] = (bool)$value;
1575  }
1576  );
1577  }
1578  }
1579  $this->filePermissions = ‪$filePermissions;
1580  }
1582  }
1583 
1592  public function ‪getFilePermissionsForStorage(ResourceStorage $storageObject)
1593  {
1594  $finalUserPermissions = $this->‪getFilePermissions();
1595  if (!$this->‪isAdmin()) {
1596  $storageFilePermissions = $this->‪getTSConfig()['permissions.']['file.']['storage.'][$storageObject->getUid() . '.'] ?? [];
1597  if (!empty($storageFilePermissions)) {
1598  array_walk(
1599  $storageFilePermissions,
1600  static function ($value, $permission) use (&$finalUserPermissions) {
1601  $finalUserPermissions[$permission] = (bool)$value;
1602  }
1603  );
1604  }
1605  }
1606  return $finalUserPermissions;
1607  }
1608 
1627  public function ‪getDefaultUploadFolder($pid = null, $table = null, $field = null)
1628  {
1629  $uploadFolder = $this->‪getTSConfig()['options.']['defaultUploadFolder'] ?? '';
1630  if ($uploadFolder) {
1631  try {
1632  $uploadFolder = GeneralUtility::makeInstance(ResourceFactory::class)->getFolderObjectFromCombinedIdentifier($uploadFolder);
1633  } catch (Exception\FolderDoesNotExistException $e) {
1634  $uploadFolder = null;
1635  }
1636  }
1637  if (empty($uploadFolder)) {
1638  foreach ($this->‪getFileStorages() as $storage) {
1639  if ($storage->isDefault() && $storage->isWritable()) {
1640  try {
1641  $uploadFolder = $storage->getDefaultFolder();
1642  if ($uploadFolder->checkActionPermission('write')) {
1643  break;
1644  }
1645  $uploadFolder = null;
1646  } catch (Exception $folderAccessException) {
1647  // If the folder is not accessible (no permissions / does not exist) we skip this one.
1648  }
1649  break;
1650  }
1651  }
1652  if (!$uploadFolder instanceof Folder) {
1653  foreach ($this->‪getFileStorages() as $storage) {
1654  if ($storage->isWritable()) {
1655  try {
1656  $uploadFolder = $storage->getDefaultFolder();
1657  if ($uploadFolder->checkActionPermission('write')) {
1658  break;
1659  }
1660  $uploadFolder = null;
1661  } catch (Exception $folderAccessException) {
1662  // If the folder is not accessible (no permissions / does not exist) try the next one.
1663  }
1664  }
1665  }
1666  }
1667  }
1668 
1669  // @deprecated HOOK: getDefaultUploadFolder
1670  if (!empty(‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauthgroup.php']['getDefaultUploadFolder'] ?? [])) {
1671  trigger_error('The hook $GLOBALS[\'TYPO3_CONF_VARS\'][\'SC_OPTIONS\'][\'t3lib/class.t3lib_userauthgroup.php\'][\'getDefaultUploadFolder\'] will be removed in TYPO3 v13.0. Use the PSR-14 AfterDefaultUploadFolderWasResolvedEvent instead.', E_USER_DEPRECATED);
1672  }
1673  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauthgroup.php']['getDefaultUploadFolder'] ?? [] as $_funcRef) {
1674  $_params = [
1675  'uploadFolder' => $uploadFolder,
1676  'pid' => $pid,
1677  'table' => $table,
1678  'field' => $field,
1679  ];
1680  $uploadFolder = GeneralUtility::callUserFunction($_funcRef, $_params, $this);
1681  }
1682 
1683  if ($uploadFolder instanceof ‪Folder) {
1684  return $uploadFolder;
1685  }
1686  return false;
1687  }
1688 
1698  public function ‪getDefaultUploadTemporaryFolder()
1699  {
1700  $defaultTemporaryFolder = null;
1701  $defaultFolder = $this->‪getDefaultUploadFolder();
1702 
1703  if ($defaultFolder !== false) {
1704  $tempFolderName = '_temp_';
1705  $createFolder = !$defaultFolder->hasFolder($tempFolderName);
1706  if ($createFolder === true) {
1707  try {
1708  $defaultTemporaryFolder = $defaultFolder->createFolder($tempFolderName);
1709  } catch (‪Exception $folderAccessException) {
1710  }
1711  } else {
1712  $defaultTemporaryFolder = $defaultFolder->getSubfolder($tempFolderName);
1713  }
1714  }
1715 
1716  return $defaultTemporaryFolder;
1717  }
1726  public function ‪workspaceInit()
1727  {
1728  // Initializing workspace by evaluating and setting the workspace, possibly updating it in the user record!
1729  $this->‪setWorkspace($this->user['workspace_id']);
1730  // Limiting the DB mountpoints if there any selected in the workspace record
1732  $allowed_languages = (string)($this->‪getTSConfig()['options.']['workspaces.']['allowed_languages.'][‪$this->workspace] ?? '');
1733  if ($allowed_languages !== '') {
1734  $this->groupData['allowed_languages'] = ‪StringUtility::uniqueList($allowed_languages);
1735  }
1736  }
1737 
1741  protected function ‪initializeDbMountpointsInWorkspace()
1742  {
1743  $dbMountpoints = trim($this->workspaceRec['db_mountpoints'] ?? '');
1744  if ($this->workspace > 0 && $dbMountpoints != '') {
1745  $filteredDbMountpoints = [];
1746  // Notice: We cannot call $this->getPagePermsClause(1);
1747  // as usual because the group-list is not available at this point.
1748  // But bypassing is fine because all we want here is check if the
1749  // workspace mounts are inside the current webmounts rootline.
1750  // The actual permission checking on page level is done elsewhere
1751  // as usual anyway before the page tree is rendered.
1752  $readPerms = '1=1';
1753  // Traverse mount points of the workspace, add them,
1754  // but make sure they match against the users' DB mounts
1755 
1756  $workspaceWebMounts = ‪GeneralUtility::intExplode(',', $dbMountpoints);
1757  $webMountsOfUser = ‪GeneralUtility::intExplode(',', (string)($this->groupData['webmounts'] ?? ''));
1758  $webMountsOfUser = array_combine($webMountsOfUser, $webMountsOfUser) ?: [];
1759 
1760  $entryPointRootLineUids = [];
1761  foreach ($webMountsOfUser as $webMountPageId) {
1762  $rootLine = BackendUtility::BEgetRootLine($webMountPageId, '', true);
1763  $entryPointRootLineUids[$webMountPageId] = array_map('intval', array_column($rootLine, 'uid'));
1764  }
1765  foreach ($entryPointRootLineUids as $webMountOfUser => $uidsOfRootLine) {
1766  // Remove the DB mounts of the user if the DB mount is not in the list of
1767  // workspace mounts
1768  foreach ($workspaceWebMounts as $webmountOfWorkspace) {
1769  // This workspace DB mount is somewhere in the rootline of the users' web mount,
1770  // so this is "OK" to be included
1771  if (in_array($webmountOfWorkspace, $uidsOfRootLine, true)) {
1772  continue;
1773  }
1774  // Remove the user's DB Mount (possible via array_combine, see above)
1775  unset($webMountsOfUser[$webMountOfUser]);
1776  }
1777  }
1778  $dbMountpoints = array_merge($workspaceWebMounts, $webMountsOfUser);
1779  $dbMountpoints = array_unique($dbMountpoints);
1780  foreach ($dbMountpoints as $mpId) {
1781  if ($this->‪isInWebMount($mpId, $readPerms)) {
1782  $filteredDbMountpoints[] = $mpId;
1783  }
1784  }
1785  // Re-insert webmounts
1786  $this->groupData['webmounts'] = implode(',', $filteredDbMountpoints);
1787  }
1788  }
1789 
1797  public function ‪checkWorkspace(int|array $wsRec): array|false
1798  {
1799  // If not array, look up workspace record
1800  if (!is_array($wsRec)) {
1801  if ($wsRec === 0) {
1802  $wsRec = ['uid' => 0];
1803  } elseif (‪ExtensionManagementUtility::isLoaded('workspaces')) {
1804  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_workspace');
1805  $queryBuilder->getRestrictions()->add(GeneralUtility::makeInstance(RootLevelRestriction::class));
1806  $wsRec = $queryBuilder
1807  ->select('*')
1808  ->from('sys_workspace')
1809  ->where($queryBuilder->expr()->eq(
1810  'uid',
1811  $queryBuilder->createNamedParameter($wsRec, ‪Connection::PARAM_INT)
1812  ))
1813  ->executeQuery()
1814  ->fetchAssociative();
1815  }
1816  }
1817  // If wsRec is set to an array, evaluate it, otherwise return false
1818  if (!is_array($wsRec)) {
1819  return false;
1820  }
1821  if ($this->‪isAdmin()) {
1822  return array_merge($wsRec, ['_ACCESS' => 'admin']);
1823  }
1824  // User is in live, and be_groups.workspace_perms has bitmask=1 included
1825  if ($wsRec['uid'] === 0) {
1826  return $this->‪hasEditAccessToLiveWorkspace()
1827  ? array_merge($wsRec, ['_ACCESS' => 'online'])
1828  : false;
1829  }
1830  // Checking if the person is workspace owner
1831  if (‪GeneralUtility::inList($wsRec['adminusers'], 'be_users_' . $this->user['uid'])) {
1832  return array_merge($wsRec, ['_ACCESS' => 'owner']);
1833  }
1834  // Checking if the editor is owner through an included user group
1835  foreach ($this->userGroupsUID as $groupUid) {
1836  if (‪GeneralUtility::inList($wsRec['adminusers'], 'be_groups_' . $groupUid)) {
1837  return array_merge($wsRec, ['_ACCESS' => 'owner']);
1838  }
1839  }
1840  // Checking if the user is member of the workspace
1841  if (‪GeneralUtility::inList($wsRec['members'], 'be_users_' . $this->user['uid'])) {
1842  return array_merge($wsRec, ['_ACCESS' => 'member']);
1843  }
1844  // Checking if the user is member through an included user group
1845  foreach ($this->userGroupsUID as $groupUid) {
1846  if (‪GeneralUtility::inList($wsRec['members'], 'be_groups_' . $groupUid)) {
1847  return array_merge($wsRec, ['_ACCESS' => 'member']);
1848  }
1849  }
1850  return false;
1851  }
1852 
1857  protected function ‪hasEditAccessToLiveWorkspace(): bool
1858  {
1859  return (bool)(($this->groupData['workspace_perms'] ?? 0) & 1);
1860  }
1870  public function ‪checkWorkspaceCurrent()
1871  {
1872  if (!isset($this->checkWorkspaceCurrent_cache)) {
1873  $this->checkWorkspaceCurrent_cache = $this->‪checkWorkspace($this->workspace);
1874  }
1876  }
1877 
1884  public function ‪setWorkspace($workspaceId)
1885  {
1886  // Check workspace validity and if not found, revert to default workspace.
1887  if (!$this->‪setTemporaryWorkspace($workspaceId)) {
1889  }
1890  // Unset access cache:
1891  $this->checkWorkspaceCurrent_cache = null;
1892  // If ID is different from the stored one, change it:
1893  if ((int)$this->workspace !== (int)$this->user['workspace_id']) {
1894  $this->user['workspace_id'] = ‪$this->workspace;
1895  GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('be_users')->update(
1896  'be_users',
1897  ['workspace_id' => $this->user['workspace_id']],
1898  ['uid' => (int)$this->user['uid']]
1899  );
1900  $this->‪writelog(SystemLogType::EXTENSION, SystemLogGenericAction::UNDEFINED, SystemLogErrorClassification::MESSAGE, 0, 'User changed workspace to "{workspace}"', ['workspace' => $this->workspace]);
1901  }
1902  }
1903 
1911  public function ‪setTemporaryWorkspace($workspaceId)
1912  {
1913  $workspaceRecord = $this->‪checkWorkspace((int)$workspaceId);
1914 
1915  if ($workspaceRecord) {
1916  $this->workspaceRec = $workspaceRecord;
1917  $this->workspace = (int)$workspaceId;
1918  return true;
1919  }
1920  return false;
1921  }
1922 
1927  public function ‪setDefaultWorkspace()
1928  {
1929  $this->workspace = (int)$this->‪getDefaultWorkspace();
1930  $this->workspaceRec = $this->‪checkWorkspace($this->workspace);
1931  }
1932 
1941  public function ‪getDefaultWorkspace()
1942  {
1943  if (!‪ExtensionManagementUtility::isLoaded('workspaces')) {
1944  return 0;
1945  }
1946  // Online is default
1947  if ($this->‪checkWorkspace(0)) {
1948  return 0;
1949  }
1950  // Otherwise -99 is the fallback
1951  $defaultWorkspace = -99;
1952  // Traverse all workspaces
1953  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_workspace');
1954  $queryBuilder->getRestrictions()->add(GeneralUtility::makeInstance(RootLevelRestriction::class));
1955  $result = $queryBuilder->select('*')
1956  ->from('sys_workspace')
1957  ->orderBy('title')
1958  ->executeQuery();
1959  while ($workspaceRecord = $result->fetchAssociative()) {
1960  if ($this->‪checkWorkspace($workspaceRecord)) {
1961  $defaultWorkspace = (int)$workspaceRecord['uid'];
1962  break;
1963  }
1964  }
1965  return $defaultWorkspace;
1966  }
1967 
1986  public function ‪writelog($type, $action, $error, $details_nr, $details, $data, $tablename = '', $recuid = '', $recpid = '', $event_pid = -1, $NEWid = '', $userId = 0)
1987  {
1988  if (!$userId && !empty($this->user['uid'])) {
1989  $userId = $this->user['uid'];
1990  }
1991 
1992  if ($backuserid = $this->‪getOriginalUserIdWhenInSwitchUserMode()) {
1993  if (empty($data)) {
1994  $data = [];
1995  }
1996  $data['originalUser'] = $backuserid;
1997  }
1998 
1999  // @todo Remove this once this method is properly typed.
2000  $type = (int)$type;
2001 
2002  ‪$fields = [
2003  'userid' => (int)$userId,
2004  'type' => $type,
2005  'channel' => ‪Type::toChannel($type),
2006  'level' => ‪Type::toLevel($type),
2007  'action' => (int)$action,
2008  'error' => (int)$error,
2009  'details_nr' => (int)$details_nr,
2010  'details' => $details,
2011  'log_data' => empty($data) ? '' : json_encode($data),
2012  'tablename' => $tablename,
2013  'recuid' => (int)$recuid,
2014  'IP' => (string)GeneralUtility::getIndpEnv('REMOTE_ADDR'),
2015  'tstamp' => ‪$GLOBALS['EXEC_TIME'] ?? time(),
2016  'event_pid' => (int)$event_pid,
2017  'NEWid' => $NEWid,
2018  'workspace' => $this->workspace,
2019  ];
2020 
2021  $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('sys_log');
2022  $connection->insert(
2023  'sys_log',
2024  ‪$fields,
2025  [
2042  ]
2043  );
2044 
2045  return (int)$connection->lastInsertId('sys_log');
2046  }
2047 
2054  public static function ‪getCookieName()
2055  {
2056  $configuredCookieName = trim(‪$GLOBALS['TYPO3_CONF_VARS']['BE']['cookieName']);
2057  if (empty($configuredCookieName)) {
2058  $configuredCookieName = 'be_typo_user';
2059  }
2060  return $configuredCookieName;
2061  }
2062 
2072  public function ‪backendCheckLogin(ServerRequestInterface $request = null)
2073  {
2074  if (empty($this->user['uid'])) {
2075  // @todo: throw a proper AccessDeniedException in TYPO3 v12.0. and handle this functionality in the calling code
2076  $entryPointResolver = GeneralUtility::makeInstance(BackendEntryPointResolver::class);
2077  ‪$url = $entryPointResolver->getUriFromRequest(‪$GLOBALS['TYPO3_REQUEST']);
2078  throw new ImmediateResponseException(new RedirectResponse(‪$url, 303), 1607271747);
2079  }
2080  if ($this->‪isUserAllowedToLogin()) {
2081  $this->‪initializeBackendLogin($request);
2082  } else {
2083  // @todo: throw a proper AccessDeniedException in TYPO3 v12.0.
2084  throw new \RuntimeException('Login Error: TYPO3 is in maintenance mode at the moment. Only administrators are allowed access.', 1294585860);
2085  }
2086  }
2087 
2091  public function ‪initializeBackendLogin(ServerRequestInterface $request = null): void
2092  {
2093  // The groups are fetched and ready for permission checking in this initialization.
2094  // Tables.php must be read before this because stuff like the modules has impact in this
2095  $this->‪fetchGroupData();
2096  // Setting the UC array. It's needed with fetchGroupData first, due to default/overriding of values.
2097  $this->‪backendSetUC();
2098  if ($this->loginSessionStarted) {
2099  // Also, if there is a recovery link set, unset it now
2100  // this will be moved into its own Event at a later stage.
2101  // If a token was set previously, this is now unset, as it was now possible to log-in
2102  if ($this->user['password_reset_token'] ?? '') {
2103  GeneralUtility::makeInstance(ConnectionPool::class)
2104  ->getConnectionForTable($this->user_table)
2105  ->update($this->user_table, ['password_reset_token' => ''], ['uid' => $this->user['uid']]);
2106  }
2107 
2108  $event = new AfterUserLoggedInEvent($this, $request);
2109  GeneralUtility::makeInstance(EventDispatcherInterface::class)->dispatch($event);
2110  // Process hooks
2111  $hooks = ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauthgroup.php']['backendUserLogin'] ?? [];
2112  if (!empty($hooks)) {
2113  trigger_error(
2114  '$GLOBALS[\'TYPO3_CONF_VARS\'][\'SC_OPTIONS\'][\'t3lib/class.t3lib_userauthgroup.php\'][\'backendUserLogin\'] will be removed in TYPO3 v13.0. Use the PSR-14 "AfterUserLoggedInEvent" instead.',
2115  E_USER_DEPRECATED
2116  );
2117  }
2118  foreach ($hooks as $_funcRef) {
2119  $_params = ['user' => ‪$this->user];
2120  GeneralUtility::callUserFunction($_funcRef, $_params, $this);
2121  }
2122  }
2123  }
2124 
2132  public function ‪backendSetUC()
2133  {
2134  // Setting defaults if uc is empty
2135  $updated = false;
2136  if (empty($this->uc)) {
2137  $this->uc = array_merge(
2138  $this->uc_default,
2139  (array)‪$GLOBALS['TYPO3_CONF_VARS']['BE']['defaultUC'],
2140  GeneralUtility::removeDotsFromTS((array)($this->‪getTSConfig()['setup.']['default.'] ?? []))
2141  );
2142  $this->‪overrideUC();
2143  $updated = true;
2144  }
2145  // If TSconfig is updated, update the defaultUC.
2146  if ($this->userTSUpdated) {
2147  $this->‪overrideUC();
2148  $updated = true;
2149  }
2150  // Saving if updated.
2151  if ($updated) {
2152  $this->‪writeUC();
2153  }
2154  }
2155 
2162  public function ‪overrideUC()
2163  {
2164  $this->uc = array_merge($this->uc, (array)($this->‪getTSConfig()['setup.']['override.'] ?? []));
2165  }
2166 
2172  public function ‪resetUC()
2173  {
2174  $this->user['uc'] = '';
2175  $this->uc = [];
2176  $this->‪backendSetUC();
2177  }
2178 
2191  public function ‪isUserAllowedToLogin()
2192  {
2193  $isUserAllowedToLogin = false;
2194  $adminOnlyMode = (int)‪$GLOBALS['TYPO3_CONF_VARS']['BE']['adminOnly'];
2195  // Backend user is allowed if adminOnly is not set or user is an admin:
2196  if (!$adminOnlyMode || $this->‪isAdmin()) {
2197  $isUserAllowedToLogin = true;
2198  } elseif ($backUserId = $this->‪getOriginalUserIdWhenInSwitchUserMode()) {
2199  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('be_users');
2200  $isUserAllowedToLogin = (bool)$queryBuilder->count('uid')
2201  ->from('be_users')
2202  ->where(
2203  $queryBuilder->expr()->eq(
2204  'uid',
2205  $queryBuilder->createNamedParameter($backUserId, ‪Connection::PARAM_INT)
2206  ),
2207  $queryBuilder->expr()->eq('admin', $queryBuilder->createNamedParameter(1, ‪Connection::PARAM_INT))
2208  )
2209  ->executeQuery()
2210  ->fetchOne();
2211  }
2212  return $isUserAllowedToLogin;
2213  }
2214 
2218  public function ‪logoff()
2219  {
2220  if (isset(‪$GLOBALS['BE_USER'])
2221  && ‪$GLOBALS['BE_USER'] instanceof self
2222  && isset(‪$GLOBALS['BE_USER']->user['uid'])
2223  ) {
2224  GeneralUtility::makeInstance(FormProtectionFactory::class)->createForType('backend')->clean();
2225  // Release the locked records
2226  $this->‪releaseLockedRecords((int)$GLOBALS['BE_USER']->user['uid']);
2227 
2228  if ($this->‪isSystemMaintainer()) {
2229  // If user is system maintainer, destroy its possibly valid install tool session.
2230  $session = new SessionService();
2231  $session->destroySession(‪$GLOBALS['TYPO3_REQUEST'] ?? null);
2232  }
2233  }
2234  parent::logoff();
2235  }
2240  protected function ‪releaseLockedRecords(int $userId)
2241  {
2242  if ($userId > 0) {
2243  GeneralUtility::makeInstance(ConnectionPool::class)
2244  ->getConnectionForTable('sys_lockedrecords')
2245  ->delete(
2246  'sys_lockedrecords',
2247  ['userid' => $userId]
2248  );
2249  }
2250  }
2251 
2259  public function ‪getOriginalUserIdWhenInSwitchUserMode(): ?int
2260  {
2261  $originalUserId = $this->‪getSessionData('backuserid');
2262  return $originalUserId ? (int)$originalUserId : null;
2263  }
2264 
2268  protected function ‪evaluateMfaRequirements(): void
2269  {
2270  // In case the current session is a "switch-user" session, MFA is not required
2271  if ($this->‪getOriginalUserIdWhenInSwitchUserMode() !== null) {
2272  $this->logger->debug('MFA is skipped in switch user mode', [
2273  $this->userid_column => $this->user[$this->userid_column],
2274  $this->username_column => $this->user[$this->username_column],
2275  ]);
2276  return;
2277  }
2278  parent::evaluateMfaRequirements();
2279  }
2280 
2286  public function ‪isMfaSetupRequired(): bool
2287  {
2288  $authConfig = $this->‪getTSConfig()['auth.']['mfa.'] ?? [];
2289 
2290  if (isset($authConfig['required'])) {
2291  // user TSconfig overrules global configuration
2292  return (bool)$authConfig['required'];
2293  }
2294 
2295  $globalConfig = (int)(‪$GLOBALS['TYPO3_CONF_VARS']['BE']['requireMfa'] ?? 0);
2296  if ($globalConfig <= 1) {
2297  // 0 and 1 can directly be used by type-casting to boolean
2298  return (bool)$globalConfig;
2299  }
2300 
2301  // check the system maintainer / admin / non-admin options
2302  $isAdmin = $this->‪isAdmin();
2303  return ($globalConfig === 2 && !$isAdmin)
2304  || ($globalConfig === 3 && $isAdmin)
2305  || ($globalConfig === 4 && $this->‪isSystemMaintainer());
2306  }
2307 
2313  public function ‪isImportEnabled(): bool
2314  {
2315  return $this->‪isAdmin()
2316  || ($this->‪getTSConfig()['options.']['impexp.']['enableImportForNonAdminUser'] ?? false);
2317  }
2318 
2324  public function ‪isExportEnabled(): bool
2325  {
2326  return $this->‪isAdmin()
2327  || ($this->‪getTSConfig()['options.']['impexp.']['enableExportForNonAdminUser'] ?? false);
2328  }
2329 
2335  public function ‪shallDisplayDebugInformation(): bool
2336  {
2337  return (‪$GLOBALS['TYPO3_CONF_VARS']['BE']['debug'] ?? false) && $this->‪isAdmin();
2338  }
2339 }
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\returnWebmounts
‪array returnWebmounts()
Definition: BackendUserAuthentication.php:971
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\evaluateUserSpecificFileFilterSettings
‪evaluateUserSpecificFileFilterSettings()
Definition: BackendUserAuthentication.php:1469
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\isSystemMaintainer
‪isSystemMaintainer()
Definition: BackendUserAuthentication.php:409
‪TYPO3\CMS\Core\Database\Query\QueryHelper\parseOrderBy
‪static array array[] parseOrderBy(string $input)
Definition: QueryHelper.php:44
‪TYPO3\CMS\Core\Utility\GeneralUtility\trimExplode
‪static list< string > trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
Definition: GeneralUtility.php:916
‪TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction
Definition: HiddenRestriction.php:27
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\workspacePublishAccess
‪bool workspacePublishAccess($wsid)
Definition: BackendUserAuthentication.php:910
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\recordEditAccessInternals
‪bool recordEditAccessInternals($table, $idOrRow, $newRecord=false, $deletedRecord=false, $checkFullLanguageAccess=false)
Definition: BackendUserAuthentication.php:693
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getUserTsConfig
‪getUserTsConfig()
Definition: BackendUserAuthentication.php:959
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$usergroup_table
‪string $usergroup_table
Definition: BackendUserAuthentication.php:77
‪TYPO3\CMS\Core\Database\Connection\PARAM_INT
‪const PARAM_INT
Definition: Connection.php:47
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder
Definition: ExpressionBuilder.php:36
‪TYPO3\CMS\Core\Resource\ResourceStorage\getUid
‪int getUid()
Definition: ResourceStorage.php:328
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\setWebmounts
‪setWebmounts(array $mountPointUids, $append=false)
Definition: BackendUserAuthentication.php:982
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\EQ
‪const EQ
Definition: ExpressionBuilder.php:37
‪TYPO3\CMS\Core\SysLog\Action
Definition: Cache.php:18
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$formfield_status
‪string $formfield_status
Definition: BackendUserAuthentication.php:187
‪TYPO3\CMS\Core\TypoScript\UserTsConfig
Definition: UserTsConfig.php:28
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getPagePermsClause
‪string getPagePermsClause($perms)
Definition: BackendUserAuthentication.php:452
‪TYPO3\CMS\Core\Exception
Definition: Exception.php:22
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\initializeDbMountpointsInWorkspace
‪initializeDbMountpointsInWorkspace()
Definition: BackendUserAuthentication.php:1718
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\initializeFileStorages
‪initializeFileStorages()
Definition: BackendUserAuthentication.php:1234
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$formfield_uname
‪string $formfield_uname
Definition: BackendUserAuthentication.php:177
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\calcPerms
‪int calcPerms($row)
Definition: BackendUserAuthentication.php:521
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\workspaceAllowsLiveEditingInTable
‪workspaceAllowsLiveEditingInTable(string $table)
Definition: BackendUserAuthentication.php:800
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\checkAuthMode
‪bool checkAuthMode($table, $field, $value)
Definition: BackendUserAuthentication.php:590
‪TYPO3\CMS\Core\Authentication
Definition: AbstractAuthenticationService.php:16
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\prepareUserTsConfig
‪prepareUserTsConfig()
Definition: BackendUserAuthentication.php:1206
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$usergroup_column
‪string $usergroup_column
Definition: BackendUserAuthentication.php:72
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getTSConfig
‪array getTSConfig()
Definition: BackendUserAuthentication.php:949
‪TYPO3\CMS\Core\Type\Bitmask\Permission\NOTHING
‪const NOTHING
Definition: Permission.php:30
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$firstMainGroup
‪int $firstMainGroup
Definition: BackendUserAuthentication.php:202
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\isAdmin
‪bool isAdmin()
Definition: BackendUserAuthentication.php:243
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$uc_default
‪array $uc_default
Definition: BackendUserAuthentication.php:213
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\check
‪bool check($type, $value)
Definition: BackendUserAuthentication.php:576
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\fetchGroupData
‪fetchGroupData()
Definition: BackendUserAuthentication.php:1050
‪TYPO3\CMS\Core\Utility\StringUtility\uniqueList
‪static string uniqueList(string $list)
Definition: StringUtility.php:94
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getDefaultUploadTemporaryFolder
‪TYPO3 CMS Core Resource Folder null getDefaultUploadTemporaryFolder()
Definition: BackendUserAuthentication.php:1675
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\setDefaultWorkspace
‪setDefaultWorkspace()
Definition: BackendUserAuthentication.php:1904
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\isMemberOfGroup
‪bool isMemberOfGroup($groupId)
Definition: BackendUserAuthentication.php:257
‪TYPO3\CMS\Backend\Module\ModuleProvider
Definition: ModuleProvider.php:29
‪$fields
‪$fields
Definition: pages.php:5
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$writeAttemptLog
‪bool $writeAttemptLog
Definition: BackendUserAuthentication.php:197
‪TYPO3\CMS\Core\Database\Connection\PARAM_STR
‪const PARAM_STR
Definition: Connection.php:52
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getFileStorages
‪TYPO3 CMS Core Resource ResourceStorage[] getFileStorages()
Definition: BackendUserAuthentication.php:1455
‪TYPO3\CMS\Core\Type\Bitmask\Permission
Definition: Permission.php:26
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\isLoaded
‪static isLoaded(string $key)
Definition: ExtensionManagementUtility.php:93
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\backendCheckLogin
‪backendCheckLogin(ServerRequestInterface $request=null)
Definition: BackendUserAuthentication.php:2049
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\checkWorkspace
‪array false checkWorkspace(int|array $wsRec)
Definition: BackendUserAuthentication.php:1774
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$formfield_uident
‪string $formfield_uident
Definition: BackendUserAuthentication.php:182
‪TYPO3\CMS\Core\SysLog\Type\toChannel
‪static toChannel(int $type)
Definition: Type.php:76
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility
Definition: ExtensionManagementUtility.php:40
‪TYPO3\CMS\Core\Type\Bitmask\BackendGroupMountOption
Definition: BackendGroupMountOption.php:27
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\isInWebMount
‪int null isInWebMount($idOrRow, $readPerms='')
Definition: BackendUserAuthentication.php:301
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getCategoryMountPoints
‪array getCategoryMountPoints()
Definition: BackendUserAuthentication.php:1273
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\isMfaSetupRequired
‪isMfaSetupRequired()
Definition: BackendUserAuthentication.php:2263
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getFilePermissionsForStorage
‪array getFilePermissionsForStorage(ResourceStorage $storageObject)
Definition: BackendUserAuthentication.php:1569
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getCookieName
‪static string getCookieName()
Definition: BackendUserAuthentication.php:2031
‪TYPO3\CMS\Core\Type\Enumeration\cast
‪static static cast($value)
Definition: Enumeration.php:186
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getFileMountRecords
‪array getFileMountRecords()
Definition: BackendUserAuthentication.php:1306
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\mayMakeShortcut
‪bool mayMakeShortcut()
Definition: BackendUserAuthentication.php:787
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\resetUC
‪resetUC()
Definition: BackendUserAuthentication.php:2149
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$userid_column
‪string $userid_column
Definition: BackendUserAuthentication.php:157
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$filePermissions
‪array null $filePermissions
Definition: BackendUserAuthentication.php:137
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$user_table
‪string $user_table
Definition: BackendUserAuthentication.php:142
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\isRTE
‪isRTE()
Definition: BackendUserAuthentication.php:562
‪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:1168
‪TYPO3\CMS\Core\Database\Query\Restriction\RootLevelRestriction
Definition: RootLevelRestriction.php:27
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\evaluateMfaRequirements
‪evaluateMfaRequirements()
Definition: BackendUserAuthentication.php:2245
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\shallDisplayDebugInformation
‪shallDisplayDebugInformation()
Definition: BackendUserAuthentication.php:2312
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\setWorkspace
‪setWorkspace($workspaceId)
Definition: BackendUserAuthentication.php:1861
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getOriginalUserIdWhenInSwitchUserMode
‪int null getOriginalUserIdWhenInSwitchUserMode()
Definition: BackendUserAuthentication.php:2236
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$userTSUpdated
‪bool $userTSUpdated
Definition: BackendUserAuthentication.php:118
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\backendSetUC
‪backendSetUC()
Definition: BackendUserAuthentication.php:2109
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\ROLE_SYSTEMMAINTAINER
‪const ROLE_SYSTEMMAINTAINER
Definition: BackendUserAuthentication.php:67
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\isUserAllowedToLogin
‪bool isUserAllowedToLogin()
Definition: BackendUserAuthentication.php:2168
‪TYPO3\CMS\Core\Resource\Folder
Definition: Folder.php:37
‪TYPO3\CMS\Core\Resource\ResourceFactory
Definition: ResourceFactory.php:41
‪TYPO3\CMS\Core\Resource\Exception\FolderDoesNotExistException
Definition: FolderDoesNotExistException.php:22
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\hasEditAccessToLiveWorkspace
‪hasEditAccessToLiveWorkspace()
Definition: BackendUserAuthentication.php:1834
‪TYPO3\CMS\Core\Resource\StorageRepository
Definition: StorageRepository.php:38
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$groupData
‪array $groupData
Definition: BackendUserAuthentication.php:83
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\doesUserHaveAccess
‪bool doesUserHaveAccess($row, $perms)
Definition: BackendUserAuthentication.php:281
‪TYPO3\CMS\Webhooks\Message\$record
‪identifier readonly int readonly array $record
Definition: PageModificationMessage.php:36
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getFilePermissions
‪array getFilePermissions()
Definition: BackendUserAuthentication.php:1512
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$username_column
‪string $username_column
Definition: BackendUserAuthentication.php:147
‪TYPO3\CMS\Core\SysLog\Error
Definition: Error.php:24
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\getSessionData
‪mixed getSessionData($key)
Definition: AbstractUserAuthentication.php:1085
‪TYPO3\CMS\Core\Cache\CacheManager
Definition: CacheManager.php:36
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\checkLanguageAccess
‪bool checkLanguageAccess($langValue)
Definition: BackendUserAuthentication.php:623
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:66
‪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:2068
‪TYPO3\CMS\Core\Resource\Filter\FileNameFilter\setShowHiddenFilesAndFolders
‪static bool setShowHiddenFilesAndFolders($showHiddenFilesAndFolders)
Definition: FileNameFilter.php:71
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getDefaultUploadFolder
‪TYPO3 CMS Core Resource Folder bool getDefaultUploadFolder($pid=null, $table=null, $field=null)
Definition: BackendUserAuthentication.php:1604
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$checkWorkspaceCurrent_cache
‪array null $checkWorkspaceCurrent_cache
Definition: BackendUserAuthentication.php:129
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$userGroupsUID
‪array $userGroupsUID
Definition: BackendUserAuthentication.php:97
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$userTsConfig
‪UserTsConfig $userTsConfig
Definition: BackendUserAuthentication.php:112
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\overrideUC
‪overrideUC()
Definition: BackendUserAuthentication.php:2139
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$enablecolumns
‪array $enablecolumns
Definition: BackendUserAuthentication.php:166
‪TYPO3\CMS\Core\TypoScript\UserTsConfigFactory
Definition: UserTsConfigFactory.php:39
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$loginType
‪string $loginType
Definition: BackendUserAuthentication.php:226
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\logoff
‪logoff()
Definition: BackendUserAuthentication.php:2195
‪TYPO3\CMS\Core\Http\RedirectResponse
Definition: RedirectResponse.php:28
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\$user
‪array null $user
Definition: AbstractUserAuthentication.php:170
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\__construct
‪__construct()
Definition: BackendUserAuthentication.php:231
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\releaseLockedRecords
‪releaseLockedRecords(int $userId)
Definition: BackendUserAuthentication.php:2217
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:36
‪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:161
‪TYPO3\CMS\Core\Resource\ResourceStorage
Definition: ResourceStorage.php:127
‪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:1963
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\Type\Exception\InvalidEnumerationValueException
Definition: InvalidEnumerationValueException.php:24
‪TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction
Definition: DeletedRestriction.php:28
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:41
‪TYPO3\CMS\Core\Utility\GeneralUtility\intExplode
‪static int[] intExplode($delimiter, $string, $removeEmptyValues=false, $limit=0)
Definition: GeneralUtility.php:842
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\isExportEnabled
‪isExportEnabled()
Definition: BackendUserAuthentication.php:2301
‪TYPO3\CMS\Core\Utility\GeneralUtility\inList
‪static bool inList($list, $item)
Definition: GeneralUtility.php:532
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$workspace
‪int $workspace
Definition: BackendUserAuthentication.php:105
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\workspaceInit
‪workspaceInit()
Definition: BackendUserAuthentication.php:1703
‪TYPO3\CMS\Core\Resource\Filter\FileNameFilter
Definition: FileNameFilter.php:24
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:51
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\checkWorkspaceCurrent
‪array checkWorkspaceCurrent()
Definition: BackendUserAuthentication.php:1847
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\initializeWebmountsForElementBrowser
‪initializeWebmountsForElementBrowser()
Definition: BackendUserAuthentication.php:1005
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$userident_column
‪string $userident_column
Definition: BackendUserAuthentication.php:152
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:51
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\setTemporaryWorkspace
‪bool setTemporaryWorkspace($workspaceId)
Definition: BackendUserAuthentication.php:1888
‪TYPO3\CMS\Core\Utility\StringUtility
Definition: StringUtility.php:24
‪TYPO3\CMS\Core\Authentication\Event\AfterUserLoggedInEvent
Definition: AfterUserLoggedInEvent.php:29
‪TYPO3\CMS\Core\Http\ImmediateResponseException
Definition: ImmediateResponseException.php:35
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$workspaceRec
‪array $workspaceRec
Definition: BackendUserAuthentication.php:110
‪TYPO3\CMS\Core\Type\Bitmask\JsConfirmation
Definition: JsConfirmation.php:25
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\checkFullLanguagesAccess
‪bool checkFullLanguagesAccess($table, $record)
Definition: BackendUserAuthentication.php:643
‪TYPO3\CMS\Core\Routing\BackendEntryPointResolver
Definition: BackendEntryPointResolver.php:29
‪TYPO3\CMS\Core\Core\Environment\getContext
‪static getContext()
Definition: Environment.php:128
‪TYPO3\CMS\Core\Resource\Exception
Definition: AbstractFileOperationException.php:16
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\workspaceCheckStageForCurrent
‪bool workspaceCheckStageForCurrent($stage)
Definition: BackendUserAuthentication.php:848
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\workspaceCanCreateNewRecord
‪workspaceCanCreateNewRecord(string $table)
Definition: BackendUserAuthentication.php:829
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\isImportEnabled
‪isImportEnabled()
Definition: BackendUserAuthentication.php:2290
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$fileStorages
‪TYPO3 CMS Core Resource ResourceStorage[] $fileStorages
Definition: BackendUserAuthentication.php:133
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$writeStdLog
‪bool $writeStdLog
Definition: BackendUserAuthentication.php:192
‪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:61
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getDefaultWorkspace
‪int getDefaultWorkspace()
Definition: BackendUserAuthentication.php:1918
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\jsConfirmation
‪bool jsConfirmation($bitmask)
Definition: BackendUserAuthentication.php:1030
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\modAccess
‪bool modAccess($conf)
Definition: BackendUserAuthentication.php:364
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\writeUC
‪writeUC()
Definition: AbstractUserAuthentication.php:1006
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$errorMsg
‪string $errorMsg
Definition: BackendUserAuthentication.php:124
‪TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction
Definition: WorkspaceRestriction.php:40