From 6c2741e3e719f1cc5a193b7eefebf1d230e3763b Mon Sep 17 00:00:00 2001 From: Jonas Date: Wed, 25 Sep 2024 15:38:18 +0200 Subject: [PATCH] fix: Allow to mount the collectives user folder into a subfolder Fixes: #514 Signed-off-by: Jonas --- lib/Controller/SettingsController.php | 4 +-- lib/Mount/MountProvider.php | 11 +++++-- .../Nav/CollectivesGlobalSettings.vue | 4 +-- .../features/bootstrap/FeatureContext.php | 32 ++++++++++--------- tests/Integration/features/mountpoint.feature | 8 +++++ .../Controller/SettingsControllerTest.php | 10 ++++-- 6 files changed, 45 insertions(+), 24 deletions(-) diff --git a/lib/Controller/SettingsController.php b/lib/Controller/SettingsController.php index d54d681d1..526c15a12 100644 --- a/lib/Controller/SettingsController.php +++ b/lib/Controller/SettingsController.php @@ -53,10 +53,10 @@ private function validateSetUserSetting(string $setting, ?string $value): void { } if ($setting === 'user_folder') { - // No root folder, has to start with `/`, no subfolder + // No root folder, has to start with `/`, not allowed to end with `/` if ($value === '/' || !(str_starts_with($value, '/')) - || str_contains(substr($value, 1), '/')) { + || str_ends_with($value, '/')) { throw new InvalidArgumentException('Invalid collectives folder path'); } diff --git a/lib/Mount/MountProvider.php b/lib/Mount/MountProvider.php index 63e699aaf..1ae12805a 100644 --- a/lib/Mount/MountProvider.php +++ b/lib/Mount/MountProvider.php @@ -61,10 +61,15 @@ public function getFoldersForUser(IUser $user): array { return $folders; } + $userFolderSetting = $this->userFolderHelper->getUserFolderSetting($user->getUID()); + $internalPathPrefix = 'files'; + $userFolderPath = substr($userFolder->getInternalPath(), 0, strlen($internalPathPrefix)) == $internalPathPrefix + ? substr($userFolder->getInternalPath(), strlen('files')) . '/' + : $userFolder->getName() . '/'; + $mountPointPath = ($userFolderSetting === '/') + ? '' + : $userFolderPath; foreach ($collectives as $c) { - $mountPointPath = ($this->userFolderHelper->getUserFolderSetting($user->getUID()) === '/') - ? '' - : $userFolder->getName() . '/'; $mountPointName = $c->getName(); try { $cacheEntry = $this->collectiveFolderManager->getFolderFileCache($c->getId(), $mountPointName); diff --git a/src/components/Nav/CollectivesGlobalSettings.vue b/src/components/Nav/CollectivesGlobalSettings.vue index 41613e26a..936e3a619 100644 --- a/src/components/Nav/CollectivesGlobalSettings.vue +++ b/src/components/Nav/CollectivesGlobalSettings.vue @@ -61,10 +61,10 @@ export default { .build() picker.pick() .then((path) => { - // No root folder, has to start with `/`, no subfolder + // No root folder, has to start with `/`, not allowed to end with `/` if (path === '/' || !path.startsWith('/') - || path.includes('/', 1)) { + || path.endsWith('/')) { const error = t('collectives', 'Invalid path selected. Only folders on first level are supported.') showError(error) throw new Error(error) diff --git a/tests/Integration/features/bootstrap/FeatureContext.php b/tests/Integration/features/bootstrap/FeatureContext.php index cc3dfa3b2..efcf3c07c 100644 --- a/tests/Integration/features/bootstrap/FeatureContext.php +++ b/tests/Integration/features/bootstrap/FeatureContext.php @@ -28,6 +28,7 @@ class FeatureContext implements Context { private array $cookieJars = []; private array $requestTokens = []; private array $store = []; + private bool $setXdebugSession = false; private const CIRCLE_MEMBER_LEVEL = [ 1 => 'Member', @@ -586,14 +587,18 @@ public function userSetsPageSubpageOrder(string $user, string $page, string $sub * * @throws GuzzleException */ - public function userGetsSetting(string $user, string $key, string $value): void { + public function userGetsSetting(string $user, string $key, ?string $value = null): string { $this->setCurrentUser($user); $this->sendOcsRequest('GET', '/apps/collectives/api/v1.0/settings/user/' . $key); $this->assertStatusCode(200); $jsonBody = $this->getJson(); - Assert::assertEquals($value, $jsonBody['ocs']['data']); + if ($value) { + Assert::assertEquals($value, $jsonBody['ocs']['data']); + } + + return $jsonBody['ocs']['data']; } /** @@ -1301,13 +1306,8 @@ public function anonymousSeesPageShareAttachments(string $name, string $mimetype } private function getUserCollectivesPath(string $user): string { - // Dirty hack to not break it on local dev setup - $lang = $this->getUserLanguage($user); - if ($lang === 'de') { - return 'Kollektive'; - } - - return 'Collectives'; + $this->setCurrentUser($user); + return $this->userGetsSetting($user, 'user_folder'); } /** @@ -1330,7 +1330,7 @@ public function hasWebdavAccess(string $collective, string $user, string $permis $body = $dom->saveXML(); $userCollectivesPath = $this->getUserCollectivesPath($user); - $this->sendRemoteRequest('PROPFIND', '/dav/files/' . $user . '/' . $userCollectivesPath . '/' . urlencode($collective) . '/', $body, null, $headers); + $this->sendRemoteRequest('PROPFIND', '/dav/files/' . $user . $userCollectivesPath . '/' . urlencode($collective) . '/', $body, null, $headers); $this->assertStatusCode(207); // simplexml_load_string() would be better than preg_replace @@ -1732,11 +1732,13 @@ private function sendRequestBase(string $verb, } // Add Xdebug trigger variable as GET parameter - $xdebugSession = 'XDEBUG_SESSION=PHPSTORM'; - if (str_contains($url, '?')) { - $url .= '&' . $xdebugSession; - } else { - $url .= '?' . $xdebugSession; + if ($this->setXdebugSession) { + $xdebugSession = 'XDEBUG_SESSION=PHPSTORM'; + if (str_contains($url, '?')) { + $url .= '&' . $xdebugSession; + } else { + $url .= '?' . $xdebugSession; + } } // clear the cached json response diff --git a/tests/Integration/features/mountpoint.feature b/tests/Integration/features/mountpoint.feature index 17eeb37e8..894ba9c6c 100644 --- a/tests/Integration/features/mountpoint.feature +++ b/tests/Integration/features/mountpoint.feature @@ -17,6 +17,14 @@ Feature: mountpoint And user "alice" has webdav access to "BehatMountPoint" with permissions "RMG" And user "bob" has webdav access to "BehatMountPoint" with permissions "MG" + Scenario: Change collectives user folder for user + When user "bob" sets setting "user_folder" to value "/some/folder" + Then user "jane" has webdav access to "BehatMountPoint" with permissions "RMGDNVCK" + And user "john" has webdav access to "BehatMountPoint" with permissions "RMGDNVCK" + And user "alice" has webdav access to "BehatMountPoint" with permissions "RMG" + And user "bob" has webdav access to "BehatMountPoint" with permissions "MG" + Then user "bob" sets setting "user_folder" to value "/Collectives" + Scenario: Trash page via webdav When user "bob" fails to trash page "firstpage" via webdav in "BehatMountPoint" And user "jane" trashes page "firstpage" via webdav in "BehatMountPoint" diff --git a/tests/Unit/Controller/SettingsControllerTest.php b/tests/Unit/Controller/SettingsControllerTest.php index f14ec09b5..81a30fe2e 100644 --- a/tests/Unit/Controller/SettingsControllerTest.php +++ b/tests/Unit/Controller/SettingsControllerTest.php @@ -60,8 +60,8 @@ public function testSetUserSettingsEmptyString(): void { public function testSetUserSettingsNoSlashStart(): void { $response = new DataResponse('Invalid collectives folder path', Http::STATUS_BAD_REQUEST); self::assertEquals($response, $this->settingsController->setUserSetting('user_folder', 'test')); - self::assertEquals($response, $this->settingsController->setUserSetting('user_folder', '/test/')); self::assertEquals($response, $this->settingsController->setUserSetting('user_folder', 'test/')); + self::assertEquals($response, $this->settingsController->setUserSetting('user_folder', 'test/abc')); } public function testSetUserSettingsRootFolder(): void { @@ -69,13 +69,19 @@ public function testSetUserSettingsRootFolder(): void { self::assertEquals($response, $this->settingsController->setUserSetting('user_folder', '/')); } - public function testSetUserSettingsMultipleSlashes(): void { + public function testSetUserSettingsSlashEnd(): void { $response = new DataResponse('Invalid collectives folder path', Http::STATUS_BAD_REQUEST); self::assertEquals($response, $this->settingsController->setUserSetting('user_folder', '/test/')); + self::assertEquals($response, $this->settingsController->setUserSetting('user_folder', '/test/abc/')); } public function testSetUserSettings(): void { $response = new DataResponse('/test', Http::STATUS_OK); self::assertEquals($response, $this->settingsController->setUserSetting('user_folder', '/test')); } + + public function testSetUserSettingsSubfolder(): void { + $response = new DataResponse('/test/abc', Http::STATUS_OK); + self::assertEquals($response, $this->settingsController->setUserSetting('user_folder', '/test/abc')); + } }