diff --git a/apps/files_sharing/lib/Controller/ShareAPIController.php b/apps/files_sharing/lib/Controller/ShareAPIController.php index fb8a702cbd4..2e5ec8ada34 100644 --- a/apps/files_sharing/lib/Controller/ShareAPIController.php +++ b/apps/files_sharing/lib/Controller/ShareAPIController.php @@ -2098,10 +2098,22 @@ class ShareAPIController extends OCSController { $canDownload = false; $hideDownload = true; - $userExplicitlySetHideDownload = $share->getHideDownload(); // Capture user's explicit choice + $userExplicitlySetHideDownload = $share->getHideDownload(); $userFolder = $this->rootFolder->getUserFolder($share->getSharedBy()); $nodes = $userFolder->getById($share->getNodeId()); + + // Fallback: getById fails for federated storage when mount cache is incomplete. + // Use node already set on share during creation. + if (empty($nodes)) { + try { + $node = $share->getNode(); + $nodes = [$node]; + } catch (\Exception $e) { + return; + } + } + foreach ($nodes as $node) { // Owner always can download it - so allow it, but respect their explicit choice about hiding downloads if ($node->getOwner()?->getUID() === $share->getSharedBy()) { diff --git a/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php b/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php index 30a946c7847..5c7774de704 100644 --- a/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php +++ b/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php @@ -5648,4 +5648,33 @@ class ShareAPIControllerTest extends TestCase { $this->invokePrivate($ocs, 'checkInheritedAttributes', [$share]); } + + public function testFederatedStorageFallbackWhenGetByIdEmpty(): void { + $ocs = $this->mockFormatShare(); + + $share = $this->createMock(IShare::class); + $node = $this->createMock(File::class); + $userFolder = $this->createMock(Folder::class); + $owner = $this->createMock(IUser::class); + $storage = $this->createMock(\OCA\Files_Sharing\External\Storage::class); + + $share->method('getSharedBy')->willReturn('sharedByUser'); + $share->method('getNodeId')->willReturn(42); + $share->method('getHideDownload')->willReturn(false); + $share->method('getNode')->willReturn($node); + $node->method('getOwner')->willReturn($owner); + $owner->method('getUID')->willReturn('differentOwner'); + $node->method('getStorage')->willReturn($storage); + $storage->method('instanceOfStorage')->willReturnMap([ + [SharedStorage::class, false], + [\OCA\Files_Sharing\External\Storage::class, true] + ]); + + $userFolder->method('getById')->with(42)->willReturn([]); + $this->rootFolder->method('getUserFolder')->with('sharedByUser')->willReturn($userFolder); + + $share->expects($this->once())->method('setHideDownload')->with(false); + + $this->invokePrivate($ocs, 'checkInheritedAttributes', [$share]); + } }