diff options
Diffstat (limited to 'apps/dav/lib/Connector/Sabre/SharesPlugin.php')
-rw-r--r-- | apps/dav/lib/Connector/Sabre/SharesPlugin.php | 147 |
1 files changed, 63 insertions, 84 deletions
diff --git a/apps/dav/lib/Connector/Sabre/SharesPlugin.php b/apps/dav/lib/Connector/Sabre/SharesPlugin.php index 57c91e05a8c..f49e85333f3 100644 --- a/apps/dav/lib/Connector/Sabre/SharesPlugin.php +++ b/apps/dav/lib/Connector/Sabre/SharesPlugin.php @@ -1,39 +1,23 @@ <?php + /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Joas Schilling <coding@schilljs.com> - * @author Julius Härtl <jus@bitgrid.net> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Robin Appelman <robin@icewind.nl> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Tobias Kaminsky <tobias@kaminsky.me> - * @author Vincent Petry <vincent@nextcloud.com> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ namespace OCA\DAV\Connector\Sabre; +use OC\Share20\Exception\BackendError; use OCA\DAV\Connector\Sabre\Node as DavNode; use OCP\Files\Folder; +use OCP\Files\Node; use OCP\Files\NotFoundException; use OCP\IUserSession; +use OCP\Share\IManager; use OCP\Share\IShare; use Sabre\DAV\PropFind; +use Sabre\DAV\Server; +use Sabre\DAV\Tree; /** * Sabre Plugin to provide share-related properties @@ -50,40 +34,19 @@ class SharesPlugin extends \Sabre\DAV\ServerPlugin { * @var \Sabre\DAV\Server */ private $server; - - /** @var \OCP\Share\IManager */ - private $shareManager; - - /** @var \Sabre\DAV\Tree */ - private $tree; - - /** @var string */ - private $userId; - - /** @var \OCP\Files\Folder */ - private $userFolder; + private string $userId; /** @var IShare[][] */ - private $cachedShares = []; - + private array $cachedShares = []; /** @var string[] */ - private $cachedFolders = []; + private array $cachedFolders = []; - /** - * @param \Sabre\DAV\Tree $tree tree - * @param IUserSession $userSession user session - * @param \OCP\Files\Folder $userFolder user home folder - * @param \OCP\Share\IManager $shareManager share manager - */ public function __construct( - \Sabre\DAV\Tree $tree, - IUserSession $userSession, - \OCP\Files\Folder $userFolder, - \OCP\Share\IManager $shareManager + private Tree $tree, + private IUserSession $userSession, + private Folder $userFolder, + private IManager $shareManager, ) { - $this->tree = $tree; - $this->shareManager = $shareManager; - $this->userFolder = $userFolder; $this->userId = $userSession->getUser()->getUID(); } @@ -95,9 +58,9 @@ class SharesPlugin extends \Sabre\DAV\ServerPlugin { * * This method should set up the required event subscriptions. * - * @param \Sabre\DAV\Server $server + * @return void */ - public function initialize(\Sabre\DAV\Server $server) { + public function initialize(Server $server) { $server->xml->namespaceMap[self::NS_OWNCLOUD] = 'oc'; $server->xml->elementMap[self::SHARETYPES_PROPERTYNAME] = ShareTypeList::class; $server->protectedProperties[] = self::SHARETYPES_PROPERTYNAME; @@ -108,10 +71,10 @@ class SharesPlugin extends \Sabre\DAV\ServerPlugin { } /** - * @param \OCP\Files\Node $node + * @param Node $node * @return IShare[] */ - private function getShare(\OCP\Files\Node $node): array { + private function getShare(Node $node): array { $result = []; $requestedShareTypes = [ IShare::TYPE_USER, @@ -122,19 +85,31 @@ class SharesPlugin extends \Sabre\DAV\ServerPlugin { IShare::TYPE_ROOM, IShare::TYPE_CIRCLE, IShare::TYPE_DECK, + IShare::TYPE_SCIENCEMESH, ]; + foreach ($requestedShareTypes as $requestedShareType) { - $shares = $this->shareManager->getSharesBy( + $result = array_merge($result, $this->shareManager->getSharesBy( $this->userId, $requestedShareType, $node, false, -1 - ); - foreach ($shares as $share) { - $result[] = $share; + )); + + // Also check for shares where the user is the recipient + try { + $result = array_merge($result, $this->shareManager->getSharedWith( + $this->userId, + $requestedShareType, + $node, + -1 + )); + } catch (BackendError $e) { + // ignore } } + return $result; } @@ -156,27 +131,29 @@ class SharesPlugin extends \Sabre\DAV\ServerPlugin { */ private function getShares(DavNode $sabreNode): array { if (isset($this->cachedShares[$sabreNode->getId()])) { - $shares = $this->cachedShares[$sabreNode->getId()]; - } else { - [$parentPath,] = \Sabre\Uri\split($sabreNode->getPath()); - if ($parentPath === '') { - $parentPath = '/'; - } - // if we already cached the folder this file is in we know there are no shares for this file - if (array_search($parentPath, $this->cachedFolders) === false) { - try { - $node = $sabreNode->getNode(); - } catch (NotFoundException $e) { - return []; - } - $shares = $this->getShare($node); - $this->cachedShares[$sabreNode->getId()] = $shares; - } else { + return $this->cachedShares[$sabreNode->getId()]; + } + + [$parentPath,] = \Sabre\Uri\split($sabreNode->getPath()); + if ($parentPath === '') { + $parentPath = '/'; + } + + // if we already cached the folder containing this file + // then we already know there are no shares here. + if (array_search($parentPath, $this->cachedFolders) === false) { + try { + $node = $sabreNode->getNode(); + } catch (NotFoundException $e) { return []; } + + $shares = $this->getShare($node); + $this->cachedShares[$sabreNode->getId()] = $shares; + return $shares; } - return $shares; + return []; } /** @@ -187,18 +164,20 @@ class SharesPlugin extends \Sabre\DAV\ServerPlugin { */ public function handleGetProperties( PropFind $propFind, - \Sabre\DAV\INode $sabreNode + \Sabre\DAV\INode $sabreNode, ) { if (!($sabreNode instanceof DavNode)) { return; } - // need prefetch ? + // If the node is a directory and we are requesting share types or sharees + // then we get all the shares in the folder and cache them. + // This is more performant than iterating each files afterwards. if ($sabreNode instanceof Directory && $propFind->getDepth() !== 0 && ( - !is_null($propFind->getStatus(self::SHARETYPES_PROPERTYNAME)) || - !is_null($propFind->getStatus(self::SHAREES_PROPERTYNAME)) + !is_null($propFind->getStatus(self::SHARETYPES_PROPERTYNAME)) + || !is_null($propFind->getStatus(self::SHAREES_PROPERTYNAME)) ) ) { $folderNode = $sabreNode->getNode(); @@ -209,7 +188,7 @@ class SharesPlugin extends \Sabre\DAV\ServerPlugin { } } - $propFind->handle(self::SHARETYPES_PROPERTYNAME, function () use ($sabreNode) { + $propFind->handle(self::SHARETYPES_PROPERTYNAME, function () use ($sabreNode): ShareTypeList { $shares = $this->getShares($sabreNode); $shareTypes = array_unique(array_map(function (IShare $share) { @@ -219,7 +198,7 @@ class SharesPlugin extends \Sabre\DAV\ServerPlugin { return new ShareTypeList($shareTypes); }); - $propFind->handle(self::SHAREES_PROPERTYNAME, function () use ($sabreNode) { + $propFind->handle(self::SHAREES_PROPERTYNAME, function () use ($sabreNode): ShareeList { $shares = $this->getShares($sabreNode); return new ShareeList($shares); |