Skip to content

feat: docmdp implementation#6021

Merged
vitormattos merged 44 commits intomainfrom
feat/docmdp-implementation
Dec 8, 2025
Merged

feat: docmdp implementation#6021
vitormattos merged 44 commits intomainfrom
feat/docmdp-implementation

Conversation

@vitormattos
Copy link
Copy Markdown
Member

No description provided.

@vitormattos vitormattos added this to the Next Major (33) milestone Dec 6, 2025
@vitormattos vitormattos self-assigned this Dec 6, 2025
@github-project-automation github-project-automation Bot moved this to 0. Needs triage in Roadmap Dec 6, 2025
@vitormattos
Copy link
Copy Markdown
Member Author

/backport to stable32

@vitormattos
Copy link
Copy Markdown
Member Author

/backport to stable31

Add database columns to support DocMDP (Document Modification Detection and Prevention):

- libresign_sign_request.docmdp_level (SMALLINT, default 0)
  Stores certification level: 0=none, 1=no changes, 2=form fill, 3=form fill + annotations

- libresign_file.modification_status (SMALLINT, default 0)
  Tracks modification detection: 0=unchecked, 1=unmodified, 2=allowed, 3=violation

Both tables checked for existence before adding columns for safe migration.

Signed-off-by: Vitor Mattos <[email protected]>
Add docmdpLevel field (SMALLINT) to store DocMDP certification level
for each signature request. Includes getter/setter and type mapping.

Signed-off-by: Vitor Mattos <[email protected]>
Service to manage DocMDP configuration stored in app settings:
- isEnabled(): check if DocMDP is enabled
- setEnabled(bool): enable/disable DocMDP
- getLevel(): get default certification level (DocMdpLevel enum)
- setLevel(DocMdpLevel): set default certification level
- getConfig(): return full config with enabled status and available levels

Configuration stored in single key 'docmdp_level' for simplicity.
When disabled, key is deleted from database.

Signed-off-by: Vitor Mattos <[email protected]>
Add DocMDP support to JSignPdf signing process:
- Inject DocMdpConfigService to access admin configuration
- Add getCertificationLevel() to retrieve enabled level name
- Append -cl parameter to JSignParam when DocMDP is enabled
- Uses enum->name directly for JSignPdf compatibility

When DocMDP is enabled, JSignPdf will certify PDFs with configured level:
NOT_CERTIFIED, CERTIFIED_NO_CHANGES_ALLOWED, CERTIFIED_FORM_FILLING,
or CERTIFIED_FORM_FILLING_AND_ANNOTATIONS.

Signed-off-by: Vitor Mattos <[email protected]>
Add POST /api/v1/admin/docmdp/config endpoint:
- Accepts 'enabled' (bool) and 'defaultLevel' (int) parameters
- Validates DocMDP level with DocMdpLevel::tryFrom()
- Saves configuration via DocMdpConfigService
- Returns success message or error with appropriate HTTP status

Allows admins to enable/disable DocMDP and set default certification level.

Signed-off-by: Vitor Mattos <[email protected]>
Inject DocMdpConfigService and provide docmdp_config to frontend:
- Includes enabled status
- Includes default level
- Includes available levels with labels and descriptions

Makes DocMDP configuration available to admin settings UI.

Signed-off-by: Vitor Mattos <[email protected]>
Add Vue component for DocMDP configuration in admin settings:
- Toggle switch to enable/disable DocMDP
- Radio buttons for certification level selection:
  * No certification (P=0)
  * No changes allowed (P=1)
  * Form filling allowed (P=2)
  * Form filling and annotations (P=3)
- Loading/saving/error indicators
- Saves via POST /api/v1/admin/docmdp/config

Uses Nextcloud Vue components (NcCheckboxRadioSwitch, NcLoadingIcon,
NcSavingIndicatorIcon, NcNoteCard).

Signed-off-by: Vitor Mattos <[email protected]>
Add DocMDP information to signers array in getFileData():
- docmdp: certification level and compliance status
- modifications: detected modification types
- modification_validation: validation result details

Also improve error handling with structured logging when file content
retrieval fails, including fileId and exception context.

Makes DocMDP validation results available to frontend for display.

