diff --git a/apps/admin_audit/lib/Actions/Sharing.php b/apps/admin_audit/lib/Actions/Sharing.php index 2c28660a56f2c7b76a2fa6312f0b69521e6a916e..cab02ab188653546f6164c37028fcc67d37684bf 100644 --- a/apps/admin_audit/lib/Actions/Sharing.php +++ b/apps/admin_audit/lib/Actions/Sharing.php @@ -146,6 +146,19 @@ class Sharing extends Action { 'id', ] ); + } elseif ($params['shareType'] === IShare::TYPE_DECK) { + $this->log( + 'The %s "%s" with ID "%s" has been shared to the deck card "%s" with permissions "%s" (Share ID: %s)', + $params, + [ + 'itemType', + 'itemTarget', + 'itemSource', + 'shareWith', + 'permissions', + 'id', + ] + ); } } @@ -250,6 +263,18 @@ class Sharing extends Action { 'id', ] ); + } elseif ($params['shareType'] === IShare::TYPE_DECK) { + $this->log( + 'The %s "%s" with ID "%s" has been unshared from the deck card "%s" (Share ID: %s)', + $params, + [ + 'itemType', + 'fileTarget', + 'itemSource', + 'shareWith', + 'id', + ] + ); } } diff --git a/apps/dav/lib/Connector/Sabre/SharesPlugin.php b/apps/dav/lib/Connector/Sabre/SharesPlugin.php index 3abdf6c254694dd3156d18502ca09f32b635bac5..c4b8f0a462390b18890adaf01272072a923290e8 100644 --- a/apps/dav/lib/Connector/Sabre/SharesPlugin.php +++ b/apps/dav/lib/Connector/Sabre/SharesPlugin.php @@ -121,6 +121,7 @@ class SharesPlugin extends \Sabre\DAV\ServerPlugin { IShare::TYPE_EMAIL, IShare::TYPE_ROOM, IShare::TYPE_CIRCLE, + IShare::TYPE_DECK, ]; foreach ($requestedShareTypes as $requestedShareType) { $shares = $this->shareManager->getSharesBy( diff --git a/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php index 27af0b1501b4098017a9779440bd65865daba771..f48e652272257b9b85110a0bd4e314350e3c0167 100644 --- a/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php +++ b/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php @@ -276,6 +276,7 @@ class SharesPluginTest extends \Test\TestCase { [[IShare::TYPE_LINK]], [[IShare::TYPE_REMOTE]], [[IShare::TYPE_ROOM]], + [[IShare::TYPE_DECK]], [[IShare::TYPE_USER, IShare::TYPE_GROUP]], [[IShare::TYPE_USER, IShare::TYPE_GROUP, IShare::TYPE_LINK]], [[IShare::TYPE_USER, IShare::TYPE_LINK]], diff --git a/apps/files/lib/Controller/ApiController.php b/apps/files/lib/Controller/ApiController.php index ee4d86bc360961249576cdb37382921a2d9a3ad8..f7a0674eff0f9725f594aff836ac1d4e4d82ec9d 100644 --- a/apps/files/lib/Controller/ApiController.php +++ b/apps/files/lib/Controller/ApiController.php @@ -221,7 +221,8 @@ class ApiController extends Controller { IShare::TYPE_LINK, IShare::TYPE_REMOTE, IShare::TYPE_EMAIL, - IShare::TYPE_ROOM + IShare::TYPE_ROOM, + IShare::TYPE_DECK, ]; foreach ($requestedShareTypes as $requestedShareType) { // one of each type is enough to find out about the types diff --git a/apps/files/lib/Service/OwnershipTransferService.php b/apps/files/lib/Service/OwnershipTransferService.php index fa979c2006aeba49604d92a616294db5ed116088..bd8520b92fc0bf5b64b1f5701217f405b7dd4f01 100644 --- a/apps/files/lib/Service/OwnershipTransferService.php +++ b/apps/files/lib/Service/OwnershipTransferService.php @@ -252,7 +252,7 @@ class OwnershipTransferService { $shares = []; $progress = new ProgressBar($output); - foreach ([IShare::TYPE_GROUP, IShare::TYPE_USER, IShare::TYPE_LINK, IShare::TYPE_REMOTE, IShare::TYPE_ROOM, IShare::TYPE_EMAIL, IShare::TYPE_CIRCLE] as $shareType) { + foreach ([IShare::TYPE_GROUP, IShare::TYPE_USER, IShare::TYPE_LINK, IShare::TYPE_REMOTE, IShare::TYPE_ROOM, IShare::TYPE_EMAIL, IShare::TYPE_CIRCLE, IShare::TYPE_DECK] as $shareType) { $offset = 0; while (true) { $sharePage = $this->shareManager->getSharesBy($sourceUid, $shareType, null, true, 50, $offset); diff --git a/apps/files_sharing/js/dist/additionalScripts.js b/apps/files_sharing/js/dist/additionalScripts.js index be0ffa5e1bb6c9f396c320de215381bea83fd0c0..f5966ec3cf3f7e31a3369fc63a9e7544914643dd 100644 Binary files a/apps/files_sharing/js/dist/additionalScripts.js and b/apps/files_sharing/js/dist/additionalScripts.js differ diff --git a/apps/files_sharing/js/dist/additionalScripts.js.map b/apps/files_sharing/js/dist/additionalScripts.js.map index 0d831ba8549b381024e9f80ac4d1a30472ee2b41..20de1fff9b06dd86164f6ece925f38f7b6515123 100644 Binary files a/apps/files_sharing/js/dist/additionalScripts.js.map and b/apps/files_sharing/js/dist/additionalScripts.js.map differ diff --git a/apps/files_sharing/js/dist/files_sharing_tab.js b/apps/files_sharing/js/dist/files_sharing_tab.js index 535431fdd3a2721c4369d848a34e1090405a583b..ca78f9c06bdd7d71f07f4e2607ec558e323a832d 100644 Binary files a/apps/files_sharing/js/dist/files_sharing_tab.js and b/apps/files_sharing/js/dist/files_sharing_tab.js differ diff --git a/apps/files_sharing/js/dist/files_sharing_tab.js.map b/apps/files_sharing/js/dist/files_sharing_tab.js.map index 55c2012cee3b0c1c0062e007a2625655e105c6bc..ecd5b302c27d5326700b3f8d99666e92ede21667 100644 Binary files a/apps/files_sharing/js/dist/files_sharing_tab.js.map and b/apps/files_sharing/js/dist/files_sharing_tab.js.map differ diff --git a/apps/files_sharing/js/dist/main.js b/apps/files_sharing/js/dist/main.js index 206bc8b9044409bb245cdf70fe7f7f68fea4720f..4995303afe0a59df53dbdb3db9e00413acc061bd 100644 Binary files a/apps/files_sharing/js/dist/main.js and b/apps/files_sharing/js/dist/main.js differ diff --git a/apps/files_sharing/js/dist/main.js.map b/apps/files_sharing/js/dist/main.js.map index a50837077297bb1c22d3838ae870433a186bb106..62ae9f2491a4041cdf4b3427930bd364da9684ed 100644 Binary files a/apps/files_sharing/js/dist/main.js.map and b/apps/files_sharing/js/dist/main.js.map differ diff --git a/apps/files_sharing/lib/Controller/DeletedShareAPIController.php b/apps/files_sharing/lib/Controller/DeletedShareAPIController.php index 9b367e0654416dc28f5f1d6f3ecf6e3ed82fdf46..9a757412316afe26fcc51c0177b6d41b0b10770d 100644 --- a/apps/files_sharing/lib/Controller/DeletedShareAPIController.php +++ b/apps/files_sharing/lib/Controller/DeletedShareAPIController.php @@ -151,6 +151,14 @@ class DeletedShareAPIController extends OCSController { $result = array_merge($result, $this->getRoomShareHelper()->formatShare($share)); } catch (QueryException $e) { } + } elseif ($share->getShareType() === IShare::TYPE_DECK) { + $result['share_with'] = $share->getSharedWith(); + $result['share_with_displayname'] = ''; + + try { + $result = array_merge($result, $this->getDeckShareHelper()->formatShare($share)); + } catch (QueryException $e) { + } } return $result; @@ -162,8 +170,9 @@ class DeletedShareAPIController extends OCSController { public function index(): DataResponse { $groupShares = $this->shareManager->getDeletedSharedWith($this->userId, IShare::TYPE_GROUP, null, -1, 0); $roomShares = $this->shareManager->getDeletedSharedWith($this->userId, IShare::TYPE_ROOM, null, -1, 0); + $deckShares = $this->shareManager->getDeletedSharedWith($this->userId, IShare::TYPE_DECK, null, -1, 0); - $shares = array_merge($groupShares, $roomShares); + $shares = array_merge($groupShares, $roomShares, $deckShares); $shares = array_map(function (IShare $share) { return $this->formatShare($share); @@ -211,6 +220,23 @@ class DeletedShareAPIController extends OCSController { throw new QueryException(); } - return $this->serverContainer->query('\OCA\Talk\Share\Helper\DeletedShareAPIController'); + return $this->serverContainer->get('\OCA\Talk\Share\Helper\DeletedShareAPIController'); + } + + /** + * Returns the helper of ShareAPIHelper for deck shares. + * + * If the Deck application is not enabled or the helper is not available + * a QueryException is thrown instead. + * + * @return \OCA\Deck\Sharing\ShareAPIHelper + * @throws QueryException + */ + private function getDeckShareHelper() { + if (!$this->appManager->isEnabledForUser('deck')) { + throw new QueryException(); + } + + return $this->serverContainer->get('\OCA\Deck\Sharing\ShareAPIHelper'); } } diff --git a/apps/files_sharing/lib/Controller/ShareAPIController.php b/apps/files_sharing/lib/Controller/ShareAPIController.php index aaca16b32e6cedcd40ed4e3df04615e308f54a2c..65de654be92e636834911121bc42848a23e0c561 100644 --- a/apps/files_sharing/lib/Controller/ShareAPIController.php +++ b/apps/files_sharing/lib/Controller/ShareAPIController.php @@ -303,6 +303,14 @@ class ShareAPIController extends OCSController { $result = array_merge($result, $this->getRoomShareHelper()->formatShare($share)); } catch (QueryException $e) { } + } elseif ($share->getShareType() === IShare::TYPE_DECK) { + $result['share_with'] = $share->getSharedWith(); + $result['share_with_displayname'] = ''; + + try { + $result = array_merge($result, $this->getDeckShareHelper()->formatShare($share)); + } catch (QueryException $e) { + } } @@ -603,6 +611,12 @@ class ShareAPIController extends OCSController { } catch (QueryException $e) { throw new OCSForbiddenException($this->l->t('Sharing %s failed because the back end does not support room shares', [$path->getPath()])); } + } elseif ($shareType === IShare::TYPE_DECK) { + try { + $this->getDeckShareHelper()->createShare($share, $shareWith, $permissions, $expireDate); + } catch (QueryException $e) { + throw new OCSForbiddenException($this->l->t('Sharing %s failed because the back end does not support room shares', [$path->getPath()])); + } } else { throw new OCSBadRequestException($this->l->t('Unknown share type')); } @@ -635,8 +649,9 @@ class ShareAPIController extends OCSController { $groupShares = $this->shareManager->getSharedWith($this->currentUser, IShare::TYPE_GROUP, $node, -1, 0); $circleShares = $this->shareManager->getSharedWith($this->currentUser, IShare::TYPE_CIRCLE, $node, -1, 0); $roomShares = $this->shareManager->getSharedWith($this->currentUser, IShare::TYPE_ROOM, $node, -1, 0); + $deckShares = $this->shareManager->getSharedWith($this->currentUser, IShare::TYPE_DECK, $node, -1, 0); - $shares = array_merge($userShares, $groupShares, $circleShares, $roomShares); + $shares = array_merge($userShares, $groupShares, $circleShares, $roomShares, $deckShares); $filteredShares = array_filter($shares, function (IShare $share) { return $share->getShareOwner() !== $this->currentUser; @@ -1296,6 +1311,14 @@ class ShareAPIController extends OCSController { } } + if ($share->getShareType() === IShare::TYPE_DECK) { + try { + return $this->getDeckShareHelper()->canAccessShare($share, $this->currentUser); + } catch (QueryException $e) { + return false; + } + } + return false; } @@ -1371,7 +1394,8 @@ class ShareAPIController extends OCSController { */ protected function canDeleteShareFromSelf(\OCP\Share\IShare $share): bool { if ($share->getShareType() !== IShare::TYPE_GROUP && - $share->getShareType() !== IShare::TYPE_ROOM + $share->getShareType() !== IShare::TYPE_ROOM && + $share->getShareType() !== IShare::TYPE_DECK ) { return false; } @@ -1400,6 +1424,14 @@ class ShareAPIController extends OCSController { } } + if ($share->getShareType() === IShare::TYPE_DECK) { + try { + return $this->getDeckShareHelper()->canAccessShare($share, $this->currentUser); + } catch (QueryException $e) { + return false; + } + } + return false; } @@ -1474,6 +1506,15 @@ class ShareAPIController extends OCSController { // Do nothing, just try the other share type } + try { + if ($this->shareManager->shareProviderExists(IShare::TYPE_DECK)) { + $share = $this->shareManager->getShareById('deck:' . $id, $this->currentUser); + return $share; + } + } catch (ShareNotFound $e) { + // Do nothing, just try the other share type + } + if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) { throw new ShareNotFound(); } @@ -1517,9 +1558,25 @@ class ShareAPIController extends OCSController { throw new QueryException(); } - return $this->serverContainer->query('\OCA\Talk\Share\Helper\ShareAPIController'); + return $this->serverContainer->get('\OCA\Talk\Share\Helper\ShareAPIController'); } + /** + * Returns the helper of ShareAPIHelper for deck shares. + * + * If the Deck application is not enabled or the helper is not available + * a QueryException is thrown instead. + * + * @return \OCA\Deck\Sharing\ShareAPIHelper + * @throws QueryException + */ + private function getDeckShareHelper() { + if (!$this->appManager->isEnabledForUser('deck')) { + throw new QueryException(); + } + + return $this->serverContainer->get('\OCA\Deck\Sharing\ShareAPIHelper'); + } /** * @param string $viewer @@ -1536,7 +1593,8 @@ class ShareAPIController extends OCSController { IShare::TYPE_EMAIL, IShare::TYPE_EMAIL, IShare::TYPE_CIRCLE, - IShare::TYPE_ROOM + IShare::TYPE_ROOM, + IShare::TYPE_DECK ]; // Should we assume that the (currentUser) viewer is the owner of the node !? @@ -1689,6 +1747,8 @@ class ShareAPIController extends OCSController { // 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); + // FEDERATION if ($this->shareManager->outgoingServer2ServerSharesAllowed()) { $federatedShares = $this->shareManager->getSharesBy($this->currentUser, IShare::TYPE_REMOTE, $path, $reshares, -1, 0); @@ -1701,7 +1761,7 @@ class ShareAPIController extends OCSController { $federatedGroupShares = []; } - return array_merge($userShares, $groupShares, $linkShares, $mailShares, $circleShares, $roomShares, $federatedShares, $federatedGroupShares); + return array_merge($userShares, $groupShares, $linkShares, $mailShares, $circleShares, $roomShares, $deckShares, $federatedShares, $federatedGroupShares); } diff --git a/apps/files_sharing/lib/Controller/ShareesAPIController.php b/apps/files_sharing/lib/Controller/ShareesAPIController.php index 0509ba72f1ab951557e4d3be426fad892b304855..a2b39b407724923a723e85725a67919867b233ce 100644 --- a/apps/files_sharing/lib/Controller/ShareesAPIController.php +++ b/apps/files_sharing/lib/Controller/ShareesAPIController.php @@ -83,6 +83,7 @@ class ShareesAPIController extends OCSController { 'emails' => [], 'circles' => [], 'rooms' => [], + 'deck' => [], ], 'users' => [], 'groups' => [], @@ -92,6 +93,7 @@ class ShareesAPIController extends OCSController { 'lookup' => [], 'circles' => [], 'rooms' => [], + 'deck' => [], 'lookupEnabled' => false, ]; @@ -183,6 +185,10 @@ class ShareesAPIController extends OCSController { if ($this->shareManager->shareProviderExists(IShare::TYPE_ROOM)) { $shareTypes[] = IShare::TYPE_ROOM; } + + if ($this->shareManager->shareProviderExists(IShare::TYPE_DECK)) { + $shareTypes[] = IShare::TYPE_DECK; + } } else { $shareTypes[] = IShare::TYPE_GROUP; $shareTypes[] = IShare::TYPE_EMAIL; @@ -193,6 +199,10 @@ class ShareesAPIController extends OCSController { $shareTypes[] = IShare::TYPE_CIRCLE; } + if ($this->shareManager->shareProviderExists(IShare::TYPE_DECK)) { + $shareTypes[] = IShare::TYPE_DECK; + } + if ($shareType !== null && is_array($shareType)) { $shareTypes = array_intersect($shareTypes, $shareType); } elseif (is_numeric($shareType)) { diff --git a/apps/files_sharing/lib/MountProvider.php b/apps/files_sharing/lib/MountProvider.php index 3e703a4a6bb81904eb37d11ad4897c5c81ea1784..3ab3185b95e25499afe083f77b317b014328d9a6 100644 --- a/apps/files_sharing/lib/MountProvider.php +++ b/apps/files_sharing/lib/MountProvider.php @@ -78,6 +78,8 @@ class MountProvider implements IMountProvider { $shares = array_merge($shares, $this->shareManager->getSharedWith($user->getUID(), IShare::TYPE_GROUP, null, -1)); $shares = array_merge($shares, $this->shareManager->getSharedWith($user->getUID(), IShare::TYPE_CIRCLE, null, -1)); $shares = array_merge($shares, $this->shareManager->getSharedWith($user->getUID(), IShare::TYPE_ROOM, null, -1)); + $shares = array_merge($shares, $this->shareManager->getSharedWith($user->getUID(), IShare::TYPE_DECK, null, -1)); + // filter out excluded shares and group shares that includes self $shares = array_filter($shares, function (\OCP\Share\IShare $share) use ($user) { diff --git a/apps/files_sharing/src/components/SharingEntry.vue b/apps/files_sharing/src/components/SharingEntry.vue index 55bdbb8fdcb19d4483195714feaa8648d076a7c7..407221037dcb0ee7230bce024a548822195338ad 100644 --- a/apps/files_sharing/src/components/SharingEntry.vue +++ b/apps/files_sharing/src/components/SharingEntry.vue @@ -29,13 +29,16 @@ :tooltip-message="share.type === SHARE_TYPES.SHARE_TYPE_USER ? share.shareWith : ''" :menu-position="'left'" :url="share.shareWithAvatar" /> - <div v-tooltip.auto="tooltip" class="sharing-entry__desc"> + <component :is="share.shareWithLink ? 'a' : 'div'" + :href="share.shareWithLink" + v-tooltip.auto="tooltip" + class="sharing-entry__desc"> <h5>{{ title }}</h5> <p v-if="hasStatus"> <span>{{ share.status.icon || '' }}</span> <span>{{ share.status.message || '' }}</span> </p> - </div> + </component> <Actions menu-align="right" class="sharing-entry__actions" diff --git a/apps/files_sharing/src/components/SharingInput.vue b/apps/files_sharing/src/components/SharingInput.vue index 588ed6341663695dddb6a60217c6e74ba090264f..c8373c6c0aee3bd3936975061f5b538f638f0d87 100644 --- a/apps/files_sharing/src/components/SharingInput.vue +++ b/apps/files_sharing/src/components/SharingInput.vue @@ -186,6 +186,7 @@ export default { this.SHARE_TYPES.SHARE_TYPE_CIRCLE, this.SHARE_TYPES.SHARE_TYPE_ROOM, this.SHARE_TYPES.SHARE_TYPE_GUEST, + this.SHARE_TYPES.SHARE_TYPE_DECK, ] if (OC.getCapabilities().files_sharing.public.enabled === true) { @@ -365,6 +366,8 @@ export default { return 'icon-circle' case this.SHARE_TYPES.SHARE_TYPE_ROOM: return 'icon-room' + case this.SHARE_TYPES.SHARE_TYPE_DECK: + return 'icon-deck' default: return '' @@ -384,6 +387,8 @@ export default { desc = t('files_sharing', 'on {server}', { server: result.value.server }) } else if (result.value.shareType === this.SHARE_TYPES.SHARE_TYPE_EMAIL) { desc = result.value.shareWith + } else { + desc = result.shareWithDescription ?? '' } return { diff --git a/apps/files_sharing/src/index.js b/apps/files_sharing/src/index.js index 786b648aea1c7d74a6a027694ae853f3ba6959b0..3c0d0e65c8f0035d1659f8fe5de03d59fd2565de 100644 --- a/apps/files_sharing/src/index.js +++ b/apps/files_sharing/src/index.js @@ -32,5 +32,6 @@ Object.assign(OC, { SHARE_TYPE_GUEST: 8, SHARE_TYPE_REMOTE_GROUP: 9, SHARE_TYPE_ROOM: 10, + SHARE_TYPE_DECK: 12, }, }) diff --git a/apps/files_sharing/src/mixins/ShareTypes.js b/apps/files_sharing/src/mixins/ShareTypes.js index b84dbf96d98333c49474d9bbf6845d8604a51132..6e9524ce95264f5155cfb83b8bf3f6e49511a2c5 100644 --- a/apps/files_sharing/src/mixins/ShareTypes.js +++ b/apps/files_sharing/src/mixins/ShareTypes.js @@ -31,6 +31,7 @@ export default { SHARE_TYPE_REMOTE: OC.Share.SHARE_TYPE_REMOTE, SHARE_TYPE_CIRCLE: OC.Share.SHARE_TYPE_CIRCLE, SHARE_TYPE_GUEST: OC.Share.SHARE_TYPE_GUEST, + SHARE_TYPE_DECK: OC.Share.SHARE_TYPE_DECK, SHARE_TYPE_REMOTE_GROUP: OC.Share.SHARE_TYPE_REMOTE_GROUP, SHARE_TYPE_ROOM: OC.Share.SHARE_TYPE_ROOM, }, diff --git a/apps/files_sharing/src/models/Share.js b/apps/files_sharing/src/models/Share.js index 07f74652a442e47946648ca15167e9c185e01069..d36484f064ac26d9cd156b23eca84242576957d7 100644 --- a/apps/files_sharing/src/models/Share.js +++ b/apps/files_sharing/src/models/Share.js @@ -150,6 +150,17 @@ export default class Share { || this.#share.share_with } + /** + * Get the share with entity link + * + * @returns {string} + * @readonly + * @memberof Share + */ + get shareWithLink() { + return this.#share.share_with_link + } + /** * Get the share with avatar if any * diff --git a/apps/files_sharing/src/share.js b/apps/files_sharing/src/share.js index 7d5aeec42249cf16d6bea0799625bbc1aadeca77..47c57e70b6c94243b00dc9a3d3e7a4e722494ffb 100644 --- a/apps/files_sharing/src/share.js +++ b/apps/files_sharing/src/share.js @@ -161,6 +161,8 @@ import escapeHTML from 'escape-html' hasShares = true } else if (shareType === OC.Share.SHARE_TYPE_ROOM) { hasShares = true + } else if (shareType === OC.Share.SHARE_TYPE_DECK) { + hasShares = true } }) OCA.Sharing.Util._updateFileActionIcon($tr, hasShares, hasLink) diff --git a/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php b/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php index 1759e532810e57212ba1712fb60498a98645a1ce..a2a6ab59809d81bd19c00abde02f9a1b1509c3bf 100644 --- a/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php +++ b/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php @@ -196,10 +196,10 @@ class ShareAPIControllerTest extends TestCase { $this->expectExceptionMessage('Wrong share ID, share doesn\'t exist'); $this->shareManager - ->expects($this->exactly(5)) + ->expects($this->exactly(6)) ->method('getShareById') ->willReturnCallback(function ($id) { - if ($id === 'ocinternal:42' || $id === 'ocRoomShare:42' || $id === 'ocFederatedSharing:42' || $id === 'ocCircleShare:42' || $id === 'ocMailShare:42') { + if ($id === 'ocinternal:42' || $id === 'ocRoomShare:42' || $id === 'ocFederatedSharing:42' || $id === 'ocCircleShare:42' || $id === 'ocMailShare:42' || $id === 'deck:42') { throw new \OCP\Share\Exceptions\ShareNotFound(); } else { throw new \Exception(); @@ -1558,7 +1558,7 @@ class ShareAPIControllerTest extends TestCase { ->with($share, $this->currentUser) ->willReturn($canAccessShareByHelper); - $this->serverContainer->method('query') + $this->serverContainer->method('get') ->with('\OCA\Talk\Share\Helper\ShareAPIController') ->willReturn($helper); } @@ -2222,7 +2222,7 @@ class ShareAPIControllerTest extends TestCase { } ); - $this->serverContainer->method('query') + $this->serverContainer->method('get') ->with('\OCA\Talk\Share\Helper\ShareAPIController') ->willReturn($helper); @@ -2340,7 +2340,7 @@ class ShareAPIControllerTest extends TestCase { } ); - $this->serverContainer->method('query') + $this->serverContainer->method('get') ->with('\OCA\Talk\Share\Helper\ShareAPIController') ->willReturn($helper); @@ -4404,7 +4404,7 @@ class ShareAPIControllerTest extends TestCase { ->with($share) ->willReturn($formatShareByHelper); - $this->serverContainer->method('query') + $this->serverContainer->method('get') ->with('\OCA\Talk\Share\Helper\ShareAPIController') ->willReturn($helper); } diff --git a/apps/files_sharing/tests/MountProviderTest.php b/apps/files_sharing/tests/MountProviderTest.php index c7116230813a447d7d6a2b834a6fd910be27579f..f40bd44331e5d45134c8ef1823c6d981b5ba3976 100644 --- a/apps/files_sharing/tests/MountProviderTest.php +++ b/apps/files_sharing/tests/MountProviderTest.php @@ -123,6 +123,12 @@ class MountProviderTest extends \Test\TestCase { $this->makeMockShare(8, 102, 'user2', '/share6', 31), $this->makeMockShare(9, 102, 'user2', '/share6', 31), ]; + $deckShares = [ + $this->makeMockShare(10, 103, 'user2', '/share7', 0), + $this->makeMockShare(11, 103, 'user1', '/share7', 31), + $this->makeMockShare(12, 103, 'user2', '/share7', 31), + $this->makeMockShare(13, 103, 'user2', '/share7', 31), + ]; // tests regarding circles are made in the app itself. $circleShares = []; $this->user->expects($this->any()) @@ -144,16 +150,21 @@ class MountProviderTest extends \Test\TestCase { ->method('getSharedWith') ->with('user1', IShare::TYPE_ROOM, null, -1) ->willReturn($roomShares); + $this->shareManager->expects($this->at(4)) + ->method('getSharedWith') + ->with('user1', IShare::TYPE_DECK, null, -1) + ->willReturn($deckShares); $this->shareManager->expects($this->any()) ->method('newShare') ->willReturnCallback(function () use ($rootFolder, $userManager) { return new \OC\Share20\Share($rootFolder, $userManager); }); $mounts = $this->provider->getMountsForUser($this->user, $this->loader); - $this->assertCount(3, $mounts); + $this->assertCount(4, $mounts); $this->assertInstanceOf('OCA\Files_Sharing\SharedMount', $mounts[0]); $this->assertInstanceOf('OCA\Files_Sharing\SharedMount', $mounts[1]); $this->assertInstanceOf('OCA\Files_Sharing\SharedMount', $mounts[2]); + $this->assertInstanceOf('OCA\Files_Sharing\SharedMount', $mounts[3]); $mountedShare1 = $mounts[0]->getShare(); $this->assertEquals('2', $mountedShare1->getId()); $this->assertEquals('user2', $mountedShare1->getShareOwner()); @@ -172,6 +183,12 @@ class MountProviderTest extends \Test\TestCase { $this->assertEquals(102, $mountedShare3->getNodeId()); $this->assertEquals('/share6', $mountedShare3->getTarget()); $this->assertEquals(31, $mountedShare3->getPermissions()); + $mountedShare4 = $mounts[3]->getShare(); + $this->assertEquals('12', $mountedShare4->getId()); + $this->assertEquals('user2', $mountedShare4->getShareOwner()); + $this->assertEquals(103, $mountedShare4->getNodeId()); + $this->assertEquals('/share7', $mountedShare4->getTarget()); + $this->assertEquals(31, $mountedShare4->getPermissions()); } public function mergeSharesDataProvider() { @@ -337,6 +354,7 @@ class MountProviderTest extends \Test\TestCase { // tests regarding circles are made in the app itself. $circleShares = []; $roomShares = []; + $deckShares = []; $this->shareManager->expects($this->at(0)) ->method('getSharedWith') ->with('user1', IShare::TYPE_USER) @@ -353,6 +371,10 @@ class MountProviderTest extends \Test\TestCase { ->method('getSharedWith') ->with('user1', IShare::TYPE_ROOM, null, -1) ->willReturn($roomShares); + $this->shareManager->expects($this->at(4)) + ->method('getSharedWith') + ->with('user1', IShare::TYPE_DECK, null, -1) + ->willReturn($deckShares); $this->shareManager->expects($this->any()) ->method('newShare') ->willReturnCallback(function () use ($rootFolder, $userManager) { diff --git a/build/psalm-baseline.xml b/build/psalm-baseline.xml index 68690455ad37d8f05206459943af3e3e35c628c3..cdbd0dc677154bc2b5bf497b39cd38f5abc31fd5 100644 --- a/build/psalm-baseline.xml +++ b/build/psalm-baseline.xml @@ -1613,12 +1613,6 @@ <code>getUserFolder</code> </UndefinedInterfaceMethod> </file> - <file src="apps/files_sharing/lib/Controller/DeletedShareAPIController.php"> - <UndefinedDocblockClass occurrences="2"> - <code>$this->getRoomShareHelper()</code> - <code>\OCA\Talk\Share\Helper\DeletedShareAPIController</code> - </UndefinedDocblockClass> - </file> <file src="apps/files_sharing/lib/Controller/ShareAPIController.php"> <InvalidScalarArgument occurrences="3"> <code>$code</code> @@ -5051,16 +5045,13 @@ <code>FederatedShareProvider</code> <code>ShareByMailProvider</code> </InvalidNullableReturnType> - <InvalidReturnStatement occurrences="5"> + <InvalidReturnStatement occurrences="4"> <code>$provider</code> <code>$provider</code> - <code>$shares</code> <code>$this->roomShareProvider</code> <code>$this->shareByCircleProvider</code> </InvalidReturnStatement> - <InvalidReturnType occurrences="3"> - <code>getAllProviders</code> - <code>getProvider</code> + <InvalidReturnType occurrences="1"> <code>getProviderForType</code> </InvalidReturnType> <NullableReturnStatement occurrences="6"> diff --git a/lib/private/Share/Constants.php b/lib/private/Share/Constants.php index 2310859c5bebb35fd08cae41adc6b3a3cb179f14..77ed31762770b82a537219ed919c6402e6e59923 100644 --- a/lib/private/Share/Constants.php +++ b/lib/private/Share/Constants.php @@ -70,6 +70,11 @@ class Constants { */ public const SHARE_TYPE_ROOM = 10; // const SHARE_TYPE_USERROOM = 11; // Internal type used by RoomShareProvider + /** + * @deprecated 21.0.0 - use IShare::TYPE_DECK instead + */ + public const SHARE_TYPE_DECK = 12; + // const SHARE_TYPE_DECK_USER = 13; // Internal type used by DeckShareProvider public const FORMAT_NONE = -1; public const FORMAT_STATUSES = -2; diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php index e9895edf95aeefb564b7315da170c37b4daa5c25..6b782237b8c454499384b7f1db465c473d42d85d 100644 --- a/lib/private/Share20/Manager.php +++ b/lib/private/Share20/Manager.php @@ -248,6 +248,7 @@ class Manager implements IManager { throw new \InvalidArgumentException('SharedWith is not a valid circle'); } } elseif ($share->getShareType() === IShare::TYPE_ROOM) { + } elseif ($share->getShareType() === IShare::TYPE_DECK) { } else { // We can't handle other types yet throw new \InvalidArgumentException('unknown share type'); @@ -1887,6 +1888,10 @@ class Manager implements IManager { return true; } + public function registerShareProvider(string $shareProviderClass): void { + $this->factory->registerProvider($shareProviderClass); + } + public function getAllShares(): iterable { $providers = $this->factory->getAllProviders(); diff --git a/lib/private/Share20/ProviderFactory.php b/lib/private/Share20/ProviderFactory.php index 2d4c4e6d40a5cb4f4acb2e3ad610f4cf98897917..9f93df46ac042a624171f860bee17e6cdcdb8bfd 100644 --- a/lib/private/Share20/ProviderFactory.php +++ b/lib/private/Share20/ProviderFactory.php @@ -44,6 +44,7 @@ use OCP\EventDispatcher\IEventDispatcher; use OCP\IServerContainer; use OCP\Share\IProviderFactory; use OCP\Share\IShare; +use OCP\Share\IShareProvider; /** * Class ProviderFactory @@ -67,6 +68,10 @@ class ProviderFactory implements IProviderFactory { /** @var \OCA\Talk\Share\RoomShareProvider */ private $roomShareProvider = null; + private $registeredShareProviders = []; + + private $shareProviders = []; + /** * IProviderFactory constructor. * @@ -76,6 +81,10 @@ class ProviderFactory implements IProviderFactory { $this->serverContainer = $serverContainer; } + public function registerProvider(string $shareProviderClass): void { + $this->registeredShareProviders[] = $shareProviderClass; + } + /** * Create the default share provider. * @@ -257,6 +266,10 @@ class ProviderFactory implements IProviderFactory { */ public function getProvider($id) { $provider = null; + if (isset($this->shareProviders[$id])) { + return $this->shareProviders[$id]; + } + if ($id === 'ocinternal') { $provider = $this->defaultShareProvider(); } elseif ($id === 'ocFederatedSharing') { @@ -269,6 +282,16 @@ class ProviderFactory implements IProviderFactory { $provider = $this->getRoomShareProvider(); } + foreach ($this->registeredShareProviders as $shareProvider) { + /** @var IShareProvider $instance */ + $instance = $this->serverContainer->get($shareProvider); + $this->shareProviders[$instance->identifier()] = $instance; + } + + if (isset($this->shareProviders[$id])) { + $provider = $this->shareProviders[$id]; + } + if ($provider === null) { throw new ProviderException('No provider with id .' . $id . ' found.'); } @@ -295,6 +318,8 @@ class ProviderFactory implements IProviderFactory { $provider = $this->getShareByCircleProvider(); } elseif ($shareType === IShare::TYPE_ROOM) { $provider = $this->getRoomShareProvider(); + } elseif ($shareType === IShare::TYPE_DECK) { + $provider = $this->getProvider('deck'); } @@ -320,6 +345,17 @@ class ProviderFactory implements IProviderFactory { $shares[] = $roomShare; } + foreach ($this->registeredShareProviders as $shareProvider) { + /** @var IShareProvider $instance */ + $instance = $this->serverContainer->get($shareProvider); + if (!isset($this->shareProviders[$instance->identifier()])) { + $this->shareProviders[$instance->identifier()] = $instance; + } + $shares[] = $this->shareProviders[$instance->identifier()]; + } + + + return $shares; } } diff --git a/lib/public/Share/IManager.php b/lib/public/Share/IManager.php index cc2ec45cc9f994f1c0f79a57dc44aba44e6d4fbc..635ccc1483d68d264d10db67f6b2968e3cfa7499 100644 --- a/lib/public/Share/IManager.php +++ b/lib/public/Share/IManager.php @@ -416,6 +416,12 @@ interface IManager { */ public function shareProviderExists($shareType); + /** + * @param string $shareProviderClass + * @since 21.0.0 + */ + public function registerShareProvider(string $shareProviderClass): void; + /** * @Internal * diff --git a/lib/public/Share/IProviderFactory.php b/lib/public/Share/IProviderFactory.php index 27218497e53099c91782900080831715d61c3fbf..480837404f01d5f0bba05f53048a36dda98720c4 100644 --- a/lib/public/Share/IProviderFactory.php +++ b/lib/public/Share/IProviderFactory.php @@ -53,4 +53,10 @@ interface IProviderFactory { * @since 11.0.0 */ public function getAllProviders(); + + /** + * @since 21.0.0 + * @param string $shareProvier + */ + public function registerProvider(string $shareProvier): void; } diff --git a/lib/public/Share/IShare.php b/lib/public/Share/IShare.php index 7b38e00df46215b5b7a77e751e1c05cb55eed9bd..86aceba80f5326ae18bee1825e2a4dbd5ec389da 100644 --- a/lib/public/Share/IShare.php +++ b/lib/public/Share/IShare.php @@ -105,6 +105,17 @@ interface IShare { */ // const TYPE_USERROOM = 11; + /** + * @since 21.0.0 + */ + public const TYPE_DECK = 12; + + /** + * @internal + * @since 21.0.0 + */ + public const TYPE_DECK_USER = 13; + /** * @since 18.0.0 */ diff --git a/psalm.xml b/psalm.xml index b90af78022a8b9c8d66be987cc2ce2111d9a22b2..0706f566829ee6ef783df5d6856320c32707ee4d 100644 --- a/psalm.xml +++ b/psalm.xml @@ -85,5 +85,12 @@ <file name="core/register_command.php" /> </errorLevel> </UndefinedGlobalVariable> + <UndefinedDocblockClass> + <errorLevel type="suppress"> + <!-- Helper classes for sharing API integration from other apps --> + <referencedClass name="OCA\Deck\Sharing\ShareAPIHelper" /> + <referencedClass name="OCA\Talk\Share\Helper\DeletedShareAPIController" /> + </errorLevel> + </UndefinedDocblockClass> </issueHandlers> </psalm> diff --git a/tests/lib/Share20/ManagerTest.php b/tests/lib/Share20/ManagerTest.php index 65313858c01d751067b4b14f5926c680ad8ef249..efae909b99f32c3e0832ad71a5cfe54ab5f250a5 100644 --- a/tests/lib/Share20/ManagerTest.php +++ b/tests/lib/Share20/ManagerTest.php @@ -4362,6 +4362,9 @@ class DummyFactory implements IProviderFactory { public function getAllProviders() { return [$this->provider]; } + + public function registerProvider(string $shareProvier): void { + } } class DummyFactory2 extends DummyFactory { @@ -4378,4 +4381,7 @@ class DummyFactory2 extends DummyFactory { public function getAllProviders() { return [$this->provider, $this->provider2]; } + + public function registerProvider(string $shareProvier): void { + } }