From 8f903651e6e9d8b52a072186264cafcc23f294fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20Sz=C3=BCcs?= Date: Sat, 15 Nov 2025 19:43:53 +0100 Subject: [PATCH 1/2] feat(pipeline): add pre-publish sanitization workflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Created `Pre-publish-sanitization.json` default pipeline configuration - Added sanitization operations removing metadata, JavaScript, embedded files, and annotations - Registered new pipeline in `GeneralUtils` - Included "Pre-publish Sanitization" in the suggested automations list Signed-off-by: Balázs Szücs --- .../software/common/util/GeneralUtils.java | 1 + .../Pre-publish-sanitization.json | 54 +++++++++++++++++ .../tools/automate/useSuggestedAutomations.ts | 58 +++++++++++++++++++ .../useChangeMetadataOperation.ts | 16 ++--- 4 files changed, 122 insertions(+), 7 deletions(-) create mode 100644 app/core/src/main/resources/static/pipeline/defaultWebUIConfigs/Pre-publish-sanitization.json diff --git a/app/common/src/main/java/stirling/software/common/util/GeneralUtils.java b/app/common/src/main/java/stirling/software/common/util/GeneralUtils.java index 10ac8b595..ecf0d75d4 100644 --- a/app/common/src/main/java/stirling/software/common/util/GeneralUtils.java +++ b/app/common/src/main/java/stirling/software/common/util/GeneralUtils.java @@ -38,6 +38,7 @@ public class GeneralUtils { Set.of( "OCR images.json", "Prepare-pdfs-for-email.json", + "Pre-publish-sanitization.json", "split-rotate-auto-rename.json"); private final String DEFAULT_WEBUI_CONFIGS_DIR = "defaultWebUIConfigs"; diff --git a/app/core/src/main/resources/static/pipeline/defaultWebUIConfigs/Pre-publish-sanitization.json b/app/core/src/main/resources/static/pipeline/defaultWebUIConfigs/Pre-publish-sanitization.json new file mode 100644 index 000000000..797c191f3 --- /dev/null +++ b/app/core/src/main/resources/static/pipeline/defaultWebUIConfigs/Pre-publish-sanitization.json @@ -0,0 +1,54 @@ +{ + "name": "Pre-publish-sanitization", + "pipeline": [ + { + "operation": "/api/v1/security/sanitize-pdf", + "parameters": { + "removeJavaScript": true, + "removeEmbeddedFiles": true, + "removeXMPMetadata": true, + "removeMetadata": true, + "removeLinks": false, + "removeFonts": false + } + }, + { + "operation": "/api/v1/misc/flatten", + "parameters": { + "flattenOnlyForms": true + } + }, + { + "operation": "/api/v1/general/remove-annotations", + "parameters": {} + }, + { + "operation": "/api/v1/misc/update-metadata", + "parameters": { + "deleteAll": true, + "author": "", + "creationDate": "", + "creator": "", + "keywords": "", + "modificationDate": "", + "producer": "", + "subject": "", + "title": "", + "trapped": "" + } + }, + { + "operation": "/api/v1/misc/compress-pdf", + "parameters": { + "optimizeLevel": 3, + "expectedOutputSize": "" + } + } + ], + "_examples": { + "outputDir": "{outputFolder}/{folderName}", + "outputFileName": "{filename}-{pipelineName}-{date}-{time}" + }, + "outputDir": "{outputFolder}", + "outputFileName": "pre_publish_{filename}.PDF" +} diff --git a/frontend/src/core/hooks/tools/automate/useSuggestedAutomations.ts b/frontend/src/core/hooks/tools/automate/useSuggestedAutomations.ts index 378380050..30c33f7fa 100644 --- a/frontend/src/core/hooks/tools/automate/useSuggestedAutomations.ts +++ b/frontend/src/core/hooks/tools/automate/useSuggestedAutomations.ts @@ -9,6 +9,7 @@ import { SPLIT_METHODS } from '@app/constants/splitConstants'; const CompressIcon = () => React.createElement(LocalIcon, { icon: 'compress', width: '1.5rem', height: '1.5rem' }); const SecurityIcon = () => React.createElement(LocalIcon, { icon: 'security', width: '1.5rem', height: '1.5rem' }); const StarIcon = () => React.createElement(LocalIcon, { icon: 'star', width: '1.5rem', height: '1.5rem' }); +const PrivacyIcon = () => React.createElement(LocalIcon, { icon: 'shield-lock', width: '1.5rem', height: '1.5rem' }); export function useSuggestedAutomations(): SuggestedAutomation[] { const { t } = useTranslation(); @@ -67,6 +68,63 @@ export function useSuggestedAutomations(): SuggestedAutomation[] { updatedAt: now, icon: SecurityIcon, }, + { + id: "pre-publish-sanitization", + name: t("automation.suggested.prePublishSanitization", "Pre-publish Sanitization"), + description: t("automation.suggested.prePublishSanitizationDesc", "Sanitization workflow that removes all hidden metadata, JavaScript, embedded files, annotations, and flattens forms and layers to prevent data leakage before publishing PDFs online."), + operations: [ + { + operation: "sanitize", + parameters: { + removeJavaScript: true, + removeEmbeddedFiles: true, + removeXMPMetadata: true, + removeMetadata: true, + removeLinks: true, + removeFonts: false, + } + }, + { + operation: "flatten", + parameters: { + flattenOnlyForms: true, + } + }, + { + operation: "removeAnnotations", + parameters: {} + }, + { + operation: "changeMetadata", + parameters: { + deleteAll: true, + author: '', + creationDate: '', + creator: '', + keywords: '', + modificationDate: '', + producer: '', + subject: '', + title: '', + trapped: '', + } + }, + { + operation: "compress", + parameters: { + compressionLevel: 3, + grayscale: false, + expectedSize: '', + compressionMethod: 'quality', + fileSizeValue: '', + fileSizeUnit: 'MB', + } + }, + ], + createdAt: now, + updatedAt: now, + icon: PrivacyIcon, + }, { id: "email-preparation", name: t("automation.suggested.emailPreparation", "Email Preparation"), diff --git a/frontend/src/core/hooks/tools/changeMetadata/useChangeMetadataOperation.ts b/frontend/src/core/hooks/tools/changeMetadata/useChangeMetadataOperation.ts index 828fa01ab..b0692e5d6 100644 --- a/frontend/src/core/hooks/tools/changeMetadata/useChangeMetadataOperation.ts +++ b/frontend/src/core/hooks/tools/changeMetadata/useChangeMetadataOperation.ts @@ -40,13 +40,15 @@ export const buildChangeMetadataFormData = (parameters: ChangeMetadataParameters // Custom metadata - backend expects them as values to 'allRequestParams[customKeyX/customValueX]' let keyNumber = 0; - parameters.customMetadata.forEach((entry) => { - if (entry.key.trim() && entry.value.trim()) { - keyNumber += 1; - formData.append(`allRequestParams[customKey${keyNumber}]`, entry.key.trim()); - formData.append(`allRequestParams[customValue${keyNumber}]`, entry.value.trim()); - } - }); + if (parameters.customMetadata && Array.isArray(parameters.customMetadata)) { + parameters.customMetadata.forEach((entry) => { + if (entry.key.trim() && entry.value.trim()) { + keyNumber += 1; + formData.append(`allRequestParams[customKey${keyNumber}]`, entry.key.trim()); + formData.append(`allRequestParams[customValue${keyNumber}]`, entry.value.trim()); + } + }); + } return formData; }; From 20697b9987631bf4c88d4139e352ffa259087b2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20Sz=C3=BCcs?= Date: Sat, 15 Nov 2025 20:05:50 +0100 Subject: [PATCH 2/2] feat(sanitization): enable removal of links in pre-publish workflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Balázs Szücs --- .../defaultWebUIConfigs/Pre-publish-sanitization.json | 2 +- frontend/public/locales/en-GB/translation.json | 4 +++- .../src/core/hooks/tools/automate/useSuggestedAutomations.ts | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/core/src/main/resources/static/pipeline/defaultWebUIConfigs/Pre-publish-sanitization.json b/app/core/src/main/resources/static/pipeline/defaultWebUIConfigs/Pre-publish-sanitization.json index 797c191f3..2024f3003 100644 --- a/app/core/src/main/resources/static/pipeline/defaultWebUIConfigs/Pre-publish-sanitization.json +++ b/app/core/src/main/resources/static/pipeline/defaultWebUIConfigs/Pre-publish-sanitization.json @@ -8,7 +8,7 @@ "removeEmbeddedFiles": true, "removeXMPMetadata": true, "removeMetadata": true, - "removeLinks": false, + "removeLinks": true, "removeFonts": false } }, diff --git a/frontend/public/locales/en-GB/translation.json b/frontend/public/locales/en-GB/translation.json index a0f7a2666..64dbf2eaf 100644 --- a/frontend/public/locales/en-GB/translation.json +++ b/frontend/public/locales/en-GB/translation.json @@ -4619,7 +4619,9 @@ "secureWorkflow": "Security Workflow", "secureWorkflowDesc": "Secures PDF documents by removing potentially malicious content like JavaScript and embedded files, then adds password protection to prevent unauthorised access. Password is set to 'password' by default.", "processImages": "Process Images", - "processImagesDesc": "Converts multiple image files into a single PDF document, then applies OCR technology to extract searchable text from the images." + "processImagesDesc": "Converts multiple image files into a single PDF document, then applies OCR technology to extract searchable text from the images.", + "prePublishSanitization": "Pre-publish Sanitization", + "prePublishSanitizationDesc": "Sanitization workflow that removes all hidden metadata, JavaScript, embedded files, annotations, and flattens forms to prevent data leakage before publishing PDFs online." } }, "common": { diff --git a/frontend/src/core/hooks/tools/automate/useSuggestedAutomations.ts b/frontend/src/core/hooks/tools/automate/useSuggestedAutomations.ts index 30c33f7fa..c13ab3211 100644 --- a/frontend/src/core/hooks/tools/automate/useSuggestedAutomations.ts +++ b/frontend/src/core/hooks/tools/automate/useSuggestedAutomations.ts @@ -71,7 +71,7 @@ export function useSuggestedAutomations(): SuggestedAutomation[] { { id: "pre-publish-sanitization", name: t("automation.suggested.prePublishSanitization", "Pre-publish Sanitization"), - description: t("automation.suggested.prePublishSanitizationDesc", "Sanitization workflow that removes all hidden metadata, JavaScript, embedded files, annotations, and flattens forms and layers to prevent data leakage before publishing PDFs online."), + description: t("automation.suggested.prePublishSanitizationDesc", "Sanitization workflow that removes all hidden metadata, JavaScript, embedded files, annotations, and flattens forms to prevent data leakage before publishing PDFs online."), operations: [ { operation: "sanitize",