diff --git a/apps/federatedfilesharing/lib/FederatedShareProvider.php b/apps/federatedfilesharing/lib/FederatedShareProvider.php index 5a12f8e9be3..f81b826f12c 100644 --- a/apps/federatedfilesharing/lib/FederatedShareProvider.php +++ b/apps/federatedfilesharing/lib/FederatedShareProvider.php @@ -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(); diff --git a/apps/files/css/files.scss b/apps/files/css/files.scss index 01703df5bf1..24ecbf399e3 100644 --- a/apps/files/css/files.scss +++ b/apps/files/css/files.scss @@ -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; diff --git a/apps/files/img/unshare.svg b/apps/files/img/unshare.svg new file mode 100644 index 00000000000..0c22ca64057 --- /dev/null +++ b/apps/files/img/unshare.svg @@ -0,0 +1 @@ + diff --git a/apps/files/tests/Controller/ViewControllerTest.php b/apps/files/tests/Controller/ViewControllerTest.php index a739e26bd90..eae627fd6a4 100644 --- a/apps/files/tests/Controller/ViewControllerTest.php +++ b/apps/files/tests/Controller/ViewControllerTest.php @@ -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, diff --git a/apps/files_sharing/appinfo/app.php b/apps/files_sharing/appinfo/app.php index f5aa1fc09a1..4f5cf09befb 100644 --- a/apps/files_sharing/appinfo/app.php +++ b/apps/files_sharing/appinfo/app.php @@ -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 () { diff --git a/apps/files_sharing/appinfo/routes.php b/apps/files_sharing/appinfo/routes.php index 8e5110c6a16..eea6715e57d 100644 --- a/apps/files_sharing/appinfo/routes.php +++ b/apps/files_sharing/appinfo/routes.php @@ -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 */ diff --git a/apps/files_sharing/composer/composer/autoload_classmap.php b/apps/files_sharing/composer/composer/autoload_classmap.php index e5a86bbd095..cb64d44a54d 100644 --- a/apps/files_sharing/composer/composer/autoload_classmap.php +++ b/apps/files_sharing/composer/composer/autoload_classmap.php @@ -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', diff --git a/apps/files_sharing/composer/composer/autoload_static.php b/apps/files_sharing/composer/composer/autoload_static.php index bf41ef45ea1..dcfd5c4fe4f 100644 --- a/apps/files_sharing/composer/composer/autoload_static.php +++ b/apps/files_sharing/composer/composer/autoload_static.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', diff --git a/apps/files_sharing/js/app.js b/apps/files_sharing/js/app.js index e6c9159eda4..f63410bc9bf 100644 --- a/apps/files_sharing/js/app.js +++ b/apps/files_sharing/js/app.js @@ -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('
' + + '' + t('files_sharing', 'Shares you deleted will show up here') + '
'); + 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(); + }); }); diff --git a/apps/files_sharing/js/share.js b/apps/files_sharing/js/share.js index 22513e1b470..a925920f3bc 100644 --- a/apps/files_sharing/js/share.js +++ b/apps/files_sharing/js/share.js @@ -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); diff --git a/apps/files_sharing/js/sharedfilelist.js b/apps/files_sharing/js/sharedfilelist.js index ad818d91413..973d2120b16 100644 --- a/apps/files_sharing/js/sharedfilelist.js +++ b/apps/files_sharing/js/sharedfilelist.js @@ -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) { diff --git a/apps/files_sharing/lib/Controller/DeletedShareAPIController.php b/apps/files_sharing/lib/Controller/DeletedShareAPIController.php new file mode 100644 index 00000000000..d95b434e48f --- /dev/null +++ b/apps/files_sharing/lib/Controller/DeletedShareAPIController.php @@ -0,0 +1,168 @@ + + * @Copyright 2018, John Molakvoæ (skjnldsv)