summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorBjörn Schießle <bjoern@schiessle.org>2014-12-19 19:04:44 +0100
committerBjörn Schießle <bjoern@schiessle.org>2014-12-19 19:04:44 +0100
commit8164415b45386cb87e05e6e50cf4b8f3128b2e69 (patch)
tree1edbf481b6596533be0813d7639277fc9a92b98b /apps
parentad6814f9207ac50ad9e3e6f157ec9746c81392e9 (diff)
parent24993280edcf66f9daa5a5e82428fefef4a3ab56 (diff)
downloadnextcloud-server-8164415b45386cb87e05e6e50cf4b8f3128b2e69.tar.gz
nextcloud-server-8164415b45386cb87e05e6e50cf4b8f3128b2e69.zip
Merge pull request #12749 from owncloud/server2server-sharing-ng
server to server sharing next generation
Diffstat (limited to 'apps')
-rw-r--r--apps/files_encryption/lib/hooks.php13
-rw-r--r--apps/files_encryption/lib/util.php8
-rwxr-xr-xapps/files_encryption/tests/share.php99
-rw-r--r--apps/files_sharing/ajax/external.php11
-rw-r--r--apps/files_sharing/api/server2server.php51
-rw-r--r--apps/files_sharing/appinfo/routes.php22
-rw-r--r--apps/files_sharing/application.php21
-rw-r--r--apps/files_sharing/js/external.js95
-rw-r--r--apps/files_sharing/lib/activity.php2
-rw-r--r--apps/files_sharing/lib/connector/publicauth.php2
-rw-r--r--apps/files_sharing/lib/controllers/externalsharescontroller.php86
-rw-r--r--apps/files_sharing/lib/external/manager.php136
-rw-r--r--apps/files_sharing/lib/helper.php28
-rw-r--r--apps/files_sharing/lib/share/file.php14
-rw-r--r--apps/files_sharing/lib/updater.php7
-rw-r--r--apps/files_sharing/tests/server2server.php41
16 files changed, 513 insertions, 123 deletions
diff --git a/apps/files_encryption/lib/hooks.php b/apps/files_encryption/lib/hooks.php
index bddfb7b2544..7ddde0a3112 100644
--- a/apps/files_encryption/lib/hooks.php
+++ b/apps/files_encryption/lib/hooks.php
@@ -25,8 +25,6 @@
namespace OCA\Files_Encryption;
-use OC\Files\Filesystem;
-
/**
* Class for hook specific logic
*/
@@ -364,15 +362,16 @@ class Hooks {
if ($params['itemType'] === 'file' || $params['itemType'] === 'folder') {
$view = new \OC\Files\View('/');
- $userId = \OCP\User::getUser();
+ $userId = $params['uidOwner'];
+ $userView = new \OC\Files\View('/' . $userId . '/files');
$util = new Util($view, $userId);
- $path = \OC\Files\Filesystem::getPath($params['fileSource']);
+ $path = $userView->getPath($params['fileSource']);
// for group shares get a list of the group members
if ($params['shareType'] === \OCP\Share::SHARE_TYPE_GROUP) {
$userIds = \OC_Group::usersInGroup($params['shareWith']);
} else {
- if ($params['shareType'] === \OCP\Share::SHARE_TYPE_LINK) {
+ if ($params['shareType'] === \OCP\Share::SHARE_TYPE_LINK || $params['shareType'] === \OCP\Share::SHARE_TYPE_REMOTE) {
$userIds = array($util->getPublicShareKeyId());
} else {
$userIds = array($params['shareWith']);
@@ -619,8 +618,8 @@ class Hooks {
// check if the user still has access to the file, otherwise delete share key
$sharingUsers = \OCP\Share::getUsersSharingFile($path, $user);
- if (!in_array(\OCP\User::getUser(), $sharingUsers['users'])) {
- Keymanager::delShareKey($view, array(\OCP\User::getUser()), $keyPath, $owner, $ownerPath);
+ if (!in_array($user, $sharingUsers['users'])) {
+ Keymanager::delShareKey($view, array($user), $keyPath, $owner, $ownerPath);
}
}
diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php
index ad6948b95a6..4aaf7aa2571 100644
--- a/apps/files_encryption/lib/util.php
+++ b/apps/files_encryption/lib/util.php
@@ -1207,13 +1207,7 @@ class Util {
// handle public access
if ($this->isPublic) {
- $filename = $path;
- $fileOwnerUid = $this->userId;
-
- return array(
- $fileOwnerUid,
- $filename
- );
+ return array($this->userId, $path);
} else {
// Check that UID is valid
diff --git a/apps/files_encryption/tests/share.php b/apps/files_encryption/tests/share.php
index 9c53c73aafa..d29e6a191c8 100755
--- a/apps/files_encryption/tests/share.php
+++ b/apps/files_encryption/tests/share.php
@@ -115,6 +115,91 @@ class Share extends TestCase {
parent::tearDownAfterClass();
}
+ /**
+ * @medium
+ */
+ function testDeclineServer2ServerShare() {
+
+ $config = $this->getMockBuilder('\OCP\IConfig')
+ ->disableOriginalConstructor()->getMock();
+ $certificateManager = $this->getMock('\OCP\ICertificateManager');
+ $httpHelperMock = $this->getMockBuilder('\OC\HTTPHelper')
+ ->setConstructorArgs(array($config, $certificateManager))
+ ->getMock();
+ $httpHelperMock->expects($this->once())->method('post')->with($this->anything())->will($this->returnValue(true));
+
+ self::loginHelper(self::TEST_ENCRYPTION_SHARE_USER1);
+
+ // save file with content
+ $cryptedFile = file_put_contents('crypt:///' . self::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename, $this->dataShort);
+
+ // test that data was successfully written
+ $this->assertTrue(is_int($cryptedFile));
+
+ // get the file info from previous created file
+ $fileInfo = $this->view->getFileInfo(
+ '/' . self::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename);
+
+
+ // share the file
+ $token = \OCP\Share::shareItem('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_LINK, '', \OCP\Constants::PERMISSION_ALL);
+ $this->assertTrue(is_string($token));
+
+ $publicShareKeyId = \OC::$server->getConfig()->getAppValue('files_encryption', 'publicShareKeyId');
+
+ // check if share key for public exists
+ $this->assertTrue($this->view->file_exists(
+ '/' . self::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/keys/'
+ . $this->filename . '/' . $publicShareKeyId . '.shareKey'));
+
+ // manipulate share
+ $query = \OC::$server->getDatabaseConnection()->prepare('UPDATE `*PREFIX*share` SET `share_type` = ?, `share_with` = ? WHERE `token`=?');
+ $this->assertTrue($query->execute(array(\OCP\Share::SHARE_TYPE_REMOTE, 'foo@bar', $token)));
+
+ // check if share key not exists
+ $this->assertTrue($this->view->file_exists(
+ '/' . self::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/keys/'
+ . $this->filename . '/' . $publicShareKeyId . '.shareKey'));
+
+
+ $query = \OC::$server->getDatabaseConnection()->prepare('SELECT * FROM `*PREFIX*share` WHERE `token`=?');
+ $query->execute(array($token));
+
+ $share = $query->fetch();
+
+ $this->registerHttpHelper($httpHelperMock);
+ $_POST['token'] = $token;
+ $s2s = new \OCA\Files_Sharing\API\Server2Server();
+ $s2s->declineShare(array('id' => $share['id']));
+ $this->restoreHttpHelper();
+
+ $this->assertFalse($this->view->file_exists(
+ '/' . self::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/keys/'
+ . $this->filename . '/' . $publicShareKeyId . '.shareKey'));
+
+ }
+
+
+ /**
+ * Register an http helper mock for testing purposes.
+ * @param $httpHelper http helper mock
+ */
+ private function registerHttpHelper($httpHelper) {
+ $this->oldHttpHelper = \OC::$server->query('HTTPHelper');
+ \OC::$server->registerService('HTTPHelper', function ($c) use ($httpHelper) {
+ return $httpHelper;
+ });
+ }
+
+ /**
+ * Restore the original http helper
+ */
+ private function restoreHttpHelper() {
+ $oldHttpHelper = $this->oldHttpHelper;
+ \OC::$server->registerService('HTTPHelper', function ($c) use ($oldHttpHelper) {
+ return $oldHttpHelper;
+ });
+ }
/**
* @medium
@@ -285,7 +370,7 @@ class Share extends TestCase {
// save file with content
$cryptedFile = file_put_contents('crypt:///' . self::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->folder1 . $this->subfolder . $this->subsubfolder . '/'
- . $this->filename, $this->dataShort);
+ . $this->filename, $this->dataShort);
// test that data was successfully written
$this->assertTrue(is_int($cryptedFile));
@@ -677,7 +762,7 @@ class Share extends TestCase {
// save file with content
$cryptedFile1 = file_put_contents('crypt:///' . self::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename, $this->dataShort);
$cryptedFile2 = file_put_contents('crypt:///' . self::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->folder1 . $this->subfolder . $this->subsubfolder . '/'
- . $this->filename, $this->dataShort);
+ . $this->filename, $this->dataShort);
// test that data was successfully written
$this->assertTrue(is_int($cryptedFile1));
@@ -784,7 +869,7 @@ class Share extends TestCase {
// save file with content
$cryptedFile1 = file_put_contents('crypt:///' . self::TEST_ENCRYPTION_SHARE_USER2. '/files/' . $this->filename, $this->dataShort);
$cryptedFile2 = file_put_contents('crypt:///' . self::TEST_ENCRYPTION_SHARE_USER2 . '/files/' . $this->folder1 . $this->subfolder . $this->subsubfolder . '/'
- . $this->filename, $this->dataShort);
+ . $this->filename, $this->dataShort);
// test that data was successfully written
$this->assertTrue(is_int($cryptedFile1));
@@ -925,8 +1010,8 @@ class Share extends TestCase {
// remove share file
$this->view->unlink('/' . self::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/keys/'
- . $this->filename . '/' . self::TEST_ENCRYPTION_SHARE_USER3
- . '.shareKey');
+ . $this->filename . '/' . self::TEST_ENCRYPTION_SHARE_USER3
+ . '.shareKey');
// re-enable the file proxy
\OC_FileProxy::$enabled = $proxyStatus;
@@ -990,7 +1075,7 @@ class Share extends TestCase {
// move the file to a subfolder
$this->view->rename('/' . self::TEST_ENCRYPTION_SHARE_USER2 . '/files/' . $this->filename,
- '/' . self::TEST_ENCRYPTION_SHARE_USER2 . '/files/' . $this->folder1 . $this->filename);
+ '/' . self::TEST_ENCRYPTION_SHARE_USER2 . '/files/' . $this->folder1 . $this->filename);
// check if we can read the moved file
$retrievedRenamedFile = $this->view->file_get_contents(
@@ -1122,4 +1207,4 @@ class Share extends TestCase {
\OC\Files\Filesystem::unlink($folder);
}
-}
+} \ No newline at end of file
diff --git a/apps/files_sharing/ajax/external.php b/apps/files_sharing/ajax/external.php
index 6d68b5f7f82..1a709eda07c 100644
--- a/apps/files_sharing/ajax/external.php
+++ b/apps/files_sharing/ajax/external.php
@@ -31,10 +31,11 @@ if(!\OCP\Util::isValidFileName($name)) {
}
$externalManager = new \OCA\Files_Sharing\External\Manager(
- \OC::$server->getDatabaseConnection(),
- \OC\Files\Filesystem::getMountManager(),
- \OC\Files\Filesystem::getLoader(),
- \OC::$server->getUserSession()
+ \OC::$server->getDatabaseConnection(),
+ \OC\Files\Filesystem::getMountManager(),
+ \OC\Files\Filesystem::getLoader(),
+ \OC::$server->getUserSession(),
+ \OC::$server->getHTTPHelper()
);
$name = OCP\Files::buildNotExistingFileName('/', $name);
@@ -44,7 +45,7 @@ if (substr($remote, 0, 5) === 'https' and !OC_Util::getUrlContent($remote)) {
\OCP\JSON::error(array('data' => array('message' => $l->t("Invalid or untrusted SSL certificate"))));
exit;
} else {
- $mount = $externalManager->addShare($remote, $token, $password, $name, $owner);
+ $mount = $externalManager->addShare($remote, $token, $password, $name, $owner, true);
/**
* @var \OCA\Files_Sharing\External\Storage $storage
*/
diff --git a/apps/files_sharing/api/server2server.php b/apps/files_sharing/api/server2server.php
index 2949e2dd09c..f78d64caa73 100644
--- a/apps/files_sharing/api/server2server.php
+++ b/apps/files_sharing/api/server2server.php
@@ -34,7 +34,7 @@ class Server2Server {
public function createShare($params) {
if (!$this->isS2SEnabled(true)) {
- return \OC_OCS_Result(null, 503, 'Server does not support server-to-server sharing');
+ return new \OC_OCS_Result(null, 503, 'Server does not support server-to-server sharing');
}
$remote = isset($_POST['remote']) ? $_POST['remote'] : null;
@@ -42,7 +42,7 @@ class Server2Server {
$name = isset($_POST['name']) ? $_POST['name'] : null;
$owner = isset($_POST['owner']) ? $_POST['owner'] : null;
$shareWith = isset($_POST['shareWith']) ? $_POST['shareWith'] : null;
- $remoteId = isset($_POST['remote_id']) ? (int)$_POST['remote_id'] : null;
+ $remoteId = isset($_POST['remoteId']) ? (int)$_POST['remoteId'] : null;
if ($remote && $token && $name && $owner && $remoteId && $shareWith) {
@@ -56,19 +56,28 @@ class Server2Server {
\OC_Util::setupFS($shareWith);
- $mountPoint = \OC\Files\Filesystem::normalizePath('/' . $name);
+ $externalManager = new \OCA\Files_Sharing\External\Manager(
+ \OC::$server->getDatabaseConnection(),
+ \OC\Files\Filesystem::getMountManager(),
+ \OC\Files\Filesystem::getLoader(),
+ \OC::$server->getUserSession(),
+ \OC::$server->getHTTPHelper());
+
$name = \OCP\Files::buildNotExistingFileName('/', $name);
try {
- \OCA\Files_Sharing\Helper::addServer2ServerShare($remote, $token, $name, $mountPoint, $owner, $shareWith, '', $remoteId);
+ $externalManager->addShare($remote, $token, '', $name, $owner, false, $shareWith, $remoteId);
+
+ $user = $owner . '@' . $this->cleanupRemote($remote);
\OC::$server->getActivityManager()->publishActivity(
- 'files_sharing', \OCA\Files_Sharing\Activity::SUBJECT_REMOTE_SHARE_RECEIVED, array($owner), '', array(),
- '', '', $shareWith, \OCA\Files_Sharing\Activity::TYPE_REMOTE_SHARE, \OCA\Files_Sharing\Activity::PRIORITY_LOW);
+ 'files_sharing', \OCA\Files_Sharing\Activity::SUBJECT_REMOTE_SHARE_RECEIVED, array($user), '', array(),
+ '', '', $shareWith, \OCA\Files_Sharing\Activity::TYPE_REMOTE_SHARE, \OCA\Files_Sharing\Activity::PRIORITY_LOW);
return new \OC_OCS_Result();
} catch (\Exception $e) {
- return new \OC_OCS_Result(null, 500, 'server can not add remote share, ' . $e->getMessage());
+ \OCP\Util::writeLog('files_sharing', 'server can not add remote share, ' . $e->getMessage(), \OCP\Util::ERROR);
+ return new \OC_OCS_Result(null, 500, 'internal server error, was not able to add share from ' . $remote);
}
}
@@ -84,7 +93,7 @@ class Server2Server {
public function acceptShare($params) {
if (!$this->isS2SEnabled()) {
- return \OC_OCS_Result(null, 503, 'Server does not support server-to-server sharing');
+ return new \OC_OCS_Result(null, 503, 'Server does not support server-to-server sharing');
}
$id = $params['id'];
@@ -95,8 +104,8 @@ class Server2Server {
list($file, $link) = self::getFile($share['uid_owner'], $share['file_source']);
\OC::$server->getActivityManager()->publishActivity(
- 'files_sharing', \OCA\Files_Sharing\Activity::SUBJECT_REMOTE_SHARE_ACCEPTED, array($share['share_with'], basename($file)), '', array(),
- $file, $link, $share['uid_owner'], \OCA\Files_Sharing\Activity::TYPE_REMOTE_SHARE, \OCA\Files_Sharing\Activity::PRIORITY_LOW);
+ 'files_sharing', \OCA\Files_Sharing\Activity::SUBJECT_REMOTE_SHARE_ACCEPTED, array($share['share_with'], basename($file)), '', array(),
+ $file, $link, $share['uid_owner'], \OCA\Files_Sharing\Activity::TYPE_REMOTE_SHARE, \OCA\Files_Sharing\Activity::PRIORITY_LOW);
}
return new \OC_OCS_Result();
@@ -111,7 +120,7 @@ class Server2Server {
public function declineShare($params) {
if (!$this->isS2SEnabled()) {
- return \OC_OCS_Result(null, 503, 'Server does not support server-to-server sharing');
+ return new \OC_OCS_Result(null, 503, 'Server does not support server-to-server sharing');
}
$id = $params['id'];
@@ -126,8 +135,8 @@ class Server2Server {
list($file, $link) = $this->getFile($share['uid_owner'], $share['file_source']);
\OC::$server->getActivityManager()->publishActivity(
- 'files_sharing', \OCA\Files_Sharing\Activity::SUBJECT_REMOTE_SHARE_DECLINED, array($share['share_with'], basename($file)), '', array(),
- $file, $link, $share['uid_owner'], \OCA\Files_Sharing\Activity::TYPE_REMOTE_SHARE, \OCA\Files_Sharing\Activity::PRIORITY_LOW);
+ 'files_sharing', \OCA\Files_Sharing\Activity::SUBJECT_REMOTE_SHARE_DECLINED, array($share['share_with'], basename($file)), '', array(),
+ $file, $link, $share['uid_owner'], \OCA\Files_Sharing\Activity::TYPE_REMOTE_SHARE, \OCA\Files_Sharing\Activity::PRIORITY_LOW);
}
return new \OC_OCS_Result();
@@ -142,7 +151,7 @@ class Server2Server {
public function unshare($params) {
if (!$this->isS2SEnabled()) {
- return \OC_OCS_Result(null, 503, 'Server does not support server-to-server sharing');
+ return new \OC_OCS_Result(null, 503, 'Server does not support server-to-server sharing');
}
$id = $params['id'];
@@ -154,7 +163,9 @@ class Server2Server {
if ($token && $id && !empty($share)) {
- $owner = $share['owner'] . '@' . $share['remote'];
+ $remote = $this->cleanupRemote($share['remote']);
+
+ $owner = $share['owner'] . '@' . $remote;
$mountpoint = $share['mountpoint'];
$user = $share['user'];
@@ -162,13 +173,19 @@ class Server2Server {
$query->execute(array($id, $token));
\OC::$server->getActivityManager()->publishActivity(
- 'files_sharing', \OCA\Files_Sharing\Activity::SUBJECT_REMOTE_SHARE_DECLINED, array($owner, $mountpoint), '', array(),
- '', '', $user, \OCA\Files_Sharing\Activity::TYPE_REMOTE_SHARE, \OCA\Files_Sharing\Activity::PRIORITY_MEDIUM);
+ 'files_sharing', \OCA\Files_Sharing\Activity::SUBJECT_REMOTE_SHARE_UNSHARED, array($owner, $mountpoint), '', array(),
+ '', '', $user, \OCA\Files_Sharing\Activity::TYPE_REMOTE_SHARE, \OCA\Files_Sharing\Activity::PRIORITY_MEDIUM);
}
return new \OC_OCS_Result();
}
+ private function cleanupRemote($remote) {
+ $remote = substr($remote, strpos($remote, '://') + 3);
+
+ return rtrim($remote, '/');
+ }
+
/**
* get share
*
diff --git a/apps/files_sharing/appinfo/routes.php b/apps/files_sharing/appinfo/routes.php
index 41bdf554fc5..dd9509575b7 100644
--- a/apps/files_sharing/appinfo/routes.php
+++ b/apps/files_sharing/appinfo/routes.php
@@ -1,5 +1,16 @@
<?php
+namespace OCA\Files_Sharing\AppInfo;
+
+use OCA\Files_Sharing\Application;
+
+$application = new Application();
+$application->registerRoutes($this, [
+ 'resources' => [
+ 'ExternalShares' => ['url' => '/api/externalShares'],
+ ]
+]);
+
/** @var $this \OCP\Route\IRouter */
$this->create('core_ajax_public_preview', '/publicpreview')->action(
function() {
@@ -16,31 +27,32 @@ $this->create('sharing_external_add', '/external')
->actionInclude('files_sharing/ajax/external.php');
$this->create('sharing_external_test_remote', '/testremote')
->actionInclude('files_sharing/ajax/testremote.php');
+
// OCS API
//TODO: SET: mail notification, waiting for PR #4689 to be accepted
-OC_API::register('get',
+\OC_API::register('get',
'/apps/files_sharing/api/v1/shares',
array('\OCA\Files_Sharing\API\Local', 'getAllShares'),
'files_sharing');
-OC_API::register('post',
+\OC_API::register('post',
'/apps/files_sharing/api/v1/shares',
array('\OCA\Files_Sharing\API\Local', 'createShare'),
'files_sharing');
-OC_API::register('get',
+\OC_API::register('get',
'/apps/files_sharing/api/v1/shares/{id}',
array('\OCA\Files_Sharing\API\Local', 'getShare'),
'files_sharing');
-OC_API::register('put',
+\OC_API::register('put',
'/apps/files_sharing/api/v1/shares/{id}',
array('\OCA\Files_Sharing\API\Local', 'updateShare'),
'files_sharing');
-OC_API::register('delete',
+\OC_API::register('delete',
'/apps/files_sharing/api/v1/shares/{id}',
array('\OCA\Files_Sharing\API\Local', 'deleteShare'),
'files_sharing');
diff --git a/apps/files_sharing/application.php b/apps/files_sharing/application.php
index 089ed6afbda..9fe8785df0b 100644
--- a/apps/files_sharing/application.php
+++ b/apps/files_sharing/application.php
@@ -11,6 +11,7 @@
namespace OCA\Files_Sharing;
use OC\AppFramework\Utility\SimpleContainer;
+use OCA\Files_Sharing\Controllers\ExternalSharesController;
use OCA\Files_Sharing\Controllers\ShareController;
use OCA\Files_Sharing\Middleware\SharingCheckMiddleware;
use \OCP\AppFramework\App;
@@ -44,6 +45,14 @@ class Application extends App {
$c->query('ServerContainer')->getLogger()
);
});
+ $container->registerService('ExternalSharesController', function(SimpleContainer $c) {
+ return new ExternalSharesController(
+ $c->query('AppName'),
+ $c->query('Request'),
+ $c->query('IsIncomingShareEnabled'),
+ $c->query('ExternalManager')
+ );
+ });
/**
* Core class wrappers
@@ -54,6 +63,18 @@ class Application extends App {
$container->registerService('URLGenerator', function(SimpleContainer $c) {
return $c->query('ServerContainer')->getUrlGenerator();
});
+ $container->registerService('IsIncomingShareEnabled', function(SimpleContainer $c) {
+ return Helper::isIncomingServer2serverShareEnabled();
+ });
+ $container->registerService('ExternalManager', function(SimpleContainer $c) {
+ return new \OCA\Files_Sharing\External\Manager(
+ \OC::$server->getDatabaseConnection(),
+ \OC\Files\Filesystem::getMountManager(),
+ \OC\Files\Filesystem::getLoader(),
+ \OC::$server->getUserSession(),
+ \OC::$server->getHTTPHelper()
+ );
+ });
/**
* Middleware
diff --git a/apps/files_sharing/js/external.js b/apps/files_sharing/js/external.js
index 6ede2584cd9..aeb4b2461f8 100644
--- a/apps/files_sharing/js/external.js
+++ b/apps/files_sharing/js/external.js
@@ -8,16 +8,6 @@
*
*/
(function () {
- var addExternalShare = function (remote, token, owner, name, password) {
- return $.post(OC.generateUrl('apps/files_sharing/external'), {
- remote: remote,
- token: token,
- owner: owner,
- name: name,
- password: password
- });
- };
-
/**
* Shows "add external share" dialog.
*
@@ -27,20 +17,12 @@
* @param {String} token authentication token
* @param {bool} passwordProtected true if the share is password protected
*/
- OCA.Sharing.showAddExternalDialog = function (remote, token, owner, name, passwordProtected) {
+ OCA.Sharing.showAddExternalDialog = function (share, passwordProtected, callback) {
+ var remote = share.remote;
+ var owner = share.owner;
+ var name = share.name;
var remoteClean = (remote.substr(0, 8) === 'https://') ? remote.substr(8) : remote.substr(7);
- var callback = function (add, password) {
- password = password || '';
- if (add) {
- addExternalShare(remote, token, owner, name, password).then(function (result) {
- if (result.status === 'error') {
- OC.Notification.show(result.data.message);
- } else {
- FileList.reload();
- }
- });
- }
- };
+
if (!passwordProtected) {
OC.dialogs.confirm(
t(
@@ -49,7 +31,9 @@
{name: name, owner: owner, remote: remoteClean}
),
t('files_sharing','Remote share'),
- callback,
+ function (result) {
+ callback(result, share);
+ },
true
).then(this._adjustDialog);
} else {
@@ -60,7 +44,9 @@
{name: name, owner: owner, remote: remoteClean}
),
t('files_sharing','Remote share'),
- callback,
+ function (result) {
+ callback(result, share);
+ },
true,
t('files_sharing','Remote share password'),
true
@@ -82,17 +68,66 @@ $(document).ready(function () {
// FIXME: HACK: do not init when running unit tests, need a better way
if (!window.TESTING && OCA.Files) {// only run in the files app
var params = OC.Util.History.parseUrlQuery();
+
+ //manually add server-to-server share
if (params.remote && params.token && params.owner && params.name) {
+
+ var callbackAddShare = function(result, share) {
+ var password = share.password || '';
+ if (result) {
+ //$.post(OC.generateUrl('/apps/files_sharing/api/externalShares'), {id: share.id});
+ $.post(OC.generateUrl('apps/files_sharing/external'), {
+ remote: share.remote,
+ token: share.token,
+ owner: share.owner,
+ name: share.name,
+ password: password}, function(result) {
+ if (result.status === 'error') {
+ OC.Notification.show(result.data.message);
+ } else {
+ FileList.reload();
+ }
+ });
+ }
+ };
+
// clear hash, it is unlikely that it contain any extra parameters
location.hash = '';
params.passwordProtected = parseInt(params.protected, 10) === 1;
OCA.Sharing.showAddExternalDialog(
- params.remote,
- params.token,
- params.owner,
- params.name,
- params.passwordProtected
+ params,
+ params.passwordProtected,
+ callbackAddShare
);
}
+
+ // check for new server-to-server shares which need to be approved
+ $.get(OC.generateUrl('/apps/files_sharing/api/externalShares'),
+ {},
+ function(shares) {
+ var index;
+ for (index = 0; index < shares.length; ++index) {
+ OCA.Sharing.showAddExternalDialog(
+ shares[index],
+ false,
+ function(result, share) {
+ if (result) {
+ // Accept
+ $.post(OC.generateUrl('/apps/files_sharing/api/externalShares'), {id: share.id});
+ FileList.reload();
+ } else {
+ // Delete
+ $.ajax({
+ url: OC.generateUrl('/apps/files_sharing/api/externalShares/'+share.id),
+ type: 'DELETE'
+ });
+ }
+ }
+ );
+ }
+
+ });
+
}
+
});
diff --git a/apps/files_sharing/lib/activity.php b/apps/files_sharing/lib/activity.php
index 979df1c1da6..868830d80cd 100644
--- a/apps/files_sharing/lib/activity.php
+++ b/apps/files_sharing/lib/activity.php
@@ -98,7 +98,7 @@ class Activity implements \OCP\Activity\IExtension {
case self::SUBJECT_REMOTE_SHARE_DECLINED:
return $l->t('%1$s declined remote share %2$s', $params)->__toString();
case self::SUBJECT_REMOTE_SHARE_UNSHARED:
- return $l->t('%1$s unshared %2$s', $params)->__toString();
+ return $l->t('%1$s unshared %2$s from you', $params)->__toString();
}
}
}
diff --git a/apps/files_sharing/lib/connector/publicauth.php b/apps/files_sharing/lib/connector/publicauth.php
index 4144dafa379..a630d091fd4 100644
--- a/apps/files_sharing/lib/connector/publicauth.php
+++ b/apps/files_sharing/lib/connector/publicauth.php
@@ -69,6 +69,8 @@ class PublicAuth extends \Sabre\DAV\Auth\Backend\AbstractBasic {
} else {
return false;
}
+ } elseif ($linkItem['share_type'] == \OCP\Share::SHARE_TYPE_REMOTE) {
+ return true;
} else {
return false;
}
diff --git a/apps/files_sharing/lib/controllers/externalsharescontroller.php b/apps/files_sharing/lib/controllers/externalsharescontroller.php
new file mode 100644
index 00000000000..773ff8ce981
--- /dev/null
+++ b/apps/files_sharing/lib/controllers/externalsharescontroller.php
@@ -0,0 +1,86 @@
+<?php
+/**
+ * @author Lukas Reschke <lukas@owncloud.com>
+ * @copyright 2014 Lukas Reschke
+ *
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OCA\Files_Sharing\Controllers;
+
+use OC;
+use OCP;
+use OCP\AppFramework\Controller;
+use OCP\IRequest;
+use OCP\AppFramework\Http\JSONResponse;
+
+/**
+ * Class ExternalSharesController
+ *
+ * @package OCA\Files_Sharing\Controllers
+ */
+class ExternalSharesController extends Controller {
+
+ /** @var bool */
+ private $incomingShareEnabled;
+ /** @var \OCA\Files_Sharing\External\Manager */
+ private $externalManager;
+
+ /**
+ * @param string $appName
+ * @param IRequest $request
+ * @param \OCA\Files_Sharing\External\Manager $externalManager
+ */
+ public function __construct($appName,
+ IRequest $request,
+ $incomingShareEnabled,
+ \OCA\Files_Sharing\External\Manager $externalManager) {
+ parent::__construct($appName, $request);
+ $this->incomingShareEnabled = $incomingShareEnabled;
+ $this->externalManager = $externalManager;
+ }
+
+ /**
+ * @NoAdminRequired
+ *
+ * @return JSONResponse
+ */
+ public function index() {
+ $shares = [];
+ if ($this->incomingShareEnabled) {
+ $shares = $this->externalManager->getOpenShares();
+ }
+ return new JSONResponse($shares);
+ }
+
+ /**
+ * @NoAdminRequired
+ *
+ * @param int $id
+ * @return JSONResponse
+ */
+ public function create($id) {
+ if ($this->incomingShareEnabled) {
+ $this->externalManager->acceptShare($id);
+ }
+
+ return new JSONResponse();
+ }
+
+ /**
+ * @NoAdminRequired
+ *
+ * @param $id
+ * @return JSONResponse
+ */
+ public function destroy($id) {
+ if ($this->incomingShareEnabled) {
+ $this->externalManager->declineShare($id);
+ }
+
+ return new JSONResponse();
+ }
+
+}
diff --git a/apps/files_sharing/lib/external/manager.php b/apps/files_sharing/lib/external/manager.php
index b52e1a5044e..665e47c0fe9 100644
--- a/apps/files_sharing/lib/external/manager.php
+++ b/apps/files_sharing/lib/external/manager.php
@@ -34,25 +34,41 @@ class Manager {
private $userSession;
/**
+ * @var \OC\HTTPHelper
+ */
+ private $httpHelper;
+
+ /**
* @param \OCP\IDBConnection $connection
* @param \OC\Files\Mount\Manager $mountManager
* @param \OC\User\Session $userSession
* @param \OC\Files\Storage\StorageFactory $storageLoader
*/
public function __construct(\OCP\IDBConnection $connection, \OC\Files\Mount\Manager $mountManager,
- \OC\Files\Storage\StorageFactory $storageLoader, \OC\User\Session $userSession) {
+ \OC\Files\Storage\StorageFactory $storageLoader, \OC\User\Session $userSession, \OC\HTTPHelper $httpHelper) {
$this->connection = $connection;
$this->mountManager = $mountManager;
$this->userSession = $userSession;
$this->storageLoader = $storageLoader;
+ $this->httpHelper = $httpHelper;
}
- public function addShare($remote, $token, $password, $name, $owner) {
- $user = $this->userSession->getUser();
- if ($user) {
- $mountPoint = Filesystem::normalizePath('/' . $name);
- \OCA\Files_Sharing\Helper::addServer2ServerShare($remote, $token, $name, $mountPoint, $owner, $user->getUID(), $password, -1, true);
+ public function addShare($remote, $token, $password, $name, $owner, $accepted=false, $user = null, $remoteId = -1) {
+
+ $user = $user ? $user: $this->userSession->getUser()->getUID();
+ $accepted = $accepted ? 1 : 0;
+ $mountPoint = Filesystem::normalizePath('/' . $name);
+
+ $query = $this->connection->prepare('
+ INSERT INTO `*PREFIX*share_external`
+ (`remote`, `share_token`, `password`, `name`, `owner`, `user`, `mountpoint`, `mountpoint_hash`, `accepted`, `remote_id`)
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+ ');
+ $hash = md5($mountPoint);
+ $query->execute(array($remote, $token, $password, $name, $owner, $user, $mountPoint, $hash, $accepted, $remoteId));
+
+ if ($accepted) {
$options = array(
'remote' => $remote,
'token' => $token,
@@ -87,12 +103,85 @@ class Manager {
}
}
+ /**
+ * get share
+ *
+ * @param int $id share id
+ * @return mixed share of false
+ */
+ private function getShare($id) {
+ $getShare = $this->connection->prepare('
+ SELECT `remote`, `share_token`
+ FROM `*PREFIX*share_external`
+ WHERE `id` = ? AND `user` = ?');
+ $result = $getShare->execute(array($id, $this->userSession->getUser()->getUID()));
+
+ return $result ? $getShare->fetch() : false;
+ }
+
+ /**
+ * accept server-to-server share
+ *
+ * @param int $id
+ */
+ public function acceptShare($id) {
+
+ $share = $this->getShare($id);
+
+ if ($share) {
+ $acceptShare = $this->connection->prepare('
+ UPDATE `*PREFIX*share_external`
+ SET `accepted` = ?
+ WHERE `id` = ? AND `user` = ?');
+ $acceptShare->execute(array(1, $id, $this->userSession->getUser()->getUID()));
+ $this->sendFeedbackToRemote($share['remote'], $share['share_token'], $id, 'accept');
+ }
+ }
+
+ /**
+ * decline server-to-server share
+ *
+ * @param int $id
+ */
+ public function declineShare($id) {
+
+ $share = $this->getShare($id);
+
+ if ($share) {
+ $removeShare = $this->connection->prepare('
+ DELETE FROM `*PREFIX*share_external` WHERE `id` = ? AND `user` = ?');
+ $removeShare->execute(array($id, $this->userSession->getUser()->getUID()));
+ $this->sendFeedbackToRemote($share['remote'], $share['share_token'], $id, 'decline');
+ }
+ }
+
+ /**
+ * inform remote server whether server-to-server share was accepted/declined
+ *
+ * @param string $remote
+ * @param string $token
+ * @param int $id
+ * @param string $feedback
+ * @return boolean
+ */
+ private function sendFeedbackToRemote($remote, $token, $id, $feedback) {
+
+ $url = $remote . \OCP\Share::BASE_PATH_TO_SHARE_API . '/' . $id . '/' . $feedback . '?format=' . \OCP\Share::RESPONSE_FORMAT;
+ $fields = array('token' => $token);
+
+ $result = $this->httpHelper->post($url, $fields);
+ $status = json_decode($result['result'], true);
+
+ return ($result['success'] && $status['ocs']['meta']['statuscode'] === 100);
+ }
+
public static function setup() {
$externalManager = new \OCA\Files_Sharing\External\Manager(
- \OC::$server->getDatabaseConnection(),
- \OC\Files\Filesystem::getMountManager(),
- \OC\Files\Filesystem::getLoader(),
- \OC::$server->getUserSession()
+ \OC::$server->getDatabaseConnection(),
+ \OC\Files\Filesystem::getMountManager(),
+ \OC\Files\Filesystem::getLoader(),
+ \OC::$server->getUserSession(),
+ \OC::$server->getHTTPHelper()
);
$externalManager->setupMounts();
}
@@ -151,6 +240,18 @@ class Manager {
$user = $this->userSession->getUser();
$mountPoint = $this->stripPath($mountPoint);
$hash = md5($mountPoint);
+
+ $getShare = $this->connection->prepare('
+ SELECT `remote`, `share_token`, `remote_id`
+ FROM `*PREFIX*share_external`
+ WHERE `mountpoint_hash` = ? AND `user` = ?');
+ $result = $getShare->execute(array($hash, $user->getUID()));
+
+ if ($result) {
+ $share = $getShare->fetch();
+ $this->sendFeedbackToRemote($share['remote'], $share['share_token'], $share['remote_id'], 'decline');
+ }
+
$query = $this->connection->prepare('
DELETE FROM `*PREFIX*share_external`
WHERE `mountpoint_hash` = ?
@@ -158,4 +259,17 @@ class Manager {
');
return (bool)$query->execute(array($hash, $user->getUID()));
}
-}
+
+ /**
+ * return a list of shares which are not yet accepted by the user
+ *
+ * @return array list of open server-to-server shares
+ */
+ public function getOpenShares() {
+ $openShares = $this->connection->prepare('SELECT * FROM `*PREFIX*share_external` WHERE `accepted` = ? AND `user` = ?');
+ $result = $openShares->execute(array(0, $this->userSession->getUser()->getUID()));
+
+ return $result ? $openShares->fetchAll() : array();
+
+ }
+} \ No newline at end of file
diff --git a/apps/files_sharing/lib/helper.php b/apps/files_sharing/lib/helper.php
index 71519bd1d4a..001d0387fa4 100644
--- a/apps/files_sharing/lib/helper.php
+++ b/apps/files_sharing/lib/helper.php
@@ -2,8 +2,6 @@
namespace OCA\Files_Sharing;
-use OC_Config;
-
class Helper {
public static function registerHooks() {
@@ -21,30 +19,6 @@ class Helper {
}
/**
- * add server-to-server share to database
- *
- * @param string $remote
- * @param string $token
- * @param string $name
- * @param string $mountPoint
- * @param string $owner
- * @param string $user
- * @param string $password
- * @param int $remoteId
- * @param bool $accepted
- */
- public static function addServer2ServerShare($remote, $token, $name, $mountPoint, $owner, $user, $password='', $remoteId=-1, $accepted = false) {
- $accepted = $accepted ? 1 : 0;
- $query = \OCP\DB::prepare('
- INSERT INTO `*PREFIX*share_external`
- (`remote`, `share_token`, `password`, `name`, `owner`, `user`, `mountpoint`, `mountpoint_hash`, `accepted`, `remote_id`)
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
- ');
- $hash = md5($mountPoint);
- $query->execute(array($remote, $token, $password, $name, $owner, $user, $mountPoint, $hash, $accepted, $remoteId));
- }
-
- /**
* Sets up the filesystem and user for public sharing
* @param string $token string share token
* @param string $relativePath optional path relative to the share
@@ -89,7 +63,7 @@ class Helper {
exit();
}
- if (isset($linkItem['share_with'])) {
+ if (isset($linkItem['share_with']) && (int)$linkItem['share_type'] === \OCP\Share::SHARE_TYPE_LINK) {
if (!self::authenticate($linkItem, $password)) {
\OC_Response::setStatus(403);
\OCP\JSON::error(array('success' => false));
diff --git a/apps/files_sharing/lib/share/file.php b/apps/files_sharing/lib/share/file.php
index a5b4e75bceb..93e4af3c393 100644
--- a/apps/files_sharing/lib/share/file.php
+++ b/apps/files_sharing/lib/share/file.php
@@ -160,6 +160,20 @@ class OC_Share_Backend_File implements OCP\Share_Backend_File_Dependent {
}
/**
+ * check if server2server share is enabled
+ *
+ * @param int $shareType
+ * @return boolean
+ */
+ public function isShareTypeAllowed($shareType) {
+ if ($shareType === \OCP\Share::SHARE_TYPE_REMOTE) {
+ return \OCA\Files_Sharing\Helper::isOutgoingServer2serverShareEnabled();
+ }
+
+ return true;
+ }
+
+ /**
* resolve reshares to return the correct source item
* @param array $source
* @return array source item
diff --git a/apps/files_sharing/lib/updater.php b/apps/files_sharing/lib/updater.php
index a34140f5a35..9d8ae7cbb4f 100644
--- a/apps/files_sharing/lib/updater.php
+++ b/apps/files_sharing/lib/updater.php
@@ -161,7 +161,10 @@ class Shared_Updater {
*/
static public function postUnshareHook($params) {
- if ($params['itemType'] === 'file' || $params['itemType'] === 'folder') {
+ // only update etags for file/folders shared to local users/groups
+ if (($params['itemType'] === 'file' || $params['itemType'] === 'folder') &&
+ $params['shareType'] !== \OCP\Share::SHARE_TYPE_LINK &&
+ $params['shareType'] !== \OCP\Share::SHARE_TYPE_REMOTE) {
$deletedShares = isset($params['deletedShares']) ? $params['deletedShares'] : array();
@@ -212,7 +215,7 @@ class Shared_Updater {
/**
* rename mount point from the children if the parent was renamed
- *
+ *
* @param string $oldPath old path relative to data/user/files
* @param string $newPath new path relative to data/user/files
*/
diff --git a/apps/files_sharing/tests/server2server.php b/apps/files_sharing/tests/server2server.php
index 7aec0c4951f..0400d357b82 100644
--- a/apps/files_sharing/tests/server2server.php
+++ b/apps/files_sharing/tests/server2server.php
@@ -38,6 +38,16 @@ class Test_Files_Sharing_S2S_OCS_API extends TestCase {
self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
\OCP\Share::registerBackend('test', 'Test_Share_Backend');
+ $config = $this->getMockBuilder('\OCP\IConfig')
+ ->disableOriginalConstructor()->getMock();
+ $certificateManager = $this->getMock('\OCP\ICertificateManager');
+ $httpHelperMock = $this->getMockBuilder('\OC\HTTPHelper')
+ ->setConstructorArgs(array($config, $certificateManager))
+ ->getMock();
+ $httpHelperMock->expects($this->any())->method('post')->with($this->anything())->will($this->returnValue(true));
+
+ $this->registerHttpHelper($httpHelperMock);
+
$this->s2s = new \OCA\Files_Sharing\API\Server2Server();
}
@@ -45,10 +55,33 @@ class Test_Files_Sharing_S2S_OCS_API extends TestCase {
$query = \OCP\DB::prepare('DELETE FROM `*PREFIX*share_external`');
$query->execute();
+ $this->restoreHttpHelper();
+
parent::tearDown();
}
/**
+ * Register an http helper mock for testing purposes.
+ * @param $httpHelper http helper mock
+ */
+ private function registerHttpHelper($httpHelper) {
+ $this->oldHttpHelper = \OC::$server->query('HTTPHelper');
+ \OC::$server->registerService('HTTPHelper', function ($c) use ($httpHelper) {
+ return $httpHelper;
+ });
+ }
+
+ /**
+ * Restore the original http helper
+ */
+ private function restoreHttpHelper() {
+ $oldHttpHelper = $this->oldHttpHelper;
+ \OC::$server->registerService('HTTPHelper', function ($c) use ($oldHttpHelper) {
+ return $oldHttpHelper;
+ });
+ }
+
+ /**
* @medium
*/
function testCreateShare() {
@@ -58,7 +91,7 @@ class Test_Files_Sharing_S2S_OCS_API extends TestCase {
$_POST['name'] = 'name';
$_POST['owner'] = 'owner';
$_POST['shareWith'] = self::TEST_FILES_SHARING_API_USER2;
- $_POST['remote_id'] = 1;
+ $_POST['remoteId'] = 1;
$result = $this->s2s->createShare(null);
@@ -81,10 +114,10 @@ class Test_Files_Sharing_S2S_OCS_API extends TestCase {
function testDeclineShare() {
$dummy = \OCP\DB::prepare('
INSERT INTO `*PREFIX*share`
- (`share_type`, `uid_owner`, `item_type`, `item_source`, `item_target`, `file_source`, `file_target`, `permissions`, `stime`, `token`)
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+ (`share_type`, `uid_owner`, `item_type`, `item_source`, `item_target`, `file_source`, `file_target`, `permissions`, `stime`, `token`, `share_with`)
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
');
- $dummy->execute(array(\OCP\Share::SHARE_TYPE_REMOTE, self::TEST_FILES_SHARING_API_USER1, 'test', '1', '/1', '1', '/test.txt', '1', time(), 'token'));
+ $dummy->execute(array(\OCP\Share::SHARE_TYPE_REMOTE, self::TEST_FILES_SHARING_API_USER1, 'test', '1', '/1', '1', '/test.txt', '1', time(), 'token', 'foo@bar'));
$verify = \OCP\DB::prepare('SELECT * FROM `*PREFIX*share`');
$result = $verify->execute();