Commit graph

3,062 commits

Author SHA1 Message Date
Vitor Mattos
75766e27fd
feat: add email notification preferences to account search
Include acceptsEmailNotifications field in search results for account
method signers. This field indicates whether a user accepts email
notifications based on both Activity admin settings and user
preferences. Returns false when user has no email, Activity app is
unavailable, or notifications are disabled at admin or user level.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-16 19:12:58 -03:00
Vitor Mattos
68eada5682
docs: update API response definitions
Add description, displayName, notify, and acceptsEmailNotifications
fields to OpenAPI response type definitions for LibresignNewSigner
and LibresignIdentifyAccount.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-16 19:12:58 -03:00
Vitor Mattos
960af717bc
feat: add custom description to gateway notifications
Support custom signer descriptions in SMS, Signal, Telegram, WhatsApp,
and XMPP notifications. The description is prepended to the notification
message when provided, allowing personalized instructions through all
supported notification channels.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-16 19:12:58 -03:00
Vitor Mattos
a4d5a5f854
fix: check Activity admin setting in notification listener
Add explicit check for Activity admin (global) setting before checking
user preference for in-app notifications. This ensures consistency
across all notification channels and prevents users from enabling
notifications when disabled globally by the admin.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-16 19:12:58 -03:00
Vitor Mattos
31b097bdda
fix: check Activity admin setting before user preference
Add explicit check for Activity admin (global) setting before checking
user preference in email notifications. This ensures that when an admin
disables email notifications globally, users cannot override it with
their personal settings. The admin setting acts as a gate that must be
enabled for user preferences to take effect.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-16 19:12:58 -03:00
Vitor Mattos
5f9cf28d75
feat: add custom description to email notifications
Add optional description parameter to notifyUnsignedUser and
notifySignDataUpdated methods. When provided, the custom message is
prepended to the email body, allowing personalized instructions for
signers.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-16 19:12:58 -03:00
Vitor Mattos
66327f1d99
feat: store description in notification metadata
Include signer description in notification metadata when incrementing
notification counter. This allows tracking custom messages sent to
signers for each notification attempt.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-16 19:12:58 -03:00
Vitor Mattos
b0304dbe60
feat: persist signer identify method tab preference
Save user's selected tab (Account/Email) in the 'Add new signer' modal
to userconfig store. The preference is now persisted across modal
closures and page reloads, improving user experience by remembering
the last selected identification method.

Changes:
- Add activeTab state to RequestSignatureTab component
- Load saved tab preference from userconfig store on mount
- Save tab changes to backend with debounce (500ms)
- Add signer_identify_tab to AccountService config output
- Use snake_case naming convention for consistency with backend

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-16 10:47:34 -03:00
Vitor Mattos
3d4bdf0294
fix: filter CA ID from OU only when certificate not generated
The CA ID (libresign-ca-id:...) in OrganizationalUnit should only be
filtered out when the certificate is not generated (isSetupOk() returns
false). When the certificate is successfully generated, the CA ID must
be preserved in the API response.

This ensures:
- Generated certificates: CA ID is visible (expected behavior)
- Failed/not generated: CA ID is filtered to prevent stale data in form

Integration tests validated:
- features/account/signature.feature:2 (OpenSSL)
- features/account/signature.feature:23 (CFSSL)
- features/admin/certificate_openssl.feature:2
- features/admin/certificate_openssl.feature:35

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-15 17:39:24 -03:00
Vitor Mattos
249f0837b0
fix: prevent stale configPath and CA ID exposure in root certificate API
Filter configPath from API response when certificate is not generated to prevent
form pre-population with outdated generation numbers that cause validation errors.

Filter CA ID (libresign-ca-id:*) from OrganizationalUnit field to prevent users
from submitting stale generation values that conflict with certificate validation.

Refactor toArray() method by extracting logic into dedicated methods:
- getConfigPathForApi(): Returns empty string for non-generated certificates
- removeCaIdFromOrganizationalUnit(): Filters CA IDs from OU arrays

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-15 16:57:17 -03:00
Vitor Mattos
5618b286e5
fix: update PDF path in DevelopController
Update path from tests/php/fixtures/small_valid.pdf to
tests/php/fixtures/pdfs/small_valid.pdf after file reorganization.

