diff --git a/lib/Db/File.php b/lib/Db/File.php index 856df3dc3e..07c112f51c 100644 --- a/lib/Db/File.php +++ b/lib/Db/File.php @@ -41,6 +41,8 @@ * @method int getModificationStatus() * @method void setSignatureFlow(int $signatureFlow) * @method int getSignatureFlow() + * @method void setDocmdpLevel(int $docmdpLevel) + * @method int getDocmdpLevel() */ class File extends Entity { protected int $nodeId = 0; @@ -56,6 +58,7 @@ class File extends Entity { protected ?array $metadata = null; protected int $modificationStatus = 0; protected int $signatureFlow = SignatureFlow::NUMERIC_PARALLEL; + protected int $docmdpLevel = 0; public const STATUS_NOT_LIBRESIGN_FILE = -1; public const STATUS_DRAFT = 0; public const STATUS_ABLE_TO_SIGN = 1; @@ -83,6 +86,7 @@ public function __construct() { $this->addType('metadata', Types::JSON); $this->addType('modificationStatus', Types::SMALLINT); $this->addType('signatureFlow', Types::SMALLINT); + $this->addType('docmdpLevel', Types::SMALLINT); } public function isDeletedAccount(): bool { @@ -102,4 +106,12 @@ public function getSignatureFlowEnum(): \OCA\Libresign\Enum\SignatureFlow { public function setSignatureFlowEnum(\OCA\Libresign\Enum\SignatureFlow $flow): void { $this->setSignatureFlow($flow->toNumeric()); } + + public function getDocmdpLevelEnum(): \OCA\Libresign\Enum\DocMdpLevel { + return \OCA\Libresign\Enum\DocMdpLevel::tryFrom($this->docmdpLevel) ?? \OCA\Libresign\Enum\DocMdpLevel::NOT_CERTIFIED; + } + + public function setDocmdpLevelEnum(\OCA\Libresign\Enum\DocMdpLevel $level): void { + $this->setDocmdpLevel($level->value); + } } diff --git a/lib/Db/SignRequestMapper.php b/lib/Db/SignRequestMapper.php index 8fddbebe17..30745d6ec2 100644 --- a/lib/Db/SignRequestMapper.php +++ b/lib/Db/SignRequestMapper.php @@ -501,6 +501,7 @@ private function getFilesAssociatedFilesWithMeQueryBuilder(string $userId, array 'f.metadata', 'f.created_at', 'f.signature_flow', + 'f.docmdp_level', ) ->groupBy( 'f.id', @@ -512,6 +513,7 @@ private function getFilesAssociatedFilesWithMeQueryBuilder(string $userId, array 'f.status', 'f.created_at', 'f.signature_flow', + 'f.docmdp_level', ); // metadata is a json column, the right way is to use f.metadata::text // when the database is PostgreSQL. The problem is that the command @@ -623,12 +625,14 @@ private function formatListRow(array $row): array { $row['name'] = $this->removeExtensionFromName($row['name'], $row['metadata']); $row['signatureFlow'] = SignatureFlow::fromNumeric((int)($row['signature_flow']))->value; + $row['docmdpLevel'] = (int)($row['docmdp_level'] ?? 0); unset( $row['user_id'], $row['node_id'], $row['signed_node_id'], $row['signature_flow'], + $row['docmdp_level'], ); return $row; } diff --git a/lib/Migration/Version15001Date20251214000000.php b/lib/Migration/Version15001Date20251214000000.php new file mode 100644 index 0000000000..17f049940c --- /dev/null +++ b/lib/Migration/Version15001Date20251214000000.php @@ -0,0 +1,46 @@ +hasTable('libresign_file')) { + $tableFile = $schema->getTable('libresign_file'); + if (!$tableFile->hasColumn('docmdp_level')) { + $tableFile->addColumn('docmdp_level', Types::SMALLINT, [ + 'notnull' => true, + 'default' => 0, + 'comment' => 'DocMDP permission level for this file: 0=none, 1=no changes, 2=form fill, 3=form fill + annotations', + ]); + } + } + + return $schema; + } +} diff --git a/lib/ResponseDefinitions.php b/lib/ResponseDefinitions.php index 2b40542a06..a8b88477ff 100644 --- a/lib/ResponseDefinitions.php +++ b/lib/ResponseDefinitions.php @@ -187,6 +187,7 @@ * statusText: string, * nodeId: non-negative-int, * signatureFlow: int, + * docmdpLevel: int, * totalPages: non-negative-int, * size: non-negative-int, * pdfVersion: string, diff --git a/lib/Service/FileService.php b/lib/Service/FileService.php index e75cb9f845..1d0ed76c0b 100644 --- a/lib/Service/FileService.php +++ b/lib/Service/FileService.php @@ -712,6 +712,7 @@ private function loadLibreSignData(): void { $this->fileData->statusText = $this->fileMapper->getTextOfStatus($this->file->getStatus()); $this->fileData->nodeId = $this->file->getNodeId(); $this->fileData->signatureFlow = $this->file->getSignatureFlow(); + $this->fileData->docmdpLevel = $this->file->getDocmdpLevel(); $this->fileData->requested_by = [ 'userId' => $this->file->getUserId(), diff --git a/lib/Service/RequestSignatureService.php b/lib/Service/RequestSignatureService.php index a57ec9b313..3308a1540a 100644 --- a/lib/Service/RequestSignatureService.php +++ b/lib/Service/RequestSignatureService.php @@ -56,6 +56,7 @@ public function __construct( protected IEventDispatcher $eventDispatcher, protected FileStatusService $fileStatusService, protected SignRequestStatusService $signRequestStatusService, + protected DocMdpConfigService $docMdpConfigService, ) { } @@ -128,6 +129,8 @@ public function saveFile(array $data): FileEntity { $this->setSignatureFlowFromGlobalConfig($file); } + $this->setDocMdpLevelFromGlobalConfig($file); + $this->fileMapper->insert($file); return $file; } @@ -138,6 +141,13 @@ private function setSignatureFlowFromGlobalConfig(FileEntity $file): void { $file->setSignatureFlowEnum($globalFlow); } + private function setDocMdpLevelFromGlobalConfig(FileEntity $file): void { + if ($this->docMdpConfigService->isEnabled()) { + $docmdpLevel = $this->docMdpConfigService->getLevel(); + $file->setDocmdpLevelEnum($docmdpLevel); + } + } + private function getFileMetadata(\OCP\Files\Node $node): array { $metadata = []; if ($extension = strtolower($node->getExtension())) { diff --git a/lib/Service/SignFileService.php b/lib/Service/SignFileService.php index 5c167e7813..0d517059b3 100644 --- a/lib/Service/SignFileService.php +++ b/lib/Service/SignFileService.php @@ -338,17 +338,28 @@ public function sign(): File { * @throws LibresignException If the document has DocMDP level 1 (no changes allowed) */ protected function validateDocMdpAllowsSignatures(): void { - $resource = $this->getLibreSignFileAsResource(); + $docmdpLevel = $this->libreSignFile->getDocmdpLevelEnum(); - try { - if (!$this->docMdpHandler->allowsAdditionalSignatures($resource)) { - throw new LibresignException( - $this->l10n->t('This document has been certified with no changes allowed, so no additional signatures can be added.'), - AppFrameworkHttp::STATUS_UNPROCESSABLE_ENTITY - ); + if ($docmdpLevel === \OCA\Libresign\Enum\DocMdpLevel::CERTIFIED_NO_CHANGES_ALLOWED) { + throw new LibresignException( + $this->l10n->t('This document has been certified with no changes allowed. You cannot add more signers to this document.'), + AppFrameworkHttp::STATUS_UNPROCESSABLE_ENTITY + ); + } + + if ($docmdpLevel === \OCA\Libresign\Enum\DocMdpLevel::NOT_CERTIFIED) { + $resource = $this->getLibreSignFileAsResource(); + + try { + if (!$this->docMdpHandler->allowsAdditionalSignatures($resource)) { + throw new LibresignException( + $this->l10n->t('This document has been certified with no changes allowed. You cannot add more signers to this document.'), + AppFrameworkHttp::STATUS_UNPROCESSABLE_ENTITY + ); + } + } finally { + fclose($resource); } - } finally { - fclose($resource); } } diff --git a/openapi-full.json b/openapi-full.json index 3aaf844a4b..de9ee08dc6 100644 --- a/openapi-full.json +++ b/openapi-full.json @@ -1013,6 +1013,7 @@ "statusText", "nodeId", "signatureFlow", + "docmdpLevel", "totalPages", "size", "pdfVersion", @@ -1050,6 +1051,10 @@ "type": "integer", "format": "int64" }, + "docmdpLevel": { + "type": "integer", + "format": "int64" + }, "totalPages": { "type": "integer", "format": "int64", diff --git a/openapi.json b/openapi.json index ae39e7a0b4..217121894d 100644 --- a/openapi.json +++ b/openapi.json @@ -863,6 +863,7 @@ "statusText", "nodeId", "signatureFlow", + "docmdpLevel", "totalPages", "size", "pdfVersion", @@ -900,6 +901,10 @@ "type": "integer", "format": "int64" }, + "docmdpLevel": { + "type": "integer", + "format": "int64" + }, "totalPages": { "type": "integer", "format": "int64", diff --git a/src/Components/RightSidebar/RequestSignatureTab.vue b/src/Components/RightSidebar/RequestSignatureTab.vue index 3391749c23..e8ea7a1a83 100644 --- a/src/Components/RightSidebar/RequestSignatureTab.vue +++ b/src/Components/RightSidebar/RequestSignatureTab.vue @@ -4,6 +4,9 @@ -->