Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/Controller/FileController.php
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ private function fetchPreview(
*
* @param LibresignNewFile $file File to save
* @param string $name The name of file to sign
* @param LibresignFolderSettings $settings Settings to define the pattern to store the file. See more informations at FolderService::getFolderName method.
* @param LibresignFolderSettings $settings Settings to define how and where the file should be stored
* @param list<LibresignNewFile> $files Multiple files to create an envelope (optional, use either file or files)
* @return DataResponse<Http::STATUS_OK, LibresignNextcloudFile, array{}>|DataResponse<Http::STATUS_UNPROCESSABLE_ENTITY, array{message: string}, array{}>
*
Expand Down
22 changes: 20 additions & 2 deletions lib/Service/EnvelopeService.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,15 @@ public function createEnvelope(string $name, string $userId, int $filesCount = 0

$parentFolder = $this->folderService->getFolder();

$folderName = $name . '_' . substr(UUIDUtil::getUUID(), 0, 8);
$uuid = UUIDUtil::getUUID();
$folderName = $name . '_' . $uuid;
$envelopeFolder = $parentFolder->newFolder($folderName);

$envelope = new FileEntity();
$envelope->setNodeId($envelopeFolder->getId());
$envelope->setNodeTypeEnum(NodeType::ENVELOPE);
$envelope->setName($name);
$envelope->setUuid(UUIDUtil::getUUID());
$envelope->setUuid($uuid);
$envelope->setCreatedAt(new DateTime());
$envelope->setStatus(FileEntity::STATUS_DRAFT);

Expand Down Expand Up @@ -106,6 +107,23 @@ public function getEnvelopeByFileId(int $fileId): ?FileEntity {
}
}

public function getEnvelopeFolder(FileEntity $envelope): \OCP\Files\Folder {
$userId = $envelope->getUserId();
if (!$userId) {
throw new LibresignException('Envelope does not have a user');
}

$this->folderService->setUserId($userId);
$userFolder = $this->folderService->getFolder();

$envelopeFolderNode = $userFolder->getFirstNodeById($envelope->getNodeId());
if (!$envelopeFolderNode instanceof \OCP\Files\Folder) {
throw new LibresignException('Envelope folder not found');
}

return $envelopeFolderNode;
}

private function getMaxFilesPerEnvelope(): int {
return $this->appConfig->getValueInt(Application::APP_ID, 'envelope_max_files', 50);
}
Expand Down
7 changes: 4 additions & 3 deletions lib/Service/File/UploadProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,10 @@ public function getNodeFromUploadedFile(array $data): Node {
$extension = $this->mimeService->getExtension($content);
$this->validateFileContent($content, $extension);

$userFolder = $this->folderService->getFolder();
$folderName = $this->folderService->getFolderName($data, $data['userManager']);
$folderToFile = $userFolder->newFolder($folderName);
$folderToFile = $this->folderService->getFolderForFile($data, $data['userManager']);
if (!$folderToFile instanceof \OCP\Files\Folder) {
throw new LibresignException('Envelope folder not found');
}

@unlink($uploadedFile['tmp_name']);

Expand Down
4 changes: 1 addition & 3 deletions lib/Service/FileService.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,7 @@ public function getNodeFromData(array $data): Node {

$this->validateFileContent($content, $extension);

$userFolder = $this->folderService->getFolder();
$folderName = $this->folderService->getFolderName($data, $data['userManager']);
$folderToFile = $userFolder->newFolder($folderName);
$folderToFile = $this->folderService->getFolderForFile($data, $data['userManager']);
$filename = $this->resolveFileName($data, $extension);
return $folderToFile->newFile($filename, $content);
}
Expand Down
23 changes: 23 additions & 0 deletions lib/Service/FolderService.php
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,29 @@ private function getLibreSignDefaultPath(): string {
return $path;
}

/**
* Get or create the folder where a file should be stored
*
* @param array $data Must contain 'settings' and optionally 'name', 'userManager'
* @param mixed $identifier User or string identifier
* @return Folder The folder where files should be created
* @throws LibresignException
*/
public function getFolderForFile(array $data, $identifier): Folder {
$userFolder = $this->getFolder();

if (isset($data['settings']['envelopeFolderId'])) {
$envelopeFolder = $userFolder->getFirstNodeById($data['settings']['envelopeFolderId']);
if ($envelopeFolder === null || !$envelopeFolder instanceof Folder) {
throw new LibresignException($this->l10n->t('Envelope folder not found'));
}
return $envelopeFolder;
}

$folderName = $this->getFolderName($data, $identifier);
return $userFolder->newFolder($folderName);
}

/**
* @param array{settings: array, name: string} $data
* @param IUser $owner
Expand Down
4 changes: 2 additions & 2 deletions lib/Service/RequestSignatureService.php
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,9 @@ public function saveEnvelope(array $data): array {
try {
$envelope = $this->envelopeService->createEnvelope($envelopeName, $userId, $filesCount);

$envelopeFolderName = 'envelope-' . $envelope->getUuid();
$envelopeFolder = $this->envelopeService->getEnvelopeFolder($envelope);
$envelopeSettings = array_merge($data['settings'] ?? [], [
'folderName' => $envelopeFolderName,
'envelopeFolderId' => $envelopeFolder->getId(),
]);

foreach ($data['files'] as $fileData) {
Expand Down
2 changes: 1 addition & 1 deletion openapi-full.json
Original file line number Diff line number Diff line change
Expand Up @@ -4847,7 +4847,7 @@
"settings": {
"$ref": "#/components/schemas/FolderSettings",
"default": [],
"description": "Settings to define the pattern to store the file. See more informations at FolderService::getFolderName method."
"description": "Settings to define how and where the file should be stored"
},
"files": {
"type": "array",
Expand Down
2 changes: 1 addition & 1 deletion openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -4697,7 +4697,7 @@
"settings": {
"$ref": "#/components/schemas/FolderSettings",
"default": [],
"description": "Settings to define the pattern to store the file. See more informations at FolderService::getFolderName method."
"description": "Settings to define how and where the file should be stored"
},
"files": {
"type": "array",
Expand Down
2 changes: 1 addition & 1 deletion src/types/openapi/openapi-full.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3343,7 +3343,7 @@ export interface operations {
*/
name?: string;
/**
* @description Settings to define the pattern to store the file. See more informations at FolderService::getFolderName method.
* @description Settings to define how and where the file should be stored
* @default []
*/
settings?: components["schemas"]["FolderSettings"];
Expand Down
2 changes: 1 addition & 1 deletion src/types/openapi/openapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2865,7 +2865,7 @@ export interface operations {
*/
name?: string;
/**
* @description Settings to define the pattern to store the file. See more informations at FolderService::getFolderName method.
* @description Settings to define how and where the file should be stored
* @default []
*/
settings?: components["schemas"]["FolderSettings"];
Expand Down
23 changes: 23 additions & 0 deletions tests/php/Unit/Service/EnvelopeServiceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -163,4 +163,27 @@ public function testReturnsEnvelopeWhenFileHasParent(): void {
$this->assertNotNull($result);
$this->assertSame(5, $result->getId());
}

public function testEnvelopeUuidMatchesFolderName(): void {
$this->fileMapper->method('insert')->willReturnArgument(0);

$mockFolder = $this->createMock(Folder::class);
$mockEnvelopeFolder = $this->createMock(Folder::class);
$mockEnvelopeFolder->method('getId')->willReturn(999);

$capturedFolderName = '';
$mockFolder->method('newFolder')->willReturnCallback(
function ($folderName) use ($mockEnvelopeFolder, &$capturedFolderName) {
$capturedFolderName = $folderName;
return $mockEnvelopeFolder;
}
);

$this->folderService->method('getFolder')->willReturn($mockFolder);

$envelope = $this->service->createEnvelope('Contract', 'user1');

$this->assertStringStartsWith('Contract_', $capturedFolderName);
$this->assertStringContainsString($envelope->getUuid(), $capturedFolderName);
}
}
48 changes: 8 additions & 40 deletions tests/php/Unit/Service/File/UploadProcessorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,8 @@ public function testGetNodeFromUploadedFileSuccess(): void {
$this->mimeService->method('getExtension')->with($content)->willReturn($extension);
$this->pdfValidator->method('validate');

$folder = $this->createMock(Folder::class);
$this->folderService->method('getFolder')->willReturn($folder);
$this->folderService->method('getFolderName')->willReturn('LibreSign');

$targetFolder = $this->createMock(Folder::class);
$folder->method('newFolder')->willReturn($targetFolder);
$this->folderService->method('getFolderForFile')->willReturn($targetFolder);

$node = $this->createMock(Node::class);
$targetFolder->method('newFile')->willReturn($node);
Expand Down Expand Up @@ -110,12 +106,8 @@ public function testGetNodeFromUploadedFileValidatesUpload(): void {
$this->mimeService->method('getExtension')->willReturn('pdf');
$this->pdfValidator->method('validate');

$folder = $this->createMock(Folder::class);
$this->folderService->method('getFolder')->willReturn($folder);
$this->folderService->method('getFolderName')->willReturn('LibreSign');

$targetFolder = $this->createMock(Folder::class);
$folder->method('newFolder')->willReturn($targetFolder);
$this->folderService->method('getFolderForFile')->willReturn($targetFolder);

$node = $this->createMock(Node::class);
$targetFolder->method('newFile')->willReturn($node);
Expand Down Expand Up @@ -151,12 +143,8 @@ public function testGetNodeFromUploadedFileValidatesPdf(): void {
->method('validate')
->with($content);

$folder = $this->createMock(Folder::class);
$this->folderService->method('getFolder')->willReturn($folder);
$this->folderService->method('getFolderName')->willReturn('LibreSign');

$targetFolder = $this->createMock(Folder::class);
$folder->method('newFolder')->willReturn($targetFolder);
$this->folderService->method('getFolderForFile')->willReturn($targetFolder);

$node = $this->createMock(Node::class);
$targetFolder->method('newFile')->willReturn($node);
Expand Down Expand Up @@ -187,12 +175,8 @@ public function testProcessUploadedFilesWithRollbackSuccess(): void {
$this->pdfValidator->method('validate');
$this->validateHelper->method('validateNewFile');

$folder = $this->createMock(Folder::class);
$this->folderService->method('getFolder')->willReturn($folder);
$this->folderService->method('getFolderName')->willReturn('LibreSign');

$targetFolder = $this->createMock(Folder::class);
$folder->method('newFolder')->willReturn($targetFolder);
$this->folderService->method('getFolderForFile')->willReturn($targetFolder);

$node = $this->createMock(Node::class);
$node->method('getId')->willReturn(123);
Expand Down Expand Up @@ -229,12 +213,8 @@ public function testProcessUploadedFilesWithRollbackValidatesNewFiles(): void {
'userManager' => $user,
]);

$folder = $this->createMock(Folder::class);
$this->folderService->method('getFolder')->willReturn($folder);
$this->folderService->method('getFolderName')->willReturn('LibreSign');

$targetFolder = $this->createMock(Folder::class);
$folder->method('newFolder')->willReturn($targetFolder);
$this->folderService->method('getFolderForFile')->willReturn($targetFolder);

$node = $this->createMock(Node::class);
$node->method('getId')->willReturn(123);
Expand All @@ -261,12 +241,8 @@ public function testProcessUploadedFilesWithRollbackOnValidationError(): void {
->method('validateNewFile')
->willThrowException(new LibresignException('Invalid file'));

$folder = $this->createMock(Folder::class);
$this->folderService->method('getFolder')->willReturn($folder);
$this->folderService->method('getFolderName')->willReturn('LibreSign');

$targetFolder = $this->createMock(Folder::class);
$folder->method('newFolder')->willReturn($targetFolder);
$this->folderService->method('getFolderForFile')->willReturn($targetFolder);

$node = $this->createMock(Node::class);
$node->method('getId')->willReturn(123);
Expand Down Expand Up @@ -299,12 +275,8 @@ public function testProcessUploadedFilesWithRollbackLogsDeleteError(): void {
->method('validateNewFile')
->willThrowException(new LibresignException('Invalid file'));

$folder = $this->createMock(Folder::class);
$this->folderService->method('getFolder')->willReturn($folder);
$this->folderService->method('getFolderName')->willReturn('LibreSign');

$targetFolder = $this->createMock(Folder::class);
$folder->method('newFolder')->willReturn($targetFolder);
$this->folderService->method('getFolderForFile')->willReturn($targetFolder);

$node = $this->createMock(Node::class);
$node->method('getId')->willReturn(123);
Expand Down Expand Up @@ -344,12 +316,8 @@ public function testProcessUploadedFilesReturnsCorrectStructure(): void {
$this->pdfValidator->method('validate');
$this->validateHelper->method('validateNewFile');

$folder = $this->createMock(Folder::class);
$this->folderService->method('getFolder')->willReturn($folder);
$this->folderService->method('getFolderName')->willReturn('LibreSign');

$targetFolder = $this->createMock(Folder::class);
$folder->method('newFolder')->willReturn($targetFolder);
$this->folderService->method('getFolderForFile')->willReturn($targetFolder);

$node = $this->createMock(Node::class);
$node->method('getId')->willReturn(123);
Expand Down
60 changes: 60 additions & 0 deletions tests/php/Unit/Service/FolderServiceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -274,4 +274,64 @@ public static function providerGetFolderName(): array {
],
];
}

public function testGetFolderForFileUsesEnvelopeFolderWhenProvided(): void {
$envelopeFolderId = 456;
$data = [
'settings' => [
'envelopeFolderId' => $envelopeFolderId,
],
];

$mockUserFolder = $this->createMock(Folder::class);
$mockEnvelopeFolder = $this->createMock(Folder::class);

$mockUserFolder->expects($this->once())
->method('getFirstNodeById')
->with($envelopeFolderId)
->willReturn($mockEnvelopeFolder);

$this->appConfig->method('getUserValue')->willReturn('/LibreSign');
$this->groupManager->method('isInGroup')->willReturn(false);

$userFolder = $this->createMock(Folder::class);
$userFolder->method('isUpdateable')->willReturn(true);
$userFolder->method('get')->willReturn($mockUserFolder);
$this->root->method('getUserFolder')->willReturn($userFolder);

$service = $this->getInstance('testuser');
$result = $service->getFolderForFile($data, 'testuser');

$this->assertInstanceOf(Folder::class, $result);
}

public function testGetFolderForFileCreatesNewFolderWhenNoEnvelopeId(): void {
$data = [
'name' => 'Document',
'settings' => [],
];

$user = $this->createMock(IUser::class);
$user->method('getUID')->willReturn('user1');

$mockUserFolder = $this->createMock(Folder::class);
$mockNewFolder = $this->createMock(Folder::class);

$mockUserFolder->expects($this->once())
->method('newFolder')
->willReturn($mockNewFolder);

$this->appConfig->method('getUserValue')->willReturn('/LibreSign');
$this->groupManager->method('isInGroup')->willReturn(false);

$userFolder = $this->createMock(Folder::class);
$userFolder->method('isUpdateable')->willReturn(true);
$userFolder->method('get')->willReturn($mockUserFolder);
$this->root->method('getUserFolder')->willReturn($userFolder);

$service = $this->getInstance('user1');
$result = $service->getFolderForFile($data, $user);

$this->assertInstanceOf(Folder::class, $result);
}
}
Loading