From a747539ab46f6b00ddbd4aa0db12b7e1f18d9cc2 Mon Sep 17 00:00:00 2001 From: Christoph Bessei <28066477+christoph-bessei@users.noreply.github.com> Date: Sun, 23 Aug 2026 12:28:28 +0200 Subject: [PATCH 1/2] Fix #254 - Embedding files can fail, when storage has multiple shared mounts Signed-off-by: Christoph Bessei <28066477+christoph-bessei@users.noreply.github.com> --- lib/Controller/QueueController.php | 17 ++- tests/integration/QueueControllerTest.php | 139 ++++++++++++++++++++++ 2 files changed, 150 insertions(+), 6 deletions(-) create mode 100644 tests/integration/QueueControllerTest.php diff --git a/lib/Controller/QueueController.php b/lib/Controller/QueueController.php index 59ae1521..301398e9 100644 --- a/lib/Controller/QueueController.php +++ b/lib/Controller/QueueController.php @@ -290,12 +290,17 @@ private function getFileSource(QueueFile $document, IRootFolder $rootFolder, Sto if (empty($mounts)) { throw new \Exception('Couldn\'t find any mounts for this storage'); } - $userId = $mounts[0]->getUser()->getUID(); - - try { - $file = $rootFolder->getUserFolder($userId)->getFirstNodeById($document->getFileId()); - } catch (NotPermittedException $e) { - throw new \Exception('Not allowed to get user folder'); + $file = null; + foreach ($mounts as $mount) { + $userId = $mount->getUser()->getUID(); + try { + $file = $rootFolder->getUserFolder($userId)->getFirstNodeById($document->getFileId()); + } catch (NotPermittedException $e) { + throw new \Exception('Not allowed to get user folder'); + } + if ($file instanceof File) { + break; + } } if (!($file instanceof File)) { throw new \Exception('File not found or not a file'); diff --git a/tests/integration/QueueControllerTest.php b/tests/integration/QueueControllerTest.php new file mode 100644 index 00000000..171fbce6 --- /dev/null +++ b/tests/integration/QueueControllerTest.php @@ -0,0 +1,139 @@ +setId(7); + $document->setFileId(42); + $document->setStorageId(3); + + $queueMapper = $this->createMock(QueueMapper::class); + $queueMapper->expects($this->once()) + ->method('getFromQueue') + ->with(1) + ->willReturn([$document]); + $queueMapper->expects($this->once()) + ->method('lock') + ->with(7) + ->willReturn(true); + $queueMapper->expects($this->never()) + ->method('delete'); + + $contentItemMapper = $this->createMock(QueueContentItemMapper::class); + $contentItemMapper->expects($this->once()) + ->method('getFromQueue') + ->with(1) + ->willReturn([]); + + $wrongMount = $this->createMock(ICachedMountInfo::class); + $wrongUser = $this->createMock(IUser::class); + $wrongUser->method('getUID')->willReturn('wrong-user'); + $wrongMount->method('getUser')->willReturn($wrongUser); + + $validMount = $this->createMock(ICachedMountInfo::class); + $validUser = $this->createMock(IUser::class); + $validUser->method('getUID')->willReturn('valid-user'); + $validMount->method('getUser')->willReturn($validUser); + + $userMountCache = $this->createMock(IUserMountCache::class); + $userMountCache->expects($this->once()) + ->method('getMountsForStorageId') + ->with(3) + ->willReturn([$wrongMount, $validMount]); + + $wrongFolder = $this->createMock(Folder::class); + $wrongFolder->expects($this->once()) + ->method('getFirstNodeById') + ->with(42) + ->willReturn(null); + + $file = $this->createMock(File::class); + $file->method('getId')->willReturn(42); + $file->method('getInternalPath')->willReturn('files/Test-Text.md'); + $file->method('getMTime')->willReturn(1234567890); + $file->method('getMimeType')->willReturn('text/markdown'); + $file->method('getSize')->willReturn(123); + + $validFolder = $this->createMock(Folder::class); + $validFolder->expects($this->once()) + ->method('getFirstNodeById') + ->with(42) + ->willReturn($file); + + $rootFolder = $this->createMock(IRootFolder::class); + $rootFolder->expects($this->exactly(2)) + ->method('getUserFolder') + ->willReturnMap([ + ['wrong-user', $wrongFolder], + ['valid-user', $validFolder], + ]); + + $storageService = $this->createMock(StorageService::class); + $storageService->expects($this->once()) + ->method('getUsersForFileId') + ->with(42) + ->willReturn(['valid-user']); + + $controller = new QueueController( + 'context_chat', + $this->createMock(IRequest::class), + $this->createMock(LoggerInterface::class), + $this->createMock(IAppConfig::class), + $this->createMock(QueueService::class), + $storageService, + $this->createMock(IJobList::class), + $this->createMock(ITimeFactory::class), + $queueMapper, + ); + + $response = $controller->getDocumentsQueueItems( + $storageService, + $rootFolder, + $queueMapper, + $contentItemMapper, + $userMountCache, + 1, + ); + + $data = $response->getData(); + $this->assertEquals([ + 'userIds' => ['valid-user'], + 'reference' => ProviderConfigService::getSourceId(42), + 'title' => 'files/Test-Text.md', + 'content' => null, + 'modified' => 1234567890, + 'type' => 'text/markdown', + 'provider' => ProviderConfigService::getDefaultProviderKey(), + 'size' => 123, + ], ((array)$data['files'])[7]->jsonSerialize()); + } +} From 0c9178381ef22ac975f246baf31660abc95cc12c Mon Sep 17 00:00:00 2001 From: Christoph Bessei <28066477+christoph-bessei@users.noreply.github.com> Date: Mon, 24 Aug 2026 12:21:58 +0200 Subject: [PATCH 2/2] Fix #254 - Embedding files can fail, when storage has multiple shared mounts Signed-off-by: Christoph Bessei <28066477+christoph-bessei@users.noreply.github.com> --- tests/integration/QueueControllerTest.php | 139 ---------------------- 1 file changed, 139 deletions(-) delete mode 100644 tests/integration/QueueControllerTest.php diff --git a/tests/integration/QueueControllerTest.php b/tests/integration/QueueControllerTest.php deleted file mode 100644 index 171fbce6..00000000 --- a/tests/integration/QueueControllerTest.php +++ /dev/null @@ -1,139 +0,0 @@ -setId(7); - $document->setFileId(42); - $document->setStorageId(3); - - $queueMapper = $this->createMock(QueueMapper::class); - $queueMapper->expects($this->once()) - ->method('getFromQueue') - ->with(1) - ->willReturn([$document]); - $queueMapper->expects($this->once()) - ->method('lock') - ->with(7) - ->willReturn(true); - $queueMapper->expects($this->never()) - ->method('delete'); - - $contentItemMapper = $this->createMock(QueueContentItemMapper::class); - $contentItemMapper->expects($this->once()) - ->method('getFromQueue') - ->with(1) - ->willReturn([]); - - $wrongMount = $this->createMock(ICachedMountInfo::class); - $wrongUser = $this->createMock(IUser::class); - $wrongUser->method('getUID')->willReturn('wrong-user'); - $wrongMount->method('getUser')->willReturn($wrongUser); - - $validMount = $this->createMock(ICachedMountInfo::class); - $validUser = $this->createMock(IUser::class); - $validUser->method('getUID')->willReturn('valid-user'); - $validMount->method('getUser')->willReturn($validUser); - - $userMountCache = $this->createMock(IUserMountCache::class); - $userMountCache->expects($this->once()) - ->method('getMountsForStorageId') - ->with(3) - ->willReturn([$wrongMount, $validMount]); - - $wrongFolder = $this->createMock(Folder::class); - $wrongFolder->expects($this->once()) - ->method('getFirstNodeById') - ->with(42) - ->willReturn(null); - - $file = $this->createMock(File::class); - $file->method('getId')->willReturn(42); - $file->method('getInternalPath')->willReturn('files/Test-Text.md'); - $file->method('getMTime')->willReturn(1234567890); - $file->method('getMimeType')->willReturn('text/markdown'); - $file->method('getSize')->willReturn(123); - - $validFolder = $this->createMock(Folder::class); - $validFolder->expects($this->once()) - ->method('getFirstNodeById') - ->with(42) - ->willReturn($file); - - $rootFolder = $this->createMock(IRootFolder::class); - $rootFolder->expects($this->exactly(2)) - ->method('getUserFolder') - ->willReturnMap([ - ['wrong-user', $wrongFolder], - ['valid-user', $validFolder], - ]); - - $storageService = $this->createMock(StorageService::class); - $storageService->expects($this->once()) - ->method('getUsersForFileId') - ->with(42) - ->willReturn(['valid-user']); - - $controller = new QueueController( - 'context_chat', - $this->createMock(IRequest::class), - $this->createMock(LoggerInterface::class), - $this->createMock(IAppConfig::class), - $this->createMock(QueueService::class), - $storageService, - $this->createMock(IJobList::class), - $this->createMock(ITimeFactory::class), - $queueMapper, - ); - - $response = $controller->getDocumentsQueueItems( - $storageService, - $rootFolder, - $queueMapper, - $contentItemMapper, - $userMountCache, - 1, - ); - - $data = $response->getData(); - $this->assertEquals([ - 'userIds' => ['valid-user'], - 'reference' => ProviderConfigService::getSourceId(42), - 'title' => 'files/Test-Text.md', - 'content' => null, - 'modified' => 1234567890, - 'type' => 'text/markdown', - 'provider' => ProviderConfigService::getDefaultProviderKey(), - 'size' => 123, - ], ((array)$data['files'])[7]->jsonSerialize()); - } -}