Merge pull request #26124 from nextcloud/backport/25533/stable21
[stable21] send share notification instead of erroring on duplicate share
This commit is contained in:
commit
682df0b788
|
@ -488,6 +488,7 @@ return array(
|
||||||
'OCP\\Share\\Events\\ShareCreatedEvent' => $baseDir . '/lib/public/Share/Events/ShareCreatedEvent.php',
|
'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\\ShareDeletedEvent' => $baseDir . '/lib/public/Share/Events/ShareDeletedEvent.php',
|
||||||
'OCP\\Share\\Events\\VerifyMountPointEvent' => $baseDir . '/lib/public/Share/Events/VerifyMountPointEvent.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\\GenericShareException' => $baseDir . '/lib/public/Share/Exceptions/GenericShareException.php',
|
||||||
'OCP\\Share\\Exceptions\\IllegalIDChangeException' => $baseDir . '/lib/public/Share/Exceptions/IllegalIDChangeException.php',
|
'OCP\\Share\\Exceptions\\IllegalIDChangeException' => $baseDir . '/lib/public/Share/Exceptions/IllegalIDChangeException.php',
|
||||||
'OCP\\Share\\Exceptions\\ShareNotFound' => $baseDir . '/lib/public/Share/Exceptions/ShareNotFound.php',
|
'OCP\\Share\\Exceptions\\ShareNotFound' => $baseDir . '/lib/public/Share/Exceptions/ShareNotFound.php',
|
||||||
|
|
|
@ -517,6 +517,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
|
||||||
'OCP\\Share\\Events\\ShareCreatedEvent' => __DIR__ . '/../../..' . '/lib/public/Share/Events/ShareCreatedEvent.php',
|
'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\\ShareDeletedEvent' => __DIR__ . '/../../..' . '/lib/public/Share/Events/ShareDeletedEvent.php',
|
||||||
'OCP\\Share\\Events\\VerifyMountPointEvent' => __DIR__ . '/../../..' . '/lib/public/Share/Events/VerifyMountPointEvent.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\\GenericShareException' => __DIR__ . '/../../..' . '/lib/public/Share/Exceptions/GenericShareException.php',
|
||||||
'OCP\\Share\\Exceptions\\IllegalIDChangeException' => __DIR__ . '/../../..' . '/lib/public/Share/Exceptions/IllegalIDChangeException.php',
|
'OCP\\Share\\Exceptions\\IllegalIDChangeException' => __DIR__ . '/../../..' . '/lib/public/Share/Exceptions/IllegalIDChangeException.php',
|
||||||
'OCP\\Share\\Exceptions\\ShareNotFound' => __DIR__ . '/../../..' . '/lib/public/Share/Exceptions/ShareNotFound.php',
|
'OCP\\Share\\Exceptions\\ShareNotFound' => __DIR__ . '/../../..' . '/lib/public/Share/Exceptions/ShareNotFound.php',
|
||||||
|
|
|
@ -63,6 +63,7 @@ use OCP\Security\Events\ValidatePasswordPolicyEvent;
|
||||||
use OCP\Security\IHasher;
|
use OCP\Security\IHasher;
|
||||||
use OCP\Security\ISecureRandom;
|
use OCP\Security\ISecureRandom;
|
||||||
use OCP\Share;
|
use OCP\Share;
|
||||||
|
use OCP\Share\Exceptions\AlreadySharedException;
|
||||||
use OCP\Share\Exceptions\GenericShareException;
|
use OCP\Share\Exceptions\GenericShareException;
|
||||||
use OCP\Share\Exceptions\ShareNotFound;
|
use OCP\Share\Exceptions\ShareNotFound;
|
||||||
use OCP\Share\IManager;
|
use OCP\Share\IManager;
|
||||||
|
@ -565,7 +566,7 @@ class Manager implements IManager {
|
||||||
|
|
||||||
// Identical share already existst
|
// Identical share already existst
|
||||||
if ($existingShare->getSharedWith() === $share->getSharedWith() && $existingShare->getShareType() === $share->getShareType()) {
|
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
|
// 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());
|
$user = $this->userManager->get($share->getSharedWith());
|
||||||
|
|
||||||
if ($group->inGroup($user) && $existingShare->getShareOwner() !== $share->getShareOwner()) {
|
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()) {
|
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
|
try {
|
||||||
if ($share->getShareType() === IShare::TYPE_USER) {
|
//Verify share type
|
||||||
$this->userCreateChecks($share);
|
if ($share->getShareType() === IShare::TYPE_USER) {
|
||||||
|
$this->userCreateChecks($share);
|
||||||
|
|
||||||
//Verify the expiration date
|
//Verify the expiration date
|
||||||
$share = $this->validateExpirationDateInternal($share);
|
$share = $this->validateExpirationDateInternal($share);
|
||||||
} elseif ($share->getShareType() === IShare::TYPE_GROUP) {
|
} elseif ($share->getShareType() === IShare::TYPE_GROUP) {
|
||||||
$this->groupCreateChecks($share);
|
$this->groupCreateChecks($share);
|
||||||
|
|
||||||
//Verify the expiration date
|
//Verify the expiration date
|
||||||
$share = $this->validateExpirationDateInternal($share);
|
$share = $this->validateExpirationDateInternal($share);
|
||||||
} elseif ($share->getShareType() === IShare::TYPE_LINK) {
|
} elseif ($share->getShareType() === IShare::TYPE_LINK) {
|
||||||
$this->linkCreateChecks($share);
|
$this->linkCreateChecks($share);
|
||||||
$this->setLinkParent($share);
|
$this->setLinkParent($share);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For now ignore a set token.
|
* For now ignore a set token.
|
||||||
*/
|
*/
|
||||||
$share->setToken(
|
$share->setToken(
|
||||||
$this->secureRandom->generate(
|
$this->secureRandom->generate(
|
||||||
\OC\Share\Constants::TOKEN_LENGTH,
|
\OC\Share\Constants::TOKEN_LENGTH,
|
||||||
\OCP\Security\ISecureRandom::CHAR_HUMAN_READABLE
|
\OCP\Security\ISecureRandom::CHAR_HUMAN_READABLE
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
//Verify the expiration date
|
//Verify the expiration date
|
||||||
$share = $this->validateExpirationDate($share);
|
$share = $this->validateExpirationDate($share);
|
||||||
|
|
||||||
//Verify the password
|
//Verify the password
|
||||||
$this->verifyPassword($share->getPassword());
|
$this->verifyPassword($share->getPassword());
|
||||||
|
|
||||||
// If a password is set. Hash it!
|
// If a password is set. Hash it!
|
||||||
if ($share->getPassword() !== null) {
|
if ($share->getPassword() !== null) {
|
||||||
$share->setPassword($this->hasher->hash($share->getPassword()));
|
$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
|
// Cannot share with the owner
|
||||||
if ($share->getShareType() === IShare::TYPE_USER &&
|
if ($share->getShareType() === IShare::TYPE_USER &&
|
||||||
$share->getSharedWith() === $share->getShareOwner()) {
|
$share->getSharedWith() === $share->getShareOwner()) {
|
||||||
throw new \InvalidArgumentException('Can’t share with the share owner');
|
throw new \InvalidArgumentException('Can’t share with the share owner');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate the target
|
// Generate the target
|
||||||
$target = $this->config->getSystemValue('share_folder', '/') .'/'. $share->getNode()->getName();
|
$target = $this->config->getSystemValue('share_folder', '/') . '/' . $share->getNode()->getName();
|
||||||
$target = \OC\Files\Filesystem::normalizePath($target);
|
$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'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$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);
|
$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'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$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);
|
||||||
|
}
|
||||||
|
} 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
|
// Post share event
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue