Skip to content

[stable31] feat: sequential signing#6070

Merged
vitormattos merged 35 commits intostable31from
backport/6069/stable31
Dec 10, 2025
Merged

[stable31] feat: sequential signing#6070
vitormattos merged 35 commits intostable31from
backport/6069/stable31

Conversation

@backportbot-libresign
Copy link
Copy Markdown

@backportbot-libresign backportbot-libresign Bot commented Dec 10, 2025

Backport of #6069

Warning, This backport's changes differ from the original and might be incomplete ⚠️

Todo

  • Review and resolve any conflicts
  • Amend HEAD commit to remove the line stating to skip CI

Learn more about backports at https://docs.nextcloud.com/server/stable/go.php?to=developer-backports.

- SignRequestStatus: Enum with DRAFT, ABLE_TO_SIGN, SIGNED states
- SignatureFlow: Enum with PARALLEL and ORDERED_NUMERIC modes
- String-backed enums for database compatibility

Signed-off-by: Vitor Mattos <[email protected]>
- Add signing_order column (INT, DEFAULT 1) to libresign_sign_request
- Add status column (VARCHAR 20, DEFAULT 'draft') to libresign_sign_request
- Migration supports both PostgreSQL and MySQL/MariaDB

Signed-off-by: Vitor Mattos <[email protected]>
- Add signingOrder property (int, default 1)
- Add status property (string, default 'draft')
- Add getStatusEnum() and setStatusEnum() for enum handling
- Magic methods for string-based status access (Entity compatibility)
- Proper field type registration in constructor

Signed-off-by: Vitor Mattos <[email protected]>
- Manages signing order determination and counter
- Validates signature flow (parallel vs sequential)
- Updates next signer status after signature completion
- Integrates with IAppConfig for flow configuration

Signed-off-by: Vitor Mattos <[email protected]>
- Inject SequentialSigningService dependency
- Reset order counter before processing signers
- Determine signing order for each user
- Set initial status based on order (ABLE_TO_SIGN for first, DRAFT for others)
- Type casting for signingOrder from JSON input

Signed-off-by: Vitor Mattos <[email protected]>
- Mark SignRequest as SIGNED using setStatusEnum()
- Update next signer status after successful signature
- Integrate with SequentialSigningService for flow management

Signed-off-by: Vitor Mattos <[email protected]>
- Validate signer cannot sign if status is DRAFT
- Validate signer cannot sign again if already SIGNED
- Use getStatusEnum() for enum comparisons
- Proper error messages for blocked signers

Signed-off-by: Vitor Mattos <[email protected]>
- POST /api/v1/admin/signature-flow endpoint
- Parameter: flow (parallel or ordered_numeric)
- Saves configuration to app config
- Returns success response with saved flow

Signed-off-by: Vitor Mattos <[email protected]>
- Remove debug logging from SignRequestMapper
- Remove error logging from RequestSignatureController
- Clean up temporary debugging code

Signed-off-by: Vitor Mattos <[email protected]>
- Test parallel signing: all signers can sign immediately
- Test sequential signing: order enforced, status transitions validated
- Verify status 422 when signer attempts to sign out of order
- Verify status changes from DRAFT to ABLE_TO_SIGN after previous signer completes

Signed-off-by: Vitor Mattos <[email protected]>
- Update openapi.json with new signature-flow endpoint
- Regenerate TypeScript types from OpenAPI specs
- Auto-generated by openapi-extractor

Signed-off-by: Vitor Mattos <[email protected]>
- Change SignRequestStatus enum from string-backed to int-backed (0, 1, 2)
- Update database migration to use SMALLINT instead of VARCHAR(20)
- Update SignRequest entity to use int type for status property
- Reduces storage overhead and improves performance
- Integer values: 0=draft, 1=able_to_sign, 2=signed

Signed-off-by: Vitor Mattos <[email protected]>
Signed-off-by: Vitor Mattos <[email protected]>
- Add SequentialSigningService mock in RequestSignatureServiceTest
- Add SequentialSigningService mock in SignFileServiceTest
- Update constructor calls in both test files to include new dependency

Signed-off-by: Vitor Mattos <[email protected]>
- Add getFileId and getSigningOrder to __call callback mocks
- Return 1 for both methods in tests
- Fixes TypeError when releaseNextOrder is called with null fileId
- All 12 affected tests now pass

Signed-off-by: Vitor Mattos <[email protected]>
- Add reorderAfterDeletion method to SequentialSigningService
- Automatically activate next order when a signer is deleted
- Prevents gaps in signing sequence that would block workflow
- Call reorderAfterDeletion in unassociateToUser after deletion
- Ensures sequential flow continues even when signers are removed

Signed-off-by: Vitor Mattos <[email protected]>
…tchEventWhenSign

Add __call callbacks to SignRequest mocks in both tests to properly return
fileId and signingOrder values. Without these callbacks, the mocks were
returning null when these magic methods were called, causing
SequentialSigningService::releaseNextOrder() to fail with a TypeError.

