Commit a4809174 authored by Markus Klein's avatar Markus Klein Committed by Benni Mack
Browse files

[TASK] Allow record or uid for isInWebMount

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's avatarSusanne Moog <look@susi.dev>
Reviewed-by: Tymoteusz Motylewski's avatarTymoteusz Motylewski <t.motylewski@gmail.com>
Reviewed-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Tested-by: Susanne Moog's avatarSusanne Moog <look@susi.dev>
Tested-by: default avatarTYPO3com <noreply@typo3.com>
Tested-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
parent 0e5c7755
......@@ -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);
......
......@@ -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']);
}
......
......@@ -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;
}
......
......@@ -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);
......
......@@ -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;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment