Skip to content

[stable32] feat: envelope support#6254

Merged
vitormattos merged 265 commits intostable32from
backport/6242/stable32
Dec 30, 2025
Merged

[stable32] feat: envelope support#6254
vitormattos merged 265 commits intostable32from
backport/6242/stable32

Conversation

@backportbot-libresign
Copy link
Copy Markdown

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

Backport of #6242

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

Todo

  • Review and resolve any conflicts
  • Remove all the empty commits
  • 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.

@github-project-automation github-project-automation Bot moved this to 0. Needs triage in Roadmap Dec 29, 2025
@backportbot-libresign backportbot-libresign Bot added this to the Next Patch (32) milestone Dec 29, 2025
@vitormattos vitormattos deleted the backport/6242/stable32 branch December 29, 2025 14:03
@github-project-automation github-project-automation Bot moved this from 0. Needs triage to 4. to release in Roadmap Dec 29, 2025
@vitormattos vitormattos restored the backport/6242/stable32 branch December 29, 2025 21:46
@vitormattos vitormattos reopened this Dec 29, 2025
@github-project-automation github-project-automation Bot moved this from 4. to release to 1. to do in Roadmap Dec 29, 2025
- Create new FileUploadHelper with validateUploadedFile() and readUploadedFile()
- Centralizes upload validation (error check, is_uploaded_file, filename validation, size check)
- Automatic cleanup (@Unlink) before throwing exceptions
- Comprehensive unit tests with 7 test cases covering all edge cases
- Mock is_uploaded_file() via namespace for testing
- Follows Nextcloud core patterns (AvatarControllerTest)

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
- Add validateEnvelopeConstraints() method for business rule validation
- Validate envelope_enabled and envelope_max_files before processing files
- Fix uploadHelper property conflict with TFile trait
- Improves separation of concerns: FileService owns validation logic

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
- Import OCP\Files\Node for proper type resolution
- Fix Psalm docblock type annotations
- Use fully qualified namespace in return types

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
- Remove duplicate fileName extraction logic in saveFiles
- Let prepareFileForSaving handle all name extraction
- Fix Psalm type annotations with fully qualified namespaces
- Add inline @var annotation for  parameter type

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
- Add FileUploadHelper mock to AccountServiceTest
- Add FileUploadHelper instance to FileServiceTest
- Add FileUploadHelper mock to IdDocsServiceTest
- Replace FileService with FileUploadHelper in RequestSignatureServiceTest
- All services now correctly inject FileUploadHelper dependency

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
- Generate folderName once in saveEnvelope() using envelope UUID
- Pass same folderName to all files via settings
- Pattern: envelope-{uuid} ensures uniqueness across envelopes
- All files in an envelope now go to the same folder

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
- Changed property type from FileUploadHelper&MockObject to FileUploadHelper
- Use \OCP\Server::get(FileUploadHelper::class) to get real instance
- Fixes 'File is too big' test that requires actual validation logic
- All 105 FileServiceTest tests now passing

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
- Suppress file_get_contents warning in FileUploadHelper::readUploadedFile()
- Fix risky test in FileUploadHelperTest::testValidateUploadedFileWithForbiddenName
- Add explicit escape parameter to str_getcsv in FooterHandlerTest (PHP 8.4 compat)
- Tests now properly skip when OS-specific conditions aren't met

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Expose file validation without node creation, allowing controllers
to validate uploaded files before deciding the file creation strategy.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Changed processUploadedFiles to only validate and return file data
instead of creating nodes immediately. This ensures nodes are created
with the correct envelope folder path in saveEnvelope.

- processUploadedFiles now returns uploadedFile data structure
- Node creation moved to RequestSignatureService.saveEnvelope
- Fixed return type annotation to include uploadedFile field

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Envelope creation now ensures atomicity:
- Generate envelope UUID and folderName before creating nodes
- Create nodes with correct settings containing folderName
- Rollback all changes (nodes, files, envelope) on any error

Added dedicated rollback methods:
- rollbackEnvelopeCreation: orchestrates complete rollback
- rollbackCreatedNodes: removes filesystem nodes
- rollbackCreatedFiles: removes file entities from database
- rollbackEnvelope: removes envelope entity from database

This prevents partial envelope creation and ensures data consistency.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
- Validate envelope_enabled config before creating envelopes
- Throw descriptive exception when feature is disabled
- Keep original error message for maximum files exceeded

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Update expected message to match actual error message:
'Maximum number of files per envelope (2) exceeded'

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Detect and delegate uploadedFile processing to getNodeFromUploadedFile
method instead of trying to extract base64 from non-existent file data.
This fixes TypeError when uploading single files via file upload.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Added handling for uploadedFile case in prepareFileForSaving method.
When a single file is uploaded via file upload, it now correctly
validates and creates the node using the uploadedFile data.

Also fixed list endpoint to skip envelopes when loading user settings,
preventing 'File not found' errors for envelope nodes.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Add envelope_enabled to initial state in PageController and
TemplateLoader, allowing frontend components to respect the
administrative configuration for envelope support.

This enables proper control of multiple file uploads based on
whether the envelope feature is enabled or disabled.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Load envelope_enabled from initial state and use it to control
whether multiple file selection is allowed in the upload dialog.

