summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/cloud_federation_api/lib/Config.php9
-rw-r--r--apps/cloud_federation_api/lib/Controller/RequestHandlerController.php45
-rw-r--r--apps/federatedfilesharing/lib/AppInfo/Application.php7
-rw-r--r--apps/federatedfilesharing/lib/FederatedShareProvider.php89
-rw-r--r--apps/federatedfilesharing/lib/Notifications.php7
-rw-r--r--apps/federatedfilesharing/lib/Settings/Admin.php3
-rw-r--r--apps/federatedfilesharing/lib/ocm/CloudFederationProviderFiles.php180
-rw-r--r--apps/federatedfilesharing/templates/settings-admin.php17
-rw-r--r--apps/federatedfilesharing/tests/FederatedShareProviderTest.php28
-rw-r--r--apps/federatedfilesharing/tests/Settings/AdminTest.php21
-rw-r--r--apps/files_sharing/appinfo/database.xml11
-rw-r--r--apps/files_sharing/appinfo/info.xml2
-rw-r--r--apps/files_sharing/lib/AppInfo/Application.php2
-rw-r--r--apps/files_sharing/lib/Controller/ShareAPIController.php93
-rw-r--r--apps/files_sharing/lib/Controller/ShareesAPIController.php16
-rw-r--r--apps/files_sharing/lib/External/Manager.php157
-rw-r--r--apps/files_sharing/lib/Hooks.php2
-rw-r--r--apps/files_sharing/lib/ShareBackend/File.php4
-rw-r--r--apps/files_sharing/tests/Controller/ShareesAPIControllerTest.php78
-rw-r--r--apps/files_sharing/tests/External/ManagerTest.php16
20 files changed, 591 insertions, 196 deletions
diff --git a/apps/cloud_federation_api/lib/Config.php b/apps/cloud_federation_api/lib/Config.php
index 7d42960deaf..2fb842697d4 100644
--- a/apps/cloud_federation_api/lib/Config.php
+++ b/apps/cloud_federation_api/lib/Config.php
@@ -47,11 +47,14 @@ class Config {
*
* @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 27dd89f2abe..e7c6c415d3c 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\ICloudFederationFactory;
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 @@ class RequestHandlerController extends Controller {
IRequest $request,
ILogger $logger,
IUserManager $userManager,
+ IGroupManager $groupManager,
IURLGenerator $urlGenerator,
ICloudFederationProviderManager $cloudFederationProviderManager,
Config $config,
@@ -86,6 +91,7 @@ class RequestHandlerController extends Controller {
$this->logger = $logger;
$this->userManager = $userManager;
+ $this->groupManager = $groupManager;
$this->urlGenerator = $urlGenerator;
$this->cloudFederationProviderManager = $cloudFederationProviderManager;
$this->config = $config;
@@ -136,17 +142,37 @@ class RequestHandlerController extends Controller {
);
}
- $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 @@ class RequestHandlerController extends Controller {
$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 @@ class RequestHandlerController extends Controller {
);
}
- $user = $this->userManager->get($shareWithLocalId);
+ $user = $this->userManager->get($shareWith);
$recipientDisplayName = '';
if($user) {
$recipientDisplayName = $user->getDisplayName();
@@ -259,7 +285,6 @@ class RequestHandlerController extends Controller {
* @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 70347831211..73ac062be09 100644
--- a/apps/federatedfilesharing/lib/AppInfo/Application.php
+++ b/apps/federatedfilesharing/lib/AppInfo/Application.php
@@ -65,7 +65,8 @@ class Application extends App {
$server->getURLGenerator(),
$server->getCloudFederationFactory(),
$server->getCloudFederationProviderManager(),
- $server->getDatabaseConnection()
+ $server->getDatabaseConnection(),
+ $server->getGroupManager()
);
});
@@ -145,7 +146,9 @@ class Application extends App {
\OC::$server->getConfig(),
\OC::$server->getUserManager(),
\OC::$server->getCloudIdManager(),
- $c->query(IConfig::class)
+ $c->query(IConfig::class),
+ \OC::$server->getCloudFederationProviderManager()
+
);
}
diff --git a/apps/federatedfilesharing/lib/FederatedShareProvider.php b/apps/federatedfilesharing/lib/FederatedShareProvider.php
index f81b826f12c..d1560d90ef5 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 @@ class FederatedShareProvider implements IShareProvider {
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 @@ class FederatedShareProvider implements IShareProvider {
$this->userManager = $userManager;
$this->cloudIdManager = $cloudIdManager;
$this->gsConfig = $globalScaleConfig;
+ $this->cloudFederationProviderManager = $cloudFederationProviderManager;
}
/**
@@ -157,12 +167,23 @@ class FederatedShareProvider implements IShareProvider {
$itemType = $share->getNodeType();
$permissions = $share->getPermissions();
$sharedBy = $share->getSharedBy();
+ $shareType = $share->getShareType();
+
+ if ($shareType === \OCP\Share::SHARE_TYPE_REMOTE_GROUP &&
+ !$this->isOutgoingServer2serverGroupShareEnabled()
+ ) {
+ $message = 'It is not allowed to send federated group shares from this server.';
+ $message_t = $this->l->t('It is not allowed to send federated group shares from this server.');
+ $this->logger->debug($message, ['app' => 'Federated File Sharing']);
+ throw new \Exception($message_t);
+ }
/*
* Check if file is not already shared with the remote user
*/
- $alreadyShared = $this->getSharedWith($shareWith, self::SHARE_TYPE_REMOTE, $share->getNode(), 1, 0);
- if (!empty($alreadyShared)) {
+ $alreadyShared = $this->getSharedWith($shareWith, \OCP\Share::SHARE_TYPE_REMOTE, $share->getNode(), 1, 0);
+ $alreadySharedGroup = $this->getSharedWith($shareWith, \OCP\Share::SHARE_TYPE_REMOTE_GROUP, $share->getNode(), 1, 0);
+ if (!empty($alreadyShared) || !empty($alreadySharedGroup)) {
$message = 'Sharing %s failed, because this item is already shared with %s';
$message_t = $this->l->t('Sharing %s failed, because this item is already shared with %s', array($share->getNode()->getName(), $shareWith));
$this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']);
@@ -193,7 +214,7 @@ class FederatedShareProvider implements IShareProvider {
if ($remoteShare) {
try {
$ownerCloudId = $this->cloudIdManager->getCloudId($remoteShare['owner'], $remoteShare['remote']);
- $shareId = $this->addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $ownerCloudId->getId(), $permissions, 'tmp_token_' . time());
+ $shareId = $this->addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $ownerCloudId->getId(), $permissions, 'tmp_token_' . time(), $shareType);
$share->setId($shareId);
list($token, $remoteId) = $this->askOwnerToReShare($shareWith, $share, $shareId);
// remote share was create successfully if we get a valid token as return
@@ -238,7 +259,8 @@ class FederatedShareProvider implements IShareProvider {
$share->getSharedBy(),
$share->getShareOwner(),
$share->getPermissions(),
- $token
+ $token,
+ $share->getShareType()
);
$failure = false;
@@ -258,7 +280,8 @@ class FederatedShareProvider implements IShareProvider {
$share->getShareOwner(),
$ownerCloudId->getId(),
$share->getSharedBy(),
- $sharedByFederatedId
+ $sharedByFederatedId,
+ $share->getShareType()
);
if ($send === false) {
@@ -342,12 +365,13 @@ class FederatedShareProvider implements IShareProvider {
* @param string $uidOwner
* @param int $permissions
* @param string $token
+ * @param int $shareType
* @return int
*/
- private function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token) {
+ private function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $shareType) {
$qb = $this->dbConnection->getQueryBuilder();
$qb->insert('share')
- ->setValue('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE))
+ ->setValue('share_type', $qb->createNamedParameter($shareType))
->setValue('item_type', $qb->createNamedParameter($itemType))
->setValue('item_source', $qb->createNamedParameter($itemSource))
->setValue('file_source', $qb->createNamedParameter($itemSource))
@@ -491,7 +515,7 @@ class FederatedShareProvider implements IShareProvider {
$qb->select('*')
->from('share')
->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
- ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)))
+ ->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
->orderBy('id');
$cursor = $qb->execute();
@@ -640,7 +664,7 @@ class FederatedShareProvider implements IShareProvider {
$qb->select('*')
->from('share');
- $qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)));
+ $qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter($shareType)));
/**
* Reshares for this user are shares where they are the owner.
@@ -697,7 +721,7 @@ class FederatedShareProvider implements IShareProvider {
$qb->select('*')
->from('share')
->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
- ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)));
+ ->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)));
$cursor = $qb->execute();
$data = $cursor->fetch();
@@ -725,10 +749,11 @@ class FederatedShareProvider implements IShareProvider {
public function getSharesByPath(Node $path) {
$qb = $this->dbConnection->getQueryBuilder();
+ // get federated user shares
$cursor = $qb->select('*')
->from('share')
->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
- ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)))
+ ->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
->execute();
$shares = [];
@@ -761,7 +786,7 @@ class FederatedShareProvider implements IShareProvider {
}
$qb->setFirstResult($offset);
- $qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)));
+ $qb->where($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)));
$qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
// Filter by node if provided
@@ -792,7 +817,7 @@ class FederatedShareProvider implements IShareProvider {
$cursor = $qb->select('*')
->from('share')
- ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)))
+ ->where($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
->execute();
@@ -967,6 +992,42 @@ class FederatedShareProvider implements IShareProvider {
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 fdba3e113d6..70733bc9e2c 100644
--- a/apps/federatedfilesharing/lib/Notifications.php
+++ b/apps/federatedfilesharing/lib/Notifications.php
@@ -88,11 +88,12 @@ class Notifications {
* @param string $ownerFederatedId
* @param string $sharedBy
* @param string $sharedByFederatedId
+ * @param int $shareType (can be a remote user or group share)
* @return bool
* @throws \OC\HintException
* @throws \OC\ServerNotAvailableException
*/
- public function sendRemoteShare($token, $shareWith, $name, $remote_id, $owner, $ownerFederatedId, $sharedBy, $sharedByFederatedId) {
+ public function sendRemoteShare($token, $shareWith, $name, $remote_id, $owner, $ownerFederatedId, $sharedBy, $sharedByFederatedId, $shareType) {
list($user, $remote) = $this->addressHandler->splitUserRemote($shareWith);
@@ -109,6 +110,7 @@ class Notifications {
'sharedBy' => $sharedBy,
'sharedByFederatedId' => $sharedByFederatedId,
'remote' => $local,
+ 'shareType' => $shareType
);
$result = $this->tryHttpPostToShareEndpoint($remote, '', $fields);
@@ -392,7 +394,7 @@ class Notifications {
$fields['sharedByFederatedId'],
$fields['sharedBy'],
$fields['token'],
- 'user',
+ $fields['shareType'],
'file'
);
return $this->federationProviderManager->sendShare($share);
@@ -406,6 +408,7 @@ class Notifications {
'sharedSecret' => $fields['token'],
'shareWith' => $fields['shareWith'],
'senderId' => $fields['localId'],
+ 'shareType' => $fields['shareType'],
'message' => 'Ask owner to reshare the file'
]
);
diff --git a/apps/federatedfilesharing/lib/Settings/Admin.php b/apps/federatedfilesharing/lib/Settings/Admin.php
index cbeaa167fff..aea7957a49f 100644
--- a/apps/federatedfilesharing/lib/Settings/Admin.php
+++ b/apps/federatedfilesharing/lib/Settings/Admin.php
@@ -58,6 +58,9 @@ class Admin implements ISettings {
'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 00750f924ef..1d922ce60ba 100644
--- a/apps/federatedfilesharing/lib/ocm/CloudFederationProviderFiles.php
+++ b/apps/federatedfilesharing/lib/ocm/CloudFederationProviderFiles.php
@@ -40,10 +40,12 @@ use OCP\Federation\ICloudFederationShare;
use OCP\Federation\ICloudIdManager;
use OCP\Files\NotFoundException;
use OCP\IDBConnection;
+use OCP\IGroupManager;
use OCP\ILogger;
use OCP\IURLGenerator;
use OCP\IUserManager;
use OCP\Notification\IManager as INotificationManager;
+use OCP\Share;
use OCP\Share\Exceptions\ShareNotFound;
use OCP\Share\IShare;
use OCP\Util;
@@ -86,6 +88,9 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
/** @var IDBConnection */
private $connection;
+ /** @var IGroupManager */
+ private $groupManager;
+
/**
* CloudFederationProvider constructor.
*
@@ -101,6 +106,7 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
* @param ICloudFederationFactory $cloudFederationFactory
* @param ICloudFederationProviderManager $cloudFederationProviderManager
* @param IDBConnection $connection
+ * @param IGroupManager $groupManager
*/
public function __construct(IAppManager $appManager,
FederatedShareProvider $federatedShareProvider,
@@ -113,7 +119,8 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
IURLGenerator $urlGenerator,
ICloudFederationFactory $cloudFederationFactory,
ICloudFederationProviderManager $cloudFederationProviderManager,
- IDBConnection $connection
+ IDBConnection $connection,
+ IGroupManager $groupManager
) {
$this->appManager = $appManager;
$this->federatedShareProvider = $federatedShareProvider;
@@ -127,6 +134,7 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
$this->cloudFederationFactory = $cloudFederationFactory;
$this->cloudFederationProviderManager = $cloudFederationProviderManager;
$this->connection = $connection;
+ $this->groupManager = $groupManager;
}
@@ -175,6 +183,7 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
$remoteId = $share->getProviderId();
$sharedByFederatedId = $share->getSharedBy();
$ownerFederatedId = $share->getOwner();
+ $shareType = $this->mapShareTypeToNextcloud($share->getShareType());
// if no explicit information about the person who created the share was send
// we assume that the share comes from the owner
@@ -190,19 +199,25 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
}
// FIXME this should be a method in the user management instead
- $this->logger->debug('shareWith before, ' . $shareWith, ['app' => 'files_sharing']);
- Util::emitHook(
- '\OCA\Files_Sharing\API\Server2Server',
- 'preLoginNameUsedAsUserName',
- array('uid' => &$shareWith)
- );
- $this->logger->debug('shareWith after, ' . $shareWith, ['app' => 'files_sharing']);
+ if ($shareType === Share::SHARE_TYPE_USER) {
+ $this->logger->debug('shareWith before, ' . $shareWith, ['app' => 'files_sharing']);
+ Util::emitHook(
+ '\OCA\Files_Sharing\API\Server2Server',
+ 'preLoginNameUsedAsUserName',
+ array('uid' => &$shareWith)
+ );
+ $this->logger->debug('shareWith after, ' . $shareWith, ['app' => 'files_sharing']);
- if (!$this->userManager->userExists($shareWith)) {
- throw new ProviderCouldNotAddShareException('User does not exists', '',Http::STATUS_BAD_REQUEST);
+ if (!$this->userManager->userExists($shareWith)) {
+ throw new ProviderCouldNotAddShareException('User does not exists', '',Http::STATUS_BAD_REQUEST);
+ }
+
+ \OC_Util::setupFS($shareWith);
}
- \OC_Util::setupFS($shareWith);
+ if ($shareType === Share::SHARE_TYPE_GROUP && !$this->groupManager->groupExists($shareWith)) {
+ throw new ProviderCouldNotAddShareException('Group does not exists', '',Http::STATUS_BAD_REQUEST);
+ }
$externalManager = new \OCA\Files_Sharing\External\Manager(
\OC::$server->getDatabaseConnection(),
@@ -213,40 +228,37 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
\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, [
@@ -298,6 +310,51 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
}
/**
+ * map OCM share type (strings) to Nextcloud internal share types (integer)
+ *
+ * @param string $shareType
+ * @return int
+ */
+ private function mapShareTypeToNextcloud($shareType) {
+ $result = Share::SHARE_TYPE_USER;
+ if ($shareType === 'group') {
+ $result = Share::SHARE_TYPE_GROUP;
+ }
+
+ return $result;
+ }
+
+ /**
+ * notify user about new federated share
+ *
+ * @param $shareWith
+ * @param $shareId
+ * @param $ownerFederatedId
+ * @param $sharedByFederatedId
+ * @param $name
+ */
+ private function notifyAboutNewShare($shareWith, $shareId, $ownerFederatedId, $sharedByFederatedId, $name) {
+ $notification = $this->notificationManager->createNotification();
+ $notification->setApp('files_sharing')
+ ->setUser($shareWith)
+ ->setDateTime(new \DateTime())
+ ->setObject('remote_share', $shareId)
+ ->setSubject('remote_share', [$ownerFederatedId, $sharedByFederatedId, trim($name, '/')]);
+
+ $declineAction = $notification->createAction();
+ $declineAction->setLabel('decline')
+ ->setLink($this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/' . $shareId)), 'DELETE');
+ $notification->addAction($declineAction);
+
+ $acceptAction = $notification->createAction();
+ $acceptAction->setLabel('accept')
+ ->setLink($this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/' . $shareId)), 'POST');
+ $notification->addAction($acceptAction);
+
+ $this->notificationManager->notify($notification);
+ }
+
+ /**
* process notification that the recipient accepted a share
*
* @param string $id
@@ -521,25 +578,32 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
$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 @@ class CloudFederationProviderFiles implements ICloudFederationProvider {
* @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 187d75f21ac..1b9b88dc03e 100644
--- a/apps/federatedfilesharing/templates/settings-admin.php
+++ b/apps/federatedfilesharing/templates/settings-admin.php
@@ -23,7 +23,6 @@ script('federatedfilesharing', 'settings-admin');
<?php p($l->t('Allow users on this server to send shares to other servers'));?>
</label>
</p>
-
<p>
<input type="checkbox" name="incoming_server2server_share_enabled" id="incomingServer2serverShareEnabled" class="checkbox"
value="1" <?php if ($_['incomingServer2serverShareEnabled']) print_unescaped('checked="checked"'); ?> />
@@ -31,6 +30,22 @@ script('federatedfilesharing', 'settings-admin');
<?php p($l->t('Allow users on this server to receive shares from other servers'));?>
</label><br/>
</p>
+ <?php if($_['federatedGroupSharingSupported']): ?>
+ <p>
+ <input type="checkbox" name="outgoing_server2server_group_share_enabled" id="outgoingServer2serverGroupShareEnabled" class="checkbox"
+ value="1" <?php if ($_['outgoingServer2serverGroupShareEnabled']) print_unescaped('checked="checked"'); ?> />
+ <label for="outgoingServer2serverGroupShareEnabled">
+ <?php p($l->t('Allow users on this server to send shares to groups on other servers'));?>
+ </label>
+ </p>
+ <p>
+ <input type="checkbox" name="incoming_server2server_group_share_enabled" id="incomingServer2serverGroupShareEnabled" class="checkbox"
+ value="1" <?php if ($_['incomingServer2serverGroupShareEnabled']) print_unescaped('checked="checked"'); ?> />
+ <label for="incomingServer2serverGroupShareEnabled">
+ <?php p($l->t('Allow users on this server to receive group shares from other servers'));?>
+ </label><br/>
+ </p>
+ <?php endif; ?>
<p>
<input type="checkbox" name="lookupServerEnabled" id="lookupServerEnabled" class="checkbox"
value="1" <?php if ($_['lookupServerEnabled']) print_unescaped('checked="checked"'); ?> />
diff --git a/apps/federatedfilesharing/tests/FederatedShareProviderTest.php b/apps/federatedfilesharing/tests/FederatedShareProviderTest.php
index 52266383b36..98ad8832fa1 100644
--- a/apps/federatedfilesharing/tests/FederatedShareProviderTest.php
+++ b/apps/federatedfilesharing/tests/FederatedShareProviderTest.php
@@ -33,6 +33,7 @@ use OCA\FederatedFileSharing\AddressHandler;
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 @@ class FederatedShareProviderTest extends \Test\TestCase {
$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 @@ class FederatedShareProviderTest extends \Test\TestCase {
$this->config,
$this->userManager,
$this->cloudIdManager,
- $this->gsConfig
+ $this->gsConfig,
+ $this->cloudFederationProviderManager
);
$this->shareManager = \OC::$server->getShareManager();
@@ -141,6 +147,7 @@ class FederatedShareProviderTest extends \Test\TestCase {
->setSharedBy('sharedBy')
->setShareOwner('shareOwner')
->setPermissions(19)
+ ->setShareType(\OCP\Share::SHARE_TYPE_REMOTE)
->setNode($node);
$this->tokenHandler->method('generateToken')->willReturn('token');
@@ -212,6 +219,7 @@ class FederatedShareProviderTest extends \Test\TestCase {
->setSharedBy('sharedBy')
->setShareOwner('shareOwner')
->setPermissions(19)
+ ->setShareType(\OCP\Share::SHARE_TYPE_REMOTE)
->setNode($node);
$this->tokenHandler->method('generateToken')->willReturn('token');
@@ -268,6 +276,7 @@ class FederatedShareProviderTest extends \Test\TestCase {
->setSharedBy('sharedBy')
->setShareOwner('shareOwner')
->setPermissions(19)
+ ->setShareType(\OCP\Share::SHARE_TYPE_REMOTE)
->setNode($node);
$this->tokenHandler->method('generateToken')->willReturn('token');
@@ -367,6 +376,7 @@ class FederatedShareProviderTest extends \Test\TestCase {
->setSharedBy('sharedBy')
->setShareOwner('shareOwner')
->setPermissions(19)
+ ->setShareType(\OCP\Share::SHARE_TYPE_REMOTE)
->setNode($node);
$this->tokenHandler->method('generateToken')->willReturn('token');
@@ -417,7 +427,8 @@ class FederatedShareProviderTest extends \Test\TestCase {
$this->config,
$this->userManager,
$this->cloudIdManager,
- $this->gsConfig
+ $this->gsConfig,
+ $this->cloudFederationProviderManager
]
)->setMethods(['sendPermissionUpdate'])->getMock();
@@ -435,6 +446,7 @@ class FederatedShareProviderTest extends \Test\TestCase {
->setSharedBy($sharedBy)
->setShareOwner($owner)
->setPermissions(19)
+ ->setShareType(\OCP\Share::SHARE_TYPE_REMOTE)
->setNode($node);
$this->tokenHandler->method('generateToken')->willReturn('token');
@@ -505,6 +517,7 @@ class FederatedShareProviderTest extends \Test\TestCase {
->setSharedBy('sharedBy')
->setShareOwner('shareOwner')
->setPermissions(19)
+ ->setShareType(\OCP\Share::SHARE_TYPE_REMOTE)
->setNode($node);
$this->provider->create($share);
@@ -513,6 +526,7 @@ class FederatedShareProviderTest extends \Test\TestCase {
->setSharedBy('sharedBy2')
->setShareOwner('shareOwner')
->setPermissions(19)
+ ->setShareType(\OCP\Share::SHARE_TYPE_REMOTE)
->setNode($node);
$this->provider->create($share2);
@@ -543,6 +557,7 @@ class FederatedShareProviderTest extends \Test\TestCase {
->setSharedBy('sharedBy')
->setShareOwner('shareOwner')
->setPermissions(19)
+ ->setShareType(\OCP\Share::SHARE_TYPE_REMOTE)
->setNode($node);
$this->provider->create($share);
@@ -555,6 +570,7 @@ class FederatedShareProviderTest extends \Test\TestCase {
->setSharedBy('sharedBy')
->setShareOwner('shareOwner')
->setPermissions(19)
+ ->setShareType(\OCP\Share::SHARE_TYPE_REMOTE)
->setNode($node2);
$this->provider->create($share2);
@@ -584,6 +600,7 @@ class FederatedShareProviderTest extends \Test\TestCase {
->setSharedBy('shareOwner')
->setShareOwner('shareOwner')
->setPermissions(19)
+ ->setShareType(\OCP\Share::SHARE_TYPE_REMOTE)
->setNode($node);
$this->provider->create($share);
@@ -592,6 +609,7 @@ class FederatedShareProviderTest extends \Test\TestCase {
->setSharedBy('sharedBy')
->setShareOwner('shareOwner')
->setPermissions(19)
+ ->setShareType(\OCP\Share::SHARE_TYPE_REMOTE)
->setNode($node);
$this->provider->create($share2);
@@ -628,6 +646,7 @@ class FederatedShareProviderTest extends \Test\TestCase {
->setSharedBy('sharedBy')
->setShareOwner('shareOwner')
->setPermissions(19)
+ ->setShareType(\OCP\Share::SHARE_TYPE_REMOTE)
->setNode($node);
$this->provider->create($share);
@@ -636,6 +655,7 @@ class FederatedShareProviderTest extends \Test\TestCase {
->setSharedBy('sharedBy')
->setShareOwner('shareOwner')
->setPermissions(19)
+ ->setShareType(\OCP\Share::SHARE_TYPE_REMOTE)
->setNode($node);
$this->provider->create($share2);
@@ -826,6 +846,7 @@ class FederatedShareProviderTest extends \Test\TestCase {
->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 @@ class FederatedShareProviderTest extends \Test\TestCase {
->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 @@ class FederatedShareProviderTest extends \Test\TestCase {
->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 @@ class FederatedShareProviderTest extends \Test\TestCase {
->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 debd2bec63a..f0cf3b77d38 100644
--- a/apps/federatedfilesharing/tests/Settings/AdminTest.php
+++ b/apps/federatedfilesharing/tests/Settings/AdminTest.php
@@ -74,12 +74,28 @@ class AdminTest extends TestCase {
->willReturn($state);
$this->federatedShareProvider
->expects($this->once())
+ ->method('isIncomingServer2serverShareEnabled')
+ ->willReturn($state);
+ $this->federatedShareProvider
+ ->expects($this->once())
->method('isLookupServerQueriesEnabled')
->willReturn($state);
$this->federatedShareProvider
->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 @@ class AdminTest extends TestCase {
'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 a70be408da4..c3cfb9e1c88 100644
--- a/apps/files_sharing/appinfo/database.xml
+++ b/apps/files_sharing/appinfo/database.xml
@@ -16,6 +16,17 @@
<length>4</length>
</field>
<field>
+ <name>parent</name>
+ <type>integer</type>
+ <default>-1</default>
+ <length>4</length>
+ </field>
+ <field>
+ <name>share_type</name>
+ <type>integer</type>
+ <length>4</length>
+ </field>
+ <field>
<name>remote</name>
<type>text</type>
<notnull>true</notnull>
diff --git a/apps/files_sharing/appinfo/info.xml b/apps/files_sharing/appinfo/info.xml
index 94a31bea63c..f2725880df0 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.
</description>
- <version>1.6.1</version>
+ <version>1.6.2</version>
<licence>agpl</licence>
<author>Michael Gapczynski</author>
<author>Bjoern Schiessle</author>
diff --git a/apps/files_sharing/lib/AppInfo/Application.php b/apps/files_sharing/lib/AppInfo/Application.php
index e6ab4eb2cf1..a7d4755fbf0 100644
--- a/apps/files_sharing/lib/AppInfo/Application.php
+++ b/apps/files_sharing/lib/AppInfo/Application.php
@@ -105,6 +105,8 @@ class Application extends App {
$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 67ff9eae6d3..59b763ecf81 100644
--- a/apps/files_sharing/lib/Controller/ShareAPIController.php
+++ b/apps/files_sharing/lib/Controller/ShareAPIController.php
@@ -48,6 +48,7 @@ use OCP\IRequest;
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 @@ class ShareAPIController extends OCSController {
$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 @@ class ShareAPIController extends OCSController {
$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 @@ class ShareAPIController extends OCSController {
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 @@ class ShareAPIController extends OCSController {
$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 @@ class ShareAPIController extends OCSController {
}
$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 @@ class ShareAPIController extends OCSController {
* 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 @@ class ShareAPIController extends OCSController {
}
}
- } 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 @@ class ShareAPIController extends OCSController {
*/
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 @@ class ShareAPIController extends OCSController {
/** @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 @@ class ShareAPIController extends OCSController {
}
// 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 @@ class ShareAPIController extends OCSController {
$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 @@ class ShareAPIController extends OCSController {
/*
* 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 @@ class ShareAPIController extends OCSController {
$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 @@ class ShareAPIController extends OCSController {
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 @@ class ShareAPIController extends OCSController {
}
// 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 @@ class ShareAPIController extends OCSController {
}
}
- 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 @@ class ShareAPIController extends OCSController {
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 @@ class ShareAPIController extends OCSController {
}
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 d25f24f6f72..ee95661d4c6 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 @@ class ShareesAPIController extends OCSController {
$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 @@ class ShareesAPIController extends OCSController {
}
}
+ 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 02783560afe..6a036b663d9 100644
--- a/apps/files_sharing/lib/External/Manager.php
+++ b/apps/files_sharing/lib/External/Manager.php
@@ -39,6 +39,8 @@ use OCP\Files;
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 @@ class Manager {
IDiscoveryService $discoveryService,
ICloudFederationProviderManager $cloudFederationProviderManager,
ICloudFederationFactory $cloudFederationFactory,
+ IGroupManager $groupManager,
+ IUserManager $userManager,
$uid) {
$this->connection = $connection;
$this->mountManager = $mountManager;
@@ -116,6 +128,8 @@ class Manager {
$this->discoveryService = $discoveryService;
$this->cloudFederationProviderManager = $cloudFederationProviderManager;
$this->cloudFederationFactory = $cloudFederationFactory;
+ $this->groupManager = $groupManager;
+ $this->userManager = $userManager;
}
/**
@@ -126,12 +140,15 @@ class Manager {
* @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 @@ class Manager {
'mountpoint_hash' => $hash,
'accepted' => $accepted,
'remote_id' => $remoteId,
+ 'share_type' => $shareType,
];
$i = 1;
@@ -172,12 +190,7 @@ class Manager {
$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,
@@ -190,6 +203,32 @@ class Manager {
}
/**
+ * 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
*
* @param int $id share id
@@ -197,12 +236,27 @@ class Manager {
*/
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 @@ class Manager {
$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 @@ class Manager {
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 @@ class Manager {
$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 @@ class Manager {
$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 @@ class Manager {
* @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 cd66fd7702e..99e876eaaf0 100644
--- a/apps/files_sharing/lib/Hooks.php
+++ b/apps/files_sharing/lib/Hooks.php
@@ -42,6 +42,8 @@ class Hooks {
\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 bb28c1a33ac..bd32741e67e 100644
--- a/apps/files_sharing/lib/ShareBackend/File.php
+++ b/apps/files_sharing/lib/ShareBackend/File.php
@@ -195,6 +195,10 @@ class File implements \OCP\Share_Backend_File_Dependent {
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 98ae953a318..d8c706da03c 100644
--- a/apps/files_sharing/tests/Controller/ShareesAPIControllerTest.php
+++ b/apps/files_sharing/tests/Controller/ShareesAPIControllerTest.php
@@ -85,120 +85,125 @@ class ShareesAPIControllerTest extends TestCase {
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 @@ class ShareesAPIControllerTest extends TestCase {
* @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 @@ class ShareesAPIControllerTest extends TestCase {
$this->shareManager,
$this->collaboratorSearch
])
- ->setMethods(['isRemoteSharingAllowed', 'shareProviderExists'])
+ ->setMethods(['isRemoteSharingAllowed', 'shareProviderExists', 'isRemoteGroupSharingAllowed'])
->getMock();
$this->collaboratorSearch->expects($this->once())
@@ -264,6 +271,13 @@ class ShareesAPIControllerTest extends TestCase {
->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 2cc88160a8c..93c17ca10cf 100644
--- a/apps/files_sharing/tests/External/ManagerTest.php
+++ b/apps/files_sharing/tests/External/ManagerTest.php
@@ -35,6 +35,8 @@ use OCA\Files_Sharing\Tests\TestCase;
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 @@ class ManagerTest extends TestCase {
->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 @@ class ManagerTest extends TestCase {
\OC::$server->query(\OCP\OCS\IDiscoveryService::class),
$this->cloudFederationProviderManager,
$this->cloudFederationFactory,
+ $this->groupManager,
+ $this->userManager,
$this->uid
]
)->setMethods(['tryOCMEndPoint'])->getMock();
@@ -117,6 +129,7 @@ class ManagerTest extends TestCase {
'password' => '',
'name' => '/SharedFolder',
'owner' => 'foobar',
+ 'shareType' => \OCP\Share::SHARE_TYPE_USER,
'accepted' => false,
'user' => $this->uid,
];
@@ -125,6 +138,9 @@ class ManagerTest extends TestCase {
$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);