Commit 0c1b7648 authored by Michael Jobst's avatar Michael Jobst Committed by Thomas Müller
Browse files

share api expanded by tags (#26583)

* share api expanded by tags

* Modified files_sharing JS Unit tests

* modified tests. renamed request parameter. refactoring

* Update Share20OCS.php

Added missing function description

* Update Helper.php

Added missing function description

* Update Helper.php

implicit boolean conversion to !empty()

* Update Share20OCSTest.php
parent fb19605a
......@@ -70,7 +70,6 @@ try {
$files = \OCA\Files\Helper::getFiles($dir, $sortAttribute, $sortDirection);
}
$files = \OCA\Files\Helper::populateTags($files);
$data['directory'] = $dir;
$data['files'] = \OCA\Files\Helper::formatFileInfos($files);
$data['permissions'] = $permissions;
......
......@@ -70,7 +70,11 @@
allowedLists: [
'files',
'favorites'
'favorites',
'systemtags',
'shares.self',
'shares.others',
'shares.link'
],
_extendFileActions: function(fileActions) {
......@@ -238,4 +242,3 @@
})(OCA);
OC.Plugins.register('OCA.Files.FileList', OCA.Files.TagsPlugin);
......@@ -207,19 +207,40 @@ class Helper {
* Populate the result set with file tags
*
* @param array $fileList
* @param string $fileIdentifier identifier attribute name for values in $fileList
* @return array file list populated with tags
*/
public static function populateTags(array $fileList) {
public static function populateTags(array $fileList, $fileIdentifier = 'fileid') {
$filesById = [];
foreach ($fileList as $fileData) {
$filesById[$fileData['fileid']] = $fileData;
$filesById[$fileData[$fileIdentifier]] = $fileData;
}
$tagger = \OC::$server->getTagManager()->load('files');
$tags = $tagger->getTagsForObjects(array_keys($filesById));
if ($tags) {
if (!is_array($tags)) {
throw new \UnexpectedValueException('$tags must be an array');
}
if (!empty($tags)) {
foreach ($tags as $fileId => $fileTags) {
$filesById[$fileId]['tags'] = $fileTags;
}
foreach ($filesById as $key => $fileWithTags) {
foreach($fileList as $key2 => $file){
if( $file[$fileIdentifier] == $key){
$fileList[$key2] = $fileWithTags;
}
}
}
foreach ($fileList as $key => $file) {
if (!array_key_exists('tags', $file)) {
$fileList[$key]['tags'] = [];
}
}
}
return $fileList;
}
......
......@@ -56,7 +56,6 @@
if (options && options.linksOnly) {
this._linksOnly = true;
}
OC.Plugins.attach('OCA.Sharing.FileList', this);
},
_renderRow: function() {
......@@ -83,7 +82,7 @@
// add row with expiration date for link only shares - influenced by _createRow of filelist
if (this._linksOnly) {
var expirationTimestamp = 0;
if(fileData.shares[0].expiration !== null) {
if(fileData.shares && fileData.shares[0].expiration !== null) {
expirationTimestamp = moment(fileData.shares[0].expiration).valueOf();
}
$tr.attr('data-expiration', expirationTimestamp);
......@@ -169,7 +168,8 @@
/* jshint camelcase: false */
data: {
format: 'json',
shared_with_me: !!this._sharedWithUser
shared_with_me: !!this._sharedWithUser,
include_tags: true
},
type: 'GET',
beforeSend: function(xhr) {
......@@ -183,7 +183,8 @@
url: OC.linkToOCS('apps/files_sharing/api/v1') + 'remote_shares',
/* jshint camelcase: false */
data: {
format: 'json'
format: 'json',
include_tags: true
},
type: 'GET',
beforeSend: function(xhr) {
......@@ -238,7 +239,8 @@
type: share.type,
id: share.file_id,
path: OC.dirname(share.mountpoint),
permissions: share.permissions
permissions: share.permissions,
tags: share.tags || []
};
file.shares = [{
......@@ -276,7 +278,8 @@
var file = {
id: share.file_source,
icon: OC.MimeType.getIconUrl(share.mimetype),
mimetype: share.mimetype
mimetype: share.mimetype,
tags: share.tags || []
};
if (share.item_type === 'folder') {
file.type = 'dir';
......
......@@ -174,87 +174,87 @@ class Share20OCS {
* Get a specific share by id
*
* @param string $id
* @return \OC_OCS_Result
* @return \OC\OCS\Result
*/
public function getShare($id) {
if (!$this->shareManager->shareApiEnabled()) {
return new \OC_OCS_Result(null, 404, $this->l->t('Share API is disabled'));
return new \OC\OCS\Result(null, 404, $this->l->t('Share API is disabled'));
}
try {
$share = $this->getShareById($id);
} catch (ShareNotFound $e) {
return new \OC_OCS_Result(null, 404, $this->l->t('Wrong share ID, share doesn\'t exist'));
return new \OC\OCS\Result(null, 404, $this->l->t('Wrong share ID, share doesn\'t exist'));
}
if ($this->canAccessShare($share)) {
try {
$share = $this->formatShare($share);
return new \OC_OCS_Result([$share]);
return new \OC\OCS\Result([$share]);
} catch (NotFoundException $e) {
//Fall trough
}
}
return new \OC_OCS_Result(null, 404, $this->l->t('Wrong share ID, share doesn\'t exist'));
return new \OC\OCS\Result(null, 404, $this->l->t('Wrong share ID, share doesn\'t exist'));
}
/**
* Delete a share
*
* @param string $id
* @return \OC_OCS_Result
* @return \OC\OCS\Result
*/
public function deleteShare($id) {
if (!$this->shareManager->shareApiEnabled()) {
return new \OC_OCS_Result(null, 404, $this->l->t('Share API is disabled'));
return new \OC\OCS\Result(null, 404, $this->l->t('Share API is disabled'));
}
try {
$share = $this->getShareById($id);
} catch (ShareNotFound $e) {
return new \OC_OCS_Result(null, 404, $this->l->t('Wrong share ID, share doesn\'t exist'));
return new \OC\OCS\Result(null, 404, $this->l->t('Wrong share ID, share doesn\'t exist'));
}
try {
$share->getNode()->lock(ILockingProvider::LOCK_SHARED);
} catch (LockedException $e) {
return new \OC_OCS_Result(null, 404, 'could not delete share');
return new \OC\OCS\Result(null, 404, 'could not delete share');
}
if (!$this->canAccessShare($share)) {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new \OC_OCS_Result(null, 404, $this->l->t('Could not delete share'));
return new \OC\OCS\Result(null, 404, $this->l->t('Could not delete share'));
}
$this->shareManager->deleteShare($share);
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new \OC_OCS_Result();
return new \OC\OCS\Result();
}
/**
* @return \OC_OCS_Result
* @return \OC\OCS\Result
*/
public function createShare() {
$share = $this->shareManager->newShare();
if (!$this->shareManager->shareApiEnabled()) {
return new \OC_OCS_Result(null, 404, $this->l->t('Share API is disabled'));
return new \OC\OCS\Result(null, 404, $this->l->t('Share API is disabled'));
}
// Verify path
$path = $this->request->getParam('path', null);
if ($path === null) {
return new \OC_OCS_Result(null, 404, $this->l->t('Please specify a file or folder path'));
return new \OC\OCS\Result(null, 404, $this->l->t('Please specify a file or folder path'));
}
$userFolder = $this->rootFolder->getUserFolder($this->currentUser->getUID());
try {
$path = $userFolder->get($path);
} catch (NotFoundException $e) {
return new \OC_OCS_Result(null, 404, $this->l->t('Wrong path, file/folder doesn\'t exist'));
return new \OC\OCS\Result(null, 404, $this->l->t('Wrong path, file/folder doesn\'t exist'));
}
$share->setNode($path);
......@@ -262,7 +262,7 @@ class Share20OCS {
try {
$share->getNode()->lock(ILockingProvider::LOCK_SHARED);
} catch (LockedException $e) {
return new \OC_OCS_Result(null, 404, 'Could not create share');
return new \OC\OCS\Result(null, 404, 'Could not create share');
}
// Parse permissions (if available)
......@@ -275,7 +275,7 @@ class Share20OCS {
if ($permissions < 0 || $permissions > \OCP\Constants::PERMISSION_ALL) {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new \OC_OCS_Result(null, 404, 'invalid permissions');
return new \OC\OCS\Result(null, 404, 'invalid permissions');
}
// Shares always require read permissions
......@@ -303,20 +303,20 @@ class Share20OCS {
// Valid user is required to share
if ($shareWith === null || !$this->userManager->userExists($shareWith)) {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new \OC_OCS_Result(null, 404, $this->l->t('Please specify a valid user'));
return new \OC\OCS\Result(null, 404, $this->l->t('Please specify a valid user'));
}
$share->setSharedWith($shareWith);
$share->setPermissions($permissions);
} else if ($shareType === \OCP\Share::SHARE_TYPE_GROUP) {
if (!$this->shareManager->allowGroupSharing()) {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new \OC_OCS_Result(null, 404, $this->l->t('Group sharing is disabled by the administrator'));
return new \OC\OCS\Result(null, 404, $this->l->t('Group sharing is disabled by the administrator'));
}
// Valid group is required to share
if ($shareWith === null || !$this->groupManager->groupExists($shareWith)) {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new \OC_OCS_Result(null, 404, $this->l->t('Please specify a valid group'));
return new \OC\OCS\Result(null, 404, $this->l->t('Please specify a valid group'));
}
$share->setSharedWith($shareWith);
$share->setPermissions($permissions);
......@@ -324,7 +324,7 @@ class Share20OCS {
//Can we even share links?
if (!$this->shareManager->shareApiAllowLinks()) {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new \OC_OCS_Result(null, 404, $this->l->t('Public link sharing is disabled by the administrator'));
return new \OC\OCS\Result(null, 404, $this->l->t('Public link sharing is disabled by the administrator'));
}
/*
......@@ -334,7 +334,7 @@ class Share20OCS {
$existingShares = $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_LINK, $path, false, 1, 0);
if (!empty($existingShares)) {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new \OC_OCS_Result($this->formatShare($existingShares[0]));
return new \OC\OCS\Result($this->formatShare($existingShares[0]));
}
$publicUpload = $this->request->getParam('publicUpload', null);
......@@ -342,13 +342,13 @@ class Share20OCS {
// Check if public upload is allowed
if (!$this->shareManager->shareApiLinkAllowPublicUpload()) {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new \OC_OCS_Result(null, 403, $this->l->t('Public upload disabled by the administrator'));
return new \OC\OCS\Result(null, 403, $this->l->t('Public upload disabled by the administrator'));
}
// Public upload can only be set for folders
if ($path instanceof \OCP\Files\File) {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new \OC_OCS_Result(null, 404, $this->l->t('Public upload is only possible for publicly shared folders'));
return new \OC\OCS\Result(null, 404, $this->l->t('Public upload is only possible for publicly shared folders'));
}
$share->setPermissions(
......@@ -377,21 +377,21 @@ class Share20OCS {
$share->setExpirationDate($expireDate);
} catch (\Exception $e) {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new \OC_OCS_Result(null, 404, $this->l->t('Invalid date, date format must be YYYY-MM-DD'));
return new \OC\OCS\Result(null, 404, $this->l->t('Invalid date, date format must be YYYY-MM-DD'));
}
}
} else if ($shareType === \OCP\Share::SHARE_TYPE_REMOTE) {
if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new \OC_OCS_Result(null, 403, $this->l->t('Sharing %s failed because the back end does not allow shares from type %s', [$path->getPath(), $shareType]));
return new \OC\OCS\Result(null, 403, $this->l->t('Sharing %s failed because the back end does not allow shares from type %s', [$path->getPath(), $shareType]));
}
$share->setSharedWith($shareWith);
$share->setPermissions($permissions);
} else {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new \OC_OCS_Result(null, 400, $this->l->t('Unknown share type'));
return new \OC\OCS\Result(null, 400, $this->l->t('Unknown share type'));
}
$share->setShareType($shareType);
......@@ -402,24 +402,25 @@ class Share20OCS {
} catch (GenericShareException $e) {
$code = $e->getCode() === 0 ? 403 : $e->getCode();
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new \OC_OCS_Result(null, $code, $e->getHint());
return new \OC\OCS\Result(null, $code, $e->getHint());
}catch (\Exception $e) {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new \OC_OCS_Result(null, 403, $e->getMessage());
return new \OC\OCS\Result(null, 403, $e->getMessage());
}
$output = $this->formatShare($share);
$share->getNode()->unlock(\OCP\Lock\ILockingProvider::LOCK_SHARED);
return new \OC_OCS_Result($output);
return new \OC\OCS\Result($output);
}
/**
* @param \OCP\Files\File|\OCP\Files\Folder $node
* @return \OC_OCS_Result
* @param boolean $includeTags
* @return \OC\OCS\Result
*/
private function getSharedWithMe($node = null) {
private function getSharedWithMe($node = null, $includeTags) {
$userShares = $this->shareManager->getSharedWith($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_USER, $node, -1, 0);
$groupShares = $this->shareManager->getSharedWith($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_GROUP, $node, -1, 0);
......@@ -436,16 +437,20 @@ class Share20OCS {
}
}
return new \OC_OCS_Result($formatted);
if ($includeTags) {
$formatted = \OCA\Files\Helper::populateTags($formatted, 'file_source');
}
return new \OC\OCS\Result($formatted);
}
/**
* @param \OCP\Files\Folder $folder
* @return \OC_OCS_Result
* @return \OC\OCS\Result
*/
private function getSharesInDir($folder) {
if (!($folder instanceof \OCP\Files\Folder)) {
return new \OC_OCS_Result(null, 400, $this->l->t('Not a directory'));
return new \OC\OCS\Result(null, 400, $this->l->t('Not a directory'));
}
$nodes = $folder->getDirectoryListing();
......@@ -469,7 +474,7 @@ class Share20OCS {
}
}
return new \OC_OCS_Result($formatted);
return new \OC\OCS\Result($formatted);
}
/**
......@@ -481,11 +486,11 @@ class Share20OCS {
* - Get shares for a specific path (?path=...)
* - Get all shares in a folder (?subfiles=true&path=..)
*
* @return \OC_OCS_Result
* @return \OC\OCS\Result
*/
public function getShares() {
if (!$this->shareManager->shareApiEnabled()) {
return new \OC_OCS_Result();
return new \OC\OCS\Result();
}
$sharedWithMe = $this->request->getParam('shared_with_me', null);
......@@ -493,20 +498,22 @@ class Share20OCS {
$subfiles = $this->request->getParam('subfiles');
$path = $this->request->getParam('path', null);
$includeTags = $this->request->getParam('include_tags', false);
if ($path !== null) {
$userFolder = $this->rootFolder->getUserFolder($this->currentUser->getUID());
try {
$path = $userFolder->get($path);
$path->lock(ILockingProvider::LOCK_SHARED);
} catch (\OCP\Files\NotFoundException $e) {
return new \OC_OCS_Result(null, 404, $this->l->t('Wrong path, file/folder doesn\'t exist'));
return new \OC\OCS\Result(null, 404, $this->l->t('Wrong path, file/folder doesn\'t exist'));
} catch (LockedException $e) {
return new \OC_OCS_Result(null, 404, $this->l->t('Could not lock path'));
return new \OC\OCS\Result(null, 404, $this->l->t('Could not lock path'));
}
}
if ($sharedWithMe === 'true') {
$result = $this->getSharedWithMe($path);
$result = $this->getSharedWithMe($path, $includeTags);
if ($path !== null) {
$path->unlock(ILockingProvider::LOCK_SHARED);
}
......@@ -547,33 +554,37 @@ class Share20OCS {
}
}
if ($includeTags) {
$formatted = \OCA\Files\Helper::populateTags($formatted, 'file_source');
}
if ($path !== null) {
$path->unlock(ILockingProvider::LOCK_SHARED);
}
return new \OC_OCS_Result($formatted);
return new \OC\OCS\Result($formatted);
}
/**
* @param int $id
* @return \OC_OCS_Result
* @return \OC\OCS\Result
*/
public function updateShare($id) {
if (!$this->shareManager->shareApiEnabled()) {
return new \OC_OCS_Result(null, 404, $this->l->t('Share API is disabled'));
return new \OC\OCS\Result(null, 404, $this->l->t('Share API is disabled'));
}
try {
$share = $this->getShareById($id);
} catch (ShareNotFound $e) {
return new \OC_OCS_Result(null, 404, $this->l->t('Wrong share ID, share doesn\'t exist'));
return new \OC\OCS\Result(null, 404, $this->l->t('Wrong share ID, share doesn\'t exist'));
}
$share->getNode()->lock(\OCP\Lock\ILockingProvider::LOCK_SHARED);
if (!$this->canAccessShare($share)) {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new \OC_OCS_Result(null, 404, $this->l->t('Wrong share ID, share doesn\'t exist'));
return new \OC\OCS\Result(null, 404, $this->l->t('Wrong share ID, share doesn\'t exist'));
}
$permissions = $this->request->getParam('permissions', null);
......@@ -587,7 +598,7 @@ class Share20OCS {
if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
if ($permissions === null && $password === null && $publicUpload === null && $expireDate === null) {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new \OC_OCS_Result(null, 400, 'Wrong or no update parameter given');
return new \OC\OCS\Result(null, 400, 'Wrong or no update parameter given');
}
$newPermissions = null;
......@@ -609,7 +620,7 @@ class Share20OCS {
$newPermissions !== (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE)
) {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new \OC_OCS_Result(null, 400, $this->l->t('Can\'t change permissions for public share links'));
return new \OC\OCS\Result(null, 400, $this->l->t('Can\'t change permissions for public share links'));
}
if (
......@@ -620,12 +631,12 @@ class Share20OCS {
) {
if (!$this->shareManager->shareApiLinkAllowPublicUpload()) {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new \OC_OCS_Result(null, 403, $this->l->t('Public upload disabled by the administrator'));
return new \OC\OCS\Result(null, 403, $this->l->t('Public upload disabled by the administrator'));
}
if (!($share->getNode() instanceof \OCP\Files\Folder)) {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new \OC_OCS_Result(null, 400, $this->l->t('Public upload is only possible for publicly shared folders'));
return new \OC\OCS\Result(null, 400, $this->l->t('Public upload is only possible for publicly shared folders'));
}
// normalize to correct public upload permissions
......@@ -643,7 +654,7 @@ class Share20OCS {
$expireDate = $this->parseDate($expireDate);
} catch (\Exception $e) {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new \OC_OCS_Result(null, 400, $e->getMessage());
return new \OC\OCS\Result(null, 400, $e->getMessage());
}
$share->setExpirationDate($expireDate);
}
......@@ -658,7 +669,7 @@ class Share20OCS {
// For other shares only permissions is valid.
if ($permissions === null) {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new \OC_OCS_Result(null, 400, $this->l->t('Wrong or no update parameter given'));
return new \OC\OCS\Result(null, 400, $this->l->t('Wrong or no update parameter given'));
} else {
$permissions = (int)$permissions;
$share->setPermissions($permissions);
......@@ -678,7 +689,7 @@ class Share20OCS {
if ($share->getPermissions() & ~$maxPermissions) {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new \OC_OCS_Result(null, 404, $this->l->t('Cannot increase permissions'));
return new \OC\OCS\Result(null, 404, $this->l->t('Cannot increase permissions'));
}
}
}
......@@ -688,12 +699,12 @@ class Share20OCS {
$share = $this->shareManager->updateShare($share);
} catch (\Exception $e) {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new \OC_OCS_Result(null, 400, $e->getMessage());
return new \OC\OCS\Result(null, 400, $e->getMessage());
}
$share->getNode()->unlock(\OCP\Lock\ILockingProvider::LOCK_SHARED);
return new \OC_OCS_Result($this->formatShare($share));
return new \OC\OCS\Result($this->formatShare($share));
}
/**
......
......@@ -138,7 +138,7 @@ class Share20OCSTest extends \Test\TestCase {
$this->shareManager->method('outgoingServer2ServerSharesAllowed')->willReturn(true);
$expected = new \OC_OCS_Result(null, 404, 'Wrong share ID, share doesn\'t exist');
$expected = new \OC\OCS\Result(null, 404, 'Wrong share ID, share doesn\'t exist');
$this->assertEquals($expected, $this->ocs->deleteShare(42));
}
......@@ -165,7 +165,7 @@ class Share20OCSTest extends \Test\TestCase {
->method('unlock')
->with(\OCP\Lock\ILockingProvider::LOCK_SHARED);
$expected = new \OC_OCS_Result();
$expected = new \OC\OCS\Result();
$this->assertEquals($expected, $this->ocs->deleteShare(42));
}
......@@ -193,7 +193,7 @@ class Share20OCSTest extends \Test\TestCase {
->method('unlock')
->with(\OCP\Lock\ILockingProvider::LOCK_SHARED);
$expected = new \OC_OCS_Result(null, 404, 'could not delete share');
$expected = new \OC\OCS\Result(null, 404, 'could not delete share');
$this->assertEquals($expected, $this->ocs->deleteShare(42));
}
......@@ -207,7 +207,7 @@ class Share20OCSTest extends \Test\TestCase {
->with('ocinternal:42')
->will($this->throwException(new \OC\Share20\Exception\ShareNotFound()));
$expected = new \OC_OCS_Result(null, 404, 'wrong share ID, share doesn\'t exist.');
$expected = new \OC\OCS\Result(null, 404, 'wrong share ID, share doesn\'t exist.');
$this->assertEquals($expected, $this->ocs->getShare(42));
}
*/
......@@ -471,7 +471,7 @@ class Share20OCSTest extends \Test\TestCase {
['group', $group],
]));
$expected = new \OC_OCS_Result([$result]);
$expected = new \OC\OCS\Result([$result]);
$this->assertEquals($expected->getData(), $ocs->getShare($share->getId())->getData());
}
......@@ -487,7 +487,7 @@ class Share20OCSTest extends \Test\TestCase {
->with('ocinternal:42')
->willReturn($share);
$expected = new \OC_OCS_Result(null, 404, 'Wrong share ID, share doesn\'t exist');
$expected = new \OC\OCS\Result(null, 404, 'Wrong share ID, share doesn\'t exist');
$this->assertEquals($expected->getMeta(), $this->ocs->getShare(42)->getMeta());