send reshare over OCM API
Signed-off-by: Bjoern Schiessle <bjoern@schiessle.org>
This commit is contained in:
parent
41a1528888
commit
fab4e561f4
|
@ -117,6 +117,7 @@ class RequestHandlerController extends Controller {
|
||||||
* 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":{"sharedSecret":"secret","permissions":"webdav-property"}}}' 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":{"sharedSecret":"secret","permissions":"webdav-property"}}}' http://localhost/server/index.php/ocm/shares
|
||||||
*/
|
*/
|
||||||
public function addShare($shareWith, $name, $description, $providerId, $owner, $ownerDisplayName, $sharedBy, $sharedByDisplayName, $protocol, $shareType, $resourceType) {
|
public function addShare($shareWith, $name, $description, $providerId, $owner, $ownerDisplayName, $sharedBy, $sharedByDisplayName, $protocol, $shareType, $resourceType) {
|
||||||
|
|
||||||
if (!$this->config->incomingRequestsEnabled()) {
|
if (!$this->config->incomingRequestsEnabled()) {
|
||||||
return new JSONResponse(
|
return new JSONResponse(
|
||||||
['message' => 'This server doesn\'t support outgoing federated shares'],
|
['message' => 'This server doesn\'t support outgoing federated shares'],
|
||||||
|
@ -227,7 +228,7 @@ class RequestHandlerController extends Controller {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$provider = $this->cloudFederationProviderManager->getCloudFederationProvider($resourceType);
|
$provider = $this->cloudFederationProviderManager->getCloudFederationProvider($resourceType);
|
||||||
$provider->notificationReceived($notificationType, $providerId, $notification);
|
$result = $provider->notificationReceived($notificationType, $providerId, $notification);
|
||||||
} catch (ProviderDoesNotExistsException $e) {
|
} catch (ProviderDoesNotExistsException $e) {
|
||||||
return new JSONResponse(
|
return new JSONResponse(
|
||||||
['message' => $e->getMessage()],
|
['message' => $e->getMessage()],
|
||||||
|
@ -255,8 +256,7 @@ class RequestHandlerController extends Controller {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return new JSONResponse($result,Http::STATUS_CREATED);
|
||||||
return new JSONResponse([],Http::STATUS_CREATED);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -218,45 +218,35 @@ class RequestHandlerController extends OCSController {
|
||||||
throw new OCSBadRequestException();
|
throw new OCSBadRequestException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$notification = [
|
||||||
|
'sharedSecret' => $token,
|
||||||
|
'shareWith' => $shareWith,
|
||||||
|
'senderId' => $remoteId,
|
||||||
|
'message' => 'Recipient of a share ask the owner to reshare the file'
|
||||||
|
];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$share = $this->federatedShareProvider->getShareById($id);
|
$provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
|
||||||
} catch (Share\Exceptions\ShareNotFound $e) {
|
list($newToken, $localId) = $provider->notificationReceived('REQUEST_RESHARE', $id, $notification);
|
||||||
throw new OCSNotFoundException();
|
return new Http\DataResponse([
|
||||||
}
|
'token' => $newToken,
|
||||||
|
'remoteId' => $localId
|
||||||
// don't allow to share a file back to the owner
|
]);
|
||||||
list($user, $remote) = $this->addressHandler->splitUserRemote($shareWith);
|
} catch (ProviderDoesNotExistsException $e) {
|
||||||
$owner = $share->getShareOwner();
|
throw new OCSException('Server does not support federated cloud sharing', 503);
|
||||||
$currentServer = $this->addressHandler->generateRemoteURL();
|
} catch (ShareNotFoundException $e) {
|
||||||
if ($this->addressHandler->compareAddresses($user, $remote, $owner, $currentServer)) {
|
$this->logger->debug('Share not found: ' . $e->getMessage());
|
||||||
|
} catch (ProviderCouldNotAddShareException $e) {
|
||||||
|
$this->logger->debug('Could not add reshare: ' . $e->getMessage());
|
||||||
throw new OCSForbiddenException();
|
throw new OCSForbiddenException();
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->logger->debug('internal server error, can not process notification: ' . $e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->verifyShare($share, $token)) {
|
|
||||||
|
|
||||||
// check if re-sharing is allowed
|
|
||||||
if ($share->getPermissions() | ~Constants::PERMISSION_SHARE) {
|
|
||||||
$share->setPermissions($share->getPermissions() & $permission);
|
|
||||||
// the recipient of the initial share is now the initiator for the re-share
|
|
||||||
$share->setSharedBy($share->getSharedWith());
|
|
||||||
$share->setSharedWith($shareWith);
|
|
||||||
try {
|
|
||||||
$result = $this->federatedShareProvider->create($share);
|
|
||||||
$this->federatedShareProvider->storeRemoteId((int)$result->getId(), $remoteId);
|
|
||||||
return new Http\DataResponse([
|
|
||||||
'token' => $result->getToken(),
|
|
||||||
'remoteId' => $result->getId()
|
|
||||||
]);
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
throw new OCSBadRequestException();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new OCSForbiddenException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new OCSBadRequestException();
|
throw new OCSBadRequestException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @NoCSRFRequired
|
* @NoCSRFRequired
|
||||||
* @PublicPage
|
* @PublicPage
|
||||||
|
|
|
@ -304,7 +304,8 @@ class FederatedShareProvider implements IShareProvider {
|
||||||
$shareId,
|
$shareId,
|
||||||
$remote,
|
$remote,
|
||||||
$shareWith,
|
$shareWith,
|
||||||
$share->getPermissions()
|
$share->getPermissions(),
|
||||||
|
$share->getNode()->getName()
|
||||||
);
|
);
|
||||||
|
|
||||||
return [$token, $remoteId];
|
return [$token, $remoteId];
|
||||||
|
|
|
@ -136,20 +136,31 @@ class Notifications {
|
||||||
* @param string $remote remote address of the owner
|
* @param string $remote remote address of the owner
|
||||||
* @param string $shareWith
|
* @param string $shareWith
|
||||||
* @param int $permission
|
* @param int $permission
|
||||||
|
* @param string $filename
|
||||||
* @return bool
|
* @return bool
|
||||||
* @throws \OC\HintException
|
* @throws \OC\HintException
|
||||||
* @throws \OC\ServerNotAvailableException
|
* @throws \OC\ServerNotAvailableException
|
||||||
*/
|
*/
|
||||||
public function requestReShare($token, $id, $shareId, $remote, $shareWith, $permission) {
|
public function requestReShare($token, $id, $shareId, $remote, $shareWith, $permission, $filename) {
|
||||||
|
|
||||||
$fields = array(
|
$fields = array(
|
||||||
'shareWith' => $shareWith,
|
'shareWith' => $shareWith,
|
||||||
'token' => $token,
|
'token' => $token,
|
||||||
'permission' => $permission,
|
'permission' => $permission,
|
||||||
'remoteId' => $shareId
|
'remoteId' => $shareId,
|
||||||
);
|
);
|
||||||
|
|
||||||
$result = $this->tryHttpPostToShareEndpoint(rtrim($remote, '/'), '/' . $id . '/reshare', $fields);
|
$ocmFields = $fields;
|
||||||
|
$ocmFields['remoteId'] = $id;
|
||||||
|
$ocmFields['localId'] = $shareId;
|
||||||
|
$ocmFields['name'] = $filename;
|
||||||
|
|
||||||
|
$ocmResult = $this->tryOCMEndPoint($remote, $ocmFields, 'reshare');
|
||||||
|
if (is_array($ocmResult) && isset($ocmResult['token']) && isset($ocmResult['providerId'])) {
|
||||||
|
return [$ocmResult['token'], $ocmResult['providerId']];
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = $this->tryLegacyEndPoint(rtrim($remote, '/'), '/' . $id . '/reshare', $fields);
|
||||||
$status = json_decode($result['result'], true);
|
$status = json_decode($result['result'], true);
|
||||||
|
|
||||||
$httpRequestSuccessful = $result['success'];
|
$httpRequestSuccessful = $result['success'];
|
||||||
|
@ -310,6 +321,25 @@ class Notifications {
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $this->tryLegacyEndPoint($remoteDomain, $urlSuffix, $fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* try old federated sharing API if the OCM api doesn't work
|
||||||
|
*
|
||||||
|
* @param $remoteDomain
|
||||||
|
* @param $urlSuffix
|
||||||
|
* @param array $fields
|
||||||
|
* @return mixed
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
protected function tryLegacyEndPoint($remoteDomain, $urlSuffix, array $fields) {
|
||||||
|
|
||||||
|
$result = [
|
||||||
|
'success' => false,
|
||||||
|
'result' => '',
|
||||||
|
];
|
||||||
|
|
||||||
// Fall back to old API
|
// Fall back to old API
|
||||||
$client = $this->httpClientService->newClient();
|
$client = $this->httpClientService->newClient();
|
||||||
$federationEndpoints = $this->discoveryService->discover($remoteDomain, 'FEDERATED_SHARING');
|
$federationEndpoints = $this->discoveryService->discover($remoteDomain, 'FEDERATED_SHARING');
|
||||||
|
@ -332,6 +362,7 @@ class Notifications {
|
||||||
}
|
}
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -384,7 +415,22 @@ class Notifications {
|
||||||
'file'
|
'file'
|
||||||
);
|
);
|
||||||
return $this->federationProviderManager->sendShare($share);
|
return $this->federationProviderManager->sendShare($share);
|
||||||
|
case 'reshare':
|
||||||
|
$notification = $this->cloudFederationFactory->getCloudFederationNotification();
|
||||||
|
$notification->setMessage('REQUEST_RESHARE',
|
||||||
|
'file',
|
||||||
|
$fields['remoteId'],
|
||||||
|
[
|
||||||
|
'sharedSecret' => $fields['token'],
|
||||||
|
'shareWith' => $fields['shareWith'],
|
||||||
|
'senderId' => $fields['localId'],
|
||||||
|
'message' => 'Ask owner to reshare the file'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
return $this->federationProviderManager->sendNotification($remoteDomain, $notification);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ use OCA\FederatedFileSharing\FederatedShareProvider;
|
||||||
use OCP\Activity\IManager as IActivityManager;
|
use OCP\Activity\IManager as IActivityManager;
|
||||||
use OCP\Activity\IManager;
|
use OCP\Activity\IManager;
|
||||||
use OCP\App\IAppManager;
|
use OCP\App\IAppManager;
|
||||||
|
use OCP\Constants;
|
||||||
use OCP\Federation\Exceptions\ActionNotSupportedException;
|
use OCP\Federation\Exceptions\ActionNotSupportedException;
|
||||||
use OCP\Federation\Exceptions\AuthenticationFailedException;
|
use OCP\Federation\Exceptions\AuthenticationFailedException;
|
||||||
use OCP\Federation\Exceptions\BadRequestException;
|
use OCP\Federation\Exceptions\BadRequestException;
|
||||||
|
@ -258,6 +259,7 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
|
||||||
* @param string $notificationType (e.g. SHARE_ACCEPTED)
|
* @param string $notificationType (e.g. SHARE_ACCEPTED)
|
||||||
* @param string $providerId id of the share
|
* @param string $providerId id of the share
|
||||||
* @param array $notification payload of the notification
|
* @param array $notification payload of the notification
|
||||||
|
* @return array data send back to the sender
|
||||||
*
|
*
|
||||||
* @throws ActionNotSupportedException
|
* @throws ActionNotSupportedException
|
||||||
* @throws AuthenticationFailedException
|
* @throws AuthenticationFailedException
|
||||||
|
@ -270,11 +272,11 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
|
||||||
|
|
||||||
switch ($notificationType) {
|
switch ($notificationType) {
|
||||||
case 'SHARE_ACCEPTED':
|
case 'SHARE_ACCEPTED':
|
||||||
$this->shareAccepted($providerId, $notification);
|
return $this->shareAccepted($providerId, $notification);
|
||||||
return;
|
|
||||||
case 'SHARE_DECLINED':
|
case 'SHARE_DECLINED':
|
||||||
$this->shareDeclined($providerId, $notification);
|
return $this->shareDeclined($providerId, $notification);
|
||||||
return;
|
case 'REQUEST_RESHARE':
|
||||||
|
return $this->reshareRequested($providerId, $notification);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -282,9 +284,11 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* process notification that the recipient accepted a share
|
||||||
|
*
|
||||||
* @param string $id
|
* @param string $id
|
||||||
* @param array $notification
|
* @param array $notification
|
||||||
* @return bool
|
* @return array
|
||||||
* @throws ActionNotSupportedException
|
* @throws ActionNotSupportedException
|
||||||
* @throws AuthenticationFailedException
|
* @throws AuthenticationFailedException
|
||||||
* @throws BadRequestException
|
* @throws BadRequestException
|
||||||
|
@ -325,7 +329,7 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -351,14 +355,18 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* process notification that the recipient declined a share
|
||||||
|
*
|
||||||
* @param string $id
|
* @param string $id
|
||||||
* @param array $notification
|
* @param array $notification
|
||||||
|
* @return array
|
||||||
* @throws ActionNotSupportedException
|
* @throws ActionNotSupportedException
|
||||||
* @throws AuthenticationFailedException
|
* @throws AuthenticationFailedException
|
||||||
* @throws BadRequestException
|
* @throws BadRequestException
|
||||||
* @throws ShareNotFound
|
* @throws ShareNotFound
|
||||||
* @throws ShareNotFoundException
|
* @throws ShareNotFoundException
|
||||||
* @throws \OC\HintException
|
* @throws \OC\HintException
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
protected function shareDeclined($id, $notification) {
|
protected function shareDeclined($id, $notification) {
|
||||||
|
|
||||||
|
@ -395,6 +403,8 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
|
||||||
|
|
||||||
$this->executeDeclineShare($share);
|
$this->executeDeclineShare($share);
|
||||||
|
|
||||||
|
return [];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -424,6 +434,64 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* recipient of a share request to re-share the file with another user
|
||||||
|
*
|
||||||
|
* @param $id
|
||||||
|
* @param $notification
|
||||||
|
* @return array
|
||||||
|
* @throws AuthenticationFailedException
|
||||||
|
* @throws BadRequestException
|
||||||
|
* @throws ProviderCouldNotAddShareException
|
||||||
|
* @throws ShareNotFoundException
|
||||||
|
* @throws ShareNotFound
|
||||||
|
*/
|
||||||
|
protected function reshareRequested($id, $notification) {
|
||||||
|
|
||||||
|
if (!isset($notification['sharedSecret'])) {
|
||||||
|
throw new BadRequestException(['sharedSecret']);
|
||||||
|
}
|
||||||
|
$token = $notification['sharedSecret'];
|
||||||
|
|
||||||
|
if (!isset($notification['shareWith'])) {
|
||||||
|
throw new BadRequestException(['shareWith']);
|
||||||
|
}
|
||||||
|
$shareWith = $notification['shareWith'];
|
||||||
|
|
||||||
|
if (!isset($notification['senderId'])) {
|
||||||
|
throw new BadRequestException(['senderId']);
|
||||||
|
}
|
||||||
|
$senderId = $notification['senderId'];
|
||||||
|
|
||||||
|
$share = $this->federatedShareProvider->getShareById($id);
|
||||||
|
// don't allow to share a file back to the owner
|
||||||
|
try {
|
||||||
|
list($user, $remote) = $this->addressHandler->splitUserRemote($shareWith);
|
||||||
|
$owner = $share->getShareOwner();
|
||||||
|
$currentServer = $this->addressHandler->generateRemoteURL();
|
||||||
|
if ($this->addressHandler->compareAddresses($user, $remote, $owner, $currentServer)) {
|
||||||
|
throw new ProviderCouldNotAddShareException('Resharing back to the owner is not allowed: ' . $id);
|
||||||
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
throw new ProviderCouldNotAddShareException($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->verifyShare($share, $token);
|
||||||
|
|
||||||
|
// check if re-sharing is allowed
|
||||||
|
if ($share->getPermissions() | ~Constants::PERMISSION_SHARE) {
|
||||||
|
// the recipient of the initial share is now the initiator for the re-share
|
||||||
|
$share->setSharedBy($share->getSharedWith());
|
||||||
|
$share->setSharedWith($shareWith);
|
||||||
|
$result = $this->federatedShareProvider->create($share);
|
||||||
|
$this->federatedShareProvider->storeRemoteId((int)$result->getId(), $senderId);
|
||||||
|
return ['token' => $result->getToken(), 'providerId' => $result->getId()];
|
||||||
|
} else {
|
||||||
|
throw new ProviderCouldNotAddShareException('resharing not allowed for share: ' . $id);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new BadRequestException([]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get file
|
* get file
|
||||||
|
|
|
@ -166,7 +166,7 @@ class CloudFederationProviderManager implements ICloudFederationProviderManager
|
||||||
/**
|
/**
|
||||||
* @param string $url
|
* @param string $url
|
||||||
* @param ICloudFederationNotification $notification
|
* @param ICloudFederationNotification $notification
|
||||||
* @return bool
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function sendNotification($url, ICloudFederationNotification $notification) {
|
public function sendNotification($url, ICloudFederationNotification $notification) {
|
||||||
$ocmEndPoint = $this->getOCMEndPoint($url);
|
$ocmEndPoint = $this->getOCMEndPoint($url);
|
||||||
|
@ -182,8 +182,9 @@ class CloudFederationProviderManager implements ICloudFederationProviderManager
|
||||||
'timeout' => 10,
|
'timeout' => 10,
|
||||||
'connect_timeout' => 10,
|
'connect_timeout' => 10,
|
||||||
]);
|
]);
|
||||||
if ($response->getStatusCode() === Http::STATUS_OK) {
|
if ($response->getStatusCode() === Http::STATUS_CREATED) {
|
||||||
return true;
|
$result = json_decode($response->getBody(), true);
|
||||||
|
return (is_array($result)) ? $result : [];
|
||||||
}
|
}
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
// log the error and return false
|
// log the error and return false
|
||||||
|
|
|
@ -66,6 +66,7 @@ interface ICloudFederationProvider {
|
||||||
* @param string $notificationType (e.g SHARE_ACCEPTED)
|
* @param string $notificationType (e.g SHARE_ACCEPTED)
|
||||||
* @param string $providerId share ID
|
* @param string $providerId share ID
|
||||||
* @param array $notification provider specific notification
|
* @param array $notification provider specific notification
|
||||||
|
* @return array $data send back to sender
|
||||||
*
|
*
|
||||||
* @throws ShareNotFoundException
|
* @throws ShareNotFoundException
|
||||||
* @throws ActionNotSupportedException
|
* @throws ActionNotSupportedException
|
||||||
|
|
|
@ -77,7 +77,7 @@ interface ICloudFederationProviderManager {
|
||||||
* send federated share
|
* send federated share
|
||||||
*
|
*
|
||||||
* @param ICloudFederationShare $share
|
* @param ICloudFederationShare $share
|
||||||
* @return mixed
|
* @return bool
|
||||||
*
|
*
|
||||||
* @since 14.0.0
|
* @since 14.0.0
|
||||||
*/
|
*/
|
||||||
|
@ -88,7 +88,7 @@ interface ICloudFederationProviderManager {
|
||||||
*
|
*
|
||||||
* @param string $url
|
* @param string $url
|
||||||
* @param ICloudFederationNotification $notification
|
* @param ICloudFederationNotification $notification
|
||||||
* @return bool
|
* @return mixed
|
||||||
*
|
*
|
||||||
* @since 14.0.0
|
* @since 14.0.0
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue