[TASK] Allow record or uid for isInWebMount 68/62868/5
authorMarkus Klein <markus.klein@typo3.org>
Mon, 13 Jan 2020 18:19:36 +0000 (19:19 +0100)
committerBenni Mack <benni@typo3.org>
Tue, 14 Jan 2020 20:46:12 +0000 (21:46 +0100)
Extend the function signature of BackendUserAuthentication::isInWebMount
to allow the uid of a page or the full page record.
This saves another database lookup for the page.

Resolves: #90105
Releases: master, 9.5
Change-Id: Id246967b7a8237dbe8939126acf21fede6dda756
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/62868
Reviewed-by: Susanne Moog <look@susi.dev>
Reviewed-by: Tymoteusz Motylewski <t.motylewski@gmail.com>
Reviewed-by: Benni Mack <benni@typo3.org>
Tested-by: Susanne Moog <look@susi.dev>
Tested-by: TYPO3com <noreply@typo3.com>
Tested-by: Benni Mack <benni@typo3.org>
typo3/sysext/backend/Classes/Controller/BackendController.php
typo3/sysext/backend/Classes/Controller/ContentElement/ElementInformationController.php
typo3/sysext/backend/Classes/Tree/View/AbstractTreeView.php
typo3/sysext/backend/Classes/Utility/BackendUtility.php
typo3/sysext/core/Classes/Authentication/BackendUserAuthentication.php

index 38a899b..c10b3e5 100644 (file)
@@ -414,7 +414,7 @@ class BackendController
                 $editRecord = BackendUtility::getRecordWSOL('pages', $editId, '*', $where);
             }
             // If the page was accessible, then let the user edit it.
-            if (is_array($editRecord) && $beUser->isInWebMount($editRecord['uid'])) {
+            if (is_array($editRecord) && $beUser->isInWebMount($editRecord)) {
                 // Checking page edit parameter:
                 if (!($userTsConfig['options.']['bookmark_onEditId_dontSetPageTree'] ?? false)) {
                     $bookmarkKeepExpanded = (bool)($userTsConfig['options.']['bookmark_onEditId_keepExistingExpanded'] ?? false);
index 3bd58f3..7c36629 100644 (file)
@@ -759,7 +759,7 @@ class ElementInformationController
     protected function canAccessPage(string $tableName, array $record): bool
     {
         $recordPid = (int)($tableName === 'pages' ? $record['uid'] : $record['pid']);
-        return $this->getBackendUser()->isInWebMount($recordPid)
+        return $this->getBackendUser()->isInWebMount($tableName === 'pages' ? $record : $record['pid'])
             || $recordPid === 0 && !empty($GLOBALS['TCA'][$tableName]['ctrl']['security']['ignoreRootLevelRestriction']);
     }
 
index 0fb5f9e..20fce1b 100644 (file)
@@ -732,8 +732,7 @@ abstract class AbstractTreeView
         $idH = [];
         // Traverse the records:
         while ($crazyRecursionLimiter > 0 && ($row = $this->getDataNext($res))) {
-            $pageUid = ($this->table === 'pages') ? $row['uid'] : $row['pid'];
-            if (!$this->getBackendUser()->isInWebMount($pageUid)) {
+            if (!$this->getBackendUser()->isInWebMount($this->table === 'pages' ? $row : $row['pid'])) {
                 // Current record is not within web mount => skip it
                 continue;
             }
index e46ed5f..eb6ef0c 100644 (file)
@@ -587,7 +587,7 @@ class BackendUtility
                 }
             } else {
                 $pageinfo = self::getRecord('pages', $id, '*', $perms_clause);
-                if ($pageinfo['uid'] && static::getBackendUserAuthentication()->isInWebMount($id, $perms_clause)) {
+                if ($pageinfo['uid'] && static::getBackendUserAuthentication()->isInWebMount($pageinfo, $perms_clause)) {
                     self::workspaceOL('pages', $pageinfo);
                     if (is_array($pageinfo)) {
                         self::fixVersioningPid('pages', $pageinfo);
index c19345d..6fa84cb 100644 (file)
@@ -348,7 +348,7 @@ class BackendUserAuthentication extends AbstractUserAuthentication
     }
 
     /**
-     * Checks if the page id, $id, is found within the webmounts set up for the user.
+     * Checks if the page id or page record ($idOrRow) is found within the webmounts set up for the user.
      * This should ALWAYS be checked for any page id a user works with, whether it's about reading, writing or whatever.
      * The point is that this will add the security that a user can NEVER touch parts outside his mounted
      * pages in the page tree. This is otherwise possible if the raw page permissions allows for it.
@@ -357,27 +357,42 @@ class BackendUserAuthentication extends AbstractUserAuthentication
      * (fx. by setting TYPO3_CONF_VARS['BE']['lockBeUserToDBmounts']=0) then it returns "1" right away
      * Otherwise the function will return the uid of the webmount which was first found in the rootline of the input page $id
      *
-     * @param int $id Page ID to check
+     * @param int|array $idOrRow Page ID or full page record to check
      * @param string $readPerms Content of "->getPagePermsClause(1)" (read-permissions). If not set, they will be internally calculated (but if you have the correct value right away you can save that database lookup!)
      * @param bool|int $exitOnError If set, then the function will exit with an error message.
      * @throws \RuntimeException
      * @return int|null The page UID of a page in the rootline that matched a mount point
      */
-    public function isInWebMount($id, $readPerms = '', $exitOnError = 0)
+    public function isInWebMount($idOrRow, $readPerms = '', $exitOnError = 0)
     {
         if (!$GLOBALS['TYPO3_CONF_VARS']['BE']['lockBeUserToDBmounts'] || $this->isAdmin()) {
             return 1;
         }
-        $id = (int)$id;
-        // Check if input id is an offline version page in which case we will map id to the online version:
-        $checkRec = BackendUtility::getRecord(
-            'pages',
-            $id,
-            't3ver_oid,'
-            . $GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'] . ','
-            . $GLOBALS['TCA']['pages']['ctrl']['languageField']
-        );
-        if ((int)$checkRec['t3ver_oid'] > 0) {
+        $fetchPageFromDatabase = true;
+        if (is_array($idOrRow)) {
+            if (empty($idOrRow['uid'])) {
+                throw new \RuntimeException('The given page record is invalid. Missing uid.', 1578950324);
+            }
+            $checkRec = $idOrRow;
+            $id = (int)$idOrRow['uid'];
+            // ensure the required fields are present on the record
+            if (isset($checkRec['t3ver_oid'], $checkRec[$GLOBALS['TCA']['pages']['ctrl']['languageField']], $checkRec[$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField']])) {
+                $fetchPageFromDatabase = false;
+            }
+        } else {
+            $id = (int)$idOrRow;
+        }
+        if ($fetchPageFromDatabase) {
+            // Check if input id is an offline version page in which case we will map id to the online version:
+            $checkRec = BackendUtility::getRecord(
+                'pages',
+                $id,
+                't3ver_oid,'
+                . $GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'] . ','
+                . $GLOBALS['TCA']['pages']['ctrl']['languageField']
+            );
+        }
+        if ($checkRec['t3ver_oid'] > 0) {
             $id = (int)$checkRec['t3ver_oid'];
         }
         // if current rec is a translation then get uid from l10n_parent instead
@@ -575,7 +590,7 @@ class BackendUserAuthentication extends AbstractUserAuthentication
         }
         // Return 0 if page is not within the allowed web mount
         // Always do this for the default language page record
-        if (!$this->isInWebMount($row[$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField']] ?: $row['uid'])) {
+        if (!$this->isInWebMount($row[$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField']] ?: $row)) {
             return Permission::NOTHING;
         }
         $out = Permission::NOTHING;