From f927a1cf14fc120b347b46d44488b8591e767d91 Mon Sep 17 00:00:00 2001 From: Yvo Brevoort Date: Wed, 6 Oct 2021 14:29:06 +0000 Subject: [PATCH] Adding dynamic share providers. Signed-off-by: Michiel de Jong --- .../lib/Controller/ShareAPIController.php | 105 +++++++++++++----- lib/private/Share20/Manager.php | 1 + lib/private/Share20/ProviderFactory.php | 14 +++ lib/public/Share/IShare.php | 5 + 4 files changed, 100 insertions(+), 25 deletions(-) diff --git a/apps/files_sharing/lib/Controller/ShareAPIController.php b/apps/files_sharing/lib/Controller/ShareAPIController.php index c044148513261..d6d2446569da4 100644 --- a/apps/files_sharing/lib/Controller/ShareAPIController.php +++ b/apps/files_sharing/lib/Controller/ShareAPIController.php @@ -113,6 +113,8 @@ class ShareAPIController extends OCSController { /** @var IPreview */ private $previewManager; + private $dynamicShareTypes; + /** * Share20OCS constructor. * @@ -161,6 +163,33 @@ public function __construct( $this->serverContainer = $serverContainer; $this->userStatusManager = $userStatusManager; $this->previewManager = $previewManager; + $this->dynamicShareTypes = []; + // FIXME: Move this line into the sciencemesh app: + $this->registerHelper(IShare::TYPE_SCIENCEMESH, 'sciencemesh', '\OCA\ScienceMesh\ShareProvider\ShareAPIHelper'); + } + + public function registerHelper($shareType, $identifier, $helperClassName) { + $this->dynamicShareTypes[$shareType] = [ + "identifier" => $identifier, + "helperClass" => $helperClassName + ]; + } + + private function haveHelperFor($shareType) { + return isset($this->dynamicShareTypes[$shareType]); + } + + private function getIdentifierFor($shareType) { + return $this->dynamicShareTypes[$shareType]["identifier"]; + } + + private function getHelperFor($shareType) { + $identifier = $this->getIdentifierFor($shareType); + if (!$this->appManager->isEnabledForUser($identifier)) { + throw new QueryException(); + } + + return $this->serverContainer->get($this->dynamicShareTypes[$shareType]["helperClass"]); } /** @@ -318,6 +347,14 @@ protected function formatShare(IShare $share, Node $recipientNode = null): array $result = array_merge($result, $this->getDeckShareHelper()->formatShare($share)); } catch (QueryException $e) { } + } elseif ($this->haveHelperFor($share->getShareType())) { + $result['share_with'] = $share->getSharedWith(); + $result['share_with_displayname'] = ''; + + try { + $result = array_merge($result, $this->getHelperFor($share->getShareType())->formatShare($share)); + } catch (QueryException $e) { + } } @@ -663,6 +700,12 @@ public function createShare( } catch (QueryException $e) { throw new OCSForbiddenException($this->l->t('Sharing %s failed because the back end does not support room shares', [$node->getPath()])); } + } elseif ($this->haveHelperFor($shareType)) { + try { + $this->getHelperFor($shareType)->createShare($share, $shareWith, $permissions, $expireDate); + } catch (QueryException $e) { + throw new OCSForbiddenException($this->l->t('Sharing %s failed because the back end does not support this type of shares', [$node->getPath()])); + } } else { throw new OCSBadRequestException($this->l->t('Unknown share type')); } @@ -1568,6 +1611,17 @@ private function getShareById(string $id): IShare { // Do nothing, just try the other share type } + foreach ($this->dynamicShareTypes as $shareType => $details) { + try { + if ($this->shareManager->shareProviderExists($shareType)) { + $share = $this->shareManager->getShareById($details["identifier"] . ":" . $id, $this->currentUser); + return $share; + } + } catch (ShareNotFound $e) { + // Do nothing, just try the other share type + } + } + if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) { throw new ShareNotFound(); } @@ -1631,6 +1685,20 @@ private function getDeckShareHelper() { return $this->serverContainer->get('\OCA\Deck\Sharing\ShareAPIHelper'); } + private function getProvidersExceptOutgoing() { + // FIXME: load this list dynamically + return [ + IShare::TYPE_USER, + IShare::TYPE_GROUP, + IShare::TYPE_LINK, + IShare::TYPE_EMAIL, + IShare::TYPE_CIRCLE, + IShare::TYPE_ROOM, + IShare::TYPE_DECK, + IShare::TYPE_SCIENCEMESH + ]; + } + /** * @param string $viewer * @param Node $node @@ -1639,15 +1707,7 @@ private function getDeckShareHelper() { * @return IShare[] */ private function getSharesFromNode(string $viewer, $node, bool $reShares): array { - $providers = [ - IShare::TYPE_USER, - IShare::TYPE_GROUP, - IShare::TYPE_LINK, - IShare::TYPE_EMAIL, - IShare::TYPE_CIRCLE, - IShare::TYPE_ROOM, - IShare::TYPE_DECK - ]; + $providers = $this->getProviders(false); // Should we assume that the (currentUser) viewer is the owner of the node !? $shares = []; @@ -1785,21 +1845,16 @@ private function shareProviderResharingRights(string $userId, IShare $share, $no * @return IShare[] */ private function getAllShares(?Node $path = null, bool $reshares = false) { - // Get all shares - $userShares = $this->shareManager->getSharesBy($this->currentUser, IShare::TYPE_USER, $path, $reshares, -1, 0); - $groupShares = $this->shareManager->getSharesBy($this->currentUser, IShare::TYPE_GROUP, $path, $reshares, -1, 0); - $linkShares = $this->shareManager->getSharesBy($this->currentUser, IShare::TYPE_LINK, $path, $reshares, -1, 0); - - // EMAIL SHARES - $mailShares = $this->shareManager->getSharesBy($this->currentUser, IShare::TYPE_EMAIL, $path, $reshares, -1, 0); - - // CIRCLE SHARES - $circleShares = $this->shareManager->getSharesBy($this->currentUser, IShare::TYPE_CIRCLE, $path, $reshares, -1, 0); - - // TALK SHARES - $roomShares = $this->shareManager->getSharesBy($this->currentUser, IShare::TYPE_ROOM, $path, $reshares, -1, 0); - - $deckShares = $this->shareManager->getSharesBy($this->currentUser, IShare::TYPE_DECK, $path, $reshares, -1, 0); + $providers = $this->getProvidersExceptOutgoing(); + $shares = []; + foreach ($providers as $provider) { + if (!$this->shareManager->shareProviderExists($provider)) { + continue; + } + $providerShares = + $this->shareManager->getSharesBy($this->currentUser, $provider, $path, $reshares, -1, 0); + $shares = array_merge($shares, $providerShares); + } // FEDERATION if ($this->shareManager->outgoingServer2ServerSharesAllowed()) { @@ -1813,7 +1868,7 @@ private function getAllShares(?Node $path = null, bool $reshares = false) { $federatedGroupShares = []; } - return array_merge($userShares, $groupShares, $linkShares, $mailShares, $circleShares, $roomShares, $deckShares, $federatedShares, $federatedGroupShares); + return array_merge($shares, $federatedShares, $federatedGroupShares); } diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php index aab69eae597eb..e78fe8c85388b 100644 --- a/lib/private/Share20/Manager.php +++ b/lib/private/Share20/Manager.php @@ -245,6 +245,7 @@ protected function generalCreateChecks(IShare $share) { } } elseif ($share->getShareType() === IShare::TYPE_ROOM) { } elseif ($share->getShareType() === IShare::TYPE_DECK) { + } else if ($this->factory->getProviderForType($share->getShareType())) { } else { // We cannot handle other types yet throw new \InvalidArgumentException('unknown share type'); diff --git a/lib/private/Share20/ProviderFactory.php b/lib/private/Share20/ProviderFactory.php index 434c0017d21cb..443c0072963fd 100644 --- a/lib/private/Share20/ProviderFactory.php +++ b/lib/private/Share20/ProviderFactory.php @@ -325,6 +325,20 @@ public function getProviderForType($shareType) { $provider = $this->getRoomShareProvider(); } elseif ($shareType === IShare::TYPE_DECK) { $provider = $this->getProvider('deck'); + } else { + // try to autodetect in the registered providers; + foreach ($this->registeredShareProviders as $shareProvider) { + /** @var IShareProvider $instance */ + $instance = $this->serverContainer->get($shareProvider); + + // not all instances will have the isShareTypeSupported function; + if (method_exists($instance, "isShareTypeSupported")) { + if ($instance->isShareTypeSupported($shareType)) { + $provider = $this->getProvider($instance->identifier()); + break; + } + } + } } diff --git a/lib/public/Share/IShare.php b/lib/public/Share/IShare.php index 1d3cf9bbbdff7..6c7a720243887 100644 --- a/lib/public/Share/IShare.php +++ b/lib/public/Share/IShare.php @@ -116,6 +116,11 @@ interface IShare { */ public const TYPE_DECK_USER = 13; + /** + * @since ? + */ + public const TYPE_SCIENCEMESH = 1000; + /** * @since 18.0.0 */