diff options
Diffstat (limited to 'apps/files_sharing/lib')
3 files changed, 108 insertions, 22 deletions
diff --git a/apps/files_sharing/lib/Controller/ShareAPIController.php b/apps/files_sharing/lib/Controller/ShareAPIController.php index 35a01ccdd61..069cba42bb6 100644 --- a/apps/files_sharing/lib/Controller/ShareAPIController.php +++ b/apps/files_sharing/lib/Controller/ShareAPIController.php @@ -44,6 +44,7 @@ declare(strict_types=1); */ namespace OCA\Files_Sharing\Controller; +use OC\Files\FileInfo; use OCA\Files_Sharing\Exceptions\SharingRightsException; use OCA\Files_Sharing\External\Storage; use OCA\Files\Helper; @@ -469,12 +470,22 @@ class ShareAPIController extends OCSController { $userFolder = $this->rootFolder->getUserFolder($this->currentUser); try { - $path = $userFolder->get($path); + /** @var \OC\Files\Node\Node $node */ + $node = $userFolder->get($path); } catch (NotFoundException $e) { throw new OCSNotFoundException($this->l->t('Wrong path, file/folder does not exist')); } - $share->setNode($path); + // a user can have access to a file through different paths, with differing permissions + // combine all permissions to determine if the user can share this file + $nodes = $userFolder->getById($node->getId()); + foreach ($nodes as $nodeById) { + /** @var FileInfo $fileInfo */ + $fileInfo = $node->getFileInfo(); + $fileInfo['permissions'] |= $nodeById->getPermissions(); + } + + $share->setNode($node); try { $this->lock($share->getNode()); @@ -489,7 +500,7 @@ class ShareAPIController extends OCSController { // Shares always require read permissions $permissions |= Constants::PERMISSION_READ; - if ($path instanceof \OCP\Files\File) { + if ($node instanceof \OCP\Files\File) { // Single file shares should never have delete or create permissions $permissions &= ~Constants::PERMISSION_DELETE; $permissions &= ~Constants::PERMISSION_CREATE; @@ -500,8 +511,8 @@ class ShareAPIController extends OCSController { * We check the permissions via webdav. But the permissions of the mount point * do not equal the share permissions. Here we fix that for federated mounts. */ - if ($path->getStorage()->instanceOfStorage(Storage::class)) { - $permissions &= ~($permissions & ~$path->getPermissions()); + if ($node->getStorage()->instanceOfStorage(Storage::class)) { + $permissions &= ~($permissions & ~$node->getPermissions()); } if ($shareType === IShare::TYPE_USER) { @@ -537,7 +548,7 @@ class ShareAPIController extends OCSController { } // Public upload can only be set for folders - if ($path instanceof \OCP\Files\File) { + if ($node instanceof \OCP\Files\File) { throw new OCSNotFoundException($this->l->t('Public upload is only possible for publicly shared folders')); } @@ -573,7 +584,7 @@ class ShareAPIController extends OCSController { if ($sendPasswordByTalk === 'true') { if (!$this->appManager->isEnabledForUser('spreed')) { - throw new OCSForbiddenException($this->l->t('Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled', [$path->getPath()])); + throw new OCSForbiddenException($this->l->t('Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled', [$node->getPath()])); } $share->setSendPasswordByTalk(true); @@ -590,7 +601,7 @@ class ShareAPIController extends OCSController { } } elseif ($shareType === IShare::TYPE_REMOTE) { if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) { - throw new OCSForbiddenException($this->l->t('Sharing %1$s failed because the back end does not allow shares from type %2$s', [$path->getPath(), $shareType])); + throw new OCSForbiddenException($this->l->t('Sharing %1$s failed because the back end does not allow shares from type %2$s', [$node->getPath(), $shareType])); } if ($shareWith === null) { @@ -609,7 +620,7 @@ class ShareAPIController extends OCSController { } } elseif ($shareType === IShare::TYPE_REMOTE_GROUP) { if (!$this->shareManager->outgoingServer2ServerGroupSharesAllowed()) { - throw new OCSForbiddenException($this->l->t('Sharing %1$s failed because the back end does not allow shares from type %2$s', [$path->getPath(), $shareType])); + throw new OCSForbiddenException($this->l->t('Sharing %1$s failed because the back end does not allow shares from type %2$s', [$node->getPath(), $shareType])); } if ($shareWith === null) { @@ -643,13 +654,13 @@ class ShareAPIController extends OCSController { try { $this->getRoomShareHelper()->createShare($share, $shareWith, $permissions, $expireDate); } catch (QueryException $e) { - throw new OCSForbiddenException($this->l->t('Sharing %s failed because the back end does not support room shares', [$path->getPath()])); + throw new OCSForbiddenException($this->l->t('Sharing %s failed because the back end does not support room shares', [$node->getPath()])); } } elseif ($shareType === IShare::TYPE_DECK) { try { $this->getDeckShareHelper()->createShare($share, $shareWith, $permissions, $expireDate); } catch (QueryException $e) { - throw new OCSForbiddenException($this->l->t('Sharing %s failed because the back end does not support room shares', [$path->getPath()])); + throw new OCSForbiddenException($this->l->t('Sharing %s failed because the back end does not support room shares', [$node->getPath()])); } } else { throw new OCSBadRequestException($this->l->t('Unknown share type')); diff --git a/apps/files_sharing/lib/Migration/Version24000Date20220404142216.php b/apps/files_sharing/lib/Migration/Version24000Date20220404142216.php new file mode 100644 index 00000000000..05176ebdae9 --- /dev/null +++ b/apps/files_sharing/lib/Migration/Version24000Date20220404142216.php @@ -0,0 +1,56 @@ +<?php + +declare(strict_types=1); + +/** + * @copyright Copyright (c) 2022 Côme Chilliet <come.chilliet@nextcloud.com> + * + * @author Côme Chilliet <come.chilliet@nextcloud.com> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * 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 + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCA\Files_Sharing\Migration; + +use Closure; +use OCP\DB\ISchemaWrapper; +use OCP\Migration\IOutput; +use OCP\Migration\SimpleMigrationStep; + +/** + * Auto-generated migration step: Please modify to your needs! + */ +class Version24000Date20220404142216 extends SimpleMigrationStep { + /** + * @param IOutput $output + * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` + * @param array $options + * @return null|ISchemaWrapper + */ + public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper { + /** @var ISchemaWrapper $schema */ + $schema = $schemaClosure(); + + $table = $schema->getTable('share_external'); + $column = $table->getColumn('name'); + if ($column->getLength() < 4000) { + $column->setLength(4000); + return $schema; + } + return null; + } +} diff --git a/apps/files_sharing/lib/SharedStorage.php b/apps/files_sharing/lib/SharedStorage.php index 3ded20eb495..6a342f0bdbf 100644 --- a/apps/files_sharing/lib/SharedStorage.php +++ b/apps/files_sharing/lib/SharedStorage.php @@ -35,13 +35,15 @@ namespace OCA\Files_Sharing; use OC\Files\Cache\FailedCache; use OC\Files\Cache\NullWatcher; use OC\Files\Cache\Watcher; -use OC\Files\Filesystem; +use OCP\Files\Folder; +use OCP\Files\Node; use OC\Files\Storage\FailedStorage; use OC\Files\Storage\Wrapper\PermissionsMask; use OC\User\NoUserException; use OCA\Files_External\Config\ExternalMountPoint; use OCP\Constants; use OCP\Files\Cache\ICacheEntry; +use OCP\Files\IRootFolder; use OCP\Files\NotFoundException; use OCP\Files\Storage\IDisableEncryptionStorage; use OCP\Files\Storage\IStorage; @@ -88,6 +90,11 @@ class SharedStorage extends \OC\Files\Storage\Wrapper\Jail implements ISharedSto /** @var boolean */ private $sharingDisabledForUser; + /** @var ?Folder $ownerUserFolder */ + private $ownerUserFolder = null; + + private string $sourcePath = ''; + public function __construct($arguments) { $this->ownerView = $arguments['ownerView']; $this->logger = \OC::$server->getLogger(); @@ -129,14 +136,26 @@ class SharedStorage extends \OC\Files\Storage\Wrapper\Jail implements ISharedSto } $this->initialized = true; try { - Filesystem::initMountPoints($this->superShare->getShareOwner()); - $storageId = $this->superShare->getNodeCacheEntry() ? $this->superShare->getNodeCacheEntry()->getStorageId() : null; - $sourcePath = $this->ownerView->getPath($this->superShare->getNodeId(), $storageId); - [$this->nonMaskedStorage, $this->rootPath] = $this->ownerView->resolvePath($sourcePath); - $this->storage = new PermissionsMask([ - 'storage' => $this->nonMaskedStorage, - 'mask' => $this->superShare->getPermissions(), - ]); + /** @var IRootFolder $rootFolder */ + $rootFolder = \OC::$server->get(IRootFolder::class); + $this->ownerUserFolder = $rootFolder->getUserFolder($this->superShare->getShareOwner()); + $sourceId = $this->superShare->getNodeId(); + $ownerNodes = $this->ownerUserFolder->getById($sourceId); + /** @var Node|false $ownerNode */ + $ownerNode = current($ownerNodes); + if (!$ownerNode) { + $this->storage = new FailedStorage(['exception' => new NotFoundException("File by id $sourceId not found")]); + $this->cache = new FailedCache(); + $this->rootPath = ''; + } else { + $this->nonMaskedStorage = $ownerNode->getStorage(); + $this->sourcePath = $ownerNode->getPath(); + $this->rootPath = $ownerNode->getInternalPath(); + $this->storage = new PermissionsMask([ + 'storage' => $this->nonMaskedStorage, + 'mask' => $this->superShare->getPermissions(), + ]); + } } catch (NotFoundException $e) { // original file not accessible or deleted, set FailedStorage $this->storage = new FailedStorage(['exception' => $e]); @@ -444,7 +463,7 @@ class SharedStorage extends \OC\Files\Storage\Wrapper\Jail implements ISharedSto $targetStorage->acquireLock($targetInternalPath, $type, $provider); // lock the parent folders of the owner when locking the share as recipient if ($path === '') { - $sourcePath = $this->ownerView->getPath($this->superShare->getNodeId()); + $sourcePath = $this->ownerUserFolder->getRelativePath($this->sourcePath); $this->ownerView->lockFile(dirname($sourcePath), ILockingProvider::LOCK_SHARED, true); } } @@ -460,7 +479,7 @@ class SharedStorage extends \OC\Files\Storage\Wrapper\Jail implements ISharedSto $targetStorage->releaseLock($targetInternalPath, $type, $provider); // unlock the parent folders of the owner when unlocking the share as recipient if ($path === '') { - $sourcePath = $this->ownerView->getPath($this->superShare->getNodeId()); + $sourcePath = $this->ownerUserFolder->getRelativePath($this->sourcePath); $this->ownerView->unlockFile(dirname($sourcePath), ILockingProvider::LOCK_SHARED, true); } } |