summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjoern Schiessle <bjoern@schiessle.org>2018-05-04 15:25:02 +0200
committerBjoern Schiessle <bjoern@schiessle.org>2018-07-02 11:29:27 +0200
commita3948e8a126d6f84629841c8886fe0819ab04ad5 (patch)
tree55e8458dfc9cf257f3ec6b5a40c9d0ff03e73d67
parent6208f250e88a15794ac5b7eeef6d701aa91e131b (diff)
downloadnextcloud-server-a3948e8a126d6f84629841c8886fe0819ab04ad5.tar.gz
nextcloud-server-a3948e8a126d6f84629841c8886fe0819ab04ad5.zip
use new API to send a federated share if possible
Signed-off-by: Bjoern Schiessle <bjoern@schiessle.org>
-rw-r--r--apps/cloud_federation_api/lib/Controller/RequestHandlerController.php14
-rw-r--r--apps/federatedfilesharing/lib/AppInfo/Application.php8
-rw-r--r--apps/federatedfilesharing/lib/BackgroundJob/RetryJob.php4
-rw-r--r--apps/federatedfilesharing/lib/Notifications.php88
-rw-r--r--apps/federatedfilesharing/lib/ocm/CloudFederationProviderFiles.php10
-rw-r--r--lib/private/Federation/CloudFederationProviderManager.php73
-rw-r--r--lib/private/Federation/CloudFederationShare.php6
-rw-r--r--lib/private/Server.php2
-rw-r--r--lib/private/Share20/ProviderFactory.php4
-rw-r--r--lib/public/Federation/ICloudFederationProvider.php7
-rw-r--r--lib/public/Federation/ICloudFederationShare.php4
11 files changed, 185 insertions, 35 deletions
diff --git a/apps/cloud_federation_api/lib/Controller/RequestHandlerController.php b/apps/cloud_federation_api/lib/Controller/RequestHandlerController.php
index d551f464c22..4f16c369a2f 100644
--- a/apps/cloud_federation_api/lib/Controller/RequestHandlerController.php
+++ b/apps/cloud_federation_api/lib/Controller/RequestHandlerController.php
@@ -32,6 +32,7 @@ use OCP\Federation\Exceptions\ShareNotFoundException;
use OCP\Federation\ICloudFederationFactory;
use OCP\Federation\ICloudFederationProviderManager;
use OCP\Federation\Exceptions\ProviderDoesNotExistsException;
+use OCP\Federation\ICloudIdManager;
use OCP\ILogger;
use OCP\IRequest;
use OCP\IURLGenerator;
@@ -65,6 +66,9 @@ class RequestHandlerController extends Controller {
/** @var ICloudFederationFactory */
private $factory;
+ /** @var ICloudIdManager */
+ private $cloudIdManager;
+
public function __construct($appName,
IRequest $request,
ILogger $logger,
@@ -72,7 +76,8 @@ class RequestHandlerController extends Controller {
IURLGenerator $urlGenerator,
ICloudFederationProviderManager $cloudFederationProviderManager,
Config $config,
- ICloudFederationFactory $factory
+ ICloudFederationFactory $factory,
+ ICloudIdManager $cloudIdManager
) {
parent::__construct($appName, $request);
@@ -82,6 +87,7 @@ class RequestHandlerController extends Controller {
$this->cloudFederationProviderManager = $cloudFederationProviderManager;
$this->config = $config;
$this->factory = $factory;
+ $this->cloudIdManager = $cloudIdManager;
}
/**
@@ -104,7 +110,7 @@ class RequestHandlerController extends Controller {
* @param $resourceType ('file', 'calendar',...)
* @return Http\DataResponse|JSONResponse
*
- * Example: curl -H "Content-Type: application/json" -X POST -d '{"shareWith":"admin1","name":"welcome server2.txt","description":"desc","providerId":"2","owner":"admin2@http://localhost/server2","ownerDisplayName":"admin2 display","shareType":"user","resourceType":"file","protocol":{"name":"webdav","options":{"access_token":"8Lrd1FVEREthux7","permissions":31}}}' http://localhost/server/index.php/ocm/shares
+ * Example: curl -H "Content-Type: application/json" -X POST -d '{"shareWith":"admin1@serve1","name":"welcome server2.txt","description":"desc","providerId":"2","owner":"admin2@http://localhost/server2","ownerDisplayName":"admin2 display","shareType":"user","resourceType":"file","protocol":{"name":"webdav","options":{"access_token":"8Lrd1FVEREthux7","permissions":31}}}' http://localhost/server/index.php/ocm/shares
*/
public function addShare($shareWith, $name, $description, $providerId, $owner, $ownerDisplayName, $sharedBy, $sharedByDisplayName, $protocol, $shareType, $resourceType) {
@@ -133,7 +139,9 @@ class RequestHandlerController extends Controller {
);
}
- $shareWith = $this->mapUid($shareWith);
+ $cloudId = $this->cloudIdManager->resolveCloudId($shareWith);
+ $shareWithLocalId = $cloudId->getUser();
+ $shareWith = $this->mapUid($shareWithLocalId);
if (!$this->userManager->userExists($shareWith)) {
return new JSONResponse(
diff --git a/apps/federatedfilesharing/lib/AppInfo/Application.php b/apps/federatedfilesharing/lib/AppInfo/Application.php
index 655c01cf85d..0b61e0a0b0d 100644
--- a/apps/federatedfilesharing/lib/AppInfo/Application.php
+++ b/apps/federatedfilesharing/lib/AppInfo/Application.php
@@ -76,7 +76,9 @@ class Application extends App {
$addressHandler,
$server->getHTTPClientService(),
$server->query(\OCP\OCS\IDiscoveryService::class),
- \OC::$server->getJobList()
+ \OC::$server->getJobList(),
+ \OC::$server->getCloudFederationProviderManager(),
+ \OC::$server->getCloudFederationFactory()
);
return new RequestHandlerController(
$c->query('AppName'),
@@ -121,7 +123,9 @@ class Application extends App {
$addressHandler,
\OC::$server->getHTTPClientService(),
\OC::$server->query(\OCP\OCS\IDiscoveryService::class),
- \OC::$server->getJobList()
+ \OC::$server->getJobList(),
+ \OC::$server->getCloudFederationProviderManager(),
+ \OC::$server->getCloudFederationFactory()
);
$tokenHandler = new \OCA\FederatedFileSharing\TokenHandler(
\OC::$server->getSecureRandom()
diff --git a/apps/federatedfilesharing/lib/BackgroundJob/RetryJob.php b/apps/federatedfilesharing/lib/BackgroundJob/RetryJob.php
index de2edfe60f7..e3d7028ef65 100644
--- a/apps/federatedfilesharing/lib/BackgroundJob/RetryJob.php
+++ b/apps/federatedfilesharing/lib/BackgroundJob/RetryJob.php
@@ -75,7 +75,9 @@ class RetryJob extends Job {
$addressHandler,
\OC::$server->getHTTPClientService(),
\OC::$server->query(\OCP\OCS\IDiscoveryService::class),
- \OC::$server->getJobList()
+ \OC::$server->getJobList(),
+ \OC::$server->getCloudFederationProviderManager(),
+ \OC::$server->getCloudFederationFactory()
);
}
diff --git a/apps/federatedfilesharing/lib/Notifications.php b/apps/federatedfilesharing/lib/Notifications.php
index 6f3f699e5c4..65151e34135 100644
--- a/apps/federatedfilesharing/lib/Notifications.php
+++ b/apps/federatedfilesharing/lib/Notifications.php
@@ -27,6 +27,8 @@ namespace OCA\FederatedFileSharing;
use OCP\AppFramework\Http;
use OCP\BackgroundJob\IJobList;
+use OCP\Federation\ICloudFederationFactory;
+use OCP\Federation\ICloudFederationProviderManager;
use OCP\Http\Client\IClientService;
use OCP\OCS\IDiscoveryService;
@@ -45,22 +47,34 @@ class Notifications {
/** @var IJobList */
private $jobList;
+ /** @var ICloudFederationProviderManager */
+ private $federationProviderManager;
+
+ /** @var ICloudFederationFactory */
+ private $cloudFederationFactory;
+
/**
* @param AddressHandler $addressHandler
* @param IClientService $httpClientService
* @param IDiscoveryService $discoveryService
* @param IJobList $jobList
+ * @param ICloudFederationProviderManager $federationProviderManager
+ * @param ICloudFederationFactory $cloudFederationFactory
*/
public function __construct(
AddressHandler $addressHandler,
IClientService $httpClientService,
IDiscoveryService $discoveryService,
- IJobList $jobList
+ IJobList $jobList,
+ ICloudFederationProviderManager $federationProviderManager,
+ ICloudFederationFactory $cloudFederationFactory
) {
$this->addressHandler = $addressHandler;
$this->httpClientService = $httpClientService;
$this->discoveryService = $discoveryService;
$this->jobList = $jobList;
+ $this->federationProviderManager = $federationProviderManager;
+ $this->cloudFederationFactory = $cloudFederationFactory;
}
/**
@@ -100,7 +114,10 @@ class Notifications {
$result = $this->tryHttpPostToShareEndpoint($remote, '', $fields);
$status = json_decode($result['result'], true);
- if ($result['success'] && ($status['ocs']['meta']['statuscode'] === 100 || $status['ocs']['meta']['statuscode'] === 200)) {
+ $ocsStatus = isset($status['ocs']);
+ $ocsSuccess = $ocsStatus && ($status['ocs']['meta']['statuscode'] === 100 || $status['ocs']['meta']['statuscode'] === 200);
+
+ if ($result['success'] && (!$ocsStatus ||$ocsSuccess)) {
\OC_Hook::emit('OCP\Share', 'federated_share_added', ['server' => $remote]);
return true;
}
@@ -271,11 +288,11 @@ class Notifications {
* @param string $remoteDomain
* @param string $urlSuffix
* @param array $fields post parameters
+ * @param string $action define the action (possible values: share, reshare, accept, decline, unshare, revoke, permissions)
* @return array
* @throws \Exception
*/
- protected function tryHttpPostToShareEndpoint($remoteDomain, $urlSuffix, array $fields) {
- $client = $this->httpClientService->newClient();
+ protected function tryHttpPostToShareEndpoint($remoteDomain, $urlSuffix, array $fields, $action="share") {
if ($this->addressHandler->urlContainProtocol($remoteDomain) === false) {
$remoteDomain = 'https://' . $remoteDomain;
@@ -286,6 +303,15 @@ class Notifications {
'result' => '',
];
+ // if possible we use the new OCM API
+ $ocmResult = $this->tryOCMEndPoint($remoteDomain, $fields, $action);
+ if ($ocmResult) {
+ $result['success'] = true;
+ return $result;
+ }
+
+ // Fall back to old API
+ $client = $this->httpClientService->newClient();
$federationEndpoints = $this->discoveryService->discover($remoteDomain, 'FEDERATED_SHARING');
$endpoint = isset($federationEndpoints['share']) ? $federationEndpoints['share'] : '/ocs/v2.php/cloud/shares';
try {
@@ -307,4 +333,58 @@ class Notifications {
return $result;
}
+
+ /**
+ * check if server supports the new OCM api and ask for the correct end-point
+ *
+ * @param string $url
+ * @return string
+ */
+ protected function getOCMEndPoint($url) {
+ $client = $this->httpClientService->newClient();
+ try {
+ $response = $client->get($url, ['timeout' => 10, 'connect_timeout' => 10]);
+ } catch (\Exception $e) {
+ return '';
+ }
+
+ $result = $response->getBody();
+ $result = json_decode($result, true);
+
+ if (isset($result['end-point'])) {
+ return $result['end-point'];
+ }
+
+ return '';
+ }
+
+ /**
+ * send action regarding federated sharing to the remote server using the OCM API
+ *
+ * @param $remoteDomain
+ * @param $fields
+ * @param $action
+ *
+ * @return bool
+ */
+ protected function tryOCMEndPoint($remoteDomain, $fields, $action) {
+ switch ($action) {
+ case 'share':
+ $share = $this->cloudFederationFactory->getCloudFederationShare(
+ $fields['shareWith'] . '@' . $remoteDomain,
+ $fields['name'],
+ '',
+ $fields['remoteId'],
+ $fields['ownerFederatedId'],
+ $fields['owner'],
+ $fields['sharedByFederatedId'],
+ $fields['sharedBy'],
+ ['name' => 'webdav', 'options' => ['access_token' => $fields['token'], 'permissions' => ['read', 'write', 'share']]],
+ 'user',
+ 'file'
+ );
+ return $this->federationProviderManager->sendShare($share);
+ }
+
+ }
}
diff --git a/apps/federatedfilesharing/lib/ocm/CloudFederationProviderFiles.php b/apps/federatedfilesharing/lib/ocm/CloudFederationProviderFiles.php
index f05f4469148..dea4c3f5fc1 100644
--- a/apps/federatedfilesharing/lib/ocm/CloudFederationProviderFiles.php
+++ b/apps/federatedfilesharing/lib/ocm/CloudFederationProviderFiles.php
@@ -109,15 +109,6 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
}
/**
- * send new share to another server
- *
- * @since 14.0.0
- */
- public function sendShare() {
- // TODO: Implement sendShare() method.
- }
-
- /**
* share received from another server
*
* @param ICloudFederationShare $share
@@ -186,6 +177,7 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
\OC::$server->getHTTPClientService(),
\OC::$server->getNotificationManager(),
\OC::$server->query(\OCP\OCS\IDiscoveryService::class),
+ \OC::$server->getCloudFederationProviderManager(),
$shareWith
);
diff --git a/lib/private/Federation/CloudFederationProviderManager.php b/lib/private/Federation/CloudFederationProviderManager.php
index 73e1dd99c61..dcf666ca266 100644
--- a/lib/private/Federation/CloudFederationProviderManager.php
+++ b/lib/private/Federation/CloudFederationProviderManager.php
@@ -29,6 +29,8 @@ use OCP\Federation\ICloudFederationNotification;
use OCP\Federation\ICloudFederationProvider;
use OCP\Federation\ICloudFederationProviderManager;
use OCP\Federation\ICloudFederationShare;
+use OCP\Federation\ICloudIdManager;
+use OCP\Http\Client\IClientService;
/**
* Class Manager
@@ -45,9 +47,26 @@ class CloudFederationProviderManager implements ICloudFederationProviderManager
/** @var IAppManager */
private $appManager;
- public function __construct(IAppManager $appManager) {
+ /** @var IClientService */
+ private $httpClientService;
+
+ /** @var ICloudIdManager */
+ private $cloudIdManager;
+
+ /**
+ * CloudFederationProviderManager constructor.
+ *
+ * @param IAppManager $appManager
+ * @param IClientService $httpClientService
+ * @param ICloudIdManager $cloudIdManager
+ */
+ public function __construct(IAppManager $appManager,
+ IClientService $httpClientService,
+ ICloudIdManager $cloudIdManager) {
$this->cloudFederationProvider= [];
$this->appManager = $appManager;
+ $this->httpClientService = $httpClientService;
+ $this->cloudIdManager = $cloudIdManager;
}
@@ -103,7 +122,32 @@ class CloudFederationProviderManager implements ICloudFederationProviderManager
}
public function sendShare(ICloudFederationShare $share) {
- // TODO: Implement sendShare() method.
+ $ocmEndPoint = $this->getOCMEndPoint($share->getShareWith());
+
+ if (empty($ocmEndPoint)) {
+ return false;
+ }
+
+ $client = $this->httpClientService->newClient();
+ try {
+ $response = $client->post($ocmEndPoint . '/shares', [
+ 'body' => $share->getShare(),
+ 'timeout' => 10,
+ 'connect_timeout' => 10,
+ ]);
+ $result['result'] = $response->getBody();
+ $result['success'] = true;
+ } catch (\Exception $e) {
+ // if flat re-sharing is not supported by the remote server
+ // we re-throw the exception and fall back to the old behaviour.
+ // (flat re-shares has been introduced in Nextcloud 9.1)
+ if ($e->getCode() === Http::STATUS_INTERNAL_SERVER_ERROR) {
+ throw $e;
+ }
+ }
+
+ return true;
+
}
public function sendNotification(ICloudFederationNotification $notification) {
@@ -118,5 +162,30 @@ class CloudFederationProviderManager implements ICloudFederationProviderManager
public function isReady() {
return $this->appManager->isEnabledForUser('cloud_federation_api', false);
}
+ /**
+ * check if server supports the new OCM api and ask for the correct end-point
+ *
+ * @param string $recipient full federated cloud ID of the recipient of a share
+ * @return string
+ */
+ protected function getOCMEndPoint($recipient) {
+ $cloudId = $this->cloudIdManager->resolveCloudId($recipient);
+ $client = $this->httpClientService->newClient();
+ try {
+ $response = $client->get($cloudId->getRemote() . '/ocm-provider/', ['timeout' => 10, 'connect_timeout' => 10]);
+ } catch (\Exception $e) {
+ return '';
+ }
+
+ $result = $response->getBody();
+ $result = json_decode($result, true);
+
+ if (isset($result['end-point'])) {
+ return $result['end-point'];
+ }
+
+ return '';
+ }
+
}
diff --git a/lib/private/Federation/CloudFederationShare.php b/lib/private/Federation/CloudFederationShare.php
index 4622dc096d7..5bc172ab6b6 100644
--- a/lib/private/Federation/CloudFederationShare.php
+++ b/lib/private/Federation/CloudFederationShare.php
@@ -203,14 +203,14 @@ class CloudFederationShare implements ICloudFederationShare {
}
/**
- * get JSON encoded share, ready to send out
+ * get the whole share, ready to send out
*
- * @return string
+ * @return array
*
* @since 14.0.0
*/
public function getShare() {
- return json_encode($this->share);
+ return $this->share;
}
/**
diff --git a/lib/private/Server.php b/lib/private/Server.php
index 7156c8a2c22..8f1b24eb11d 100644
--- a/lib/private/Server.php
+++ b/lib/private/Server.php
@@ -1117,7 +1117,7 @@ class Server extends ServerContainer implements IServerContainer {
});
$this->registerService(ICloudFederationProviderManager::class, function (Server $c) {
- return new CloudFederationProviderManager($c->getAppManager());
+ return new CloudFederationProviderManager($c->getAppManager(), $c->getHTTPClientService(), $c->getCloudIdManager());
});
$this->registerService(ICloudFederationFactory::class, function (Server $c) {
diff --git a/lib/private/Share20/ProviderFactory.php b/lib/private/Share20/ProviderFactory.php
index 456b6dbc596..7d866db24fa 100644
--- a/lib/private/Share20/ProviderFactory.php
+++ b/lib/private/Share20/ProviderFactory.php
@@ -116,7 +116,9 @@ class ProviderFactory implements IProviderFactory {
$addressHandler,
$this->serverContainer->getHTTPClientService(),
$this->serverContainer->query(\OCP\OCS\IDiscoveryService::class),
- $this->serverContainer->getJobList()
+ $this->serverContainer->getJobList(),
+ \OC::$server->getCloudFederationProviderManager(),
+ \OC::$server->getCloudFederationFactory()
);
$tokenHandler = new TokenHandler(
$this->serverContainer->getSecureRandom()
diff --git a/lib/public/Federation/ICloudFederationProvider.php b/lib/public/Federation/ICloudFederationProvider.php
index 535f61aae89..38a551000f0 100644
--- a/lib/public/Federation/ICloudFederationProvider.php
+++ b/lib/public/Federation/ICloudFederationProvider.php
@@ -46,13 +46,6 @@ interface ICloudFederationProvider {
public function getShareType();
/**
- * send new share to another server
- *
- * @since 14.0.0
- */
- public function sendShare();
-
- /**
* share received from another server
*
* @param ICloudFederationShare $share
diff --git a/lib/public/Federation/ICloudFederationShare.php b/lib/public/Federation/ICloudFederationShare.php
index b116da0fb54..ce5065c70b8 100644
--- a/lib/public/Federation/ICloudFederationShare.php
+++ b/lib/public/Federation/ICloudFederationShare.php
@@ -123,9 +123,9 @@ interface ICloudFederationShare {
public function setShareType($shareType);
/**
- * get JSON encoded share, ready to send out
+ * get the whole share, ready to send out
*
- * @return string
+ * @return array
*
* @since 14.0.0
*/