From 12b52059145d34b726fbe10d40069aa5a5173fec Mon Sep 17 00:00:00 2001
From: Christoph Lehmann <christoph.lehmann@networkteam.com>
Date: Wed, 13 Sep 2017 23:34:45 +0200
Subject: [PATCH] [BUGFIX] Make category tree filterable for editors with
 category mounts

TCEFORM.pages.categories.config.treeConfig.rootUid should filter
the category tree. Non-Admin users with category mounts currently
need every child category of rootUid in their category mounts
since the rootline of rootUid is not checked against the category
mounts.

Resolves: #78274
Releases: master, 8.7
Change-Id: Id02ae69111df7397207939a034ed05797eb160ad
Reviewed-on: https://review.typo3.org/54141
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: Andreas Wolf <andreas.wolf@typo3.org>
Tested-by: Andreas Wolf <andreas.wolf@typo3.org>
---
 .../Security/CategoryPermissionsAspect.php    | 38 +++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/typo3/sysext/backend/Classes/Security/CategoryPermissionsAspect.php b/typo3/sysext/backend/Classes/Security/CategoryPermissionsAspect.php
index 06d299e913d8..ee04fc61041a 100644
--- a/typo3/sysext/backend/Classes/Security/CategoryPermissionsAspect.php
+++ b/typo3/sysext/backend/Classes/Security/CategoryPermissionsAspect.php
@@ -17,7 +17,9 @@ namespace TYPO3\CMS\Backend\Security;
 use TYPO3\CMS\Backend\Tree\TreeNode;
 use TYPO3\CMS\Backend\Tree\TreeNodeCollection;
 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
+use TYPO3\CMS\Core\Database\ConnectionPool;
 use TYPO3\CMS\Core\Tree\TableConfiguration\DatabaseTreeDataProvider;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
  * We do not have AOP in TYPO3 for now, thus the aspect which
@@ -69,6 +71,15 @@ class CategoryPermissionsAspect
 
             if (!empty($categoryMountPoints) && !empty($treeNodeCollection)) {
 
+                // Check the rootline against categoryMountPoints when tree was filtered
+                if ($dataProvider->getRootUid() !== null) {
+                    $uidsInRootline = $this->findUidsInRootline($dataProvider->getRootUid());
+                    if (!empty(array_intersect($categoryMountPoints, $uidsInRootline))) {
+                        // One of the parents was found in categoryMountPoints so all children are secure
+                        return;
+                    }
+                }
+
                 // First, remove all child nodes which must be analysed to be considered as "secure".
                 // The nodes were backed up in variable $treeNodeCollection beforehand.
                 $treeData->removeChildNodes();
@@ -122,4 +133,31 @@ class CategoryPermissionsAspect
         }
         return $result;
     }
+
+    /**
+     * Find parent uids in rootline
+     *
+     * @param int $uid
+     * @return array
+     */
+    protected function findUidsInRootline($uid)
+    {
+        /** @var \TYPO3\CMS\Core\Database\Query\QueryBuilder $queryBuilder */
+        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->categoryTableName);
+        $row = $queryBuilder
+            ->select('parent')
+            ->from($this->categoryTableName)
+            ->where(
+                $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT))
+            )
+            ->execute()
+            ->fetch();
+
+        $parentUids = [];
+        if ($row['parent'] > 0) {
+            $parentUids = $this->findUidsInRootline($row['parent']);
+            $parentUids[] = $row['parent'];
+        }
+        return $parentUids;
+    }
 }
-- 
GitLab