implement accept share notification
Signed-off-by: Bjoern Schiessle <bjoern@schiessle.org>
This commit is contained in:
parent
bbce8c3ea1
commit
8889e14c7c
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
@ -363,20 +349,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
|
||||
|
@ -548,24 +520,6 @@ class RequestHandlerController extends OCSController {
|
|||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -252,6 +264,135 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
|
|||
throw new ActionNotSupportedException($notification);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue