mirror of https://github.com/nextcloud/server.git
OCS API for server-to-server sharing
parent
f0e6876f2e
commit
698ecbf308
@ -0,0 +1,224 @@
|
||||
<?php
|
||||
/**
|
||||
* ownCloud - OCS API for server-to-server shares
|
||||
*
|
||||
* @copyright (C) 2014 ownCloud, Inc.
|
||||
*
|
||||
* @author Bjoern Schiessle <schiessle@owncloud.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or any later version.
|
||||
*
|
||||
* This library 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 library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OCA\Files_Sharing\API;
|
||||
|
||||
class Server2Server {
|
||||
|
||||
/**
|
||||
* create a new share
|
||||
*
|
||||
* @param array $params
|
||||
* @return \OC_OCS_Result
|
||||
*/
|
||||
public function createShare($params) {
|
||||
|
||||
if (!$this->isS2SEnabled(true)) {
|
||||
return \OC_OCS_Result(null, 503, 'Server does not support server-to-server sharing');
|
||||
}
|
||||
|
||||
$remote = isset($_POST['remote']) ? $_POST['remote'] : null;
|
||||
$token = isset($_POST['token']) ? $_POST['token'] : null;
|
||||
$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;
|
||||
|
||||
if ($remote && $token && $name && $owner && $remoteId && $shareWith) {
|
||||
|
||||
if(!\OCP\Util::isValidFileName($name)) {
|
||||
return new \OC_OCS_Result(null, 400, 'The mountpoint name contains invalid characters.');
|
||||
}
|
||||
|
||||
if (!\OCP\User::userExists($shareWith)) {
|
||||
return new \OC_OCS_Result(null, 400, 'User does not exists');
|
||||
}
|
||||
|
||||
\OC_Util::setupFS($shareWith);
|
||||
|
||||
$mountPoint = \OC\Files\Filesystem::normalizePath('/' . $name);
|
||||
$name = \OCP\Files::buildNotExistingFileName('/', $name);
|
||||
|
||||
try {
|
||||
\OCA\Files_Sharing\Helper::addServer2ServerShare($remote, $token, $name, $mountPoint, $owner, $shareWith, '', $remoteId);
|
||||
|
||||
\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);
|
||||
|
||||
return new \OC_OCS_Result();
|
||||
} catch (\Exception $e) {
|
||||
return new \OC_OCS_Result(null, 500, 'server can not add remote share, ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return new \OC_OCS_Result(null, 400, 'server can not add remote share, missing parameter');
|
||||
}
|
||||
|
||||
/**
|
||||
* accept server-to-server share
|
||||
*
|
||||
* @param array $params
|
||||
* @return \OC_OCS_Result
|
||||
*/
|
||||
public function acceptShare($params) {
|
||||
|
||||
if (!$this->isS2SEnabled()) {
|
||||
return \OC_OCS_Result(null, 503, 'Server does not support server-to-server sharing');
|
||||
}
|
||||
|
||||
$id = $params['id'];
|
||||
$token = isset($_POST['token']) ? $_POST['token'] : null;
|
||||
$share = self::getShare($id, $token);
|
||||
|
||||
if ($share) {
|
||||
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);
|
||||
}
|
||||
|
||||
return new \OC_OCS_Result();
|
||||
}
|
||||
|
||||
/**
|
||||
* decline server-to-server share
|
||||
*
|
||||
* @param array $params
|
||||
* @return \OC_OCS_Result
|
||||
*/
|
||||
public function declineShare($params) {
|
||||
|
||||
if (!$this->isS2SEnabled()) {
|
||||
return \OC_OCS_Result(null, 503, 'Server does not support server-to-server sharing');
|
||||
}
|
||||
|
||||
$id = $params['id'];
|
||||
$token = isset($_POST['token']) ? $_POST['token'] : null;
|
||||
|
||||
$share = $this->getShare($id, $token);
|
||||
|
||||
if ($share) {
|
||||
// userId must be set to the user who unshares
|
||||
\OCP\Share::unshare($share['item_type'], $share['item_source'], $share['share_type'], null, $share['uid_owner']);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
return new \OC_OCS_Result();
|
||||
}
|
||||
|
||||
/**
|
||||
* remove server-to-server share if it was unshared by the owner
|
||||
*
|
||||
* @param array $params
|
||||
* @return \OC_OCS_Result
|
||||
*/
|
||||
public function unshare($params) {
|
||||
|
||||
if (!$this->isS2SEnabled()) {
|
||||
return \OC_OCS_Result(null, 503, 'Server does not support server-to-server sharing');
|
||||
}
|
||||
|
||||
$id = $params['id'];
|
||||
$token = isset($_POST['token']) ? $_POST['token'] : null;
|
||||
|
||||
$query = \OCP\DB::prepare('SELECT * FROM `*PREFIX*share_external` WHERE `remote_id` = ? AND `share_token` = ?');
|
||||
$query->execute(array($id, $token));
|
||||
$share = $query->fetchRow();
|
||||
|
||||
if ($token && $id && !empty($share)) {
|
||||
|
||||
$owner = $share['owner'] . '@' . $share['remote'];
|
||||
$mountpoint = $share['mountpoint'];
|
||||
$user = $share['user'];
|
||||
|
||||
$query = \OCP\DB::prepare('DELETE FROM `*PREFIX*share_external` WHERE `remote_id` = ? AND `share_token` = ?');
|
||||
$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);
|
||||
}
|
||||
|
||||
return new \OC_OCS_Result();
|
||||
}
|
||||
|
||||
/**
|
||||
* get share
|
||||
*
|
||||
* @param int $id
|
||||
* @param string $token
|
||||
* @return array
|
||||
*/
|
||||
private function getShare($id, $token) {
|
||||
$query = \OCP\DB::prepare('SELECT * FROM `*PREFIX*share` WHERE `id` = ? AND `token` = ? AND `share_type` = ?');
|
||||
$query->execute(array($id, $token, \OCP\Share::SHARE_TYPE_REMOTE));
|
||||
$share = $query->fetchRow();
|
||||
|
||||
return $share;
|
||||
}
|
||||
|
||||
/**
|
||||
* get file
|
||||
*
|
||||
* @param string $user
|
||||
* @param int $fileSource
|
||||
* @return array with internal path of the file and a absolute link to it
|
||||
*/
|
||||
private function getFile($user, $fileSource) {
|
||||
\OC_Util::setupFS($user);
|
||||
|
||||
$file = \OC\Files\Filesystem::getPath($fileSource);
|
||||
$args = \OC\Files\Filesystem::is_dir($file) ? array('dir' => $file) : array('dir' => dirname($file), 'scrollto' => $file);
|
||||
$link = \OCP\Util::linkToAbsolute('files', 'index.php', $args);
|
||||
|
||||
return array($file, $link);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* check if server-to-server sharing is enabled
|
||||
*
|
||||
* @param bool $incoming
|
||||
* @return bool
|
||||
*/
|
||||
private function isS2SEnabled($incoming = false) {
|
||||
|
||||
$result = \OCP\App::isEnabled('files_sharing');
|
||||
|
||||
if ($incoming) {
|
||||
$result = $result && \OCA\Files_Sharing\Helper::isIncomingServer2serverShareEnabled();
|
||||
} else {
|
||||
$result = $result && \OCA\Files_Sharing\Helper::isOutgoingServer2serverShareEnabled();
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
@ -1 +1 @@
|
||||
0.5.3
|
||||
0.5.4
|
||||
|
@ -0,0 +1,165 @@
|
||||
<?php
|
||||
/**
|
||||
* ownCloud - publish activities
|
||||
*
|
||||
* @copyright (c) 2014, ownCloud Inc.
|
||||
*
|
||||
* @author Bjoern Schiessle <schiessle@owncloud.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or any later version.
|
||||
*
|
||||
* This library 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 library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace OCA\Files_Sharing;
|
||||
|
||||
class Activity implements \OCP\Activity\IExtension {
|
||||
|
||||
const TYPE_REMOTE_SHARE = 'remote_share';
|
||||
const SUBJECT_REMOTE_SHARE_RECEIVED = 'remote_share_received';
|
||||
const SUBJECT_REMOTE_SHARE_ACCEPTED = 'remote_share_accepted';
|
||||
const SUBJECT_REMOTE_SHARE_DECLINED = 'remote_share_declined';
|
||||
const SUBJECT_REMOTE_SHARE_UNSHARED = 'remote_share_unshared';
|
||||
|
||||
/**
|
||||
* The extension can return an array of additional notification types.
|
||||
* If no additional types are to be added false is to be returned
|
||||
*
|
||||
* @param string $languageCode
|
||||
* @return array|false
|
||||
*/
|
||||
public function getNotificationTypes($languageCode) {
|
||||
$l = \OC::$server->getL10N('files_sharing', $languageCode);
|
||||
return array(self::TYPE_REMOTE_SHARE => $l->t('A file or folder was shared from <strong>another server</strong>'));
|
||||
}
|
||||
|
||||
/**
|
||||
* The extension can filter the types based on the filter if required.
|
||||
* In case no filter is to be applied false is to be returned unchanged.
|
||||
*
|
||||
* @param array $types
|
||||
* @param string $filter
|
||||
* @return array|false
|
||||
*/
|
||||
public function filterNotificationTypes($types, $filter) {
|
||||
return $types;
|
||||
}
|
||||
|
||||
/**
|
||||
* For a given method additional types to be displayed in the settings can be returned.
|
||||
* In case no additional types are to be added false is to be returned.
|
||||
*
|
||||
* @param string $method
|
||||
* @return array|false
|
||||
*/
|
||||
public function getDefaultTypes($method) {
|
||||
if ($method === 'stream') {
|
||||
return array(self::TYPE_REMOTE_SHARE);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* The extension can translate a given message to the requested languages.
|
||||
* If no translation is available false is to be returned.
|
||||
*
|
||||
* @param string $app
|
||||
* @param string $text
|
||||
* @param array $params
|
||||
* @param boolean $stripPath
|
||||
* @param boolean $highlightParams
|
||||
* @param string $languageCode
|
||||
* @return string|false
|
||||
*/
|
||||
public function translate($app, $text, $params, $stripPath, $highlightParams, $languageCode) {
|
||||
|
||||
$l = \OC::$server->getL10N('files_sharing', $languageCode);
|
||||
|
||||
if (!$text) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ($app === 'files_sharing') {
|
||||
switch ($text) {
|
||||
case self::SUBJECT_REMOTE_SHARE_RECEIVED:
|
||||
return $l->t('You received a new remote share from %s', $params)->__toString();
|
||||
case self::SUBJECT_REMOTE_SHARE_ACCEPTED:
|
||||
return $l->t('%1$s accepted remote share <strong>%2$s</strong>', $params)->__toString();
|
||||
case self::SUBJECT_REMOTE_SHARE_DECLINED:
|
||||
return $l->t('%1$s declined remote share <strong>%2$s</strong>', $params)->__toString();
|
||||
case self::SUBJECT_REMOTE_SHARE_UNSHARED:
|
||||
return $l->t('%1$s unshared <strong>%2$s</strong>', $params)->__toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A string naming the css class for the icon to be used can be returned.
|
||||
* If no icon is known for the given type false is to be returned.
|
||||
*
|
||||
* @param string $type
|
||||
* @return string|false
|
||||
*/
|
||||
public function getTypeIcon($type) {
|
||||
return 'icon-share';
|
||||
}
|
||||
|
||||
/**
|
||||
* The extension can define the parameter grouping by returning the index as integer.
|
||||
* In case no grouping is required false is to be returned.
|
||||
*
|
||||
* @param array $activity
|
||||
* @return integer|false
|
||||
*/
|
||||
public function getGroupParameter($activity) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* The extension can define additional navigation entries. The array returned has to contain two keys 'top'
|
||||
* and 'apps' which hold arrays with the relevant entries.
|
||||
* If no further entries are to be added false is no be returned.
|
||||
*
|
||||
* @return array|false
|
||||
*/
|
||||
public function getNavigation() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* The extension can check if a customer filter (given by a query string like filter=abc) is valid or not.
|
||||
*
|
||||
* @param string $filterValue
|
||||
* @return boolean
|
||||
*/
|
||||
public function isFilterValid($filterValue) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* For a given filter the extension can specify the sql query conditions including parameters for that query.
|
||||
* In case the extension does not know the filter false is to be returned.
|
||||
* The query condition and the parameters are to be returned as array with two elements.
|
||||
* E.g. return array('`app` = ? and `message` like ?', array('mail', 'ownCloud%'));
|
||||
*
|
||||
* @param string $filter
|
||||
* @return array|false
|
||||
*/
|
||||
public function getQueryForFilter($filter) {
|
||||
if ($filter === 'shares') {
|
||||
return array('`app` = ? and `type` = ?', array('files_sharing', self::TYPE_REMOTE_SHARE));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,102 @@
|
||||
<?php
|
||||
/**
|
||||
* ownCloud - test server-to-server OCS API
|
||||
*
|
||||
* @copyright (c) ownCloud, Inc.
|
||||
*
|
||||
* @author Bjoern Schiessle <schiessle@owncloud.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or any later version.
|
||||
*
|
||||
* This library 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 library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
use OCA\Files_Sharing\Tests\TestCase;
|
||||
|
||||
/**
|
||||
* Class Test_Files_Sharing_Api
|
||||
*/
|
||||
class Test_Files_Sharing_S2S_OCS_API extends TestCase {
|
||||
|
||||
const TEST_FOLDER_NAME = '/folder_share_api_test';
|
||||
|
||||
private $s2s;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
|
||||
\OCP\Share::registerBackend('test', 'Test_Share_Backend');
|
||||
|
||||
$this->s2s = new \OCA\Files_Sharing\API\Server2Server();
|
||||
}
|
||||
|
||||
protected function tearDown() {
|
||||
$query = \OCP\DB::prepare('DELETE FROM `*PREFIX*share_external`');
|
||||
$query->execute();
|
||||
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* @medium
|
||||
*/
|
||||
function testCreateShare() {
|
||||
// simulate a post request
|
||||
$_POST['remote'] = 'localhost';
|
||||
$_POST['token'] = 'token';
|
||||
$_POST['name'] = 'name';
|
||||
$_POST['owner'] = 'owner';
|
||||
$_POST['shareWith'] = self::TEST_FILES_SHARING_API_USER2;
|
||||
$_POST['remote_id'] = 1;
|
||||
|
||||
$result = $this->s2s->createShare(null);
|
||||
|
||||
$this->assertTrue($result->succeeded());
|
||||
|
||||
$query = \OCP\DB::prepare('SELECT * FROM `*PREFIX*share_external` WHERE `remote_id` = ?');
|
||||
$result = $query->execute(array('1'));
|
||||
$data = $result->fetchRow();
|
||||
|
||||
$this->assertSame('localhost', $data['remote']);
|
||||
$this->assertSame('token', $data['share_token']);
|
||||
$this->assertSame('/name', $data['name']);
|
||||
$this->assertSame('owner', $data['owner']);
|
||||
$this->assertSame(self::TEST_FILES_SHARING_API_USER2, $data['user']);
|
||||
$this->assertSame(1, (int)$data['remote_id']);
|
||||
$this->assertSame(0, (int)$data['accepted']);
|
||||
}
|
||||
|
||||
|
||||
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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
');
|
||||
$dummy->execute(array(\OCP\Share::SHARE_TYPE_REMOTE, self::TEST_FILES_SHARING_API_USER1, 'test', '1', '/1', '1', '/test.txt', '1', time(), 'token'));
|
||||
|
||||
$verify = \OCP\DB::prepare('SELECT * FROM `*PREFIX*share`');
|
||||
$result = $verify->execute();
|
||||
$data = $result->fetchAll();
|
||||
$this->assertSame(1, count($data));
|
||||
|
||||
$_POST['token'] = 'token';
|
||||
$this->s2s->declineShare(array('id' => $data[0]['id']));
|
||||
|
||||
$verify = \OCP\DB::prepare('SELECT * FROM `*PREFIX*share`');
|
||||
$result = $verify->execute();
|
||||
$data = $result->fetchAll();
|
||||
$this->assertEmpty($data);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue