summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorMorris Jobke <hey@morrisjobke.de>2021-03-19 09:18:49 +0100
committerGitHub <noreply@github.com>2021-03-19 09:18:49 +0100
commit682df0b78896771ffbfe1a5a4fcba07fece9aa53 (patch)
tree060314ac32948a23c939589ccde75983862feca6 /lib
parent942b40583c64173f55b5d5910a5a86bbed4bbd34 (diff)
parentf2a35cd3f87685833b463e993365fc6bf82b4ba8 (diff)
downloadnextcloud-server-682df0b78896771ffbfe1a5a4fcba07fece9aa53.tar.gz
nextcloud-server-682df0b78896771ffbfe1a5a4fcba07fece9aa53.zip
Merge pull request #26124 from nextcloud/backport/25533/stable21
[stable21] send share notification instead of erroring on duplicate share
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/Manager.php132
-rw-r--r--lib/public/Share/Exceptions/AlreadySharedException.php50
4 files changed, 121 insertions, 63 deletions
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php
index fe24e817087..756414a6c42 100644
--- a/lib/composer/composer/autoload_classmap.php
+++ b/lib/composer/composer/autoload_classmap.php
@@ -488,6 +488,7 @@ return array(
'OCP\\Share\\Events\\ShareCreatedEvent' => $baseDir . '/lib/public/Share/Events/ShareCreatedEvent.php',
'OCP\\Share\\Events\\ShareDeletedEvent' => $baseDir . '/lib/public/Share/Events/ShareDeletedEvent.php',
'OCP\\Share\\Events\\VerifyMountPointEvent' => $baseDir . '/lib/public/Share/Events/VerifyMountPointEvent.php',
+ 'OCP\\Share\\Exceptions\\AlreadySharedException' => $baseDir . '/lib/public/Share/Exceptions/AlreadySharedException.php',
'OCP\\Share\\Exceptions\\GenericShareException' => $baseDir . '/lib/public/Share/Exceptions/GenericShareException.php',
'OCP\\Share\\Exceptions\\IllegalIDChangeException' => $baseDir . '/lib/public/Share/Exceptions/IllegalIDChangeException.php',
'OCP\\Share\\Exceptions\\ShareNotFound' => $baseDir . '/lib/public/Share/Exceptions/ShareNotFound.php',
diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php
index 1827ac55d42..7c7243776f8 100644
--- a/lib/composer/composer/autoload_static.php
+++ b/lib/composer/composer/autoload_static.php
@@ -517,6 +517,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OCP\\Share\\Events\\ShareCreatedEvent' => __DIR__ . '/../../..' . '/lib/public/Share/Events/ShareCreatedEvent.php',
'OCP\\Share\\Events\\ShareDeletedEvent' => __DIR__ . '/../../..' . '/lib/public/Share/Events/ShareDeletedEvent.php',
'OCP\\Share\\Events\\VerifyMountPointEvent' => __DIR__ . '/../../..' . '/lib/public/Share/Events/VerifyMountPointEvent.php',
+ 'OCP\\Share\\Exceptions\\AlreadySharedException' => __DIR__ . '/../../..' . '/lib/public/Share/Exceptions/AlreadySharedException.php',
'OCP\\Share\\Exceptions\\GenericShareException' => __DIR__ . '/../../..' . '/lib/public/Share/Exceptions/GenericShareException.php',
'OCP\\Share\\Exceptions\\IllegalIDChangeException' => __DIR__ . '/../../..' . '/lib/public/Share/Exceptions/IllegalIDChangeException.php',
'OCP\\Share\\Exceptions\\ShareNotFound' => __DIR__ . '/../../..' . '/lib/public/Share/Exceptions/ShareNotFound.php',
diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php
index d7e1d053519..d45a376b719 100644
--- a/lib/private/Share20/Manager.php
+++ b/lib/private/Share20/Manager.php
@@ -63,6 +63,7 @@ use OCP\Security\Events\ValidatePasswordPolicyEvent;
use OCP\Security\IHasher;
use OCP\Security\ISecureRandom;
use OCP\Share;
+use OCP\Share\Exceptions\AlreadySharedException;
use OCP\Share\Exceptions\GenericShareException;
use OCP\Share\Exceptions\ShareNotFound;
use OCP\Share\IManager;
@@ -565,7 +566,7 @@ class Manager implements IManager {
// Identical share already existst
if ($existingShare->getSharedWith() === $share->getSharedWith() && $existingShare->getShareType() === $share->getShareType()) {
- throw new \Exception('Path is already shared with this user');
+ throw new AlreadySharedException('Path is already shared with this user', $existingShare);
}
// The share is already shared with this user via a group share
@@ -575,7 +576,7 @@ class Manager implements IManager {
$user = $this->userManager->get($share->getSharedWith());
if ($group->inGroup($user) && $existingShare->getShareOwner() !== $share->getShareOwner()) {
- throw new \Exception('Path is already shared with this user');
+ throw new AlreadySharedException('Path is already shared with this user', $existingShare);
}
}
}
@@ -620,7 +621,7 @@ class Manager implements IManager {
}
if ($existingShare->getSharedWith() === $share->getSharedWith() && $existingShare->getShareType() === $share->getShareType()) {
- throw new \Exception('Path is already shared with this group');
+ throw new AlreadySharedException('Path is already shared with this group', $existingShare);
}
}
}
@@ -734,77 +735,82 @@ class Manager implements IManager {
}
}
- //Verify share type
- if ($share->getShareType() === IShare::TYPE_USER) {
- $this->userCreateChecks($share);
-
- //Verify the expiration date
- $share = $this->validateExpirationDateInternal($share);
- } elseif ($share->getShareType() === IShare::TYPE_GROUP) {
- $this->groupCreateChecks($share);
+ try {
+ //Verify share type
+ if ($share->getShareType() === IShare::TYPE_USER) {
+ $this->userCreateChecks($share);
- //Verify the expiration date
- $share = $this->validateExpirationDateInternal($share);
- } elseif ($share->getShareType() === IShare::TYPE_LINK) {
- $this->linkCreateChecks($share);
- $this->setLinkParent($share);
+ //Verify the expiration date
+ $share = $this->validateExpirationDateInternal($share);
+ } elseif ($share->getShareType() === IShare::TYPE_GROUP) {
+ $this->groupCreateChecks($share);
- /*
- * For now ignore a set token.
- */
- $share->setToken(
- $this->secureRandom->generate(
- \OC\Share\Constants::TOKEN_LENGTH,
- \OCP\Security\ISecureRandom::CHAR_HUMAN_READABLE
- )
- );
+ //Verify the expiration date
+ $share = $this->validateExpirationDateInternal($share);
+ } elseif ($share->getShareType() === IShare::TYPE_LINK) {
+ $this->linkCreateChecks($share);
+ $this->setLinkParent($share);
+
+ /*
+ * For now ignore a set token.
+ */
+ $share->setToken(
+ $this->secureRandom->generate(
+ \OC\Share\Constants::TOKEN_LENGTH,
+ \OCP\Security\ISecureRandom::CHAR_HUMAN_READABLE
+ )
+ );
- //Verify the expiration date
- $share = $this->validateExpirationDate($share);
+ //Verify the expiration date
+ $share = $this->validateExpirationDate($share);
- //Verify the password
- $this->verifyPassword($share->getPassword());
+ //Verify the password
+ $this->verifyPassword($share->getPassword());
- // If a password is set. Hash it!
- if ($share->getPassword() !== null) {
- $share->setPassword($this->hasher->hash($share->getPassword()));
+ // If a password is set. Hash it!
+ if ($share->getPassword() !== null) {
+ $share->setPassword($this->hasher->hash($share->getPassword()));
+ }
+ } elseif ($share->getShareType() === IShare::TYPE_EMAIL) {
+ $share->setToken(
+ $this->secureRandom->generate(
+ \OC\Share\Constants::TOKEN_LENGTH,
+ \OCP\Security\ISecureRandom::CHAR_HUMAN_READABLE
+ )
+ );
}
- } elseif ($share->getShareType() === IShare::TYPE_EMAIL) {
- $share->setToken(
- $this->secureRandom->generate(
- \OC\Share\Constants::TOKEN_LENGTH,
- \OCP\Security\ISecureRandom::CHAR_HUMAN_READABLE
- )
- );
- }
- // Cannot share with the owner
- if ($share->getShareType() === IShare::TYPE_USER &&
- $share->getSharedWith() === $share->getShareOwner()) {
- throw new \InvalidArgumentException('Can’t share with the share owner');
- }
+ // Cannot share with the owner
+ if ($share->getShareType() === IShare::TYPE_USER &&
+ $share->getSharedWith() === $share->getShareOwner()) {
+ throw new \InvalidArgumentException('Can’t share with the share owner');
+ }
- // Generate the target
- $target = $this->config->getSystemValue('share_folder', '/') .'/'. $share->getNode()->getName();
- $target = \OC\Files\Filesystem::normalizePath($target);
- $share->setTarget($target);
+ // Generate the target
+ $target = $this->config->getSystemValue('share_folder', '/') . '/' . $share->getNode()->getName();
+ $target = \OC\Files\Filesystem::normalizePath($target);
+ $share->setTarget($target);
- // Pre share event
- $event = new GenericEvent($share);
- $this->legacyDispatcher->dispatch('OCP\Share::preShare', $event);
- if ($event->isPropagationStopped() && $event->hasArgument('error')) {
- throw new \Exception($event->getArgument('error'));
- }
+ // Pre share event
+ $event = new GenericEvent($share);
+ $this->legacyDispatcher->dispatch('OCP\Share::preShare', $event);
+ if ($event->isPropagationStopped() && $event->hasArgument('error')) {
+ throw new \Exception($event->getArgument('error'));
+ }
- $oldShare = $share;
- $provider = $this->factory->getProviderForType($share->getShareType());
- $share = $provider->create($share);
- //reuse the node we already have
- $share->setNode($oldShare->getNode());
+ $oldShare = $share;
+ $provider = $this->factory->getProviderForType($share->getShareType());
+ $share = $provider->create($share);
+ //reuse the node we already have
+ $share->setNode($oldShare->getNode());
- // Reset the target if it is null for the new share
- if ($share->getTarget() === '') {
- $share->setTarget($target);
+ // Reset the target if it is null for the new share
+ if ($share->getTarget() === '') {
+ $share->setTarget($target);
+ }
+ } catch (AlreadySharedException $e) {
+ // if a share for the same target already exists, dont create a new one, but do trigger the hooks and notifications again
+ $share = $e->getExistingShare();
}
// Post share event
diff --git a/lib/public/Share/Exceptions/AlreadySharedException.php b/lib/public/Share/Exceptions/AlreadySharedException.php
new file mode 100644
index 00000000000..2f8b9257387
--- /dev/null
+++ b/lib/public/Share/Exceptions/AlreadySharedException.php
@@ -0,0 +1,50 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2021 Robin Appelman <robin@icewind.nl>
+ *
+ * @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 OCP\Share\Exceptions;
+
+use OCP\Share\IShare;
+
+/**
+ * @since 22.0.0
+ */
+class AlreadySharedException extends GenericShareException {
+ /** @var IShare */
+ private $existingShare;
+
+ /**
+ * @since 22.0.0
+ */
+ public function __construct(string $message, IShare $existingShare) {
+ parent::__construct($message);
+
+ $this->existingShare = $existingShare;
+ }
+
+ /**
+ * @since 22.0.0
+ */
+ public function getExistingShare(): IShare {
+ return $this->existingShare;
+ }
+}