aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorKate <26026535+provokateurin@users.noreply.github.com>2024-11-25 14:41:40 +0100
committerGitHub <noreply@github.com>2024-11-25 14:41:40 +0100
commit235b7d7c26930367533f2e845bb2180ba9151608 (patch)
tree26c2c38d2a3a3fe687866fb617647983987d44f3 /lib
parent5088b910ec4a8c003ec22822741f1664eab90175 (diff)
parent7c3a78ad7695eeebe37ed0b15def92599bf43d2f (diff)
downloadnextcloud-server-235b7d7c26930367533f2e845bb2180ba9151608.tar.gz
nextcloud-server-235b7d7c26930367533f2e845bb2180ba9151608.zip
Merge pull request #49073 from nextcloud/feat/files_sharing/co-owner
Diffstat (limited to 'lib')
-rw-r--r--lib/composer/composer/autoload_classmap.php1
-rw-r--r--lib/composer/composer/autoload_static.php1
-rw-r--r--lib/private/Share20/DefaultShareProvider.php4
-rw-r--r--lib/private/Share20/Manager.php74
-rw-r--r--lib/public/Files/Mount/IShareOwnerlessMount.php18
-rw-r--r--lib/public/Share/IManager.php9
6 files changed, 82 insertions, 25 deletions
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php
index cc6b8be326c..5834bfd47b5 100644
--- a/lib/composer/composer/autoload_classmap.php
+++ b/lib/composer/composer/autoload_classmap.php
@@ -409,6 +409,7 @@ return array(
'OCP\\Files\\Mount\\IMountManager' => $baseDir . '/lib/public/Files/Mount/IMountManager.php',
'OCP\\Files\\Mount\\IMountPoint' => $baseDir . '/lib/public/Files/Mount/IMountPoint.php',
'OCP\\Files\\Mount\\IMovableMount' => $baseDir . '/lib/public/Files/Mount/IMovableMount.php',
+ 'OCP\\Files\\Mount\\IShareOwnerlessMount' => $baseDir . '/lib/public/Files/Mount/IShareOwnerlessMount.php',
'OCP\\Files\\Mount\\ISystemMountPoint' => $baseDir . '/lib/public/Files/Mount/ISystemMountPoint.php',
'OCP\\Files\\Node' => $baseDir . '/lib/public/Files/Node.php',
'OCP\\Files\\NotEnoughSpaceException' => $baseDir . '/lib/public/Files/NotEnoughSpaceException.php',
diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php
index 54959bc6b91..e510e80d4c6 100644
--- a/lib/composer/composer/autoload_static.php
+++ b/lib/composer/composer/autoload_static.php
@@ -450,6 +450,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OCP\\Files\\Mount\\IMountManager' => __DIR__ . '/../../..' . '/lib/public/Files/Mount/IMountManager.php',
'OCP\\Files\\Mount\\IMountPoint' => __DIR__ . '/../../..' . '/lib/public/Files/Mount/IMountPoint.php',
'OCP\\Files\\Mount\\IMovableMount' => __DIR__ . '/../../..' . '/lib/public/Files/Mount/IMovableMount.php',
+ 'OCP\\Files\\Mount\\IShareOwnerlessMount' => __DIR__ . '/../../..' . '/lib/public/Files/Mount/IShareOwnerlessMount.php',
'OCP\\Files\\Mount\\ISystemMountPoint' => __DIR__ . '/../../..' . '/lib/public/Files/Mount/ISystemMountPoint.php',
'OCP\\Files\\Node' => __DIR__ . '/../../..' . '/lib/public/Files/Node.php',
'OCP\\Files\\NotEnoughSpaceException' => __DIR__ . '/../../..' . '/lib/public/Files/NotEnoughSpaceException.php',
diff --git a/lib/private/Share20/DefaultShareProvider.php b/lib/private/Share20/DefaultShareProvider.php
index db2734190e4..40fbae541ce 100644
--- a/lib/private/Share20/DefaultShareProvider.php
+++ b/lib/private/Share20/DefaultShareProvider.php
@@ -798,13 +798,15 @@ class DefaultShareProvider implements IShareProviderWithNotification, IShareProv
->andWhere(
$qb->expr()->orX(
$qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USER)),
- $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP))
+ $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)),
+ $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_LINK)),
)
)
->andWhere($qb->expr()->orX(
$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
))
+ ->orderBy('id', 'ASC')
->executeQuery();
$shares = [];
diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php
index 4856c051307..4dadcdbfcd7 100644
--- a/lib/private/Share20/Manager.php
+++ b/lib/private/Share20/Manager.php
@@ -17,6 +17,7 @@ use OCP\Files\File;
use OCP\Files\Folder;
use OCP\Files\IRootFolder;
use OCP\Files\Mount\IMountManager;
+use OCP\Files\Mount\IShareOwnerlessMount;
use OCP\Files\Node;
use OCP\Files\NotFoundException;
use OCP\HintException;
@@ -785,13 +786,13 @@ class Manager implements IManager {
* @throws \InvalidArgumentException
* @throws GenericShareException
*/
- public function updateShare(IShare $share) {
+ public function updateShare(IShare $share, bool $onlyValid = true) {
$expirationDateUpdated = false;
$this->canShare($share);
try {
- $originalShare = $this->getShareById($share->getFullId());
+ $originalShare = $this->getShareById($share->getFullId(), onlyValid: $onlyValid);
} catch (\UnexpectedValueException $e) {
throw new \InvalidArgumentException($this->l->t('Share does not have a full ID'));
}
@@ -1215,23 +1216,32 @@ class Manager implements IManager {
throw new \Exception('non-shallow getSharesInFolder is no longer supported');
}
- return array_reduce($providers, function ($shares, IShareProvider $provider) use ($userId, $node, $reshares) {
- $newShares = $provider->getSharesInFolder($userId, $node, $reshares);
- foreach ($newShares as $fid => $data) {
- if (!isset($shares[$fid])) {
- $shares[$fid] = [];
- }
+ $isOwnerless = $node->getMountPoint() instanceof IShareOwnerlessMount;
- $shares[$fid] = array_merge($shares[$fid], $data);
+ $shares = [];
+ foreach ($providers as $provider) {
+ if ($isOwnerless) {
+ foreach ($node->getDirectoryListing() as $childNode) {
+ $data = $provider->getSharesByPath($childNode);
+ $fid = $childNode->getId();
+ $shares[$fid] ??= [];
+ $shares[$fid] = array_merge($shares[$fid], $data);
+ }
+ } else {
+ foreach ($provider->getSharesInFolder($userId, $node, $reshares) as $fid => $data) {
+ $shares[$fid] ??= [];
+ $shares[$fid] = array_merge($shares[$fid], $data);
+ }
}
- return $shares;
- }, []);
+ }
+
+ return $shares;
}
/**
* @inheritdoc
*/
- public function getSharesBy($userId, $shareType, $path = null, $reshares = false, $limit = 50, $offset = 0) {
+ public function getSharesBy($userId, $shareType, $path = null, $reshares = false, $limit = 50, $offset = 0, bool $onlyValid = true) {
if ($path !== null &&
!($path instanceof \OCP\Files\File) &&
!($path instanceof \OCP\Files\Folder)) {
@@ -1244,7 +1254,11 @@ class Manager implements IManager {
return [];
}
- $shares = $provider->getSharesBy($userId, $shareType, $path, $reshares, $limit, $offset);
+ if ($path?->getMountPoint() instanceof IShareOwnerlessMount) {
+ $shares = array_filter($provider->getSharesByPath($path), static fn (IShare $share) => $share->getShareType() === $shareType);
+ } else {
+ $shares = $provider->getSharesBy($userId, $shareType, $path, $reshares, $limit, $offset);
+ }
/*
* Work around so we don't return expired shares but still follow
@@ -1256,11 +1270,13 @@ class Manager implements IManager {
while (true) {
$added = 0;
foreach ($shares as $share) {
- try {
- $this->checkShare($share);
- } catch (ShareNotFound $e) {
- // Ignore since this basically means the share is deleted
- continue;
+ if ($onlyValid) {
+ try {
+ $this->checkShare($share);
+ } catch (ShareNotFound $e) {
+ // Ignore since this basically means the share is deleted
+ continue;
+ }
}
$added++;
@@ -1288,7 +1304,12 @@ class Manager implements IManager {
$offset += $added;
// Fetch again $limit shares
- $shares = $provider->getSharesBy($userId, $shareType, $path, $reshares, $limit, $offset);
+ if ($path?->getMountPoint() instanceof IShareOwnerlessMount) {
+ // We already fetched all shares, so end here
+ $shares = [];
+ } else {
+ $shares = $provider->getSharesBy($userId, $shareType, $path, $reshares, $limit, $offset);
+ }
// No more shares means we are done
if (empty($shares)) {
@@ -1347,7 +1368,7 @@ class Manager implements IManager {
/**
* @inheritdoc
*/
- public function getShareById($id, $recipient = null) {
+ public function getShareById($id, $recipient = null, bool $onlyValid = true) {
if ($id === null) {
throw new ShareNotFound();
}
@@ -1362,7 +1383,9 @@ class Manager implements IManager {
$share = $provider->getShareById($id, $recipient);
- $this->checkShare($share);
+ if ($onlyValid) {
+ $this->checkShare($share);
+ }
return $share;
}
@@ -1469,6 +1492,15 @@ class Manager implements IManager {
$this->deleteShare($share);
throw new ShareNotFound($this->l->t('The requested share does not exist anymore'));
}
+
+ try {
+ $share->getNode();
+ // Ignore share, file is still accessible
+ } catch (NotFoundException) {
+ // Access lost, but maybe only temporarily, so don't delete the share right away
+ throw new ShareNotFound($this->l->t('The requested share does not exist anymore'));
+ }
+
if ($this->config->getAppValue('files_sharing', 'hide_disabled_user_shares', 'no') === 'yes') {
$uids = array_unique([$share->getShareOwner(),$share->getSharedBy()]);
foreach ($uids as $uid) {
diff --git a/lib/public/Files/Mount/IShareOwnerlessMount.php b/lib/public/Files/Mount/IShareOwnerlessMount.php
new file mode 100644
index 00000000000..b73ee620859
--- /dev/null
+++ b/lib/public/Files/Mount/IShareOwnerlessMount.php
@@ -0,0 +1,18 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCP\Files\Mount;
+
+/**
+ * Denotes that shares created under this mountpoint will be manageable by everyone with share permission.
+ *
+ * @since 31.0.0
+ */
+interface IShareOwnerlessMount {
+}
diff --git a/lib/public/Share/IManager.php b/lib/public/Share/IManager.php
index b07bc8f8051..c3a8494a5ac 100644
--- a/lib/public/Share/IManager.php
+++ b/lib/public/Share/IManager.php
@@ -41,11 +41,12 @@ interface IManager {
* The state can't be changed this way: use acceptShare
*
* @param IShare $share
+ * @param bool $onlyValid Only updates valid shares, invalid shares will be deleted automatically and are not updated
* @return IShare The share object
* @throws \InvalidArgumentException
* @since 9.0.0
*/
- public function updateShare(IShare $share);
+ public function updateShare(IShare $share, bool $onlyValid = true);
/**
* Accept a share.
@@ -127,10 +128,11 @@ interface IManager {
* @param bool $reshares
* @param int $limit The maximum number of returned results, -1 for all results
* @param int $offset
+ * @param bool $onlyValid Only returns valid shares, invalid shares will be deleted automatically and are not returned
* @return IShare[]
* @since 9.0.0
*/
- public function getSharesBy($userId, $shareType, $path = null, $reshares = false, $limit = 50, $offset = 0);
+ public function getSharesBy($userId, $shareType, $path = null, $reshares = false, $limit = 50, $offset = 0, bool $onlyValid = true);
/**
* Get shares shared with $user.
@@ -168,11 +170,12 @@ interface IManager {
*
* @param string $id
* @param string|null $recipient userID of the recipient
+ * @param bool $onlyValid Only returns valid shares, invalid shares will be deleted automatically and are not returned
* @return IShare
* @throws ShareNotFound
* @since 9.0.0
*/
- public function getShareById($id, $recipient = null);
+ public function getShareById($id, $recipient = null, bool $onlyValid = true);
/**
* Get the share by token possible with password