Signed-off-by: Vitor Mattos <[email protected]>
Add proper PHPDoc annotations:
- Detailed parameter descriptions for enabled and defaultLevel
- Complete DataResponse return type with status codes and schemas
- HTTP status code documentation (200, 400, 500)

Fixes OpenAPI generation errors.

Signed-off-by: Vitor Mattos <[email protected]>
Regenerate OpenAPI documentation files to include setDocMdpConfig endpoint:
- openapi-administration.json
- openapi-full.json
- TypeScript type definitions

Generated from updated PHPDoc annotations.

Signed-off-by: Vitor Mattos <[email protected]>
Remove unused import and fix PHPDoc formatting:
- Remove unused DocMdpLevel import from JSignPdfHandler
- Fix trailing whitespace in AdminController PHPDoc

Signed-off-by: Vitor Mattos <[email protected]>
- AdminTest: Add DocMdpConfigService mock parameter to Admin constructor
- FileServiceTest: Remove DocMDP fields (docmdp, modifications, modification_validation) from test comparisons

These tests were failing because:
1. Admin class now requires DocMdpConfigService as 9th constructor parameter
2. FileService.getFileData() now includes DocMDP-related fields in signers array

Both fixes ensure tests properly handle the new DocMDP feature additions.

Signed-off-by: Vitor Mattos <[email protected]>
- Remove duplicate getLabel() and getDescription() methods from DocMdpConfigService
- Use enum methods directly by passing IL10N instance
- Improve descriptions to differentiate between approval and certifying signatures
- Align descriptions with ISO 32000 DocMDP specification terminology

The new descriptions clearly distinguish:
- Approval signature (NOT_CERTIFIED): allows all modifications
- Certifying signature (levels 1-3): restricts modifications based on level

Signed-off-by: Vitor Mattos <[email protected]>
Consolidate PDF generation logic into a reusable trait to:
- Eliminate code duplication across test files
- Provide single source of truth for PDF fixtures
- Support both minimal (DocMdpHandler) and FPDI-valid (FileService) PDFs
- Cover all DocMDP levels and ISO 32000-1 validation scenarios

Includes 25 fixture methods covering:
- DocMDP levels 0-3
- Form field/annotation/structural modifications
- ISO signature validation edge cases
- ICP-Brasil compliance testing

Signed-off-by: Vitor Mattos <[email protected]>
Add public method to check if DocMDP level allows additional signatures.
Returns false only for CERTIFIED_NO_CHANGES_ALLOWED (level 1).

Required for FileService to validate signature requests against DocMDP policy.

Signed-off-by: Vitor Mattos <[email protected]>
Extract file validation logic from getNodeFromData() into dedicated methods:
- validateFileContent(): public method for PDF validation with FPDI
- validateDocMdpAllowsSignatures(): private method for DocMDP level 1 check

Benefits:
- Improved testability with public validation interface
- Separation of concerns (validation vs node creation)
- Enables DocMDP policy enforcement before file processing
- Adds comprehensive @throws documentation

Requires DocMdpHandler injection via FileService constructor.

Signed-off-by: Vitor Mattos <[email protected]>
Add DocMdpHandler dependency to FileService constructor to enable
DocMDP validation in TFile trait.

Assigns to TFile::docMdpHandler property for validateDocMdpAllowsSignatures().

Signed-off-by: Vitor Mattos <[email protected]>
Fix test setup and assertion patterns:
- Add missing appConfig mock initialization
- Inject DocMdpHandler from server container
- Use expectNotToPerformAssertions() for validation tests
- Place expectations at method start (PHPUnit best practice)

Validation tests assert 'no exception thrown' behavior:
- testValidateFileContentAllowsDocMdpLevel2/3
- testValidateFileContentAllowsUnsignedPdf
- testValidateFileContentSkipsNonPdfFiles
- testValidateFileContentRejectsDocMdpLevel1

Uses PdfFixtureTrait for all PDF generation.

All 98 tests passing (154 assertions).

Signed-off-by: Vitor Mattos <[email protected]>
Replace all inline PDF generation with PdfFixtureTrait methods.

Achieves 100% fixture consolidation across 39 tests.

Benefits:
- Zero code duplication
- Consistent PDF structures
- Easier maintenance
- Better test clarity

All tests passing.

Signed-off-by: Vitor Mattos <[email protected]>
Add DocMdpHandler dependency to enable future DocMDP validation
during signature request processing.

