mirror of
https://github.com/documenso/documenso.git
synced 2025-11-13 00:03:33 +10:00
fix: prevent hidden layers from being toggled in pdf viewers (#1528)
https://github.com/user-attachments/assets/e10194ca-212b-40ee-b9a1-85ef54829a40 --------- Co-authored-by: Mythie <me@lucasjamessmith.me>
This commit is contained in:
@ -6,8 +6,12 @@ import PostHogServerClient from '@documenso/lib/server-only/feature-flags/get-po
|
|||||||
import { DOCUMENT_AUDIT_LOG_TYPE } from '@documenso/lib/types/document-audit-logs';
|
import { DOCUMENT_AUDIT_LOG_TYPE } from '@documenso/lib/types/document-audit-logs';
|
||||||
import { createDocumentAuditLogData } from '@documenso/lib/utils/document-audit-logs';
|
import { createDocumentAuditLogData } from '@documenso/lib/utils/document-audit-logs';
|
||||||
import { prisma } from '@documenso/prisma';
|
import { prisma } from '@documenso/prisma';
|
||||||
import { DocumentStatus, RecipientRole, SigningStatus } from '@documenso/prisma/client';
|
import {
|
||||||
import { WebhookTriggerEvents } from '@documenso/prisma/client';
|
DocumentStatus,
|
||||||
|
RecipientRole,
|
||||||
|
SigningStatus,
|
||||||
|
WebhookTriggerEvents,
|
||||||
|
} from '@documenso/prisma/client';
|
||||||
import { signPdf } from '@documenso/signing';
|
import { signPdf } from '@documenso/signing';
|
||||||
|
|
||||||
import { ZWebhookDocumentSchema } from '../../types/webhook-payload';
|
import { ZWebhookDocumentSchema } from '../../types/webhook-payload';
|
||||||
|
|||||||
@ -9,8 +9,8 @@ import {
|
|||||||
RecipientRole,
|
RecipientRole,
|
||||||
SendStatus,
|
SendStatus,
|
||||||
SigningStatus,
|
SigningStatus,
|
||||||
|
WebhookTriggerEvents,
|
||||||
} from '@documenso/prisma/client';
|
} from '@documenso/prisma/client';
|
||||||
import { WebhookTriggerEvents } from '@documenso/prisma/client';
|
|
||||||
|
|
||||||
import { jobs } from '../../jobs/client';
|
import { jobs } from '../../jobs/client';
|
||||||
import { extractDerivedDocumentEmailSettings } from '../../types/document-email';
|
import { extractDerivedDocumentEmailSettings } from '../../types/document-email';
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
import type { PDFField, PDFWidgetAnnotation } from 'pdf-lib';
|
import type { PDFField, PDFWidgetAnnotation } from 'pdf-lib';
|
||||||
import { PDFCheckBox, PDFRadioGroup, PDFRef } from 'pdf-lib';
|
|
||||||
import {
|
import {
|
||||||
|
PDFCheckBox,
|
||||||
PDFDict,
|
PDFDict,
|
||||||
type PDFDocument,
|
type PDFDocument,
|
||||||
PDFName,
|
PDFName,
|
||||||
|
PDFRadioGroup,
|
||||||
|
PDFRef,
|
||||||
drawObject,
|
drawObject,
|
||||||
popGraphicsState,
|
popGraphicsState,
|
||||||
pushGraphicsState,
|
pushGraphicsState,
|
||||||
@ -11,7 +13,18 @@ import {
|
|||||||
translate,
|
translate,
|
||||||
} from 'pdf-lib';
|
} from 'pdf-lib';
|
||||||
|
|
||||||
|
export const removeOptionalContentGroups = (document: PDFDocument) => {
|
||||||
|
const context = document.context;
|
||||||
|
const catalog = context.lookup(context.trailerInfo.Root);
|
||||||
|
|
||||||
|
if (catalog instanceof PDFDict) {
|
||||||
|
catalog.delete(PDFName.of('OCProperties'));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const flattenForm = (document: PDFDocument) => {
|
export const flattenForm = (document: PDFDocument) => {
|
||||||
|
removeOptionalContentGroups(document);
|
||||||
|
|
||||||
const form = document.getForm();
|
const form = document.getForm();
|
||||||
|
|
||||||
form.updateFieldAppearances();
|
form.updateFieldAppearances();
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import { DocumentDataType } from '@documenso/prisma/client';
|
|||||||
|
|
||||||
import { AppError } from '../../errors/app-error';
|
import { AppError } from '../../errors/app-error';
|
||||||
import { createDocumentData } from '../../server-only/document-data/create-document-data';
|
import { createDocumentData } from '../../server-only/document-data/create-document-data';
|
||||||
|
import { removeOptionalContentGroups } from '../../server-only/pdf/flatten-form';
|
||||||
|
|
||||||
type File = {
|
type File = {
|
||||||
name: string;
|
name: string;
|
||||||
@ -24,20 +25,25 @@ export const putPdfFile = async (file: File) => {
|
|||||||
() => false,
|
() => false,
|
||||||
);
|
);
|
||||||
|
|
||||||
// This will prevent uploading encrypted PDFs or anything that can't be opened.
|
const pdf = await PDFDocument.load(await file.arrayBuffer()).catch((e) => {
|
||||||
if (!isEncryptedDocumentsAllowed) {
|
console.error(`PDF upload parse error: ${e.message}`);
|
||||||
await PDFDocument.load(await file.arrayBuffer()).catch((e) => {
|
|
||||||
console.error(`PDF upload parse error: ${e.message}`);
|
|
||||||
|
|
||||||
throw new AppError('INVALID_DOCUMENT_FILE');
|
throw new AppError('INVALID_DOCUMENT_FILE');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!isEncryptedDocumentsAllowed && pdf.isEncrypted) {
|
||||||
|
throw new AppError('INVALID_DOCUMENT_FILE');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!file.name.endsWith('.pdf')) {
|
if (!file.name.endsWith('.pdf')) {
|
||||||
file.name = `${file.name}.pdf`;
|
file.name = `${file.name}.pdf`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { type, data } = await putFile(file);
|
removeOptionalContentGroups(pdf);
|
||||||
|
|
||||||
|
const bytes = await pdf.save();
|
||||||
|
|
||||||
|
const { type, data } = await putFile(new File([bytes], file.name, { type: 'application/pdf' }));
|
||||||
|
|
||||||
return await createDocumentData({ type, data });
|
return await createDocumentData({ type, data });
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user