When envelope feature is disabled, only single file uploads are
permitted. When enabled, users can select multiple files to create
an envelope.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
- Changed getThumbnail to use fileMapper->getByFileId instead of fileService->getMyLibresignFile
- getMyLibresignFile depends on signRequestMapper which requires sign requests to exist
- DRAFT files without signers were returning 404 on thumbnail endpoint
- Now uses direct file lookup with ownership verification

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Enable multi-line text display for document certification descriptions
in SignerDetails component by overriding NcListItem's default ellipsis
behavior. This ensures users can read the complete certification level
description without truncation.

- Override --list-item-height to auto for .extra-chain items
- Force white-space: normal to allow line breaks
- Disable text-overflow ellipsis behavior

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
- Derive name from URL path in FileService::getNodeFromData
- Fallback to node name when data['name'] is empty in RequestSignatureService::saveFile
- Accept localhost URLs in FileContentProvider validation

Prevents file.name being null/empty when importing by URL.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
When uploading multiple files with envelope support enabled, prompt
the user to enter a name for the envelope before proceeding with the
upload. The name field is limited to 256 characters to match the
backend constraint.

- Add modal dialog to collect envelope name
- Validate non-empty envelope name before upload
- Include envelope name in FormData for multi-file uploads
- Add cancel handler to abort envelope creation
- Reset envelope state after upload completes

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Add optional 'name' parameter to updateSign() method allowing
envelope name updates via PATCH requests. Includes PHPDoc
documentation for the new parameter.

This enables updating envelope names without requiring signers
to be provided in the request.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Make validateIdentifySigners() return early if users array is empty,
allowing PATCH requests to update envelope properties (like name)
without requiring signers to be provided.

This prevents 'No signers' validation errors when updating envelope
metadata without modifying the signer list.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Add support for updating envelope name when uuid is provided and
name is present in the request data. Updates the file entity and
persists the change to the database.

This allows existing envelopes to be renamed via PATCH requests
without affecting their status or signers.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Create standalone dialog component for editing names with:
- Character counter (0-255 chars)
- Min/max length validation (3-255 chars)
- Success/error message display
- Disabled save button for invalid input
- Generic and reusable for various use cases

The component encapsulates all validation logic, styling,
and event handling, allowing reuse across RequestPicker
and other parts of the application.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Replace inline NcDialog form with reusable EditNameDialog component:
- Removes duplicate code (~17 lines)
- Adds consistent validation (3-255 chars)
- Improves UX with character counter and validation feedback
- Simplifies confirmEnvelopeName to receive name as parameter

Maintains all existing functionality while improving code
maintainability and user experience.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Implement inline envelope name editing in EnvelopeFilesList with:
- Direct NcTextField in header (no modal needed)
- 1-second debounce for auto-save
- Real-time validation (3-255 chars)
- Inline feedback (success/error states)
- Loading indicator during save
- Helper text for validation messages

User experience improvements:
- Edit name directly without clicking edit button
- Automatic save after typing stops
- Immediate visual feedback on success/error
- No need to manually trigger save action

Replaces modal-based editing for more fluid UX.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
- Add async rename(uuid, newName) method
- Makes PATCH request to /apps/libresign/api/v1/request-signature
- Updates file name in store on success
- Returns boolean indicating success/failure

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
- Add conditional rendering of rename form with NcTextField
- Implement startRenaming() to activate form with auto-focus and text selection
- Implement stopRenaming() to close form and reset state
- Implement onRename() to validate and emit rename event
- Add renaming event to notify parent components about editing state
- Add styling for inline rename form with border and padding

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
- Import pencil-outline icon (mdi-pencil-outline)
- Register 'rename' action in mounted hook
- Add rename action handler in onActionClick to emit 'start-rename' event
- Implement doRename(newName) method that calls filesStore.rename()
- Add 'rename' and 'start-rename' to component emits

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
- Add renamingSaving state to show spinner only during API request
- Listen to 'rename' event from FileEntryName and trigger doRename()
- Listen to 'renaming' event from FileEntryName to track editing state
- Listen to 'start-rename' event from FileEntryActions to activate form
- Close rename form after successful save with stopRenaming()
- Show success notification with renamed filename information
- Update checkbox loading state to include renamingSaving indicator

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
…ition NcActions using CSS vars on .app-content (non-scoped transform)\n- Constrain popper with boundaries/container to .app-content > .files-list\n- Clear --mouse-pos-x/y on NcActions @closed only when no menu open\n- Close previous menu and reopen on nextTick to avoid stale content\n\nfix(actions): hide "Open file" for envelopes; DRY file lookup\n\n- Do not show "Open file" when source.nodeType is envelope\n- Add computed file and refactor visibleIf to reuse it\n\nMatches Nextcloud Files behavior and prevents flicker/jump.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
…pe settings section with a switch to enable/disable envelopes (writes to app config key 'envelope_enabled').\n- Reads initial value from provisioning API and updates capabilities via backend check.\n- Matches existing settings patterns (NcCheckboxRadioSwitch, OCP.AppConfig).

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
@vitormattos vitormattos marked this pull request as ready for review December 29, 2025 23:13
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
@vitormattos vitormattos force-pushed the backport/6242/stable32 branch from a43e899 to da41c10 Compare December 29, 2025 23:44
@vitormattos vitormattos merged commit 7f94b1d into stable32 Dec 30, 2025
52 of 62 checks passed
@vitormattos vitormattos deleted the backport/6242/stable32 branch December 30, 2025 00:02
@github-project-automation github-project-automation Bot moved this from 1. to do to 4. to release in Roadmap Dec 30, 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