summaryrefslogtreecommitdiffstats
path: root/apps/federatedfilesharing/lib
diff options
context:
space:
mode:
authorBjoern Schiessle <bjoern@schiessle.org>2018-06-13 14:19:59 +0200
committerBjoern Schiessle <bjoern@schiessle.org>2018-07-11 10:11:44 +0200
commitb23032e4c569f7ba54197171cbb02ed8119b6811 (patch)
tree882cc64ab6398f33962428d79aa270055a20f6e0 /apps/federatedfilesharing/lib
parentc8631d607ef827f0eb29312faf7b2b808e1a8e7d (diff)
downloadnextcloud-server-b23032e4c569f7ba54197171cbb02ed8119b6811.tar.gz
nextcloud-server-b23032e4c569f7ba54197171cbb02ed8119b6811.zip
implement federated group shares
Signed-off-by: Bjoern Schiessle <bjoern@schiessle.org>
Diffstat (limited to 'apps/federatedfilesharing/lib')
-rw-r--r--apps/federatedfilesharing/lib/AppInfo/Application.php7
-rw-r--r--apps/federatedfilesharing/lib/FederatedShareProvider.php44
-rw-r--r--apps/federatedfilesharing/lib/Notifications.php7
-rw-r--r--apps/federatedfilesharing/lib/ocm/CloudFederationProviderFiles.php113
4 files changed, 122 insertions, 49 deletions
diff --git a/apps/federatedfilesharing/lib/AppInfo/Application.php b/apps/federatedfilesharing/lib/AppInfo/Application.php
index 70347831211..73ac062be09 100644
--- a/apps/federatedfilesharing/lib/AppInfo/Application.php
+++ b/apps/federatedfilesharing/lib/AppInfo/Application.php
@@ -65,7 +65,8 @@ class Application extends App {
$server->getURLGenerator(),
$server->getCloudFederationFactory(),
$server->getCloudFederationProviderManager(),
- $server->getDatabaseConnection()
+ $server->getDatabaseConnection(),
+ $server->getGroupManager()
);
});
@@ -145,7 +146,9 @@ class Application extends App {
\OC::$server->getConfig(),
\OC::$server->getUserManager(),
\OC::$server->getCloudIdManager(),
- $c->query(IConfig::class)
+ $c->query(IConfig::class),
+ \OC::$server->getCloudFederationProviderManager()
+
);
}
diff --git a/apps/federatedfilesharing/lib/FederatedShareProvider.php b/apps/federatedfilesharing/lib/FederatedShareProvider.php
index d32560c4ffd..d1560d90ef5 100644
--- a/apps/federatedfilesharing/lib/FederatedShareProvider.php
+++ b/apps/federatedfilesharing/lib/FederatedShareProvider.php
@@ -96,6 +96,9 @@ class FederatedShareProvider implements IShareProvider {
/** @var ICloudFederationProviderManager */
private $cloudFederationProviderManager;
+ /** @var array list of supported share types */
+ private $supportedShareType = [\OCP\Share::SHARE_TYPE_REMOTE_GROUP, \OCP\Share::SHARE_TYPE_REMOTE];
+
/**
* DefaultShareProvider constructor.
*
@@ -164,12 +167,23 @@ class FederatedShareProvider implements IShareProvider {
$itemType = $share->getNodeType();
$permissions = $share->getPermissions();
$sharedBy = $share->getSharedBy();
+ $shareType = $share->getShareType();
+
+ if ($shareType === \OCP\Share::SHARE_TYPE_REMOTE_GROUP &&
+ !$this->isOutgoingServer2serverGroupShareEnabled()
+ ) {
+ $message = 'It is not allowed to send federated group shares from this server.';
+ $message_t = $this->l->t('It is not allowed to send federated group shares from this server.');
+ $this->logger->debug($message, ['app' => 'Federated File Sharing']);
+ throw new \Exception($message_t);
+ }
/*
* Check if file is not already shared with the remote user
*/
- $alreadyShared = $this->getSharedWith($shareWith, self::SHARE_TYPE_REMOTE, $share->getNode(), 1, 0);
- if (!empty($alreadyShared)) {
+ $alreadyShared = $this->getSharedWith($shareWith, \OCP\Share::SHARE_TYPE_REMOTE, $share->getNode(), 1, 0);
+ $alreadySharedGroup = $this->getSharedWith($shareWith, \OCP\Share::SHARE_TYPE_REMOTE_GROUP, $share->getNode(), 1, 0);
+ if (!empty($alreadyShared) || !empty($alreadySharedGroup)) {
$message = 'Sharing %s failed, because this item is already shared with %s';
$message_t = $this->l->t('Sharing %s failed, because this item is already shared with %s', array($share->getNode()->getName(), $shareWith));
$this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']);
@@ -200,7 +214,7 @@ class FederatedShareProvider implements IShareProvider {
if ($remoteShare) {
try {
$ownerCloudId = $this->cloudIdManager->getCloudId($remoteShare['owner'], $remoteShare['remote']);
- $shareId = $this->addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $ownerCloudId->getId(), $permissions, 'tmp_token_' . time());
+ $shareId = $this->addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $ownerCloudId->getId(), $permissions, 'tmp_token_' . time(), $shareType);
$share->setId($shareId);
list($token, $remoteId) = $this->askOwnerToReShare($shareWith, $share, $shareId);
// remote share was create successfully if we get a valid token as return
@@ -245,7 +259,8 @@ class FederatedShareProvider implements IShareProvider {
$share->getSharedBy(),
$share->getShareOwner(),
$share->getPermissions(),
- $token
+ $token,
+ $share->getShareType()
);
$failure = false;
@@ -265,7 +280,8 @@ class FederatedShareProvider implements IShareProvider {
$share->getShareOwner(),
$ownerCloudId->getId(),
$share->getSharedBy(),
- $sharedByFederatedId
+ $sharedByFederatedId,
+ $share->getShareType()
);
if ($send === false) {
@@ -349,12 +365,13 @@ class FederatedShareProvider implements IShareProvider {
* @param string $uidOwner
* @param int $permissions
* @param string $token
+ * @param int $shareType
* @return int
*/
- private function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token) {
+ private function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $shareType) {
$qb = $this->dbConnection->getQueryBuilder();
$qb->insert('share')
- ->setValue('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE))
+ ->setValue('share_type', $qb->createNamedParameter($shareType))
->setValue('item_type', $qb->createNamedParameter($itemType))
->setValue('item_source', $qb->createNamedParameter($itemSource))
->setValue('file_source', $qb->createNamedParameter($itemSource))
@@ -498,7 +515,7 @@ class FederatedShareProvider implements IShareProvider {
$qb->select('*')
->from('share')
->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
- ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)))
+ ->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
->orderBy('id');
$cursor = $qb->execute();
@@ -647,7 +664,7 @@ class FederatedShareProvider implements IShareProvider {
$qb->select('*')
->from('share');
- $qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)));
+ $qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter($shareType)));
/**
* Reshares for this user are shares where they are the owner.
@@ -704,7 +721,7 @@ class FederatedShareProvider implements IShareProvider {
$qb->select('*')
->from('share')
->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
- ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)));
+ ->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)));
$cursor = $qb->execute();
$data = $cursor->fetch();
@@ -732,10 +749,11 @@ class FederatedShareProvider implements IShareProvider {
public function getSharesByPath(Node $path) {
$qb = $this->dbConnection->getQueryBuilder();
+ // get federated user shares
$cursor = $qb->select('*')
->from('share')
->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
- ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)))
+ ->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
->execute();
$shares = [];
@@ -768,7 +786,7 @@ class FederatedShareProvider implements IShareProvider {
}
$qb->setFirstResult($offset);
- $qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)));
+ $qb->where($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)));
$qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
// Filter by node if provided
@@ -799,7 +817,7 @@ class FederatedShareProvider implements IShareProvider {
$cursor = $qb->select('*')
->from('share')
- ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)))
+ ->where($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
->execute();
diff --git a/apps/federatedfilesharing/lib/Notifications.php b/apps/federatedfilesharing/lib/Notifications.php
index fdba3e113d6..70733bc9e2c 100644
--- a/apps/federatedfilesharing/lib/Notifications.php
+++ b/apps/federatedfilesharing/lib/Notifications.php
@@ -88,11 +88,12 @@ class Notifications {
* @param string $ownerFederatedId
* @param string $sharedBy
* @param string $sharedByFederatedId
+ * @param int $shareType (can be a remote user or group share)
* @return bool
* @throws \OC\HintException
* @throws \OC\ServerNotAvailableException
*/
- public function sendRemoteShare($token, $shareWith, $name, $remote_id, $owner, $ownerFederatedId, $sharedBy, $sharedByFederatedId) {
+ public function sendRemoteShare($token, $shareWith, $name, $remote_id, $owner, $ownerFederatedId, $sharedBy, $sharedByFederatedId, $shareType) {
list($user, $remote) = $this->addressHandler->splitUserRemote($shareWith);
@@ -109,6 +110,7 @@ class Notifications {
'sharedBy' => $sharedBy,
'sharedByFederatedId' => $sharedByFederatedId,
'remote' => $local,
+ 'shareType' => $shareType
);
$result = $this->tryHttpPostToShareEndpoint($remote, '', $fields);
@@ -392,7 +394,7 @@ class Notifications {
$fields['sharedByFederatedId'],
$fields['sharedBy'],
$fields['token'],
- 'user',
+ $fields['shareType'],
'file'
);
return $this->federationProviderManager->sendShare($share);
@@ -406,6 +408,7 @@ class Notifications {
'sharedSecret' => $fields['token'],
'shareWith' => $fields['shareWith'],
'senderId' => $fields['localId'],
+ 'shareType' => $fields['shareType'],
'message' => 'Ask owner to reshare the file'
]
);
diff --git a/apps/federatedfilesharing/lib/ocm/CloudFederationProviderFiles.php b/apps/federatedfilesharing/lib/ocm/CloudFederationProviderFiles.php
index 00750f924ef..cb7b6478e77 100644
--- a/apps/federatedfilesharing/lib/ocm/CloudFederationProviderFiles.php
+++ b/apps/federatedfilesharing/lib/ocm/CloudFederationProviderFiles.php
@@ -40,10 +40,12 @@ use OCP\Federation\ICloudFederationShare;
use OCP\Federation\ICloudIdManager;
use OCP\Files\NotFoundException;
use OCP\IDBConnection;
+use OCP\IGroupManager;
use OCP\ILogger;
use OCP\IURLGenerator;
use OCP\IUserManager;
use OCP\Notification\IManager as INotificationManager;
+use OCP\Share;
use OCP\Share\Exceptions\ShareNotFound;
use OCP\Share\IShare;
use OCP\Util;
@@ -86,6 +88,9 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
/** @var IDBConnection */
private $connection;
+ /** @var IGroupManager */
+ private $groupManager;
+
/**
* CloudFederationProvider constructor.
*
@@ -101,6 +106,7 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
* @param ICloudFederationFactory $cloudFederationFactory
* @param ICloudFederationProviderManager $cloudFederationProviderManager
* @param IDBConnection $connection
+ * @param IGroupManager $groupManager
*/
public function __construct(IAppManager $appManager,
FederatedShareProvider $federatedShareProvider,
@@ -113,7 +119,8 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
IURLGenerator $urlGenerator,
ICloudFederationFactory $cloudFederationFactory,
ICloudFederationProviderManager $cloudFederationProviderManager,
- IDBConnection $connection
+ IDBConnection $connection,
+ IGroupManager $groupManager
) {
$this->appManager = $appManager;
$this->federatedShareProvider = $federatedShareProvider;
@@ -127,6 +134,7 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
$this->cloudFederationFactory = $cloudFederationFactory;
$this->cloudFederationProviderManager = $cloudFederationProviderManager;
$this->connection = $connection;
+ $this->groupManager = $groupManager;
}
@@ -175,6 +183,7 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
$remoteId = $share->getProviderId();
$sharedByFederatedId = $share->getSharedBy();
$ownerFederatedId = $share->getOwner();
+ $shareType = $this->mapShareTypeToNextcloud($share->getShareType());
// if no explicit information about the person who created the share was send
// we assume that the share comes from the owner
@@ -190,19 +199,25 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
}
// FIXME this should be a method in the user management instead
- $this->logger->debug('shareWith before, ' . $shareWith, ['app' => 'files_sharing']);
- Util::emitHook(
- '\OCA\Files_Sharing\API\Server2Server',
- 'preLoginNameUsedAsUserName',
- array('uid' => &$shareWith)
- );
- $this->logger->debug('shareWith after, ' . $shareWith, ['app' => 'files_sharing']);
+ if ($shareType === Share::SHARE_TYPE_USER) {
+ $this->logger->debug('shareWith before, ' . $shareWith, ['app' => 'files_sharing']);
+ Util::emitHook(
+ '\OCA\Files_Sharing\API\Server2Server',
+ 'preLoginNameUsedAsUserName',
+ array('uid' => &$shareWith)
+ );
+ $this->logger->debug('shareWith after, ' . $shareWith, ['app' => 'files_sharing']);
- if (!$this->userManager->userExists($shareWith)) {
- throw new ProviderCouldNotAddShareException('User does not exists', '',Http::STATUS_BAD_REQUEST);
+ if (!$this->userManager->userExists($shareWith)) {
+ throw new ProviderCouldNotAddShareException('User does not exists', '',Http::STATUS_BAD_REQUEST);
+ }
+
+ \OC_Util::setupFS($shareWith);
}
- \OC_Util::setupFS($shareWith);
+ if ($shareType === Share::SHARE_TYPE_GROUP && !$this->groupManager->groupExists($shareWith)) {
+ throw new ProviderCouldNotAddShareException('Group does not exists', '',Http::STATUS_BAD_REQUEST);
+ }
$externalManager = new \OCA\Files_Sharing\External\Manager(
\OC::$server->getDatabaseConnection(),
@@ -217,7 +232,7 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
);
try {
- $externalManager->addShare($remote, $token, '', $name, $owner, false, $shareWith, $remoteId);
+ $externalManager->addShare($remote, $token, '', $name, $owner, $shareType,false, $shareWith, $remoteId);
$shareId = \OC::$server->getDatabaseConnection()->lastInsertId('*PREFIX*share_external');
$event = $this->activityManager->generateEvent();
@@ -228,25 +243,14 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
->setObject('remote_share', (int)$shareId, $name);
\OC::$server->getActivityManager()->publish($event);
- $notification = $this->notificationManager->createNotification();
- $notification->setApp('files_sharing')
- ->setUser($shareWith)
- ->setDateTime(new \DateTime())
- ->setObject('remote_share', $shareId)
- ->setSubject('remote_share', [$ownerFederatedId, $sharedByFederatedId, trim($name, '/')]);
-
- $declineAction = $notification->createAction();
- $declineAction->setLabel('decline')
- ->setLink($this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/' . $shareId)), 'DELETE');
- $notification->addAction($declineAction);
-
- $acceptAction = $notification->createAction();
- $acceptAction->setLabel('accept')
- ->setLink($this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/' . $shareId)), 'POST');
- $notification->addAction($acceptAction);
-
- $this->notificationManager->notify($notification);
-
+ if ($shareType === Share::SHARE_TYPE_USER) {
+ $this->notifyAboutNewShare($shareWith, $shareId, $ownerFederatedId, $sharedByFederatedId, $name);
+ } else {
+ $groupMembers = $this->groupManager->get($shareWith)->getUsers();
+ foreach ($groupMembers as $user) {
+ $this->notifyAboutNewShare($user, $shareId, $ownerFederatedId, $sharedByFederatedId, $name);
+ }
+ }
return $shareId;
} catch (\Exception $e) {
$this->logger->logException($e, [
@@ -298,6 +302,51 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
}
/**
+ * map OCM share type (strings) to Nextcloud internal share types (integer)
+ *
+ * @param string $shareType
+ * @return int
+ */
+ private function mapShareTypeToNextcloud($shareType) {
+ $result = Share::SHARE_TYPE_USER;
+ if ($shareType === 'group') {
+ $result = Share::SHARE_TYPE_GROUP;
+ }
+
+ return $result;
+ }
+
+ /**
+ * notify user about new federated share
+ *
+ * @param $shareWith
+ * @param $shareId
+ * @param $ownerFederatedId
+ * @param $sharedByFederatedId
+ * @param $name
+ */
+ private function notifyAboutNewShare($shareWith, $shareId, $ownerFederatedId, $sharedByFederatedId, $name) {
+ $notification = $this->notificationManager->createNotification();
+ $notification->setApp('files_sharing')
+ ->setUser($shareWith)
+ ->setDateTime(new \DateTime())
+ ->setObject('remote_share', $shareId)
+ ->setSubject('remote_share', [$ownerFederatedId, $sharedByFederatedId, trim($name, '/')]);
+
+ $declineAction = $notification->createAction();
+ $declineAction->setLabel('decline')
+ ->setLink($this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/' . $shareId)), 'DELETE');
+ $notification->addAction($declineAction);
+
+ $acceptAction = $notification->createAction();
+ $acceptAction->setLabel('accept')
+ ->setLink($this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/' . $shareId)), 'POST');
+ $notification->addAction($acceptAction);
+
+ $this->notificationManager->notify($notification);
+ }
+
+ /**
* process notification that the recipient accepted a share
*
* @param string $id
@@ -771,6 +820,6 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
* @since 14.0.0
*/
public function getSupportedShareTypes() {
- return ['user'];
+ return ['user', 'group'];
}
}