Merge pull request #9909 from nextcloud/feature/2192/allow_group_share_undeletion
Add API to undelete delete group shares
This commit is contained in:
commit
cbfcfb236f
|
@ -38,6 +38,7 @@ use OCP\IConfig;
|
|||
use OCP\IL10N;
|
||||
use OCP\ILogger;
|
||||
use OCP\IUserManager;
|
||||
use OCP\Share\Exceptions\GenericShareException;
|
||||
use OCP\Share\IShare;
|
||||
use OCP\Share\IShareProvider;
|
||||
use OC\Share20\Exception\InvalidShare;
|
||||
|
@ -585,6 +586,10 @@ class FederatedShareProvider implements IShareProvider {
|
|||
// 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) {
|
||||
$qb = $this->dbConnection->getQueryBuilder();
|
||||
|
|
|
@ -105,6 +105,9 @@
|
|||
.nav-icon-trashbin {
|
||||
background-image: url('../img/delete.svg?v=1');
|
||||
}
|
||||
.nav-icon-deletedshares {
|
||||
background-image: url('../img/unshare.svg?v=1');
|
||||
}
|
||||
|
||||
#app-navigation .nav-files a.nav-icon-files {
|
||||
width: auto;
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m12.5 1a2.5 2.5 0 0 0-2.5 2.5 2.5 2.5 0 0 0 0.003906 0.12891l-4.9023 2.4512a2.5 2.5 0 0 0-1.6016-0.58008 2.5 2.5 0 0 0-2.5 2.5 2.5 2.5 0 0 0 2.5 2.5 2.5 2.5 0 0 0 0.30469-0.021484l3.4395-1.7246-1.25-0.625a2.5 2.5 0 0 0 0.0058594-0.12891 2.5 2.5 0 0 0-0.0039062-0.12891l4.9023-2.4512a2.5 2.5 0 0 0 1.6016 0.58008 2.5 2.5 0 0 0 0.26562-0.013672l1.5625-0.7832a2.5 2.5 0 0 0 0.67188-1.7031 2.5 2.5 0 0 0-2.5-2.5zm0.25391 9.0156-3.7246 1.8672 0.97656 0.48828a2.5 2.5 0 0 0-0.005859 0.12891 2.5 2.5 0 0 0 2.5 2.5 2.5 2.5 0 0 0 2.5-2.5 2.5 2.5 0 0 0-2.2461-2.4844z"/><rect transform="rotate(-26.63)" x="-1.0586" y="11.891" width="11.687" height="2.0029" ry="0" style="paint-order:normal"/></svg>
|
After Width: | Height: | Size: 795 B |
|
@ -206,6 +206,17 @@ class ViewControllerTest extends TestCase {
|
|||
'type' => 'link',
|
||||
'classes' => '',
|
||||
],
|
||||
[
|
||||
'id' => 'deletedshares',
|
||||
'appname' => 'files_sharing',
|
||||
'script' => 'list.php',
|
||||
'order' => 18,
|
||||
'name' => \OC::$server->getL10N('files_sharing')->t('Deleted shares'),
|
||||
'active' => false,
|
||||
'icon' => '',
|
||||
'type' => 'link',
|
||||
'classes' => '',
|
||||
],
|
||||
[
|
||||
'id' => 'systemtagsfilter',
|
||||
'appname' => 'systemtags',
|
||||
|
@ -269,6 +280,10 @@ class ViewControllerTest extends TestCase {
|
|||
'id' => 'sharinglinks',
|
||||
'content' => null,
|
||||
],
|
||||
[
|
||||
'id' => 'deletedshares',
|
||||
'content' => null,
|
||||
],
|
||||
[
|
||||
'id' => 'systemtagsfilter',
|
||||
'content' => null,
|
||||
|
|
|
@ -48,6 +48,9 @@ $eventDispatcher->addListener(
|
|||
);
|
||||
|
||||
$config = \OC::$server->getConfig();
|
||||
$shareManager = \OC::$server->getShareManager();
|
||||
$userSession = \OC::$server->getUserSession();
|
||||
|
||||
if ($config->getAppValue('core', 'shareapi_enabled', 'yes') === 'yes') {
|
||||
\OCA\Files\App::getNavigationManager()->add(function () {
|
||||
$l = \OC::$server->getL10N('files_sharing');
|
||||
|
@ -59,6 +62,17 @@ if ($config->getAppValue('core', 'shareapi_enabled', 'yes') === 'yes') {
|
|||
'name' => $l->t('Shared with you'),
|
||||
];
|
||||
});
|
||||
|
||||
\OCA\Files\App::getNavigationManager()->add(function () {
|
||||
$l = \OC::$server->getL10N('files_sharing');
|
||||
return [
|
||||
'id' => 'deletedshares',
|
||||
'appname' => 'files_sharing',
|
||||
'script' => 'list.php',
|
||||
'order' => 18,
|
||||
'name' => $l->t('Deleted shares'),
|
||||
];
|
||||
});
|
||||
|
||||
if (\OCP\Util::isSharingDisabledForUser() === false) {
|
||||
\OCA\Files\App::getNavigationManager()->add(function () {
|
||||
|
|
|
@ -73,6 +73,19 @@ return [
|
|||
'url' => '/api/v1/shares/{id}',
|
||||
'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
|
||||
*/
|
||||
|
|
|
@ -22,6 +22,7 @@ return array(
|
|||
'OCA\\Files_Sharing\\Capabilities' => $baseDir . '/../lib/Capabilities.php',
|
||||
'OCA\\Files_Sharing\\Collaboration\\ShareRecipientSorter' => $baseDir . '/../lib/Collaboration/ShareRecipientSorter.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\\PublicPreviewController' => $baseDir . '/../lib/Controller/PublicPreviewController.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\\Collaboration\\ShareRecipientSorter' => __DIR__ . '/..' . '/../lib/Collaboration/ShareRecipientSorter.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\\PublicPreviewController' => __DIR__ . '/..' . '/../lib/Controller/PublicPreviewController.php',
|
||||
'OCA\\Files_Sharing\\Controller\\RemoteController' => __DIR__ . '/..' . '/../lib/Controller/RemoteController.php',
|
||||
|
|
|
@ -92,6 +92,30 @@ OCA.Sharing.App = {
|
|||
return this._linkFileList;
|
||||
},
|
||||
|
||||
initSharingDeleted: function($el) {
|
||||
if (this._deletedFileList) {
|
||||
return this._deletedFileList;
|
||||
}
|
||||
this._deletedFileList = new OCA.Sharing.FileList(
|
||||
$el,
|
||||
{
|
||||
id: 'shares.deleted',
|
||||
scrollContainer: $('#app-content'),
|
||||
showDeleted: true,
|
||||
sharedWithUser: true,
|
||||
fileActions: this._restoreShareAction(),
|
||||
config: OCA.Files.App.getFilesConfig()
|
||||
}
|
||||
);
|
||||
|
||||
this._extendFileList(this._deletedFileList);
|
||||
this._deletedFileList.appName = t('files_sharing', 'Deleted shares');
|
||||
this._deletedFileList.$el.find('#emptycontent').html('<div class="icon-share"></div>' +
|
||||
'<h2>' + t('files_sharing', 'No deleted shares') + '</h2>' +
|
||||
'<p>' + t('files_sharing', 'Shares you deleted will show up here') + '</p>');
|
||||
return this._deletedFileList;
|
||||
},
|
||||
|
||||
removeSharingIn: function() {
|
||||
if (this._inFileList) {
|
||||
this._inFileList.$fileList.empty();
|
||||
|
@ -110,6 +134,12 @@ OCA.Sharing.App = {
|
|||
}
|
||||
},
|
||||
|
||||
removeSharingDeleted: function() {
|
||||
if (this._deletedFileList) {
|
||||
this._deletedFileList.$fileList.empty();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Destroy the app
|
||||
*/
|
||||
|
@ -151,6 +181,29 @@ OCA.Sharing.App = {
|
|||
return fileActions;
|
||||
},
|
||||
|
||||
_restoreShareAction: function() {
|
||||
var fileActions = new OCA.Files.FileActions();
|
||||
fileActions.registerAction({
|
||||
name: 'Restore',
|
||||
displayName: '',
|
||||
altText: t('files_sharing', 'Restore share'),
|
||||
mime: 'all',
|
||||
permissions: OC.PERMISSION_ALL,
|
||||
iconClass: 'icon-history',
|
||||
type: OCA.Files.FileActions.TYPE_INLINE,
|
||||
actionHandler: function(fileName, context) {
|
||||
var shareId = context.$file.data('shareId');
|
||||
$.post(OC.linkToOCS('apps/files_sharing/api/v1/deletedshares', 2) + shareId)
|
||||
.success(function(result) {
|
||||
context.fileList.remove(context.fileInfoModel.attributes.name);
|
||||
}).fail(function() {
|
||||
OC.Notification.showTemporary(t('files_sharing', 'Something happened. Unable to restore the share.'));
|
||||
});
|
||||
}
|
||||
});
|
||||
return fileActions;
|
||||
},
|
||||
|
||||
_onActionsUpdated: function(ev) {
|
||||
_.each([this._inFileList, this._outFileList, this._linkFileList], function(list) {
|
||||
if (!list) {
|
||||
|
@ -193,4 +246,10 @@ $(document).ready(function() {
|
|||
$('#app-content-sharinglinks').on('hide', function() {
|
||||
OCA.Sharing.App.removeSharingLinks();
|
||||
});
|
||||
$('#app-content-deletedshares').on('show', function(e) {
|
||||
OCA.Sharing.App.initSharingDeleted($(e.target));
|
||||
});
|
||||
$('#app-content-deletedshares').on('hide', function() {
|
||||
OCA.Sharing.App.removeSharingDeleted();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -42,6 +42,12 @@
|
|||
var fileActions = fileList.fileActions;
|
||||
var oldCreateRow = fileList._createRow;
|
||||
fileList._createRow = function(fileData) {
|
||||
|
||||
if (fileData.permissions === 0) {
|
||||
// no permission, disabling sidebar
|
||||
delete fileActions.actions.all.Details;
|
||||
}
|
||||
|
||||
var tr = oldCreateRow.apply(this, arguments);
|
||||
var sharePermissions = OCA.Sharing.Util.getSharePermissions(fileData);
|
||||
tr.attr('data-share-permissions', sharePermissions);
|
||||
|
@ -158,11 +164,15 @@
|
|||
permissions: OC.PERMISSION_ALL,
|
||||
iconClass: 'icon-shared',
|
||||
type: OCA.Files.FileActions.TYPE_INLINE,
|
||||
actionHandler: function(fileName) {
|
||||
fileList.showDetailsView(fileName, 'shareTabView');
|
||||
actionHandler: function(fileName, context) {
|
||||
// do not open sidebar if permission is set and equal to 0
|
||||
var permissions = parseInt(context.$file.data('share-permissions'), 10);
|
||||
if (isNaN(permissions) || permissions > 0) {
|
||||
fileList.showDetailsView(fileName, 'shareTabView');
|
||||
}
|
||||
},
|
||||
render: function(actionSpec, isDefault, context) {
|
||||
var permissions = parseInt(context.$file.attr('data-permissions'), 10);
|
||||
var permissions = parseInt(context.$file.data('permissions'), 10);
|
||||
// if no share permissions but share owner exists, still show the link
|
||||
if ((permissions & OC.PERMISSION_SHARE) !== 0 || context.$file.attr('data-share-owner')) {
|
||||
return fileActions._defaultRenderAction.call(fileActions, actionSpec, isDefault, context);
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
*/
|
||||
_sharedWithUser: false,
|
||||
_linksOnly: false,
|
||||
_showDeleted: false,
|
||||
_clientSideSort: true,
|
||||
_allowSelection: false,
|
||||
|
||||
|
@ -56,6 +57,9 @@
|
|||
if (options && options.linksOnly) {
|
||||
this._linksOnly = true;
|
||||
}
|
||||
if (options && options.showDeleted) {
|
||||
this._showDeleted = true;
|
||||
}
|
||||
},
|
||||
|
||||
_renderRow: function() {
|
||||
|
@ -78,7 +82,11 @@
|
|||
var permission = parseInt($tr.attr('data-permissions')) | OC.PERMISSION_DELETE;
|
||||
$tr.attr('data-permissions', permission);
|
||||
}
|
||||
|
||||
if (this._showDeleted) {
|
||||
var permission = fileData.permissions;
|
||||
$tr.attr('data-share-permissions', permission);
|
||||
}
|
||||
|
||||
// add row with expiration date for link only shares - influenced by _createRow of filelist
|
||||
if (this._linksOnly) {
|
||||
var expirationTimestamp = 0;
|
||||
|
@ -183,20 +191,36 @@
|
|||
// there is only root
|
||||
this._setCurrentDir('/', false);
|
||||
|
||||
|
||||
if (this._showDeleted) {
|
||||
var shares = $.ajax({
|
||||
url: OC.linkToOCS('apps/files_sharing/api/v1', 2) + 'deletedshares',
|
||||
/* jshint camelcase: false */
|
||||
data: {
|
||||
format: 'json',
|
||||
include_tags: true
|
||||
},
|
||||
type: 'GET',
|
||||
beforeSend: function(xhr) {
|
||||
xhr.setRequestHeader('OCS-APIREQUEST', 'true');
|
||||
},
|
||||
});
|
||||
} else {
|
||||
var shares = $.ajax({
|
||||
url: OC.linkToOCS('apps/files_sharing/api/v1') + 'shares',
|
||||
/* jshint camelcase: false */
|
||||
data: {
|
||||
format: 'json',
|
||||
shared_with_me: !!this._sharedWithUser,
|
||||
include_tags: true
|
||||
},
|
||||
type: 'GET',
|
||||
beforeSend: function(xhr) {
|
||||
xhr.setRequestHeader('OCS-APIREQUEST', 'true');
|
||||
},
|
||||
});
|
||||
}
|
||||
var promises = [];
|
||||
var shares = $.ajax({
|
||||
url: OC.linkToOCS('apps/files_sharing/api/v1') + 'shares',
|
||||
/* jshint camelcase: false */
|
||||
data: {
|
||||
format: 'json',
|
||||
shared_with_me: !!this._sharedWithUser,
|
||||
include_tags: true
|
||||
},
|
||||
type: 'GET',
|
||||
beforeSend: function(xhr) {
|
||||
xhr.setRequestHeader('OCS-APIREQUEST', 'true');
|
||||
},
|
||||
});
|
||||
promises.push(shares);
|
||||
|
||||
if (!!this._sharedWithUser) {
|
||||
|
|
|
@ -0,0 +1,168 @@
|
|||
<?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\Files\IRootFolder;
|
||||
use OCP\Files\NotFoundException;
|
||||
use OCP\IGroupManager;
|
||||
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;
|
||||
|
||||
/** @var IGroupManager */
|
||||
private $groupManager;
|
||||
|
||||
/** @var IRootFolder */
|
||||
private $rootFolder;
|
||||
|
||||
public function __construct(string $appName,
|
||||
IRequest $request,
|
||||
ShareManager $shareManager,
|
||||
string $UserId,
|
||||
IUserManager $userManager,
|
||||
IGroupManager $groupManager,
|
||||
IRootFolder $rootFolder) {
|
||||
parent::__construct($appName, $request);
|
||||
|
||||
$this->shareManager = $shareManager;
|
||||
$this->userId = $UserId;
|
||||
$this->userManager = $userManager;
|
||||
$this->groupManager = $groupManager;
|
||||
$this->rootFolder = $rootFolder;
|
||||
}
|
||||
|
||||
private function formatShare(IShare $share): array {
|
||||
|
||||
$result = [
|
||||
'id' => $share->getFullId(),
|
||||
'share_type' => $share->getShareType(),
|
||||
'uid_owner' => $share->getSharedBy(),
|
||||
'displayname_owner' => $this->userManager->get($share->getSharedBy())->getDisplayName(),
|
||||
'permissions' => 0,
|
||||
'stime' => $share->getShareTime()->getTimestamp(),
|
||||
'parent' => null,
|
||||
'expiration' => null,
|
||||
'token' => null,
|
||||
'uid_file_owner' => $share->getShareOwner(),
|
||||
'displayname_file_owner' => $this->userManager->get($share->getShareOwner())->getDisplayName(),
|
||||
'path' => $share->getTarget(),
|
||||
];
|
||||
$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
|
||||
$nodes = $userFolder->getById($share->getNodeId());
|
||||
if (empty($nodes)) {
|
||||
// fallback to guessing the path
|
||||
$node = $userFolder->get($share->getTarget());
|
||||
if ($node === null || $share->getTarget() === '') {
|
||||
throw new NotFoundException();
|
||||
}
|
||||
} else {
|
||||
$node = $nodes[0];
|
||||
}
|
||||
|
||||
$result['path'] = $userFolder->getRelativePath($node->getPath());
|
||||
if ($node instanceOf \OCP\Files\Folder) {
|
||||
$result['item_type'] = 'folder';
|
||||
} else {
|
||||
$result['item_type'] = 'file';
|
||||
}
|
||||
$result['mimetype'] = $node->getMimetype();
|
||||
$result['storage_id'] = $node->getStorage()->getId();
|
||||
$result['storage'] = $node->getStorage()->getCache()->getNumericStorageId();
|
||||
$result['item_source'] = $node->getId();
|
||||
$result['file_source'] = $node->getId();
|
||||
$result['file_parent'] = $node->getParent()->getId();
|
||||
$result['file_target'] = $share->getTarget();
|
||||
|
||||
$expiration = $share->getExpirationDate();
|
||||
if ($expiration !== null) {
|
||||
$result['expiration'] = $expiration->format('Y-m-d 00:00:00');
|
||||
}
|
||||
|
||||
$group = $this->groupManager->get($share->getSharedWith());
|
||||
$result['share_with'] = $share->getSharedWith();
|
||||
$result['share_with_displayname'] = $group !== null ? $group->getDisplayName() : $share->getSharedWith();
|
||||
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function index(): DataResponse {
|
||||
$shares = $this->shareManager->getDeletedSharedWith($this->userId, \OCP\Share::SHARE_TYPE_GROUP, null, -1, 0);
|
||||
|
||||
$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([]);
|
||||
}
|
||||
}
|
|
@ -151,7 +151,6 @@ class ShareAPIController extends OCSController {
|
|||
$node = $recipientNode;
|
||||
} else {
|
||||
$nodes = $userFolder->getById($share->getNodeId());
|
||||
|
||||
if (empty($nodes)) {
|
||||
// fallback to guessing the path
|
||||
$node = $userFolder->get($share->getTarget());
|
||||
|
|
|
@ -42,6 +42,7 @@ use OCP\Mail\IMailer;
|
|||
use OCP\Security\IHasher;
|
||||
use OCP\Security\ISecureRandom;
|
||||
use OC\Share20\Share;
|
||||
use OCP\Share\Exceptions\GenericShareException;
|
||||
use OCP\Share\Exceptions\ShareNotFound;
|
||||
use OCP\Share\IShare;
|
||||
use OCP\Share\IShareProvider;
|
||||
|
@ -692,6 +693,10 @@ class ShareByMailProvider implements IShareProvider {
|
|||
// nothing to do here, mail shares are only outgoing shares
|
||||
}
|
||||
|
||||
public function restore(IShare $share, string $recipient): IShare {
|
||||
throw new GenericShareException('not implemented');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
|
|
|
@ -31,6 +31,7 @@ namespace OC\Share20;
|
|||
|
||||
use OC\Files\Cache\Cache;
|
||||
use OCP\Files\Folder;
|
||||
use OCP\Share\IShare;
|
||||
use OCP\Share\IShareProvider;
|
||||
use OC\Share20\Exception\InvalidShare;
|
||||
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
|
||||
*/
|
||||
|
@ -922,6 +958,7 @@ class DefaultShareProvider implements IShareProvider {
|
|||
while($data = $stmt->fetch()) {
|
||||
$shareMap[$data['parent']]->setPermissions((int)$data['permissions']);
|
||||
$shareMap[$data['parent']]->setTarget($data['file_target']);
|
||||
$shareMap[$data['parent']]->setParent($data['parent']);
|
||||
}
|
||||
|
||||
$stmt->closeCursor();
|
||||
|
|
|
@ -61,6 +61,7 @@ use OCP\Share\Exceptions\GenericShareException;
|
|||
use OCP\Share\Exceptions\ShareNotFound;
|
||||
use OCP\Share\IManager;
|
||||
use OCP\Share\IProviderFactory;
|
||||
use OCP\Share\IShare;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||
use Symfony\Component\EventDispatcher\GenericEvent;
|
||||
use OCP\Share\IShareProvider;
|
||||
|
@ -978,6 +979,13 @@ class Manager implements IManager {
|
|||
$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
|
||||
*/
|
||||
|
@ -1121,6 +1129,25 @@ class Manager implements IManager {
|
|||
return $shares;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getDeletedSharedWith($userId, $shareType, $node = null, $limit = 50, $offset = 0) {
|
||||
$shares = $this->getSharedWith($userId, $shareType, $node, $limit, $offset);
|
||||
|
||||
// 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());
|
||||
});
|
||||
|
||||
return $shares;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
|
|
|
@ -29,6 +29,7 @@ namespace OCP\Share;
|
|||
use OCP\Files\Folder;
|
||||
use OCP\Files\Node;
|
||||
|
||||
use OCP\Share\Exceptions\GenericShareException;
|
||||
use OCP\Share\Exceptions\ShareNotFound;
|
||||
|
||||
/**
|
||||
|
@ -83,6 +84,20 @@ interface IManager {
|
|||
*/
|
||||
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.
|
||||
* This is updating the share target. So where the recipient has the share mounted.
|
||||
|
@ -134,6 +149,20 @@ interface IManager {
|
|||
*/
|
||||
public function getSharedWith($userId, $shareType, $node = null, $limit = 50, $offset = 0);
|
||||
|
||||
/**
|
||||
* Get deleted shares shared with $user.
|
||||
* Filter by $node if provided
|
||||
*
|
||||
* @param string $userId
|
||||
* @param int $shareType
|
||||
* @param Node|null $node
|
||||
* @param int $limit The maximum number of shares returned, -1 for all
|
||||
* @param int $offset
|
||||
* @return IShare[]
|
||||
* @since 14.0.0
|
||||
*/
|
||||
public function getDeletedSharedWith($userId, $shareType, $node = null, $limit = 50, $offset = 0);
|
||||
|
||||
/**
|
||||
* Retrieve a share by the share id.
|
||||
* If the recipient is set make sure to retrieve the file for that user.
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
namespace OCP\Share;
|
||||
|
||||
use OCP\Files\Folder;
|
||||
use OCP\Share\Exceptions\GenericShareException;
|
||||
use OCP\Share\Exceptions\ShareNotFound;
|
||||
use OCP\Files\Node;
|
||||
|
||||
/**
|
||||
|
@ -80,6 +82,18 @@ interface IShareProvider {
|
|||
*/
|
||||
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.
|
||||
* This is updating the share target. Thus the mount point of the recipient.
|
||||
|
|
Loading…
Reference in New Issue