Signed-off-by: Vitor Mattos <[email protected]>
Add setSignatureFlowConfig() method to AdminController to allow
administrators to configure the signature flow mode (parallel or
ordered_numeric). The endpoint validates the mode using the
SignatureFlow enum and deletes the config key when parallel mode
is selected (as it's the default).

Endpoint: POST /api/v1/admin/signature-flow/config
Signed-off-by: Vitor Mattos <[email protected]>
Create SignatureFlow.vue component for admin settings to configure
signing order mode. Administrators can choose between:
- Simultaneous (Parallel): all signers receive at the same time
- Sequential: signers organized by order number

The component follows the same pattern as other admin settings
(DocMDP) with radio buttons, loading states, and error handling.

Integrated into Settings.vue admin panel.

Signed-off-by: Vitor Mattos <[email protected]>
Regenerate OpenAPI documentation files to include the new
signature flow configuration endpoint.

Signed-off-by: Vitor Mattos <[email protected]>
Install vuedraggable v2.24.3 to enable drag-and-drop
functionality for signing order management in sequential
signature flows.

Signed-off-by: Vitor Mattos <[email protected]>
Add signature_flow to initial state in PageController and
TemplateLoader to enable frontend components to access the
current signature flow mode (parallel or ordered_numeric).

Signed-off-by: Vitor Mattos <[email protected]>
Include signingOrder field in signer data returned by FileService.
Sort signers by signingOrder (ascending) and displayName as secondary
sort to maintain consistent ordering in the UI.

Signed-off-by: Vitor Mattos <[email protected]>
Add signingOrderMixin.js with recalculateSigningOrders and
normalizeSigningOrders methods to centralize signing order
calculations and normalization logic used by both drag-and-drop
and manual input components.

Signed-off-by: Vitor Mattos <[email protected]>
Auto-assign incrementing signingOrder to new signers in ordered_numeric
mode. When deleting a signer, decrement signingOrder of subsequent
signers to close gaps and maintain sequential ordering.

Signed-off-by: Vitor Mattos <[email protected]>
Display counter-number badge with highlighted style when in
ordered_numeric mode. Show DragVertical icon handle when drag-and-drop
is enabled. Add closeActions method to programmatically close action
menu after input submission.

Signed-off-by: Vitor Mattos <[email protected]>
Integrate vuedraggable to enable drag-and-drop reordering when in
ordered_numeric mode. Track originalOrders during drag operations,
recalculate signingOrder using shared mixin logic, emit
signing-order-changed event to trigger auto-save. Include CSS
animations and visual feedback for drag states.

Signed-off-by: Vitor Mattos <[email protected]>
Add NcActionInput for manual signing order entry with dual-mode
behavior: updateSigningOrder for visual reordering during typing,
confirmSigningOrder for normalization and persistence on submit/blur.
Implement debounced auto-save (1000ms) after drag-and-drop or manual
order changes. Listen to signing-order-changed event from Signers
component using Vue $emit pattern.

Signed-off-by: Vitor Mattos <[email protected]>
In ordered_numeric signature flow, all signers were receiving

notifications regardless of their status. This caused signers

with signing_order > 1 (status DRAFT) to be notified immediately.

Changes:

- Update SignRequest status on PATCH operations, not just INSERT

- Only notify signers when status is ABLE_TO_SIGN

- Ensure signers with order > 1 remain in DRAFT status until

previous orders are completed

This ensures notifications are sent only to signers who can

actually sign at that moment.

Signed-off-by: Vitor Mattos <[email protected]>

[skip ci]
Update Behat test to use correct endpoint URL and parameter name:
- Changed from '/api/v1/admin/signature-flow' to '/api/v1/admin/signature-flow/config'
- Changed parameter from 'flow' to 'mode'

This aligns with the actual AdminController endpoint implementation.

Signed-off-by: Vitor Mattos <[email protected]>
Signed-off-by: Vitor Mattos <[email protected]>
@vitormattos vitormattos marked this pull request as ready for review December 10, 2025 15:54
When multiple signers have the same signingOrder value, they should
maintain their insertion order (defined by signRequestId) rather than
being sorted alphabetically by displayName.

This change ensures that when signingOrder is equal, signers are
sorted by signRequestId (which is auto-incrementing) instead of
displayName, preserving the order in which they were originally added.

Fixes Behat integration test failures where tests expected signers
to appear in insertion order.

Signed-off-by: Vitor Mattos <[email protected]>
@vitormattos vitormattos merged commit 309ee1e into stable31 Dec 10, 2025
62 checks passed
@vitormattos vitormattos deleted the backport/6069/stable31 branch December 10, 2025 17:02
@github-project-automation github-project-automation Bot moved this from 0. Needs triage to 4. to release in Roadmap Dec 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

1 participant