From 7ab2690310f81682bcab4ae84b64e3c241471275 Mon Sep 17 00:00:00 2001 From: JiaJia Ji Date: Mon, 9 Dec 2024 15:04:04 +0100 Subject: [PATCH 1/6] followup #767 --- src/Helper/GridHelperService.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Helper/GridHelperService.php b/src/Helper/GridHelperService.php index 7311228cf..ba651be64 100644 --- a/src/Helper/GridHelperService.php +++ b/src/Helper/GridHelperService.php @@ -609,14 +609,14 @@ public function prepareListingForGrid(array $requestParams, string $requestedLan if (isset($requestParams['only_direct_children']) && $requestParams['only_direct_children'] === 'true') { $conditionFilters[] = 'parentId = ' . $folder->getId(); - } else { - $quotedPath = $list->quote($folder->getRealFullPath()); - $quotedWildcardPath = $list->quote($list->escapeLike(str_replace('//', '/', $folder->getRealFullPath() . '/')) . '%'); - $conditionFilters[] = '(`path` = ' . $quotedPath . ' OR `path` like ' . $quotedWildcardPath . ')'; } if (!$adminUser->isAdmin()) { $conditionFilters[] = $this->getPermittedPathsByUser('object', $adminUser); + } else { + $quotedPath = $list->quote($folder->getRealFullPath()); + $quotedWildcardPath = $list->quote($list->escapeLike(str_replace('//', '/', $folder->getRealFullPath() . '/')) . '%'); + $conditionFilters[] = '(`path` = ' . $quotedPath . ' OR `path` like ' . $quotedWildcardPath . ')'; } $featureJoins = []; @@ -943,14 +943,14 @@ protected function getPermittedPathsByUser(string $type, User $user): string $exceptions = ''; $folderSuffix = ''; if ($allowedPaths) { - $exceptionsConcat = implode("%' OR `path` LIKE '", $allowedPaths); - $exceptions = " OR (`path` LIKE '" . $exceptionsConcat . "%')"; + $exceptionsConcat = implode("%' OR CONCAT(`path`,`key`) LIKE '", $allowedPaths); + $exceptions = " OR (CONCAT(`path`,`key`) LIKE '" . $exceptionsConcat . "%')"; $folderSuffix = '/'; //if allowed children are found, the current folder is listable but its content is still blocked, can easily done by adding a trailing slash } - $forbiddenPathSql[] = ' (`path` NOT LIKE ' . $db->quote($forbiddenPath . $folderSuffix . '%') . $exceptions . ') '; + $forbiddenPathSql[] = ' (CONCAT(`path`,`key`) NOT LIKE ' . $db->quote($forbiddenPath . $folderSuffix . '%') . $exceptions . ') '; } foreach ($elementPaths['allowed'] as $allowedPaths) { - $allowedPathSql[] = ' `path` LIKE ' . $db->quote($allowedPaths . '%'); + $allowedPathSql[] = ' CONCAT(`path`,`key`) LIKE ' . $db->quote($allowedPaths . '%'); } // this is to avoid query error when implode is empty. From 0a1e532c0290a76d2aa76f103edd6868bb8c18e9 Mon Sep 17 00:00:00 2001 From: JiaJia Ji Date: Mon, 9 Dec 2024 15:08:21 +0100 Subject: [PATCH 2/6] followup #767 --- src/Helper/GridHelperService.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Helper/GridHelperService.php b/src/Helper/GridHelperService.php index ba651be64..216c12812 100644 --- a/src/Helper/GridHelperService.php +++ b/src/Helper/GridHelperService.php @@ -609,16 +609,17 @@ public function prepareListingForGrid(array $requestParams, string $requestedLan if (isset($requestParams['only_direct_children']) && $requestParams['only_direct_children'] === 'true') { $conditionFilters[] = 'parentId = ' . $folder->getId(); - } - - if (!$adminUser->isAdmin()) { - $conditionFilters[] = $this->getPermittedPathsByUser('object', $adminUser); } else { $quotedPath = $list->quote($folder->getRealFullPath()); $quotedWildcardPath = $list->quote($list->escapeLike(str_replace('//', '/', $folder->getRealFullPath() . '/')) . '%'); $conditionFilters[] = '(`path` = ' . $quotedPath . ' OR `path` like ' . $quotedWildcardPath . ')'; } + if (!$adminUser->isAdmin()) { + $conditionFilters[] = $this->getPermittedPathsByUser('object', $adminUser); + } + + $featureJoins = []; $slugJoins = []; $featureAndSlugFilters = []; From 4267368cc2fd7b6fb4523144b517f4e31e2196b8 Mon Sep 17 00:00:00 2001 From: JiaJia Ji Date: Mon, 9 Dec 2024 18:04:56 +0100 Subject: [PATCH 3/6] wip: alternative to concat --- src/Helper/GridHelperService.php | 54 ++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/src/Helper/GridHelperService.php b/src/Helper/GridHelperService.php index 216c12812..c3ba84be7 100644 --- a/src/Helper/GridHelperService.php +++ b/src/Helper/GridHelperService.php @@ -924,6 +924,39 @@ public function createXlsxExportFile(FilesystemOperator $storage, string $fileHa return $response; } + private function optimizedConcatLike(string $fullpath): string + { + //CONCAT(`path`,`key`) LIKE '" . $fullpath . "%' + $pathParts = explode('/', $fullpath); + $leaf = array_pop($pathParts); + $path = implode('/', $pathParts); + + return '( + (`path` = "' . $path . '/" AND `key` = "' . $leaf . '") + OR + `path` LIKE "' . $fullpath . '/%" + )'; + } + + private function optimizedConcatNotLike(string $fullpath, $onlyChildren = false): string + { + //CONCAT(`path`,`key`) NOT LIKE '" . $fullpath . "%' + $pathParts = explode('/', $fullpath); + $leaf = array_pop($pathParts); + $path = implode('/', $pathParts); + + if ($onlyChildren){ + return '`path` NOT LIKE "' . $fullpath . '/%"'; + } + + return '( + (`path` != "' . $path . '/" AND `key` != "' . $leaf . '") + AND + `path` NOT LIKE "' . $fullpath . '/%" + )'; + + } + /** * * @@ -931,27 +964,30 @@ public function createXlsxExportFile(FilesystemOperator $storage, string $fileHa */ protected function getPermittedPathsByUser(string $type, User $user): string { - $db = Db::get(); - $allowedTypes = []; if ($user->isAllowed($type . 's')) { //the permissions are just plural $elementPaths = Service::findForbiddenPaths($type, $user); - + $onlyChildren = false; $forbiddenPathSql = []; $allowedPathSql = []; foreach ($elementPaths['forbidden'] as $forbiddenPath => $allowedPaths) { $exceptions = ''; - $folderSuffix = ''; if ($allowedPaths) { - $exceptionsConcat = implode("%' OR CONCAT(`path`,`key`) LIKE '", $allowedPaths); - $exceptions = " OR (CONCAT(`path`,`key`) LIKE '" . $exceptionsConcat . "%')"; - $folderSuffix = '/'; //if allowed children are found, the current folder is listable but its content is still blocked, can easily done by adding a trailing slash + $exceptionsConcat = ''; + foreach ($allowedPaths as $path){ + if ($exceptionsConcat !== '') { + $exceptionsConcat.= ' OR '; + } + $exceptionsConcat.= $this->optimizedConcatLike($path); + } + $exceptions = " OR (" . $exceptionsConcat . ")"; + $onlyChildren = true; //if allowed children are found, the current folder can be listed but its content is still blocked, can easily done by adding a trailing slash } - $forbiddenPathSql[] = ' (CONCAT(`path`,`key`) NOT LIKE ' . $db->quote($forbiddenPath . $folderSuffix . '%') . $exceptions . ') '; + $forbiddenPathSql[] = $this->optimizedConcatNotLike($forbiddenPath, $onlyChildren) . $exceptions; } foreach ($elementPaths['allowed'] as $allowedPaths) { - $allowedPathSql[] = ' CONCAT(`path`,`key`) LIKE ' . $db->quote($allowedPaths . '%'); + $allowedPathSql[] = $this->optimizedConcatLike($allowedPaths ); } // this is to avoid query error when implode is empty. From 3b657f492d322aaaeb700cf7bf7cbc011046c05b Mon Sep 17 00:00:00 2001 From: JiaJia Ji Date: Mon, 9 Dec 2024 19:00:13 +0100 Subject: [PATCH 4/6] stan fix --- src/Helper/GridHelperService.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Helper/GridHelperService.php b/src/Helper/GridHelperService.php index c3ba84be7..4bb08eb2b 100644 --- a/src/Helper/GridHelperService.php +++ b/src/Helper/GridHelperService.php @@ -938,7 +938,7 @@ private function optimizedConcatLike(string $fullpath): string )'; } - private function optimizedConcatNotLike(string $fullpath, $onlyChildren = false): string + private function optimizedConcatNotLike(string $fullpath, bool $onlyChildren = false): string { //CONCAT(`path`,`key`) NOT LIKE '" . $fullpath . "%' $pathParts = explode('/', $fullpath); From 55b4fccbbc46172c52065b332f14bbc7f17f5d4b Mon Sep 17 00:00:00 2001 From: JiaJia Ji Date: Tue, 10 Dec 2024 10:33:23 +0100 Subject: [PATCH 5/6] cleanup comments --- src/Helper/GridHelperService.php | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/Helper/GridHelperService.php b/src/Helper/GridHelperService.php index 4bb08eb2b..c8940e7fa 100644 --- a/src/Helper/GridHelperService.php +++ b/src/Helper/GridHelperService.php @@ -619,7 +619,6 @@ public function prepareListingForGrid(array $requestParams, string $requestedLan $conditionFilters[] = $this->getPermittedPathsByUser('object', $adminUser); } - $featureJoins = []; $slugJoins = []; $featureAndSlugFilters = []; @@ -924,9 +923,11 @@ public function createXlsxExportFile(FilesystemOperator $storage, string $fileHa return $response; } + /** + * A more performant alternative to "CONCAT(`path`,`key`) LIKE $fullpath" + */ private function optimizedConcatLike(string $fullpath): string { - //CONCAT(`path`,`key`) LIKE '" . $fullpath . "%' $pathParts = explode('/', $fullpath); $leaf = array_pop($pathParts); $path = implode('/', $pathParts); @@ -938,9 +939,12 @@ private function optimizedConcatLike(string $fullpath): string )'; } + /** + * A more performant alternative to "CONCAT(`path`,`key`) NOT LIKE $fullpath" + * Set $onlyChildren to true when you want to exclude the folder/element itself + */ private function optimizedConcatNotLike(string $fullpath, bool $onlyChildren = false): string { - //CONCAT(`path`,`key`) NOT LIKE '" . $fullpath . "%' $pathParts = explode('/', $fullpath); $leaf = array_pop($pathParts); $path = implode('/', $pathParts); @@ -982,7 +986,8 @@ protected function getPermittedPathsByUser(string $type, User $user): string $exceptionsConcat.= $this->optimizedConcatLike($path); } $exceptions = " OR (" . $exceptionsConcat . ")"; - $onlyChildren = true; //if allowed children are found, the current folder can be listed but its content is still blocked, can easily done by adding a trailing slash + //if any allowed child is found, the current folder can be listed but its content is still blocked + $onlyChildren = true; } $forbiddenPathSql[] = $this->optimizedConcatNotLike($forbiddenPath, $onlyChildren) . $exceptions; } @@ -1008,7 +1013,7 @@ protected function getPermittedPathsByUser(string $type, User $user): string $forbiddenAndAllowedSql.= ' )'; - $allowedTypes[] = $forbiddenAndAllowedSql; + $allowedTypes[] = $forbiddenAndAllowedSql; } //if allowedTypes is still empty after getting the workspaces, it means that there are no any main permissions set From 74990d6032a22269fe050b29f78b33466b355775 Mon Sep 17 00:00:00 2001 From: JiaJia Ji Date: Tue, 10 Dec 2024 10:34:26 +0100 Subject: [PATCH 6/6] cs fix --- src/Helper/GridHelperService.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Helper/GridHelperService.php b/src/Helper/GridHelperService.php index c8940e7fa..1e2ce8802 100644 --- a/src/Helper/GridHelperService.php +++ b/src/Helper/GridHelperService.php @@ -1013,7 +1013,7 @@ protected function getPermittedPathsByUser(string $type, User $user): string $forbiddenAndAllowedSql.= ' )'; - $allowedTypes[] = $forbiddenAndAllowedSql; + $allowedTypes[] = $forbiddenAndAllowedSql; } //if allowedTypes is still empty after getting the workspaces, it means that there are no any main permissions set