diff --git a/apps/cloud_federation_api/lib/Config.php b/apps/cloud_federation_api/lib/Config.php
index 7d42960deaf80..2fb842697d44a 100644
--- a/apps/cloud_federation_api/lib/Config.php
+++ b/apps/cloud_federation_api/lib/Config.php
@@ -47,11 +47,14 @@ public function __construct(ICloudFederationProviderManager $cloudFederationProv
*
* @param string $resourceType
* @return array
- * @throws \OCP\Federation\Exceptions\ProviderDoesNotExistsException
*/
public function getSupportedShareTypes($resourceType) {
- $provider = $this->cloudFederationProviderManager->getCloudFederationProvider($resourceType);
- return $provider->getSupportedShareTypes();
+ try {
+ $provider = $this->cloudFederationProviderManager->getCloudFederationProvider($resourceType);
+ return $provider->getSupportedShareTypes();
+ } catch (\Exception $e) {
+ return [];
+ }
}
}
diff --git a/apps/cloud_federation_api/lib/Controller/RequestHandlerController.php b/apps/cloud_federation_api/lib/Controller/RequestHandlerController.php
index 27dd89f2abe97..e7c6c415d3c49 100644
--- a/apps/cloud_federation_api/lib/Controller/RequestHandlerController.php
+++ b/apps/cloud_federation_api/lib/Controller/RequestHandlerController.php
@@ -35,6 +35,7 @@
use OCP\Federation\ICloudFederationProviderManager;
use OCP\Federation\Exceptions\ProviderDoesNotExistsException;
use OCP\Federation\ICloudIdManager;
+use OCP\IGroupManager;
use OCP\ILogger;
use OCP\IRequest;
use OCP\IURLGenerator;
@@ -57,6 +58,9 @@ class RequestHandlerController extends Controller {
/** @var IUserManager */
private $userManager;
+ /** @var IGroupManager */
+ private $groupManager;
+
/** @var IURLGenerator */
private $urlGenerator;
@@ -76,6 +80,7 @@ public function __construct($appName,
IRequest $request,
ILogger $logger,
IUserManager $userManager,
+ IGroupManager $groupManager,
IURLGenerator $urlGenerator,
ICloudFederationProviderManager $cloudFederationProviderManager,
Config $config,
@@ -86,6 +91,7 @@ public function __construct($appName,
$this->logger = $logger;
$this->userManager = $userManager;
+ $this->groupManager = $groupManager;
$this->urlGenerator = $urlGenerator;
$this->cloudFederationProviderManager = $cloudFederationProviderManager;
$this->config = $config;
@@ -136,17 +142,37 @@ public function addShare($shareWith, $name, $description, $providerId, $owner, $
);
}
- $cloudId = $this->cloudIdManager->resolveCloudId($shareWith);
- $shareWithLocalId = $cloudId->getUser();
- $shareWith = $this->mapUid($shareWithLocalId);
-
- if (!$this->userManager->userExists($shareWith)) {
+ $supportedShareTypes = $this->config->getSupportedShareTypes($resourceType);
+ if (!in_array($shareType, $supportedShareTypes)) {
return new JSONResponse(
- ['message' => 'User "' . $shareWith . '" does not exists at ' . $this->urlGenerator->getBaseUrl()],
- Http::STATUS_BAD_REQUEST
+ ['message' => 'Share type "' . $shareType . '" not implemented'],
+ Http::STATUS_NOT_IMPLEMENTED
);
}
+ $cloudId = $this->cloudIdManager->resolveCloudId($shareWith);
+ $shareWith = $cloudId->getUser();
+
+ if ($shareType === 'user') {
+ $shareWith = $this->mapUid($shareWith);
+
+ if (!$this->userManager->userExists($shareWith)) {
+ return new JSONResponse(
+ ['message' => 'User "' . $shareWith . '" does not exists at ' . $this->urlGenerator->getBaseUrl()],
+ Http::STATUS_BAD_REQUEST
+ );
+ }
+ }
+
+ if ($shareType === 'group') {
+ if(!$this->groupManager->groupExists($shareWith)) {
+ return new JSONResponse(
+ ['message' => 'Group "' . $shareWith . '" does not exists at ' . $this->urlGenerator->getBaseUrl()],
+ Http::STATUS_BAD_REQUEST
+ );
+ }
+ }
+
// if no explicit display name is given, we use the uid as display name
$ownerDisplayName = $ownerDisplayName === null ? $owner : $ownerDisplayName;
$sharedByDisplayName = $sharedByDisplayName === null ? $sharedBy : $sharedByDisplayName;
@@ -161,7 +187,7 @@ public function addShare($shareWith, $name, $description, $providerId, $owner, $
$provider = $this->cloudFederationProviderManager->getCloudFederationProvider($resourceType);
$share = $this->factory->getCloudFederationShare($shareWith, $name, $description, $providerId, $owner, $ownerDisplayName, $sharedBy, $sharedByDisplayName, '', $shareType, $resourceType);
$share->setProtocol($protocol);
- $id = $provider->shareReceived($share);
+ $provider->shareReceived($share);
} catch (ProviderDoesNotExistsException $e) {
return new JSONResponse(
['message' => $e->getMessage()],
@@ -179,7 +205,7 @@ public function addShare($shareWith, $name, $description, $providerId, $owner, $
);
}
- $user = $this->userManager->get($shareWithLocalId);
+ $user = $this->userManager->get($shareWith);
$recipientDisplayName = '';
if($user) {
$recipientDisplayName = $user->getDisplayName();
@@ -259,7 +285,6 @@ public function receiveNotification($notificationType, $resourceType, $providerI
* @return string mixed
*/
private function mapUid($uid) {
- \OC::$server->getURLGenerator()->linkToDocs('key');
// FIXME this should be a method in the user management instead
$this->logger->debug('shareWith before, ' . $uid, ['app' => $this->appName]);
\OCP\Util::emitHook(
diff --git a/apps/federatedfilesharing/lib/AppInfo/Application.php b/apps/federatedfilesharing/lib/AppInfo/Application.php
index 7034783121125..73ac062be095c 100644
--- a/apps/federatedfilesharing/lib/AppInfo/Application.php
+++ b/apps/federatedfilesharing/lib/AppInfo/Application.php
@@ -65,7 +65,8 @@ function() use ($container) {
$server->getURLGenerator(),
$server->getCloudFederationFactory(),
$server->getCloudFederationProviderManager(),
- $server->getDatabaseConnection()
+ $server->getDatabaseConnection(),
+ $server->getGroupManager()
);
});
@@ -145,7 +146,9 @@ protected function initFederatedShareProvider() {
\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 f81b826f12cdb..d1560d90ef528 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\ICloudFederationProviderManager;
use OCP\Federation\ICloudIdManager;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\Files\Folder;
@@ -92,6 +93,12 @@ class FederatedShareProvider implements IShareProvider {
/** @var \OCP\GlobalScale\IConfig */
private $gsConfig;
+ /** @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.
*
@@ -106,6 +113,7 @@ class FederatedShareProvider implements IShareProvider {
* @param IUserManager $userManager
* @param ICloudIdManager $cloudIdManager
* @param \OCP\GlobalScale\IConfig $globalScaleConfig
+ * @param ICloudFederationProviderManager $cloudFederationProviderManager
*/
public function __construct(
IDBConnection $connection,
@@ -118,7 +126,8 @@ public function __construct(
IConfig $config,
IUserManager $userManager,
ICloudIdManager $cloudIdManager,
- \OCP\GlobalScale\IConfig $globalScaleConfig
+ \OCP\GlobalScale\IConfig $globalScaleConfig,
+ ICloudFederationProviderManager $cloudFederationProviderManager
) {
$this->dbConnection = $connection;
$this->addressHandler = $addressHandler;
@@ -131,6 +140,7 @@ public function __construct(
$this->userManager = $userManager;
$this->cloudIdManager = $cloudIdManager;
$this->gsConfig = $globalScaleConfig;
+ $this->cloudFederationProviderManager = $cloudFederationProviderManager;
}
/**
@@ -157,12 +167,23 @@ public function create(IShare $share) {
$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']);
@@ -193,7 +214,7 @@ public function create(IShare $share) {
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
@@ -238,7 +259,8 @@ protected function createFederatedShare(IShare $share) {
$share->getSharedBy(),
$share->getShareOwner(),
$share->getPermissions(),
- $token
+ $token,
+ $share->getShareType()
);
$failure = false;
@@ -258,7 +280,8 @@ protected function createFederatedShare(IShare $share) {
$share->getShareOwner(),
$ownerCloudId->getId(),
$share->getSharedBy(),
- $sharedByFederatedId
+ $sharedByFederatedId,
+ $share->getShareType()
);
if ($send === false) {
@@ -342,12 +365,13 @@ protected function getShareFromExternalShareTable(IShare $share) {
* @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))
@@ -491,7 +515,7 @@ public function getChildren(IShare $parent) {
$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();
@@ -640,7 +664,7 @@ public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offs
$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.
@@ -697,7 +721,7 @@ public function getShareById($id, $recipientId = null) {
$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();
@@ -725,10 +749,11 @@ public function getShareById($id, $recipientId = null) {
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 = [];
@@ -761,7 +786,7 @@ public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
}
$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
@@ -792,7 +817,7 @@ public function getShareByToken($token) {
$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();
@@ -967,6 +992,42 @@ public function isIncomingServer2serverShareEnabled() {
return ($result === 'yes');
}
+
+ /**
+ * check if users from other Nextcloud instances are allowed to send federated group shares
+ *
+ * @return bool
+ */
+ public function isOutgoingServer2serverGroupShareEnabled() {
+ if ($this->gsConfig->onlyInternalFederation()) {
+ return false;
+ }
+ $result = $this->config->getAppValue('files_sharing', 'outgoing_server2server_group_share_enabled', 'no');
+ return ($result === 'yes');
+ }
+
+ /**
+ * check if users are allowed to receive federated group shares
+ *
+ * @return bool
+ */
+ public function isIncomingServer2serverGroupShareEnabled() {
+ if ($this->gsConfig->onlyInternalFederation()) {
+ return false;
+ }
+ $result = $this->config->getAppValue('files_sharing', 'incoming_server2server_group_share_enabled', 'no');
+ return ($result === 'yes');
+ }
+
+ /**
+ * check if federated group sharing is supported, therefore the OCM API need to be enabled
+ *
+ * @return bool
+ */
+ public function isFederatedGroupSharingSupported() {
+ return $this->cloudFederationProviderManager->isReady();
+ }
+
/**
* Check if querying sharees on the lookup server is enabled
*
diff --git a/apps/federatedfilesharing/lib/Notifications.php b/apps/federatedfilesharing/lib/Notifications.php
index fdba3e113d68a..70733bc9e2ccb 100644
--- a/apps/federatedfilesharing/lib/Notifications.php
+++ b/apps/federatedfilesharing/lib/Notifications.php
@@ -88,11 +88,12 @@ public function __construct(
* @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 @@ public function sendRemoteShare($token, $shareWith, $name, $remote_id, $owner, $
'sharedBy' => $sharedBy,
'sharedByFederatedId' => $sharedByFederatedId,
'remote' => $local,
+ 'shareType' => $shareType
);
$result = $this->tryHttpPostToShareEndpoint($remote, '', $fields);
@@ -392,7 +394,7 @@ protected function tryOCMEndPoint($remoteDomain, $fields, $action) {
$fields['sharedByFederatedId'],
$fields['sharedBy'],
$fields['token'],
- 'user',
+ $fields['shareType'],
'file'
);
return $this->federationProviderManager->sendShare($share);
@@ -406,6 +408,7 @@ protected function tryOCMEndPoint($remoteDomain, $fields, $action) {
'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/Settings/Admin.php b/apps/federatedfilesharing/lib/Settings/Admin.php
index cbeaa167fff72..aea7957a49f77 100644
--- a/apps/federatedfilesharing/lib/Settings/Admin.php
+++ b/apps/federatedfilesharing/lib/Settings/Admin.php
@@ -58,6 +58,9 @@ public function getForm() {
'internalOnly' => $this->gsConfig->onlyInternalFederation(),
'outgoingServer2serverShareEnabled' => $this->fedShareProvider->isOutgoingServer2serverShareEnabled(),
'incomingServer2serverShareEnabled' => $this->fedShareProvider->isIncomingServer2serverShareEnabled(),
+ 'federatedGroupSharingSupported' => $this->fedShareProvider->isFederatedGroupSharingSupported(),
+ 'outgoingServer2serverGroupShareEnabled' => $this->fedShareProvider->isOutgoingServer2serverGroupShareEnabled(),
+ 'incomingServer2serverGroupShareEnabled' => $this->fedShareProvider->isIncomingServer2serverGroupShareEnabled(),
'lookupServerEnabled' => $this->fedShareProvider->isLookupServerQueriesEnabled(),
'lookupServerUploadEnabled' => $this->fedShareProvider->isLookupServerUploadEnabled(),
];
diff --git a/apps/federatedfilesharing/lib/ocm/CloudFederationProviderFiles.php b/apps/federatedfilesharing/lib/ocm/CloudFederationProviderFiles.php
index 00750f924ef3a..1d922ce60ba65 100644
--- a/apps/federatedfilesharing/lib/ocm/CloudFederationProviderFiles.php
+++ b/apps/federatedfilesharing/lib/ocm/CloudFederationProviderFiles.php
@@ -40,10 +40,12 @@
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 @@ public function __construct(IAppManager $appManager,
IURLGenerator $urlGenerator,
ICloudFederationFactory $cloudFederationFactory,
ICloudFederationProviderManager $cloudFederationProviderManager,
- IDBConnection $connection
+ IDBConnection $connection,
+ IGroupManager $groupManager
) {
$this->appManager = $appManager;
$this->federatedShareProvider = $federatedShareProvider;
@@ -127,6 +134,7 @@ public function __construct(IAppManager $appManager,
$this->cloudFederationFactory = $cloudFederationFactory;
$this->cloudFederationProviderManager = $cloudFederationProviderManager;
$this->connection = $connection;
+ $this->groupManager = $groupManager;
}
@@ -175,6 +183,7 @@ public function shareReceived(ICloudFederationShare $share) {
$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 @@ public function shareReceived(ICloudFederationShare $share) {
}
// 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(),
@@ -213,40 +228,37 @@ public function shareReceived(ICloudFederationShare $share) {
\OC::$server->query(\OCP\OCS\IDiscoveryService::class),
\OC::$server->getCloudFederationProviderManager(),
\OC::$server->getCloudFederationFactory(),
+ \OC::$server->getGroupManager(),
+ \OC::$server->getUserManager(),
$shareWith
);
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();
- $event->setApp('files_sharing')
- ->setType('remote_share')
- ->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_RECEIVED, [$ownerFederatedId, trim($name, '/')])
- ->setAffectedUser($shareWith)
- ->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) {
+ $event = $this->activityManager->generateEvent();
+ $event->setApp('files_sharing')
+ ->setType('remote_share')
+ ->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_RECEIVED, [$ownerFederatedId, trim($name, '/')])
+ ->setAffectedUser($shareWith)
+ ->setObject('remote_share', (int)$shareId, $name);
+ \OC::$server->getActivityManager()->publish($event);
+ $this->notifyAboutNewShare($shareWith, $shareId, $ownerFederatedId, $sharedByFederatedId, $name);
+ } else {
+ $groupMembers = $this->groupManager->get($shareWith)->getUsers();
+ foreach ($groupMembers as $user) {
+ $event = $this->activityManager->generateEvent();
+ $event->setApp('files_sharing')
+ ->setType('remote_share')
+ ->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_RECEIVED, [$ownerFederatedId, trim($name, '/')])
+ ->setAffectedUser($user->getUID())
+ ->setObject('remote_share', (int)$shareId, $name);
+ \OC::$server->getActivityManager()->publish($event);
+ $this->notifyAboutNewShare($user->getUID(), $shareId, $ownerFederatedId, $sharedByFederatedId, $name);
+ }
+ }
return $shareId;
} catch (\Exception $e) {
$this->logger->logException($e, [
@@ -297,6 +309,51 @@ public function notificationReceived($notificationType, $providerId, array $noti
throw new BadRequestException([$notificationType]);
}
+ /**
+ * 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
*
@@ -521,25 +578,32 @@ private function unshare($id, array $notification) {
$qb->execute();
- if ($share['accepted']) {
- $path = trim($mountpoint, '/');
- } else {
- $path = trim($share['name'], '/');
- }
+ // delete all child in case of a group share
+ $qb = $this->connection->getQueryBuilder();
+ $qb->delete('share_external')
+ ->where($qb->expr()->eq('parent', $qb->createNamedParameter((int)$share['id'])));
+ $qb->execute();
+
+ if ((int)$share['share_type'] === Share::SHARE_TYPE_USER) {
+ 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);
- $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);
+ $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 [];
@@ -771,6 +835,6 @@ private function isS2SEnabled($incoming = false) {
* @since 14.0.0
*/
public function getSupportedShareTypes() {
- return ['user'];
+ return ['user', 'group'];
}
}
diff --git a/apps/federatedfilesharing/templates/settings-admin.php b/apps/federatedfilesharing/templates/settings-admin.php
index 187d75f21ac36..1b9b88dc03e07 100644
--- a/apps/federatedfilesharing/templates/settings-admin.php
+++ b/apps/federatedfilesharing/templates/settings-admin.php
@@ -23,7 +23,6 @@
t('Allow users on this server to send shares to other servers'));?>
-
/>
@@ -31,6 +30,22 @@
t('Allow users on this server to receive shares from other servers'));?>
+
+
+ />
+
+
+
+ />
+
+
+
/>
diff --git a/apps/federatedfilesharing/tests/FederatedShareProviderTest.php b/apps/federatedfilesharing/tests/FederatedShareProviderTest.php
index 52266383b367c..98ad8832fa164 100644
--- a/apps/federatedfilesharing/tests/FederatedShareProviderTest.php
+++ b/apps/federatedfilesharing/tests/FederatedShareProviderTest.php
@@ -33,6 +33,7 @@
use OCA\FederatedFileSharing\FederatedShareProvider;
use OCA\FederatedFileSharing\Notifications;
use OCA\FederatedFileSharing\TokenHandler;
+use OCP\Federation\ICloudFederationProviderManager;
use OCP\Federation\ICloudIdManager;
use OCP\Files\File;
use OCP\Files\IRootFolder;
@@ -80,6 +81,8 @@ class FederatedShareProviderTest extends \Test\TestCase {
/** @var ICloudIdManager */
private $cloudIdManager;
+ /** @var \PHPUnit_Framework_MockObject_MockObject|ICloudFederationProviderManager */
+ private $cloudFederationProviderManager;
public function setUp() {
parent::setUp();
@@ -107,6 +110,8 @@ public function setUp() {
$this->userManager->expects($this->any())->method('userExists')->willReturn(true);
+ $this->cloudFederationProviderManager = $this->createMock(ICloudFederationProviderManager::class);
+
$this->provider = new FederatedShareProvider(
$this->connection,
$this->addressHandler,
@@ -118,7 +123,8 @@ public function setUp() {
$this->config,
$this->userManager,
$this->cloudIdManager,
- $this->gsConfig
+ $this->gsConfig,
+ $this->cloudFederationProviderManager
);
$this->shareManager = \OC::$server->getShareManager();
@@ -141,6 +147,7 @@ public function testCreate() {
->setSharedBy('sharedBy')
->setShareOwner('shareOwner')
->setPermissions(19)
+ ->setShareType(\OCP\Share::SHARE_TYPE_REMOTE)
->setNode($node);
$this->tokenHandler->method('generateToken')->willReturn('token');
@@ -212,6 +219,7 @@ public function testCreateCouldNotFindServer() {
->setSharedBy('sharedBy')
->setShareOwner('shareOwner')
->setPermissions(19)
+ ->setShareType(\OCP\Share::SHARE_TYPE_REMOTE)
->setNode($node);
$this->tokenHandler->method('generateToken')->willReturn('token');
@@ -268,6 +276,7 @@ public function testCreateException() {
->setSharedBy('sharedBy')
->setShareOwner('shareOwner')
->setPermissions(19)
+ ->setShareType(\OCP\Share::SHARE_TYPE_REMOTE)
->setNode($node);
$this->tokenHandler->method('generateToken')->willReturn('token');
@@ -367,6 +376,7 @@ public function testCreateAlreadyShared() {
->setSharedBy('sharedBy')
->setShareOwner('shareOwner')
->setPermissions(19)
+ ->setShareType(\OCP\Share::SHARE_TYPE_REMOTE)
->setNode($node);
$this->tokenHandler->method('generateToken')->willReturn('token');
@@ -417,7 +427,8 @@ public function testUpdate($owner, $sharedBy) {
$this->config,
$this->userManager,
$this->cloudIdManager,
- $this->gsConfig
+ $this->gsConfig,
+ $this->cloudFederationProviderManager
]
)->setMethods(['sendPermissionUpdate'])->getMock();
@@ -435,6 +446,7 @@ public function testUpdate($owner, $sharedBy) {
->setSharedBy($sharedBy)
->setShareOwner($owner)
->setPermissions(19)
+ ->setShareType(\OCP\Share::SHARE_TYPE_REMOTE)
->setNode($node);
$this->tokenHandler->method('generateToken')->willReturn('token');
@@ -505,6 +517,7 @@ public function testGetSharedBy() {
->setSharedBy('sharedBy')
->setShareOwner('shareOwner')
->setPermissions(19)
+ ->setShareType(\OCP\Share::SHARE_TYPE_REMOTE)
->setNode($node);
$this->provider->create($share);
@@ -513,6 +526,7 @@ public function testGetSharedBy() {
->setSharedBy('sharedBy2')
->setShareOwner('shareOwner')
->setPermissions(19)
+ ->setShareType(\OCP\Share::SHARE_TYPE_REMOTE)
->setNode($node);
$this->provider->create($share2);
@@ -543,6 +557,7 @@ public function testGetSharedByWithNode() {
->setSharedBy('sharedBy')
->setShareOwner('shareOwner')
->setPermissions(19)
+ ->setShareType(\OCP\Share::SHARE_TYPE_REMOTE)
->setNode($node);
$this->provider->create($share);
@@ -555,6 +570,7 @@ public function testGetSharedByWithNode() {
->setSharedBy('sharedBy')
->setShareOwner('shareOwner')
->setPermissions(19)
+ ->setShareType(\OCP\Share::SHARE_TYPE_REMOTE)
->setNode($node2);
$this->provider->create($share2);
@@ -584,6 +600,7 @@ public function testGetSharedByWithReshares() {
->setSharedBy('shareOwner')
->setShareOwner('shareOwner')
->setPermissions(19)
+ ->setShareType(\OCP\Share::SHARE_TYPE_REMOTE)
->setNode($node);
$this->provider->create($share);
@@ -592,6 +609,7 @@ public function testGetSharedByWithReshares() {
->setSharedBy('sharedBy')
->setShareOwner('shareOwner')
->setPermissions(19)
+ ->setShareType(\OCP\Share::SHARE_TYPE_REMOTE)
->setNode($node);
$this->provider->create($share2);
@@ -628,6 +646,7 @@ public function testGetSharedByWithLimit() {
->setSharedBy('sharedBy')
->setShareOwner('shareOwner')
->setPermissions(19)
+ ->setShareType(\OCP\Share::SHARE_TYPE_REMOTE)
->setNode($node);
$this->provider->create($share);
@@ -636,6 +655,7 @@ public function testGetSharedByWithLimit() {
->setSharedBy('sharedBy')
->setShareOwner('shareOwner')
->setPermissions(19)
+ ->setShareType(\OCP\Share::SHARE_TYPE_REMOTE)
->setNode($node);
$this->provider->create($share2);
@@ -826,6 +846,7 @@ public function testGetSharesInFolder() {
->setSharedBy($u1->getUID())
->setShareOwner($u1->getUID())
->setPermissions(\OCP\Constants::PERMISSION_READ)
+ ->setShareType(\OCP\Share::SHARE_TYPE_REMOTE)
->setNode($file1);
$this->provider->create($share1);
@@ -834,6 +855,7 @@ public function testGetSharesInFolder() {
->setSharedBy($u2->getUID())
->setShareOwner($u1->getUID())
->setPermissions(\OCP\Constants::PERMISSION_READ)
+ ->setShareType(\OCP\Share::SHARE_TYPE_REMOTE)
->setNode($file2);
$this->provider->create($share2);
@@ -880,6 +902,7 @@ public function testGetAccessList() {
->setSharedBy($u1->getUID())
->setShareOwner($u1->getUID())
->setPermissions(\OCP\Constants::PERMISSION_READ)
+ ->setShareType(\OCP\Share::SHARE_TYPE_REMOTE)
->setNode($file1);
$this->provider->create($share1);
@@ -888,6 +911,7 @@ public function testGetAccessList() {
->setSharedBy($u1->getUID())
->setShareOwner($u1->getUID())
->setPermissions(\OCP\Constants::PERMISSION_READ)
+ ->setShareType(\OCP\Share::SHARE_TYPE_REMOTE)
->setNode($file1);
$this->provider->create($share2);
diff --git a/apps/federatedfilesharing/tests/Settings/AdminTest.php b/apps/federatedfilesharing/tests/Settings/AdminTest.php
index debd2bec63a06..f0cf3b77d3890 100644
--- a/apps/federatedfilesharing/tests/Settings/AdminTest.php
+++ b/apps/federatedfilesharing/tests/Settings/AdminTest.php
@@ -72,6 +72,10 @@ public function testGetForm($state) {
->expects($this->once())
->method('isIncomingServer2serverShareEnabled')
->willReturn($state);
+ $this->federatedShareProvider
+ ->expects($this->once())
+ ->method('isIncomingServer2serverShareEnabled')
+ ->willReturn($state);
$this->federatedShareProvider
->expects($this->once())
->method('isLookupServerQueriesEnabled')
@@ -80,6 +84,18 @@ public function testGetForm($state) {
->expects($this->once())
->method('isLookupServerUploadEnabled')
->willReturn($state);
+ $this->federatedShareProvider
+ ->expects($this->once())
+ ->method('isFederatedGroupSharingSupported')
+ ->willReturn($state);
+ $this->federatedShareProvider
+ ->expects($this->once())
+ ->method('isOutgoingServer2serverGroupShareEnabled')
+ ->willReturn($state);
+ $this->federatedShareProvider
+ ->expects($this->once())
+ ->method('isIncomingServer2serverGroupShareEnabled')
+ ->willReturn($state);
$this->gsConfig->expects($this->once())->method('onlyInternalFederation')
->willReturn($state);
@@ -88,7 +104,10 @@ public function testGetForm($state) {
'outgoingServer2serverShareEnabled' => $state,
'incomingServer2serverShareEnabled' => $state,
'lookupServerEnabled' => $state,
- 'lookupServerUploadEnabled' => $state
+ 'lookupServerUploadEnabled' => $state,
+ 'federatedGroupSharingSupported' => $state,
+ 'outgoingServer2serverGroupShareEnabled' => $state,
+ 'incomingServer2serverGroupShareEnabled' => $state,
];
$expected = new TemplateResponse('federatedfilesharing', 'settings-admin', $params, '');
$this->assertEquals($expected, $this->admin->getForm());
diff --git a/apps/files_sharing/appinfo/database.xml b/apps/files_sharing/appinfo/database.xml
index a70be408da4fb..c3cfb9e1c8816 100644
--- a/apps/files_sharing/appinfo/database.xml
+++ b/apps/files_sharing/appinfo/database.xml
@@ -15,6 +15,17 @@
1
4
+
+ parent
+ integer
+ -1
+ 4
+
+
+ share_type
+ integer
+ 4
+
remote
text
diff --git a/apps/files_sharing/appinfo/info.xml b/apps/files_sharing/appinfo/info.xml
index 94a31bea63c87..f2725880df0a8 100644
--- a/apps/files_sharing/appinfo/info.xml
+++ b/apps/files_sharing/appinfo/info.xml
@@ -9,7 +9,7 @@
Turning the feature off removes shared files and folders on the server for all share recipients, and also on the sync clients and mobile apps. More information is available in the Nextcloud Documentation.
- 1.6.1
+ 1.6.2
agpl
Michael Gapczynski
Bjoern Schiessle
diff --git a/apps/files_sharing/lib/AppInfo/Application.php b/apps/files_sharing/lib/AppInfo/Application.php
index e6ab4eb2cf131..a7d4755fbf0aa 100644
--- a/apps/files_sharing/lib/AppInfo/Application.php
+++ b/apps/files_sharing/lib/AppInfo/Application.php
@@ -105,6 +105,8 @@ public function __construct(array $urlParams = array()) {
$server->query(\OCP\OCS\IDiscoveryService::class),
$server->getCloudFederationProviderManager(),
$server->getCloudFederationFactory(),
+ $server->getGroupManager(),
+ $server->getUserManager(),
$uid
);
});
diff --git a/apps/files_sharing/lib/Controller/ShareAPIController.php b/apps/files_sharing/lib/Controller/ShareAPIController.php
index 67ff9eae6d36e..59b763ecf816c 100644
--- a/apps/files_sharing/lib/Controller/ShareAPIController.php
+++ b/apps/files_sharing/lib/Controller/ShareAPIController.php
@@ -48,6 +48,7 @@
use OCP\IURLGenerator;
use OCP\Files\IRootFolder;
use OCP\Lock\LockedException;
+use OCP\Share;
use OCP\Share\IManager;
use OCP\Share\Exceptions\ShareNotFound;
use OCP\Share\Exceptions\GenericShareException;
@@ -181,15 +182,15 @@ protected function formatShare(\OCP\Share\IShare $share, Node $recipientNode = n
$result['expiration'] = $expiration->format('Y-m-d 00:00:00');
}
- if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
+ if ($share->getShareType() === Share::SHARE_TYPE_USER) {
$sharedWith = $this->userManager->get($share->getSharedWith());
$result['share_with'] = $share->getSharedWith();
$result['share_with_displayname'] = $sharedWith !== null ? $sharedWith->getDisplayName() : $share->getSharedWith();
- } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
+ } else if ($share->getShareType() === Share::SHARE_TYPE_GROUP) {
$group = $this->groupManager->get($share->getSharedWith());
$result['share_with'] = $share->getSharedWith();
$result['share_with_displayname'] = $group !== null ? $group->getDisplayName() : $share->getSharedWith();
- } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
+ } else if ($share->getShareType() === Share::SHARE_TYPE_LINK) {
$result['share_with'] = $share->getPassword();
$result['share_with_displayname'] = $share->getPassword();
@@ -197,16 +198,16 @@ protected function formatShare(\OCP\Share\IShare $share, Node $recipientNode = n
$result['token'] = $share->getToken();
$result['url'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $share->getToken()]);
- } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE) {
+ } else if ($share->getShareType() === Share::SHARE_TYPE_REMOTE || $share->getShareType() || Share::SHARE_TYPE_REMOTE_GROUP) {
$result['share_with'] = $share->getSharedWith();
$result['share_with_displayname'] = $this->getDisplayNameFromAddressBook($share->getSharedWith(), 'CLOUD');
$result['token'] = $share->getToken();
- } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
+ } else if ($share->getShareType() === Share::SHARE_TYPE_EMAIL) {
$result['share_with'] = $share->getSharedWith();
$result['password'] = $share->getPassword();
$result['share_with_displayname'] = $this->getDisplayNameFromAddressBook($share->getSharedWith(), 'EMAIL');
$result['token'] = $share->getToken();
- } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_CIRCLE) {
+ } else if ($share->getShareType() === Share::SHARE_TYPE_CIRCLE) {
// getSharedWith() returns either "name (type, owner)" or
// "name (type, owner) [id]", depending on the Circles app version.
$hasCircleId = (substr($share->getSharedWith(), -1) === ']');
@@ -301,7 +302,7 @@ public function deleteShare(string $id): DataResponse {
throw new OCSNotFoundException($this->l->t('Could not delete share'));
}
- if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP &&
+ if ($share->getShareType() === Share::SHARE_TYPE_GROUP &&
$share->getShareOwner() !== $this->currentUser &&
$share->getSharedBy() !== $this->currentUser) {
$this->shareManager->deleteFromSelf($share, $this->currentUser);
@@ -388,14 +389,14 @@ public function createShare(
$permissions &= ~($permissions & ~$path->getPermissions());
}
- if ($shareType === \OCP\Share::SHARE_TYPE_USER) {
+ if ($shareType === Share::SHARE_TYPE_USER) {
// Valid user is required to share
if ($shareWith === null || !$this->userManager->userExists($shareWith)) {
throw new OCSNotFoundException($this->l->t('Please specify a valid user'));
}
$share->setSharedWith($shareWith);
$share->setPermissions($permissions);
- } else if ($shareType === \OCP\Share::SHARE_TYPE_GROUP) {
+ } else if ($shareType === Share::SHARE_TYPE_GROUP) {
if (!$this->shareManager->allowGroupSharing()) {
throw new OCSNotFoundException($this->l->t('Group sharing is disabled by the administrator'));
}
@@ -406,7 +407,7 @@ public function createShare(
}
$share->setSharedWith($shareWith);
$share->setPermissions($permissions);
- } else if ($shareType === \OCP\Share::SHARE_TYPE_LINK) {
+ } else if ($shareType === Share::SHARE_TYPE_LINK) {
//Can we even share links?
if (!$this->shareManager->shareApiAllowLinks()) {
throw new OCSNotFoundException($this->l->t('Public link sharing is disabled by the administrator'));
@@ -416,7 +417,7 @@ public function createShare(
* For now we only allow 1 link share.
* Return the existing link share if this is a duplicate
*/
- $existingShares = $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_LINK, $path, false, 1, 0);
+ $existingShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_LINK, $path, false, 1, 0);
if (!empty($existingShares)) {
return new DataResponse($this->formatShare($existingShares[0]));
}
@@ -457,21 +458,28 @@ public function createShare(
}
}
- } else if ($shareType === \OCP\Share::SHARE_TYPE_REMOTE) {
+ } else if ($shareType === Share::SHARE_TYPE_REMOTE) {
if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) {
throw new OCSForbiddenException($this->l->t('Sharing %s failed because the back end does not allow shares from type %s', [$path->getPath(), $shareType]));
}
$share->setSharedWith($shareWith);
$share->setPermissions($permissions);
- } else if ($shareType === \OCP\Share::SHARE_TYPE_EMAIL) {
+ } else if ($shareType === Share::SHARE_TYPE_REMOTE_GROUP) {
+ if (!$this->shareManager->outgoingServer2ServerGroupSharesAllowed()) {
+ throw new OCSForbiddenException($this->l->t('Sharing %s failed because the back end does not allow shares from type %s', [$path->getPath(), $shareType]));
+ }
+
+ $share->setSharedWith($shareWith);
+ $share->setPermissions($permissions);
+ } else if ($shareType === Share::SHARE_TYPE_EMAIL) {
if ($share->getNodeType() === 'file') {
$share->setPermissions(Constants::PERMISSION_READ);
} else {
$share->setPermissions($permissions);
}
$share->setSharedWith($shareWith);
- } else if ($shareType === \OCP\Share::SHARE_TYPE_CIRCLE) {
+ } else if ($shareType === Share::SHARE_TYPE_CIRCLE) {
if (!\OC::$server->getAppManager()->isEnabledForUser('circles') || !class_exists('\OCA\Circles\ShareByCircleProvider')) {
throw new OCSNotFoundException($this->l->t('You cannot share to a Circle if the app is not enabled'));
}
@@ -512,9 +520,9 @@ public function createShare(
*/
private function getSharedWithMe($node = null, bool $includeTags): DataResponse {
- $userShares = $this->shareManager->getSharedWith($this->currentUser, \OCP\Share::SHARE_TYPE_USER, $node, -1, 0);
- $groupShares = $this->shareManager->getSharedWith($this->currentUser, \OCP\Share::SHARE_TYPE_GROUP, $node, -1, 0);
- $circleShares = $this->shareManager->getSharedWith($this->currentUser, \OCP\Share::SHARE_TYPE_CIRCLE, $node, -1, 0);
+ $userShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_USER, $node, -1, 0);
+ $groupShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_GROUP, $node, -1, 0);
+ $circleShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_CIRCLE, $node, -1, 0);
$shares = array_merge($userShares, $groupShares, $circleShares);
@@ -554,14 +562,14 @@ private function getSharesInDir(Node $folder): DataResponse {
/** @var \OCP\Share\IShare[] $shares */
$shares = [];
foreach ($nodes as $node) {
- $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_USER, $node, false, -1, 0));
- $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_GROUP, $node, false, -1, 0));
- $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_LINK, $node, false, -1, 0));
- if($this->shareManager->shareProviderExists(\OCP\Share::SHARE_TYPE_EMAIL)) {
- $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_EMAIL, $node, false, -1, 0));
+ $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_USER, $node, false, -1, 0));
+ $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_GROUP, $node, false, -1, 0));
+ $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_LINK, $node, false, -1, 0));
+ if($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) {
+ $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_EMAIL, $node, false, -1, 0));
}
if ($this->shareManager->outgoingServer2ServerSharesAllowed()) {
- $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_REMOTE, $node, false, -1, 0));
+ $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_REMOTE, $node, false, -1, 0));
}
}
@@ -635,16 +643,16 @@ public function getShares(
}
// Get all shares
- $userShares = $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_USER, $path, $reshares, -1, 0);
- $groupShares = $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_GROUP, $path, $reshares, -1, 0);
- $linkShares = $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_LINK, $path, $reshares, -1, 0);
- if ($this->shareManager->shareProviderExists(\OCP\Share::SHARE_TYPE_EMAIL)) {
- $mailShares = $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_EMAIL, $path, $reshares, -1, 0);
+ $userShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_USER, $path, $reshares, -1, 0);
+ $groupShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_GROUP, $path, $reshares, -1, 0);
+ $linkShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_LINK, $path, $reshares, -1, 0);
+ if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) {
+ $mailShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_EMAIL, $path, $reshares, -1, 0);
} else {
$mailShares = [];
}
- if ($this->shareManager->shareProviderExists(\OCP\Share::SHARE_TYPE_CIRCLE)) {
- $circleShares = $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_CIRCLE, $path, $reshares, -1, 0);
+ if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_CIRCLE)) {
+ $circleShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_CIRCLE, $path, $reshares, -1, 0);
} else {
$circleShares = [];
}
@@ -652,7 +660,12 @@ public function getShares(
$shares = array_merge($userShares, $groupShares, $linkShares, $mailShares, $circleShares);
if ($this->shareManager->outgoingServer2ServerSharesAllowed()) {
- $federatedShares = $this->shareManager->getSharesBy($this->currentUser, \OCP\Share::SHARE_TYPE_REMOTE, $path, $reshares, -1, 0);
+ $federatedShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_REMOTE, $path, $reshares, -1, 0);
+ $shares = array_merge($shares, $federatedShares);
+ }
+
+ if ($this->shareManager->outgoingServer2ServerGroupSharesAllowed()) {
+ $federatedShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_REMOTE_GROUP, $path, $reshares, -1, 0);
$shares = array_merge($shares, $federatedShares);
}
@@ -711,7 +724,7 @@ public function updateShare(
/*
* expirationdate, password and publicUpload only make sense for link shares
*/
- if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
+ if ($share->getShareType() === Share::SHARE_TYPE_LINK) {
$newPermissions = null;
if ($publicUpload === 'true') {
@@ -783,7 +796,7 @@ public function updateShare(
$share->setPermissions($permissions);
}
- if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
+ if ($share->getShareType() === Share::SHARE_TYPE_EMAIL) {
if ($password === '') {
$share->setPassword(null);
} else if ($password !== null) {
@@ -806,8 +819,8 @@ public function updateShare(
if ($permissions !== null && $share->getShareOwner() !== $this->currentUser) {
/* Check if this is an incomming share */
- $incomingShares = $this->shareManager->getSharedWith($this->currentUser, \OCP\Share::SHARE_TYPE_USER, $share->getNode(), -1, 0);
- $incomingShares = array_merge($incomingShares, $this->shareManager->getSharedWith($this->currentUser, \OCP\Share::SHARE_TYPE_GROUP, $share->getNode(), -1, 0));
+ $incomingShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_USER, $share->getNode(), -1, 0);
+ $incomingShares = array_merge($incomingShares, $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_GROUP, $share->getNode(), -1, 0));
/** @var \OCP\Share\IShare[] $incomingShares */
if (!empty($incomingShares)) {
@@ -846,13 +859,13 @@ protected function canAccessShare(\OCP\Share\IShare $share, bool $checkGroups =
}
// If the share is shared with you (or a group you are a member of)
- if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER &&
+ if ($share->getShareType() === Share::SHARE_TYPE_USER &&
$share->getSharedWith() === $this->currentUser
) {
return true;
}
- if ($checkGroups && $share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
+ if ($checkGroups && $share->getShareType() === Share::SHARE_TYPE_GROUP) {
$sharedWith = $this->groupManager->get($share->getSharedWith());
$user = $this->userManager->get($this->currentUser);
if ($user !== null && $sharedWith !== null && $sharedWith->inGroup($user)) {
@@ -860,7 +873,7 @@ protected function canAccessShare(\OCP\Share\IShare $share, bool $checkGroups =
}
}
- if ($share->getShareType() === \OCP\Share::SHARE_TYPE_CIRCLE) {
+ if ($share->getShareType() === Share::SHARE_TYPE_CIRCLE) {
// TODO: have a sanity check like above?
return true;
}
@@ -915,7 +928,7 @@ private function getShareById(string $id): IShare {
try {
- if ($this->shareManager->shareProviderExists(\OCP\Share::SHARE_TYPE_CIRCLE)) {
+ if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_CIRCLE)) {
$share = $this->shareManager->getShareById('ocCircleShare:' . $id, $this->currentUser);
return $share;
}
@@ -924,7 +937,7 @@ private function getShareById(string $id): IShare {
}
try {
- if ($this->shareManager->shareProviderExists(\OCP\Share::SHARE_TYPE_EMAIL)) {
+ if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) {
$share = $this->shareManager->getShareById('ocMailShare:' . $id, $this->currentUser);
return $share;
}
diff --git a/apps/files_sharing/lib/Controller/ShareesAPIController.php b/apps/files_sharing/lib/Controller/ShareesAPIController.php
index d25f24f6f7262..ee95661d4c608 100644
--- a/apps/files_sharing/lib/Controller/ShareesAPIController.php
+++ b/apps/files_sharing/lib/Controller/ShareesAPIController.php
@@ -67,12 +67,14 @@ class ShareesAPIController extends OCSController {
'users' => [],
'groups' => [],
'remotes' => [],
+ 'remote_groups' => [],
'emails' => [],
'circles' => [],
],
'users' => [],
'groups' => [],
'remotes' => [],
+ 'remote_groups' => [],
'emails' => [],
'lookup' => [],
'circles' => [],
@@ -153,6 +155,10 @@ public function search(string $search = '', string $itemType = null, int $page =
$shareTypes[] = Share::SHARE_TYPE_REMOTE;
}
+ if ($this->isRemoteGroupSharingAllowed($itemType)) {
+ $shareTypes[] = Share::SHARE_TYPE_REMOTE_GROUP;
+ }
+
if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) {
$shareTypes[] = Share::SHARE_TYPE_EMAIL;
}
@@ -216,6 +222,16 @@ protected function isRemoteSharingAllowed(string $itemType): bool {
}
}
+ protected function isRemoteGroupSharingAllowed(string $itemType): bool {
+ try {
+ // FIXME: static foo makes unit testing unnecessarily difficult
+ $backend = \OC\Share\Share::getBackend($itemType);
+ return $backend->isShareTypeAllowed(Share::SHARE_TYPE_REMOTE_GROUP);
+ } catch (\Exception $e) {
+ return false;
+ }
+ }
+
/**
* Generates a bunch of pagination links for the current page
diff --git a/apps/files_sharing/lib/External/Manager.php b/apps/files_sharing/lib/External/Manager.php
index 02783560afe45..6a036b663d9e0 100644
--- a/apps/files_sharing/lib/External/Manager.php
+++ b/apps/files_sharing/lib/External/Manager.php
@@ -39,6 +39,8 @@
use OCP\Files\Storage\IStorageFactory;
use OCP\Http\Client\IClientService;
use OCP\IDBConnection;
+use OCP\IGroupManager;
+use OCP\IUserManager;
use OCP\Notification\IManager;
use OCP\OCS\IDiscoveryService;
use OCP\Share;
@@ -87,6 +89,12 @@ class Manager {
/** @var ICloudFederationFactory */
private $cloudFederationFactory;
+ /** @var IGroupManager */
+ private $groupManager;
+
+ /** @var IUserManager */
+ private $userManager;
+
/**
* @param IDBConnection $connection
* @param \OC\Files\Mount\Manager $mountManager
@@ -96,6 +104,8 @@ class Manager {
* @param IDiscoveryService $discoveryService
* @param ICloudFederationProviderManager $cloudFederationProviderManager
* @param ICloudFederationFactory $cloudFederationFactory
+ * @param IGroupManager $groupManager
+ * @param IUserManager $userManager
* @param string $uid
*/
public function __construct(IDBConnection $connection,
@@ -106,6 +116,8 @@ public function __construct(IDBConnection $connection,
IDiscoveryService $discoveryService,
ICloudFederationProviderManager $cloudFederationProviderManager,
ICloudFederationFactory $cloudFederationFactory,
+ IGroupManager $groupManager,
+ IUserManager $userManager,
$uid) {
$this->connection = $connection;
$this->mountManager = $mountManager;
@@ -116,6 +128,8 @@ public function __construct(IDBConnection $connection,
$this->discoveryService = $discoveryService;
$this->cloudFederationProviderManager = $cloudFederationProviderManager;
$this->cloudFederationFactory = $cloudFederationFactory;
+ $this->groupManager = $groupManager;
+ $this->userManager = $userManager;
}
/**
@@ -126,12 +140,15 @@ public function __construct(IDBConnection $connection,
* @param string $password
* @param string $name
* @param string $owner
+ * @param int $shareType
* @param boolean $accepted
* @param string $user
* @param int $remoteId
+ * @param int $parent
* @return Mount|null
+ * @throws \Doctrine\DBAL\DBALException
*/
- public function addShare($remote, $token, $password, $name, $owner, $accepted=false, $user = null, $remoteId = -1) {
+ public function addShare($remote, $token, $password, $name, $owner, $shareType, $accepted=false, $user = null, $remoteId = -1, $parent = -1) {
$user = $user ? $user : $this->uid;
$accepted = $accepted ? 1 : 0;
@@ -156,6 +173,7 @@ public function addShare($remote, $token, $password, $name, $owner, $accepted=fa
'mountpoint_hash' => $hash,
'accepted' => $accepted,
'remote_id' => $remoteId,
+ 'share_type' => $shareType,
];
$i = 1;
@@ -172,12 +190,7 @@ public function addShare($remote, $token, $password, $name, $owner, $accepted=fa
$mountPoint = Filesystem::normalizePath('/' . $mountPoint);
$hash = md5($mountPoint);
- $query = $this->connection->prepare('
- INSERT INTO `*PREFIX*share_external`
- (`remote`, `share_token`, `password`, `name`, `owner`, `user`, `mountpoint`, `mountpoint_hash`, `accepted`, `remote_id`)
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
- ');
- $query->execute(array($remote, $token, $password, $name, $owner, $user, $mountPoint, $hash, $accepted, $remoteId));
+ $this->writeShareToDb($remote, $token, $password, $name, $owner, $user, $mountPoint, $hash, $accepted, $remoteId, $parent, $shareType);
$options = array(
'remote' => $remote,
@@ -189,6 +202,32 @@ public function addShare($remote, $token, $password, $name, $owner, $accepted=fa
return $this->mountShare($options);
}
+ /**
+ * write remote share to the database
+ *
+ * @param $remote
+ * @param $token
+ * @param $password
+ * @param $name
+ * @param $owner
+ * @param $user
+ * @param $mountPoint
+ * @param $hash
+ * @param $accepted
+ * @param $remoteId
+ * @param $parent
+ * @param $shareType
+ * @return bool
+ */
+ private function writeShareToDb($remote, $token, $password, $name, $owner, $user, $mountPoint, $hash, $accepted, $remoteId, $parent, $shareType) {
+ $query = $this->connection->prepare('
+ INSERT INTO `*PREFIX*share_external`
+ (`remote`, `share_token`, `password`, `name`, `owner`, `user`, `mountpoint`, `mountpoint_hash`, `accepted`, `remote_id`, `parent`, `share_type`)
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+ ');
+ return $query->execute(array($remote, $token, $password, $name, $owner, $user, $mountPoint, $hash, $accepted, $remoteId, $parent, $shareType));
+ }
+
/**
* get share
*
@@ -197,12 +236,27 @@ public function addShare($remote, $token, $password, $name, $owner, $accepted=fa
*/
public function getShare($id) {
$getShare = $this->connection->prepare('
- SELECT `id`, `remote`, `remote_id`, `share_token`, `name`, `owner`, `user`, `mountpoint`, `accepted`
+ SELECT `id`, `remote`, `remote_id`, `share_token`, `name`, `owner`, `user`, `mountpoint`, `accepted`, `parent`, `share_type`, `password`, `mountpoint_hash`
FROM `*PREFIX*share_external`
- WHERE `id` = ? AND `user` = ?');
- $result = $getShare->execute(array($id, $this->uid));
+ WHERE `id` = ?');
+ $result = $getShare->execute(array($id));
+
+ $share = $result ? $getShare->fetch() : [];
+
+ $validShare = is_array($share) && isset($share['share_type']) && isset($share['user']);
+
+ // check if the user is allowed to access it
+ if ($validShare && (int)$share['share_type'] === Share::SHARE_TYPE_USER && $share['user'] === $this->uid) {
+ return $share;
+ } else if ($validShare && (int)$share['share_type'] === Share::SHARE_TYPE_GROUP) {
+ $user = $this->userManager->get($this->uid);
+ if ($this->groupManager->get($share['user'])->inGroup($user)) {
+ return $share;
+ }
+ }
+
+ return false;
- return $result ? $getShare->fetch() : false;
}
/**
@@ -222,15 +276,30 @@ public function acceptShare($id) {
$mountPoint = Files::buildNotExistingFileName($shareFolder, $share['name']);
$mountPoint = Filesystem::normalizePath($mountPoint);
$hash = md5($mountPoint);
+ $userShareAccepted = false;
- $acceptShare = $this->connection->prepare('
+ if((int)$share['share_type'] === Share::SHARE_TYPE_USER) {
+ $acceptShare = $this->connection->prepare('
UPDATE `*PREFIX*share_external`
SET `accepted` = ?,
`mountpoint` = ?,
`mountpoint_hash` = ?
WHERE `id` = ? AND `user` = ?');
- $updated = $acceptShare->execute(array(1, $mountPoint, $hash, $id, $this->uid));
- if ($updated === true) {
+ $userShareAccepted = $acceptShare->execute(array(1, $mountPoint, $hash, $id, $this->uid));
+ } else {
+ $result = $this->writeShareToDb(
+ $share['remote'],
+ $share['share_token'],
+ $share['password'],
+ $share['name'],
+ $share['owner'],
+ $this->uid,
+ $mountPoint, $hash, 1,
+ $share['remote_id'],
+ $id,
+ $share['share_type']);
+ }
+ if ($userShareAccepted === true) {
$this->sendFeedbackToRemote($share['remote'], $share['share_token'], $share['remote_id'], 'accept');
\OC_Hook::emit(Share::class, 'federated_share_added', ['server' => $share['remote']]);
$result = true;
@@ -252,18 +321,34 @@ public function acceptShare($id) {
public function declineShare($id) {
$share = $this->getShare($id);
+ $result = false;
- if ($share) {
+ if ($share && (int)$share['share_type'] === Share::SHARE_TYPE_USER) {
$removeShare = $this->connection->prepare('
DELETE FROM `*PREFIX*share_external` WHERE `id` = ? AND `user` = ?');
$removeShare->execute(array($id, $this->uid));
$this->sendFeedbackToRemote($share['remote'], $share['share_token'], $share['remote_id'], 'decline');
$this->processNotification($id);
- return true;
+ $result = true;
+ } else if ($share && (int)$share['share_type'] === Share::SHARE_TYPE_GROUP) {
+ $result = $this->writeShareToDb(
+ $share['remote'],
+ $share['share_token'],
+ $share['password'],
+ $share['name'],
+ $share['owner'],
+ $this->uid,
+ $share['mountpoint'],
+ $share['mountpoint_hash'],
+ 0,
+ $share['remote_id'],
+ $id,
+ $share['share_type']);
+ $this->processNotification($id);
}
- return false;
+ return $result;
}
/**
@@ -297,7 +382,7 @@ private function sendFeedbackToRemote($remote, $token, $remoteId, $feedback) {
$federationEndpoints = $this->discoveryService->discover($remote, 'FEDERATED_SHARING');
$endpoint = isset($federationEndpoints['share']) ? $federationEndpoints['share'] : '/ocs/v2.php/cloud/shares';
- $url = rtrim($remote, '/') . $endpoint . '/' . $remoteId . '/' . $feedback . '?format=' . \OCP\Share::RESPONSE_FORMAT;
+ $url = rtrim($remote, '/') . $endpoint . '/' . $remoteId . '/' . $feedback . '?format=' . Share::RESPONSE_FORMAT;
$fields = array('token' => $token);
$client = $this->clientService->newClient();
@@ -430,28 +515,33 @@ public function removeShare($mountPoint) {
$hash = md5($mountPoint);
$getShare = $this->connection->prepare('
- SELECT `remote`, `share_token`, `remote_id`
+ SELECT `remote`, `share_token`, `remote_id`, `share_type`, `id`
FROM `*PREFIX*share_external`
WHERE `mountpoint_hash` = ? AND `user` = ?');
$result = $getShare->execute(array($hash, $this->uid));
- if ($result) {
+ $share = $getShare->fetch();
+ $getShare->closeCursor();
+ if ($result && (int)$share['share_type'] === Share::SHARE_TYPE_USER) {
try {
- $share = $getShare->fetch();
$this->sendFeedbackToRemote($share['remote'], $share['share_token'], $share['remote_id'], 'decline');
} catch (\Exception $e) {
// if we fail to notify the remote (probably cause the remote is down)
// we still want the share to be gone to prevent undeletable remotes
}
- }
- $getShare->closeCursor();
- $query = $this->connection->prepare('
+ $query = $this->connection->prepare('
DELETE FROM `*PREFIX*share_external`
- WHERE `mountpoint_hash` = ?
- AND `user` = ?
- ');
- $result = (bool)$query->execute(array($hash, $this->uid));
+ WHERE `id` = ?
+ ');
+ $result = (bool)$query->execute(array((int)$share['id']));
+ } else if ($result && (int)$share['share_type'] === Share::SHARE_TYPE_GROUP) {
+ $query = $this->connection->prepare('
+ UPDATE `*PREFIX*share_external`
+ SET `accepted` = ?
+ WHERE `id` = ?');
+ $result = (bool)$query->execute(array(0, (int)$share['id']));
+ }
if($result) {
$this->removeReShares($id);
@@ -537,10 +627,17 @@ public function getAcceptedShares() {
* @return array list of open server-to-server shares
*/
private function getShares($accepted) {
+ $user = $this->userManager->get($this->uid);
+ $groups = $this->groupManager->getUserGroups($user);
+ $userGroups = [];
+ foreach ($groups as $group) {
+ $userGroups[] = $group->getGID();
+ }
+
$query = 'SELECT `id`, `remote`, `remote_id`, `share_token`, `name`, `owner`, `user`, `mountpoint`, `accepted`
FROM `*PREFIX*share_external`
- WHERE `user` = ?';
- $parameters = [$this->uid];
+ WHERE (`user` = ? OR `user` IN (?))';
+ $parameters = [$this->uid, implode(',',$userGroups)];
if (!is_null($accepted)) {
$query .= ' AND `accepted` = ?';
$parameters[] = (int) $accepted;
diff --git a/apps/files_sharing/lib/Hooks.php b/apps/files_sharing/lib/Hooks.php
index cd66fd7702ebb..99e876eaaf02f 100644
--- a/apps/files_sharing/lib/Hooks.php
+++ b/apps/files_sharing/lib/Hooks.php
@@ -42,6 +42,8 @@ public static function deleteUser($params) {
\OC::$server->query(\OCP\OCS\IDiscoveryService::class),
\OC::$server->getCloudFederationProviderManager(),
\OC::$server->getCloudFederationFactory(),
+ \OC::$server->getGroupManager(),
+ \OC::$server->getUserManager(),
$params['uid']);
$manager->removeUserShares($params['uid']);
diff --git a/apps/files_sharing/lib/ShareBackend/File.php b/apps/files_sharing/lib/ShareBackend/File.php
index bb28c1a33ac25..bd32741e67e65 100644
--- a/apps/files_sharing/lib/ShareBackend/File.php
+++ b/apps/files_sharing/lib/ShareBackend/File.php
@@ -195,6 +195,10 @@ public function isShareTypeAllowed($shareType) {
return $this->federatedShareProvider->isOutgoingServer2serverShareEnabled();
}
+ if ($shareType === \OCP\Share::SHARE_TYPE_REMOTE_GROUP) {
+ return $this->federatedShareProvider->isOutgoingServer2serverGroupShareEnabled();
+ }
+
return true;
}
diff --git a/apps/files_sharing/tests/Controller/ShareesAPIControllerTest.php b/apps/files_sharing/tests/Controller/ShareesAPIControllerTest.php
index 98ae953a31810..d8c706da03c07 100644
--- a/apps/files_sharing/tests/Controller/ShareesAPIControllerTest.php
+++ b/apps/files_sharing/tests/Controller/ShareesAPIControllerTest.php
@@ -85,120 +85,125 @@ protected function setUp() {
public function dataSearch() {
$noRemote = [Share::SHARE_TYPE_USER, Share::SHARE_TYPE_GROUP, Share::SHARE_TYPE_EMAIL];
- $allTypes = [Share::SHARE_TYPE_USER, Share::SHARE_TYPE_GROUP, Share::SHARE_TYPE_REMOTE, Share::SHARE_TYPE_EMAIL];
+ $allTypes = [Share::SHARE_TYPE_USER, Share::SHARE_TYPE_GROUP, Share::SHARE_TYPE_REMOTE, Share::SHARE_TYPE_REMOTE_GROUP, Share::SHARE_TYPE_EMAIL];
return [
- [[], '', 'yes', true, true, $noRemote, false, true, true],
+ [[], '', 'yes', true, true, true, $noRemote, false, true, true],
// Test itemType
[[
'search' => '',
- ], '', 'yes', true, true, $noRemote, false, true, true],
+ ], '', 'yes', true, true, true, $noRemote, false, true, true],
[[
'search' => 'foobar',
- ], '', 'yes', true, true, $noRemote, false, true, true],
+ ], '', 'yes', true, true, true, $noRemote, false, true, true],
[[
'search' => 0,
- ], '', 'yes', true, true, $noRemote, false, true, true],
+ ], '', 'yes', true, true, true, $noRemote, false, true, true],
// Test itemType
[[
'itemType' => '',
- ], '', 'yes', true, true, $noRemote, false, true, true],
+ ], '', 'yes', true, true, true, $noRemote, false, true, true],
[[
'itemType' => 'folder',
- ], '', 'yes', true, true, $allTypes, false, true, true],
+ ], '', 'yes', true, true, true, $allTypes, false, true, true],
[[
'itemType' => 0,
- ], '', 'yes', true, true, $noRemote, false, true, true],
-
+ ], '', 'yes', true, true , true, $noRemote, false, true, true],
// Test shareType
[[
'itemType' => 'call',
- ], '', 'yes', true, true, $noRemote, false, true, true],
+ ], '', 'yes', true, true, true, $noRemote, false, true, true],
[[
'itemType' => 'folder',
- ], '', 'yes', true, true, $allTypes, false, true, true],
+ ], '', 'yes', true, true, true, $allTypes, false, true, true],
[[
'itemType' => 'folder',
'shareType' => 0,
- ], '', 'yes', true, false, [0], false, true, true],
+ ], '', 'yes', true, true, false, [0], false, true, true],
[[
'itemType' => 'folder',
'shareType' => '0',
- ], '', 'yes', true, false, [0], false, true, true],
+ ], '', 'yes', true, true, false, [0], false, true, true],
[[
'itemType' => 'folder',
'shareType' => 1,
- ], '', 'yes', true, false, [1], false, true, true],
+ ], '', 'yes', true, true, false, [1], false, true, true],
[[
'itemType' => 'folder',
'shareType' => 12,
- ], '', 'yes', true, false, [], false, true, true],
+ ], '', 'yes', true, true, false, [], false, true, true],
[[
'itemType' => 'folder',
'shareType' => 'foobar',
- ], '', 'yes', true, true, $allTypes, false, true, true],
+ ], '', 'yes', true, true, true, $allTypes, false, true, true],
+
[[
'itemType' => 'folder',
'shareType' => [0, 1, 2],
- ], '', 'yes', false, false, [0, 1], false, true, true],
+ ], '', 'yes', false, false, false, [0, 1], false, true, true],
[[
'itemType' => 'folder',
'shareType' => [0, 1],
- ], '', 'yes', false, false, [0, 1], false, true, true],
+ ], '', 'yes', false, false, false, [0, 1], false, true, true],
+ [[
+ 'itemType' => 'folder',
+ 'shareType' => $allTypes,
+ ], '', 'yes', true, true, true, $allTypes, false, true, true],
[[
'itemType' => 'folder',
'shareType' => $allTypes,
- ], '', 'yes', true, true, $allTypes, false, true, true],
+ ], '', 'yes', false, false, false, [0, 1], false, true, true],
[[
'itemType' => 'folder',
'shareType' => $allTypes,
- ], '', 'yes', false, false, [0, 1], false, true, true],
+ ], '', 'yes', true, false, false, [0, 6], false, true, false],
[[
'itemType' => 'folder',
'shareType' => $allTypes,
- ], '', 'yes', true, false, [0, 6], false, true, false],
+ ], '', 'yes', false, false, true, [0, 4], false, true, false],
[[
'itemType' => 'folder',
'shareType' => $allTypes,
- ], '', 'yes', false, true, [0, 4], false, true, false],
+ ], '', 'yes', true, true, false, [0, 6, 9], false, true, false],
// Test pagination
[[
'itemType' => 'folder',
'page' => 1,
- ], '', 'yes', true, true, $allTypes, false, true, true],
+ ], '', 'yes', true, true, true, $allTypes, false, true, true],
[[
'itemType' => 'folder',
'page' => 10,
- ], '', 'yes', true, true, $allTypes, false, true, true],
+ ], '', 'yes', true, true, true, $allTypes, false, true, true],
// Test perPage
[[
'itemType' => 'folder',
'perPage' => 1,
- ], '', 'yes', true, true, $allTypes, false, true, true],
+ ], '', 'yes', true, true, true, $allTypes, false, true, true],
[[
'itemType' => 'folder',
'perPage' => 10,
- ], '', 'yes', true, true, $allTypes, false, true, true],
+ ], '', 'yes', true, true, true, $allTypes, false, true, true],
// Test $shareWithGroupOnly setting
[[
'itemType' => 'folder',
- ], 'no', 'yes', true, true, $allTypes, false, true, true],
+ ], 'no', 'yes', true, true, true, $allTypes, false, true, true],
[[
'itemType' => 'folder',
- ], 'yes', 'yes', true, true, $allTypes, true, true, true],
+ ], 'yes', 'yes', true, true, true, $allTypes, true, true, true],
// Test $shareeEnumeration setting
[[
'itemType' => 'folder',
- ], 'no', 'yes', true, true, $allTypes, false, true, true],
+ ], 'no', 'yes', true, true, true, $allTypes, false, true, true],
[[
'itemType' => 'folder',
- ], 'no', 'no', true, true, $allTypes, false, false, true],
+ ], 'no', 'no', true, true, true, $allTypes, false, false, true],
+
];
}
@@ -209,13 +214,15 @@ public function dataSearch() {
* @param string $apiSetting
* @param string $enumSetting
* @param bool $remoteSharingEnabled
+ * @param bool $isRemoteGroupSharingEnabled
* @param bool $emailSharingEnabled
* @param array $shareTypes
* @param bool $shareWithGroupOnly
* @param bool $shareeEnumeration
* @param bool $allowGroupSharing
+ * @throws OCSBadRequestException
*/
- public function testSearch($getData, $apiSetting, $enumSetting, $remoteSharingEnabled, $emailSharingEnabled, $shareTypes, $shareWithGroupOnly, $shareeEnumeration, $allowGroupSharing) {
+ public function testSearch($getData, $apiSetting, $enumSetting, $remoteSharingEnabled, $isRemoteGroupSharingEnabled, $emailSharingEnabled, $shareTypes, $shareWithGroupOnly, $shareeEnumeration, $allowGroupSharing) {
$search = isset($getData['search']) ? $getData['search'] : '';
$itemType = isset($getData['itemType']) ? $getData['itemType'] : 'irrelevant';
$page = isset($getData['page']) ? $getData['page'] : 1;
@@ -251,7 +258,7 @@ public function testSearch($getData, $apiSetting, $enumSetting, $remoteSharingEn
$this->shareManager,
$this->collaboratorSearch
])
- ->setMethods(['isRemoteSharingAllowed', 'shareProviderExists'])
+ ->setMethods(['isRemoteSharingAllowed', 'shareProviderExists', 'isRemoteGroupSharingAllowed'])
->getMock();
$this->collaboratorSearch->expects($this->once())
@@ -264,6 +271,13 @@ public function testSearch($getData, $apiSetting, $enumSetting, $remoteSharingEn
->with($itemType)
->willReturn($remoteSharingEnabled);
+
+ $sharees->expects($this->any())
+ ->method('isRemoteGroupSharingAllowed')
+ ->with($itemType)
+ ->willReturn($isRemoteGroupSharingEnabled);
+
+
$this->shareManager->expects($this->any())
->method('shareProviderExists')
->with(\OCP\Share::SHARE_TYPE_EMAIL)
diff --git a/apps/files_sharing/tests/External/ManagerTest.php b/apps/files_sharing/tests/External/ManagerTest.php
index 2cc88160a8cc7..93c17ca10cf9a 100644
--- a/apps/files_sharing/tests/External/ManagerTest.php
+++ b/apps/files_sharing/tests/External/ManagerTest.php
@@ -35,6 +35,8 @@
use OCP\Federation\ICloudFederationFactory;
use OCP\Federation\ICloudFederationProviderManager;
use OCP\Http\Client\IClientService;
+use OCP\IGroupManager;
+use OCP\IUserManager;
use Test\Traits\UserTrait;
/**
@@ -62,6 +64,12 @@ class ManagerTest extends TestCase {
/** @var ICloudFederationFactory|\PHPUnit_Framework_MockObject_MockObject */
private $cloudFederationFactory;
+ /** @var \PHPUnit_Framework_MockObject_MockObject|IGroupManager */
+ private $groupManager;
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject|IUserManager */
+ private $userManager;
+
private $uid;
/**
@@ -81,6 +89,8 @@ protected function setUp() {
->disableOriginalConstructor()->getMock();
$this->cloudFederationProviderManager = $this->createMock(ICloudFederationProviderManager::class);
$this->cloudFederationFactory = $this->createMock(ICloudFederationFactory::class);
+ $this->groupManager = $this->createMock(IGroupManager::class);
+ $this->userManager = $this->createMock(IUserManager::class);
$this->manager = $this->getMockBuilder(Manager::class)
->setConstructorArgs(
@@ -93,6 +103,8 @@ protected function setUp() {
\OC::$server->query(\OCP\OCS\IDiscoveryService::class),
$this->cloudFederationProviderManager,
$this->cloudFederationFactory,
+ $this->groupManager,
+ $this->userManager,
$this->uid
]
)->setMethods(['tryOCMEndPoint'])->getMock();
@@ -117,6 +129,7 @@ public function testAddShare() {
'password' => '',
'name' => '/SharedFolder',
'owner' => 'foobar',
+ 'shareType' => \OCP\Share::SHARE_TYPE_USER,
'accepted' => false,
'user' => $this->uid,
];
@@ -125,6 +138,9 @@ public function testAddShare() {
$shareData3 = $shareData1;
$shareData3['token'] = 'token3';
+ $this->userManager->expects($this->any())->method('get')->willReturn($this->user);
+ $this->groupManager->expects($this->any())->method(('getUserGroups'))->willReturn([]);
+
$this->manager->expects($this->at(0))->method('tryOCMEndPoint')->with('http://localhost', 'token1', -1, 'accept')->willReturn(false);
$this->manager->expects($this->at(1))->method('tryOCMEndPoint')->with('http://localhost', 'token3', -1, 'decline')->willReturn(false);
diff --git a/build/integration/features/bootstrap/FederationContext.php b/build/integration/features/bootstrap/FederationContext.php
index f3eb004fb848a..12bf9c0fe631e 100644
--- a/build/integration/features/bootstrap/FederationContext.php
+++ b/build/integration/features/bootstrap/FederationContext.php
@@ -35,6 +35,7 @@
class FederationContext implements Context, SnippetAcceptingContext {
use WebDav;
+ use AppConfiguration;
/**
* @Given /^User "([^"]*)" from server "(LOCAL|REMOTE)" shares "([^"]*)" with user "([^"]*)" from server "(LOCAL|REMOTE)"$/
@@ -56,6 +57,27 @@ public function federateSharing($sharerUser, $sharerServer, $sharerPath, $sharee
$this->usingServer($previous);
}
+
+ /**
+ * @Given /^User "([^"]*)" from server "(LOCAL|REMOTE)" shares "([^"]*)" with group "([^"]*)" from server "(LOCAL|REMOTE)"$/
+ *
+ * @param string $sharerUser
+ * @param string $sharerServer "LOCAL" or "REMOTE"
+ * @param string $sharerPath
+ * @param string $shareeUser
+ * @param string $shareeServer "LOCAL" or "REMOTE"
+ */
+ public function federateGroupSharing($sharerUser, $sharerServer, $sharerPath, $shareeGroup, $shareeServer){
+ if ($shareeServer == "REMOTE"){
+ $shareWith = "$shareeGroup@" . substr($this->remoteBaseUrl, 0, -4);
+ } else {
+ $shareWith = "$shareeGroup@" . substr($this->localBaseUrl, 0, -4);
+ }
+ $previous = $this->usingServer($sharerServer);
+ $this->createShare($sharerUser, $sharerPath, 9, $shareWith, null, null, null);
+ $this->usingServer($previous);
+ }
+
/**
* @When /^User "([^"]*)" from server "(LOCAL|REMOTE)" accepts last pending share$/
* @param string $user
@@ -73,4 +95,9 @@ public function acceptLastPendingShare($user, $server){
$this->theOCSStatusCodeShouldBe('100');
$this->usingServer($previous);
}
+
+ protected function resetAppConfigs() {
+ $this->modifyServerConfig('files_sharing', 'incoming_server2server_group_share_enabled', 'no');
+ $this->modifyServerConfig('files_sharing', 'outgoing_server2server_group_share_enabled', 'no');
+ }
}
diff --git a/build/integration/federation_features/federated.feature b/build/integration/federation_features/federated.feature
index c7b20cf86a74b..87515e2ccab5f 100644
--- a/build/integration/federation_features/federated.feature
+++ b/build/integration/federation_features/federated.feature
@@ -28,6 +28,40 @@ Feature: federated
| share_with | user1@REMOTE |
| share_with_displayname | user1@REMOTE |
+ Scenario: Federated group share a file with another server
+ Given Using server "REMOTE"
+ And parameter "incoming_server2server_group_share_enabled" of app "files_sharing" is set to "yes"
+ And user "gs-user1" exists
+ And user "gs-user2" exists
+ And group "group1" exists
+ And As an "admin"
+ And Add user "gs-user1" to the group "group1"
+ And Add user "gs-user2" to the group "group1"
+ And Using server "LOCAL"
+ And parameter "outgoing_server2server_group_share_enabled" of app "files_sharing" is set to "yes"
+ And user "gs-user0" exists
+ When User "gs-user0" from server "LOCAL" shares "/textfile0.txt" with group "group1" from server "REMOTE"
+ Then the OCS status code should be "100"
+ And the HTTP status code should be "200"
+ And Share fields of last share match with
+ | id | A_NUMBER |
+ | item_type | file |
+ | item_source | A_NUMBER |
+ | share_type | 9 |
+ | file_source | A_NUMBER |
+ | path | /textfile0.txt |
+ | permissions | 19 |
+ | stime | A_NUMBER |
+ | storage | A_NUMBER |
+ | mail_send | 0 |
+ | uid_owner | gs-user0 |
+ | storage_id | home::gs-user0 |
+ | file_parent | A_NUMBER |
+ | displayname_owner | gs-user0 |
+ | share_with | group1@REMOTE |
+ | share_with_displayname | group1@REMOTE |
+
+
Scenario: Federate share a file with local server
Given Using server "LOCAL"
And user "user0" exists
@@ -76,6 +110,49 @@ Feature: federated
| mountpoint | {{TemporaryMountPointName#/textfile0.txt}} |
| accepted | 0 |
+ Scenario: Remote sharee can see the pending group share
+ Given Using server "REMOTE"
+ And parameter "incoming_server2server_group_share_enabled" of app "files_sharing" is set to "yes"
+ And user "gs-user1" exists
+ And user "gs-user2" exists
+ And group "group1" exists
+ And As an "admin"
+ And Add user "gs-user1" to the group "group1"
+ And Add user "gs-user2" to the group "group1"
+ And Using server "LOCAL"
+ And parameter "outgoing_server2server_group_share_enabled" of app "files_sharing" is set to "yes"
+ And user "gs-user0" exists
+ When User "gs-user0" from server "LOCAL" shares "/textfile0.txt" with group "group1" from server "REMOTE"
+ And Using server "REMOTE"
+ And As an "gs-user1"
+ When sending "GET" to "/apps/files_sharing/api/v1/remote_shares/pending"
+ Then the OCS status code should be "100"
+ And the HTTP status code should be "200"
+ And Share fields of last share match with
+ | id | A_NUMBER |
+ | remote | LOCAL |
+ | remote_id | A_NUMBER |
+ | share_token | A_TOKEN |
+ | name | /textfile0.txt |
+ | owner | gs-user0 |
+ | user | group1 |
+ | mountpoint | {{TemporaryMountPointName#/textfile0.txt}} |
+ | accepted | 0 |
+ And As an "gs-user2"
+ When sending "GET" to "/apps/files_sharing/api/v1/remote_shares/pending"
+ Then the OCS status code should be "100"
+ And the HTTP status code should be "200"
+ And Share fields of last share match with
+ | id | A_NUMBER |
+ | remote | LOCAL |
+ | remote_id | A_NUMBER |
+ | share_token | A_TOKEN |
+ | name | /textfile0.txt |
+ | owner | gs-user0 |
+ | user | group1 |
+ | mountpoint | {{TemporaryMountPointName#/textfile0.txt}} |
+ | accepted | 0 |
+
Scenario: accept a pending remote share
Given Using server "REMOTE"
And user "user1" exists
@@ -86,6 +163,23 @@ Feature: federated
Then the OCS status code should be "100"
And the HTTP status code should be "200"
+ Scenario: accept a pending remote group share
+ Given Using server "REMOTE"
+ And parameter "incoming_server2server_group_share_enabled" of app "files_sharing" is set to "yes"
+ And user "gs-user1" exists
+ And user "gs-user2" exists
+ And group "group1" exists
+ And As an "admin"
+ And Add user "gs-user1" to the group "group1"
+ And Add user "gs-user2" to the group "group1"
+ And Using server "LOCAL"
+ And parameter "outgoing_server2server_group_share_enabled" of app "files_sharing" is set to "yes"
+ And user "gs-user0" exists
+ When User "gs-user0" from server "LOCAL" shares "/textfile0.txt" with group "group1" from server "REMOTE"
+ When User "gs-user1" from server "REMOTE" accepts last pending share
+ Then the OCS status code should be "100"
+ And the HTTP status code should be "200"
+
Scenario: Reshare a federated shared file
Given Using server "REMOTE"
And user "user1" exists
diff --git a/core/js/share.js b/core/js/share.js
index f301de254156b..e4d9364b2d198 100644
--- a/core/js/share.js
+++ b/core/js/share.js
@@ -11,6 +11,7 @@ OC.Share = _.extend(OC.Share || {}, {
SHARE_TYPE_REMOTE:6,
SHARE_TYPE_CIRCLE:7,
SHARE_TYPE_GUEST:8,
+ SHARE_TYPE_REMOTE_GROUP:9,
/**
* Regular expression for splitting parts of remote share owners:
diff --git a/core/js/sharedialogshareelistview.js b/core/js/sharedialogshareelistview.js
index 1e873a7208eee..0ff4c36b712d8 100644
--- a/core/js/sharedialogshareelistview.js
+++ b/core/js/sharedialogshareelistview.js
@@ -198,6 +198,8 @@
shareWithDisplayName = shareWithDisplayName + " (" + t('core', 'group') + ')';
} else if (shareType === OC.Share.SHARE_TYPE_REMOTE) {
shareWithDisplayName = shareWithDisplayName + " (" + t('core', 'remote') + ')';
+ } else if (shareType === OC.Share.SHARE_TYPE_REMOTE_GROUP) {
+ shareWithDisplayName = shareWithDisplayName + " (" + t('core', 'remote group') + ')';
} else if (shareType === OC.Share.SHARE_TYPE_EMAIL) {
shareWithDisplayName = shareWithDisplayName + " (" + t('core', 'email') + ')';
} else if (shareType === OC.Share.SHARE_TYPE_CIRCLE) {
@@ -207,7 +209,10 @@
shareWithTitle = shareWith + " (" + t('core', 'group') + ')';
} else if (shareType === OC.Share.SHARE_TYPE_REMOTE) {
shareWithTitle = shareWith + " (" + t('core', 'remote') + ')';
- } else if (shareType === OC.Share.SHARE_TYPE_EMAIL) {
+ } else if (shareType === OC.Share.SHARE_TYPE_REMOTE_GROUP) {
+ shareWithTitle = shareWith + " (" + t('core', 'remote group') + ')';
+ }
+ else if (shareType === OC.Share.SHARE_TYPE_EMAIL) {
shareWithTitle = shareWith + " (" + t('core', 'email') + ')';
} else if (shareType === OC.Share.SHARE_TYPE_CIRCLE) {
shareWithTitle = shareWith;
@@ -243,6 +248,7 @@
shareId: this.model.get('shares')[shareIndex].id,
modSeed: shareType !== OC.Share.SHARE_TYPE_USER && shareType !== OC.Share.SHARE_TYPE_CIRCLE,
isRemoteShare: shareType === OC.Share.SHARE_TYPE_REMOTE,
+ isRemoteGroupShare: shareType === OC.Share.SHARE_TYPE_REMOTE_GROUP,
isMailShare: shareType === OC.Share.SHARE_TYPE_EMAIL,
isCircleShare: shareType === OC.Share.SHARE_TYPE_CIRCLE,
isFileSharedByMail: shareType === OC.Share.SHARE_TYPE_EMAIL && !this.model.isFolder(),
diff --git a/core/js/sharedialogview.js b/core/js/sharedialogview.js
index dede768fad5a7..d886e45856fe6 100644
--- a/core/js/sharedialogview.js
+++ b/core/js/sharedialogview.js
@@ -93,6 +93,9 @@
this.configModel.on('change:isRemoteShareAllowed', function() {
view.render();
});
+ this.configModel.on('change:isRemoteGroupShareAllowed', function() {
+ view.render();
+ });
this.model.on('change:permissions', function() {
view.render();
});
@@ -161,7 +164,7 @@
},
function (result) {
if (result.ocs.meta.statuscode === 100) {
- var filter = function(users, groups, remotes, emails, circles) {
+ var filter = function(users, groups, remotes, remote_groups, emails, circles) {
if (typeof(emails) === 'undefined') {
emails = [];
}
@@ -172,6 +175,7 @@
var usersLength;
var groupsLength;
var remotesLength;
+ var remoteGroupsLength;
var emailsLength;
var circlesLength;
@@ -228,6 +232,14 @@
break;
}
}
+ } else if (share.share_type === OC.Share.SHARE_TYPE_REMOTE_GROUP) {
+ remoteGroupsLength = remote_groups.length;
+ for (j = 0; j < remoteGroupsLength; j++) {
+ if (remote_groups[j].value.shareWith === share.share_with) {
+ remote_groups.splice(j, 1);
+ break;
+ }
+ }
} else if (share.share_type === OC.Share.SHARE_TYPE_EMAIL) {
emailsLength = emails.length;
for (j = 0; j < emailsLength; j++) {
@@ -252,6 +264,7 @@
result.ocs.data.exact.users,
result.ocs.data.exact.groups,
result.ocs.data.exact.remotes,
+ result.ocs.data.exact.remote_groups,
result.ocs.data.exact.emails,
result.ocs.data.exact.circles
);
@@ -259,6 +272,7 @@
var exactUsers = result.ocs.data.exact.users;
var exactGroups = result.ocs.data.exact.groups;
var exactRemotes = result.ocs.data.exact.remotes;
+ var exactRemoteGroups = result.ocs.data.exact.remote_groups;
var exactEmails = [];
if (typeof(result.ocs.data.emails) !== 'undefined') {
exactEmails = result.ocs.data.exact.emails;
@@ -268,12 +282,13 @@
exactCircles = result.ocs.data.exact.circles;
}
- var exactMatches = exactUsers.concat(exactGroups).concat(exactRemotes).concat(exactEmails).concat(exactCircles);
+ var exactMatches = exactUsers.concat(exactGroups).concat(exactRemotes).concat(exactRemoteGroups).concat(exactEmails).concat(exactCircles);
filter(
result.ocs.data.users,
result.ocs.data.groups,
result.ocs.data.remotes,
+ result.ocs.data.remote_groups,
result.ocs.data.emails,
result.ocs.data.circles
);
@@ -281,6 +296,7 @@
var users = result.ocs.data.users;
var groups = result.ocs.data.groups;
var remotes = result.ocs.data.remotes;
+ var remoteGroups = result.ocs.data.remote_groups;
var lookup = result.ocs.data.lookup;
var emails = [];
if (typeof(result.ocs.data.emails) !== 'undefined') {
@@ -291,7 +307,7 @@
circles = result.ocs.data.circles;
}
- var suggestions = exactMatches.concat(users).concat(groups).concat(remotes).concat(emails).concat(circles).concat(lookup);
+ var suggestions = exactMatches.concat(users).concat(groups).concat(remotes).concat(remoteGroups).concat(emails).concat(circles).concat(lookup);
deferred.resolve(suggestions, exactMatches);
} else {
@@ -414,7 +430,9 @@
if (item.value.shareType === OC.Share.SHARE_TYPE_GROUP) {
text = t('core', '{sharee} (group)', { sharee: text }, undefined, { escape: false });
} else if (item.value.shareType === OC.Share.SHARE_TYPE_REMOTE) {
- text = t('core', '{sharee} (remote)', { sharee: text }, undefined, { escape: false });
+ text = t('core', '{sharee} (remote)', {sharee: text}, undefined, {escape: false});
+ } else if (item.value.shareType === OC.Share.SHARE_TYPE_REMOTE_GROUP) {
+ text = t('core', '{sharee} (remote group)', { sharee: text }, undefined, { escape: false });
} else if (item.value.shareType === OC.Share.SHARE_TYPE_EMAIL) {
text = t('core', '{sharee} (email)', { sharee: text }, undefined, { escape: false });
} else if (item.value.shareType === OC.Share.SHARE_TYPE_CIRCLE) {
diff --git a/core/js/tests/specs/sharedialogviewSpec.js b/core/js/tests/specs/sharedialogviewSpec.js
index d363915984987..83c890532025d 100644
--- a/core/js/tests/specs/sharedialogviewSpec.js
+++ b/core/js/tests/specs/sharedialogviewSpec.js
@@ -489,11 +489,13 @@ describe('OC.Share.ShareDialogView', function() {
'exact': {
'users': [],
'groups': [],
- 'remotes': []
+ 'remotes': [],
+ 'remote_groups': [],
},
'users': [],
'groups': [],
'remotes': [],
+ 'remote_groups': [],
'lookup': []
}
}
@@ -529,7 +531,8 @@ describe('OC.Share.ShareDialogView', function() {
'exact': {
'users': [],
'groups': [],
- 'remotes': []
+ 'remotes': [],
+ 'remote_groups': [],
},
'users': [
{
@@ -542,6 +545,7 @@ describe('OC.Share.ShareDialogView', function() {
],
'groups': [],
'remotes': [],
+ 'remote_groups': [],
'lookup': []
}
}
@@ -589,11 +593,13 @@ describe('OC.Share.ShareDialogView', function() {
}
],
'groups': [],
- 'remotes': []
+ 'remotes': [],
+ 'remote_groups': [],
},
'users': [],
'groups': [],
'remotes': [],
+ 'remote_groups': [],
'lookup': []
}
}
@@ -651,7 +657,8 @@ describe('OC.Share.ShareDialogView', function() {
}
}
],
- 'remotes': []
+ 'remotes': [],
+ 'remote_groups': [],
},
'users': [
{
@@ -679,6 +686,7 @@ describe('OC.Share.ShareDialogView', function() {
}
],
'remotes': [],
+ 'remote_groups': [],
'lookup': []
}
}
@@ -744,11 +752,13 @@ describe('OC.Share.ShareDialogView', function() {
}
],
'groups': [],
- 'remotes': []
+ 'remotes': [],
+ 'remote_groups': [],
},
'users': [],
'groups': [],
'remotes': [],
+ 'remote_groups': [],
'lookup': []
}
}
@@ -817,11 +827,13 @@ describe('OC.Share.ShareDialogView', function() {
}
],
'groups': [],
- 'remotes': []
+ 'remotes': [],
+ 'remote_groups': [],
},
'users': [],
'groups': [],
'remotes': [],
+ 'remote_groups': [],
'lookup': []
}
}
@@ -928,7 +940,8 @@ describe('OC.Share.ShareDialogView', function() {
}
],
'groups': [],
- 'remotes': []
+ 'remotes': [],
+ 'remote_groups': [],
},
'users': [
{
@@ -941,6 +954,7 @@ describe('OC.Share.ShareDialogView', function() {
],
'groups': [],
'remotes': [],
+ 'remote_groups': [],
'lookup': []
}
}
@@ -983,7 +997,8 @@ describe('OC.Share.ShareDialogView', function() {
}
}
],
- 'remotes': []
+ 'remotes': [],
+ 'remote_groups': [],
},
'users': [],
'groups': [
@@ -996,6 +1011,7 @@ describe('OC.Share.ShareDialogView', function() {
}
],
'remotes': [],
+ 'remote_groups': [],
'lookup': []
}
}
@@ -1038,7 +1054,8 @@ describe('OC.Share.ShareDialogView', function() {
'shareWith': 'foo@bar.com/baz'
}
}
- ]
+ ],
+ 'remote_groups': [],
},
'users': [],
'groups': [],
@@ -1051,6 +1068,7 @@ describe('OC.Share.ShareDialogView', function() {
}
}
],
+ 'remote_groups': [],
'lookup': []
}
}
@@ -1086,6 +1104,7 @@ describe('OC.Share.ShareDialogView', function() {
'users': [],
'groups': [],
'remotes': [],
+ 'remote_groups': [],
'emails': [
{
'label': 'foo@bar.com',
@@ -1099,6 +1118,7 @@ describe('OC.Share.ShareDialogView', function() {
'users': [],
'groups': [],
'remotes': [],
+ 'remote_groups': [],
'lookup': [],
'emails': [
{
@@ -1143,6 +1163,7 @@ describe('OC.Share.ShareDialogView', function() {
'users': [],
'groups': [],
'remotes': [],
+ 'remote_groups': [],
'circles': [
{
'label': 'CircleName (type, owner)',
@@ -1163,6 +1184,7 @@ describe('OC.Share.ShareDialogView', function() {
'users': [],
'groups': [],
'remotes': [],
+ 'remote_groups': [],
'lookup': [],
'circles': [
{
@@ -1211,7 +1233,8 @@ describe('OC.Share.ShareDialogView', function() {
'exact': {
'users': [],
'groups': [],
- 'remotes': []
+ 'remotes': [],
+ 'remote_groups': [],
},
'users': [
{
@@ -1231,6 +1254,7 @@ describe('OC.Share.ShareDialogView', function() {
],
'groups': [],
'remotes': [],
+ 'remote_groups': [],
'lookup': []
}
}
@@ -1270,7 +1294,8 @@ describe('OC.Share.ShareDialogView', function() {
'exact': {
'users': [],
'groups': [],
- 'remotes': []
+ 'remotes': [],
+ 'remote_groups': [],
},
'users': [
{
@@ -1290,6 +1315,7 @@ describe('OC.Share.ShareDialogView', function() {
],
'groups': [],
'remotes': [],
+ 'remote_groups': [],
'lookup': []
}
}
@@ -1364,7 +1390,8 @@ describe('OC.Share.ShareDialogView', function() {
'exact': {
'users': [],
'groups': [],
- 'remotes': []
+ 'remotes': [],
+ 'remote_groups': [],
},
'users': [
{
@@ -1384,6 +1411,7 @@ describe('OC.Share.ShareDialogView', function() {
],
'groups': [],
'remotes': [],
+ 'remote_groups': [],
'lookup': []
}
}
@@ -1423,7 +1451,8 @@ describe('OC.Share.ShareDialogView', function() {
}
],
'groups': [],
- 'remotes': []
+ 'remotes': [],
+ 'remote_groups': [],
},
'users': [
{
@@ -1436,6 +1465,7 @@ describe('OC.Share.ShareDialogView', function() {
],
'groups': [],
'remotes': [],
+ 'remote_groups': [],
'lookup': []
}
}
@@ -1467,7 +1497,8 @@ describe('OC.Share.ShareDialogView', function() {
'exact': {
'users': [],
'groups': [],
- 'remotes': []
+ 'remotes': [],
+ 'remote_groups': [],
},
'users': [],
'groups': [
@@ -1487,6 +1518,7 @@ describe('OC.Share.ShareDialogView', function() {
}
],
'remotes': [],
+ 'remote_groups': [],
'lookup': []
}
}
@@ -1526,7 +1558,8 @@ describe('OC.Share.ShareDialogView', function() {
}
}
],
- 'remotes': []
+ 'remotes': [],
+ 'remote_groups': [],
},
'users': [],
'groups': [
@@ -1539,6 +1572,7 @@ describe('OC.Share.ShareDialogView', function() {
}
],
'remotes': [],
+ 'remote_groups': [],
'lookup': []
}
}
@@ -1570,7 +1604,8 @@ describe('OC.Share.ShareDialogView', function() {
'exact': {
'users': [],
'groups': [],
- 'remotes': []
+ 'remotes': [],
+ 'remote_groups': [],
},
'users': [],
'groups': [],
@@ -1590,6 +1625,7 @@ describe('OC.Share.ShareDialogView', function() {
}
}
],
+ 'remote_groups': [],
'lookup': []
}
}
@@ -1629,7 +1665,8 @@ describe('OC.Share.ShareDialogView', function() {
'shareWith': 'foo@bar.com/baz'
}
}
- ]
+ ],
+ 'remote_groups': [],
},
'users': [],
'groups': [],
@@ -1642,6 +1679,7 @@ describe('OC.Share.ShareDialogView', function() {
}
}
],
+ 'remote_groups': [],
'lookup': []
}
}
@@ -1674,12 +1712,14 @@ describe('OC.Share.ShareDialogView', function() {
'users': [],
'groups': [],
'remotes': [],
+ 'remote_groups': [],
'emails': []
},
'users': [],
'groups': [],
'remotes': [],
'lookup': [],
+ 'remote_groups': [],
'emails': [
{
'label': 'foo@bar.com',
@@ -1727,6 +1767,7 @@ describe('OC.Share.ShareDialogView', function() {
'users': [],
'groups': [],
'remotes': [],
+ 'remote_groups': [],
'emails': [
{
'label': 'foo@bar.com',
@@ -1740,6 +1781,7 @@ describe('OC.Share.ShareDialogView', function() {
'users': [],
'groups': [],
'remotes': [],
+ 'remote_groups': [],
'lookup': [],
'emails': [
{
@@ -1781,11 +1823,13 @@ describe('OC.Share.ShareDialogView', function() {
'users': [],
'groups': [],
'remotes': [],
+ 'remote_groups': [],
'circles': []
},
'users': [],
'groups': [],
'remotes': [],
+ 'remote_groups': [],
'lookup': [],
'circles': [
{
@@ -1834,6 +1878,7 @@ describe('OC.Share.ShareDialogView', function() {
'users': [],
'groups': [],
'remotes': [],
+ 'remote_groups': [],
'circles': [
{
'label': 'CircleName (type, owner)',
@@ -1854,6 +1899,7 @@ describe('OC.Share.ShareDialogView', function() {
'users': [],
'groups': [],
'remotes': [],
+ 'remote_groups': [],
'lookup': [],
'circles': [
{
@@ -2031,11 +2077,13 @@ describe('OC.Share.ShareDialogView', function() {
'exact': {
'users': [],
'groups': [],
- 'remotes': []
+ 'remotes': [],
+ 'remote_groups': [],
},
'users': [],
'groups': [],
'remotes': [],
+ 'remote_groups': [],
'lookup': []
}
}
@@ -2126,11 +2174,13 @@ describe('OC.Share.ShareDialogView', function() {
}
],
'groups': [],
- 'remotes': []
+ 'remotes': [],
+ 'remote_groups': [],
},
'users': [],
'groups': [],
'remotes': [],
+ 'remote_groups': [],
'lookup': []
}
}
@@ -2191,11 +2241,13 @@ describe('OC.Share.ShareDialogView', function() {
}
],
'groups': [],
- 'remotes': []
+ 'remotes': [],
+ 'remote_groups': [],
},
'users': [],
'groups': [],
'remotes': [],
+ 'remote_groups': [],
'lookup': []
}
}
@@ -2248,12 +2300,14 @@ describe('OC.Share.ShareDialogView', function() {
'exact': {
'users': [],
'groups': [],
- 'remotes': []
+ 'remotes': [],
+ 'remote_groups': [],
},
'users': [],
'groups': [],
'remotes': [],
- 'lookup': []
+ 'lookup': [],
+ 'remote_groups': [],
}
}
});
@@ -2292,7 +2346,8 @@ describe('OC.Share.ShareDialogView', function() {
'exact': {
'users': [],
'groups': [],
- 'remotes': []
+ 'remotes': [],
+ 'remote_groups': [],
},
'users': [
{
@@ -2305,6 +2360,7 @@ describe('OC.Share.ShareDialogView', function() {
],
'groups': [],
'remotes': [],
+ 'remote_groups': [],
'lookup': []
}
}
@@ -2356,11 +2412,13 @@ describe('OC.Share.ShareDialogView', function() {
}
}
],
- 'remotes': []
+ 'remotes': [],
+ 'remote_groups': [],
},
'users': [],
'groups': [],
'remotes': [],
+ 'remote_groups': [],
'lookup': []
}
}
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php
index faf17a109b24d..7113f60bc6890 100644
--- a/lib/composer/composer/autoload_classmap.php
+++ b/lib/composer/composer/autoload_classmap.php
@@ -471,6 +471,7 @@
'OC\\Collaboration\\Collaborators\\GroupPlugin' => $baseDir . '/lib/private/Collaboration/Collaborators/GroupPlugin.php',
'OC\\Collaboration\\Collaborators\\LookupPlugin' => $baseDir . '/lib/private/Collaboration/Collaborators/LookupPlugin.php',
'OC\\Collaboration\\Collaborators\\MailPlugin' => $baseDir . '/lib/private/Collaboration/Collaborators/MailPlugin.php',
+ 'OC\\Collaboration\\Collaborators\\RemoteGroupPlugin' => $baseDir . '/lib/private/Collaboration/Collaborators/RemoteGroupPlugin.php',
'OC\\Collaboration\\Collaborators\\RemotePlugin' => $baseDir . '/lib/private/Collaboration/Collaborators/RemotePlugin.php',
'OC\\Collaboration\\Collaborators\\Search' => $baseDir . '/lib/private/Collaboration/Collaborators/Search.php',
'OC\\Collaboration\\Collaborators\\SearchResult' => $baseDir . '/lib/private/Collaboration/Collaborators/SearchResult.php',
diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php
index a8d748137e881..ffb50df5b098d 100644
--- a/lib/composer/composer/autoload_static.php
+++ b/lib/composer/composer/autoload_static.php
@@ -501,6 +501,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Collaboration\\Collaborators\\GroupPlugin' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Collaborators/GroupPlugin.php',
'OC\\Collaboration\\Collaborators\\LookupPlugin' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Collaborators/LookupPlugin.php',
'OC\\Collaboration\\Collaborators\\MailPlugin' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Collaborators/MailPlugin.php',
+ 'OC\\Collaboration\\Collaborators\\RemoteGroupPlugin' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Collaborators/RemoteGroupPlugin.php',
'OC\\Collaboration\\Collaborators\\RemotePlugin' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Collaborators/RemotePlugin.php',
'OC\\Collaboration\\Collaborators\\Search' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Collaborators/Search.php',
'OC\\Collaboration\\Collaborators\\SearchResult' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Collaborators/SearchResult.php',
diff --git a/lib/private/Collaboration/Collaborators/RemoteGroupPlugin.php b/lib/private/Collaboration/Collaborators/RemoteGroupPlugin.php
new file mode 100644
index 0000000000000..c48a1fbae204d
--- /dev/null
+++ b/lib/private/Collaboration/Collaborators/RemoteGroupPlugin.php
@@ -0,0 +1,78 @@
+
+ *
+ * @author Arthur Schiwon
+ *
+ * @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 .
+ *
+ */
+
+namespace OC\Collaboration\Collaborators;
+
+
+use OCP\Collaboration\Collaborators\ISearchPlugin;
+use OCP\Collaboration\Collaborators\ISearchResult;
+use OCP\Collaboration\Collaborators\SearchResultType;
+use OCP\Contacts\IManager;
+use OCP\Federation\ICloudFederationProviderManager;
+use OCP\Federation\ICloudIdManager;
+use OCP\IConfig;
+use OCP\Share;
+
+class RemoteGroupPlugin implements ISearchPlugin {
+ protected $shareeEnumeration;
+
+ /** @var ICloudIdManager */
+ private $cloudIdManager;
+ /** @var IConfig */
+ private $config;
+ /** @var bool */
+ private $enabled = false;
+
+ public function __construct(ICloudFederationProviderManager $cloudFederationProviderManager, ICloudIdManager $cloudIdManager) {
+ try {
+ $fileSharingProvider = $cloudFederationProviderManager->getCloudFederationProvider('file');
+ $supportedShareTypes = $fileSharingProvider->getSupportedShareTypes();
+ if (in_array('group', $supportedShareTypes)) {
+ $this->enabled = true;
+ }
+ } catch (\Exception $e) {
+ // do nothing, just don't enable federated group shares
+ }
+ $this->cloudIdManager = $cloudIdManager;
+ }
+
+ public function search($search, $limit, $offset, ISearchResult $searchResult) {
+ $result = ['wide' => [], 'exact' => []];
+ $resultType = new SearchResultType('remote_groups');
+
+ if ($this->enabled && $this->cloudIdManager->isValidCloudId($search) && $offset === 0) {
+ $result['exact'][] = [
+ 'label' => $search,
+ 'value' => [
+ 'shareType' => Share::SHARE_TYPE_REMOTE_GROUP,
+ 'shareWith' => $search,
+ ],
+ ];
+ }
+
+ $searchResult->addResultSet($resultType, $result['wide'], $result['exact']);
+
+ return true;
+ }
+
+}
diff --git a/lib/private/Federation/CloudFederationProviderManager.php b/lib/private/Federation/CloudFederationProviderManager.php
index 254ceb03bf870..94b2f05274770 100644
--- a/lib/private/Federation/CloudFederationProviderManager.php
+++ b/lib/private/Federation/CloudFederationProviderManager.php
@@ -157,6 +157,7 @@ public function sendShare(ICloudFederationShare $share) {
// we re-throw the exception and fall back to the old behaviour.
// (flat re-shares has been introduced in Nextcloud 9.1)
if ($e->getCode() === Http::STATUS_INTERNAL_SERVER_ERROR) {
+ $this->logger->debug($e->getMessage());
throw $e;
}
}
diff --git a/lib/private/Federation/CloudFederationShare.php b/lib/private/Federation/CloudFederationShare.php
index 0c2795188f06f..e0360d78cb262 100644
--- a/lib/private/Federation/CloudFederationShare.php
+++ b/lib/private/Federation/CloudFederationShare.php
@@ -204,7 +204,11 @@ public function setProtocol(array $protocol) {
* @since 14.0.0
*/
public function setShareType($shareType) {
- $this->share['shareType'] = $shareType;
+ if ($shareType === 'group' || $shareType === \OCP\Share::SHARE_TYPE_REMOTE_GROUP) {
+ $this->share['shareType'] = 'group';
+ } else {
+ $this->share['shareType'] = 'user';
+ }
}
/**
diff --git a/lib/private/Server.php b/lib/private/Server.php
index 90e9e81c105c0..c9f8001631eb6 100644
--- a/lib/private/Server.php
+++ b/lib/private/Server.php
@@ -60,6 +60,7 @@
use OC\Authentication\Token\IProvider;
use OC\Collaboration\Collaborators\GroupPlugin;
use OC\Collaboration\Collaborators\MailPlugin;
+use OC\Collaboration\Collaborators\RemoteGroupPlugin;
use OC\Collaboration\Collaborators\RemotePlugin;
use OC\Collaboration\Collaborators\UserPlugin;
use OC\Command\CronBus;
@@ -1066,6 +1067,7 @@ public function __construct($webRoot, \OC\Config $config) {
$instance->registerPlugin(['shareType' => 'SHARE_TYPE_GROUP', 'class' => GroupPlugin::class]);
$instance->registerPlugin(['shareType' => 'SHARE_TYPE_EMAIL', 'class' => MailPlugin::class]);
$instance->registerPlugin(['shareType' => 'SHARE_TYPE_REMOTE', 'class' => RemotePlugin::class]);
+ $instance->registerPlugin(['shareType' => 'SHARE_TYPE_REMOTE_GROUP', 'class' => RemoteGroupPlugin::class]);
return $instance;
});
diff --git a/lib/private/Share/Constants.php b/lib/private/Share/Constants.php
index f351f8d7fdae9..4eb79734c0616 100644
--- a/lib/private/Share/Constants.php
+++ b/lib/private/Share/Constants.php
@@ -37,6 +37,7 @@ class Constants {
const SHARE_TYPE_REMOTE = 6;
const SHARE_TYPE_CIRCLE = 7;
const SHARE_TYPE_GUEST = 8;
+ const SHARE_TYPE_REMOTE_GROUP = 9;
const FORMAT_NONE = -1;
const FORMAT_STATUSES = -2;
diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php
index 5116351a6bc99..76b523afd10b3 100644
--- a/lib/private/Share20/Manager.php
+++ b/lib/private/Share20/Manager.php
@@ -226,6 +226,10 @@ protected function generalCreateChecks(\OCP\Share\IShare $share) {
if ($share->getSharedWith() === null) {
throw new \InvalidArgumentException('SharedWith should not be empty');
}
+ } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE_GROUP) {
+ if ($share->getSharedWith() === null) {
+ throw new \InvalidArgumentException('SharedWith should not be empty');
+ }
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
if ($share->getSharedWith() === null) {
throw new \InvalidArgumentException('SharedWith should not be empty');
@@ -1579,6 +1583,13 @@ public function outgoingServer2ServerSharesAllowed() {
return $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes') === 'yes';
}
+ /**
+ * @inheritdoc
+ */
+ public function outgoingServer2ServerGroupSharesAllowed() {
+ return $this->config->getAppValue('files_sharing', 'outgoing_server2server_group_share_enabled', 'no') === 'yes';
+ }
+
/**
* @inheritdoc
*/
diff --git a/lib/private/Share20/ProviderFactory.php b/lib/private/Share20/ProviderFactory.php
index 7d866db24fa9d..80ef9412ffa64 100644
--- a/lib/private/Share20/ProviderFactory.php
+++ b/lib/private/Share20/ProviderFactory.php
@@ -135,7 +135,8 @@ protected function federatedShareProvider() {
$this->serverContainer->getConfig(),
$this->serverContainer->getUserManager(),
$this->serverContainer->getCloudIdManager(),
- $this->serverContainer->getGlobalScaleConfig()
+ $this->serverContainer->getGlobalScaleConfig(),
+ $this->serverContainer->getCloudFederationProviderManager()
);
}
@@ -250,7 +251,7 @@ public function getProviderForType($shareType) {
$shareType === \OCP\Share::SHARE_TYPE_LINK
) {
$provider = $this->defaultShareProvider();
- } else if ($shareType === \OCP\Share::SHARE_TYPE_REMOTE) {
+ } else if ($shareType === \OCP\Share::SHARE_TYPE_REMOTE || \OCP\Share::SHARE_TYPE_REMOTE_GROUP) {
$provider = $this->federatedShareProvider();
} else if ($shareType === \OCP\Share::SHARE_TYPE_EMAIL) {
$provider = $this->getShareByMailProvider();
diff --git a/lib/public/Share/IManager.php b/lib/public/Share/IManager.php
index d4fc3e1474999..302be5233273c 100644
--- a/lib/public/Share/IManager.php
+++ b/lib/public/Share/IManager.php
@@ -369,6 +369,14 @@ public function sharingDisabledForUser($userId);
*/
public function outgoingServer2ServerSharesAllowed();
+ /**
+ * Check if outgoing server2server shares are allowed
+ * @return bool
+ * @since 14.0.0
+ */
+ public function outgoingServer2ServerGroupSharesAllowed();
+
+
/**
* Check if a given share provider exists
* @param int $shareType