use new API to send a federated share if possible
Signed-off-by: Bjoern Schiessle <bjoern@schiessle.org>
This commit is contained in:
parent
6208f250e8
commit
a3948e8a12
11 changed files with 185 additions and 35 deletions
|
@ -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(
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,15 +108,6 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
|
|||
return 'file';
|
||||
}
|
||||
|
||||
/**
|
||||
* send new share to another server
|
||||
*
|
||||
* @since 14.0.0
|
||||
*/
|
||||
public function sendShare() {
|
||||
// TODO: Implement sendShare() method.
|
||||
}
|
||||
|
||||
/**
|
||||
* share received from another server
|
||||
*
|
||||
|
@ -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
|
||||
);
|
||||
|
||||
|
|
|
@ -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 '';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -45,13 +45,6 @@ interface ICloudFederationProvider {
|
|||
*/
|
||||
public function getShareType();
|
||||
|
||||
/**
|
||||
* send new share to another server
|
||||
*
|
||||
* @since 14.0.0
|
||||
*/
|
||||
public function sendShare();
|
||||
|
||||
/**
|
||||
* share received from another server
|
||||
*
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue