From c28da417fd69de8a038483bc0751fbf36655c2b2 Mon Sep 17 00:00:00 2001 From: Ferdinand Thiessen Date: Tue, 4 Aug 2026 21:59:43 +0200 Subject: [PATCH] test(sharing): add tests to ensure public preview endpoint works as expected This is a regression test as we received multiple invalid requests, which turned out to be duplicated for the bug fixed already years ago with: https://github.com/nextcloud/server/pull/35057 Signed-off-by: Ferdinand Thiessen --- .../features/bootstrap/Sharing.php | 85 +++++++++++++++++++ .../sharing-public-preview.feature | 42 +++++++++ 2 files changed, 127 insertions(+) create mode 100644 build/integration/sharing_features/sharing-public-preview.feature diff --git a/build/integration/features/bootstrap/Sharing.php b/build/integration/features/bootstrap/Sharing.php index 6420b2218fce3..69fbdd29dc454 100644 --- a/build/integration/features/bootstrap/Sharing.php +++ b/build/integration/features/bootstrap/Sharing.php @@ -7,6 +7,8 @@ */ use Behat\Gherkin\Node\TableNode; use GuzzleHttp\Client; +use GuzzleHttp\Exception\ClientException; +use GuzzleHttp\Exception\ServerException; use OCA\Files_Sharing\MountProvider; use PHPUnit\Framework\Assert; use Psr\Http\Message\ResponseInterface; @@ -177,6 +179,89 @@ public function lastShareWithPasswordCanBeDownloaded($password) { $this->checkDownload($fullUrl, ['', $password], 'text/plain'); } + /** + * Get the token of the last created share + */ + private function getLastShareToken(): string { + if (count($this->lastShareData->data->element) > 0) { + return (string)$this->lastShareData->data[0]->token; + } + + return (string)$this->lastShareData->data->token; + } + + /** + * Authenticate the current session against a password protected link share, + * the same way a browser does it using the public share authentication page. + * + * @Given /^authenticating to the last public share with password "([^"]*)"$/ + */ + public function authenticatingToTheLastPublicShareWithPassword(string $password): void { + $token = $this->getLastShareToken(); + $authUrl = substr($this->baseUrl, 0, -4) . "index.php/s/$token/authenticate/showShare"; + + $client = new Client(); + + // Load the authentication page to get a session and the CSRF token + $response = $client->get($authUrl, ['cookies' => $this->cookieJar]); + $this->extracRequestTokenFromResponse($response); + + $this->response = $client->post( + $authUrl, + [ + 'cookies' => $this->cookieJar, + 'allow_redirects' => ['track_redirects' => true], + 'form_params' => [ + 'password' => $password, + 'requesttoken' => $this->requestToken, + ], + ] + ); + + // On success the authentication redirects to the share itself, + // on failure the authentication page is rendered again without any redirect. + Assert::assertEquals(200, $this->response->getStatusCode()); + Assert::assertStringContainsString( + "index.php/s/$token", + $this->response->getHeaderLine('X-Guzzle-Redirect-History'), + 'Authenticating to the share did not redirect to the share' + ); + } + + /** + * @When /^getting the public preview of the last share for file "([^"]*)"$/ + */ + public function gettingThePublicPreviewOfTheLastShare(string $file): void { + $token = $this->getLastShareToken(); + $fullUrl = substr($this->baseUrl, 0, -4) . "index.php/apps/files_sharing/publicpreview/$token"; + + $client = new Client(); + try { + $this->response = $client->get( + $fullUrl, + [ + 'cookies' => $this->cookieJar, + 'query' => [ + 'file' => $file, + 'x' => 64, + 'y' => 64, + ], + ] + ); + } catch (ClientException|ServerException $e) { + $this->response = $e->getResponse(); + } + } + + /** + * @Then /^the response should be an image$/ + */ + public function theResponseShouldBeAnImage(): void { + $finfo = new finfo; + $mimeType = $finfo->buffer((string)$this->response->getBody(), FILEINFO_MIME_TYPE); + Assert::assertStringStartsWith('image/', $mimeType, "Expected an image but got '$mimeType'"); + } + private function checkDownload($url, $auth = null, $mimeType = null) { if ($auth !== null) { $options['auth'] = $auth; diff --git a/build/integration/sharing_features/sharing-public-preview.feature b/build/integration/sharing_features/sharing-public-preview.feature new file mode 100644 index 0000000000000..576bafca72bb2 --- /dev/null +++ b/build/integration/sharing_features/sharing-public-preview.feature @@ -0,0 +1,42 @@ +# SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later +Feature: sharing-public-preview + Background: + Given using api version "1" + And using new dav path + And user "user0" exists + And As an "user0" + And User "user0" created a folder "/preview-share" + And User "user0" uploads file "data/green-square-256.png" to "/preview-share/image.png" + + Scenario: Getting the public preview of an image on a link share without password + Given as "user0" creating a share with + | path | preview-share | + | shareType | 3 | + | permissions | 1 | + And the OCS status code should be "100" + When getting the public preview of the last share for file "/image.png" + Then the HTTP status code should be "200" + And the response should be an image + + Scenario: Getting the public preview of an image on a password protected link share after authenticating + Given as "user0" creating a share with + | path | preview-share | + | shareType | 3 | + | permissions | 1 | + | password | publicpw | + And the OCS status code should be "100" + And authenticating to the last public share with password "publicpw" + When getting the public preview of the last share for file "/image.png" + Then the HTTP status code should be "200" + And the response should be an image + + Scenario: Getting the public preview of an image on a password protected link share is not possible without authenticating + Given as "user0" creating a share with + | path | preview-share | + | shareType | 3 | + | permissions | 1 | + | password | publicpw | + And the OCS status code should be "100" + When getting the public preview of the last share for file "/image.png" + Then the HTTP status code should be "404"