Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[stable29] fix(dav): Public WebDAV endpoint should allow GET requests #48631

Open
wants to merge 1 commit into
base: stable29
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions apps/dav/appinfo/v2/publicremote.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,15 @@
$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();
Expand Down Expand Up @@ -152,4 +156,4 @@
$server->addPlugin($filesDropPlugin);

// And off we go!
$server->exec();
$server->start();
2 changes: 1 addition & 1 deletion build/integration/config/behat.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ default:
paths:
- "%paths.base%/../dav_features"
contexts:
- FeatureContext:
- DavFeatureContext:
baseUrl: http://localhost:8080/ocs/
admin:
- admin
Expand Down
41 changes: 41 additions & 0 deletions build/integration/dav_features/dav-v2-public.feature
Original file line number Diff line number Diff line change
@@ -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
9 changes: 7 additions & 2 deletions build/integration/features/bootstrap/CommandLineContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -61,8 +62,12 @@ public function maintenanceModeIsDisabled() {
/** @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) {
Expand Down
2 changes: 0 additions & 2 deletions build/integration/features/bootstrap/CommentsContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,6 @@ public function __construct($baseUrl) {
}
}



/**
* get a named entry from response instead of picking a random entry from values
*
Expand Down
23 changes: 23 additions & 0 deletions build/integration/features/bootstrap/DavFeatureContext.php
Original file line number Diff line number Diff line change
@@ -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');
}
}
14 changes: 14 additions & 0 deletions build/integration/features/bootstrap/Download.php
Original file line number Diff line number Diff line change
Expand Up @@ -138,4 +138,18 @@ public function theDownloadedZipFileContainsAFolderNamed($folderName) {
"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'
);
}
}
1 change: 0 additions & 1 deletion build/integration/features/bootstrap/FeatureContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@

require __DIR__ . '/../../vendor/autoload.php';


/**
* Features context.
*/
Expand Down
44 changes: 44 additions & 0 deletions build/integration/features/bootstrap/WebDav.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,14 @@ public function usingNewDavPath() {
$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;
Expand Down Expand Up @@ -270,6 +278,42 @@ public function downloadingFile($fileName) {
}
}

/**
* @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
Expand Down
Loading