Signed-off-by: Bjoern Schiessle <bjoern@schiessle.org>tags/v14.0.0beta1
@@ -27,6 +27,7 @@ use OCA\CloudFederationAPI\Config; | |||
use OCP\AppFramework\Controller; | |||
use OCP\AppFramework\Http; | |||
use OCP\AppFramework\Http\JSONResponse; | |||
use OCP\Federation\Exceptions\ActionNotSupportedException; | |||
use OCP\Federation\Exceptions\ProviderCouldNotAddShareException; | |||
use OCP\Federation\Exceptions\ShareNotFoundException; | |||
use OCP\Federation\ICloudFederationFactory; | |||
@@ -190,13 +191,12 @@ class RequestHandlerController extends Controller { | |||
/** | |||
* receive notification about existing share | |||
* | |||
* @param $resourceType ('file', 'calendar',...) | |||
* @param string $name resource name (e.g "file", "calendar",...) | |||
* @param string $id unique id of the corresponding item on the receiving site | |||
* @param array $notification contain the actual notification, content is defined by cloud federation provider | |||
* @param string $notificationType (notification type, e.g. SHARE_ACCEPTED) | |||
* @param string $resourceType (calendar, file, contact,...) | |||
* @param array $message contain the actual notification, content is defined by cloud federation provider | |||
* @return JSONResponse | |||
*/ | |||
public function receiveNotification($resourceType, $name, $id, $notification) { | |||
public function receiveNotification($notificationType, $resourceType, $message) { | |||
if (!$this->config->incomingRequestsEnabled()) { | |||
return new JSONResponse( | |||
['message' => 'This server doesn\'t support outgoing federated shares'], | |||
@@ -205,9 +205,9 @@ class RequestHandlerController extends Controller { | |||
} | |||
// check if all required parameters are set | |||
if ($name === null || | |||
$id === null || | |||
!is_array($notification) | |||
if ($notificationType === null || | |||
$resourceType === null || | |||
!is_array($message) | |||
) { | |||
return new JSONResponse( | |||
['message' => 'Missing arguments'], | |||
@@ -217,7 +217,7 @@ class RequestHandlerController extends Controller { | |||
try { | |||
$provider = $this->cloudFederationProviderManager->getCloudFederationProvider($resourceType); | |||
$provider->notificationReceived($id, $notification); | |||
$provider->notificationReceived($notificationType, $message); | |||
} catch (ProviderDoesNotExistsException $e) { | |||
return new JSONResponse( | |||
['message' => $e->getMessage()], | |||
@@ -228,6 +228,11 @@ class RequestHandlerController extends Controller { | |||
['message' => $e->getMessage()], | |||
Http::STATUS_BAD_REQUEST | |||
); | |||
} catch (ActionNotSupportedException $e) { | |||
return new JSONResponse( | |||
['message' => $e->getMessage()], | |||
Http::STATUS_NOT_IMPLEMENTED | |||
); | |||
} catch (\Exception $e) { | |||
return new JSONResponse( | |||
['message' => 'Internal error at ' . $this->urlGenerator->getBaseUrl()], |
@@ -27,7 +27,9 @@ use OCA\FederatedFileSharing\AddressHandler; | |||
use OCA\FederatedFileSharing\FederatedShareProvider; | |||
use OCP\Activity\IManager as IActivityManager; | |||
use OCP\App\IAppManager; | |||
use OCP\Federation\Exceptions\ActionNotSupportedException; | |||
use OCP\Federation\Exceptions\ProviderCouldNotAddShareException; | |||
use OCP\Federation\Exceptions\ShareNotFoundException; | |||
use OCP\Federation\ICloudFederationProvider; | |||
use OCP\Federation\ICloudFederationShare; | |||
use OCP\Federation\ICloudIdManager; | |||
@@ -178,6 +180,7 @@ class CloudFederationProviderFiles implements ICloudFederationProvider { | |||
\OC::$server->getNotificationManager(), | |||
\OC::$server->query(\OCP\OCS\IDiscoveryService::class), | |||
\OC::$server->getCloudFederationProviderManager(), | |||
\OC::$server->getCloudFederationFactory(), | |||
$shareWith | |||
); | |||
@@ -230,15 +233,22 @@ class CloudFederationProviderFiles implements ICloudFederationProvider { | |||
/** | |||
* notification received from another server | |||
* | |||
* @param string $id unique ID of a already existing share | |||
* @param array $notification provider specific notification | |||
* @param string $notificationType (e.g. SHARE_ACCEPTED) | |||
* @param array $message | |||
* | |||
* @throws \OCP\Federation\Exceptions\ShareNotFoundException | |||
* @throws ShareNotFoundException | |||
* @throws ActionNotSupportedException | |||
* | |||
* @since 14.0.0 | |||
*/ | |||
public function notificationReceived($id, $notification) { | |||
// TODO: Implement notificationReceived() method. | |||
public function notificationReceived($notificationType, array $message) { | |||
switch ($notificationType) { | |||
case 'SHARE_ACCEPTED' : | |||
return; | |||
} | |||
throw new ActionNotSupportedException($notificationType); | |||
} | |||
/** |
@@ -103,6 +103,8 @@ class Application extends App { | |||
$server->getHTTPClientService(), | |||
$server->getNotificationManager(), | |||
$server->query(\OCP\OCS\IDiscoveryService::class), | |||
$server->getCloudFederationProviderManager(), | |||
$server->getCloudFederationFactory(), | |||
$uid | |||
); | |||
}); |
@@ -33,6 +33,8 @@ namespace OCA\Files_Sharing\External; | |||
use OC\Files\Filesystem; | |||
use OCA\Files_Sharing\Helper; | |||
use OCP\Federation\ICloudFederationFactory; | |||
use OCP\Federation\ICloudFederationProviderManager; | |||
use OCP\Files; | |||
use OCP\Files\Storage\IStorageFactory; | |||
use OCP\Http\Client\IClientService; | |||
@@ -79,6 +81,12 @@ class Manager { | |||
*/ | |||
private $discoveryService; | |||
/** @var ICloudFederationProviderManager */ | |||
private $cloudFederationProviderManager; | |||
/** @var ICloudFederationFactory */ | |||
private $cloudFederationFactory; | |||
/** | |||
* @param IDBConnection $connection | |||
* @param \OC\Files\Mount\Manager $mountManager | |||
@@ -86,6 +94,8 @@ class Manager { | |||
* @param IClientService $clientService | |||
* @param IManager $notificationManager | |||
* @param IDiscoveryService $discoveryService | |||
* @param ICloudFederationProviderManager $cloudFederationProviderManager | |||
* @param ICloudFederationFactory $cloudFederationFactory | |||
* @param string $uid | |||
*/ | |||
public function __construct(IDBConnection $connection, | |||
@@ -94,6 +104,8 @@ class Manager { | |||
IClientService $clientService, | |||
IManager $notificationManager, | |||
IDiscoveryService $discoveryService, | |||
ICloudFederationProviderManager $cloudFederationProviderManager, | |||
ICloudFederationFactory $cloudFederationFactory, | |||
$uid) { | |||
$this->connection = $connection; | |||
$this->mountManager = $mountManager; | |||
@@ -102,6 +114,8 @@ class Manager { | |||
$this->uid = $uid; | |||
$this->notificationManager = $notificationManager; | |||
$this->discoveryService = $discoveryService; | |||
$this->cloudFederationProviderManager = $cloudFederationProviderManager; | |||
$this->cloudFederationFactory = $cloudFederationFactory; | |||
} | |||
/** | |||
@@ -274,6 +288,12 @@ class Manager { | |||
*/ | |||
private function sendFeedbackToRemote($remote, $token, $remoteId, $feedback) { | |||
$result = $this->tryOCMEndPoint($remote, $token, $remoteId, $feedback); | |||
if($result === true) { | |||
return true; | |||
} | |||
$federationEndpoints = $this->discoveryService->discover($remote, 'FEDERATED_SHARING'); | |||
$endpoint = isset($federationEndpoints['share']) ? $federationEndpoints['share'] : '/ocs/v2.php/cloud/shares'; | |||
@@ -299,6 +319,31 @@ class Manager { | |||
return ($status['ocs']['meta']['statuscode'] === 100 || $status['ocs']['meta']['statuscode'] === 200); | |||
} | |||
/** | |||
* try send accept message to ocm end-point | |||
* | |||
* @param string $remoteDomain | |||
* @param string $token | |||
* @param $remoteId | |||
* @param string $feedback | |||
* @return mixed | |||
*/ | |||
protected function tryOCMEndPoint($remoteDomain, $token, $remoteId, $feedback) { | |||
switch ($feedback) { | |||
case 'accept': | |||
$notification = $this->cloudFederationFactory->getCloudFederationNotification(); | |||
$notification->setMessage('SHARE_ACCEPTED', 'file', | |||
[ | |||
'id' => $remoteId, | |||
'access_token' => $token | |||
] | |||
); | |||
return $this->cloudFederationProviderManager->sendNotification($remoteDomain, $notification); | |||
} | |||
} | |||
/** | |||
* remove '/user/files' from the path and trailing slashes | |||
* |
@@ -40,6 +40,8 @@ class Hooks { | |||
\OC::$server->getHTTPClientService(), | |||
\OC::$server->getNotificationManager(), | |||
\OC::$server->query(\OCP\OCS\IDiscoveryService::class), | |||
\OC::$server->getCloudFederationProviderManager(), | |||
\OC::$server->getCloudFederationFactory(), | |||
$params['uid']); | |||
$manager->removeUserShares($params['uid']); |
@@ -30,23 +30,28 @@ class CloudFederationNotification implements ICloudFederationNotification { | |||
/** | |||
* add a message to the notification | |||
* | |||
* @param string $identifier | |||
* @param string $message | |||
* @param string $notificationType (e.g. SHARE_ACCEPTED) | |||
* @param string $resourceType (e.g. file, calendar, contact,...) | |||
* @param array $message | |||
* | |||
* @since 14.0.0 | |||
*/ | |||
public function setMessage($identifier, $message) { | |||
$this->message[$identifier] = $message; | |||
public function setMessage($notificationType, $resourceType, array $message) { | |||
$this->message = [ | |||
'notificationType' => $notificationType, | |||
'resourceType' => $resourceType, | |||
'message' => $message, | |||
]; | |||
} | |||
/** | |||
* get JSON encoded Message, ready to send out | |||
* get message, ready to send out | |||
* | |||
* @return string | |||
* @return array | |||
* | |||
* @since 14.0.0 | |||
*/ | |||
public function getMessage() { | |||
return json_encode($this->message); | |||
return $this->message; | |||
} | |||
} |
@@ -22,8 +22,8 @@ | |||
namespace OC\Federation; | |||
use OC\AppFramework\Http; | |||
use OCP\App\IAppManager; | |||
use OCP\Federation\Exceptions\ProviderAlreadyExistsException; | |||
use OCP\Federation\Exceptions\ProviderDoesNotExistsException; | |||
use OCP\Federation\ICloudFederationNotification; | |||
use OCP\Federation\ICloudFederationProvider; | |||
@@ -31,6 +31,7 @@ use OCP\Federation\ICloudFederationProviderManager; | |||
use OCP\Federation\ICloudFederationShare; | |||
use OCP\Federation\ICloudIdManager; | |||
use OCP\Http\Client\IClientService; | |||
use OCP\ILogger; | |||
/** | |||
* Class Manager | |||
@@ -53,20 +54,26 @@ class CloudFederationProviderManager implements ICloudFederationProviderManager | |||
/** @var ICloudIdManager */ | |||
private $cloudIdManager; | |||
/** @var ILogger */ | |||
private $logger; | |||
/** | |||
* CloudFederationProviderManager constructor. | |||
* | |||
* @param IAppManager $appManager | |||
* @param IClientService $httpClientService | |||
* @param ICloudIdManager $cloudIdManager | |||
* @param ILogger $logger | |||
*/ | |||
public function __construct(IAppManager $appManager, | |||
IClientService $httpClientService, | |||
ICloudIdManager $cloudIdManager) { | |||
ICloudIdManager $cloudIdManager, | |||
ILogger $logger) { | |||
$this->cloudFederationProvider= []; | |||
$this->appManager = $appManager; | |||
$this->httpClientService = $httpClientService; | |||
$this->cloudIdManager = $cloudIdManager; | |||
$this->logger = $logger; | |||
} | |||
@@ -135,8 +142,11 @@ class CloudFederationProviderManager implements ICloudFederationProviderManager | |||
'timeout' => 10, | |||
'connect_timeout' => 10, | |||
]); | |||
$result['result'] = $response->getBody(); | |||
$result['success'] = true; | |||
if ($response->getStatusCode() === Http::STATUS_OK) { | |||
return 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. | |||
@@ -146,12 +156,38 @@ class CloudFederationProviderManager implements ICloudFederationProviderManager | |||
} | |||
} | |||
return true; | |||
return false; | |||
} | |||
public function sendNotification(ICloudFederationNotification $notification) { | |||
// TODO: Implement sendNotification() method. | |||
/** | |||
* @param string $url | |||
* @param ICloudFederationNotification $notification | |||
* @return bool | |||
*/ | |||
public function sendNotification($url, ICloudFederationNotification $notification) { | |||
$ocmEndPoint = $this->getOCMEndPoint($url); | |||
if (empty($ocmEndPoint)) { | |||
return false; | |||
} | |||
$client = $this->httpClientService->newClient(); | |||
try { | |||
$response = $client->post($ocmEndPoint . '/notifications', [ | |||
'body' => $notification->getMessage(), | |||
'timeout' => 10, | |||
'connect_timeout' => 10, | |||
]); | |||
if ($response->getStatusCode() === Http::STATUS_OK) { | |||
return true; | |||
} | |||
} catch (\Exception $e) { | |||
// log the error and return false | |||
$this->logger->error('error while sending notification for federated share: ' . $e->getMessage()); | |||
} | |||
return false; | |||
} | |||
/** |
@@ -1117,7 +1117,7 @@ class Server extends ServerContainer implements IServerContainer { | |||
}); | |||
$this->registerService(ICloudFederationProviderManager::class, function (Server $c) { | |||
return new CloudFederationProviderManager($c->getAppManager(), $c->getHTTPClientService(), $c->getCloudIdManager()); | |||
return new CloudFederationProviderManager($c->getAppManager(), $c->getHTTPClientService(), $c->getCloudIdManager(), $c->getLogger()); | |||
}); | |||
$this->registerService(ICloudFederationFactory::class, function (Server $c) { |
@@ -0,0 +1,39 @@ | |||
<?php | |||
/** | |||
* @copyright Copyright (c) 2018 Bjoern Schiessle <bjoern@schiessle.org> | |||
* | |||
* @license GNU AGPL version 3 or any later version | |||
* | |||
* This program is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU Affero General Public License as | |||
* published by the Free Software Foundation, either version 3 of the | |||
* License, or (at your option) any later version. | |||
* | |||
* This program 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 program. If not, see <http://www.gnu.org/licenses/>. | |||
* | |||
*/ | |||
namespace OCP\Federation\Exceptions; | |||
use OC\HintException; | |||
class ActionNotSupportedException extends HintException { | |||
/** | |||
* ActionNotSupportedException constructor. | |||
* | |||
*/ | |||
public function __construct($action) { | |||
$l = \OC::$server->getL10N('federation'); | |||
$message = 'Action "' . $action . '" not supported or implemented.'; | |||
$hint = $l->t('Action "%s" not supported or implemented.', [$action]); | |||
parent::__construct($message, $hint); | |||
} | |||
} |
@@ -26,15 +26,16 @@ interface ICloudFederationNotification { | |||
/** | |||
* add a message to the notification | |||
* | |||
* @param string $identifier | |||
* @param string $message | |||
* @param string $notificationType (e.g. SHARE_ACCEPTED) | |||
* @param string $resourceType (e.g. file, calendar, contact,...) | |||
* @param array $message | |||
* | |||
* @since 14.0.0 | |||
*/ | |||
public function setMessage($identifier, $message); | |||
public function setMessage($notificationType, $resourceType, array $message); | |||
/** | |||
* get JSON encoded Message, ready to send out | |||
* get message, ready to send out | |||
* | |||
* @return string | |||
* |
@@ -21,6 +21,7 @@ | |||
namespace OCP\Federation; | |||
use OCP\Federation\Exceptions\ActionNotSupportedException; | |||
use OCP\Federation\Exceptions\ProviderCouldNotAddShareException; | |||
use OCP\Federation\Exceptions\ShareNotFoundException; | |||
@@ -60,13 +61,14 @@ interface ICloudFederationProvider { | |||
/** | |||
* notification received from another server | |||
* | |||
* @param string $id unique ID of a already existing share | |||
* @param array $notification provider specific notification | |||
* @param string $notificationType (e.g SHARE_ACCEPTED) | |||
* @param array $message provider specific notification | |||
* | |||
* @throws ShareNotFoundException | |||
* @throws ActionNotSupportedException | |||
* | |||
* @since 14.0.0 | |||
*/ | |||
public function notificationReceived($id, $notification); | |||
public function notificationReceived($notificationType, array $message); | |||
} |
@@ -86,12 +86,13 @@ interface ICloudFederationProviderManager { | |||
/** | |||
* send notification about existing share | |||
* | |||
* @param string $url | |||
* @param ICloudFederationNotification $notification | |||
* @return mixed | |||
* @return bool | |||
* | |||
* @since 14.0.0 | |||
*/ | |||
public function sendNotification(ICloudFederationNotification $notification); | |||
public function sendNotification($url, ICloudFederationNotification $notification); | |||
/** | |||
* check if the new cloud federation API is ready to be used |