summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjoern Schiessle <bjoern@schiessle.org>2018-05-29 16:21:13 +0200
committerBjoern Schiessle <bjoern@schiessle.org>2018-07-02 11:29:28 +0200
commit8889e14c7cb848634895d8bbdedd13194c37301c (patch)
tree75f54fd99948e7b3d92ba3028dcdf29477b6630c
parentbbce8c3ea1c73726f233961fe7bdb16b8a08bb67 (diff)
downloadnextcloud-server-8889e14c7cb848634895d8bbdedd13194c37301c.tar.gz
nextcloud-server-8889e14c7cb848634895d8bbdedd13194c37301c.zip
implement accept share notification
Signed-off-by: Bjoern Schiessle <bjoern@schiessle.org>
-rw-r--r--apps/cloud_federation_api/lib/Controller/RequestHandlerController.php9
-rw-r--r--apps/federatedfilesharing/lib/Controller/RequestHandlerController.php78
-rw-r--r--apps/federatedfilesharing/lib/FederatedShareProvider.php5
-rw-r--r--apps/federatedfilesharing/lib/ocm/CloudFederationProviderFiles.php157
-rw-r--r--lib/public/Federation/Exceptions/AuthenticationFailedException.php40
-rw-r--r--lib/public/Federation/Exceptions/BadRequestException.php66
-rw-r--r--lib/public/Federation/ICloudFederationProvider.php4
-rw-r--r--lib/public/Share/IShareProvider.php6
8 files changed, 289 insertions, 76 deletions
diff --git a/apps/cloud_federation_api/lib/Controller/RequestHandlerController.php b/apps/cloud_federation_api/lib/Controller/RequestHandlerController.php
index 5ec1496ce6b..4ee8344b6b5 100644
--- a/apps/cloud_federation_api/lib/Controller/RequestHandlerController.php
+++ b/apps/cloud_federation_api/lib/Controller/RequestHandlerController.php
@@ -28,6 +28,8 @@ use OCP\AppFramework\Controller;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\JSONResponse;
use OCP\Federation\Exceptions\ActionNotSupportedException;
+use OCP\Federation\Exceptions\AuthenticationFailedException;
+use OCP\Federation\Exceptions\BadRequestException;
use OCP\Federation\Exceptions\ProviderCouldNotAddShareException;
use OCP\Federation\Exceptions\ShareNotFoundException;
use OCP\Federation\ICloudFederationFactory;
@@ -241,7 +243,12 @@ class RequestHandlerController extends Controller {
['message' => $e->getMessage()],
Http::STATUS_NOT_IMPLEMENTED
);
- } catch (\Exception $e) {
+ } catch (BadRequestException $e) {
+ return new JSONResponse($e->getReturnMessage(), Http::STATUS_BAD_REQUEST);
+ } catch (AuthenticationFailedException $e) {
+ return new JSONResponse(["message" => "RESOURCE_NOT_FOUND"], Http::STATUS_FORBIDDEN);
+ }
+ catch (\Exception $e) {
return new JSONResponse(
['message' => 'Internal error at ' . $this->urlGenerator->getBaseUrl()],
Http::STATUS_BAD_REQUEST
diff --git a/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php b/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php
index e2cc050d879..628e306e994 100644
--- a/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php
+++ b/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php
@@ -42,6 +42,7 @@ use OCP\AppFramework\OCSController;
use OCP\Constants;
use OCP\Federation\Exceptions\ProviderCouldNotAddShareException;
use OCP\Federation\Exceptions\ProviderDoesNotExistsException;
+use OCP\Federation\Exceptions\ShareNotFoundException;
use OCP\Federation\ICloudFederationFactory;
use OCP\Federation\ICloudFederationProviderManager;
use OCP\Federation\ICloudIdManager;
@@ -265,47 +266,32 @@ class RequestHandlerController extends OCSController {
* @param int $id
* @return Http\DataResponse
* @throws OCSException
+ * @throws Share\Exceptions\ShareNotFound
+ * @throws \OC\HintException
*/
public function acceptShare($id) {
- if (!$this->isS2SEnabled()) {
- throw new OCSException('Server does not support federated cloud sharing', 503);
- }
-
$token = isset($_POST['token']) ? $_POST['token'] : null;
- try {
- $share = $this->federatedShareProvider->getShareById($id);
- } catch (Share\Exceptions\ShareNotFound $e) {
- return new Http\DataResponse();
- }
+ $notification = [
+ 'sharedSecret' => $token,
+ 'message' => 'Recipient accept the share'
+ ];
- if ($this->verifyShare($share, $token)) {
- $this->executeAcceptShare($share);
- if ($share->getShareOwner() !== $share->getSharedBy()) {
- list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
- $remoteId = $this->federatedShareProvider->getRemoteId($share);
- $this->notifications->sendAcceptShare($remote, $remoteId, $share->getToken());
- }
+ try {
+ $provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
+ $provider->notificationReceived('SHARE_ACCEPTED', $id, $notification);
+ } catch (ProviderDoesNotExistsException $e) {
+ throw new OCSException('Server does not support federated cloud sharing', 503);
+ } catch (ShareNotFoundException $e) {
+ $this->logger->debug('Share not found: ' . $e->getMessage());
+ } catch (\Exception $e) {
+ $this->logger->debug('internal server error, can not process notification: ' . $e->getMessage());
}
return new Http\DataResponse();
}
- protected function executeAcceptShare(Share\IShare $share) {
- $fileId = (int) $share->getNode()->getId();
- list($file, $link) = $this->getFile($this->getCorrectUid($share), $fileId);
-
- $event = \OC::$server->getActivityManager()->generateEvent();
- $event->setApp('files_sharing')
- ->setType('remote_share')
- ->setAffectedUser($this->getCorrectUid($share))
- ->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_ACCEPTED, [$share->getSharedWith(), [$fileId => $file]])
- ->setObject('files', $fileId, $file)
- ->setLink($link);
- \OC::$server->getActivityManager()->publish($event);
- }
-
/**
* @NoCSRFRequired
* @PublicPage
@@ -364,20 +350,6 @@ class RequestHandlerController extends OCSController {
}
/**
- * check if we are the initiator or the owner of a re-share and return the correct UID
- *
- * @param Share\IShare $share
- * @return string
- */
- protected function getCorrectUid(Share\IShare $share) {
- if ($this->userManager->userExists($share->getShareOwner())) {
- return $share->getShareOwner();
- }
-
- return $share->getSharedBy();
- }
-
- /**
* @NoCSRFRequired
* @PublicPage
*
@@ -549,24 +521,6 @@ class RequestHandlerController extends OCSController {
}
/**
- * check if we got the right share
- *
- * @param Share\IShare $share
- * @param string $token
- * @return bool
- */
- protected function verifyShare(Share\IShare $share, $token) {
- if (
- $share->getShareType() === FederatedShareProvider::SHARE_TYPE_REMOTE &&
- $share->getToken() === $token
- ) {
- return true;
- }
-
- return false;
- }
-
- /**
* @NoCSRFRequired
* @PublicPage
*
diff --git a/apps/federatedfilesharing/lib/FederatedShareProvider.php b/apps/federatedfilesharing/lib/FederatedShareProvider.php
index ecc1e1710b8..07597cae8e5 100644
--- a/apps/federatedfilesharing/lib/FederatedShareProvider.php
+++ b/apps/federatedfilesharing/lib/FederatedShareProvider.php
@@ -30,6 +30,7 @@
namespace OCA\FederatedFileSharing;
use OC\Share20\Share;
+use OCP\Federation\Exceptions\ShareNotFoundException;
use OCP\Federation\ICloudIdManager;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\Files\Folder;
@@ -708,13 +709,13 @@ class FederatedShareProvider implements IShareProvider {
$cursor->closeCursor();
if ($data === false) {
- throw new ShareNotFound();
+ throw new ShareNotFoundException();
}
try {
$share = $this->createShareObject($data);
} catch (InvalidShare $e) {
- throw new ShareNotFound();
+ throw new ShareNotFoundException();
}
return $share;
diff --git a/apps/federatedfilesharing/lib/ocm/CloudFederationProviderFiles.php b/apps/federatedfilesharing/lib/ocm/CloudFederationProviderFiles.php
index e7f6f1b9194..798b0bef3f4 100644
--- a/apps/federatedfilesharing/lib/ocm/CloudFederationProviderFiles.php
+++ b/apps/federatedfilesharing/lib/ocm/CloudFederationProviderFiles.php
@@ -22,21 +22,29 @@
namespace OCA\FederatedFileSharing\OCM;
use OC\AppFramework\Http;
+use OC\Files\Filesystem;
use OCA\Files_Sharing\Activity\Providers\RemoteShares;
use OCA\FederatedFileSharing\AddressHandler;
use OCA\FederatedFileSharing\FederatedShareProvider;
use OCP\Activity\IManager as IActivityManager;
+use OCP\Activity\IManager;
use OCP\App\IAppManager;
use OCP\Federation\Exceptions\ActionNotSupportedException;
+use OCP\Federation\Exceptions\AuthenticationFailedException;
+use OCP\Federation\Exceptions\BadRequestException;
use OCP\Federation\Exceptions\ProviderCouldNotAddShareException;
use OCP\Federation\Exceptions\ShareNotFoundException;
use OCP\Federation\ICloudFederationProvider;
use OCP\Federation\ICloudFederationShare;
use OCP\Federation\ICloudIdManager;
+use OCP\Files\NotFoundException;
use OCP\ILogger;
use OCP\IURLGenerator;
use OCP\IUserManager;
use OCP\Notification\IManager as INotificationManager;
+use OCP\Share\Exceptions\ShareNotFound;
+use OCP\Share\IShare;
+use OCP\Util;
class CloudFederationProviderFiles implements ICloudFederationProvider {
@@ -153,13 +161,13 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
if ($remote && $token && $name && $owner && $remoteId && $shareWith) {
- if (!\OCP\Util::isValidFileName($name)) {
+ if (!Util::isValidFileName($name)) {
throw new ProviderCouldNotAddShareException('The mountpoint name contains invalid characters.', '', Http::STATUS_BAD_REQUEST);
}
// FIXME this should be a method in the user management instead
$this->logger->debug('shareWith before, ' . $shareWith, ['app' => 'files_sharing']);
- \OCP\Util::emitHook(
+ Util::emitHook(
'\OCA\Files_Sharing\API\Server2Server',
'preLoginNameUsedAsUserName',
array('uid' => &$shareWith)
@@ -174,8 +182,8 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
$externalManager = new \OCA\Files_Sharing\External\Manager(
\OC::$server->getDatabaseConnection(),
- \OC\Files\Filesystem::getMountManager(),
- \OC\Files\Filesystem::getLoader(),
+ Filesystem::getMountManager(),
+ Filesystem::getLoader(),
\OC::$server->getHTTPClientService(),
\OC::$server->getNotificationManager(),
\OC::$server->query(\OCP\OCS\IDiscoveryService::class),
@@ -219,7 +227,7 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
} catch (\Exception $e) {
$this->logger->logException($e, [
'message' => 'Server can not add remote share.',
- 'level' => \OCP\Util::ERROR,
+ 'level' => Util::ERROR,
'app' => 'files_sharing'
]);
throw new ProviderCouldNotAddShareException('internal server error, was not able to add share from ' . $remote, '', HTTP::STATUS_INTERNAL_SERVER_ERROR);
@@ -237,14 +245,18 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
* @param string $providerId id of the share
* @param array $notification payload of the notification
*
- * @throws ShareNotFoundException
* @throws ActionNotSupportedException
- *
+ * @throws AuthenticationFailedException
+ * @throws BadRequestException
+ * @throws ShareNotFoundException
+ * @throws \OC\HintException
* @since 14.0.0
*/
public function notificationReceived($notificationType, $providerId, array $notification) {
+
switch ($notificationType) {
- case 'SHARE_ACCEPTED' :
+ case 'SHARE_ACCEPTED':
+ $this->shareAccepted($providerId, $notification);
return;
}
@@ -253,6 +265,135 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
}
/**
+ * @param $id
+ * @param $notification
+ * @return bool
+ * @throws ActionNotSupportedException
+ * @throws AuthenticationFailedException
+ * @throws BadRequestException
+ * @throws ShareNotFoundException
+ * @throws \OC\HintException
+ */
+ private function shareAccepted($id, $notification) {
+
+ if (!$this->isS2SEnabled(true)) {
+ throw new ActionNotSupportedException('Server does not support federated cloud sharing', '', Http::STATUS_SERVICE_UNAVAILABLE);
+ }
+
+ if (!isset($notification['sharedSecret'])) {
+ throw new BadRequestException(['sharedSecret']);
+ }
+
+ $token = $notification['sharedSecret'];
+
+ $share = $this->federatedShareProvider->getShareById($id);
+
+ $this->verifyShare($share, $token);
+ $this->executeAcceptShare($share);
+ if ($share->getShareOwner() !== $share->getSharedBy()) {
+ list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
+ $remoteId = $this->federatedShareProvider->getRemoteId($share);
+ $notification = $this->cloudFederationFactory->getCloudFederationNotification();
+ $notification->setMessage(
+ 'SHARE_ACCEPTED',
+ 'file',
+ $remoteId,
+ [
+ 'sharedSecret' => $token,
+ 'message' => 'Recipient accepted the re-share'
+ ]
+
+ );
+ $this->cloudFederationProviderManager->sendNotification($remote, $notification);
+
+ }
+
+ return true;
+ }
+
+
+ /**
+ * @param IShare $share
+ * @throws ShareNotFoundException
+ */
+ protected function executeAcceptShare(IShare $share) {
+ try {
+ $fileId = (int)$share->getNode()->getId();
+ list($file, $link) = $this->getFile($this->getCorrectUid($share), $fileId);
+ } catch (\Exception $e) {
+ throw new ShareNotFoundException();
+ }
+
+ $event = $this->activityManager->generateEvent();
+ $event->setApp('files_sharing')
+ ->setType('remote_share')
+ ->setAffectedUser($this->getCorrectUid($share))
+ ->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_ACCEPTED, [$share->getSharedWith(), [$fileId => $file]])
+ ->setObject('files', $fileId, $file)
+ ->setLink($link);
+ $this->activityManager->publish($event);
+ }
+
+ /**
+ * 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);
+
+ try {
+ $file = Filesystem::getPath($fileSource);
+ } catch (NotFoundException $e) {
+ $file = null;
+ }
+ $args = Filesystem::is_dir($file) ? array('dir' => $file) : array('dir' => dirname($file), 'scrollto' => $file);
+ $link = Util::linkToAbsolute('files', 'index.php', $args);
+
+ return array($file, $link);
+
+ }
+
+ /**
+ * check if we are the initiator or the owner of a re-share and return the correct UID
+ *
+ * @param IShare $share
+ * @return string
+ */
+ protected function getCorrectUid(IShare $share) {
+ if ($this->userManager->userExists($share->getShareOwner())) {
+ return $share->getShareOwner();
+ }
+
+ return $share->getSharedBy();
+ }
+
+
+
+ /**
+ * check if we got the right share
+ *
+ * @param IShare $share
+ * @param string $token
+ * @return bool
+ * @throws AuthenticationFailedException
+ */
+ protected function verifyShare(IShare $share, $token) {
+ if (
+ $share->getShareType() === FederatedShareProvider::SHARE_TYPE_REMOTE &&
+ $share->getToken() === $token
+ ) {
+ return true;
+ }
+
+ throw new AuthenticationFailedException();
+ }
+
+
+
+ /**
* check if server-to-server sharing is enabled
*
* @param bool $incoming
diff --git a/lib/public/Federation/Exceptions/AuthenticationFailedException.php b/lib/public/Federation/Exceptions/AuthenticationFailedException.php
new file mode 100644
index 00000000000..a9a412dd835
--- /dev/null
+++ b/lib/public/Federation/Exceptions/AuthenticationFailedException.php
@@ -0,0 +1,40 @@
+<?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 AuthenticationFailedException extends HintException {
+
+ /**
+ * BadRequestException constructor.
+ *
+ * @param array $missingParameters
+ */
+ public function __construct() {
+ $l = \OC::$server->getL10N('federation');
+ $message = 'Authentication failed, wrong token or provider ID given';
+ $hint = $l->t('Authentication failed, wrong token or provider ID given');
+ parent::__construct($message, $hint);
+ }
+
+}
diff --git a/lib/public/Federation/Exceptions/BadRequestException.php b/lib/public/Federation/Exceptions/BadRequestException.php
new file mode 100644
index 00000000000..67cf911c2a0
--- /dev/null
+++ b/lib/public/Federation/Exceptions/BadRequestException.php
@@ -0,0 +1,66 @@
+<?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 BadRequestException extends HintException {
+
+ private $parameterList;
+
+ /**
+ * BadRequestException constructor.
+ *
+ * @param array $missingParameters
+ */
+ public function __construct(array $missingParameters) {
+ $l = \OC::$server->getL10N('federation');
+ $this->parameterList = $missingParameters;
+ $parameterList = implode(',', $missingParameters);
+ $message = 'Parameters missing in order to complete the request. Missing Parameters: ' . $parameterList;
+ $hint = $l->t('Parameters missing in order to complete the request. Missing Parameters: "%s"', [$parameterList]);
+ parent::__construct($message, $hint);
+ }
+
+ /**
+ * get array with the return message as defined in the OCM API
+ *
+ * @return array
+ */
+ public function getReturnMessage() {
+ $result = [
+ 'message' => 'RESOURCE_NOT_FOUND',
+ 'validationErrors' =>[
+ ]
+ ];
+
+ foreach ($this->parameterList as $missingParameter) {
+ $result['validationErrors'] = [
+ 'name' => $missingParameter,
+ 'message' => 'NOT_FOUND'
+ ];
+ }
+
+ return $result;
+ }
+
+}
diff --git a/lib/public/Federation/ICloudFederationProvider.php b/lib/public/Federation/ICloudFederationProvider.php
index f11ed4fde33..36af413cdc2 100644
--- a/lib/public/Federation/ICloudFederationProvider.php
+++ b/lib/public/Federation/ICloudFederationProvider.php
@@ -22,6 +22,8 @@
namespace OCP\Federation;
use OCP\Federation\Exceptions\ActionNotSupportedException;
+use OCP\Federation\Exceptions\AuthenticationFailedException;
+use OCP\Federation\Exceptions\BadRequestException;
use OCP\Federation\Exceptions\ProviderCouldNotAddShareException;
use OCP\Federation\Exceptions\ShareNotFoundException;
@@ -67,6 +69,8 @@ interface ICloudFederationProvider {
*
* @throws ShareNotFoundException
* @throws ActionNotSupportedException
+ * @throws BadRequestException
+ * @throws AuthenticationFailedException
*
* @since 14.0.0
*/
diff --git a/lib/public/Share/IShareProvider.php b/lib/public/Share/IShareProvider.php
index 4db43d953cf..bcb12de8b84 100644
--- a/lib/public/Share/IShareProvider.php
+++ b/lib/public/Share/IShareProvider.php
@@ -24,8 +24,8 @@
namespace OCP\Share;
+use OCP\Federation\Exceptions\ShareNotFoundException;
use OCP\Files\Folder;
-use OCP\Share\Exceptions\ShareNotFound;
use OCP\Files\Node;
/**
@@ -46,7 +46,7 @@ interface IShareProvider {
/**
* Create a share
- *
+ *
* @param \OCP\Share\IShare $share
* @return \OCP\Share\IShare The share object
* @since 9.0.0
@@ -125,7 +125,7 @@ interface IShareProvider {
* @param int $id
* @param string|null $recipientId
* @return \OCP\Share\IShare
- * @throws ShareNotFound
+ * @throws ShareNotFoundException
* @since 9.0.0
*/
public function getShareById($id, $recipientId = null);