Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
abf6bb7
feat: add numeric conversion methods to SignatureFlow enum
vitormattos Dec 12, 2025
0f89027
feat: add signature_flow column to libresign_file table
vitormattos Dec 12, 2025
ff7b64b
feat: add signature flow support to File entity
vitormattos Dec 12, 2025
ad71acb
refactor: use file-level signature flow in SequentialSigningService
vitormattos Dec 12, 2025
c16ba73
feat: add signatureFlow parameter to request-signature endpoint
vitormattos Dec 12, 2025
7918cd5
feat: implement signature flow handling in RequestSignatureService
vitormattos Dec 12, 2025
3ac6e06
refactor: pass file entity to SequentialSigningService in SignFileSer…
vitormattos Dec 12, 2025
8a4e018
feat: include signatureFlow in API responses
vitormattos Dec 12, 2025
0e3ed55
docs: add signatureFlow parameter to OpenAPI specification
vitormattos Dec 12, 2025
a02bb43
chore: remove unecessary docblock
vitormattos Dec 12, 2025
1d62e46
refactor: move signature flow constants to enum
vitormattos Dec 12, 2025
06b1b8f
chore: regenerate TypeScript types from OpenAPI spec
vitormattos Dec 12, 2025
df44227
fix: add signatureFlow to ValidateFile schema
vitormattos Dec 12, 2025
d38d3c0
refactor: read signature flow from file data in frontend
vitormattos Dec 12, 2025
c468f3a
test: add unit tests for signature flow feature
vitormattos Dec 12, 2025
da8ca88
fix: add signatureFlow to ValidateFile schema in openapi.json
vitormattos Dec 12, 2025
4a15f79
fix: openapi documentation
vitormattos Dec 12, 2025
e97580b
fix: correctly increment order counter after user-provided order
vitormattos Dec 12, 2025
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
13 changes: 11 additions & 2 deletions lib/Controller/RequestSignatureController.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public function __construct(
* @param string $name The name of file to sign
* @param string|null $callback URL that will receive a POST after the document is signed
* @param integer|null $status Numeric code of status * 0 - no signers * 1 - signed * 2 - pending
* @param string|null $signatureFlow Signature flow mode: 'parallel' or 'ordered_numeric'. If not provided, uses global configuration
* @return DataResponse<Http::STATUS_OK, array{data: LibresignValidateFile, message: string}, array{}>|DataResponse<Http::STATUS_UNPROCESSABLE_ENTITY, array{message?: string, action?: integer, errors?: list<array{message: string, title?: string}>}, array{}>
*
* 200: OK
Expand All @@ -65,15 +66,23 @@ public function __construct(
#[NoCSRFRequired]
#[RequireManager]
#[ApiRoute(verb: 'POST', url: '/api/{apiVersion}/request-signature', requirements: ['apiVersion' => '(v1)'])]
public function request(array $file, array $users, string $name, ?string $callback = null, ?int $status = 1): DataResponse {
public function request(
array $file,
array $users,
string $name,
?string $callback = null,
?int $status = 1,
?string $signatureFlow = null,
): DataResponse {
$user = $this->userSession->getUser();
$data = [
'file' => $file,
'name' => $name,
'users' => $users,
'status' => $status,
'callback' => $callback,
'userManager' => $user
'userManager' => $user,
'signatureFlow' => $signatureFlow,
];
try {
$this->requestSignatureService->validateNewRequestToFile($data);
Expand Down
13 changes: 13 additions & 0 deletions lib/Db/File.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

namespace OCA\Libresign\Db;

use OCA\Libresign\Enum\SignatureFlow;
use OCP\AppFramework\Db\Entity;
use OCP\DB\Types;

Expand Down Expand Up @@ -38,6 +39,8 @@
* @method ?array getMetadata()
* @method void setModificationStatus(int $modificationStatus)
* @method int getModificationStatus()
* @method void setSignatureFlow(int $signatureFlow)
* @method int getSignatureFlow()
*/
class File extends Entity {
protected int $nodeId = 0;
Expand All @@ -52,6 +55,7 @@ class File extends Entity {
protected ?string $callback = null;
protected ?array $metadata = null;
protected int $modificationStatus = 0;
protected int $signatureFlow = SignatureFlow::NUMERIC_PARALLEL;
public const STATUS_NOT_LIBRESIGN_FILE = -1;
public const STATUS_DRAFT = 0;
public const STATUS_ABLE_TO_SIGN = 1;
Expand All @@ -78,6 +82,7 @@ public function __construct() {
$this->addType('status', Types::INTEGER);
$this->addType('metadata', Types::JSON);
$this->addType('modificationStatus', Types::SMALLINT);
$this->addType('signatureFlow', Types::SMALLINT);
}

public function isDeletedAccount(): bool {
Expand All @@ -89,4 +94,12 @@ public function getUserId(): string {
$metadata = $this->getMetadata();
return $metadata['deleted_account']['account'] ?? $this->userId ?? '';
}

public function getSignatureFlowEnum(): \OCA\Libresign\Enum\SignatureFlow {
return \OCA\Libresign\Enum\SignatureFlow::fromNumeric($this->signatureFlow);
}

public function setSignatureFlowEnum(\OCA\Libresign\Enum\SignatureFlow $flow): void {
$this->setSignatureFlow($flow->toNumeric());
}
}
5 changes: 5 additions & 0 deletions lib/Db/SignRequestMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
namespace OCA\Libresign\Db;

use DateTimeInterface;
use OCA\Libresign\Enum\SignatureFlow;
use OCA\Libresign\Enum\SignRequestStatus;
use OCA\Libresign\Helper\Pagination;
use OCA\Libresign\Service\IdentifyMethod\IIdentifyMethod;
Expand Down Expand Up @@ -500,6 +501,7 @@ private function getFilesAssociatedFilesWithMeQueryBuilder(string $userId, array
'f.status',
'f.metadata',
'f.created_at',
'f.signature_flow',
)
->groupBy(
'f.id',
Expand All @@ -510,6 +512,7 @@ private function getFilesAssociatedFilesWithMeQueryBuilder(string $userId, array
'f.name',
'f.status',
'f.created_at',
'f.signature_flow',
);
// 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
Expand Down Expand Up @@ -620,11 +623,13 @@ private function formatListRow(array $row): array {
$row['nodeId'] = (int)$row['node_id'];

$row['name'] = $this->removeExtensionFromName($row['name'], $row['metadata']);
$row['signatureFlow'] = SignatureFlow::fromNumeric((int)($row['signature_flow']))->value;

unset(
$row['user_id'],
$row['node_id'],
$row['signed_node_id'],
$row['signature_flow'],
);
return $row;
}
Expand Down
18 changes: 18 additions & 0 deletions lib/Enum/SignatureFlow.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,22 @@
enum SignatureFlow: string {
case PARALLEL = 'parallel';
case ORDERED_NUMERIC = 'ordered_numeric';

public const NUMERIC_PARALLEL = 1;
public const NUMERIC_ORDERED_NUMERIC = 2;

public function toNumeric(): int {
return match($this) {
self::PARALLEL => self::NUMERIC_PARALLEL,
self::ORDERED_NUMERIC => self::NUMERIC_ORDERED_NUMERIC,
};
}

public static function fromNumeric(int $value): self {
return match($value) {
self::NUMERIC_PARALLEL => self::PARALLEL,
self::NUMERIC_ORDERED_NUMERIC => self::ORDERED_NUMERIC,
default => throw new \ValueError("Invalid numeric value for SignatureFlow: $value"),
};
}
}
12 changes: 12 additions & 0 deletions lib/Migration/Version15000Date20251209000000.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
namespace OCA\Libresign\Migration;

use Closure;
use OCA\Libresign\Enum\SignatureFlow;
use OCP\DB\ISchemaWrapper;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\DB\Types;
Expand Down Expand Up @@ -56,6 +57,17 @@ public function changeSchema(IOutput $output, Closure $schemaClosure, array $opt
}
}

if ($schema->hasTable('libresign_file')) {
$tableFile = $schema->getTable('libresign_file');
if (!$tableFile->hasColumn('signature_flow')) {
$tableFile->addColumn('signature_flow', Types::SMALLINT, [
'notnull' => true,
'default' => SignatureFlow::NUMERIC_PARALLEL,
'comment' => 'Signature flow mode: 1=parallel, 2=ordered_numeric',
]);
}
}

return $schema;
}

Expand Down
1 change: 1 addition & 0 deletions lib/ResponseDefinitions.php
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@
* status: 0|1|2|3|4,
* statusText: string,
* nodeId: non-negative-int,
* signatureFlow: int,
* totalPages: non-negative-int,
* size: non-negative-int,
* pdfVersion: string,
Expand Down
1 change: 1 addition & 0 deletions lib/Service/FileService.php
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,7 @@ private function loadLibreSignData(): void {
$this->fileData->created_at = $this->file->getCreatedAt()->format(DateTimeInterface::ATOM);
$this->fileData->statusText = $this->fileMapper->getTextOfStatus($this->file->getStatus());
$this->fileData->nodeId = $this->file->getNodeId();
$this->fileData->signatureFlow = $this->file->getSignatureFlow();

$this->fileData->requested_by = [
'userId' => $this->file->getUserId(),
Expand Down
23 changes: 23 additions & 0 deletions lib/Service/RequestSignatureService.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,22 @@

namespace OCA\Libresign\Service;

use OCA\Libresign\AppInfo\Application;
use OCA\Libresign\Db\File as FileEntity;
use OCA\Libresign\Db\FileElementMapper;
use OCA\Libresign\Db\FileMapper;
use OCA\Libresign\Db\IdentifyMethodMapper;
use OCA\Libresign\Db\SignRequest as SignRequestEntity;
use OCA\Libresign\Db\SignRequestMapper;
use OCA\Libresign\Enum\SignatureFlow;
use OCA\Libresign\Handler\DocMdpHandler;
use OCA\Libresign\Helper\ValidateHelper;
use OCA\Libresign\Service\IdentifyMethod\IIdentifyMethod;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\Files\IMimeTypeDetector;
use OCP\Files\Node;
use OCP\Http\Client\IClientService;
use OCP\IAppConfig;
use OCP\IL10N;
use OCP\IUser;
use OCP\IUserManager;
Expand All @@ -47,6 +50,7 @@ public function __construct(
protected DocMdpHandler $docMdpHandler,
protected LoggerInterface $logger,
protected SequentialSigningService $sequentialSigningService,
protected IAppConfig $appConfig,
) {
}

Expand All @@ -56,6 +60,7 @@ public function save(array $data): FileEntity {
if (!isset($data['status'])) {
$data['status'] = $file->getStatus();
}
$this->sequentialSigningService->setFile($file);
$this->associateToSigners($data, $file->getId());
return $file;
}
Expand Down Expand Up @@ -106,10 +111,28 @@ public function saveFile(array $data): FileEntity {
} else {
$file->setStatus(FileEntity::STATUS_ABLE_TO_SIGN);
}

if (isset($data['signatureFlow']) && is_string($data['signatureFlow'])) {
try {
$signatureFlow = \OCA\Libresign\Enum\SignatureFlow::from($data['signatureFlow']);
$file->setSignatureFlowEnum($signatureFlow);
} catch (\ValueError) {
$this->setSignatureFlowFromGlobalConfig($file);
}
} else {
$this->setSignatureFlowFromGlobalConfig($file);
}

$this->fileMapper->insert($file);
return $file;
}

private function setSignatureFlowFromGlobalConfig(FileEntity $file): void {
$globalFlowValue = $this->appConfig->getValueString(Application::APP_ID, 'signature_flow', SignatureFlow::PARALLEL->value);
$globalFlow = SignatureFlow::from($globalFlowValue);
$file->setSignatureFlowEnum($globalFlow);
}

private function updateStatus(FileEntity $file, int $status): FileEntity {
if ($status > $file->getStatus()) {
$file->setStatus($status);
Expand Down
26 changes: 13 additions & 13 deletions lib/Service/SequentialSigningService.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@

namespace OCA\Libresign\Service;

use OCA\Libresign\AppInfo\Application;
use OCA\Libresign\Db\File as FileEntity;
use OCA\Libresign\Db\SignRequestMapper;
use OCA\Libresign\Enum\SignatureFlow;
use OCA\Libresign\Enum\SignRequestStatus;
use OCP\IAppConfig;

class SequentialSigningService {
private int $currentOrder = 1;
private ?FileEntity $file = null;

public function __construct(
private IAppConfig $appConfig,
Expand All @@ -24,9 +25,11 @@ public function __construct(
) {
}

/**
* Check if ordered numeric flow is enabled
*/
public function setFile(FileEntity $file): self {
$this->file = $file;
return $this;
}

public function isOrderedNumericFlow(): bool {
return $this->getSignatureFlow() === SignatureFlow::ORDERED_NUMERIC;
}
Expand All @@ -51,8 +54,8 @@ public function determineSigningOrder(?int $userProvidedOrder): int {
}

if ($userProvidedOrder !== null) {
if ($userProvidedOrder > $this->currentOrder) {
$this->currentOrder = $userProvidedOrder;
if ($userProvidedOrder >= $this->currentOrder) {
$this->currentOrder = $userProvidedOrder + 1;
}
return $userProvidedOrder;
}
Expand Down Expand Up @@ -162,13 +165,10 @@ private function activateSignersForOrder(array $signRequests, int $order): void
}

private function getSignatureFlow(): SignatureFlow {
$value = $this->appConfig->getValueString(
Application::APP_ID,
'signature_flow',
SignatureFlow::PARALLEL->value
);

return SignatureFlow::from($value);
if ($this->file === null) {
throw new \LogicException('File must be set before calling getSignatureFlow(). Call setFile() first.');
}
return $this->file->getSignatureFlowEnum();
}

/**
Expand Down
10 changes: 6 additions & 4 deletions lib/Service/SignFileService.php
Original file line number Diff line number Diff line change
Expand Up @@ -380,10 +380,12 @@ protected function updateSignRequest(string $hash): void {

$this->signRequestMapper->update($this->signRequest);

$this->sequentialSigningService->releaseNextOrder(
$this->signRequest->getFileId(),
$this->signRequest->getSigningOrder()
);
$this->sequentialSigningService
->setFile($this->libreSignFile)
->releaseNextOrder(
$this->signRequest->getFileId(),
$this->signRequest->getSigningOrder()
);
}

protected function updateLibreSignFile(string $hash): void {
Expand Down
10 changes: 10 additions & 0 deletions openapi-full.json
Original file line number Diff line number Diff line change
Expand Up @@ -1012,6 +1012,7 @@
"status",
"statusText",
"nodeId",
"signatureFlow",
"totalPages",
"size",
"pdfVersion",
Expand Down Expand Up @@ -1045,6 +1046,10 @@
"format": "int64",
"minimum": 0
},
"signatureFlow": {
"type": "integer",
"format": "int64"
},
"totalPages": {
"type": "integer",
"format": "int64",
Expand Down Expand Up @@ -6456,6 +6461,11 @@
"nullable": true,
"default": 1,
"description": "Numeric code of status * 0 - no signers * 1 - signed * 2 - pending"
},
"signatureFlow": {
"type": "string",
"nullable": true,
"description": "Signature flow mode: 'parallel' or 'ordered_numeric'. If not provided, uses global configuration"
}
}
}
Expand Down
10 changes: 10 additions & 0 deletions openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -862,6 +862,7 @@
"status",
"statusText",
"nodeId",
"signatureFlow",
"totalPages",
"size",
"pdfVersion",
Expand Down Expand Up @@ -895,6 +896,10 @@
"format": "int64",
"minimum": 0
},
"signatureFlow": {
"type": "integer",
"format": "int64"
},
"totalPages": {
"type": "integer",
"format": "int64",
Expand Down Expand Up @@ -6306,6 +6311,11 @@
"nullable": true,
"default": 1,
"description": "Numeric code of status * 0 - no signers * 1 - signed * 2 - pending"
},
"signatureFlow": {
"type": "string",
"nullable": true,
"description": "Signature flow mode: 'parallel' or 'ordered_numeric'. If not provided, uses global configuration"
}
}
}
Expand Down
Loading
Loading