diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php index 0998e58e27085..c444993646184 100644 --- a/lib/private/Share20/Manager.php +++ b/lib/private/Share20/Manager.php @@ -1402,7 +1402,7 @@ public function getShareByToken($token) { } $share = null; try { - if ($this->shareApiAllowLinks()) { + if ($this->config->getAppValue('core', 'shareapi_allow_links', 'yes') === 'yes') { $provider = $this->factory->getProviderForType(IShare::TYPE_LINK); $share = $provider->getShareByToken($token); } @@ -1485,6 +1485,17 @@ protected function checkShare(IShare $share): void { } } } + + // For link and email shares, verify the share owner can still create such shares + if ($share->getShareType() === IShare::TYPE_LINK || $share->getShareType() === IShare::TYPE_EMAIL) { + $shareOwner = $this->userManager->get($share->getShareOwner()); + if ($shareOwner === null) { + throw new ShareNotFound($this->l->t('The requested share does not exist anymore')); + } + if (!$this->userCanCreateLinkShares($shareOwner)) { + throw new ShareNotFound($this->l->t('The requested share does not exist anymore')); + } + } } /** @@ -1731,14 +1742,15 @@ public function shareApiEnabled() { /** * Is public link sharing enabled * + * @param ?IUser $user User to check against group exclusions, defaults to current session user * @return bool */ - public function shareApiAllowLinks() { + public function shareApiAllowLinks(?IUser $user = null) { if ($this->config->getAppValue('core', 'shareapi_allow_links', 'yes') !== 'yes') { return false; } - $user = $this->userSession->getUser(); + $user = $user ?? $this->userSession->getUser(); if ($user) { $excludedGroups = json_decode($this->config->getAppValue('core', 'shareapi_allow_links_exclude_groups', '[]')); if ($excludedGroups) { @@ -1750,6 +1762,16 @@ public function shareApiAllowLinks() { return true; } + /** + * Check if a specific user can create link shares + * + * @param IUser $user The user to check + * @return bool + */ + protected function userCanCreateLinkShares(IUser $user): bool { + return $this->shareApiAllowLinks($user); + } + /** * Is password on public link requires * diff --git a/lib/public/Share/IManager.php b/lib/public/Share/IManager.php index b07bc8f80515e..e934f6112d159 100644 --- a/lib/public/Share/IManager.php +++ b/lib/public/Share/IManager.php @@ -294,10 +294,12 @@ public function shareApiEnabled(); /** * Is public link sharing enabled * + * @param ?IUser $user User to check against group exclusions, defaults to current session user * @return bool * @since 9.0.0 + * @since 33.0.0 Added optional $user parameter */ - public function shareApiAllowLinks(); + public function shareApiAllowLinks(?IUser $user = null); /** * Is password on public link required diff --git a/tests/lib/Share20/ManagerTest.php b/tests/lib/Share20/ManagerTest.php index 561e7e52bcef0..dff5e8489eafa 100644 --- a/tests/lib/Share20/ManagerTest.php +++ b/tests/lib/Share20/ManagerTest.php @@ -3227,21 +3227,29 @@ public function testGetShareByTokenWithPublicLinksDisabled() { public function testGetShareByTokenPublicUploadDisabled() { $this->config - ->expects($this->exactly(3)) + ->expects($this->exactly(5)) ->method('getAppValue') ->willReturnMap([ ['core', 'shareapi_allow_links', 'yes', 'yes'], ['core', 'shareapi_allow_public_upload', 'yes', 'no'], ['files_sharing', 'hide_disabled_user_shares', 'no', 'no'], + ['core', 'shareapi_allow_links_exclude_groups', '[]', '[]'], ]); $share = $this->manager->newShare(); $share->setShareType(IShare::TYPE_LINK) ->setPermissions(\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE); $share->setSharedWith('sharedWith'); + $share->setShareOwner('shareOwner'); $folder = $this->createMock(\OC\Files\Node\Folder::class); $share->setNode($folder); + $shareOwner = $this->createMock(IUser::class); + $this->userManager->expects($this->once()) + ->method('get') + ->with('shareOwner') + ->willReturn($shareOwner); + $this->defaultProvider->expects($this->once()) ->method('getShareByToken') ->willReturn('validToken')