Signed-off-by: Vitor Mattos <[email protected]>
Add DocMDP admin configuration component and enhance validation view:

Settings.vue:
- Import and register DocMDP component
- Add to admin settings panel

Validation.vue:
- Display document certification level
- Show modification validation status
- Add collapsible DocMDP details section
- Visual indicators for modification status (success/warning/error)
- Icons: mdiShieldCheck, mdiShieldOff, mdiInformationOutline
- Revision count display with pluralization

Modification status mapping (File::MODIFICATION_*):
- 1 (unmodified) → green checkmark
- 2 (allowed modifications) → yellow alert
- 3 (violations) → red cancel
- 0 (unchecked) → help icon

Signed-off-by: Vitor Mattos <[email protected]>
Sort use statements alphabetically.

Signed-off-by: Vitor Mattos <[email protected]>
- Remove unused $scenarioName parameter from test method and data provider
- Use expectNotToPerformAssertions() for scenarios that shouldn't throw exceptions
- Consolidate exception expectations into if-else block for better readability
- Simplify data provider by removing redundant scenario name keys

Signed-off-by: Vitor Mattos <[email protected]>
- Extract PDF-to-resource conversion logic from validateDocMdpAllowsSignatures
- New protected method getLibreSignFileAsResource() handles file retrieval and resource creation
- Improves testability by separating I/O operations from validation logic
- Enables mocking of file access layer independently from DocMDP validation
- Maintains resource cleanup with try-finally block in validateDocMdpAllowsSignatures

Signed-off-by: Vitor Mattos <[email protected]>
- Implement DocMdpHandler to validate PDF Document Modification Detection and Prevention (DocMDP)
- Add allowsAdditionalSignatures() method to check if PDF permits additional signatures
- Support detection of DocMDP level 1 (no changes allowed) certification
- Parse PDF signature dictionaries and transformation parameters
- Prevent signatures on DocMDP level 1 certified documents per PDF specification
- Enable compliance with PDF document certification and signature workflows

Signed-off-by: Vitor Mattos <[email protected]>
- Test allowsAdditionalSignatures() with various DocMDP permission levels
- Verify unsigned PDFs allow additional signatures
- Test DocMDP level 0 (not certified) allows signatures
- Test DocMDP level 1 (no changes) blocks additional signatures
- Test DocMDP levels 2 and 3 allow signatures with form filling/annotations
- Validate DocMDP detection with real-world ICP-Brasil certificate example
- Test complete certificate chain validation (LYSEON TECH 4-level chain)
- Use PdfFixtureTrait for generating test PDFs with various DocMDP configurations
- Ensure proper resource handling and edge case coverage

Signed-off-by: Vitor Mattos <[email protected]>
Signed-off-by: Vitor Mattos <[email protected]>
- Add validation to ensure fopen() returns valid resource
- Throw LibresignException if temporary resource creation fails
- Prevents false return value that violates psalm type contract
- Add @throws LibresignException to method documentation
- Fixes psalm FalsableReturnStatement error

Signed-off-by: Vitor Mattos <[email protected]>
… line 344 to improve behavior as required.\n\nSigned-off-by: Vitor Mattos <[email protected]>

Signed-off-by: Vitor Mattos <[email protected]>
Changed implementation at line 172 as required.

Signed-off-by: Vitor Mattos <[email protected]>
…rror messages for loading and saving configuration to be more generic and user-friendly.

Signed-off-by: Vitor Mattos <[email protected]>
Tests now only check for exception type, not message, for DocMDP-related logic.

Signed-off-by: Vitor Mattos <[email protected]>
@vitormattos vitormattos force-pushed the feat/docmdp-implementation branch from 4e12696 to 0a578c2 Compare December 8, 2025 19:54
Removes translated message assertion for robustness.

Signed-off-by: Vitor Mattos <[email protected]>
Simplifies test setup and improves maintainability.

Signed-off-by: Vitor Mattos <[email protected]>
@vitormattos vitormattos merged commit 7440034 into main Dec 8, 2025
26 checks passed
@vitormattos vitormattos deleted the feat/docmdp-implementation branch December 8, 2025 20:17
@github-project-automation github-project-automation Bot moved this from 0. Needs triage to 4. to release in Roadmap Dec 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

1 participant