diff --git a/packages/lib/server-only/document/seal-document.ts b/packages/lib/server-only/document/seal-document.ts index 2cae98775..603361c5e 100644 --- a/packages/lib/server-only/document/seal-document.ts +++ b/packages/lib/server-only/document/seal-document.ts @@ -22,6 +22,7 @@ import type { RequestMetadata } from '../../universal/extract-request-metadata'; import { getFile } from '../../universal/upload/get-file'; import { putPdfFile } from '../../universal/upload/put-file'; import { fieldsContainUnsignedRequiredField } from '../../utils/advanced-fields-helpers'; +import { getAuditLogsPdf } from '../htmltopdf/get-audit-logs-pdf'; import { getCertificatePdf } from '../htmltopdf/get-certificate-pdf'; import { flattenAnnotations } from '../pdf/flatten-annotations'; import { flattenForm } from '../pdf/flatten-form'; @@ -117,6 +118,10 @@ export const sealDocument = async ({ }).catch(() => null) : null; + const auditLogData = await getAuditLogsPdf({ documentId }).catch(() => null); + + console.log({ auditLogData }); + const doc = await PDFDocument.load(pdfData); // Normalize and flatten layers that could cause issues with the signature @@ -134,6 +139,16 @@ export const sealDocument = async ({ }); } + if (auditLogData) { + const auditLog = await PDFDocument.load(auditLogData); + + const auditLogPages = await doc.copyPages(auditLog, auditLog.getPageIndices()); + + auditLogPages.forEach((page) => { + doc.addPage(page); + }); + } + for (const field of fields) { await insertFieldInPDF(doc, field); } diff --git a/packages/lib/server-only/htmltopdf/get-audit-logs-pdf.ts b/packages/lib/server-only/htmltopdf/get-audit-logs-pdf.ts new file mode 100644 index 000000000..4af5e4107 --- /dev/null +++ b/packages/lib/server-only/htmltopdf/get-audit-logs-pdf.ts @@ -0,0 +1,53 @@ +import { DateTime } from 'luxon'; +import type { Browser } from 'playwright'; + +import { NEXT_PUBLIC_WEBAPP_URL } from '../../constants/app'; +import { encryptSecondaryData } from '../crypto/encrypt'; + +export type GetAuditLogsPdfParams = { + documentId: number; +}; + +export const getAuditLogsPdf = async ({ documentId }: GetAuditLogsPdfParams) => { + const { chromium } = await import('playwright'); + + const encryptedId = encryptSecondaryData({ + data: documentId.toString(), + expiresAt: DateTime.now().plus({ minutes: 5 }).toJSDate().valueOf(), + }); + + let browser: Browser; + + if (process.env.NEXT_PRIVATE_BROWSERLESS_URL) { + // !: Use CDP rather than the default `connect` method to avoid coupling to the playwright version. + // !: Previously we would have to keep the playwright version in sync with the browserless version to avoid errors. + browser = await chromium.connectOverCDP(process.env.NEXT_PRIVATE_BROWSERLESS_URL); + } else { + browser = await chromium.launch(); + } + + if (!browser) { + throw new Error( + 'Failed to establish a browser, please ensure you have either a Browserless.io url or chromium browser installed', + ); + } + + const browserContext = await browser.newContext(); + + const page = await browserContext.newPage(); + + await page.goto(`${NEXT_PUBLIC_WEBAPP_URL()}/__htmltopdf/audit-log?d=${encryptedId}`, { + waitUntil: 'networkidle', + timeout: 10_000, + }); + + const result = await page.pdf({ + format: 'A4', + }); + + await browserContext.close(); + + void browser.close(); + + return result; +};