diff options
author | Kate <26026535+provokateurin@users.noreply.github.com> | 2024-10-15 13:32:33 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-10-15 13:32:33 +0200 |
commit | 2a69cf785d88869dea7dcb78dd53190a59c1617d (patch) | |
tree | d2b38cc4f1c9b980d20dc43babd29eea0d6c6c81 | |
parent | c03ff3c6c8a930f5171fb0af739d1b6871bceb36 (diff) | |
parent | eae69cb8bc4dc428b50b34d2a7aecca022823af3 (diff) | |
download | nextcloud-server-2a69cf785d88869dea7dcb78dd53190a59c1617d.tar.gz nextcloud-server-2a69cf785d88869dea7dcb78dd53190a59c1617d.zip |
Merge pull request #48631 from nextcloud/backport/dav-get
-rw-r--r-- | apps/dav/appinfo/v2/publicremote.php | 16 | ||||
-rw-r--r-- | build/integration/config/behat.yml | 2 | ||||
-rw-r--r-- | build/integration/dav_features/dav-v2-public.feature | 41 | ||||
-rw-r--r-- | build/integration/features/bootstrap/CommandLineContext.php | 9 | ||||
-rw-r--r-- | build/integration/features/bootstrap/CommentsContext.php | 2 | ||||
-rw-r--r-- | build/integration/features/bootstrap/DavFeatureContext.php | 23 | ||||
-rw-r--r-- | build/integration/features/bootstrap/Download.php | 14 | ||||
-rw-r--r-- | build/integration/features/bootstrap/FeatureContext.php | 1 | ||||
-rw-r--r-- | build/integration/features/bootstrap/WebDav.php | 44 |
9 files changed, 140 insertions, 12 deletions
diff --git a/apps/dav/appinfo/v2/publicremote.php b/apps/dav/appinfo/v2/publicremote.php index 0381614a328..c48f582ab4a 100644 --- a/apps/dav/appinfo/v2/publicremote.php +++ b/apps/dav/appinfo/v2/publicremote.php @@ -96,11 +96,15 @@ preg_match('/(^files\/\w+)/i', substr($requestUri, strlen($baseuri)), $match); $baseuri = $baseuri . $match[0]; $server = $serverFactory->createServer($baseuri, $requestUri, $authPlugin, function (\Sabre\DAV\Server $server) use ($authBackend, $linkCheckPlugin, $filesDropPlugin) { - $isAjax = in_array('XMLHttpRequest', explode(',', $_SERVER['HTTP_X_REQUESTED_WITH'] ?? '')); - $federatedShareProvider = \OCP\Server::get(FederatedShareProvider::class); - if ($federatedShareProvider->isOutgoingServer2serverShareEnabled() === false && !$isAjax) { - // this is what is thrown when trying to access a non-existing share - throw new NotAuthenticated(); + // GET must be allowed for e.g. showing images and allowing Zip downloads + if ($server->httpRequest->getMethod() !== 'GET') { + // If this is *not* a GET request we only allow access to public DAV from AJAX or when Server2Server is allowed + $isAjax = in_array('XMLHttpRequest', explode(',', $_SERVER['HTTP_X_REQUESTED_WITH'] ?? '')); + $federatedShareProvider = \OCP\Server::get(FederatedShareProvider::class); + if ($federatedShareProvider->isOutgoingServer2serverShareEnabled() === false && $isAjax === false) { + // this is what is thrown when trying to access a non-existing share + throw new NotAuthenticated(); + } } $share = $authBackend->getShare(); @@ -152,4 +156,4 @@ $server->addPlugin($linkCheckPlugin); $server->addPlugin($filesDropPlugin); // And off we go! -$server->exec(); +$server->start(); diff --git a/build/integration/config/behat.yml b/build/integration/config/behat.yml index 8401b841cdd..896b5cd2ec1 100644 --- a/build/integration/config/behat.yml +++ b/build/integration/config/behat.yml @@ -58,7 +58,7 @@ default: paths: - "%paths.base%/../dav_features" contexts: - - FeatureContext: + - DavFeatureContext: baseUrl: http://localhost:8080/ocs/ admin: - admin diff --git a/build/integration/dav_features/dav-v2-public.feature b/build/integration/dav_features/dav-v2-public.feature new file mode 100644 index 00000000000..66102f81e9d --- /dev/null +++ b/build/integration/dav_features/dav-v2-public.feature @@ -0,0 +1,41 @@ +# SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later +Feature: dav-v2-public + Background: + Given using api version "1" + + Scenario: Downloading a file from public share with Ajax header + Given using new dav path + And As an "admin" + And user "user0" exists + And user "user1" exists + And As an "user1" + And user "user1" created a folder "/testshare" + When User "user1" uploads file "data/green-square-256.png" to "/testshare/image.png" + And as "user1" creating a share with + | path | testshare | + | shareType | 3 | + | permissions | 1 | + And As an "user0" + Given using new public dav path + When Downloading public file "/image.png" + Then the downloaded file has the content of "/testshare/image.png" from "user1" data + + # Test that downloading files work to ensure e.g. the viewer works or files can be downloaded + Scenario: Downloading a file from public share without Ajax header and disabled s2s share + Given using new dav path + And As an "admin" + And user "user0" exists + And user "user1" exists + And As an "user1" + And user "user1" created a folder "/testshare" + When User "user1" uploads file "data/green-square-256.png" to "/testshare/image.png" + And as "user1" creating a share with + | path | testshare | + | shareType | 3 | + | permissions | 1 | + And As an "user0" + Given parameter "outgoing_server2server_share_enabled" of app "files_sharing" is set to "no" + Given using new public dav path + When Downloading public file "/image.png" without ajax header + Then the downloaded file has the content of "/testshare/image.png" from "user1" data diff --git a/build/integration/features/bootstrap/CommandLineContext.php b/build/integration/features/bootstrap/CommandLineContext.php index 8f9cfc7b45a..7be6863deae 100644 --- a/build/integration/features/bootstrap/CommandLineContext.php +++ b/build/integration/features/bootstrap/CommandLineContext.php @@ -26,6 +26,7 @@ */ require __DIR__ . '/../../vendor/autoload.php'; +use Behat\Behat\Context\Exception\ContextNotFoundException; use Behat\Behat\Hook\Scope\BeforeScenarioScope; use PHPUnit\Framework\Assert; @@ -61,8 +62,12 @@ class CommandLineContext implements \Behat\Behat\Context\Context { /** @BeforeScenario */ public function gatherContexts(BeforeScenarioScope $scope) { $environment = $scope->getEnvironment(); - // this should really be "WebDavContext" ... - $this->featureContext = $environment->getContext('FeatureContext'); + // this should really be "WebDavContext" + try { + $this->featureContext = $environment->getContext('FeatureContext'); + } catch (ContextNotFoundException) { + $this->featureContext = $environment->getContext('DavFeatureContext'); + } } private function findLastTransferFolderForUser($sourceUser, $targetUser) { diff --git a/build/integration/features/bootstrap/CommentsContext.php b/build/integration/features/bootstrap/CommentsContext.php index 0eddf972bc1..70fb23a2b2d 100644 --- a/build/integration/features/bootstrap/CommentsContext.php +++ b/build/integration/features/bootstrap/CommentsContext.php @@ -49,8 +49,6 @@ class CommentsContext implements \Behat\Behat\Context\Context { } } - - /** * get a named entry from response instead of picking a random entry from values * diff --git a/build/integration/features/bootstrap/DavFeatureContext.php b/build/integration/features/bootstrap/DavFeatureContext.php new file mode 100644 index 00000000000..acca52ccafc --- /dev/null +++ b/build/integration/features/bootstrap/DavFeatureContext.php @@ -0,0 +1,23 @@ +<?php +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +use Behat\Behat\Context\Context; +use Behat\Behat\Context\SnippetAcceptingContext; + +require __DIR__ . '/../../vendor/autoload.php'; + +class DavFeatureContext implements Context, SnippetAcceptingContext { + use AppConfiguration; + use ContactsMenu; + use ExternalStorage; + use Search; + use WebDav; + use Trashbin; + + protected function resetAppConfigs() { + $this->deleteServerConfig('files_sharing', 'outgoing_server2server_share_enabled'); + } +} diff --git a/build/integration/features/bootstrap/Download.php b/build/integration/features/bootstrap/Download.php index e5e6dc64853..8b871b1cd78 100644 --- a/build/integration/features/bootstrap/Download.php +++ b/build/integration/features/bootstrap/Download.php @@ -138,4 +138,18 @@ trait Download { "Local header for folder did not appear once in zip file" ); } + + /** + * @Then the downloaded file has the content of :sourceFilename from :user data + */ + public function theDownloadedFileHasContentOfUserFile($sourceFilename, $user) { + $this->getDownloadedFile(); + $expectedFileContents = file_get_contents($this->getDataDirectory() . "/$user/files" . $sourceFilename); + + // prevent the whole file from being printed in case of error. + Assert::assertEquals( + 0, strcmp($expectedFileContents, $this->downloadedFile), + 'Downloaded file content does not match local file content' + ); + } } diff --git a/build/integration/features/bootstrap/FeatureContext.php b/build/integration/features/bootstrap/FeatureContext.php index 27ad69857e2..8f49a1f1491 100644 --- a/build/integration/features/bootstrap/FeatureContext.php +++ b/build/integration/features/bootstrap/FeatureContext.php @@ -28,7 +28,6 @@ use Behat\Behat\Context\SnippetAcceptingContext; require __DIR__ . '/../../vendor/autoload.php'; - /** * Features context. */ diff --git a/build/integration/features/bootstrap/WebDav.php b/build/integration/features/bootstrap/WebDav.php index a832e26ec18..3e63a974fba 100644 --- a/build/integration/features/bootstrap/WebDav.php +++ b/build/integration/features/bootstrap/WebDav.php @@ -80,6 +80,14 @@ trait WebDav { $this->usingOldDavPath = false; } + /** + * @Given /^using new public dav path$/ + */ + public function usingNewPublicDavPath() { + $this->davPath = 'public.php/dav'; + $this->usingOldDavPath = false; + } + public function getDavFilesPath($user) { if ($this->usingOldDavPath === true) { return $this->davPath; @@ -271,6 +279,42 @@ trait WebDav { } /** + * @When Downloading public file :filename + */ + public function downloadingPublicFile(string $filename) { + $token = $this->lastShareData->data->token; + $fullUrl = substr($this->baseUrl, 0, -4) . "public.php/dav/files/$token/$filename"; + + $client = new GClient(); + $options = [ + 'headers' => [ + 'X-Requested-With' => 'XMLHttpRequest', + ] + ]; + + try { + $this->response = $client->request('GET', $fullUrl, $options); + } catch (\GuzzleHttp\Exception\ClientException $e) { + $this->response = $e->getResponse(); + } + } + + /** + * @When Downloading public file :filename without ajax header + */ + public function downloadingPublicFileWithoutHeader(string $filename) { + $token = $this->lastShareData->data->token; + $fullUrl = substr($this->baseUrl, 0, -4) . "public.php/dav/files/$token/$filename"; + + $client = new GClient(); + try { + $this->response = $client->request('GET', $fullUrl); + } catch (\GuzzleHttp\Exception\ClientException $e) { + $this->response = $e->getResponse(); + } + } + + /** * @Then Downloaded content should start with :start * @param int $start * @throws \Exception |