Fixes /apps/libresign/develop/pdf route.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-15 16:02:35 -03:00
Vitor Mattos
9274075bf8
chore: update dependencies and handler
Update composer.json and Pkcs12Handler changes from refactoring.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-15 15:53:02 -03:00
Vitor Mattos
114b4eabd1
test: fix unit tests for DocMDP per-file feature
- Add docmdpLevel to LibresignValidateFile schema in ResponseDefinitions
- Add DocMdpConfigService mock to RequestSignatureServiceTest
- Fix constructor parameter order in RequestSignatureServiceTest
- Mock validateDocMdpAllowsSignatures in SignFileServiceTest
- Mock getDocmdpLevelEnum to return NOT_CERTIFIED in test scenarios
- Fixes OpenAPI schema validation errors
- Fixes ArgumentCountError in RequestSignatureService tests
- Fixes enum mocking issues in SignFileService tests

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-14 16:38:34 -03:00
Vitor Mattos
c43159c777
feat: include docmdpLevel in API responses
- Add docmdp_level to SELECT and GROUP BY in SignRequestMapper
- Format docmdpLevel as integer in API response
- Add docmdpLevel to FileService::loadLibreSignData()
- Ensures frontend receives per-file DocMDP configuration

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-14 16:38:34 -03:00
Vitor Mattos
8acb7f8576
feat: validate DocMDP per file before signing
- Update validateDocMdpAllowsSignatures() to check file's docmdpLevel first
- Falls back to PDF extraction for legacy files (level 0)
- Throws consistent error message for DocMDP level 1
- Prevents adding signatures to certified documents with no changes allowed

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-14 16:38:34 -03:00
Vitor Mattos
cff28b6ceb
feat: save DocMDP level from global config to file on creation
- Add DocMdpConfigService dependency to RequestSignatureService
- Create setDocMdpLevelFromGlobalConfig() method
- Save admin DocMDP configuration to file entity on creation
- Allows per-file DocMDP configuration instead of only global

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-14 16:38:34 -03:00
Vitor Mattos
3a026f5c10
feat: add docmdp_level column to libresign_file table
- Add migration to create docmdp_level column (SMALLINT, default 0)
- Add docmdpLevel property to File entity with getters/setters
- Add getDocmdpLevelEnum() and setDocmdpLevelEnum() methods
- DocMDP levels: 0=not certified, 1=no changes, 2=form fill, 3=annotations

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-14 16:38:34 -03:00
Vitor Mattos
d5e3cae60c
refactor: remove unused IAppConfig dependency from SequentialSigningService
IAppConfig was injected but never used in any method.
Removed dependency to clean up constructor.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-14 14:00:30 -03:00
Vitor Mattos
a22fef141b
refactor: extract status logic from RequestSignatureService
Injected FileStatusService and SignRequestStatusService to delegate
all status-related operations. Removed status determination methods
and notification validation logic, delegating to specialized services.
Updated method calls to use appropriate service methods.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-14 13:53:09 -03:00
Vitor Mattos
d74ffe257d
feat: add SignRequestStatusService for sign request status logic
Created dedicated service to manage sign request status determination
and validation. Implements shouldNotifySignRequest, canNotifySignRequest,
updateStatusIfAllowed, determineInitialStatus, and private helper methods
for status calculation based on file status, signer status, signing order,
and flow type (parallel/sequential).

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-14 13:53:02 -03:00
Vitor Mattos
ecc8a6a2f1
feat: add FileStatusService for file status operations
Created dedicated service to handle file status management.
Includes updateFileStatusIfUpgrade to upgrade file status and
canNotifySigners to validate if file status allows notifications.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-14 13:52:53 -03:00
Vitor Mattos
9349178f67
fix: cs
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-13 17:24:36 -03:00
Vitor Mattos
65d0f90086
refactor: extract cancellation event logic to dedicated method
Extracts the SignRequestCanceledEvent dispatching logic from
unassociateToUser into a dedicated dispatchCancellationEventIfNeeded
method for better code organization and single responsibility.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-13 17:22:59 -03:00
Vitor Mattos
05f609537a
chore: rollback to default value
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-13 17:20:01 -03:00
Vitor Mattos
f4f03eed71
fix: cs
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-13 17:18:31 -03:00
Vitor Mattos
0cf44f0865
fix: standardize notification defaults to false
Changes default values for email and push notifications to false
in LibresignActivitySettings, ensuring all LibreSign activity types
follow the same pattern and respect user opt-in preference.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-13 17:17:59 -03:00
Vitor Mattos
29b887a098
feat: register SignRequestCanceledEvent listeners in Application
Registers all three listeners (Notification, Mail, and Activity)
for the SignRequestCanceledEvent in the application bootstrap.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-13 17:16:43 -03:00
Vitor Mattos
f06e664ec1
feat: handle SignRequestCanceledEvent in Activity Listener
Registers the cancellation event in the activity stream,
allowing users to see signature request cancellations
in their activity history.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-13 17:16:30 -03:00
Vitor Mattos
a09013e0a8
feat: handle SignRequestCanceledEvent in MailNotifyListener
Implements email notification for canceled signature requests.
Sends email to users informing them that their signature
request has been canceled.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-13 17:16:16 -03:00
Vitor Mattos
c863c72313
feat: add notification message for canceled signature requests
Implements the notification message formatting in Notifier
to display cancellation notifications with proper subject
and message text.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-13 17:16:03 -03:00
Vitor Mattos
6009a86f73
feat: handle SignRequestCanceledEvent in NotificationListener
Implements the notification handler for canceled signature requests.
Sends in-app notifications to users when their signature request
is canceled, respecting user activity settings preferences.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-13 17:15:50 -03:00
Vitor Mattos
ced672accc
feat: add Activity settings and provider for signature request cancellation
Creates the Activity components for the cancellation notification:
- SignRequestCanceled settings class
- SignRequestCanceled provider for activity stream

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-13 17:15:36 -03:00
Vitor Mattos
135143dd1b
feat: dispatch SignRequestCanceledEvent when signature request is canceled
When a signature request with status ABLE_TO_SIGN is deleted,
dispatch the SignRequestCanceledEvent for each identify method.
This allows notification and email listeners to inform users
about the cancellation.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-13 17:15:16 -03:00
Vitor Mattos
75ddc77012
feat: add SignRequestCanceledEvent
This event is dispatched when a signature request is canceled,
allowing listeners to send notifications to the affected user.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-13 17:14:59 -03:00
Vitor Mattos
5d33e0b1f4
fix: Prioritize file status over signer status in parallel flow
When file status is ABLE_TO_SIGN (1) in parallel flow, all signers
should be set to ABLE_TO_SIGN regardless of individual signer status
sent by frontend. This fixes the issue where signers remained in DRAFT
status (0) even after clicking 'Request signatures'.

