Add API to undelete delete group shares
When a group share is deleted we keep track of this in the DB. Right now it is only possible for a recipient to get back the share by asking the sharer to delete it and to share it again. This doesn't scale. This endpoint makes it possible to get back the share. Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl>
This commit is contained in:
parent
86d9528bc9
commit
d805959e81
|
@ -38,6 +38,7 @@ use OCP\IConfig;
|
||||||
use OCP\IL10N;
|
use OCP\IL10N;
|
||||||
use OCP\ILogger;
|
use OCP\ILogger;
|
||||||
use OCP\IUserManager;
|
use OCP\IUserManager;
|
||||||
|
use OCP\Share\Exceptions\GenericShareException;
|
||||||
use OCP\Share\IShare;
|
use OCP\Share\IShare;
|
||||||
use OCP\Share\IShareProvider;
|
use OCP\Share\IShareProvider;
|
||||||
use OC\Share20\Exception\InvalidShare;
|
use OC\Share20\Exception\InvalidShare;
|
||||||
|
@ -585,6 +586,10 @@ class FederatedShareProvider implements IShareProvider {
|
||||||
// TODO move this code over to this app
|
// TODO move this code over to this app
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function restore(IShare $share, string $recipient): IShare {
|
||||||
|
throw new GenericShareException('not implemented');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public function getSharesInFolder($userId, Folder $node, $reshares) {
|
public function getSharesInFolder($userId, Folder $node, $reshares) {
|
||||||
$qb = $this->dbConnection->getQueryBuilder();
|
$qb = $this->dbConnection->getQueryBuilder();
|
||||||
|
|
|
@ -73,6 +73,19 @@ return [
|
||||||
'url' => '/api/v1/shares/{id}',
|
'url' => '/api/v1/shares/{id}',
|
||||||
'verb' => 'DELETE',
|
'verb' => 'DELETE',
|
||||||
],
|
],
|
||||||
|
/*
|
||||||
|
* Deleted Shares
|
||||||
|
*/
|
||||||
|
[
|
||||||
|
'name' => 'DeletedShareAPI#index',
|
||||||
|
'url' => '/api/v1/deletedshares',
|
||||||
|
'verb' => 'GET',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'DeletedShareAPI#undelete',
|
||||||
|
'url' => '/api/v1/deletedshares/{id}',
|
||||||
|
'verb' => 'POST',
|
||||||
|
],
|
||||||
/*
|
/*
|
||||||
* OCS Sharee API
|
* OCS Sharee API
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -22,6 +22,7 @@ return array(
|
||||||
'OCA\\Files_Sharing\\Capabilities' => $baseDir . '/../lib/Capabilities.php',
|
'OCA\\Files_Sharing\\Capabilities' => $baseDir . '/../lib/Capabilities.php',
|
||||||
'OCA\\Files_Sharing\\Collaboration\\ShareRecipientSorter' => $baseDir . '/../lib/Collaboration/ShareRecipientSorter.php',
|
'OCA\\Files_Sharing\\Collaboration\\ShareRecipientSorter' => $baseDir . '/../lib/Collaboration/ShareRecipientSorter.php',
|
||||||
'OCA\\Files_Sharing\\Command\\CleanupRemoteStorages' => $baseDir . '/../lib/Command/CleanupRemoteStorages.php',
|
'OCA\\Files_Sharing\\Command\\CleanupRemoteStorages' => $baseDir . '/../lib/Command/CleanupRemoteStorages.php',
|
||||||
|
'OCA\\Files_Sharing\\Controller\\DeletedShareAPIController' => $baseDir . '/../lib/Controller/DeletedShareAPIController.php',
|
||||||
'OCA\\Files_Sharing\\Controller\\ExternalSharesController' => $baseDir . '/../lib/Controller/ExternalSharesController.php',
|
'OCA\\Files_Sharing\\Controller\\ExternalSharesController' => $baseDir . '/../lib/Controller/ExternalSharesController.php',
|
||||||
'OCA\\Files_Sharing\\Controller\\PublicPreviewController' => $baseDir . '/../lib/Controller/PublicPreviewController.php',
|
'OCA\\Files_Sharing\\Controller\\PublicPreviewController' => $baseDir . '/../lib/Controller/PublicPreviewController.php',
|
||||||
'OCA\\Files_Sharing\\Controller\\RemoteController' => $baseDir . '/../lib/Controller/RemoteController.php',
|
'OCA\\Files_Sharing\\Controller\\RemoteController' => $baseDir . '/../lib/Controller/RemoteController.php',
|
||||||
|
|
|
@ -37,6 +37,7 @@ class ComposerStaticInitFiles_Sharing
|
||||||
'OCA\\Files_Sharing\\Capabilities' => __DIR__ . '/..' . '/../lib/Capabilities.php',
|
'OCA\\Files_Sharing\\Capabilities' => __DIR__ . '/..' . '/../lib/Capabilities.php',
|
||||||
'OCA\\Files_Sharing\\Collaboration\\ShareRecipientSorter' => __DIR__ . '/..' . '/../lib/Collaboration/ShareRecipientSorter.php',
|
'OCA\\Files_Sharing\\Collaboration\\ShareRecipientSorter' => __DIR__ . '/..' . '/../lib/Collaboration/ShareRecipientSorter.php',
|
||||||
'OCA\\Files_Sharing\\Command\\CleanupRemoteStorages' => __DIR__ . '/..' . '/../lib/Command/CleanupRemoteStorages.php',
|
'OCA\\Files_Sharing\\Command\\CleanupRemoteStorages' => __DIR__ . '/..' . '/../lib/Command/CleanupRemoteStorages.php',
|
||||||
|
'OCA\\Files_Sharing\\Controller\\DeletedShareAPIController' => __DIR__ . '/..' . '/../lib/Controller/DeletedShareAPIController.php',
|
||||||
'OCA\\Files_Sharing\\Controller\\ExternalSharesController' => __DIR__ . '/..' . '/../lib/Controller/ExternalSharesController.php',
|
'OCA\\Files_Sharing\\Controller\\ExternalSharesController' => __DIR__ . '/..' . '/../lib/Controller/ExternalSharesController.php',
|
||||||
'OCA\\Files_Sharing\\Controller\\PublicPreviewController' => __DIR__ . '/..' . '/../lib/Controller/PublicPreviewController.php',
|
'OCA\\Files_Sharing\\Controller\\PublicPreviewController' => __DIR__ . '/..' . '/../lib/Controller/PublicPreviewController.php',
|
||||||
'OCA\\Files_Sharing\\Controller\\RemoteController' => __DIR__ . '/..' . '/../lib/Controller/RemoteController.php',
|
'OCA\\Files_Sharing\\Controller\\RemoteController' => __DIR__ . '/..' . '/../lib/Controller/RemoteController.php',
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
/**
|
||||||
|
* @Copyright 2018, Roeland Jago Douma <roeland@famdouma.nl>
|
||||||
|
* @Copyright 2018, John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
|
||||||
|
*
|
||||||
|
* @author John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
|
||||||
|
* @author Roeland Jago Douma <roeland@famdouma.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 OCA\Files_Sharing\Controller;
|
||||||
|
|
||||||
|
use OCP\AppFramework\Http\DataResponse;
|
||||||
|
use OCP\AppFramework\OCS\OCSException;
|
||||||
|
use OCP\AppFramework\OCS\OCSNotFoundException;
|
||||||
|
use OCP\AppFramework\OCSController;
|
||||||
|
use OCP\IRequest;
|
||||||
|
use OCP\IUserManager;
|
||||||
|
use OCP\Share\Exceptions\GenericShareException;
|
||||||
|
use OCP\Share\Exceptions\ShareNotFound;
|
||||||
|
use OCP\Share\IManager as ShareManager;
|
||||||
|
use OCP\Share\IShare;
|
||||||
|
|
||||||
|
class DeletedShareAPIController extends OCSController {
|
||||||
|
|
||||||
|
/** @var ShareManager */
|
||||||
|
private $shareManager;
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
private $userId;
|
||||||
|
|
||||||
|
/** @var IUserManager */
|
||||||
|
private $userManager;
|
||||||
|
|
||||||
|
public function __construct(string $appName,
|
||||||
|
IRequest $request,
|
||||||
|
ShareManager $shareManager,
|
||||||
|
string $UserId,
|
||||||
|
IUserManager $userManager) {
|
||||||
|
parent::__construct($appName, $request);
|
||||||
|
|
||||||
|
$this->shareManager = $shareManager;
|
||||||
|
$this->userId = $UserId;
|
||||||
|
$this->userManager = $userManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function formatShare(IShare $share): array {
|
||||||
|
return [
|
||||||
|
'id' => $share->getFullId(),
|
||||||
|
'uid_owner' => $share->getShareOwner(),
|
||||||
|
'displayname_owner' => $this->userManager->get($share->getShareOwner())->getDisplayName(),
|
||||||
|
'path' => $share->getTarget(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @NoAdminRequired
|
||||||
|
*/
|
||||||
|
public function index(): DataResponse {
|
||||||
|
$shares = $this->shareManager->getSharedWith($this->userId, \OCP\Share::SHARE_TYPE_GROUP, null, -1, 0);
|
||||||
|
|
||||||
|
// Only get deleted shares
|
||||||
|
$shares = array_filter($shares, function(IShare $share) {
|
||||||
|
return $share->getPermissions() === 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Only get shares where the owner still exists
|
||||||
|
$shares = array_filter($shares, function (IShare $share) {
|
||||||
|
return $this->userManager->userExists($share->getShareOwner());
|
||||||
|
});
|
||||||
|
|
||||||
|
$shares = array_map(function (IShare $share) {
|
||||||
|
return $this->formatShare($share);
|
||||||
|
}, $shares);
|
||||||
|
|
||||||
|
return new DataResponse($shares);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @NoAdminRequired
|
||||||
|
*
|
||||||
|
* @throws OCSException
|
||||||
|
*/
|
||||||
|
public function undelete(string $id): DataResponse {
|
||||||
|
try {
|
||||||
|
$share = $this->shareManager->getShareById($id, $this->userId);
|
||||||
|
} catch (ShareNotFound $e) {
|
||||||
|
throw new OCSNotFoundException('Share not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($share->getPermissions() !== 0) {
|
||||||
|
throw new OCSNotFoundException('No deleted share found');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->shareManager->restoreShare($share, $this->userId);
|
||||||
|
} catch (GenericShareException $e) {
|
||||||
|
throw new OCSException('Something went wrong');
|
||||||
|
}
|
||||||
|
|
||||||
|
return new DataResponse([]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -42,6 +42,7 @@ use OCP\Mail\IMailer;
|
||||||
use OCP\Security\IHasher;
|
use OCP\Security\IHasher;
|
||||||
use OCP\Security\ISecureRandom;
|
use OCP\Security\ISecureRandom;
|
||||||
use OC\Share20\Share;
|
use OC\Share20\Share;
|
||||||
|
use OCP\Share\Exceptions\GenericShareException;
|
||||||
use OCP\Share\Exceptions\ShareNotFound;
|
use OCP\Share\Exceptions\ShareNotFound;
|
||||||
use OCP\Share\IShare;
|
use OCP\Share\IShare;
|
||||||
use OCP\Share\IShareProvider;
|
use OCP\Share\IShareProvider;
|
||||||
|
@ -692,6 +693,10 @@ class ShareByMailProvider implements IShareProvider {
|
||||||
// nothing to do here, mail shares are only outgoing shares
|
// nothing to do here, mail shares are only outgoing shares
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function restore(IShare $share, string $recipient): IShare {
|
||||||
|
throw new GenericShareException('not implemented');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -31,6 +31,7 @@ namespace OC\Share20;
|
||||||
|
|
||||||
use OC\Files\Cache\Cache;
|
use OC\Files\Cache\Cache;
|
||||||
use OCP\Files\Folder;
|
use OCP\Files\Folder;
|
||||||
|
use OCP\Share\IShare;
|
||||||
use OCP\Share\IShareProvider;
|
use OCP\Share\IShareProvider;
|
||||||
use OC\Share20\Exception\InvalidShare;
|
use OC\Share20\Exception\InvalidShare;
|
||||||
use OC\Share20\Exception\ProviderException;
|
use OC\Share20\Exception\ProviderException;
|
||||||
|
@ -410,6 +411,41 @@ class DefaultShareProvider implements IShareProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*
|
||||||
|
* For now this only works for group shares
|
||||||
|
* If this gets implemented for normal shares we have to extend it
|
||||||
|
*/
|
||||||
|
public function restore(IShare $share, string $recipient): IShare {
|
||||||
|
$qb = $this->dbConn->getQueryBuilder();
|
||||||
|
$qb->select('permissions')
|
||||||
|
->from('share')
|
||||||
|
->where(
|
||||||
|
$qb->expr()->eq('id', $qb->createNamedParameter($share->getId()))
|
||||||
|
);
|
||||||
|
$cursor = $qb->execute();
|
||||||
|
$data = $cursor->fetch();
|
||||||
|
$cursor->closeCursor();
|
||||||
|
|
||||||
|
$originalPermission = $data['permissions'];
|
||||||
|
|
||||||
|
$qb = $this->dbConn->getQueryBuilder();
|
||||||
|
$qb->update('share')
|
||||||
|
->set('permissions', $qb->createNamedParameter($originalPermission))
|
||||||
|
->where(
|
||||||
|
$qb->expr()->eq('parent', $qb->createNamedParameter($share->getParent()))
|
||||||
|
)->andWhere(
|
||||||
|
$qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP))
|
||||||
|
)->andWhere(
|
||||||
|
$qb->expr()->eq('share_with', $qb->createNamedParameter($recipient))
|
||||||
|
);
|
||||||
|
|
||||||
|
$qb->execute();
|
||||||
|
|
||||||
|
return $this->getShareById($share->getId(), $recipient);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
|
@ -922,6 +958,7 @@ class DefaultShareProvider implements IShareProvider {
|
||||||
while($data = $stmt->fetch()) {
|
while($data = $stmt->fetch()) {
|
||||||
$shareMap[$data['parent']]->setPermissions((int)$data['permissions']);
|
$shareMap[$data['parent']]->setPermissions((int)$data['permissions']);
|
||||||
$shareMap[$data['parent']]->setTarget($data['file_target']);
|
$shareMap[$data['parent']]->setTarget($data['file_target']);
|
||||||
|
$shareMap[$data['parent']]->setParent($data['parent']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$stmt->closeCursor();
|
$stmt->closeCursor();
|
||||||
|
|
|
@ -61,6 +61,7 @@ use OCP\Share\Exceptions\GenericShareException;
|
||||||
use OCP\Share\Exceptions\ShareNotFound;
|
use OCP\Share\Exceptions\ShareNotFound;
|
||||||
use OCP\Share\IManager;
|
use OCP\Share\IManager;
|
||||||
use OCP\Share\IProviderFactory;
|
use OCP\Share\IProviderFactory;
|
||||||
|
use OCP\Share\IShare;
|
||||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||||
use Symfony\Component\EventDispatcher\GenericEvent;
|
use Symfony\Component\EventDispatcher\GenericEvent;
|
||||||
use OCP\Share\IShareProvider;
|
use OCP\Share\IShareProvider;
|
||||||
|
@ -978,6 +979,13 @@ class Manager implements IManager {
|
||||||
$this->eventDispatcher->dispatch('OCP\Share::postUnshareFromSelf', $event);
|
$this->eventDispatcher->dispatch('OCP\Share::postUnshareFromSelf', $event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function restoreShare(IShare $share, string $recipientId): IShare {
|
||||||
|
list($providerId, ) = $this->splitFullId($share->getFullId());
|
||||||
|
$provider = $this->factory->getProvider($providerId);
|
||||||
|
|
||||||
|
return $provider->restore($share, $recipientId);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -29,6 +29,7 @@ namespace OCP\Share;
|
||||||
use OCP\Files\Folder;
|
use OCP\Files\Folder;
|
||||||
use OCP\Files\Node;
|
use OCP\Files\Node;
|
||||||
|
|
||||||
|
use OCP\Share\Exceptions\GenericShareException;
|
||||||
use OCP\Share\Exceptions\ShareNotFound;
|
use OCP\Share\Exceptions\ShareNotFound;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -83,6 +84,20 @@ interface IManager {
|
||||||
*/
|
*/
|
||||||
public function deleteFromSelf(IShare $share, $recipientId);
|
public function deleteFromSelf(IShare $share, $recipientId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restore the share when it has been deleted
|
||||||
|
* Certain share types can be restored when they have been deleted
|
||||||
|
* but the provider should properly handle this\
|
||||||
|
*
|
||||||
|
* @param IShare $share The share to restore
|
||||||
|
* @param string $recipientId The user to restore the share for
|
||||||
|
* @return IShare The restored share object
|
||||||
|
* @throws GenericShareException In case restoring the share failed
|
||||||
|
*
|
||||||
|
* @since 14.0.0
|
||||||
|
*/
|
||||||
|
public function restoreShare(IShare $share, string $recipientId): IShare;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move the share as a recipient of the share.
|
* Move the share as a recipient of the share.
|
||||||
* This is updating the share target. So where the recipient has the share mounted.
|
* This is updating the share target. So where the recipient has the share mounted.
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
namespace OCP\Share;
|
namespace OCP\Share;
|
||||||
|
|
||||||
use OCP\Files\Folder;
|
use OCP\Files\Folder;
|
||||||
|
use OCP\Share\Exceptions\GenericShareException;
|
||||||
|
use OCP\Share\Exceptions\ShareNotFound;
|
||||||
use OCP\Files\Node;
|
use OCP\Files\Node;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -80,6 +82,18 @@ interface IShareProvider {
|
||||||
*/
|
*/
|
||||||
public function deleteFromSelf(\OCP\Share\IShare $share, $recipient);
|
public function deleteFromSelf(\OCP\Share\IShare $share, $recipient);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restore a share for a given recipient. The implementation could be provider independant.
|
||||||
|
*
|
||||||
|
* @param IShare $share
|
||||||
|
* @param string $recipient
|
||||||
|
* @return IShare The restored share object
|
||||||
|
*
|
||||||
|
* @since 14.0.0
|
||||||
|
* @throws GenericShareException In case the share could not be restored
|
||||||
|
*/
|
||||||
|
public function restore(IShare $share, string $recipient): IShare;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move a share as a recipient.
|
* Move a share as a recipient.
|
||||||
* This is updating the share target. Thus the mount point of the recipient.
|
* This is updating the share target. Thus the mount point of the recipient.
|
||||||
|
|
Loading…
Reference in New Issue