From 99135d6c474e54ff3cb063c7385b8a38b5994ab0 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Mon, 5 Jan 2026 18:09:22 -0300 Subject: [PATCH 1/3] feat: Add support for nodeId validation in ValidateHelper Support validating files by Nextcloud nodeId in addition to LibreSign fileId. This enables creating signature requests for files that haven't been registered in LibreSign yet. The validateFile method now accepts 'nodeId' parameter and validates it similarly to 'fileId', ensuring the file exists and has the correct MIME type. Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- lib/Helper/ValidateHelper.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/Helper/ValidateHelper.php b/lib/Helper/ValidateHelper.php index ac4b1d55e8..876fd4bd88 100644 --- a/lib/Helper/ValidateHelper.php +++ b/lib/Helper/ValidateHelper.php @@ -125,6 +125,17 @@ public function validateFile(array $data, int $type = self::TYPE_TO_SIGN, ?IUser } $this->validateIfNodeIdExists((int)$data['file']['fileId'], $data['userManager']->getUID(), $type); $this->validateMimeTypeAcceptedByNodeId((int)$data['file']['fileId'], $data['userManager']->getUID(), $type); + } elseif (!empty($data['file']['nodeId'])) { + if (!is_numeric($data['file']['nodeId'])) { + throw new LibresignException($this->l10n->t('File type: %s. Invalid fileID.', [$this->getTypeOfFile($type)])); + } + if (!is_a($user, IUser::class)) { + if (!is_a($data['userManager'], IUser::class)) { + throw new LibresignException($this->l10n->t('User not found.')); + } + } + $this->validateIfNodeIdExists((int)$data['file']['nodeId'], $data['userManager']->getUID(), $type); + $this->validateMimeTypeAcceptedByNodeId((int)$data['file']['nodeId'], $data['userManager']->getUID(), $type); } elseif (!empty($data['file']['base64'])) { $this->validateBase64($data['file']['base64'], $type); } elseif (!empty($data['file']['path'])) { From 27d66f3f1b69fe5fe586e2e520173123f9e57c3b Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Mon, 5 Jan 2026 18:09:57 -0300 Subject: [PATCH 2/3] feat: Add nodeId support in FileService.getNodeFromData Enable FileService to retrieve nodes using Nextcloud nodeId in addition to LibreSign fileId. This allows the service to handle both registered LibreSign files and new Nextcloud files in the same workflow. The method now checks for 'nodeId' after 'fileId' and 'path', maintaining backward compatibility while adding new functionality. Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- lib/Service/FileService.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/Service/FileService.php b/lib/Service/FileService.php index be8211173a..2a5fca7151 100644 --- a/lib/Service/FileService.php +++ b/lib/Service/FileService.php @@ -115,6 +115,9 @@ public function getNodeFromData(array $data): Node { if (isset($data['file']['path'])) { return $this->folderService->getFileByPath($data['file']['path']); } + if (isset($data['file']['nodeId'])) { + return $this->folderService->getFileByNodeId($data['file']['nodeId']); + } $content = $this->getFileRaw($data); $extension = $this->getExtension($content); From 13c4a3bdd0fcbaf5a0350fe4d54c41ef95315225 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Mon, 5 Jan 2026 18:10:25 -0300 Subject: [PATCH 3/3] test: Add unit tests for nodeId validation support Add comprehensive test coverage for: - ValidateHelper nodeId validation (success, invalid nodeId, missing user) - FileService nodeId-based node retrieval - Precedence of fileId over nodeId when both are provided These tests ensure the new nodeId functionality works correctly while maintaining backward compatibility with existing fileId behavior. Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- lib/Helper/ValidateHelper.php | 2 +- tests/php/Unit/Helper/ValidateHelperTest.php | 41 +++++++++++ tests/php/Unit/Service/FileServiceTest.php | 72 ++++++++++++++++++++ 3 files changed, 114 insertions(+), 1 deletion(-) diff --git a/lib/Helper/ValidateHelper.php b/lib/Helper/ValidateHelper.php index 876fd4bd88..39bd95b9ba 100644 --- a/lib/Helper/ValidateHelper.php +++ b/lib/Helper/ValidateHelper.php @@ -130,7 +130,7 @@ public function validateFile(array $data, int $type = self::TYPE_TO_SIGN, ?IUser throw new LibresignException($this->l10n->t('File type: %s. Invalid fileID.', [$this->getTypeOfFile($type)])); } if (!is_a($user, IUser::class)) { - if (!is_a($data['userManager'], IUser::class)) { + if (!isset($data['userManager']) || !is_a($data['userManager'], IUser::class)) { throw new LibresignException($this->l10n->t('User not found.')); } } diff --git a/tests/php/Unit/Helper/ValidateHelperTest.php b/tests/php/Unit/Helper/ValidateHelperTest.php index 7b29c6bff8..28f2aface7 100644 --- a/tests/php/Unit/Helper/ValidateHelperTest.php +++ b/tests/php/Unit/Helper/ValidateHelperTest.php @@ -135,6 +135,47 @@ public function testValidateNewFileUsingFileIdWithSuccess():void { $this->assertNull($actual); } + public function testValidateNewFileUsingNodeIdWithSuccess():void { + $file = $this->createMock(\OCP\Files\File::class); + $file + ->method('getMimeType') + ->willReturn('application/pdf'); + $this->root + ->method('getUserFolder') + ->willReturn($this->root); + $this->root + ->method('getFirstNodeById') + ->willReturn($file); + + $user = $this->createMock(\OCP\IUser::class); + $user->method('getUID')->willReturn('john.doe'); + $actual = $this->getValidateHelper()->validateNewFile([ + 'file' => ['nodeId' => 35523], + 'name' => 'test', + 'userManager' => $user, + ]); + $this->assertNull($actual); + } + + public function testValidateFileWithInvalidNodeId():void { + $this->expectExceptionMessage('Invalid fileID'); + $user = $this->createMock(\OCP\IUser::class); + $user->method('getUID')->willReturn('john.doe'); + $this->getValidateHelper()->validateFile([ + 'file' => ['nodeId' => 'invalid'], + 'name' => 'test', + 'userManager' => $user, + ]); + } + + public function testValidateFileWithNodeIdWithoutUser():void { + $this->expectExceptionMessage('User not found'); + $this->getValidateHelper()->validateFile([ + 'file' => ['nodeId' => 35523], + 'name' => 'test', + ]); + } + public function testValidateNotRequestedSignWhenAlreadyAskedToSignThisDocument():void { $this->signRequestMapper->method('getByNodeId')->willReturn('exists'); $this->expectExceptionMessage('Already asked to sign this document'); diff --git a/tests/php/Unit/Service/FileServiceTest.php b/tests/php/Unit/Service/FileServiceTest.php index 62fdf48b69..c8324f0109 100644 --- a/tests/php/Unit/Service/FileServiceTest.php +++ b/tests/php/Unit/Service/FileServiceTest.php @@ -88,4 +88,76 @@ public function testSetFileByIdSetsFile(): void { $this->assertInstanceOf(FileService::class, $returned); $this->assertSame(1, $service->getStatus()); } + + public function testGetNodeFromDataWithNodeId(): void { + $node = $this->createMock(\OCP\Files\File::class); + $folderService = $this->createMock(\OCA\Libresign\Service\FolderService::class); + $folderService->method('getUserId')->willReturn('testuser'); + $folderService->method('getFileByNodeId')->with(35523)->willReturn($node); + + $userManager = $this->createMock(\OCP\IUser::class); + $userManager->method('getUID')->willReturn('testuser'); + + $service = $this->createFileService([ + \OCA\Libresign\Service\FolderService::class => $folderService, + ]); + + $data = [ + 'file' => ['nodeId' => 35523], + 'userManager' => $userManager, + ]; + + $result = $service->getNodeFromData($data); + $this->assertSame($node, $result); + } + + public function testGetNodeFromDataWithFileId(): void { + $node = $this->createMock(\OCP\Files\File::class); + $folderService = $this->createMock(\OCA\Libresign\Service\FolderService::class); + $folderService->method('getUserId')->willReturn('testuser'); + $folderService->method('getFileByNodeId')->with(12345)->willReturn($node); + + $userManager = $this->createMock(\OCP\IUser::class); + $userManager->method('getUID')->willReturn('testuser'); + + $service = $this->createFileService([ + \OCA\Libresign\Service\FolderService::class => $folderService, + ]); + + $data = [ + 'file' => ['fileId' => 12345], + 'userManager' => $userManager, + ]; + + $result = $service->getNodeFromData($data); + $this->assertSame($node, $result); + } + + public function testGetNodeFromDataPrefersFileIdOverNodeId(): void { + $nodeFromFileId = $this->createMock(\OCP\Files\File::class); + $folderService = $this->createMock(\OCA\Libresign\Service\FolderService::class); + $folderService->method('getUserId')->willReturn('testuser'); + $folderService->expects($this->once()) + ->method('getFileByNodeId') + ->with(12345) + ->willReturn($nodeFromFileId); + + $userManager = $this->createMock(\OCP\IUser::class); + $userManager->method('getUID')->willReturn('testuser'); + + $service = $this->createFileService([ + \OCA\Libresign\Service\FolderService::class => $folderService, + ]); + + $data = [ + 'file' => [ + 'fileId' => 12345, + 'nodeId' => 35523, // This should be ignored + ], + 'userManager' => $userManager, + ]; + + $result = $service->getNodeFromData($data); + $this->assertSame($nodeFromFileId, $result); + } }