Skip to content

Commit

Permalink
Merge pull request #43865 from nextcloud/backport/43859/stable24
Browse files Browse the repository at this point in the history
  • Loading branch information
skjnldsv authored Feb 28, 2024
2 parents d7cc59b + 06c2af4 commit 6be0289
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 14 deletions.
2 changes: 1 addition & 1 deletion apps/dav/lib/Connector/Sabre/ServerFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ public function createServer($baseUri,

// Allow view-only plugin for webdav requests
$server->addPlugin(new ViewOnlyPlugin(
$this->psrLogger
$userFolder
));

if ($this->userSession->isLoggedIn()) {
Expand Down
24 changes: 18 additions & 6 deletions apps/dav/lib/DAV/ViewOnlyPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,24 @@
use OCA\DAV\Connector\Sabre\Exception\Forbidden;
use OCA\DAV\Connector\Sabre\File as DavFile;
use OCA\Files_Versions\Sabre\VersionFile;
use OCP\Files\Folder;
use OCP\Files\NotFoundException;
use Psr\Log\LoggerInterface;
use Sabre\DAV\Exception\NotFound;
use Sabre\DAV\Server;
use Sabre\DAV\ServerPlugin;
use Sabre\HTTP\RequestInterface;
use Sabre\DAV\Exception\NotFound;

/**
* Sabre plugin for restricting file share receiver download:
*/
class ViewOnlyPlugin extends ServerPlugin {
private ?Server $server = null;
private LoggerInterface $logger;
private ?Folder $userFolder;

public function __construct(LoggerInterface $logger) {
$this->logger = $logger;
public function __construct(
?Folder $userFolder
) {
$this->userFolder = $userFolder;
}

/**
Expand Down Expand Up @@ -74,8 +76,18 @@ public function checkViewOnly(RequestInterface $request): bool {
if ($davNode instanceof DavFile) {
// Restrict view-only to nodes which are shared
$node = $davNode->getNode();
} else if ($davNode instanceof VersionFile) {
} elseif ($davNode instanceof VersionFile) {
$node = $davNode->getVersion()->getSourceFile();
$currentUserId = $this->userFolder->getOwner()->getUID();
// The version source file is relative to the owner storage.
// But we need the node from the current user perspective.
if ($node->getOwner()->getUID() !== $currentUserId) {
$nodes = $this->userFolder->getById($node->getId());
$node = array_pop($nodes);
if (!$node) {
throw new NotFoundException("Version file not accessible by current user");
}
}
} else {
return true;
}
Expand Down
10 changes: 5 additions & 5 deletions apps/dav/lib/Server.php
Original file line number Diff line number Diff line change
Expand Up @@ -230,11 +230,6 @@ public function __construct(IRequest $request, string $baseUri) {
$this->server->addPlugin(new FakeLockerPlugin());
}

// Allow view-only plugin for webdav requests
$this->server->addPlugin(new ViewOnlyPlugin(
\OC::$server->get(LoggerInterface::class)
));

if (BrowserErrorPagePlugin::isBrowserRequest($request)) {
$this->server->addPlugin(new BrowserErrorPagePlugin());
}
Expand All @@ -244,6 +239,11 @@ public function __construct(IRequest $request, string $baseUri) {

// wait with registering these until auth is handled and the filesystem is setup
$this->server->on('beforeMethod:*', function () use ($root, $lazySearchBackend) {
// Allow view-only plugin for webdav requests
$this->server->addPlugin(new ViewOnlyPlugin(
\OC::$server->getUserFolder(),
));

// custom properties plugin must be the last one
$userSession = \OC::$server->getUserSession();
$user = $userSession->getUser();
Expand Down
28 changes: 26 additions & 2 deletions apps/dav/tests/unit/DAV/ViewOnlyPluginTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@
use OCA\Files_Versions\Versions\IVersion;
use OCA\Files_Versions\Sabre\VersionFile;
use OCP\Files\File;
use OCP\Files\Folder;
use OCP\Files\Storage\IStorage;
use OCP\IUser;
use OCP\Share\IAttributes;
use OCP\Share\IShare;
use Psr\Log\LoggerInterface;
use Sabre\DAV\Server;
use Sabre\DAV\Tree;
use Test\TestCase;
Expand All @@ -43,10 +44,13 @@ class ViewOnlyPluginTest extends TestCase {
private $tree;
/** @var RequestInterface | \PHPUnit\Framework\MockObject\MockObject */
private $request;
/** @var Folder | \PHPUnit\Framework\MockObject\MockObject */
private $userFolder;

public function setUp(): void {
$this->userFolder = $this->createMock(Folder::class);
$this->plugin = new ViewOnlyPlugin(
$this->createMock(LoggerInterface::class)
$this->userFolder,
);
$this->request = $this->createMock(RequestInterface::class);
$this->tree = $this->createMock(Tree::class);
Expand Down Expand Up @@ -111,6 +115,26 @@ public function testCanGet(bool $isVersion, ?bool $attrEnabled, bool $expectCanD
$davNode->expects($this->once())
->method('getVersion')
->willReturn($version);

$currentUser = $this->createMock(IUser::class);
$currentUser->expects($this->once())
->method('getUID')
->willReturn('alice');
$nodeInfo->expects($this->once())
->method('getOwner')
->willReturn($currentUser);

$nodeInfo = $this->createMock(File::class);
$owner = $this->createMock(IUser::class);
$owner->expects($this->once())
->method('getUID')
->willReturn('bob');
$this->userFolder->expects($this->once())
->method('getById')
->willReturn([$nodeInfo]);
$this->userFolder->expects($this->once())
->method('getOwner')
->willReturn($owner);
} else {
$davPath = 'files/path/to/file.odt';
$davNode = $this->createMock(DavFile::class);
Expand Down
1 change: 1 addition & 0 deletions apps/dav/tests/unit/ServerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public function test($uri, array $plugins) {
/** @var IRequest | \PHPUnit\Framework\MockObject\MockObject $r */
$r = $this->createMock(IRequest::class);
$r->expects($this->any())->method('getRequestUri')->willReturn($uri);
$this->loginAsUser('admin');
$s = new Server($r, '/');
$this->assertNotNull($s->server);
foreach ($plugins as $plugin) {
Expand Down

0 comments on commit 6be0289

Please sign in to comment.