From b86ccc8df520ecef349bad95ffa0f872ae67f763 Mon Sep 17 00:00:00 2001
From: Oliver Bartsch <bo@cedev.de>
Date: Sun, 1 Mar 2020 18:28:44 +0100
Subject: [PATCH] [BUGFIX] Take tables_modify in PageLayoutView into account

If a non-admin user currently has no access to modify the `tt_content`
table they still get editing options displayed in the PageLayoutView.
Using these options leads to an infinty load of the FormEngine.

Therefore a new function `hasContentModificationAndAccessPermissions`
is introduced which also takes `tables_modify` into account. This function
is now used in various places in PageLayoutView and replaces the current
check which only validates the users access permission.

Resolves: #90608
Releases: master
Change-Id: I5a12557dff2ccdffc41d4df238965404603ef386
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/63520
Tested-by: TYPO3com <noreply@typo3.com>
Tested-by: Georg Ringer <georg.ringer@gmail.com>
Tested-by: Benni Mack <benni@typo3.org>
Reviewed-by: Georg Ringer <georg.ringer@gmail.com>
Reviewed-by: Benni Mack <benni@typo3.org>
---
 .../backend/Classes/View/PageLayoutView.php   | 26 ++++++++++++++-----
 1 file changed, 20 insertions(+), 6 deletions(-)

diff --git a/typo3/sysext/backend/Classes/View/PageLayoutView.php b/typo3/sysext/backend/Classes/View/PageLayoutView.php
index fd5ad18ee0f3..ea0486099152 100644
--- a/typo3/sysext/backend/Classes/View/PageLayoutView.php
+++ b/typo3/sysext/backend/Classes/View/PageLayoutView.php
@@ -397,7 +397,7 @@ class PageLayoutView implements LoggerAwareInterface
                                 0,
                                 $disableMoveAndNewButtons,
                                 true,
-                                $this->getBackendUser()->doesUserHaveAccess($this->pageinfo, Permission::CONTENT_EDIT)
+                                $this->hasContentModificationAndAccessPermissions()
                             );
                             $innerContent = '<div ' . ($row['_ORIG_uid'] ? ' class="ver-element"' : '') . '>'
                                 . $this->tt_content_drawItem($row) . '</div>';
@@ -890,7 +890,7 @@ class PageLayoutView implements LoggerAwareInterface
     {
         $icons = '';
         // Edit whole of column:
-        if ($editParams && $this->getBackendUser()->doesUserHaveAccess($this->pageinfo, Permission::CONTENT_EDIT) && $this->getBackendUser()->checkLanguageAccess(0)) {
+        if ($editParams && $this->hasContentModificationAndAccessPermissions() && $this->getBackendUser()->checkLanguageAccess(0)) {
             $link = $this->uriBuilder->buildUriFromRoute('record_edit') . $editParams . '&returnUrl=' . rawurlencode(GeneralUtility::getIndpEnv('REQUEST_URI'));
             $icons = '<a href="' . htmlspecialchars($link) . '"  title="'
                 . htmlspecialchars($this->getLanguageService()->getLL('editColumn')) . '">'
@@ -1044,7 +1044,7 @@ class PageLayoutView implements LoggerAwareInterface
                     . ' data-button-close-text="' . htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:cancel')) . '"'
                     . ' title="' . htmlspecialchars($this->getLanguageService()->getLL('deleteItem')) . '">'
                     . $this->iconFactory->getIcon('actions-edit-delete', Icon::SIZE_SMALL)->render() . '</a>';
-                if ($out && $backendUser->doesUserHaveAccess($this->pageinfo, Permission::CONTENT_EDIT)) {
+                if ($out && $this->hasContentModificationAndAccessPermissions()) {
                     $out = '<div class="btn-group btn-group-sm" role="group">' . $out . '</div>';
                 } else {
                     $out = '';
@@ -1140,7 +1140,7 @@ class PageLayoutView implements LoggerAwareInterface
             (
                 $this->getBackendUser()->isAdmin()
                 || ((int)$row['editlock'] === 0 && (int)$this->pageinfo['editlock'] === 0)
-                && $this->getBackendUser()->doesUserHaveAccess($this->pageinfo, Permission::CONTENT_EDIT)
+                && $this->hasContentModificationAndAccessPermissions()
                 && $this->getBackendUser()->checkAuthMode('tt_content', 'CType', $row['CType'], $GLOBALS['TYPO3_CONF_VARS']['BE']['explicitADmode'])
             )
         ) {
@@ -1480,7 +1480,10 @@ class PageLayoutView implements LoggerAwareInterface
      */
     public function linkEditContent($str, $row)
     {
-        if ($this->doEdit && $this->getBackendUser()->recordEditAccessInternals('tt_content', $row)) {
+        if ($this->doEdit
+            && $this->hasContentModificationAndAccessPermissions()
+            && $this->getBackendUser()->recordEditAccessInternals('tt_content', $row)
+        ) {
             $urlParameters = [
                 'edit' => [
                     'tt_content' => [
@@ -1998,10 +2001,21 @@ class PageLayoutView implements LoggerAwareInterface
             return true;
         }
         return !$this->pageinfo['editlock']
-            && $this->getBackendUser()->doesUserHaveAccess($this->pageinfo, Permission::CONTENT_EDIT)
+            && $this->hasContentModificationAndAccessPermissions()
             && ($languageId === null || $this->getBackendUser()->checkLanguageAccess($languageId));
     }
 
+    /**
+     * Check if current user has modification and access permissons for content set
+     *
+     * @return bool
+     */
+    protected function hasContentModificationAndAccessPermissions(): bool
+    {
+        return $this->getBackendUser()->check('tables_modify', 'tt_content')
+            && $this->getBackendUser()->doesUserHaveAccess($this->pageinfo, Permission::CONTENT_EDIT);
+    }
+
     /**
      * Returns the language service
      * @return LanguageService
-- 
GitLab