implement unshare notification

Signed-off-by: Bjoern Schiessle <bjoern@schiessle.org>
This commit is contained in:
Bjoern Schiessle 2018-06-04 16:36:37 +02:00
parent fab4e561f4
commit a176a1f318
No known key found for this signature in database
GPG key ID: 2378A753E2BF04F6
4 changed files with 145 additions and 63 deletions

View file

@ -64,7 +64,8 @@ class Application extends App {
$server->getNotificationManager(),
$server->getURLGenerator(),
$server->getCloudFederationFactory(),
$server->getCloudFederationProviderManager()
$server->getCloudFederationProviderManager(),
$server->getDatabaseConnection()
);
});

View file

@ -333,60 +333,12 @@ class RequestHandlerController extends OCSController {
$token = isset($_POST['token']) ? $_POST['token'] : null;
$qb = $this->connection->getQueryBuilder();
$qb->select('*')
->from('share_external')
->where(
$qb->expr()->andX(
$qb->expr()->eq('remote_id', $qb->createNamedParameter($id)),
$qb->expr()->eq('share_token', $qb->createNamedParameter($token))
)
);
$result = $qb->execute();
$share = $result->fetch();
$result->closeCursor();
if ($token && $id && !empty($share)) {
$remote = $this->cleanupRemote($share['remote']);
$owner = $this->cloudIdManager->getCloudId($share['owner'], $remote);
$mountpoint = $share['mountpoint'];
$user = $share['user'];
$qb = $this->connection->getQueryBuilder();
$qb->delete('share_external')
->where(
$qb->expr()->andX(
$qb->expr()->eq('remote_id', $qb->createNamedParameter($id)),
$qb->expr()->eq('share_token', $qb->createNamedParameter($token))
)
);
$result = $qb->execute();
$result->closeCursor();
if ($share['accepted']) {
$path = trim($mountpoint, '/');
} else {
$path = trim($share['name'], '/');
}
$notificationManager = \OC::$server->getNotificationManager();
$notification = $notificationManager->createNotification();
$notification->setApp('files_sharing')
->setUser($share['user'])
->setObject('remote_share', (int)$share['id']);
$notificationManager->markProcessed($notification);
$event = \OC::$server->getActivityManager()->generateEvent();
$event->setApp('files_sharing')
->setType('remote_share')
->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_UNSHARED, [$owner->getId(), $path])
->setAffectedUser($user)
->setObject('remote_share', (int)$share['id'], $path);
\OC::$server->getActivityManager()->publish($event);
try {
$provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
$notification = ['sharedSecret' => $token];
$provider->notificationReceived('SHARE_UNSHARED', $id, $notification);
} catch (\Exception $e) {
$this->logger->debug('processing unshare notification failed: ' . $e->getMessage());
}
return new Http\DataResponse();
@ -410,16 +362,20 @@ class RequestHandlerController extends OCSController {
* @throws OCSBadRequestException
*/
public function revoke($id) {
$token = $this->request->getParam('token');
$share = $this->federatedShareProvider->getShareById($id);
$notification = $this->cloudFederationFactory->getCloudFederationNotification();
$notification->setMessage(['sharedSecret' => $token]);
if ($this->verifyShare($share, $token)) {
$this->federatedShareProvider->removeShareFromTable($share);
try {
$provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
$provider->notificationReceived('SHARE_UNSHARE', $id, $notification);
return new Http\DataResponse();
} catch (\Exception $e) {
throw new OCSBadRequestException();
}
throw new OCSBadRequestException();
}
/**

View file

@ -199,7 +199,7 @@ class Notifications {
* @return bool
*/
public function sendRevokeShare($remote, $id, $token) {
$this->sendUpdateToRemote($remote, $id, $token, 'revoke');
$this->sendUpdateToRemote($remote, $id, $token, 'reshare_undo');
}
/**
@ -250,12 +250,15 @@ class Notifications {
*/
public function sendUpdateToRemote($remote, $remoteId, $token, $action, $data = [], $try = 0) {
$fields = array('token' => $token);
$fields = [
'token' => $token,
'remoteId' => $remoteId
];
foreach ($data as $key => $value) {
$fields[$key] = $value;
}
$result = $this->tryHttpPostToShareEndpoint(rtrim($remote, '/'), '/' . $remoteId . '/' . $action, $fields);
$result = $this->tryHttpPostToShareEndpoint(rtrim($remote, '/'), '/' . $remoteId . '/' . $action, $fields, $action);
$status = json_decode($result['result'], true);
if ($result['success'] &&
@ -416,6 +419,7 @@ class Notifications {
);
return $this->federationProviderManager->sendShare($share);
case 'reshare':
// ask owner to reshare a file
$notification = $this->cloudFederationFactory->getCloudFederationNotification();
$notification->setMessage('REQUEST_RESHARE',
'file',
@ -428,6 +432,18 @@ class Notifications {
]
);
return $this->federationProviderManager->sendNotification($remoteDomain, $notification);
case 'unshare':
//owner unshares the file from the recipient again
$notification = $this->cloudFederationFactory->getCloudFederationNotification();
$notification->setMessage('SHARE_UNSHARED',
'file',
$fields['remoteId'],
[
'sharedSecret' => $fields['token'],
]
);
return $this->federationProviderManager->sendNotification($remoteDomain, $notification);
return false;
}
return false;

View file

@ -41,6 +41,7 @@ use OCP\Federation\ICloudFederationProviderManager;
use OCP\Federation\ICloudFederationShare;
use OCP\Federation\ICloudIdManager;
use OCP\Files\NotFoundException;
use OCP\IDBConnection;
use OCP\ILogger;
use OCP\IURLGenerator;
use OCP\IUserManager;
@ -84,6 +85,9 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
/** @var ICloudFederationProviderManager */
private $cloudFederationProviderManager;
/** @var IDBConnection */
private $connection;
/**
* CloudFederationProvider constructor.
*
@ -98,6 +102,7 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
* @param IURLGenerator $urlGenerator
* @param ICloudFederationFactory $cloudFederationFactory
* @param ICloudFederationProviderManager $cloudFederationProviderManager
* @param IDBConnection $connection
*/
public function __construct(IAppManager $appManager,
FederatedShareProvider $federatedShareProvider,
@ -109,7 +114,8 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
INotificationManager $notificationManager,
IURLGenerator $urlGenerator,
ICloudFederationFactory $cloudFederationFactory,
ICloudFederationProviderManager $cloudFederationProviderManager
ICloudFederationProviderManager $cloudFederationProviderManager,
IDBConnection $connection
) {
$this->appManager = $appManager;
$this->federatedShareProvider = $federatedShareProvider;
@ -122,6 +128,7 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
$this->urlGenerator = $urlGenerator;
$this->cloudFederationFactory = $cloudFederationFactory;
$this->cloudFederationProviderManager = $cloudFederationProviderManager;
$this->connection = $connection;
}
@ -275,8 +282,12 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
return $this->shareAccepted($providerId, $notification);
case 'SHARE_DECLINED':
return $this->shareDeclined($providerId, $notification);
case 'SHARE_UNSHARED':
return $this->unshare($providerId, $notification);
case 'REQUEST_RESHARE':
return $this->reshareRequested($providerId, $notification);
case 'RESHARE_UNDO':
return $this->undoReshare($providerId, $notification);
}
@ -434,6 +445,104 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
}
/**
* received the notification that the owner unshared a file from you
*
* @param string $id
* @param string $notification
* @return array
* @throws AuthenticationFailedException
* @throws BadRequestException
* @throws ShareNotFoundException
*/
private function undoReshare($id, $notification) {
if (!isset($notification['sharedSecret'])) {
throw new BadRequestException(['sharedSecret']);
}
$token = $notification['sharedSecret'];
$share = $this->federatedShareProvider->getShareById($id);
$this->verifyShare($share, $token);
$this->federatedShareProvider->removeShareFromTable($share);
return [];
}
private function unshare($id, $notification) {
error_log("new unshare!");
if (!$this->isS2SEnabled(true)) {
throw new ActionNotSupportedException("incoming shares disabled!");
}
if (!isset($notification['sharedSecret'])) {
throw new BadRequestException(['sharedSecret']);
}
$token = $notification['sharedSecret'];
$qb = $this->connection->getQueryBuilder();
$qb->select('*')
->from('share_external')
->where(
$qb->expr()->andX(
$qb->expr()->eq('remote_id', $qb->createNamedParameter($id)),
$qb->expr()->eq('share_token', $qb->createNamedParameter($token))
)
);
$result = $qb->execute();
$share = $result->fetch();
$result->closeCursor();
if ($token && $id && !empty($share)) {
$remote = $this->cleanupRemote($share['remote']);
$owner = $this->cloudIdManager->getCloudId($share['owner'], $remote);
$mountpoint = $share['mountpoint'];
$user = $share['user'];
$qb = $this->connection->getQueryBuilder();
$qb->delete('share_external')
->where(
$qb->expr()->andX(
$qb->expr()->eq('remote_id', $qb->createNamedParameter($id)),
$qb->expr()->eq('share_token', $qb->createNamedParameter($token))
)
);
$qb->execute();
if ($share['accepted']) {
$path = trim($mountpoint, '/');
} else {
$path = trim($share['name'], '/');
}
$notification = $this->notificationManager->createNotification();
$notification->setApp('files_sharing')
->setUser($share['user'])
->setObject('remote_share', (int)$share['id']);
$this->notificationManager->markProcessed($notification);
$event = $this->activityManager->generateEvent();
$event->setApp('files_sharing')
->setType('remote_share')
->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_UNSHARED, [$owner->getId(), $path])
->setAffectedUser($user)
->setObject('remote_share', (int)$share['id'], $path);
\OC::$server->getActivityManager()->publish($event);
}
return [];
}
private function cleanupRemote($remote) {
$remote = substr($remote, strpos($remote, '://') + 3);
return rtrim($remote, '/');
}
/**
* recipient of a share request to re-share the file with another user
*