‪TYPO3CMS  10.4
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 Doctrine\DBAL\Driver\Statement;
19 use Psr\Http\Message\ServerRequestInterface;
42 use ‪TYPO3\CMS\Core\SysLog\Action\Login as SystemLogLoginAction;
43 use ‪TYPO3\CMS\Core\SysLog\Error as SystemLogErrorClassification;
44 use ‪TYPO3\CMS\Core\SysLog\Type as SystemLogType;
52 use TYPO3\CMS\Install\Service\SessionService;
53 
62 {
63  public const ‪ROLE_SYSTEMMAINTAINER = 'systemMaintainer';
64 
69  public ‪$usergroup_column = 'usergroup';
70 
75  public ‪$usergroup_table = 'be_groups';
76 
82  public ‪$groupData = [
83  'filemounts' => []
84  ];
85 
90  public ‪$userGroups = [];
91 
96  public ‪$userGroupsUID = [];
97 
102  public ‪$groupList = '';
103 
111  public ‪$workspace = -99;
112 
117  public ‪$workspaceRec = [];
118 
126  public ‪$dataLists = [
127  'webmount_list' => '',
128  'filemount_list' => '',
129  'file_permissions' => '',
130  'modList' => '',
131  'tables_select' => '',
132  'tables_modify' => '',
133  'pagetypes_select' => '',
134  'non_exclude_fields' => '',
135  'explicit_allowdeny' => '',
136  'allowed_languages' => '',
137  'workspace_perms' => '',
138  'available_widgets' => '',
139  'custom_options' => ''
140  ];
141 
147  public ‪$includeGroupArray = [];
148 
152  protected ‪$userTS = [];
153 
157  protected ‪$userTSUpdated = false;
158 
164  public ‪$errorMsg = '';
165 
171 
175  protected ‪$fileStorages;
176 
180  protected ‪$filePermissions;
181 
186  public ‪$user_table = 'be_users';
187 
192  public ‪$username_column = 'username';
193 
198  public ‪$userident_column = 'password';
199 
204  public ‪$userid_column = 'uid';
205 
209  public ‪$lastLogin_column = 'lastlogin';
210 
214  public ‪$enablecolumns = [
215  'rootLevel' => 1,
216  'deleted' => 'deleted',
217  'disabled' => 'disable',
218  'starttime' => 'starttime',
219  'endtime' => 'endtime'
220  ];
221 
226  public ‪$formfield_uname = 'username';
227 
232  public ‪$formfield_uident = 'userident';
233 
238  public ‪$formfield_status = 'login_status';
239 
244  public ‪$writeStdLog = true;
245 
250  public ‪$writeAttemptLog = true;
251 
262  public ‪$sessionTimeout = 28800;
263 
268  public ‪$firstMainGroup = 0;
269 
274  public ‪$uc;
275 
286  public ‪$uc_default = [
287  'interfaceSetup' => '',
288  // serialized content that is used to store interface pane and menu positions. Set by the logout.php-script
289  'moduleData' => [],
290  // user-data for the modules
291  'thumbnailsByDefault' => 1,
292  'emailMeAtLogin' => 0,
293  'titleLen' => 50,
294  'edit_RTE' => '1',
295  'edit_docModuleUpload' => '1',
296  'resizeTextareas' => 1,
297  'resizeTextareas_MaxHeight' => 500,
298  'resizeTextareas_Flexible' => 0
299  ];
300 
305  public ‪$loginType = 'BE';
306 
310  public function ‪__construct()
311  {
312  $this->name = ‪self::getCookieName();
313  $this->warningEmail = ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['warning_email_addr'];
314  $this->sessionTimeout = (int)‪$GLOBALS['TYPO3_CONF_VARS']['BE']['sessionTimeout'];
315  parent::__construct();
316  }
317 
324  public function ‪isAdmin()
325  {
326  return is_array($this->user) && ($this->user['admin'] & 1) == 1;
327  }
328 
338  public function ‪isMemberOfGroup($groupId)
339  {
340  $groupId = (int)$groupId;
341  if ($this->groupList && $groupId) {
342  return GeneralUtility::inList($this->groupList, (string)$groupId);
343  }
344  return false;
345  }
346 
362  public function ‪doesUserHaveAccess($row, $perms)
363  {
364  $userPerms = $this->‪calcPerms($row);
365  return ($userPerms & $perms) == $perms;
366  }
367 
384  public function ‪isInWebMount($idOrRow, $readPerms = '', $exitOnError = 0)
385  {
386  if (!‪$GLOBALS['TYPO3_CONF_VARS']['BE']['lockBeUserToDBmounts'] || $this->‪isAdmin()) {
387  return 1;
388  }
389  $checkRec = [];
390  $fetchPageFromDatabase = true;
391  if (is_array($idOrRow)) {
392  if (!isset($idOrRow['uid'])) {
393  throw new \RuntimeException('The given page record is invalid. Missing uid.', 1578950324);
394  }
395  $checkRec = $idOrRow;
396  ‪$id = (int)$idOrRow['uid'];
397  // ensure the required fields are present on the record
398  if (isset($checkRec['t3ver_oid'], $checkRec[‪$GLOBALS['TCA']['pages']['ctrl']['languageField']], $checkRec[‪$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField']])) {
399  $fetchPageFromDatabase = false;
400  }
401  } else {
402  ‪$id = (int)$idOrRow;
403  }
404  if ($fetchPageFromDatabase) {
405  // Check if input id is an offline version page in which case we will map id to the online version:
406  $checkRec = ‪BackendUtility::getRecord(
407  'pages',
408  ‪$id,
409  't3ver_oid,'
410  . ‪$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'] . ','
411  . ‪$GLOBALS['TCA']['pages']['ctrl']['languageField']
412  );
413  }
414  if ($checkRec['t3ver_oid'] > 0) {
415  ‪$id = (int)$checkRec['t3ver_oid'];
416  }
417  // if current rec is a translation then get uid from l10n_parent instead
418  // because web mounts point to pages in default language and rootline returns uids of default languages
419  if ((int)$checkRec[‪$GLOBALS['TCA']['pages']['ctrl']['languageField']] !== 0 && (int)$checkRec[‪$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField']] !== 0) {
420  ‪$id = (int)$checkRec[‪$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField']];
421  }
422  if (!$readPerms) {
423  $readPerms = $this->‪getPagePermsClause(‪Permission::PAGE_SHOW);
424  }
425  if (‪$id > 0) {
426  $wM = $this->‪returnWebmounts();
427  $rL = ‪BackendUtility::BEgetRootLine(‪$id, ' AND ' . $readPerms, true);
428  foreach ($rL as $v) {
429  if ($v['uid'] && in_array($v['uid'], $wM)) {
430  return $v['uid'];
431  }
432  }
433  }
434  if ($exitOnError) {
435  throw new \RuntimeException('Access Error: This page is not within your DB-mounts', 1294586445);
436  }
437  return null;
438  }
439 
447  public function ‪modAccess($conf)
448  {
449  if (!‪BackendUtility::isModuleSetInTBE_MODULES($conf['name'])) {
450  throw new \RuntimeException('Fatal Error: This module "' . $conf['name'] . '" is not enabled in TBE_MODULES', 1294586446);
451  }
452  // Workspaces check:
453  if (
454  !empty($conf['workspaces'])
456  && ($this->workspace !== 0 || !GeneralUtility::inList($conf['workspaces'], 'online'))
457  && ($this->workspace !== -1 || !GeneralUtility::inList($conf['workspaces'], 'offline'))
458  && ($this->workspace <= 0 || !GeneralUtility::inList($conf['workspaces'], 'custom'))
459  ) {
460  throw new \RuntimeException('Workspace Error: This module "' . $conf['name'] . '" is not available under the current workspace', 1294586447);
461  }
462  // Returns false if conf[access] is set to system maintainers and the user is system maintainer
463  if (strpos($conf['access'], self::ROLE_SYSTEMMAINTAINER) !== false && !$this->‪isSystemMaintainer()) {
464  throw new \RuntimeException('This module "' . $conf['name'] . '" is only available as system maintainer', 1504804727);
465  }
466  // Returns TRUE if conf[access] is not set at all or if the user is admin
467  if (!$conf['access'] || $this->‪isAdmin()) {
468  return true;
469  }
470  // If $conf['access'] is set but not with 'admin' then we return TRUE, if the module is found in the modList
471  $acs = false;
472  if (strpos($conf['access'], 'admin') === false && $conf['name']) {
473  $acs = $this->‪check('modules', $conf['name']);
474  }
475  if (!$acs) {
476  throw new \RuntimeException('Access Error: You don\'t have access to this module.', 1294586448);
477  }
478  return $acs;
479  }
480 
488  public function ‪isSystemMaintainer(): bool
489  {
490  if (!$this->‪isAdmin()) {
491  return false;
492  }
493 
494  if ((int)‪$GLOBALS['BE_USER']->user['ses_backuserid'] !== 0) {
495  return false;
496  }
497  if (‪Environment::getContext()->isDevelopment()) {
498  return true;
499  }
500  $systemMaintainers = ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['systemMaintainers'] ?? [];
501  $systemMaintainers = array_map('intval', $systemMaintainers);
502  if (!empty($systemMaintainers)) {
503  return in_array((int)$this->user['uid'], $systemMaintainers, true);
504  }
505  // No system maintainers set up yet, so any admin is allowed to access the modules
506  // but explicitly no system maintainers allowed (empty string in TYPO3_CONF_VARS).
507  // @todo: this needs to be adjusted once system maintainers can log into the install tool with their credentials
508  if (isset(‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['systemMaintainers'])
509  && empty(‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['systemMaintainers'])) {
510  return false;
511  }
512  return true;
513  }
514 
531  public function ‪getPagePermsClause($perms)
532  {
533  if (is_array($this->user)) {
534  if ($this->‪isAdmin()) {
535  return ' 1=1';
536  }
537  // Make sure it's integer.
538  $perms = (int)$perms;
539  $expressionBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
540  ->getQueryBuilderForTable('pages')
541  ->expr();
542 
543  // User
544  $constraint = $expressionBuilder->orX(
545  $expressionBuilder->comparison(
546  $expressionBuilder->bitAnd('pages.perms_everybody', $perms),
548  $perms
549  ),
550  $expressionBuilder->andX(
551  $expressionBuilder->eq('pages.perms_userid', (int)$this->user['uid']),
552  $expressionBuilder->comparison(
553  $expressionBuilder->bitAnd('pages.perms_user', $perms),
555  $perms
556  )
557  )
558  );
559 
560  // Group (if any is set)
561  if ($this->groupList) {
562  $constraint->add(
563  $expressionBuilder->andX(
564  $expressionBuilder->in(
565  'pages.perms_groupid',
566  ‪GeneralUtility::intExplode(',', $this->groupList)
567  ),
568  $expressionBuilder->comparison(
569  $expressionBuilder->bitAnd('pages.perms_group', $perms),
571  $perms
572  )
573  )
574  );
575  }
576 
577  $constraint = ' (' . (string)$constraint . ')';
578 
579  // ****************
580  // getPagePermsClause-HOOK
581  // ****************
582  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauthgroup.php']['getPagePermsClause'] ?? [] as $_funcRef) {
583  $_params = ['currentClause' => $constraint, 'perms' => $perms];
584  $constraint = GeneralUtility::callUserFunction($_funcRef, $_params, $this);
585  }
586  return $constraint;
587  }
588  return ' 1=0';
589  }
590 
600  public function ‪calcPerms($row)
601  {
602  // Return 31 for admin users.
603  if ($this->‪isAdmin()) {
604  return ‪Permission::ALL;
605  }
606  // Return 0 if page is not within the allowed web mount
607  if (!$this->‪isInWebMount($row)) {
608  return ‪Permission::NOTHING;
609  }
611  if (
612  isset($row['perms_userid']) && isset($row['perms_user']) && isset($row['perms_groupid'])
613  && isset($row['perms_group']) && isset($row['perms_everybody']) && isset($this->groupList)
614  ) {
615  if ($this->user['uid'] == $row['perms_userid']) {
616  $out |= $row['perms_user'];
617  }
618  if ($this->‪isMemberOfGroup($row['perms_groupid'])) {
619  $out |= $row['perms_group'];
620  }
621  $out |= $row['perms_everybody'];
622  }
623  // ****************
624  // CALCPERMS hook
625  // ****************
626  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauthgroup.php']['calcPerms'] ?? [] as $_funcRef) {
627  $_params = [
628  'row' => $row,
629  'outputPermissions' => $out
630  ];
631  $out = GeneralUtility::callUserFunction($_funcRef, $_params, $this);
632  }
633  return $out;
634  }
635 
642  public function ‪isRTE(): bool
643  {
644  return (bool)($this->uc['edit_RTE'] ?? false);
645  }
646 
656  public function ‪check($type, $value)
657  {
658  return isset($this->groupData[$type])
659  && ($this->‪isAdmin() || GeneralUtility::inList($this->groupData[$type], $value));
660  }
661 
671  public function ‪checkAuthMode($table, $field, $value, $authMode)
672  {
673  // Admin users can do anything:
674  if ($this->‪isAdmin()) {
675  return true;
676  }
677  // Allow all blank values:
678  if ((string)$value === '') {
679  return true;
680  }
681  // Allow dividers:
682  if ($value === '--div--') {
683  return true;
684  }
685  // Certain characters are not allowed in the value
686  if (preg_match('/[:|,]/', $value)) {
687  return false;
688  }
689  // Initialize:
690  $testValue = $table . ':' . $field . ':' . $value;
691  $out = true;
692  // Checking value:
693  switch ((string)$authMode) {
694  case 'explicitAllow':
695  if (!GeneralUtility::inList($this->groupData['explicit_allowdeny'], $testValue . ':ALLOW')) {
696  $out = false;
697  }
698  break;
699  case 'explicitDeny':
700  if (GeneralUtility::inList($this->groupData['explicit_allowdeny'], $testValue . ':DENY')) {
701  $out = false;
702  }
703  break;
704  case 'individual':
705  if (is_array(‪$GLOBALS['TCA'][$table]) && is_array(‪$GLOBALS['TCA'][$table]['columns'][$field])) {
706  $items = ‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['items'];
707  if (is_array($items)) {
708  foreach ($items as $iCfg) {
709  if ((string)$iCfg[1] === (string)$value && ($iCfg[5] ?? '')) {
710  switch ((string)($iCfg[5] ?? '')) {
711  case 'EXPL_ALLOW':
712  if (!GeneralUtility::inList(
713  $this->groupData['explicit_allowdeny'],
714  $testValue . ':ALLOW'
715  )) {
716  $out = false;
717  }
718  break;
719  case 'EXPL_DENY':
720  if (GeneralUtility::inList($this->groupData['explicit_allowdeny'], $testValue . ':DENY')) {
721  $out = false;
722  }
723  break;
724  }
725  break;
726  }
727  }
728  }
729  }
730  break;
731  }
732  return $out;
733  }
734 
741  public function ‪checkLanguageAccess($langValue)
742  {
743  // The users language list must be non-blank - otherwise all languages are allowed.
744  if (trim($this->groupData['allowed_languages']) !== '') {
745  $langValue = (int)$langValue;
746  // Language must either be explicitly allowed OR the lang Value be "-1" (all languages)
747  if ($langValue != -1 && !$this->‪check('allowed_languages', (string)$langValue)) {
748  return false;
749  }
750  }
751  return true;
752  }
753 
761  public function ‪checkFullLanguagesAccess($table, $record)
762  {
763  if (!$this->‪checkLanguageAccess(0)) {
764  return false;
765  }
766 
768  $pointerField = ‪$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'];
769  $pointerValue = $record[$pointerField] > 0 ? $record[$pointerField] : $record['uid'];
770  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
771  $queryBuilder->getRestrictions()
772  ->removeAll()
773  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
774  ->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, (int)$this->workspace));
775  $recordLocalizations = $queryBuilder->select('*')
776  ->from($table)
777  ->where(
778  $queryBuilder->expr()->eq(
779  $pointerField,
780  $queryBuilder->createNamedParameter($pointerValue, \PDO::PARAM_INT)
781  )
782  )
783  ->execute()
784  ->fetchAll();
785 
786  foreach ($recordLocalizations as $recordLocalization) {
787  if (!$this->‪checkLanguageAccess($recordLocalization[‪$GLOBALS['TCA'][$table]['ctrl']['languageField']])) {
788  return false;
789  }
790  }
791  }
792  return true;
793  }
794 
811  public function ‪recordEditAccessInternals($table, $idOrRow, $newRecord = false, $deletedRecord = false, $checkFullLanguageAccess = false)
812  {
813  if (!isset(‪$GLOBALS['TCA'][$table])) {
814  return false;
815  }
816  // Always return TRUE for Admin users.
817  if ($this->‪isAdmin()) {
818  return true;
819  }
820  // Fetching the record if the $idOrRow variable was not an array on input:
821  if (!is_array($idOrRow)) {
822  if ($deletedRecord) {
823  $idOrRow = ‪BackendUtility::getRecord($table, $idOrRow, '*', '', false);
824  } else {
825  $idOrRow = ‪BackendUtility::getRecord($table, $idOrRow);
826  }
827  if (!is_array($idOrRow)) {
828  $this->errorMsg = 'ERROR: Record could not be fetched.';
829  return false;
830  }
831  }
832  // Checking languages:
833  if ($table === 'pages' && $checkFullLanguageAccess && !$this->‪checkFullLanguagesAccess($table, $idOrRow)) {
834  return false;
835  }
836  if (‪$GLOBALS['TCA'][$table]['ctrl']['languageField']) {
837  // Language field must be found in input row - otherwise it does not make sense.
838  if (isset($idOrRow[‪$GLOBALS['TCA'][$table]['ctrl']['languageField']])) {
839  if (!$this->‪checkLanguageAccess($idOrRow[‪$GLOBALS['TCA'][$table]['ctrl']['languageField']])) {
840  $this->errorMsg = 'ERROR: Language was not allowed.';
841  return false;
842  }
843  if (
844  $checkFullLanguageAccess && $idOrRow[‪$GLOBALS['TCA'][$table]['ctrl']['languageField']] == 0
845  && !$this->‪checkFullLanguagesAccess($table, $idOrRow)
846  ) {
847  $this->errorMsg = 'ERROR: Related/affected language was not allowed.';
848  return false;
849  }
850  } else {
851  $this->errorMsg = 'ERROR: The "languageField" field named "'
852  . ‪$GLOBALS['TCA'][$table]['ctrl']['languageField'] . '" was not found in testing record!';
853  return false;
854  }
855  }
856  // Checking authMode fields:
857  if (is_array(‪$GLOBALS['TCA'][$table]['columns'])) {
858  foreach (‪$GLOBALS['TCA'][$table]['columns'] as $fieldName => $fieldValue) {
859  if (isset($idOrRow[$fieldName])) {
860  if (
861  $fieldValue['config']['type'] === 'select' && $fieldValue['config']['authMode']
862  && $fieldValue['config']['authMode_enforce'] === 'strict'
863  ) {
864  if (!$this->‪checkAuthMode($table, $fieldName, $idOrRow[$fieldName], $fieldValue['config']['authMode'])) {
865  $this->errorMsg = 'ERROR: authMode "' . $fieldValue['config']['authMode']
866  . '" failed for field "' . $fieldName . '" with value "'
867  . $idOrRow[$fieldName] . '" evaluated';
868  return false;
869  }
870  }
871  }
872  }
873  }
874  // Checking "editlock" feature (doesn't apply to new records)
875  if (!$newRecord && ‪$GLOBALS['TCA'][$table]['ctrl']['editlock']) {
876  if (isset($idOrRow[‪$GLOBALS['TCA'][$table]['ctrl']['editlock']])) {
877  if ($idOrRow[‪$GLOBALS['TCA'][$table]['ctrl']['editlock']]) {
878  $this->errorMsg = 'ERROR: Record was locked for editing. Only admin users can change this state.';
879  return false;
880  }
881  } else {
882  $this->errorMsg = 'ERROR: The "editLock" field named "' . ‪$GLOBALS['TCA'][$table]['ctrl']['editlock']
883  . '" was not found in testing record!';
884  return false;
885  }
886  }
887  // Checking record permissions
888  // THIS is where we can include a check for "perms_" fields for other records than pages...
889  // Process any hooks
890  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauthgroup.php']['recordEditAccessInternals'] ?? [] as $funcRef) {
891  $params = [
892  'table' => $table,
893  'idOrRow' => $idOrRow,
894  'newRecord' => $newRecord
895  ];
896  if (!GeneralUtility::callUserFunction($funcRef, $params, $this)) {
897  return false;
898  }
899  }
900  // Finally, return TRUE if all is well.
901  return true;
902  }
903 
909  public function ‪mayMakeShortcut()
910  {
911  return ($this->‪getTSConfig()['options.']['enableBookmarks'] ?? false)
912  && !($this->‪getTSConfig()['options.']['mayNotCreateEditBookmarks'] ?? false);
913  }
914 
927  public function ‪workspaceCannotEditRecord($table, $recData)
928  {
929  // Only test if the user is in a workspace
930  if ($this->workspace === 0) {
931  return false;
932  }
933  $tableSupportsVersioning = ‪BackendUtility::isTableWorkspaceEnabled($table);
934  if (!is_array($recData)) {
935  $recData = ‪BackendUtility::getRecord(
936  $table,
937  $recData,
938  'pid' . ($tableSupportsVersioning ? ',t3ver_oid,t3ver_wsid,t3ver_stage' : '')
939  );
940  }
941  if (is_array($recData)) {
942  // We are testing a "version" (identified by having a t3ver_oid): it can be edited provided
943  // that workspace matches and versioning is enabled for the table.
944  if ($tableSupportsVersioning && (int)($recData['t3ver_oid'] ?? 0) > 0) {
945  if ((int)$recData['t3ver_wsid'] !== $this->workspace) {
946  // So does workspace match?
947  return 'Workspace ID of record didn\'t match current workspace';
948  }
949  // So is the user allowed to "use" the edit stage within the workspace?
950  return $this->‪workspaceCheckStageForCurrent(0)
951  ? false
952  : 'User\'s access level did not allow for editing';
953  }
954  // Check if we are testing a "live" record
955  if ($this->‪workspaceAllowsLiveEditingInTable($table)) {
956  // Live records are OK in the current workspace
957  return false;
958  }
959  // If not offline, output error
960  return 'Online record was not in a workspace!';
961  }
962  return 'No record';
963  }
964 
974  public function ‪workspaceCannotEditOfflineVersion($table, $recData)
975  {
977  return 'Table does not support versioning.';
978  }
979  if (!is_array($recData)) {
980  $recData = ‪BackendUtility::getRecord($table, $recData, 'uid,pid,t3ver_oid,t3ver_wsid,t3ver_stage');
981  }
982  if (is_array($recData)) {
983  if ((int)$recData['t3ver_oid'] > 0) {
984  return $this->‪workspaceCannotEditRecord($table, $recData);
985  }
986  return 'Not an offline version';
987  }
988  return 'No record';
989  }
990 
1005  public function ‪workspaceAllowLiveRecordsInPID($pid, $table)
1006  {
1007  // Always for Live workspace AND if live-edit is enabled
1008  // and tables are completely without versioning it is ok as well.
1009  if (
1010  $this->workspace === 0
1011  || $this->workspaceRec['live_edit'] && !‪BackendUtility::isTableWorkspaceEnabled($table)
1012  || ‪$GLOBALS['TCA'][$table]['ctrl']['versioningWS_alwaysAllowLiveEdit']
1013  ) {
1014  // OK to create for this table.
1015  return 2;
1016  }
1017  // If the answer is FALSE it means the only valid way to create or edit records in the PID is by versioning
1018  return false;
1019  }
1020 
1030  public function ‪workspaceAllowsLiveEditingInTable(string $table): bool
1031  {
1032  // In live workspace the record can be added/modified
1033  if ($this->workspace === 0) {
1034  return true;
1035  }
1036  // Workspace setting allows to "live edit" records of tables without versioning
1037  if ($this->workspaceRec['live_edit'] && !‪BackendUtility::isTableWorkspaceEnabled($table)) {
1038  return true;
1039  }
1040  // Always for Live workspace AND if live-edit is enabled
1041  // and tables are completely without versioning it is ok as well.
1042  if (‪$GLOBALS['TCA'][$table]['ctrl']['versioningWS_alwaysAllowLiveEdit']) {
1043  return true;
1044  }
1045  // If the answer is FALSE it means the only valid way to create or edit records by creating records in the workspace
1046  return false;
1047  }
1048 
1059  public function ‪workspaceCreateNewRecord($pid, $table)
1060  {
1061  // If LIVE records cannot be created due to workspace restrictions, prepare creation of placeholder-record
1063  // So, if no live records were allowed, we have to create a new version of this record
1064  return false;
1065  }
1066  return true;
1067  }
1068 
1078  public function ‪workspaceCanCreateNewRecord(string $table): bool
1079  {
1080  // If LIVE records cannot be created due to workspace restrictions, prepare creation of placeholder-record
1082  return false;
1083  }
1084  return true;
1085  }
1086 
1099  public function ‪workspaceAllowAutoCreation($table, ‪$id, $recpid)
1100  {
1101  // No version can be created in live workspace
1102  if ($this->workspace === 0) {
1103  return false;
1104  }
1105  // No versioning support for this table, so no version can be created
1107  return false;
1108  }
1109  if ($recpid < 0) {
1110  return false;
1111  }
1112  // There must be no existing version of this record in workspace
1113  if (‪BackendUtility::getWorkspaceVersionOfRecord($this->workspace, $table, ‪$id, 'uid')) {
1114  return false;
1115  }
1116  return true;
1117  }
1118 
1129  public function ‪workspaceCheckStageForCurrent($stage)
1130  {
1131  // Always allow for admins
1132  if ($this->‪isAdmin()) {
1133  return true;
1134  }
1135  // Always OK for live workspace
1136  if ($this->workspace === 0 || !‪ExtensionManagementUtility::isLoaded('workspaces')) {
1137  return true;
1138  }
1139  $stage = (int)$stage;
1140  $stat = $this->‪checkWorkspaceCurrent();
1141  $accessType = $stat['_ACCESS'];
1142  // Workspace owners are always allowed for stage change
1143  if ($accessType === 'owner') {
1144  return true;
1145  }
1146 
1147  // Check if custom staging is activated
1148  ‪$workspaceRec = ‪BackendUtility::getRecord('sys_workspace', $stat['uid']);
1149  if (‪$workspaceRec['custom_stages'] > 0 && $stage !== 0 && $stage !== -10) {
1150  // Get custom stage record
1151  $workspaceStageRec = ‪BackendUtility::getRecord('sys_workspace_stage', $stage);
1152  // Check if the user is responsible for the current stage
1153  if (
1154  $accessType === 'member'
1155  && GeneralUtility::inList($workspaceStageRec['responsible_persons'], 'be_users_' . $this->user['uid'])
1156  ) {
1157  return true;
1158  }
1159  // Check if the user is in a group which is responsible for the current stage
1160  foreach ($this->userGroupsUID as $groupUid) {
1161  if (
1162  $accessType === 'member'
1163  && GeneralUtility::inList($workspaceStageRec['responsible_persons'], 'be_groups_' . $groupUid)
1164  ) {
1165  return true;
1166  }
1167  }
1168  } elseif ($stage === -10 || $stage === -20) {
1169  // Nobody is allowed to do that except the owner (which was checked above)
1170  return false;
1171  } elseif (
1172  $accessType === 'reviewer' && $stage <= 1
1173  || $accessType === 'member' && $stage <= 0
1174  ) {
1175  return true;
1176  }
1177  return false;
1178  }
1179 
1191  public function ‪workspacePublishAccess($wsid)
1192  {
1193  if ($this->‪isAdmin()) {
1194  return true;
1195  }
1196  $wsAccess = $this->‪checkWorkspace($wsid);
1197  // If no access to workspace, of course you cannot publish!
1198  if ($wsAccess === false) {
1199  return false;
1200  }
1201  if ((int)$wsAccess['uid'] === 0) {
1202  // If access to Live workspace, no problem.
1203  return true;
1204  }
1205  // Custom workspaces
1206  // 1. Owners can always publish
1207  if ($wsAccess['_ACCESS'] === 'owner') {
1208  return true;
1209  }
1210  // 2. User has access to online workspace which is OK as well as long as publishing
1211  // access is not limited by workspace option.
1212  return $this->‪checkWorkspace(0) && !($wsAccess['publish_access'] & 2);
1213  }
1214 
1221  public function ‪workspaceSwapAccess()
1222  {
1223  // Always possible in live workspace
1224  if ($this->workspace === 0) {
1225  return true;
1226  }
1227  // In custom workspaces, only possible if swap_modes flag is not "2" (explicitly disabling swapping)
1228  if ((int)$this->workspaceRec['swap_modes'] !== 2) {
1229  return true;
1230  }
1231  return false;
1232  }
1233 
1249  public function ‪getTSConfig()
1250  {
1251  return ‪$this->userTS;
1252  }
1253 
1261  public function ‪returnWebmounts()
1262  {
1263  return (string)$this->groupData['webmounts'] != '' ? explode(',', $this->groupData['webmounts']) : [];
1264  }
1265 
1272  public function ‪setWebmounts(array $mountPointUids, $append = false)
1273  {
1274  if (empty($mountPointUids)) {
1275  return;
1276  }
1277  if ($append) {
1278  $currentWebMounts = ‪GeneralUtility::intExplode(',', $this->groupData['webmounts']);
1279  $mountPointUids = array_merge($currentWebMounts, $mountPointUids);
1280  }
1281  $this->groupData['webmounts'] = implode(',', array_unique($mountPointUids));
1282  }
1283 
1295  public function ‪initializeWebmountsForElementBrowser()
1296  {
1297  $alternativeWebmountPoint = (int)$this->‪getSessionData('pageTree_temporaryMountPoint');
1298  if ($alternativeWebmountPoint) {
1299  $alternativeWebmountPoint = ‪GeneralUtility::intExplode(',', (string)$alternativeWebmountPoint);
1300  $this->‪setWebmounts($alternativeWebmountPoint);
1301  return;
1302  }
1303 
1304  $alternativeWebmountPoints = trim($this->‪getTSConfig()['options.']['pageTree.']['altElementBrowserMountPoints'] ?? '');
1305  $appendAlternativeWebmountPoints = $this->‪getTSConfig()['options.']['pageTree.']['altElementBrowserMountPoints.']['append'] ?? '';
1306  if ($alternativeWebmountPoints) {
1307  $alternativeWebmountPoints = ‪GeneralUtility::intExplode(',', $alternativeWebmountPoints);
1308  $this->‪setWebmounts($alternativeWebmountPoints, $appendAlternativeWebmountPoints);
1309  }
1310  }
1311 
1320  public function ‪jsConfirmation($bitmask)
1321  {
1322  try {
1323  $alertPopupsSetting = trim((string)($this->‪getTSConfig()['options.']['alertPopups'] ?? ''));
1324  $alertPopup = ‪JsConfirmation::cast($alertPopupsSetting === '' ? null : (int)$alertPopupsSetting);
1325  } catch (InvalidEnumerationValueException $e) {
1326  $alertPopup = new JsConfirmation();
1327  }
1328 
1329  return ‪JsConfirmation::cast($bitmask)->matches($alertPopup);
1330  }
1331 
1341  public function ‪fetchGroupData()
1342  {
1343  if ($this->user['uid']) {
1344  // Get lists for the be_user record and set them as default/primary values.
1345  // Enabled Backend Modules
1346  $this->dataLists['modList'] = $this->user['userMods'];
1347  // Add available widgets
1348  $this->dataLists['available_widgets'] = $this->user['available_widgets'] ?? '';
1349  // Add Allowed Languages
1350  $this->dataLists['allowed_languages'] = $this->user['allowed_languages'];
1351  // Set user value for workspace permissions.
1352  $this->dataLists['workspace_perms'] = $this->user['workspace_perms'];
1353  // Database mountpoints
1354  $this->dataLists['webmount_list'] = $this->user['db_mountpoints'];
1355  // File mountpoints
1356  $this->dataLists['filemount_list'] = $this->user['file_mountpoints'];
1357  // Fileoperation permissions
1358  $this->dataLists['file_permissions'] = $this->user['file_permissions'];
1359 
1360  // BE_GROUPS:
1361  // Get the groups...
1362  if (!empty($this->user[$this->usergroup_column])) {
1363  // Fetch groups will add a lot of information to the internal arrays: modules, accesslists, TSconfig etc.
1364  // Refer to fetchGroups() function.
1365  $this->‪fetchGroups($this->user[$this->usergroup_column]);
1366  }
1367  // Populating the $this->userGroupsUID -array with the groups in the order in which they were LAST included.!!
1368  $this->userGroupsUID = array_reverse(array_unique(array_reverse($this->includeGroupArray)));
1369  // Finally this is the list of group_uid's in the order they are parsed (including subgroups!)
1370  // and without duplicates (duplicates are presented with their last entrance in the list,
1371  // which thus reflects the order of the TypoScript in TSconfig)
1372  $this->groupList = implode(',', $this->userGroupsUID);
1373  $this->‪setCachedList($this->groupList);
1374 
1375  $this->‪prepareUserTsConfig();
1376 
1377  // Processing webmounts
1378  // Admin's always have the root mounted
1379  if ($this->‪isAdmin() && !($this->‪getTSConfig()['options.']['dontMountAdminMounts'] ?? false)) {
1380  $this->dataLists['webmount_list'] = '0,' . $this->dataLists['webmount_list'];
1381  }
1382  // The lists are cleaned for duplicates
1383  $this->groupData['webmounts'] = GeneralUtility::uniqueList($this->dataLists['webmount_list']);
1384  $this->groupData['pagetypes_select'] = GeneralUtility::uniqueList($this->dataLists['pagetypes_select']);
1385  $this->groupData['tables_select'] = GeneralUtility::uniqueList($this->dataLists['tables_modify'] . ',' . $this->dataLists['tables_select']);
1386  $this->groupData['tables_modify'] = GeneralUtility::uniqueList($this->dataLists['tables_modify']);
1387  $this->groupData['non_exclude_fields'] = GeneralUtility::uniqueList($this->dataLists['non_exclude_fields']);
1388  $this->groupData['explicit_allowdeny'] = GeneralUtility::uniqueList($this->dataLists['explicit_allowdeny']);
1389  $this->groupData['allowed_languages'] = GeneralUtility::uniqueList($this->dataLists['allowed_languages']);
1390  $this->groupData['custom_options'] = GeneralUtility::uniqueList($this->dataLists['custom_options']);
1391  $this->groupData['modules'] = GeneralUtility::uniqueList($this->dataLists['modList']);
1392  $this->groupData['available_widgets'] = GeneralUtility::uniqueList($this->dataLists['available_widgets']);
1393  $this->groupData['file_permissions'] = GeneralUtility::uniqueList($this->dataLists['file_permissions']);
1394  $this->groupData['workspace_perms'] = $this->dataLists['workspace_perms'];
1395 
1396  if (!empty(trim($this->groupData['webmounts']))) {
1397  // Checking read access to web mounts if there are mounts points (not empty string, false or 0)
1398  $webmounts = explode(',', $this->groupData['webmounts']);
1399  // Selecting all web mounts with permission clause for reading
1400  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
1401  $queryBuilder->getRestrictions()
1402  ->removeAll()
1403  ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
1404 
1405  $MProws = $queryBuilder->select('uid')
1406  ->from('pages')
1407  // @todo DOCTRINE: check how to make getPagePermsClause() portable
1408  ->where(
1410  $queryBuilder->expr()->in(
1411  'uid',
1412  $queryBuilder->createNamedParameter(
1413  ‪GeneralUtility::intExplode(',', $this->groupData['webmounts']),
1414  Connection::PARAM_INT_ARRAY
1415  )
1416  )
1417  )
1418  ->execute()
1419  ->fetchAll();
1420  $MProws = array_column(($MProws ?: []), 'uid', 'uid');
1421  foreach ($webmounts as $idx => $mountPointUid) {
1422  // If the mount ID is NOT found among selected pages, unset it:
1423  if ($mountPointUid > 0 && !isset($MProws[$mountPointUid])) {
1424  unset($webmounts[$idx]);
1425  }
1426  }
1427  // Implode mounts in the end.
1428  $this->groupData['webmounts'] = implode(',', $webmounts);
1429  }
1430  // Setting up workspace situation (after webmounts are processed!):
1431  $this->‪workspaceInit();
1432  }
1433  }
1434 
1439  protected function ‪prepareUserTsConfig(): void
1440  {
1441  $collectedUserTSconfig = [
1442  'default' => ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['defaultUserTSconfig']
1443  ];
1444  // Default TSconfig for admin-users
1445  if ($this->‪isAdmin()) {
1446  $collectedUserTSconfig[] = 'admPanel.enable.all = 1';
1447  }
1448  // Setting defaults for sys_note author / email
1449  $collectedUserTSconfig[] = '
1450 TCAdefaults.sys_note.author = ' . $this->user['realName'] . '
1451 TCAdefaults.sys_note.email = ' . $this->user['email'];
1452 
1453  // Loop through all groups and add their 'TSconfig' fields
1454  foreach ($this->includeGroupArray as $groupId) {
1455  $collectedUserTSconfig['group_' . $groupId] = $this->userGroups[$groupId]['TSconfig'] ?? '';
1456  }
1457 
1458  $collectedUserTSconfig[] = $this->user['TSconfig'];
1459  // Check external files
1460  $collectedUserTSconfig = ‪TypoScriptParser::checkIncludeLines_array($collectedUserTSconfig);
1461  // Imploding with "[global]" will make sure that non-ended confinements with braces are ignored.
1462  $userTS_text = implode("\n[GLOBAL]\n", $collectedUserTSconfig);
1463  // Parsing the user TSconfig (or getting from cache)
1464  $hash = md5('userTS:' . $userTS_text);
1465  $cache = GeneralUtility::makeInstance(CacheManager::class)->getCache('hash');
1466  if (!($this->userTS = $cache->get($hash))) {
1467  $parseObj = GeneralUtility::makeInstance(TypoScriptParser::class);
1468  $conditionMatcher = GeneralUtility::makeInstance(ConditionMatcher::class);
1469  $parseObj->parse($userTS_text, $conditionMatcher);
1470  $this->userTS = $parseObj->setup;
1471  $cache->set($hash, $this->userTS, ['UserTSconfig'], 0);
1472  // Ensure to update UC later
1473  $this->userTSUpdated = true;
1474  }
1475  }
1476 
1485  public function ‪fetchGroups($grList, $idList = '')
1486  {
1487  // Fetching records of the groups in $grList (which are not blocked by lockedToDomain either):
1488  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->usergroup_table);
1489  $expressionBuilder = $queryBuilder->expr();
1490  $constraints = $expressionBuilder->andX(
1491  $expressionBuilder->eq(
1492  'pid',
1493  $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
1494  ),
1495  $expressionBuilder->in(
1496  'uid',
1497  $queryBuilder->createNamedParameter(
1498  ‪GeneralUtility::intExplode(',', $grList),
1499  Connection::PARAM_INT_ARRAY
1500  )
1501  ),
1502  $expressionBuilder->orX(
1503  $expressionBuilder->eq('lockToDomain', $queryBuilder->quote('')),
1504  $expressionBuilder->isNull('lockToDomain'),
1505  $expressionBuilder->eq(
1506  'lockToDomain',
1507  $queryBuilder->createNamedParameter(GeneralUtility::getIndpEnv('HTTP_HOST'), \PDO::PARAM_STR)
1508  )
1509  )
1510  );
1511  // Hook for manipulation of the WHERE sql sentence which controls which BE-groups are included
1512  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauthgroup.php']['fetchGroupQuery'] ?? [] as $className) {
1513  $hookObj = GeneralUtility::makeInstance($className);
1514  if (method_exists($hookObj, 'fetchGroupQuery_processQuery')) {
1515  $constraints = $hookObj->fetchGroupQuery_processQuery($this, $grList, $idList, (string)$constraints);
1516  }
1517  }
1518  $res = $queryBuilder->select('*')
1519  ->from($this->usergroup_table)
1520  ->where($constraints)
1521  ->execute();
1522  // The userGroups array is filled
1523  while ($row = $res->fetch(\PDO::FETCH_ASSOC)) {
1524  $this->userGroups[$row['uid']] = $row;
1525  }
1526  // Traversing records in the correct order
1527  foreach (explode(',', $grList) as $uid) {
1528  // Get row:
1529  $row = $this->userGroups[$uid];
1530  // Must be an array and $uid should not be in the idList, because then it is somewhere previously in the grouplist
1531  if (is_array($row) && !GeneralUtility::inList($idList, $uid)) {
1532  // Include sub groups
1533  if (trim($row['subgroup'])) {
1534  // Make integer list
1535  $theList = implode(',', ‪GeneralUtility::intExplode(',', $row['subgroup']));
1536  // Call recursively, pass along list of already processed groups so they are not recursed again.
1537  $this->‪fetchGroups($theList, $idList . ',' . $uid);
1538  }
1539  // Add the group uid, current list to the internal arrays.
1540  $this->includeGroupArray[] = $uid;
1541  // Mount group database-mounts
1542  if (($this->user['options'] & ‪Permission::PAGE_SHOW) == 1) {
1543  $this->dataLists['webmount_list'] .= ',' . $row['db_mountpoints'];
1544  }
1545  // Mount group file-mounts
1546  if (($this->user['options'] & ‪Permission::PAGE_EDIT) == 2) {
1547  $this->dataLists['filemount_list'] .= ',' . $row['file_mountpoints'];
1548  }
1549  // The lists are made: groupMods, tables_select, tables_modify, pagetypes_select, non_exclude_fields, explicit_allowdeny, allowed_languages, custom_options
1550  $this->dataLists['modList'] .= ',' . $row['groupMods'];
1551  $this->dataLists['available_widgets'] .= ',' . $row['availableWidgets'];
1552  $this->dataLists['tables_select'] .= ',' . $row['tables_select'];
1553  $this->dataLists['tables_modify'] .= ',' . $row['tables_modify'];
1554  $this->dataLists['pagetypes_select'] .= ',' . $row['pagetypes_select'];
1555  $this->dataLists['non_exclude_fields'] .= ',' . $row['non_exclude_fields'];
1556  $this->dataLists['explicit_allowdeny'] .= ',' . $row['explicit_allowdeny'];
1557  $this->dataLists['allowed_languages'] .= ',' . $row['allowed_languages'];
1558  $this->dataLists['custom_options'] .= ',' . $row['custom_options'];
1559  $this->dataLists['file_permissions'] .= ',' . $row['file_permissions'];
1560  // Setting workspace permissions:
1561  $this->dataLists['workspace_perms'] |= $row['workspace_perms'];
1562  // If this function is processing the users OWN group-list (not subgroups) AND
1563  // if the ->firstMainGroup is not set, then the ->firstMainGroup will be set.
1564  if ($idList === '' && !$this->firstMainGroup) {
1565  $this->firstMainGroup = $uid;
1566  }
1567  }
1568  }
1569  // HOOK: fetchGroups_postProcessing
1570  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauthgroup.php']['fetchGroups_postProcessing'] ?? [] as $_funcRef) {
1571  $_params = [];
1572  GeneralUtility::callUserFunction($_funcRef, $_params, $this);
1573  }
1574  }
1575 
1586  public function ‪setCachedList($cList)
1587  {
1588  if ((string)$cList != (string)$this->user['usergroup_cached_list']) {
1589  GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('be_users')->update(
1590  'be_users',
1591  ['usergroup_cached_list' => $cList],
1592  ['uid' => (int)$this->user['uid']]
1593  );
1594  }
1595  }
1596 
1601  protected function ‪initializeFileStorages()
1602  {
1603  $this->fileStorages = [];
1605  $storageRepository = GeneralUtility::makeInstance(StorageRepository::class);
1606  // Admin users have all file storages visible, without any filters
1607  if ($this->‪isAdmin()) {
1608  $storageObjects = $storageRepository->findAll();
1609  foreach ($storageObjects as $storageObject) {
1610  $this->fileStorages[$storageObject->getUid()] = $storageObject;
1611  }
1612  } else {
1613  // Regular users only have storages that are defined in their filemounts
1614  // Permissions and file mounts for the storage are added in StoragePermissionAspect
1615  foreach ($this->‪getFileMountRecords() as $row) {
1616  if (!array_key_exists((int)$row['base'], $this->fileStorages)) {
1617  $storageObject = $storageRepository->findByUid($row['base']);
1618  if ($storageObject) {
1619  $this->fileStorages[$storageObject->getUid()] = $storageObject;
1620  }
1621  }
1622  }
1623  }
1624 
1625  // This has to be called always in order to set certain filters
1627  }
1628 
1635  public function ‪getCategoryMountPoints()
1636  {
1637  $categoryMountPoints = '';
1638 
1639  // Category mounts of the groups
1640  if (is_array($this->userGroups)) {
1641  foreach ($this->userGroups as $group) {
1642  if ($group['category_perms']) {
1643  $categoryMountPoints .= ',' . $group['category_perms'];
1644  }
1645  }
1646  }
1647 
1648  // Category mounts of the user record
1649  if ($this->user['category_perms']) {
1650  $categoryMountPoints .= ',' . $this->user['category_perms'];
1651  }
1652 
1653  // Make the ids unique
1654  $categoryMountPoints = ‪GeneralUtility::trimExplode(',', $categoryMountPoints);
1655  $categoryMountPoints = array_filter($categoryMountPoints); // remove empty value
1656  $categoryMountPoints = array_unique($categoryMountPoints); // remove unique value
1657 
1658  return $categoryMountPoints;
1659  }
1660 
1668  public function ‪getFileMountRecords()
1669  {
1670  $runtimeCache = GeneralUtility::makeInstance(CacheManager::class)->getCache('runtime');
1671  $fileMountRecordCache = $runtimeCache->get('backendUserAuthenticationFileMountRecords') ?: [];
1672 
1673  if (!empty($fileMountRecordCache)) {
1674  return $fileMountRecordCache;
1675  }
1676 
1677  $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
1678 
1679  // Processing file mounts (both from the user and the groups)
1680  $fileMounts = array_unique(‪GeneralUtility::intExplode(',', $this->dataLists['filemount_list'], true));
1681 
1682  // Limit file mounts if set in workspace record
1683  if ($this->workspace > 0 && !empty($this->workspaceRec['file_mountpoints'])) {
1684  $workspaceFileMounts = ‪GeneralUtility::intExplode(',', $this->workspaceRec['file_mountpoints'], true);
1685  $fileMounts = array_intersect($fileMounts, $workspaceFileMounts);
1686  }
1687 
1688  if (!empty($fileMounts)) {
1689  $orderBy = ‪$GLOBALS['TCA']['sys_filemounts']['ctrl']['default_sortby'] ?? 'sorting';
1690 
1691  $queryBuilder = $connectionPool->getQueryBuilderForTable('sys_filemounts');
1692  $queryBuilder->getRestrictions()
1693  ->removeAll()
1694  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
1695  ->add(GeneralUtility::makeInstance(HiddenRestriction::class))
1696  ->add(GeneralUtility::makeInstance(RootLevelRestriction::class));
1697 
1698  $queryBuilder->select('*')
1699  ->from('sys_filemounts')
1700  ->where(
1701  $queryBuilder->expr()->in('uid', $queryBuilder->createNamedParameter($fileMounts, Connection::PARAM_INT_ARRAY))
1702  );
1703 
1704  foreach (‪QueryHelper::parseOrderBy($orderBy) as $fieldAndDirection) {
1705  $queryBuilder->addOrderBy(...$fieldAndDirection);
1706  }
1707 
1708  $fileMountRecords = $queryBuilder->execute()->fetchAll(\PDO::FETCH_ASSOC);
1709  if ($fileMountRecords !== false) {
1710  foreach ($fileMountRecords as $fileMount) {
1711  $fileMountRecordCache[$fileMount['base'] . $fileMount['path']] = $fileMount;
1712  }
1713  }
1714  }
1715 
1716  // Read-only file mounts
1717  $readOnlyMountPoints = \trim($this->‪getTSConfig()['options.']['folderTree.']['altElementBrowserMountPoints'] ?? '');
1718  if ($readOnlyMountPoints) {
1719  // We cannot use the API here but need to fetch the default storage record directly
1720  // to not instantiate it (which directly applies mount points) before all mount points are resolved!
1721  $queryBuilder = $connectionPool->getQueryBuilderForTable('sys_file_storage');
1722  $defaultStorageRow = $queryBuilder->select('uid')
1723  ->from('sys_file_storage')
1724  ->where(
1725  $queryBuilder->expr()->eq('is_default', $queryBuilder->createNamedParameter(1, \PDO::PARAM_INT))
1726  )
1727  ->setMaxResults(1)
1728  ->execute()
1729  ->fetch(\PDO::FETCH_ASSOC);
1730 
1731  $readOnlyMountPointArray = ‪GeneralUtility::trimExplode(',', $readOnlyMountPoints);
1732  foreach ($readOnlyMountPointArray as $readOnlyMountPoint) {
1733  $readOnlyMountPointConfiguration = ‪GeneralUtility::trimExplode(':', $readOnlyMountPoint);
1734  if (count($readOnlyMountPointConfiguration) === 2) {
1735  // A storage is passed in the configuration
1736  $storageUid = (int)$readOnlyMountPointConfiguration[0];
1737  $path = $readOnlyMountPointConfiguration[1];
1738  } else {
1739  if (empty($defaultStorageRow)) {
1740  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);
1741  }
1742  // Backwards compatibility: If no storage is passed, we use the default storage
1743  $storageUid = $defaultStorageRow['uid'];
1744  $path = $readOnlyMountPointConfiguration[0];
1745  }
1746  $fileMountRecordCache[$storageUid . $path] = [
1747  'base' => $storageUid,
1748  'title' => $path,
1749  'path' => $path,
1750  'read_only' => true
1751  ];
1752  }
1753  }
1754 
1755  // Personal or Group filemounts are not accessible if file mount list is set in workspace record
1756  if ($this->workspace <= 0 || empty($this->workspaceRec['file_mountpoints'])) {
1757  // If userHomePath is set, we attempt to mount it
1758  if (‪$GLOBALS['TYPO3_CONF_VARS']['BE']['userHomePath']) {
1759  [$userHomeStorageUid, $userHomeFilter] = explode(':', ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['userHomePath'], 2);
1760  $userHomeStorageUid = (int)$userHomeStorageUid;
1761  $userHomeFilter = '/' . ltrim($userHomeFilter, '/');
1762  if ($userHomeStorageUid > 0) {
1763  // Try and mount with [uid]_[username]
1764  $path = $userHomeFilter . $this->user['uid'] . '_' . $this->user['username'] . ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['userUploadDir'];
1765  $fileMountRecordCache[$userHomeStorageUid . $path] = [
1766  'base' => $userHomeStorageUid,
1767  'title' => $this->user['username'],
1768  'path' => $path,
1769  'read_only' => false,
1770  'user_mount' => true
1771  ];
1772  // Try and mount with only [uid]
1773  $path = $userHomeFilter . $this->user['uid'] . ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['userUploadDir'];
1774  $fileMountRecordCache[$userHomeStorageUid . $path] = [
1775  'base' => $userHomeStorageUid,
1776  'title' => $this->user['username'],
1777  'path' => $path,
1778  'read_only' => false,
1779  'user_mount' => true
1780  ];
1781  }
1782  }
1783 
1784  // Mount group home-dirs
1785  if ((is_array($this->user) && $this->user['options'] & ‪Permission::PAGE_EDIT) == 2 && ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['groupHomePath'] != '') {
1786  // If groupHomePath is set, we attempt to mount it
1787  [$groupHomeStorageUid, $groupHomeFilter] = explode(':', ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['groupHomePath'], 2);
1788  $groupHomeStorageUid = (int)$groupHomeStorageUid;
1789  $groupHomeFilter = '/' . ltrim($groupHomeFilter, '/');
1790  if ($groupHomeStorageUid > 0) {
1791  foreach ($this->userGroups as ‪$groupData) {
1792  $path = $groupHomeFilter . ‪$groupData['uid'];
1793  $fileMountRecordCache[$groupHomeStorageUid . $path] = [
1794  'base' => $groupHomeStorageUid,
1795  'title' => ‪$groupData['title'],
1796  'path' => $path,
1797  'read_only' => false,
1798  'user_mount' => true
1799  ];
1800  }
1801  }
1802  }
1803  }
1804 
1805  $runtimeCache->set('backendUserAuthenticationFileMountRecords', $fileMountRecordCache);
1806  return $fileMountRecordCache;
1807  }
1808 
1816  public function ‪getFileStorages()
1817  {
1818  // Initializing file mounts after the groups are fetched
1819  if ($this->fileStorages === null) {
1820  $this->‪initializeFileStorages();
1821  }
1822  return ‪$this->fileStorages;
1823  }
1824 
1831  {
1832  // Add the option for also displaying the non-hidden files
1833  if ($this->uc['showHiddenFilesAndFolders']) {
1835  }
1836  }
1837 
1873  public function ‪getFilePermissions()
1874  {
1875  if (!isset($this->filePermissions)) {
1877  // File permissions
1878  'addFile' => false,
1879  'readFile' => false,
1880  'writeFile' => false,
1881  'copyFile' => false,
1882  'moveFile' => false,
1883  'renameFile' => false,
1884  'deleteFile' => false,
1885  // Folder permissions
1886  'addFolder' => false,
1887  'readFolder' => false,
1888  'writeFolder' => false,
1889  'copyFolder' => false,
1890  'moveFolder' => false,
1891  'renameFolder' => false,
1892  'deleteFolder' => false,
1893  'recursivedeleteFolder' => false
1894  ];
1895  if ($this->‪isAdmin()) {
1896  ‪$filePermissions = array_map('is_bool', ‪$filePermissions);
1897  } else {
1898  $userGroupRecordPermissions = ‪GeneralUtility::trimExplode(',', $this->groupData['file_permissions'] ?? '', true);
1899  array_walk(
1900  $userGroupRecordPermissions,
1901  function ($permission) use (&‪$filePermissions) {
1902  ‪$filePermissions[$permission] = true;
1903  }
1904  );
1905 
1906  // Finally overlay any userTSconfig
1907  $permissionsTsConfig = $this->‪getTSConfig()['permissions.']['file.']['default.'] ?? [];
1908  if (!empty($permissionsTsConfig)) {
1909  array_walk(
1910  $permissionsTsConfig,
1911  function ($value, $permission) use (&‪$filePermissions) {
1912  ‪$filePermissions[$permission] = (bool)$value;
1913  }
1914  );
1915  }
1916  }
1917  $this->filePermissions = ‪$filePermissions;
1918  }
1920  }
1921 
1931  public function ‪getFilePermissionsForStorage(ResourceStorage $storageObject)
1932  {
1933  $finalUserPermissions = $this->‪getFilePermissions();
1934  if (!$this->‪isAdmin()) {
1935  $storageFilePermissions = $this->‪getTSConfig()['permissions.']['file.']['storage.'][$storageObject->getUid() . '.'] ?? [];
1936  if (!empty($storageFilePermissions)) {
1937  array_walk(
1938  $storageFilePermissions,
1939  function ($value, $permission) use (&$finalUserPermissions) {
1940  $finalUserPermissions[$permission] = (bool)$value;
1941  }
1942  );
1943  }
1944  }
1945  return $finalUserPermissions;
1946  }
1947 
1965  public function ‪getDefaultUploadFolder($pid = null, $table = null, $field = null)
1966  {
1967  $uploadFolder = $this->‪getTSConfig()['options.']['defaultUploadFolder'] ?? '';
1968  if ($uploadFolder) {
1969  try {
1970  $uploadFolder = GeneralUtility::makeInstance(ResourceFactory::class)->getFolderObjectFromCombinedIdentifier($uploadFolder);
1971  } catch (Exception\FolderDoesNotExistException $e) {
1972  $uploadFolder = null;
1973  }
1974  }
1975  if (empty($uploadFolder)) {
1976  foreach ($this->‪getFileStorages() as $storage) {
1977  if ($storage->isDefault() && $storage->isWritable()) {
1978  try {
1979  $uploadFolder = $storage->getDefaultFolder();
1980  if ($uploadFolder->checkActionPermission('write')) {
1981  break;
1982  }
1983  $uploadFolder = null;
1984  } catch (Exception $folderAccessException) {
1985  // If the folder is not accessible (no permissions / does not exist) we skip this one.
1986  }
1987  break;
1988  }
1989  }
1990  if (!$uploadFolder instanceof Folder) {
1992  foreach ($this->‪getFileStorages() as $storage) {
1993  if ($storage->isWritable()) {
1994  try {
1995  $uploadFolder = $storage->getDefaultFolder();
1996  if ($uploadFolder->checkActionPermission('write')) {
1997  break;
1998  }
1999  $uploadFolder = null;
2000  } catch (Exception $folderAccessException) {
2001  // If the folder is not accessible (no permissions / does not exist) try the next one.
2002  }
2003  }
2004  }
2005  }
2006  }
2007 
2008  // HOOK: getDefaultUploadFolder
2009  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauthgroup.php']['getDefaultUploadFolder'] ?? [] as $_funcRef) {
2010  $_params = [
2011  'uploadFolder' => $uploadFolder,
2012  'pid' => $pid,
2013  'table' => $table,
2014  'field' => $field,
2015  ];
2016  $uploadFolder = GeneralUtility::callUserFunction($_funcRef, $_params, $this);
2017  }
2018 
2019  if ($uploadFolder instanceof Folder) {
2020  return $uploadFolder;
2021  }
2022  return false;
2023  }
2024 
2033  public function ‪getDefaultUploadTemporaryFolder()
2034  {
2035  $defaultTemporaryFolder = null;
2036  $defaultFolder = $this->‪getDefaultUploadFolder();
2037 
2038  if ($defaultFolder !== false) {
2039  $tempFolderName = '_temp_';
2040  $createFolder = !$defaultFolder->hasFolder($tempFolderName);
2041  if ($createFolder === true) {
2042  try {
2043  $defaultTemporaryFolder = $defaultFolder->createFolder($tempFolderName);
2044  } catch (‪Exception $folderAccessException) {
2045  }
2046  } else {
2047  $defaultTemporaryFolder = $defaultFolder->getSubfolder($tempFolderName);
2048  }
2049  }
2050 
2051  return $defaultTemporaryFolder;
2052  }
2053 
2061  public function ‪workspaceInit()
2062  {
2063  // Initializing workspace by evaluating and setting the workspace, possibly updating it in the user record!
2064  $this->‪setWorkspace($this->user['workspace_id']);
2065  // Limiting the DB mountpoints if there any selected in the workspace record
2067  $allowed_languages = $this->‪getTSConfig()['options.']['workspaces.']['allowed_languages.'][‪$this->workspace] ?? '';
2068  if (!empty($allowed_languages)) {
2069  $this->groupData['allowed_languages'] = GeneralUtility::uniqueList($allowed_languages);
2070  }
2071  }
2072 
2076  protected function ‪initializeDbMountpointsInWorkspace()
2077  {
2078  $dbMountpoints = trim($this->workspaceRec['db_mountpoints'] ?? '');
2079  if ($this->workspace > 0 && $dbMountpoints != '') {
2080  $filteredDbMountpoints = [];
2081  // Notice: We cannot call $this->getPagePermsClause(1);
2082  // as usual because the group-list is not available at this point.
2083  // But bypassing is fine because all we want here is check if the
2084  // workspace mounts are inside the current webmounts rootline.
2085  // The actual permission checking on page level is done elsewhere
2086  // as usual anyway before the page tree is rendered.
2087  $readPerms = '1=1';
2088  // Traverse mount points of the workspace, add them,
2089  // but make sure they match against the users' DB mounts
2090 
2091  $workspaceWebMounts = ‪GeneralUtility::intExplode(',', $dbMountpoints);
2092  $webMountsOfUser = ‪GeneralUtility::intExplode(',', $this->dataLists['webmount_list']);
2093  $webMountsOfUser = array_combine($webMountsOfUser, $webMountsOfUser);
2094 
2095  $entryPointRootLineUids = [];
2096  foreach ($webMountsOfUser as $webMountPageId) {
2097  $rootLine = ‪BackendUtility::BEgetRootLine($webMountPageId, '', true);
2098  $entryPointRootLineUids[$webMountPageId] = array_map('intval', array_column($rootLine, 'uid'));
2099  }
2100  foreach ($entryPointRootLineUids as $webMountOfUser => $uidsOfRootLine) {
2101  // Remove the DB mounts of the user if the DB mount is not in the list of
2102  // workspace mounts
2103  foreach ($workspaceWebMounts as $webmountOfWorkspace) {
2104  // This workspace DB mount is somewhere in the rootline of the users' web mount,
2105  // so this is "OK" to be included
2106  if (in_array($webmountOfWorkspace, $uidsOfRootLine, true)) {
2107  continue;
2108  }
2109  // Remove the user's DB Mount (possible via array_combine, see above)
2110  unset($webMountsOfUser[$webMountOfUser]);
2111  }
2112  }
2113  $dbMountpoints = array_merge($workspaceWebMounts, $webMountsOfUser);
2114  $dbMountpoints = array_unique($dbMountpoints);
2115  foreach ($dbMountpoints as $mpId) {
2116  if ($this->‪isInWebMount($mpId, $readPerms)) {
2117  $filteredDbMountpoints[] = $mpId;
2118  }
2119  }
2120  // Re-insert webmounts
2121  $this->groupData['webmounts'] = implode(',', $filteredDbMountpoints);
2122  }
2123  }
2124 
2133  public function ‪checkWorkspace($wsRec, ‪$fields = '*')
2134  {
2135  $retVal = false;
2136  // If not array, look up workspace record:
2137  if (!is_array($wsRec)) {
2138  switch ((string)$wsRec) {
2139  case '0':
2140  $wsRec = ['uid' => $wsRec];
2141  break;
2142  default:
2143  if (‪ExtensionManagementUtility::isLoaded('workspaces')) {
2144  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_workspace');
2145  $queryBuilder->getRestrictions()->add(GeneralUtility::makeInstance(RootLevelRestriction::class));
2146  $wsRec = $queryBuilder->select(...‪GeneralUtility::trimExplode(',', ‪$fields))
2147  ->from('sys_workspace')
2148  ->where($queryBuilder->expr()->eq(
2149  'uid',
2150  $queryBuilder->createNamedParameter($wsRec, \PDO::PARAM_INT)
2151  ))
2152  ->orderBy('title')
2153  ->setMaxResults(1)
2154  ->execute()
2155  ->fetch(\PDO::FETCH_ASSOC);
2156  }
2157  }
2158  }
2159  // If wsRec is set to an array, evaluate it:
2160  if (is_array($wsRec)) {
2161  if ($this->‪isAdmin()) {
2162  return array_merge($wsRec, ['_ACCESS' => 'admin']);
2163  }
2164  switch ((string)$wsRec['uid']) {
2165  case '0':
2166  $retVal = $this->groupData['workspace_perms'] & ‪Permission::PAGE_SHOW
2167  ? array_merge($wsRec, ['_ACCESS' => 'online'])
2168  : false;
2169  break;
2170  default:
2171  // Checking if the guy is admin:
2172  if (GeneralUtility::inList($wsRec['adminusers'], 'be_users_' . $this->user['uid'])) {
2173  return array_merge($wsRec, ['_ACCESS' => 'owner']);
2174  }
2175  // Checking if he is owner through a user group of his:
2176  foreach ($this->userGroupsUID as $groupUid) {
2177  if (GeneralUtility::inList($wsRec['adminusers'], 'be_groups_' . $groupUid)) {
2178  return array_merge($wsRec, ['_ACCESS' => 'owner']);
2179  }
2180  }
2181  // Checking if he is member as user:
2182  if (GeneralUtility::inList($wsRec['members'], 'be_users_' . $this->user['uid'])) {
2183  return array_merge($wsRec, ['_ACCESS' => 'member']);
2184  }
2185  // Checking if he is member through a user group of his:
2186  foreach ($this->userGroupsUID as $groupUid) {
2187  if (GeneralUtility::inList($wsRec['members'], 'be_groups_' . $groupUid)) {
2188  return array_merge($wsRec, ['_ACCESS' => 'member']);
2189  }
2190  }
2191  }
2192  }
2193  return $retVal;
2194  }
2195 
2204  public function ‪checkWorkspaceCurrent()
2205  {
2206  if (!isset($this->checkWorkspaceCurrent_cache)) {
2207  $this->checkWorkspaceCurrent_cache = $this->‪checkWorkspace($this->workspace);
2208  }
2210  }
2211 
2218  public function ‪setWorkspace($workspaceId)
2219  {
2220  // Check workspace validity and if not found, revert to default workspace.
2221  if (!$this->‪setTemporaryWorkspace($workspaceId)) {
2222  $this->‪setDefaultWorkspace();
2223  }
2224  // Unset access cache:
2225  $this->checkWorkspaceCurrent_cache = null;
2226  // If ID is different from the stored one, change it:
2227  if ((int)$this->workspace !== (int)$this->user['workspace_id']) {
2228  $this->user['workspace_id'] = ‪$this->workspace;
2229  GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('be_users')->update(
2230  'be_users',
2231  ['workspace_id' => $this->user['workspace_id']],
2232  ['uid' => (int)$this->user['uid']]
2233  );
2234  $this->‪writelog(SystemLogType::EXTENSION, SystemLogGenericAction::UNDEFINED, SystemLogErrorClassification::MESSAGE, 0, 'User changed workspace to "' . $this->workspace . '"', []);
2235  }
2236  }
2237 
2245  public function ‪setTemporaryWorkspace($workspaceId)
2246  {
2247  $result = false;
2248  $workspaceRecord = $this->‪checkWorkspace($workspaceId);
2249 
2250  if ($workspaceRecord) {
2251  $this->workspaceRec = $workspaceRecord;
2252  $this->workspace = (int)$workspaceId;
2253  $result = true;
2254  }
2255 
2256  return $result;
2257  }
2258 
2263  public function ‪setDefaultWorkspace()
2264  {
2265  $this->workspace = (int)$this->‪getDefaultWorkspace();
2266  $this->workspaceRec = $this->‪checkWorkspace($this->workspace);
2267  }
2268 
2277  public function ‪getDefaultWorkspace()
2278  {
2279  if (!‪ExtensionManagementUtility::isLoaded('workspaces')) {
2280  return 0;
2281  }
2282  // Online is default
2283  if ($this->‪checkWorkspace(0)) {
2284  return 0;
2285  }
2286  // Otherwise -99 is the fallback
2287  $defaultWorkspace = -99;
2288  // Traverse all workspaces
2289  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_workspace');
2290  $queryBuilder->getRestrictions()->add(GeneralUtility::makeInstance(RootLevelRestriction::class));
2291  $result = $queryBuilder->select('*')
2292  ->from('sys_workspace')
2293  ->orderBy('title')
2294  ->execute();
2295  while ($workspaceRecord = $result->fetch()) {
2296  if ($this->‪checkWorkspace($workspaceRecord)) {
2297  $defaultWorkspace = (int)$workspaceRecord['uid'];
2298  break;
2299  }
2300  }
2301  return $defaultWorkspace;
2302  }
2303 
2322  public function ‪writelog($type, $action, $error, $details_nr, $details, $data, $tablename = '', $recuid = '', $recpid = '', $event_pid = -1, $NEWid = '', $userId = 0)
2323  {
2324  if (!$userId && !empty($this->user['uid'])) {
2325  $userId = $this->user['uid'];
2326  }
2327 
2328  if (!empty($this->user['ses_backuserid'])) {
2329  if (empty($data)) {
2330  $data = [];
2331  }
2332  $data['originalUser'] = $this->user['ses_backuserid'];
2333  }
2334 
2335  ‪$fields = [
2336  'userid' => (int)$userId,
2337  'type' => (int)$type,
2338  'action' => (int)$action,
2339  'error' => (int)$error,
2340  'details_nr' => (int)$details_nr,
2341  'details' => $details,
2342  'log_data' => serialize($data),
2343  'tablename' => $tablename,
2344  'recuid' => (int)$recuid,
2345  'IP' => (string)GeneralUtility::getIndpEnv('REMOTE_ADDR'),
2346  'tstamp' => ‪$GLOBALS['EXEC_TIME'] ?? time(),
2347  'event_pid' => (int)$event_pid,
2348  'NEWid' => $NEWid,
2349  'workspace' => $this->workspace
2350  ];
2351 
2352  $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('sys_log');
2353  $connection->insert(
2354  'sys_log',
2355  ‪$fields,
2356  [
2357  \PDO::PARAM_INT,
2358  \PDO::PARAM_INT,
2359  \PDO::PARAM_INT,
2360  \PDO::PARAM_INT,
2361  \PDO::PARAM_INT,
2362  \PDO::PARAM_STR,
2363  \PDO::PARAM_STR,
2364  \PDO::PARAM_STR,
2365  \PDO::PARAM_INT,
2366  \PDO::PARAM_STR,
2367  \PDO::PARAM_INT,
2368  \PDO::PARAM_INT,
2369  \PDO::PARAM_STR,
2370  \PDO::PARAM_STR,
2371  ]
2372  );
2373 
2374  return (int)$connection->lastInsertId('sys_log');
2375  }
2376 
2388  public function ‪checkLogFailures($email, $secondsBack = 3600, $max = 3)
2389  {
2390  if (!GeneralUtility::validEmail($email)) {
2391  return;
2392  }
2393  $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
2394 
2395  // Get last flag set in the log for sending
2396  $theTimeBack = ‪$GLOBALS['EXEC_TIME'] - $secondsBack;
2397  $queryBuilder = $connectionPool->getQueryBuilderForTable('sys_log');
2398  $queryBuilder->select('tstamp')
2399  ->from('sys_log')
2400  ->where(
2401  $queryBuilder->expr()->eq(
2402  'type',
2403  $queryBuilder->createNamedParameter(SystemLogType::LOGIN, \PDO::PARAM_INT)
2404  ),
2405  $queryBuilder->expr()->eq(
2406  'action',
2407  $queryBuilder->createNamedParameter(SystemLogLoginAction::SEND_FAILURE_WARNING_EMAIL, \PDO::PARAM_INT)
2408  ),
2409  $queryBuilder->expr()->gt(
2410  'tstamp',
2411  $queryBuilder->createNamedParameter($theTimeBack, \PDO::PARAM_INT)
2412  )
2413  )
2414  ->orderBy('tstamp', 'DESC')
2415  ->setMaxResults(1);
2416  if ($testRow = $queryBuilder->execute()->fetch(\PDO::FETCH_ASSOC)) {
2417  $theTimeBack = $testRow['tstamp'];
2418  }
2419 
2420  $queryBuilder = $connectionPool->getQueryBuilderForTable('sys_log');
2421  $rowCount = $queryBuilder->count('uid')
2422  ->from('sys_log')
2423  ->where(
2424  $queryBuilder->expr()->eq(
2425  'type',
2426  $queryBuilder->createNamedParameter(SystemLogType::LOGIN, \PDO::PARAM_INT)
2427  ),
2428  $queryBuilder->expr()->eq(
2429  'action',
2430  $queryBuilder->createNamedParameter(SystemLogLoginAction::ATTEMPT, \PDO::PARAM_INT)
2431  ),
2432  $queryBuilder->expr()->neq(
2433  'error',
2434  $queryBuilder->createNamedParameter(SystemLogErrorClassification::MESSAGE, \PDO::PARAM_INT)
2435  ),
2436  $queryBuilder->expr()->gt(
2437  'tstamp',
2438  $queryBuilder->createNamedParameter($theTimeBack, \PDO::PARAM_INT)
2439  )
2440  )
2441  ->execute()
2442  ->fetchColumn(0);
2443 
2444  // Check for more than $max number of error failures with the last period.
2445  if ($rowCount > $max) {
2446  $result = $queryBuilder
2447  ->select('*')
2448  ->orderBy('tstamp')
2449  ->execute();
2450 
2451  // OK, so there were more than the max allowed number of login failures - so we will send an email then.
2452  $this->‪sendLoginAttemptEmail($result, $email);
2453  // Login failure attempt written to log
2454  $this->‪writelog(SystemLogType::LOGIN, SystemLogLoginAction::SEND_FAILURE_WARNING_EMAIL, SystemLogErrorClassification::MESSAGE, 3, 'Failure warning (%s failures within %s seconds) sent by email to %s', [$rowCount, $secondsBack, $email]);
2455  }
2456  }
2457 
2464  protected function ‪sendLoginAttemptEmail(Statement $result, string $emailAddress): void
2465  {
2466  $emailData = [];
2467  while ($row = $result->fetch(\PDO::FETCH_ASSOC)) {
2468  $theData = unserialize($row['log_data'], ['allowed_classes' => false]);
2469  $text = @sprintf($row['details'], (string)$theData[0], (string)$theData[1], (string)$theData[2]);
2470  if ((int)$row['type'] === SystemLogType::LOGIN) {
2471  $text = str_replace('###IP###', $row['IP'], $text);
2472  }
2473  $emailData[] = [
2474  'row' => $row,
2475  'text' => $text
2476  ];
2477  }
2478  $email = GeneralUtility::makeInstance(FluidEmail::class)
2479  ->to($emailAddress)
2480  ->setTemplate('Security/LoginAttemptFailedWarning')
2481  ->assign('lines', $emailData);
2482  if (‪$GLOBALS['TYPO3_REQUEST'] instanceof ServerRequestInterface) {
2483  $email->setRequest(‪$GLOBALS['TYPO3_REQUEST']);
2484  }
2485  GeneralUtility::makeInstance(Mailer::class)->send($email);
2486  }
2487 
2494  public static function ‪getCookieName()
2495  {
2496  $configuredCookieName = trim(‪$GLOBALS['TYPO3_CONF_VARS']['BE']['cookieName']);
2497  if (empty($configuredCookieName)) {
2498  $configuredCookieName = 'be_typo_user';
2499  }
2500  return $configuredCookieName;
2501  }
2502 
2511  public function ‪checkLockToIP()
2512  {
2513  $isValid = true;
2514  if (‪$GLOBALS['TYPO3_CONF_VARS']['BE']['enabledBeUserIPLock']) {
2515  $IPList = trim($this->‪getTSConfig()['options.']['lockToIP'] ?? '');
2516  if (!empty($IPList)) {
2517  $isValid = GeneralUtility::cmpIP(GeneralUtility::getIndpEnv('REMOTE_ADDR'), $IPList);
2518  }
2519  }
2520  return $isValid;
2521  }
2522 
2532  public function ‪backendCheckLogin($proceedIfNoUserIsLoggedIn = false)
2533  {
2534  if (empty($this->user['uid'])) {
2535  if ($proceedIfNoUserIsLoggedIn === false) {
2536  $url = GeneralUtility::getIndpEnv('TYPO3_SITE_URL') . TYPO3_mainDir;
2538  }
2539  } else {
2540  // ...and if that's the case, call these functions
2541  $this->‪fetchGroupData();
2542  // The groups are fetched and ready for permission checking in this initialization.
2543  // Tables.php must be read before this because stuff like the modules has impact in this
2544  if ($this->‪checkLockToIP()) {
2545  if ($this->‪isUserAllowedToLogin()) {
2546  // Setting the UC array. It's needed with fetchGroupData first, due to default/overriding of values.
2548  if ($this->loginSessionStarted) {
2549  // Also, if there is a recovery link set, unset it now
2550  // this will be moved into its own Event at a later stage.
2551  // If a token was set previously, this is now unset, as it was now possible to log-in
2552  if ($this->user['password_reset_token'] ?? '') {
2553  GeneralUtility::makeInstance(ConnectionPool::class)
2554  ->getConnectionForTable($this->user_table)
2555  ->update($this->user_table, ['password_reset_token' => ''], ['uid' => $this->user['uid']]);
2556  }
2557  // Process hooks
2558  $hooks = ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauthgroup.php']['backendUserLogin'];
2559  foreach ($hooks ?? [] as $_funcRef) {
2560  $_params = ['user' => ‪$this->user];
2561  GeneralUtility::callUserFunction($_funcRef, $_params, $this);
2562  }
2563  }
2564  } else {
2565  throw new \RuntimeException('Login Error: TYPO3 is in maintenance mode at the moment. Only administrators are allowed access.', 1294585860);
2566  }
2567  } else {
2568  throw new \RuntimeException('Login Error: IP locking prevented you from being authorized. Can\'t proceed, sorry.', 1294585861);
2569  }
2570  }
2571  }
2572 
2579  public function ‪backendSetUC()
2580  {
2581  // UC - user configuration is a serialized array inside the user object
2582  // If there is a saved uc we implement that instead of the default one.
2583  $this->‪unpack_uc();
2584  // Setting defaults if uc is empty
2585  $updated = false;
2586  $originalUc = [];
2587  if (is_array($this->uc) && isset($this->uc['ucSetByInstallTool'])) {
2588  $originalUc = ‪$this->uc;
2589  unset($originalUc['ucSetByInstallTool'], $this->uc);
2590  }
2591  if (!is_array($this->uc)) {
2592  $this->uc = array_merge(
2593  $this->uc_default,
2594  (array)‪$GLOBALS['TYPO3_CONF_VARS']['BE']['defaultUC'],
2595  GeneralUtility::removeDotsFromTS((array)($this->‪getTSConfig()['setup.']['default.'] ?? [])),
2596  $originalUc
2597  );
2598  $this->‪overrideUC();
2599  $updated = true;
2600  }
2601  // If TSconfig is updated, update the defaultUC.
2602  if ($this->userTSUpdated) {
2603  $this->‪overrideUC();
2604  $updated = true;
2605  }
2606  // Setting default lang from be_user record.
2607  if (!isset($this->uc['lang'])) {
2608  $this->uc['lang'] = $this->user['lang'];
2609  $updated = true;
2610  }
2611  // Setting the time of the first login:
2612  if (!isset($this->uc['firstLoginTimeStamp'])) {
2613  $this->uc['firstLoginTimeStamp'] = ‪$GLOBALS['EXEC_TIME'];
2614  $updated = true;
2615  }
2616  // Saving if updated.
2617  if ($updated) {
2618  $this->‪writeUC();
2619  }
2620  }
2621 
2628  public function ‪overrideUC()
2629  {
2630  $this->uc = array_merge((array)$this->uc, (array)($this->‪getTSConfig()['setup.']['override.'] ?? []));
2631  }
2632 
2638  public function ‪resetUC()
2639  {
2640  $this->user['uc'] = '';
2641  $this->uc = '';
2642  $this->‪backendSetUC();
2643  }
2644 
2656  protected function ‪isUserAllowedToLogin()
2657  {
2658  $isUserAllowedToLogin = false;
2659  $adminOnlyMode = (int)‪$GLOBALS['TYPO3_CONF_VARS']['BE']['adminOnly'];
2660  // Backend user is allowed if adminOnly is not set or user is an admin:
2661  if (!$adminOnlyMode || $this->‪isAdmin()) {
2662  $isUserAllowedToLogin = true;
2663  } elseif ($this->user['ses_backuserid']) {
2664  $backendUserId = (int)$this->user['ses_backuserid'];
2665  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('be_users');
2666  $isUserAllowedToLogin = (bool)$queryBuilder->count('uid')
2667  ->from('be_users')
2668  ->where(
2669  $queryBuilder->expr()->eq(
2670  'uid',
2671  $queryBuilder->createNamedParameter($backendUserId, \PDO::PARAM_INT)
2672  ),
2673  $queryBuilder->expr()->eq('admin', $queryBuilder->createNamedParameter(1, \PDO::PARAM_INT))
2674  )
2675  ->execute()
2676  ->fetchColumn(0);
2677  }
2678  return $isUserAllowedToLogin;
2679  }
2680 
2684  public function ‪logoff()
2685  {
2686  if (isset(‪$GLOBALS['BE_USER'])
2687  && ‪$GLOBALS['BE_USER'] instanceof self
2688  && isset(‪$GLOBALS['BE_USER']->user['uid'])
2689  ) {
2691  // Release the locked records
2692  $this->‪releaseLockedRecords((int)$GLOBALS['BE_USER']->user['uid']);
2693 
2694  if ($this->‪isSystemMaintainer()) {
2695  // If user is system maintainer, destroy its possibly valid install tool session.
2696  $session = new SessionService();
2697  $session->destroySession();
2698  }
2699  }
2700  parent::logoff();
2701  }
2702 
2707  protected function ‪releaseLockedRecords(int $userId)
2708  {
2709  if ($userId > 0) {
2710  GeneralUtility::makeInstance(ConnectionPool::class)
2711  ->getConnectionForTable('sys_lockedrecords')
2712  ->delete(
2713  'sys_lockedrecords',
2714  ['userid' => $userId]
2715  );
2716  }
2717  }
2718 
2724  public function ‪isImportEnabled(): bool
2725  {
2726  return $this->‪isAdmin()
2727  || ($this->‪getTSConfig()['options.']['impexp.']['enableImportForNonAdminUser'] ?? false);
2728  }
2729 
2735  public function ‪isExportEnabled(): bool
2736  {
2737  return $this->‪isAdmin()
2738  || ($this->‪getTSConfig()['options.']['impexp.']['enableExportForNonAdminUser'] ?? false);
2739  }
2740 }
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\backendCheckLogin
‪backendCheckLogin($proceedIfNoUserIsLoggedIn=false)
Definition: BackendUserAuthentication.php:2500
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\returnWebmounts
‪array returnWebmounts()
Definition: BackendUserAuthentication.php:1229
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\evaluateUserSpecificFileFilterSettings
‪evaluateUserSpecificFileFilterSettings()
Definition: BackendUserAuthentication.php:1798
‪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\workspacePublishAccess
‪bool workspacePublishAccess($wsid)
Definition: BackendUserAuthentication.php:1159
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\recordEditAccessInternals
‪bool recordEditAccessInternals($table, $idOrRow, $newRecord=false, $deletedRecord=false, $checkFullLanguageAccess=false)
Definition: BackendUserAuthentication.php:779
‪TYPO3\CMS\Core\FormProtection\FormProtectionFactory\get
‪static TYPO3 CMS Core FormProtection AbstractFormProtection get($classNameOrType='default',... $constructorArguments)
Definition: FormProtectionFactory.php:74
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$usergroup_table
‪string $usergroup_table
Definition: BackendUserAuthentication.php:73
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder
Definition: ExpressionBuilder.php:35
‪TYPO3\CMS\Backend\Utility\BackendUtility\isModuleSetInTBE_MODULES
‪static bool isModuleSetInTBE_MODULES($modName)
Definition: BackendUtility.php:3287
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\workspaceCreateNewRecord
‪bool workspaceCreateNewRecord($pid, $table)
Definition: BackendUserAuthentication.php:1027
‪TYPO3\CMS\Core\Resource\ResourceStorage\getUid
‪int getUid()
Definition: ResourceStorage.php:321
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\setWebmounts
‪setWebmounts(array $mountPointUids, $append=false)
Definition: BackendUserAuthentication.php:1240
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\EQ
‪const EQ
Definition: ExpressionBuilder.php:36
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\writeUC
‪writeUC($variable='')
Definition: AbstractUserAuthentication.php:1120
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\unpack_uc
‪unpack_uc($theUC='')
Definition: AbstractUserAuthentication.php:1142
‪TYPO3\CMS\Core\SysLog\Action
Definition: Cache.php:18
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$formfield_status
‪string $formfield_status
Definition: BackendUserAuthentication.php:213
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getPagePermsClause
‪string getPagePermsClause($perms)
Definition: BackendUserAuthentication.php:499
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\workspaceSwapAccess
‪bool workspaceSwapAccess()
Definition: BackendUserAuthentication.php:1189
‪TYPO3\CMS\Core\Exception
Definition: Exception.php:22
‪TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser
Definition: TypoScriptParser.php:37
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\initializeDbMountpointsInWorkspace
‪initializeDbMountpointsInWorkspace()
Definition: BackendUserAuthentication.php:2044
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\initializeFileStorages
‪initializeFileStorages()
Definition: BackendUserAuthentication.php:1569
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$formfield_uname
‪string $formfield_uname
Definition: BackendUserAuthentication.php:203
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\calcPerms
‪int calcPerms($row)
Definition: BackendUserAuthentication.php:568
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\setCachedList
‪setCachedList($cList)
Definition: BackendUserAuthentication.php:1554
‪TYPO3\CMS\Core\Authentication
Definition: AbstractAuthenticationService.php:16
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\prepareUserTsConfig
‪prepareUserTsConfig()
Definition: BackendUserAuthentication.php:1407
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$usergroup_column
‪string $usergroup_column
Definition: BackendUserAuthentication.php:68
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getTSConfig
‪array getTSConfig()
Definition: BackendUserAuthentication.php:1217
‪TYPO3\CMS\Backend\Configuration\TypoScript\ConditionMatching\ConditionMatcher
Definition: ConditionMatcher.php:30
‪TYPO3\CMS\Core\Type\Bitmask\Permission\NOTHING
‪const NOTHING
Definition: Permission.php:28
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$firstMainGroup
‪int $firstMainGroup
Definition: BackendUserAuthentication.php:239
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$userGroups
‪array $userGroups
Definition: BackendUserAuthentication.php:86
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\isAdmin
‪bool isAdmin()
Definition: BackendUserAuthentication.php:292
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$uc_default
‪array $uc_default
Definition: BackendUserAuthentication.php:255
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$uc
‪array $uc
Definition: BackendUserAuthentication.php:244
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\check
‪bool check($type, $value)
Definition: BackendUserAuthentication.php:624
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\isSystemMaintainer
‪bool isSystemMaintainer()
Definition: BackendUserAuthentication.php:456
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\fetchGroupData
‪fetchGroupData()
Definition: BackendUserAuthentication.php:1309
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\fetchGroups
‪fetchGroups($grList, $idList='')
Definition: BackendUserAuthentication.php:1453
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\workspaceAllowLiveRecordsInPID
‪mixed workspaceAllowLiveRecordsInPID($pid, $table)
Definition: BackendUserAuthentication.php:973
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getDefaultUploadTemporaryFolder
‪TYPO3 CMS Core Resource Folder null getDefaultUploadTemporaryFolder()
Definition: BackendUserAuthentication.php:2001
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\setDefaultWorkspace
‪setDefaultWorkspace()
Definition: BackendUserAuthentication.php:2231
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\workspaceCanCreateNewRecord
‪bool workspaceCanCreateNewRecord(string $table)
Definition: BackendUserAuthentication.php:1046
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\isMemberOfGroup
‪bool isMemberOfGroup($groupId)
Definition: BackendUserAuthentication.php:306
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\$id
‪string $id
Definition: AbstractUserAuthentication.php:215
‪TYPO3\CMS\Backend\Utility\BackendUtility\BEgetRootLine
‪static array BEgetRootLine($uid, $clause='', $workspaceOL=false, array $additionalFields=[])
Definition: BackendUtility.php:343
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\checkAuthMode
‪bool checkAuthMode($table, $field, $value, $authMode)
Definition: BackendUserAuthentication.php:639
‪$fields
‪$fields
Definition: pages.php:5
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$writeAttemptLog
‪bool $writeAttemptLog
Definition: BackendUserAuthentication.php:223
‪TYPO3\CMS\Core\SysLog\Action\Login
Definition: Login.php:24
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$filePermissions
‪array $filePermissions
Definition: BackendUserAuthentication.php:164
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getFileStorages
‪TYPO3 CMS Core Resource ResourceStorage[] getFileStorages()
Definition: BackendUserAuthentication.php:1784
‪TYPO3\CMS\Core\Type\Bitmask\Permission
Definition: Permission.php:24
‪TYPO3\CMS\Core\Core\Environment\getContext
‪static ApplicationContext getContext()
Definition: Environment.php:133
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$formfield_uident
‪string $formfield_uident
Definition: BackendUserAuthentication.php:208
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility
Definition: ExtensionManagementUtility.php:43
‪TYPO3\CMS\Backend\Utility\BackendUtility\isTableWorkspaceEnabled
‪static bool isTableWorkspaceEnabled($table)
Definition: BackendUtility.php:4021
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getCategoryMountPoints
‪array getCategoryMountPoints()
Definition: BackendUserAuthentication.php:1603
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getFilePermissionsForStorage
‪array getFilePermissionsForStorage(ResourceStorage $storageObject)
Definition: BackendUserAuthentication.php:1899
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$includeGroupArray
‪array $includeGroupArray
Definition: BackendUserAuthentication.php:137
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\checkLockToIP
‪bool checkLockToIP()
Definition: BackendUserAuthentication.php:2479
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getCookieName
‪static string getCookieName()
Definition: BackendUserAuthentication.php:2462
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\checkLogFailures
‪checkLogFailures($email, $secondsBack=3600, $max=3)
Definition: BackendUserAuthentication.php:2356
‪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:1636
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\mayMakeShortcut
‪bool mayMakeShortcut()
Definition: BackendUserAuthentication.php:877
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\resetUC
‪resetUC()
Definition: BackendUserAuthentication.php:2606
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$userid_column
‪string $userid_column
Definition: BackendUserAuthentication.php:184
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$user_table
‪string $user_table
Definition: BackendUserAuthentication.php:169
‪TYPO3\CMS\Core\Database\Query\QueryHelper
Definition: QueryHelper.php:32
‪TYPO3\CMS\Core\Mail\FluidEmail
Definition: FluidEmail.php:35
‪TYPO3\CMS\Core\Type\Bitmask\Permission\ALL
‪const ALL
Definition: Permission.php:58
‪TYPO3\CMS\Core\Database\Query\Restriction\RootLevelRestriction
Definition: RootLevelRestriction.php:27
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\setWorkspace
‪setWorkspace($workspaceId)
Definition: BackendUserAuthentication.php:2186
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$userTSUpdated
‪bool $userTSUpdated
Definition: BackendUserAuthentication.php:145
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\backendSetUC
‪backendSetUC()
Definition: BackendUserAuthentication.php:2547
‪TYPO3\CMS\Core\FormProtection\AbstractFormProtection\clean
‪clean()
Definition: AbstractFormProtection.php:64
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\ROLE_SYSTEMMAINTAINER
‪const ROLE_SYSTEMMAINTAINER
Definition: BackendUserAuthentication.php:63
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\isUserAllowedToLogin
‪bool isUserAllowedToLogin()
Definition: BackendUserAuthentication.php:2624
‪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\Resource\StorageRepository
Definition: StorageRepository.php:31
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$groupData
‪array $groupData
Definition: BackendUserAuthentication.php:79
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\doesUserHaveAccess
‪bool doesUserHaveAccess($row, $perms)
Definition: BackendUserAuthentication.php:330
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\workspaceAllowAutoCreation
‪bool workspaceAllowAutoCreation($table, $id, $recpid)
Definition: BackendUserAuthentication.php:1067
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getFilePermissions
‪array getFilePermissions()
Definition: BackendUserAuthentication.php:1841
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$username_column
‪string $username_column
Definition: BackendUserAuthentication.php:174
‪TYPO3\CMS\Core\SysLog\Error
Definition: Error.php:24
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\getSessionData
‪mixed getSessionData($key)
Definition: AbstractUserAuthentication.php:1206
‪TYPO3\CMS\Core\Cache\CacheManager
Definition: CacheManager.php:35
‪TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser\checkIncludeLines_array
‪static array checkIncludeLines_array(array $array)
Definition: TypoScriptParser.php:1190
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\checkLanguageAccess
‪bool checkLanguageAccess($langValue)
Definition: BackendUserAuthentication.php:709
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:62
‪TYPO3\CMS\Core\Type\Bitmask\Permission\PAGE_SHOW
‪const PAGE_SHOW
Definition: Permission.php:33
‪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:1933
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$checkWorkspaceCurrent_cache
‪array null $checkWorkspaceCurrent_cache
Definition: BackendUserAuthentication.php:156
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$userGroupsUID
‪array $userGroupsUID
Definition: BackendUserAuthentication.php:91
‪TYPO3\CMS\Core\Mail\Mailer
Definition: Mailer.php:38
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\sendLoginAttemptEmail
‪sendLoginAttemptEmail(Statement $result, string $emailAddress)
Definition: BackendUserAuthentication.php:2432
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\overrideUC
‪overrideUC()
Definition: BackendUserAuthentication.php:2596
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$enablecolumns
‪array $enablecolumns
Definition: BackendUserAuthentication.php:192
‪TYPO3\CMS\Backend\Utility\BackendUtility
Definition: BackendUtility.php:75
‪TYPO3\CMS\Backend\Utility\BackendUtility\getWorkspaceVersionOfRecord
‪static array bool getWorkspaceVersionOfRecord($workspace, $table, $uid, $fields=' *')
Definition: BackendUtility.php:3705
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$loginType
‪string $loginType
Definition: BackendUserAuthentication.php:273
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\logoff
‪logoff()
Definition: BackendUserAuthentication.php:2652
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecord
‪static array null getRecord($table, $uid, $fields=' *', $where='', $useDeleteClause=true)
Definition: BackendUtility.php:95
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\workspaceCannotEditRecord
‪string workspaceCannotEditRecord($table, $recData)
Definition: BackendUserAuthentication.php:895
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\$user
‪array null $user
Definition: AbstractUserAuthentication.php:230
‪TYPO3\CMS\Core\Utility\GeneralUtility\trimExplode
‪static string[] trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
Definition: GeneralUtility.php:1059
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\__construct
‪__construct()
Definition: BackendUserAuthentication.php:278
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\releaseLockedRecords
‪releaseLockedRecords(int $userId)
Definition: BackendUserAuthentication.php:2675
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:36
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$sessionTimeout
‪int $sessionTimeout
Definition: BackendUserAuthentication.php:234
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$lastLogin_column
‪string $lastLogin_column
Definition: BackendUserAuthentication.php:188
‪TYPO3\CMS\Core\Resource\ResourceStorage
Definition: ResourceStorage.php:122
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\isRTE
‪bool isRTE()
Definition: BackendUserAuthentication.php:610
‪TYPO3\CMS\Core\FormProtection\FormProtectionFactory
Definition: FormProtectionFactory.php:47
‪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:2290
‪TYPO3\CMS\Backend\Utility\BackendUtility\isTableLocalizable
‪static bool isTableLocalizable($table)
Definition: BackendUtility.php:578
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$userTS
‪array $userTS
Definition: BackendUserAuthentication.php:141
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\checkWorkspace
‪array checkWorkspace($wsRec, $fields=' *')
Definition: BackendUserAuthentication.php:2101
‪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:40
‪TYPO3\CMS\Core\Type\Bitmask\Permission\PAGE_EDIT
‪const PAGE_EDIT
Definition: Permission.php:38
‪TYPO3\CMS\Core\Utility\GeneralUtility\intExplode
‪static int[] intExplode($delimiter, $string, $removeEmptyValues=false, $limit=0)
Definition: GeneralUtility.php:988
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\isExportEnabled
‪isExportEnabled()
Definition: BackendUserAuthentication.php:2703
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$workspace
‪int $workspace
Definition: BackendUserAuthentication.php:104
‪TYPO3\CMS\Core\Utility\HttpUtility
Definition: HttpUtility.php:24
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\workspaceInit
‪workspaceInit()
Definition: BackendUserAuthentication.php:2029
‪TYPO3\CMS\Core\Resource\Filter\FileNameFilter
Definition: FileNameFilter.php:24
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\checkWorkspaceCurrent
‪array checkWorkspaceCurrent()
Definition: BackendUserAuthentication.php:2172
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\initializeWebmountsForElementBrowser
‪initializeWebmountsForElementBrowser()
Definition: BackendUserAuthentication.php:1263
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$userident_column
‪string $userident_column
Definition: BackendUserAuthentication.php:179
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\setTemporaryWorkspace
‪bool setTemporaryWorkspace($workspaceId)
Definition: BackendUserAuthentication.php:2213
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$groupList
‪string $groupList
Definition: BackendUserAuthentication.php:96
‪TYPO3\CMS\Core\Utility\HttpUtility\redirect
‪static redirect($url, $httpStatus=self::HTTP_STATUS_303)
Definition: HttpUtility.php:106
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$workspaceRec
‪array $workspaceRec
Definition: BackendUserAuthentication.php:109
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\isLoaded
‪static bool isLoaded($key)
Definition: ExtensionManagementUtility.php:114
‪TYPO3\CMS\Core\Type\Bitmask\JsConfirmation
Definition: JsConfirmation.php:25
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\checkFullLanguagesAccess
‪bool checkFullLanguagesAccess($table, $record)
Definition: BackendUserAuthentication.php:729
‪TYPO3\CMS\Core\Resource\Exception
Definition: AbstractFileOperationException.php:16
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\workspaceCheckStageForCurrent
‪bool workspaceCheckStageForCurrent($stage)
Definition: BackendUserAuthentication.php:1097
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\isImportEnabled
‪isImportEnabled()
Definition: BackendUserAuthentication.php:2692
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$fileStorages
‪TYPO3 CMS Core Resource ResourceStorage[] $fileStorages
Definition: BackendUserAuthentication.php:160
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$writeStdLog
‪bool $writeStdLog
Definition: BackendUserAuthentication.php:218
‪TYPO3\CMS\Core\SysLog\Type
Definition: Type.php:24
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication
Definition: AbstractUserAuthentication.php:51
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getDefaultWorkspace
‪int getDefaultWorkspace()
Definition: BackendUserAuthentication.php:2245
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\jsConfirmation
‪bool jsConfirmation($bitmask)
Definition: BackendUserAuthentication.php:1288
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$dataLists
‪array $dataLists
Definition: BackendUserAuthentication.php:117
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\modAccess
‪bool modAccess($conf)
Definition: BackendUserAuthentication.php:415
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\isInWebMount
‪int null isInWebMount($idOrRow, $readPerms='', $exitOnError=0)
Definition: BackendUserAuthentication.php:352
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\workspaceAllowsLiveEditingInTable
‪bool workspaceAllowsLiveEditingInTable(string $table)
Definition: BackendUserAuthentication.php:998
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\$errorMsg
‪string $errorMsg
Definition: BackendUserAuthentication.php:151
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\workspaceCannotEditOfflineVersion
‪string workspaceCannotEditOfflineVersion($table, $recData)
Definition: BackendUserAuthentication.php:942
‪TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction
Definition: WorkspaceRestriction.php:39