From 3b0654fc6195974d68f5d2711aaa17b62feb7156 Mon Sep 17 00:00:00 2001
From: Helmut Hummel <typo3@helhum.io>
Date: Tue, 7 Nov 2017 15:09:08 +0100
Subject: [PATCH] [BUGFIX] Show deleted page actions in record history

Because users have no access to deleted pages,
the access check always fails, leading to delete page
actions not being shown in the history despite being
properly tracked.

We now check this case and do a more lightweight check
so that we still have the permissions checked,
but can show deleted pages without disclosing unwanted
information.

Resolves: #45056
Releases: 7.6, 8.7, master
Change-Id: Id919a24651c18a351f9723e86610b525a4f4726c
Reviewed-on: https://review.typo3.org/54580
Reviewed-by: Mathias Schreiber <mathias.schreiber@typo3.com>
Tested-by: Mathias Schreiber <mathias.schreiber@typo3.com>
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Wouter Wolters <typo3@wouterwolters.nl>
Reviewed-by: Markus Klein <markus.klein@typo3.org>
Tested-by: Markus Klein <markus.klein@typo3.org>
---
 .../ElementHistoryController.php              |  1 +
 .../backend/Classes/History/RecordHistory.php | 26 ++++++++++++++++---
 .../Partials/RecordHistory/History.html       |  2 +-
 3 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/typo3/sysext/backend/Classes/Controller/ContentElement/ElementHistoryController.php b/typo3/sysext/backend/Classes/Controller/ContentElement/ElementHistoryController.php
index 8f8a4f5d3421..6cf459b77aff 100644
--- a/typo3/sysext/backend/Classes/Controller/ContentElement/ElementHistoryController.php
+++ b/typo3/sysext/backend/Classes/Controller/ContentElement/ElementHistoryController.php
@@ -333,6 +333,7 @@ class ElementHistoryController
 
             $singleLine['title'] = $this->generateTitle($entry['tablename'], $entry['recuid']);
             $singleLine['elementUrl'] = $this->buildUrl(['element' => $entry['tablename'] . ':' . $entry['recuid']]);
+            $singleLine['actiontype'] = $entry['actiontype'];
             if ((int)$entry['actiontype'] === RecordHistoryStore::ACTION_MODIFY) {
                 // show changes
                 if (!$this->showDiff) {
diff --git a/typo3/sysext/backend/Classes/History/RecordHistory.php b/typo3/sysext/backend/Classes/History/RecordHistory.php
index e6f2d9c620df..da43799239fe 100644
--- a/typo3/sysext/backend/Classes/History/RecordHistory.php
+++ b/typo3/sysext/backend/Classes/History/RecordHistory.php
@@ -19,6 +19,7 @@ use TYPO3\CMS\Core\Database\ConnectionPool;
 use TYPO3\CMS\Core\Database\Query\QueryBuilder;
 use TYPO3\CMS\Core\DataHandling\DataHandler;
 use TYPO3\CMS\Core\History\RecordHistoryStore;
+use TYPO3\CMS\Core\Type\Bitmask\Permission;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
@@ -534,10 +535,27 @@ class RecordHistory
         }
 
         if (!isset($this->pageAccessCache[$pageId])) {
-            $this->pageAccessCache[$pageId] = BackendUtility::readPageAccess(
-                $pageId,
-                $this->getBackendUser()->getPagePermsClause(1)
-            );
+            $isDeletedPage = false;
+            if (isset($GLOBALS['TCA']['pages']['ctrl']['delete'])) {
+                $deletedField = $GLOBALS['TCA']['pages']['ctrl']['delete'];
+                $pageRecord = BackendUtility::getRecord('pages', $pageId, $deletedField, '', false);
+                $isDeletedPage = (bool)$pageRecord[$deletedField];
+            }
+            if ($isDeletedPage) {
+                // The page is deleted, so we fake its uid to be the one of the parent page.
+                // By doing so, the following API will use this id to traverse the rootline
+                // and check whether it is in the users' web mounts.
+                // We check however if the user has (or better had) access to the deleted page itself.
+                // Since the only way we got here is by requesting the history of the parent page
+                // we can be sure this parent page actually exists.
+                $pageRecord['uid'] = $pageRecord['pid'];
+                $this->pageAccessCache[$pageId] = $this->getBackendUser()->doesUserHaveAccess($pageRecord, Permission::PAGE_SHOW);
+            } else {
+                $this->pageAccessCache[$pageId] = BackendUtility::readPageAccess(
+                    $pageId,
+                    $this->getBackendUser()->getPagePermsClause(Permission::PAGE_SHOW)
+                );
+            }
         }
 
         return $this->pageAccessCache[$pageId] !== false;
diff --git a/typo3/sysext/backend/Resources/Private/Partials/RecordHistory/History.html b/typo3/sysext/backend/Resources/Private/Partials/RecordHistory/History.html
index dc39b3beb7fb..84963790ae8b 100644
--- a/typo3/sysext/backend/Resources/Private/Partials/RecordHistory/History.html
+++ b/typo3/sysext/backend/Resources/Private/Partials/RecordHistory/History.html
@@ -35,7 +35,7 @@
 					<f:if condition="{historyRow.originalBackendUserName}"> ({f:translate(key: 'LLL:EXT:backend/Resources/Private/Language/locallang_show_rechis.xlf:viaUser')} {historyRow.originalBackendUserName})</f:if>
 				</td>
 				<td>
-					<a href="{elementUrl}" title="{f:translate('LLL:EXT:backend/Resources/Private/Language/locallang_show_rechis.xlf:linkRecordHistory')}">{historyRow.title}</a>
+					<a href="{elementUrl}" title="{f:translate(id: 'LLL:EXT:backend/Resources/Private/Language/locallang_show_rechis.xlf:linkRecordHistory')}">{historyRow.title -> f:format.raw()}</a>
 				</td>
 				<td>
 					<f:switch expression="{historyRow.actiontype}">
-- 
GitLab