diff --git a/apps/dav/lib/Connector/Sabre/SharesPlugin.php b/apps/dav/lib/Connector/Sabre/SharesPlugin.php
index afafa4dcc14a..b6d9e83d3250 100644
--- a/apps/dav/lib/Connector/Sabre/SharesPlugin.php
+++ b/apps/dav/lib/Connector/Sabre/SharesPlugin.php
@@ -133,7 +133,9 @@ private function getSharesForNodeIds($nodeIDs) {
\OCP\Share::SHARE_TYPE_USER,
\OCP\Share::SHARE_TYPE_GROUP,
\OCP\Share::SHARE_TYPE_LINK,
- \OCP\Share::SHARE_TYPE_REMOTE
+ \OCP\Share::SHARE_TYPE_REMOTE,
+ \OCP\Share::SHARE_TYPE_REMOTE_GROUP
+
];
// Query DB for share types for specified node IDs
diff --git a/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php
index 9fefcf047ba3..25f631de9f6f 100644
--- a/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php
@@ -91,7 +91,8 @@ public function testGetProperties($shareTypes) {
\OCP\Share::SHARE_TYPE_USER,
\OCP\Share::SHARE_TYPE_GROUP,
\OCP\Share::SHARE_TYPE_LINK,
- \OCP\Share::SHARE_TYPE_REMOTE
+ \OCP\Share::SHARE_TYPE_REMOTE,
+ \OCP\Share::SHARE_TYPE_REMOTE_GROUP
];
$this->shareManager->expects($this->any())
@@ -172,7 +173,8 @@ public function testPreloadThenGetProperties($shareTypes) {
\OCP\Share::SHARE_TYPE_USER,
\OCP\Share::SHARE_TYPE_GROUP,
\OCP\Share::SHARE_TYPE_LINK,
- \OCP\Share::SHARE_TYPE_REMOTE
+ \OCP\Share::SHARE_TYPE_REMOTE,
+ \OCP\Share::SHARE_TYPE_REMOTE_GROUP
];
$this->shareManager->expects($this->any())
diff --git a/apps/federatedfilesharing/lib/AppInfo/Application.php b/apps/federatedfilesharing/lib/AppInfo/Application.php
index ccbee8ba8214..180c4bc64aa4 100644
--- a/apps/federatedfilesharing/lib/AppInfo/Application.php
+++ b/apps/federatedfilesharing/lib/AppInfo/Application.php
@@ -140,7 +140,8 @@ function ($c) use ($server) {
$server->getUserManager(),
$c->query('AddressHandler'),
$c->query('FederatedShareManager'),
- $server->getLogger()
+ $server->getLogger(),
+ $server->getConfig()
);
}
);
diff --git a/apps/federatedfilesharing/lib/Controller/OcmController.php b/apps/federatedfilesharing/lib/Controller/OcmController.php
index d739d268e633..74e1d8559840 100644
--- a/apps/federatedfilesharing/lib/Controller/OcmController.php
+++ b/apps/federatedfilesharing/lib/Controller/OcmController.php
@@ -32,10 +32,12 @@
use OCA\FederatedFileSharing\Ocm\Exception\OcmException;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http;
+use OCP\IConfig;
use OCP\ILogger;
use OCP\IRequest;
use OCP\IURLGenerator;
use OCP\IUserManager;
+use OCP\Share\Exceptions\ShareNotFound;
/**
* Class OcmController
@@ -75,6 +77,9 @@ class OcmController extends Controller {
*/
protected $logger;
+ /** @var IConfig */
+ private $config;
+
/**
* OcmController constructor.
*
@@ -86,6 +91,7 @@ class OcmController extends Controller {
* @param AddressHandler $addressHandler
* @param FedShareManager $fedShareManager
* @param ILogger $logger
+ * @param IConfig $config
*/
public function __construct(
$appName,
@@ -95,7 +101,8 @@ public function __construct(
IUserManager $userManager,
AddressHandler $addressHandler,
FedShareManager $fedShareManager,
- ILogger $logger
+ ILogger $logger,
+ IConfig $config
) {
parent::__construct($appName, $request);
@@ -105,6 +112,7 @@ public function __construct(
$this->addressHandler = $addressHandler;
$this->fedShareManager = $fedShareManager;
$this->logger = $logger;
+ $this->config = $config;
}
/**
@@ -177,6 +185,24 @@ public function createShare(
$resourceType,
$protocol
) {
+ // Allow other apps to overwrite the behaviour of this endpoint
+ $controllerClass = $this->config->getSystemValue('sharing.ocmController');
+ if (($controllerClass !== '') && ($controllerClass !== null)) {
+ $controller = \OC::$server->query($controllerClass);
+ return $controller->createShare(
+ $shareWith,
+ $name,
+ $description,
+ $providerId,
+ $owner,
+ $ownerDisplayName,
+ $sender,
+ $senderDisplayName,
+ $shareType,
+ $resourceType,
+ $protocol
+ );
+ }
try {
$this->ocmMiddleware->assertIncomingSharingEnabled();
$this->ocmMiddleware->assertNotNull(
@@ -284,6 +310,17 @@ public function processNotification(
$providerId,
$notification
) {
+ // Allow other apps to overwrite the behaviour of this endpoint
+ $controllerClass = $this->config->getSystemValue('sharing.ocmController');
+ if (($controllerClass !== '') && ($controllerClass !== null)) {
+ $controller = \OC::$server->query($controllerClass);
+ return $controller->processNotification(
+ $notificationType,
+ $resourceType,
+ $providerId,
+ $notification
+ );
+ }
try {
if (!\is_array($notification)) {
throw new BadRequestException(
diff --git a/apps/federatedfilesharing/tests/Controller/OcmControllerTest.php b/apps/federatedfilesharing/tests/Controller/OcmControllerTest.php
index 2a953a2ddf1b..6532d544a783 100644
--- a/apps/federatedfilesharing/tests/Controller/OcmControllerTest.php
+++ b/apps/federatedfilesharing/tests/Controller/OcmControllerTest.php
@@ -33,6 +33,7 @@
use OCA\FederatedFileSharing\Tests\TestCase;
use OCP\App\IAppManager;
use OCP\AppFramework\Http;
+use OCP\IConfig;
use OCP\ILogger;
use OCP\IRequest;
use OCP\IURLGenerator;
@@ -86,6 +87,11 @@ class OcmControllerTest extends TestCase {
*/
private $logger;
+ /**
+ * @var IConfig | \PHPUnit\Framework\MockObject\MockObject
+ */
+ private $config;
+
/**
* @var OcmController
*/
@@ -107,6 +113,7 @@ protected function setUp(): void {
$this->addressHandler = $this->createMock(AddressHandler::class);
$this->fedShareManager = $this->createMock(FedShareManager::class);
$this->logger = $this->createMock(ILogger::class);
+ $this->config = $this->createMock(IConfig::class);
$this->ocmController = new OcmController(
'federatedfilesharing',
@@ -116,7 +123,8 @@ protected function setUp(): void {
$this->userManager,
$this->addressHandler,
$this->fedShareManager,
- $this->logger
+ $this->logger,
+ $this->config
);
}
diff --git a/apps/files_sharing/js/app.js b/apps/files_sharing/js/app.js
index 2c98da47d548..61a8da9e851b 100644
--- a/apps/files_sharing/js/app.js
+++ b/apps/files_sharing/js/app.js
@@ -209,18 +209,19 @@ OCA.Sharing.App = {
fileList.fileSummary.$el.find('.filesize').remove();
},
- _setShareState: function(fileId, state, isRemote) {
+ _setShareState: function(fileId, state, isRemote, shareType) {
var method = 'POST';
if (state === OC.Share.STATE_REJECTED) {
method = 'DELETE';
}
-
var endPoint = isRemote === true ? 'remote_shares/pending/' : 'shares/pending/';
var xhr = $.ajax({
url: OC.linkToOCS('apps/files_sharing/api/v1') + endPoint + encodeURIComponent(fileId) + '?format=json',
contentType: 'application/json',
dataType: 'json',
type: method,
+ // be aware that `shareType` should not be an empty string
+ data: JSON.stringify((shareType !== undefined ? { shareType: shareType } : {})),
});
xhr.fail(function(response) {
var message = '';
@@ -236,6 +237,7 @@ OCA.Sharing.App = {
_shareStateActionHandler: function(context, newState) {
var targetFileData = context.fileList.elementToFile(context.$file);
var isRemote = targetFileData.shareLocationType === 'remote';
+ const shareType = targetFileData.shareType;
function responseCallback(response, status) {
if (status === 'success') {
var meta = response.ocs.meta;
@@ -252,7 +254,7 @@ OCA.Sharing.App = {
}
context.fileList.showFileBusyState(context.$file, true);
- this._setShareState(context.fileInfoModel.get('shares')[0].id, newState, isRemote)
+ this._setShareState(context.fileInfoModel.get('shares')[0].id, newState, isRemote, shareType)
.then(responseCallback);
},
diff --git a/apps/files_sharing/js/external.js b/apps/files_sharing/js/external.js
index e9eb3ac5d9ca..41afb6d45b7e 100644
--- a/apps/files_sharing/js/external.js
+++ b/apps/files_sharing/js/external.js
@@ -142,16 +142,20 @@
shares[index],
false,
function(result, share) {
+ let shareType = "user";
+ if (share.hasOwnProperty('share_type') ){
+ shareType = share.share_type;
+ }
if (result) {
// Accept
- $.post(OC.generateUrl('/apps/files_sharing/api/externalShares'), {id: share.id})
+ $.post(OC.generateUrl('/apps/files_sharing/api/externalShares'), {id: share.id, share_type: shareType })
.then(function() {
fileList.reload();
});
} else {
// Delete
$.ajax({
- url: OC.generateUrl('/apps/files_sharing/api/externalShares/'+share.id),
+ url: OC.generateUrl('/apps/files_sharing/api/externalShares/'+share.id+"?share_type="+shareType),
type: 'DELETE'
});
}
diff --git a/apps/files_sharing/js/share.js b/apps/files_sharing/js/share.js
index 93789ef86462..004f014cd574 100644
--- a/apps/files_sharing/js/share.js
+++ b/apps/files_sharing/js/share.js
@@ -151,6 +151,8 @@
hasShares = true;
} else if (shareType === OC.Share.SHARE_TYPE_REMOTE) {
hasShares = true;
+ } else if (shareType === OC.Share.SHARE_TYPE_REMOTE_GROUP) {
+ hasShares = true;
}
});
OCA.Sharing.Util._updateFileActionIcon($tr, hasShares, hasLink);
diff --git a/apps/files_sharing/js/sharedfilelist.js b/apps/files_sharing/js/sharedfilelist.js
index 7a8230d77680..e9b55312cbac 100644
--- a/apps/files_sharing/js/sharedfilelist.js
+++ b/apps/files_sharing/js/sharedfilelist.js
@@ -88,6 +88,7 @@
$dateColumn.before($tr.children('td:first'));
$tr.find('td.filename input:checkbox').remove();
$tr.attr('data-share-location-type', fileData.shareLocationType);
+ $tr.attr('data-share-type', fileData.shareType);
$tr.attr('data-share-id', _.pluck(fileData.shares, 'id').join(','));
// add row with expiration date for link only shares - influenced by _createRow of filelist
if (this._linksOnly) {
@@ -309,7 +310,8 @@
}
fileInfo.shareState = parseInt($el.attr('data-share-state'), 10);
- fileInfo.shareLocationType = $el.attr('data-share-location-type');
+ fileInfo.shareLocationType = $el.attr('data-share-location-type');
+ fileInfo.shareType = $el.attr('data-share-type') || "";
return fileInfo;
},
@@ -355,7 +357,8 @@
path: OC.dirname(share.mountpoint),
permissions: share.permissions,
tags: share.tags || [],
- shareLocationType: 'remote'
+ shareLocationType: 'remote',
+ shareType: share.share_type || ''
};
file.shares = [{
diff --git a/apps/files_sharing/lib/AppInfo/Application.php b/apps/files_sharing/lib/AppInfo/Application.php
index 47637b98750c..11cd5437d8b4 100644
--- a/apps/files_sharing/lib/AppInfo/Application.php
+++ b/apps/files_sharing/lib/AppInfo/Application.php
@@ -81,7 +81,8 @@ public function __construct(array $urlParams = []) {
$c->query('Request'),
$c->query('ExternalManager'),
$c->query('HttpClientService'),
- $server->getEventDispatcher()
+ $server->getEventDispatcher(),
+ $server->getConfig()
);
});
@@ -119,6 +120,8 @@ public function __construct(array $urlParams = []) {
$server->getEventDispatcher(),
$uid
),
+ $server->getConfig(),
+ $server->getLogger(),
$uid
);
});
diff --git a/apps/files_sharing/lib/Controller/RemoteOcsController.php b/apps/files_sharing/lib/Controller/RemoteOcsController.php
index 97c437921c74..8d82b28cf736 100644
--- a/apps/files_sharing/lib/Controller/RemoteOcsController.php
+++ b/apps/files_sharing/lib/Controller/RemoteOcsController.php
@@ -29,6 +29,8 @@
use OCP\Share;
use OCP\Files\StorageNotAvailableException;
use OCP\Files\StorageInvalidException;
+use OCP\IConfig;
+use OCP\ILogger;
class RemoteOcsController extends OCSController {
/** @var IRequest */
@@ -40,23 +42,39 @@ class RemoteOcsController extends OCSController {
/** @var string */
protected $uid;
+ /**
+ * @var IConfig
+ */
+ protected $config;
+
+ /**
+ * @var ILogger
+ */
+ protected $logger;
+
/**
* RemoteOcsController constructor.
*
* @param string $appName
* @param IRequest $request
* @param Manager $externalManager
+ * @param IConfig config
+ * @param ILogger $loggar
* @param string $uid
*/
public function __construct(
$appName,
IRequest $request,
Manager $externalManager,
+ IConfig $config,
+ ILogger $logger,
$uid
) {
parent::__construct($appName, $request);
$this->request = $request;
$this->externalManager = $externalManager;
+ $this->config = $config;
+ $this->logger = $logger;
$this->uid = $uid;
}
@@ -126,6 +144,8 @@ public function declineShare($id) {
*/
public function getShares($includingPending = false) {
$shares = [];
+ $groupExternalManager = null;
+
foreach ($this->externalManager->getAcceptedShares() as $shareInfo) {
try {
$shares[] = $this->extendShareInfo($shareInfo);
@@ -136,6 +156,22 @@ public function getShares($includingPending = false) {
}
}
+ // Allow the Federated Groups app to overwrite the behaviour of this endpoint
+ $managerClass = $this->config->getSystemValue('sharing.groupExternalManager');
+ if (!empty($managerClass)) {
+ $groupExternalManager = \OC::$server->query($managerClass);
+
+ foreach ($groupExternalManager->getAcceptedShares() as $shareInfo) {
+ try {
+ $shares[] = $this->extendShareInfo($shareInfo);
+ } catch (StorageNotAvailableException $e) {
+ $this->logger->logException($e, ['app' => 'files_sharing']);
+ } catch (StorageInvalidException $e) {
+ $this->logger->logException($e, ['app' => 'files_sharing']);
+ }
+ }
+ }
+
if ($includingPending === true) {
/**
* pending shares have mountpoint looking like
@@ -152,7 +188,10 @@ function ($share) {
$share['mountpoint'] = \rtrim($share['mountpoint'], '}');
return $share;
},
- $this->externalManager->getOpenShares()
+ \array_merge(
+ $this->externalManager->getOpenShares(),
+ $groupExternalManager === null ? [] : $groupExternalManager->getOpenShares()
+ )
);
$shares = \array_merge($shares, $openShares);
}
diff --git a/apps/files_sharing/lib/Controller/Share20OcsController.php b/apps/files_sharing/lib/Controller/Share20OcsController.php
index ab9eb943f0b1..0a2d706cb78b 100644
--- a/apps/files_sharing/lib/Controller/Share20OcsController.php
+++ b/apps/files_sharing/lib/Controller/Share20OcsController.php
@@ -23,6 +23,7 @@
use Exception;
use OC\Files\Filesystem;
+use OC\Share20\Exception\ProviderException;
use OCA\Files_Sharing\SharingAllowlist;
use OCP\Constants;
use OC\OCS\Result;
@@ -267,7 +268,7 @@ protected function formatShare(IShare $share, $received = false) {
if ($share->getToken() !== null) {
$result['url'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $share->getToken()]);
}
- } elseif ($share->getShareType() === Share::SHARE_TYPE_REMOTE) {
+ } elseif ($share->getShareType() === Share::SHARE_TYPE_REMOTE || $share->getShareType() === Share::SHARE_TYPE_REMOTE_GROUP) {
$result['share_with'] = $share->getSharedWith();
$result['share_with_displayname'] = $share->getSharedWith();
$result['token'] = $share->getToken();
@@ -553,7 +554,7 @@ public function createShare() {
if ($password !== '') {
$share->setPassword($password);
}
- } elseif ($shareType === Share::SHARE_TYPE_REMOTE) {
+ } elseif ($shareType === Share::SHARE_TYPE_REMOTE || $shareType === Share::SHARE_TYPE_REMOTE_GROUP) {
if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new Result(null, 403, $this->l->t('Sharing %s failed because the back end does not allow shares from type %s', [$path->getPath(), $shareType]));
@@ -702,6 +703,7 @@ public function getShares() {
return new Result();
}
+ $supportedShareTypes = $this->getSupportedShareTypes();
$sharedWithMe = $this->request->getParam('shared_with_me', null);
$reshares = $this->request->getParam('reshares', null);
$subfiles = $this->request->getParam('subfiles');
@@ -710,26 +712,16 @@ public function getShares() {
$includeTags = $this->request->getParam('include_tags', false);
$shareTypes = $this->request->getParam('share_types', '');
if ($shareTypes === '') {
- $shareTypes = [
- Share::SHARE_TYPE_USER,
- Share::SHARE_TYPE_GROUP,
- Share::SHARE_TYPE_LINK,
- Share::SHARE_TYPE_REMOTE,
- ];
+ $shareTypes = $supportedShareTypes;
} else {
$shareTypes = \explode(',', $shareTypes);
}
- $requestedShareTypes = [
- Share::SHARE_TYPE_USER => false,
- Share::SHARE_TYPE_GROUP => false,
- Share::SHARE_TYPE_LINK => false,
- Share::SHARE_TYPE_REMOTE => false,
- ];
-
+ $requestedShareTypes = array_fill_keys($supportedShareTypes, false);
+
if ($this->shareManager->outgoingServer2ServerSharesAllowed() === false) {
// if outgoing remote shares aren't allowed, the remote share type can't be chosen
- unset($requestedShareTypes[Share::SHARE_TYPE_REMOTE]);
+ unset($requestedShareTypes[Share::SHARE_TYPE_REMOTE], $requestedShareTypes[Share::SHARE_TYPE_REMOTE_GROUP]);
}
foreach ($shareTypes as $shareType) {
if (isset($requestedShareTypes[$shareType])) {
@@ -1211,16 +1203,27 @@ private function parseDate($expireDate) {
*/
private function getShareById($id, $recipient = null) {
$share = null;
-
+ $providerIds = \array_keys($this->shareManager->getProvidersCapabilities());
+
// First check if it is an internal share.
- try {
- $share = $this->shareManager->getShareById('ocinternal:'.$id, $recipient);
- } catch (ShareNotFound $e) {
- if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) {
- throw new ShareNotFound();
+ foreach ($providerIds as $providerId) {
+ try {
+ $share = $this->shareManager->getShareById($providerId .":". $id, $recipient);
+ return $share;
+ } catch (ShareNotFound $e) {
+ if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) {
+ throw new ShareNotFound();
+ }
+
+ continue;
+ } catch (ProviderException $e) {
+ // We should iterate all provider to find proper provider for given share
+ continue;
}
+ }
- $share = $this->shareManager->getShareById('ocFederatedSharing:' . $id, $recipient);
+ if ($share === null) {
+ throw new ShareNotFound();
}
return $share;
@@ -1290,4 +1293,23 @@ private function getPermissionsFromRequest() {
return $permission;
}
+
+ /**
+ * @return mixed
+ */
+ private function getSupportedShareTypes() {
+ $providersCapabilities = $this->shareManager->getProvidersCapabilities();
+
+ $shareTypes = [];
+
+ foreach ($providersCapabilities as $capabilities) {
+ foreach ($capabilities as $key => $value) {
+ $shareTypes[] = $key;
+ }
+ }
+ $shareTypes = \array_unique($shareTypes);
+ $shareTypes = array_keys(array_intersect(Share::CONVERT_SHARE_TYPE_TO_STRING, $shareTypes));
+
+ return $shareTypes;
+ }
}
diff --git a/apps/files_sharing/lib/Controllers/ExternalSharesController.php b/apps/files_sharing/lib/Controllers/ExternalSharesController.php
index 62e0cf2794db..7cc05cca6921 100644
--- a/apps/files_sharing/lib/Controllers/ExternalSharesController.php
+++ b/apps/files_sharing/lib/Controllers/ExternalSharesController.php
@@ -29,6 +29,7 @@
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Http\JSONResponse;
use OCP\Http\Client\IClientService;
+use OCP\IConfig;
use OCP\IRequest;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\GenericEvent;
@@ -41,6 +42,8 @@
class ExternalSharesController extends Controller {
/** @var \OCA\Files_Sharing\External\Manager */
private $externalManager;
+ /** @var \OCA\Files_Sharing\External\Manager */
+ private $groupExternalManager = null;
/** @var IClientService */
private $clientService;
/**
@@ -48,6 +51,10 @@ class ExternalSharesController extends Controller {
*/
private $dispatcher;
+ /** @var IConfig $config */
+ private $config;
+
+ public const group_share_type = "group";
/**
* ExternalSharesController constructor.
*
@@ -56,18 +63,21 @@ class ExternalSharesController extends Controller {
* @param \OCA\Files_Sharing\External\Manager $externalManager
* @param IClientService $clientService
* @param EventDispatcherInterface $eventDispatcher
+ * @param IConfig $config
*/
public function __construct(
$appName,
IRequest $request,
\OCA\Files_Sharing\External\Manager $externalManager,
IClientService $clientService,
- EventDispatcherInterface $eventDispatcher
+ EventDispatcherInterface $eventDispatcher,
+ IConfig $config
) {
parent::__construct($appName, $request);
$this->externalManager = $externalManager;
$this->clientService = $clientService;
$this->dispatcher = $eventDispatcher;
+ $this->config = $config;
}
/**
@@ -77,7 +87,13 @@ public function __construct(
* @return JSONResponse
*/
public function index() {
- return new JSONResponse($this->externalManager->getOpenShares());
+ $federatedGroupResult = [];
+ $groupExternalManager = $this->initGroupManager();
+ if ($groupExternalManager !== null) {
+ $federatedGroupResult = $groupExternalManager->getOpenShares();
+ }
+ $result = array_merge($federatedGroupResult, $this->externalManager->getOpenShares());
+ return new JSONResponse($result);
}
/**
@@ -85,13 +101,16 @@ public function index() {
* @NoOutgoingFederatedSharingRequired
*
* @param int $id
+ * @param string $share_type
* @return JSONResponse
*/
- public function create($id) {
- $shareInfo = $this->externalManager->getShare($id);
+ public function create($id, $share_type) {
+ $manager = $this->getManagerForShareType($share_type);
+ $shareInfo = $manager->getShare($id);
+
if ($shareInfo !== false) {
- $mountPoint = $this->externalManager->getShareRecipientMountPoint($shareInfo);
- $fileId = $this->externalManager->getShareFileId($shareInfo, $mountPoint);
+ $mountPoint = $manager->getShareRecipientMountPoint($shareInfo);
+ $fileId = $manager->getShareFileId($shareInfo, $mountPoint);
$event = new GenericEvent(
null,
@@ -106,7 +125,7 @@ public function create($id) {
]
);
$this->dispatcher->dispatch($event, 'remoteshare.accepted');
- $this->externalManager->acceptShare($id);
+ $manager->acceptShare($id);
}
return new JSONResponse();
}
@@ -118,8 +137,9 @@ public function create($id) {
* @param integer $id
* @return JSONResponse
*/
- public function destroy($id) {
- $shareInfo = $this->externalManager->getShare($id);
+ public function destroy($id, $share_type) {
+ $manager = $this->getManagerForShareType($share_type);
+ $shareInfo = $manager->getShare($id);
if ($shareInfo !== false) {
$event = new GenericEvent(
null,
@@ -131,11 +151,30 @@ public function destroy($id) {
]
);
$this->dispatcher->dispatch($event, 'remoteshare.declined');
- $this->externalManager->declineShare($id);
+ $manager->declineShare($id);
}
return new JSONResponse();
}
+ private function initGroupManager() {
+ // Allow other apps to add an external manager for user-to-group shares
+ $managerClass = $this->config->getSystemValue('sharing.groupExternalManager');
+ if ($managerClass !== '') {
+ return \OC::$server->query($managerClass);
+ }
+ return null;
+ }
+
+ private function getManagerForShareType($share_type) {
+ $groupExternalManager = $this->initGroupManager();
+ if ($share_type === self::group_share_type && $groupExternalManager !== null) {
+ $manager = $groupExternalManager;
+ } else {
+ $manager = $this->externalManager;
+ }
+ return $manager;
+ }
+
/**
* Test whether the specified remote is accessible
*
diff --git a/apps/files_sharing/tests/Controller/RemoteOcsControllerTest.php b/apps/files_sharing/tests/Controller/RemoteOcsControllerTest.php
index 514149929d03..7fa328b898d3 100644
--- a/apps/files_sharing/tests/Controller/RemoteOcsControllerTest.php
+++ b/apps/files_sharing/tests/Controller/RemoteOcsControllerTest.php
@@ -24,6 +24,8 @@
use OC\Files\FileInfo;
use OCA\Files_Sharing\Controller\RemoteOcsController;
use OCA\Files_Sharing\External\Manager;
+use OCP\IConfig;
+use OCP\ILogger;
use OCP\IRequest;
use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
@@ -38,16 +40,27 @@ class RemoteOcsControllerTest extends TestCase {
/** @var Manager */
protected $externalManager;
+ /** @var IConfig */
+ protected $config;
+
+ /** @var ILogger */
+ protected $logger;
+
/** @var RemoteOcsController | MockObject */
protected $controller;
protected function setUp(): void {
$this->request = $this->createMock(IRequest::class);
$this->externalManager = $this->createMock(Manager::class);
+ $this->config = $this->createMock(IConfig::class);
+ $this->logger = $this->createMock(ILogger::class);
+
$this->controller = new RemoteOcsController(
$this->appName,
$this->request,
$this->externalManager,
+ $this->config,
+ $this->logger,
'user'
);
}
@@ -170,6 +183,8 @@ public function testGetShare($getShareResult, $expectedStatusCode) {
$this->appName,
$this->request,
$this->externalManager,
+ $this->config,
+ $this->logger,
'user'
])
->setMethods(['getFileInfo'])
diff --git a/apps/files_sharing/tests/Controller/Share20OcsControllerTest.php b/apps/files_sharing/tests/Controller/Share20OcsControllerTest.php
index 0598929f22b8..babfb5c4e06b 100644
--- a/apps/files_sharing/tests/Controller/Share20OcsControllerTest.php
+++ b/apps/files_sharing/tests/Controller/Share20OcsControllerTest.php
@@ -121,6 +121,20 @@ protected function setUp(): void {
->expects($this->any())
->method('newShare')
->willReturn($this->newShare());
+ $this->shareManager
+ ->method('getProvidersCapabilities')
+ ->willReturn([
+ "ocinternal" =>
+ [
+ "user" => ["shareExpiration"],
+ "group" => ["shareExpiration"],
+ "link" => ["shareExpiration", "passwordProtected"]
+ ],
+ "ocFederatedSharing"=>
+ [
+ "remote" => ["shareExpiration"]
+ ],
+ ]);
$this->groupManager = $this->createMock(IGroupManager::class);
$this->userManager = $this->createMock(IUserManager::class);
$this->request = $this->createMock(IRequest::class);
diff --git a/apps/files_sharing/tests/Controllers/ExternalShareControllerTest.php b/apps/files_sharing/tests/Controllers/ExternalShareControllerTest.php
index 2e745d5675cf..0d9ee014986c 100644
--- a/apps/files_sharing/tests/Controllers/ExternalShareControllerTest.php
+++ b/apps/files_sharing/tests/Controllers/ExternalShareControllerTest.php
@@ -65,7 +65,8 @@ public function getExternalShareController() {
$this->request,
$this->externalManager,
$this->clientService,
- \OC::$server->getEventDispatcher()
+ \OC::$server->getEventDispatcher(),
+ \OC::$server->getConfig()
);
}
@@ -107,7 +108,7 @@ public function testCreate() {
$called[] = 'remoteshare.accepted';
\array_push($called, $event);
});
- $this->assertEquals(new JSONResponse(), $this->getExternalShareController()->create($shareId));
+ $this->assertEquals(new JSONResponse(), $this->getExternalShareController()->create($shareId, "remote"));
$this->assertSame('remoteshare.accepted', $called[0]);
$this->assertInstanceOf(GenericEvent::class, $called[1]);
@@ -137,7 +138,7 @@ public function testDestroy() {
\array_push($called, $event);
});
- $this->assertEquals(new JSONResponse(), $this->getExternalShareController()->destroy($shareId));
+ $this->assertEquals(new JSONResponse(), $this->getExternalShareController()->destroy($shareId, "user"));
$this->assertSame('remoteshare.declined', $called[0]);
$this->assertInstanceOf(GenericEvent::class, $called[1]);
diff --git a/apps/files_sharing/tests/js/externalSpec.js b/apps/files_sharing/tests/js/externalSpec.js
index 21f88b3c333a..4d0ea3d7fed9 100644
--- a/apps/files_sharing/tests/js/externalSpec.js
+++ b/apps/files_sharing/tests/js/externalSpec.js
@@ -174,7 +174,7 @@ describe('OCA.Sharing external tests', function() {
var request = fakeServer.requests[1];
var query = OC.parseQueryString(request.requestBody);
expect(request.method).toEqual('POST');
- expect(query).toEqual({id: '123'});
+ expect(query).toEqual({id: '123', share_type: 'user'});
expect(request.url).toEqual(
OC.webroot + '/index.php/apps/files_sharing/api/externalShares'
);
@@ -200,7 +200,7 @@ describe('OCA.Sharing external tests', function() {
var request = fakeServer.requests[1];
expect(request.method).toEqual('DELETE');
expect(request.url).toEqual(
- OC.webroot + '/index.php/apps/files_sharing/api/externalShares/123'
+ OC.webroot + '/index.php/apps/files_sharing/api/externalShares/123?share_type=user'
);
expect(plugin.filesApp.fileList.reload.notCalled).toEqual(true);
diff --git a/changelog/unreleased/40577 b/changelog/unreleased/40577
new file mode 100644
index 000000000000..02ebc8dcb44e
--- /dev/null
+++ b/changelog/unreleased/40577
@@ -0,0 +1,10 @@
+Enhancement: Add support for OCM via ScienceMesh
+
+
+We've added an if-statement in the files_sharing ShareesController
+code that searches for remote sharees. When the 'sciencemesh' app
+is installed, use it instead of the federatedfilesharing app to
+find sharee matches for OCM sharing.
+
+https://github.com/owncloud/core/issues/40577
+https://github.com/pondersource/oc-sciencemesh/pull/39
\ No newline at end of file
diff --git a/core/css/icons.css b/core/css/icons.css
index 40c81111fb1a..6f2ff89a9351 100644
--- a/core/css/icons.css
+++ b/core/css/icons.css
@@ -203,6 +203,10 @@ img.icon-loading-small-dark, object.icon-loading-small-dark, video.icon-loading-
background-image: url('../img/actions/history.svg');
}
+.icon-group {
+ background-image: url('../img/actions/group.svg');
+}
+
.icon-info {
background-image: url('../img/actions/info.svg');
}
diff --git a/core/css/share.css b/core/css/share.css
index a6f7bd67d7cc..22ea16d4c6be 100644
--- a/core/css/share.css
+++ b/core/css/share.css
@@ -53,9 +53,16 @@
.share-autocomplete-item {
display: flex;
+ align-items: center;
max-width: 220px;
}
+.share-autocomplete-item .icon {
+ margin-left: auto;
+ margin-right: 5px;
+ background-size: 24px 24px;
+}
+
@media (min-width: 1152px) {
.share-autocomplete-item {
max-width: 20vw;
diff --git a/core/img/actions/group.svg b/core/img/actions/group.svg
new file mode 100644
index 000000000000..9b37641c5d13
--- /dev/null
+++ b/core/img/actions/group.svg
@@ -0,0 +1,9 @@
+
+
\ No newline at end of file
diff --git a/core/js/share.js b/core/js/share.js
index 28de617b055d..c4d0e2a5222b 100644
--- a/core/js/share.js
+++ b/core/js/share.js
@@ -9,6 +9,7 @@ OC.Share = _.extend(OC.Share || {}, {
SHARE_TYPE_LINK:3,
SHARE_TYPE_GUEST:4,
SHARE_TYPE_REMOTE:6,
+ SHARE_TYPE_REMOTE_GROUP:7,
STATE_ACCEPTED: 0,
STATE_PENDING: 1,
diff --git a/core/js/sharedialogview.js b/core/js/sharedialogview.js
index 856814912dae..6b6a131e3c65 100644
--- a/core/js/sharedialogview.js
+++ b/core/js/sharedialogview.js
@@ -62,6 +62,9 @@
'{{/if}}' +
'
{{typeInfo}}' +
'' +
+ '{{#if showIcon}}' +
+ '' +
+ '{{/if}}' +
'' +
'' +
'';
@@ -353,8 +356,9 @@
},
autocompleteRenderItem: function(ul, item) {
-
var text = item.label;
+ let showIcon = false;
+ let iconClass = ""
var typeInfo = t('core', 'User');
if (item.batch) {
@@ -363,6 +367,11 @@
if (item.value.shareType === OC.Share.SHARE_TYPE_GROUP) {
typeInfo = t('core', 'Group');
}
+ if (item.value.shareType === OC.Share.SHARE_TYPE_REMOTE_GROUP) {
+ typeInfo = t('core', 'Federated Group');
+ showIcon = true
+ iconClass = "icon-contacts-dark"
+ }
if (item.value.shareType === OC.Share.SHARE_TYPE_GUEST) {
typeInfo = t('core', 'Guest');
}
@@ -375,7 +384,7 @@
typeInfo = t('core', 'Federated');
}
}
- if(item.value.userType === OC.User.USER_TYPE_GUEST){
+ if (item.value.userType === OC.User.USER_TYPE_GUEST) {
typeInfo = t('core', 'Guest');
}
@@ -383,12 +392,14 @@
var $el = $(template({
showAvatar: this.configModel.areAvatarsEnabled(),
displayName: text,
+ showIcon,
+ iconClass,
typeInfo: typeInfo,
additionalInfo: item.value.shareWithAdditionalInfo,
shareTypeClass: (item.value.shareType === OC.Share.SHARE_TYPE_GROUP) ? 'group' : 'user'
}));
- if(this.configModel.areAvatarsEnabled()) {
+ if (this.configModel.areAvatarsEnabled()) {
var $avatar = $el.find('.avatardiv');
if (item.value.shareType === OC.Share.SHARE_TYPE_USER) {
$avatar.avatar(item.value.shareWith, 32, undefined, undefined, undefined, item.label);
diff --git a/lib/private/Share/Constants.php b/lib/private/Share/Constants.php
index 8583b6da6b33..908e27395382 100644
--- a/lib/private/Share/Constants.php
+++ b/lib/private/Share/Constants.php
@@ -31,6 +31,7 @@ class Constants {
public const SHARE_TYPE_GUEST = 4;
public const SHARE_TYPE_CONTACT = 5; // ToDo Check if it is still in use otherwise remove it
public const SHARE_TYPE_REMOTE = 6;
+ public const SHARE_TYPE_REMOTE_GROUP = 7;
public const CONVERT_SHARE_TYPE_TO_STRING = [
self::SHARE_TYPE_USER => 'user',
@@ -39,6 +40,7 @@ class Constants {
self::SHARE_TYPE_GUEST => 'guest',
self::SHARE_TYPE_CONTACT => 'contact',
self::SHARE_TYPE_REMOTE => 'remote',
+ self::SHARE_TYPE_REMOTE_GROUP => 'remote_group',
];
/**
diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php
index bac7968de6ec..4a69bd7f4c84 100644
--- a/lib/private/Share20/Manager.php
+++ b/lib/private/Share20/Manager.php
@@ -52,6 +52,7 @@
use OCP\Share\IAttributes;
use OCP\Share\IManager;
use OCP\Share\IProviderFactory;
+use OC\Share20\Exception\ProviderException;
use OCP\Share\IShare;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\GenericEvent;
@@ -266,7 +267,7 @@ protected function generalChecks(\OCP\Share\IShare $share) {
if ($share->getSharedWith() !== null) {
throw new \InvalidArgumentException('SharedWith should be empty');
}
- } elseif ($share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE) {
+ } elseif ($share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE || $share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE_GROUP) {
if ($share->getSharedWith() === null) {
throw new \InvalidArgumentException('SharedWith should not be empty');
}
@@ -1529,10 +1530,32 @@ public function getShareByToken($token) {
// If it is not a link share try to fetch a federated share by token
if ($share === null) {
- $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_REMOTE);
- $share = $provider->getShareByToken($token);
+ try {
+ $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_REMOTE);
+ $share = $provider->getShareByToken($token);
+ } catch(ShareNotFound $ex) {
+ $this->logger->error(
+ "shared file not found by token: $token for federated user share, try to check federated group share.",
+ ['app' => __CLASS__]
+ );
+ try {
+ $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_REMOTE_GROUP);
+ if ($provider !== null) {
+ $share = $provider->getShareByToken($token);
+ }
+ } catch (ShareNotFound $ex) {
+ $this->logger->error(
+ "shared file not found by token: $token for federated group share",
+ ['app' => __CLASS__]
+ );
+ } catch (ProviderException $ex) {
+ $this->logger->logException(
+ $ex,
+ ['app' => __CLASS__]
+ );
+ }
+ }
}
-
if (self::shareHasExpired($share)) {
$this->activityManager->setAgentAuthor(IEvent::AUTOMATION_AUTHOR);
try {
diff --git a/lib/private/Share20/ProviderFactory.php b/lib/private/Share20/ProviderFactory.php
index 243a702cc564..ae9478065bf6 100644
--- a/lib/private/Share20/ProviderFactory.php
+++ b/lib/private/Share20/ProviderFactory.php
@@ -130,7 +130,8 @@ public function getProviderForType($shareType) {
$shareType === \OCP\Share::SHARE_TYPE_GROUP ||
$shareType === \OCP\Share::SHARE_TYPE_LINK) {
$provider = $this->defaultShareProvider();
- } elseif ($shareType === \OCP\Share::SHARE_TYPE_REMOTE) {
+ } elseif ($shareType === \OCP\Share::SHARE_TYPE_REMOTE ||
+ $shareType === \OCP\Share::SHARE_TYPE_REMOTE_GROUP) {
$provider = $this->federatedShareProvider();
}