The logic now:
1. Check file status DRAFT first - keep all signers as DRAFT
2. Check file status ABLE_TO_SIGN - apply flow-based logic:
   - Parallel: All signers get ABLE_TO_SIGN
   - Ordered: Only first signer gets ABLE_TO_SIGN
3. Fallback to individual signer status for other cases

Resolves issue where sign_request records stayed at status 0 while
libresign_file was updated to status 1.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-13 10:07:04 -03:00
Vitor Mattos
e97580bc21
fix: correctly increment order counter after user-provided order
When user provides a specific signing order, the next auto-assigned
order should be the provided value + 1.

Changed condition from > to >= and set currentOrder to userProvidedOrder + 1
instead of just userProvidedOrder.

This ensures proper order sequencing when mixing user-provided and
auto-assigned orders.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-12 17:27:11 -03:00
Vitor Mattos
df44227af1
fix: add signatureFlow to ValidateFile schema
Add signatureFlow field to ValidateFile schema in OpenAPI specs and
ResponseDefinitions.

- Update openapi.json and openapi-full.json schemas
- Add signatureFlow to LibresignValidateFile psalm type
- Mark as required field with integer type

This fixes OpenAPI validation errors in API tests.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-12 17:18:55 -03:00
Vitor Mattos
1d62e46b5c
refactor: move signature flow constants to enum
Move database value constants from File entity to SignatureFlow enum
where they belong as the single source of truth.

- Add SignatureFlow::NUMERIC_PARALLEL and NUMERIC_ORDERED_NUMERIC
- Remove circular dependency between File and SignatureFlow
- Update all references to use enum constants
- Use descriptive names instead of abbreviations

This follows single responsibility principle: the enum owns its
database representation.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-12 17:14:12 -03:00
Vitor Mattos
a02bb43ebf
chore: remove unecessary docblock
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-12 17:05:04 -03:00
Vitor Mattos
8a4e018c6a
feat: include signatureFlow in API responses
Expose signature flow configuration in file list and detail endpoints.

FileService changes:
- Add signatureFlow to fileData object in formatFile()

SignRequestMapper changes:
- Include f.signature_flow in SELECT query
- Convert numeric value to enum string in formatListRow()
- Remove signature_flow from response (cleanup after conversion)

This enables frontend to display and use per-file signature flow
configuration.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-12 17:02:18 -03:00
Vitor Mattos
3ac6e064f6
refactor: pass file entity to SequentialSigningService in SignFileService
Update releaseNextOrder call to provide file entity context.

- Call setFile() before releaseNextOrder()
- Enables SequentialSigningService to read file-level signature flow

This ensures signature flow logic uses the correct per-file
configuration during document signing workflow.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-12 17:01:47 -03:00
Vitor Mattos
7918cd51c5
feat: implement signature flow handling in RequestSignatureService
Add signature flow parameter processing and file configuration logic.

- Parse signatureFlow from request data and convert to enum
- Fall back to global config if parameter invalid or missing
- Set file entity signature flow via setSignatureFlowEnum()
- Initialize SequentialSigningService with file entity context
- Add IAppConfig dependency for global fallback

This completes the backend logic for per-file signature flow
configuration with graceful fallback to system defaults.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-12 17:01:13 -03:00
Vitor Mattos
c16ba73bc8
feat: add signatureFlow parameter to request-signature endpoint
Add optional signatureFlow parameter to POST /request-signature API.

- Accepts 'parallel' or 'ordered_numeric' values
- Falls back to global configuration if not provided
- Documented in PHPDoc and OpenAPI annotations

This enables clients to specify signature flow mode per document
when creating signature requests.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-12 17:00:53 -03:00
Vitor Mattos
ad71acbbcd
refactor: use file-level signature flow in SequentialSigningService
Replace global config dependency with file-level signature flow.

- Add setFile() method to inject File entity
- Replace getSignatureFlow() to read from file instead of IAppConfig
- Remove IAppConfig dependency (no longer needed)
- Add validation: throws LogicException if getSignatureFlow() called without file

This enables per-file signature flow configuration while maintaining
backward compatibility through database default values.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-12 16:59:14 -03:00
Vitor Mattos
ff7b64b526
feat: add signature flow support to File entity
Add signatureFlow property and enum conversion helper methods to File entity.

- New protected property: signatureFlow (SMALLINT, default 1)
- getSignatureFlowEnum(): Returns SignatureFlow enum from integer
- setSignatureFlowEnum(): Sets integer from SignatureFlow enum

These methods provide type-safe access to signature flow configuration
stored in the database.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-12 16:58:51 -03:00
Vitor Mattos
0f89027464
feat: add signature_flow column to libresign_file table
Add signature_flow column to store signature flow mode at file level.

- Column type: SMALLINT NOT NULL DEFAULT 1
- 1 = parallel (default)
- 2 = ordered_numeric

This enables per-file configuration of signature flow, overriding the
global application setting when specified.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-12 16:58:18 -03:00
Vitor Mattos
abf6bb70b1
feat: add numeric conversion methods to SignatureFlow enum
Add toNumeric() and fromNumeric() methods to enable conversion between
SignatureFlow enum values and their integer database representations.

- PARALLEL = 1
- ORDERED_NUMERIC = 2

This allows storing signature flow as integers in the database while
maintaining type-safe enum usage in the code.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-12 16:57:57 -03:00
Vitor Mattos
6f83a9c04d
fix: set default value for signer_order column in migration
Set default value of 0 for signer_order column to prevent NULL values
that would cause issues with sequential signing feature.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-12 16:30:59 -03:00
Vitor Mattos
ede3fe8b9b
fix: cs
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-12 15:07:42 -03:00
Vitor Mattos
48915dca4b
refactor: delegate status validation to SequentialSigningService
Remove internal validation methods from RequestSignatureService and
delegate to SequentialSigningService for better separation of concerns.

Changes:
- Remove hasPendingLowerOrderSigners() private method
- Remove isStatusUpgrade() private method
- Replace inline ordering validation with call to
  validateStatusByOrder()
- Simplify determineInitialStatus() by delegating validation logic

This reduces complexity in RequestSignatureService and makes the code
more maintainable by following single responsibility principle. All
sequential signing logic is now centralized in the specialized service.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
2025-12-12 15:03:52 -03:00