From c507751eeda5e013657f28f212e647e5aa75a1dc Mon Sep 17 00:00:00 2001
From: nilsarne
Date: Mon, 9 Dec 2024 14:40:41 +0100
Subject: [PATCH 1/8] =?UTF-8?q?POC=20for=20bruk=20av=20Gotenberg=20til=20?=
=?UTF-8?q?=C3=A5=20generere=20PDF=20av=20s=C3=B8knad?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.nais/fyllut/config.yaml | 2 +
.nais/fyllut/dev-delingslenke.yaml | 3 +
.nais/fyllut/dev.yaml | 3 +
.nais/fyllut/preprod-alt.yaml | 3 +
.nais/fyllut/preprod.yaml | 3 +
.nais/fyllut/prod.yaml | 3 +
mocks/mocks/routes/skjemabygging-proxy.js | 2 +-
packages/fyllut-backend/icons/nav-logo.svg | 3 +
packages/fyllut-backend/src/config/config.ts | 2 +
packages/fyllut-backend/src/config/types.d.ts | 1 +
.../routers/api/{exstream.ts => gotenberg.ts} | 10 +-
.../src/routers/api/helpers/htmlBuilder.ts | 4 +
.../src/routers/api/helpers/pdfService.ts | 157 +++++++++++-------
.../fyllut-backend/src/routers/api/index.js | 4 +-
.../src/routers/api/send-inn-utfylt-soknad.ts | 2 +-
15 files changed, 131 insertions(+), 71 deletions(-)
create mode 100644 packages/fyllut-backend/icons/nav-logo.svg
rename packages/fyllut-backend/src/routers/api/{exstream.ts => gotenberg.ts} (89%)
diff --git a/.nais/fyllut/config.yaml b/.nais/fyllut/config.yaml
index 068fb037f..da85187a2 100644
--- a/.nais/fyllut/config.yaml
+++ b/.nais/fyllut/config.yaml
@@ -87,6 +87,8 @@ spec:
value: {{skjemabygging-proxy-url}}
- name: SKJEMABYGGING_PROXY_CLIENT_ID
value: {{skjemabygging-proxy-client-id}}
+ - name: GOTENBERG_URL
+ value: {{gotenberg-url}}
- name: SEND_INN_TOKEN_X_CLIENT_ID
value: {{send-inn-token-x-client-id}}
- name: SEND_INN_HOST
diff --git a/.nais/fyllut/dev-delingslenke.yaml b/.nais/fyllut/dev-delingslenke.yaml
index d1760bf3b..43051d3d9 100644
--- a/.nais/fyllut/dev-delingslenke.yaml
+++ b/.nais/fyllut/dev-delingslenke.yaml
@@ -8,6 +8,7 @@ foersteside-url: https://www.nav.no/soknader/api/forsteside
dekorator-url: https://www.nav.no/dekoratoren?simple=true
skjemabygging-proxy-client-id: 95170319-b4d7-4190-8271-118ed19bafbf
skjemabygging-proxy-url: https://skjemabygging-proxy.dev-fss-pub.nais.io
+gotenberg-url: http://upload-convert-to-pdf.fyllut-sendinn
send-inn-token-x-client-id: dev-gcp:team-soknad:innsending-api
send-inn-host: http://innsending-api.team-soknad
forms-api-url: https://forms-api.nav.no
@@ -46,6 +47,8 @@ accessPolicy:
- application: nav-dekoratoren
namespace: personbruker
cluster: dev-gcp
+ - application: upload-convert-to-pdf
+ namespace: fyllut-sendinn
external:
- host: skjemabygging-proxy.dev-fss-pub.nais.io
- host: formio-api.intern.dev.nav.no
diff --git a/.nais/fyllut/dev.yaml b/.nais/fyllut/dev.yaml
index f9d5dd64d..04da4d1b0 100644
--- a/.nais/fyllut/dev.yaml
+++ b/.nais/fyllut/dev.yaml
@@ -8,6 +8,7 @@ foersteside-url: https://www.nav.no/soknader/api/forsteside
dekorator-url: https://www.nav.no/dekoratoren?simple=true
skjemabygging-proxy-client-id: 95170319-b4d7-4190-8271-118ed19bafbf
skjemabygging-proxy-url: https://skjemabygging-proxy.dev-fss-pub.nais.io
+gotenberg-url: http://upload-convert-to-pdf.fyllut-sendinn
send-inn-token-x-client-id: dev-gcp:team-soknad:innsending-api
send-inn-host: http://innsending-api.team-soknad
kodeverk:
@@ -40,6 +41,8 @@ accessPolicy:
- application: forms-api
namespace: fyllut-sendinn
cluster: dev-gcp
+ - application: upload-convert-to-pdf
+ namespace: fyllut-sendinn
external:
- host: skjemabygging-proxy.dev-fss-pub.nais.io
- host: formio-api.intern.dev.nav.no
diff --git a/.nais/fyllut/preprod-alt.yaml b/.nais/fyllut/preprod-alt.yaml
index c0c6e5ce7..45a211d64 100644
--- a/.nais/fyllut/preprod-alt.yaml
+++ b/.nais/fyllut/preprod-alt.yaml
@@ -9,6 +9,7 @@ foersteside-url: https://www.nav.no/soknader/api/forsteside
dekorator-url: https://www.nav.no/dekoratoren?simple=true
skjemabygging-proxy-client-id: 95170319-b4d7-4190-8271-118ed19bafbf
skjemabygging-proxy-url: https://skjemabygging-proxy.dev-fss-pub.nais.io
+gotenberg-url: http://upload-convert-to-pdf.fyllut-sendinn
send-inn-token-x-client-id: dev-gcp:team-soknad:innsending-api
send-inn-host: http://innsending-api.team-soknad
kodeverk:
@@ -47,6 +48,8 @@ accessPolicy:
- application: forms-api
namespace: fyllut-sendinn
cluster: dev-gcp
+ - application: upload-convert-to-pdf
+ namespace: fyllut-sendinn
external:
- host: skjemabygging-proxy.dev-fss-pub.nais.io
- host: formio-api.intern.dev.nav.no
diff --git a/.nais/fyllut/preprod.yaml b/.nais/fyllut/preprod.yaml
index c807ea709..b85c06962 100644
--- a/.nais/fyllut/preprod.yaml
+++ b/.nais/fyllut/preprod.yaml
@@ -9,6 +9,7 @@ foersteside-url: https://www.nav.no/soknader/api/forsteside
dekorator-url: https://www.nav.no/dekoratoren?simple=true
skjemabygging-proxy-client-id: 95170319-b4d7-4190-8271-118ed19bafbf
skjemabygging-proxy-url: https://skjemabygging-proxy.dev-fss-pub.nais.io
+gotenberg-url: http://upload-convert-to-pdf.fyllut-sendinn
send-inn-token-x-client-id: dev-gcp:team-soknad:innsending-api
send-inn-host: http://innsending-api.team-soknad
kodeverk:
@@ -48,6 +49,8 @@ accessPolicy:
- application: forms-api
namespace: fyllut-sendinn
cluster: dev-gcp
+ - application: upload-convert-to-pdf
+ namespace: fyllut-sendinn
external:
- host: skjemabygging-proxy.dev-fss-pub.nais.io
- host: formio-api.intern.dev.nav.no
diff --git a/.nais/fyllut/prod.yaml b/.nais/fyllut/prod.yaml
index 8f00fc36d..d16cabb2b 100644
--- a/.nais/fyllut/prod.yaml
+++ b/.nais/fyllut/prod.yaml
@@ -8,6 +8,7 @@ foersteside-url: https://www.nav.no/soknader/api/forsteside
dekorator-url: https://www.nav.no/dekoratoren?simple=true
skjemabygging-proxy-client-id: 031863f2-9881-44af-ace5-6b5ab52afeb1
skjemabygging-proxy-url: https://skjemabygging-proxy.prod-fss-pub.nais.io
+gotenberg-url: http://upload-convert-to-pdf.fyllut-sendinn
send-inn-token-x-client-id: prod-gcp:team-soknad:innsending-api
send-inn-host: http://innsending-api.team-soknad
kodeverk:
@@ -45,6 +46,8 @@ accessPolicy:
- application: forms-api
namespace: fyllut-sendinn
cluster: prod-gcp
+ - application: upload-convert-to-pdf
+ namespace: fyllut-sendinn
external:
- host: skjemabygging-proxy.prod-fss-pub.nais.io
- host: formio-api.intern.nav.no
diff --git a/mocks/mocks/routes/skjemabygging-proxy.js b/mocks/mocks/routes/skjemabygging-proxy.js
index 18bf7ed7c..1ebcdf1b2 100644
--- a/mocks/mocks/routes/skjemabygging-proxy.js
+++ b/mocks/mocks/routes/skjemabygging-proxy.js
@@ -1,7 +1,7 @@
module.exports = [
{
id: 'post-exstream-pdf',
- url: '/skjemabygging-proxy/exstream',
+ url: '/skjemabygging-proxy/gotenberg',
method: 'POST',
variants: [
{
diff --git a/packages/fyllut-backend/icons/nav-logo.svg b/packages/fyllut-backend/icons/nav-logo.svg
new file mode 100644
index 000000000..f5677fbc3
--- /dev/null
+++ b/packages/fyllut-backend/icons/nav-logo.svg
@@ -0,0 +1,3 @@
+
diff --git a/packages/fyllut-backend/src/config/config.ts b/packages/fyllut-backend/src/config/config.ts
index e7f9914bc..6bdddc589 100644
--- a/packages/fyllut-backend/src/config/config.ts
+++ b/packages/fyllut-backend/src/config/config.ts
@@ -79,6 +79,7 @@ const localDevelopmentConfig: DefaultConfig = {
decoratorUrl: 'https://www.nav.no/dekoratoren?simple=true',
skjemabyggingProxyUrl: process.env.SKJEMABYGGING_PROXY_URL || 'https://skjemabygging-proxy.dev-fss-pub.nais.io',
skjemabyggingProxyClientId: '95170319-b4d7-4190-8271-118ed19bafbf',
+ gotenbergUrl: process.env.GOTENBERG_URL || 'https://upload-convert-to-pdf.fyllut-sendinn',
azureOpenidTokenEndpoint:
process.env.AZURE_OPENID_CONFIG_TOKEN_ENDPOINT ||
'https://login.microsoftonline.com/966ac572-f5b7-4bbe-aa88-c76419c0f851/oauth2/v2.0/token',
@@ -125,6 +126,7 @@ const defaultConfig: DefaultConfig = {
decoratorUrl: process.env.DECORATOR_URL!,
skjemabyggingProxyUrl: process.env.SKJEMABYGGING_PROXY_URL!,
skjemabyggingProxyClientId: process.env.SKJEMABYGGING_PROXY_CLIENT_ID!,
+ gotenbergUrl: process.env.GOTENBERG_URL!,
azureOpenidTokenEndpoint: process.env.AZURE_OPENID_CONFIG_TOKEN_ENDPOINT!,
clientId: process.env.AZURE_APP_CLIENT_ID!,
skjemaDir: process.env.SKJEMA_DIR!,
diff --git a/packages/fyllut-backend/src/config/types.d.ts b/packages/fyllut-backend/src/config/types.d.ts
index 8281a23c4..b4cc4aa2b 100644
--- a/packages/fyllut-backend/src/config/types.d.ts
+++ b/packages/fyllut-backend/src/config/types.d.ts
@@ -43,6 +43,7 @@ export type DefaultConfig = {
decoratorUrl: string;
skjemabyggingProxyUrl: string;
skjemabyggingProxyClientId: string;
+ gotenbergUrl: string;
azureOpenidTokenEndpoint: string;
clientId: string;
skjemaDir?: string;
diff --git a/packages/fyllut-backend/src/routers/api/exstream.ts b/packages/fyllut-backend/src/routers/api/gotenberg.ts
similarity index 89%
rename from packages/fyllut-backend/src/routers/api/exstream.ts
rename to packages/fyllut-backend/src/routers/api/gotenberg.ts
index e2884a5c3..81c6d7bf1 100644
--- a/packages/fyllut-backend/src/routers/api/exstream.ts
+++ b/packages/fyllut-backend/src/routers/api/gotenberg.ts
@@ -6,7 +6,6 @@ import {
Submission,
} from '@navikt/skjemadigitalisering-shared-domain';
import { NextFunction, Request, Response } from 'express';
-import { base64Decode } from '../../utils/base64';
import { htmlResponseError } from '../../utils/errorHandling';
import { logErrorWithStacktrace } from '../../utils/errors';
import { createPdf } from './helpers/pdfService';
@@ -28,7 +27,7 @@ const parseBody = (
return { form, submission, submissionMethod, translations, language };
};
-const exstream = {
+const gotenberg = {
post: async (req: Request, res: Response, next: NextFunction) => {
try {
const { form, submission, submissionMethod, translations, language } = parseBody(req);
@@ -42,8 +41,9 @@ const exstream = {
translations,
languageCode,
);
- res.contentType(pdf.contentType);
- res.send(base64Decode(pdf.data));
+
+ res.setHeader('Content-Type', 'application/pdf');
+ res.status(200).send(Buffer.from(new Uint8Array(pdf)));
} catch (e) {
logErrorWithStacktrace(e as Error);
const createPdfError = htmlResponseError('Generering av PDF feilet');
@@ -52,4 +52,4 @@ const exstream = {
},
};
-export default exstream;
+export default gotenberg;
diff --git a/packages/fyllut-backend/src/routers/api/helpers/htmlBuilder.ts b/packages/fyllut-backend/src/routers/api/helpers/htmlBuilder.ts
index eae10d32f..86e02f585 100644
--- a/packages/fyllut-backend/src/routers/api/helpers/htmlBuilder.ts
+++ b/packages/fyllut-backend/src/routers/api/helpers/htmlBuilder.ts
@@ -73,15 +73,19 @@ p {margin: 0}
.alt {margin-bottom: 5px; font-family: "Courier New", sans-serif; font-style: italic;}
.innrykk {margin: 0px 0px 10px 20px;}
.underskrift {margin-bottom: 30px;}
+.navlogored {height: 16px;float: left;margin: 4px auto 2px auto;}
`;
const body = (formSummaryObject: SummaryPanel[], confirmation?: string, signatures?: string) => `
+${navlogo}
${formSummaryObject.map(section).join('')}
${confirmation || ''}
${signatures || ''}
`;
+const navlogo: string = ``;
+
const section = (formSection: SummaryPanel) => `
${formSection.label}
${sectionContent(formSection.components, 1)}`;
diff --git a/packages/fyllut-backend/src/routers/api/helpers/pdfService.ts b/packages/fyllut-backend/src/routers/api/helpers/pdfService.ts
index 336538250..855e70623 100644
--- a/packages/fyllut-backend/src/routers/api/helpers/pdfService.ts
+++ b/packages/fyllut-backend/src/routers/api/helpers/pdfService.ts
@@ -6,16 +6,16 @@ import {
translationUtils,
} from '@navikt/skjemadigitalisering-shared-domain';
import correlator from 'express-correlation-id';
+import FormData from 'form-data';
+import { readFileSync } from 'fs';
+import path from 'path';
import { config } from '../../../config/config';
import { logger } from '../../../logger';
import { appMetrics } from '../../../services';
-import { base64Decode, base64Encode } from '../../../utils/base64';
-import { responseToError, synchronousResponseToError } from '../../../utils/errorHandling';
+import { synchronousResponseToError } from '../../../utils/errorHandling';
import fetchWithRetry, { HeadersInit } from '../../../utils/fetchWithRetry';
import { createHtmlFromSubmission } from './htmlBuilder';
-const { skjemabyggingProxyUrl, gitVersion } = config;
-
export const createPdfAsByteArray = async (
accessToken: string,
form: NavFormType,
@@ -24,8 +24,7 @@ export const createPdfAsByteArray = async (
translations: I18nTranslationMap,
language: string,
) => {
- const pdf = await createPdf(accessToken, form, submission, submissionMethod, translations, language);
- return Array.from(base64Decode(pdf.data) ?? []);
+ return await createPdfFromGotenberg(accessToken, form, submission, submissionMethod, translations, language);
};
export const createPdf = async (
@@ -35,6 +34,47 @@ export const createPdf = async (
submissionMethod: string,
translations: I18nTranslationMap,
language: string,
+) => {
+ const pdf = await createPdfFromGotenberg(accessToken, form, submission, submissionMethod, translations, language);
+ return Buffer.from(new Uint8Array(pdf));
+};
+
+const footer: string =
+ '\n' +
+ '\n' +
+ ' \n' +
+ '\n' +
+ '\n' +
+ 'Generert 16. Nov 2024 kl 14:30:
\n' +
+ ' av
\n' +
+ '\n' +
+ '';
+
+const filePath = path.join(process.cwd(), '/icons/nav-logo.svg');
+
+const navIcon = readFileSync(filePath, { encoding: 'utf-8', flag: 'r' });
+
+export const createPdfFromGotenberg = async (
+ accessToken: string,
+ form: NavFormType,
+ submission: Submission,
+ submissionMethod: string,
+ translations: I18nTranslationMap,
+ language: string,
) => {
const translate = (text: string, textReplacements?: I18nTranslationReplacements) =>
translationUtils.translateWithTextReplacements({
@@ -48,88 +88,81 @@ export const createPdf = async (
if (!html || Object.keys(html).length === 0) {
throw Error('Missing HTML for generating PDF.');
}
- const { fodselsnummerDNummerSoker } = submission.data;
+ //const { fodselsnummerDNummerSoker } = submission.data;
appMetrics.exstreamPdfRequestsCounter.inc();
let errorOccurred = false;
const stopMetricRequestDuration = appMetrics.outgoingRequestDuration.startTimer({
- service: 'exstream',
- method: 'createPdf',
+ service: 'gotenberg',
+ method: 'createPdfFromGotenberg',
});
+ const assets = {};
+ const options = { pdfa: true, pdfua: true };
+ const gotenbergUrl = config.gotenbergUrl;
try {
- return await createPdfFromHtml(
- accessToken,
- translate(form.title),
- form.properties.skjemanummer,
- language,
- html,
- (fodselsnummerDNummerSoker as string | undefined) || '—',
- );
+ return await createPdfCallingGotenberg(accessToken, gotenbergUrl, html, assets, options);
} catch (e) {
errorOccurred = true;
appMetrics.exstreamPdfFailuresCounter.inc();
throw e;
} finally {
const durationSeconds = stopMetricRequestDuration({ error: String(errorOccurred) });
- logger.info(`Request to exstream pdf service completed after ${durationSeconds} seconds`, {
+ logger.info(`Request to gotenberg pdf service completed after ${durationSeconds} seconds`, {
error: errorOccurred,
durationSeconds,
});
}
};
-export const createPdfFromHtml = async (
+const createPdfCallingGotenberg = async (
azureAccessToken: string,
- title: string,
- skjemanummer: string,
- language: string,
+ gotenbergUrl: string,
html: string,
- pid: string,
-) => {
- const response = await fetchWithRetry(`${skjemabyggingProxyUrl}/exstream`, {
+ assets: { [filename: string]: string },
+ options: { pdfa: boolean; pdfua: boolean },
+): Promise => {
+ const formData = new FormData();
+
+ // Add the main HTML content
+ formData.append('files', Buffer.from(html), 'index.html');
+ formData.append('files', Buffer.from(footer), 'footer.html');
+ if (navIcon != null) {
+ formData.append('files', Buffer.from(navIcon), 'Nav-logo.svg');
+ }
+
+ // Add optional assets like logos, footers, etc.
+ for (const [filename, content] of Object.entries(assets)) {
+ formData.append('files', Buffer.from(content), filename);
+ }
+
+ // Add Gotenberg-specific options
+ formData.append('pdfa', options.pdfa ? 'PDF/A-1b' : '');
+ formData.append('pdfua', options.pdfua ? 'true' : '');
+ formData.append('skipNetworkIdleEvent', 'false');
+
+ // Send the request to Gotenberg
+ const gotenbergResponse = await fetchWithRetry(`${gotenbergUrl}/forms/chromium/convert/html`, {
retry: 3,
headers: {
- Authorization: `Bearer ${azureAccessToken}`,
+ ...formData.getHeaders(),
+ //Authorization: `Bearer ${azureAccessToken}`,
'x-correlation-id': correlator.getId(),
- 'Content-Type': 'application/json',
} as HeadersInit,
method: 'POST',
- body: JSON.stringify({
- content: {
- contentType: 'application/json',
- data: base64Encode(
- JSON.stringify({
- dokumentTittel: title,
- spraakkode: language,
- blankettnr: skjemanummer,
- brukersFnr: pid,
- skjemaversjon: gitVersion,
- html: base64Encode(html),
- }),
- ),
- async: 'true',
- },
- RETURNFORMAT: 'PDF',
- RETURNDATA: 'TRUE',
- }),
+ body: formData,
});
- if (response.ok) {
- const json: any = await response.json();
- if (!json.data?.result?.[0]?.content) {
- if (json.data?.id) {
- throw synchronousResponseToError(
- `Feil i responsdata fra Exstream på id "${json.data?.id}"`,
- json,
- response.status,
- response.url,
- true,
- );
- } else {
- throw synchronousResponseToError('Feil i responsdata fra Exstream', json, response.status, response.url, true);
- }
- }
- return json.data.result[0].content;
+ if (!gotenbergResponse.ok) {
+ const errorText = await gotenbergResponse.text();
+ console.error('Gotenberg error response:', errorText);
+ throw synchronousResponseToError(
+ `Feil i responsdata fra Gotenberg på id "${correlator.getId()}"`,
+ errorText,
+ gotenbergResponse.status,
+ gotenbergResponse.url,
+ true,
+ );
}
- throw await responseToError(response, 'Feil ved generering av PDF hos Exstream', true);
+ const pdfBuffer = gotenbergResponse.arrayBuffer();
+ return pdfBuffer;
};
diff --git a/packages/fyllut-backend/src/routers/api/index.js b/packages/fyllut-backend/src/routers/api/index.js
index 39397335f..5b4f76f54 100644
--- a/packages/fyllut-backend/src/routers/api/index.js
+++ b/packages/fyllut-backend/src/routers/api/index.js
@@ -9,11 +9,11 @@ import { initApiConfig } from './api-helper';
import commonCodes from './common-codes';
import config from './config';
import enhetsliste from './enhetsliste.js';
-import exstream from './exstream';
import form from './form';
import forms from './forms';
import forsteside from './forsteside';
import globalTranslations from './global-translations.js';
+import gotenberg from './gotenberg';
import log from './log';
import mottaksadresser from './mottaksadresser.js';
import pdl from './pdl';
@@ -47,7 +47,7 @@ apiRouter.post('/send-inn/soknad', tokenxSendInn, sendInnSoknad.post);
apiRouter.put('/send-inn/soknad', tokenxSendInn, sendInnSoknad.put);
apiRouter.put('/send-inn/utfyltsoknad', azureSkjemabyggingProxy, tokenxSendInn, sendInnUtfyltSoknad.put);
apiRouter.get('/common-codes/archive-subjects', kodeverkToken, commonCodes.getArchiveSubjects);
-apiRouter.post('/pdf/convert', azureSkjemabyggingProxy, exstream.post);
+apiRouter.post('/pdf/convert', azureSkjemabyggingProxy, gotenberg.post);
apiRouter.get('/common-codes/currencies', kodeverkToken, commonCodes.getCurrencies);
apiRouter.post('/log/:level', rateLimiter(60000, 60), log.post);
apiRouter.get('/health/status', status.get);
diff --git a/packages/fyllut-backend/src/routers/api/send-inn-utfylt-soknad.ts b/packages/fyllut-backend/src/routers/api/send-inn-utfylt-soknad.ts
index e7dca33cf..6c075a84d 100644
--- a/packages/fyllut-backend/src/routers/api/send-inn-utfylt-soknad.ts
+++ b/packages/fyllut-backend/src/routers/api/send-inn-utfylt-soknad.ts
@@ -33,7 +33,7 @@ const sendInnUtfyltSoknad = {
next(new Error(errorMessage));
return;
}
-
+ logger.warning('***** Skal konvertere søknad til PDF ******');
const pdfByteArray = await createPdfAsByteArray(
req.headers.AzureAccessToken as string,
form,
From 9d14a3c16dcd0539412cdc56b3cebaadbec5ecca Mon Sep 17 00:00:00 2001
From: nilsarne
Date: Thu, 19 Dec 2024 16:05:34 +0100
Subject: [PATCH 2/8] =?UTF-8?q?POC=20for=20bruk=20av=20Gotenberg=20til=20?=
=?UTF-8?q?=C3=A5=20generere=20PDF=20av=20s=C3=B8knad?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.nais/fyllut/dev-delingslenke.yaml | 1 +
.nais/fyllut/dev.yaml | 1 +
.nais/fyllut/preprod-alt.yaml | 1 +
.nais/fyllut/preprod.yaml | 1 +
.nais/fyllut/prod.yaml | 1 +
mocks/mocks/collections.json | 2 +-
mocks/mocks/routes/skjemabygging-proxy.js | 4 +-
packages/fyllut-backend/src/app.test.ts | 2 +-
packages/fyllut-backend/src/config/config.ts | 4 +-
.../src/routers/api/exstream.test.ts | 45 ------------------
.../routers/api/helpers/footer-template.html | 46 +++++++++++++++++++
.../src/routers/api/helpers/footerBuilder.ts | 31 +++++++++++++
.../src/routers/api/helpers/htmlBuilder.ts | 4 +-
.../src/routers/api/helpers/pdfService.ts | 44 ++++++------------
.../fyllut-backend/src/routers/api/index.js | 2 +-
.../api/send-inn-utfylt-soknad.test.ts | 6 +--
.../src/routers/api/send-inn-utfylt-soknad.ts | 2 +-
.../src/texts/statiskeTekster.js | 8 ++++
18 files changed, 118 insertions(+), 87 deletions(-)
delete mode 100644 packages/fyllut-backend/src/routers/api/exstream.test.ts
create mode 100644 packages/fyllut-backend/src/routers/api/helpers/footer-template.html
create mode 100644 packages/fyllut-backend/src/routers/api/helpers/footerBuilder.ts
diff --git a/.nais/fyllut/dev-delingslenke.yaml b/.nais/fyllut/dev-delingslenke.yaml
index 43051d3d9..c2831d9f2 100644
--- a/.nais/fyllut/dev-delingslenke.yaml
+++ b/.nais/fyllut/dev-delingslenke.yaml
@@ -49,6 +49,7 @@ accessPolicy:
cluster: dev-gcp
- application: upload-convert-to-pdf
namespace: fyllut-sendinn
+ cluster: dev-gcp
external:
- host: skjemabygging-proxy.dev-fss-pub.nais.io
- host: formio-api.intern.dev.nav.no
diff --git a/.nais/fyllut/dev.yaml b/.nais/fyllut/dev.yaml
index 04da4d1b0..6a4f1e599 100644
--- a/.nais/fyllut/dev.yaml
+++ b/.nais/fyllut/dev.yaml
@@ -43,6 +43,7 @@ accessPolicy:
cluster: dev-gcp
- application: upload-convert-to-pdf
namespace: fyllut-sendinn
+ cluster: dev-gcp
external:
- host: skjemabygging-proxy.dev-fss-pub.nais.io
- host: formio-api.intern.dev.nav.no
diff --git a/.nais/fyllut/preprod-alt.yaml b/.nais/fyllut/preprod-alt.yaml
index 45a211d64..ed5bf2887 100644
--- a/.nais/fyllut/preprod-alt.yaml
+++ b/.nais/fyllut/preprod-alt.yaml
@@ -50,6 +50,7 @@ accessPolicy:
cluster: dev-gcp
- application: upload-convert-to-pdf
namespace: fyllut-sendinn
+ cluster: dev-gcp
external:
- host: skjemabygging-proxy.dev-fss-pub.nais.io
- host: formio-api.intern.dev.nav.no
diff --git a/.nais/fyllut/preprod.yaml b/.nais/fyllut/preprod.yaml
index b85c06962..e62815982 100644
--- a/.nais/fyllut/preprod.yaml
+++ b/.nais/fyllut/preprod.yaml
@@ -51,6 +51,7 @@ accessPolicy:
cluster: dev-gcp
- application: upload-convert-to-pdf
namespace: fyllut-sendinn
+ cluster: dev-gcp
external:
- host: skjemabygging-proxy.dev-fss-pub.nais.io
- host: formio-api.intern.dev.nav.no
diff --git a/.nais/fyllut/prod.yaml b/.nais/fyllut/prod.yaml
index d16cabb2b..1432b5b1d 100644
--- a/.nais/fyllut/prod.yaml
+++ b/.nais/fyllut/prod.yaml
@@ -48,6 +48,7 @@ accessPolicy:
cluster: prod-gcp
- application: upload-convert-to-pdf
namespace: fyllut-sendinn
+ cluster: prod-gcp
external:
- host: skjemabygging-proxy.prod-fss-pub.nais.io
- host: formio-api.intern.nav.no
diff --git a/mocks/mocks/collections.json b/mocks/mocks/collections.json
index 0375f9cf7..4e51b2c23 100644
--- a/mocks/mocks/collections.json
+++ b/mocks/mocks/collections.json
@@ -7,7 +7,7 @@
"get-translations:success",
"post-azure-openid-token:success",
"get-kodeverk-currencies:success",
- "post-exstream-pdf:success",
+ "post-gotenberg-pdf:success",
"get-tokenx-endpoint:success",
"post-tokenx:success",
"post-soknad:success",
diff --git a/mocks/mocks/routes/skjemabygging-proxy.js b/mocks/mocks/routes/skjemabygging-proxy.js
index 1ebcdf1b2..6dde09cc9 100644
--- a/mocks/mocks/routes/skjemabygging-proxy.js
+++ b/mocks/mocks/routes/skjemabygging-proxy.js
@@ -1,7 +1,7 @@
module.exports = [
{
- id: 'post-exstream-pdf',
- url: '/skjemabygging-proxy/gotenberg',
+ id: 'post-gotenberg-pdf',
+ url: '/skjemabygging-proxy/extream',
method: 'POST',
variants: [
{
diff --git a/packages/fyllut-backend/src/app.test.ts b/packages/fyllut-backend/src/app.test.ts
index 8bf8d793c..5717484e3 100644
--- a/packages/fyllut-backend/src/app.test.ts
+++ b/packages/fyllut-backend/src/app.test.ts
@@ -253,7 +253,7 @@ describe('app', () => {
.post(extractPath(azureTokenEndpoint))
.reply(200, { access_token: 'azure-access-token' });
const skjemabyggingproxyScope = nock(process.env.SKJEMABYGGING_PROXY_URL as string)
- .post('/exstream')
+ .post('/gotenberg')
.reply(200, { data: { result: [{ content: { data: '' } }] } });
const tokenxWellKnownScope = nock(extractHost(tokenxConfig?.wellKnownUrl))
.get(extractPath(tokenxConfig?.wellKnownUrl))
diff --git a/packages/fyllut-backend/src/config/config.ts b/packages/fyllut-backend/src/config/config.ts
index 6bdddc589..c484963ec 100644
--- a/packages/fyllut-backend/src/config/config.ts
+++ b/packages/fyllut-backend/src/config/config.ts
@@ -79,7 +79,7 @@ const localDevelopmentConfig: DefaultConfig = {
decoratorUrl: 'https://www.nav.no/dekoratoren?simple=true',
skjemabyggingProxyUrl: process.env.SKJEMABYGGING_PROXY_URL || 'https://skjemabygging-proxy.dev-fss-pub.nais.io',
skjemabyggingProxyClientId: '95170319-b4d7-4190-8271-118ed19bafbf',
- gotenbergUrl: process.env.GOTENBERG_URL || 'https://upload-convert-to-pdf.fyllut-sendinn',
+ gotenbergUrl: process.env.GOTENBERG_URL || 'https://convert-to-pdf.intern.dev.nav.no',
azureOpenidTokenEndpoint:
process.env.AZURE_OPENID_CONFIG_TOKEN_ENDPOINT ||
'https://login.microsoftonline.com/966ac572-f5b7-4bbe-aa88-c76419c0f851/oauth2/v2.0/token',
@@ -173,4 +173,4 @@ const checkConfigConsistency = (config: ConfigType, logError = logger.error, exi
}
};
-export { checkConfigConsistency, config };
+export { checkConfigConsistency, config, defaultConfig };
diff --git a/packages/fyllut-backend/src/routers/api/exstream.test.ts b/packages/fyllut-backend/src/routers/api/exstream.test.ts
deleted file mode 100644
index 42a235e9c..000000000
--- a/packages/fyllut-backend/src/routers/api/exstream.test.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import nock from 'nock';
-import { mockRequest, mockResponse } from '../../test/testHelpers';
-import { base64Decode } from '../../utils/base64';
-import exstream from './exstream';
-
-const formTitle = 'testskjema';
-const defaultBody = {
- form: JSON.stringify({ title: formTitle, components: [], properties: { skjemanummer: 'NAV 12.34-56' } }),
- submission: JSON.stringify({ data: {} }),
- submissionMethod: 'paper',
- translations: JSON.stringify({}),
- language: 'nb-NO',
-};
-
-describe('exstream', () => {
- it('decodes and sends the pdf on success', async () => {
- const skjemabyggingproxyScope = nock(process.env.SKJEMABYGGING_PROXY_URL as string)
- .post('/exstream')
- .reply(200, { data: { result: [{ content: { data: 'base64EncodedPDFstring' } }] } });
- const req = mockRequest({ headers: { AzureAccessToken: 'azure-access-token' }, body: defaultBody });
- const res = mockResponse();
- const next = vi.fn();
- await exstream.post(req, res, next);
- expect(next).not.toHaveBeenCalled();
- expect(res.send).toHaveBeenCalledWith(base64Decode('base64EncodedPDFstring'));
- skjemabyggingproxyScope.done();
- });
-
- it('calls next if skjemabygging-proxy returns error', async () => {
- const skjemabyggingproxyScope = nock(process.env.SKJEMABYGGING_PROXY_URL as string)
- .post('/exstream')
- .reply(500, 'error body');
- const req = mockRequest({ headers: { AzureAccessToken: 'azure-access-token' }, body: defaultBody });
- const res = mockResponse();
- const next = vi.fn();
- await exstream.post(req, res, next);
-
- expect(next).toHaveBeenCalledTimes(1);
- const error = next.mock.calls[0][0];
- expect(error?.message).toBe('Generering av PDF feilet');
- expect(error?.render_html).toBe(true);
- expect(res.send).not.toHaveBeenCalled();
- skjemabyggingproxyScope.done();
- });
-});
diff --git a/packages/fyllut-backend/src/routers/api/helpers/footer-template.html b/packages/fyllut-backend/src/routers/api/helpers/footer-template.html
new file mode 100644
index 000000000..96c3700d5
--- /dev/null
+++ b/packages/fyllut-backend/src/routers/api/helpers/footer-template.html
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
diff --git a/packages/fyllut-backend/src/routers/api/helpers/footerBuilder.ts b/packages/fyllut-backend/src/routers/api/helpers/footerBuilder.ts
new file mode 100644
index 000000000..a3854ee36
--- /dev/null
+++ b/packages/fyllut-backend/src/routers/api/helpers/footerBuilder.ts
@@ -0,0 +1,31 @@
+import { TEXTS } from '@navikt/skjemadigitalisering-shared-domain';
+import { readFileSync } from 'fs';
+import path from 'path';
+
+const filePath = path.join(process.cwd(), '/src/routers/api/helpers/footer-template.html');
+
+export async function generateFooterHtml(
+ userId,
+ schemaVersion,
+ skjemanummer,
+ language,
+ translate: (text: string) => string,
+) {
+ let footerHtml = readFileSync(filePath, { encoding: 'utf-8', flag: 'r' });
+
+ const creationDate = new Date().toLocaleString();
+
+ footerHtml = footerHtml
+ .replace('{{USER_ID}}', userId)
+ .replace('{{CREATION_DATE}}', creationDate)
+ .replace('{{SCHEMA_VERSION}}', schemaVersion)
+ .replace('{{SCHEMA_NUMBER}}', skjemanummer)
+ .replace('{{userIdLabel}}', translate(TEXTS.statiske.footer.userIdLabel))
+ .replace('{{createdLabel}}', translate(TEXTS.statiske.footer.createdDatelabel))
+ .replace('{{schemaNumberLabel}}', translate(TEXTS.statiske.footer.schemaNumberLabel))
+ .replace('{{versionLabel}}', translate(TEXTS.statiske.footer.versionLabel))
+ .replace('{{pageLabel}}', translate(TEXTS.statiske.footer.pageLabel))
+ .replace('{{ofLabel}}', translate(TEXTS.statiske.footer.ofLabel));
+
+ return footerHtml;
+}
diff --git a/packages/fyllut-backend/src/routers/api/helpers/htmlBuilder.ts b/packages/fyllut-backend/src/routers/api/helpers/htmlBuilder.ts
index 86e02f585..e006cabf9 100644
--- a/packages/fyllut-backend/src/routers/api/helpers/htmlBuilder.ts
+++ b/packages/fyllut-backend/src/routers/api/helpers/htmlBuilder.ts
@@ -74,6 +74,8 @@ p {margin: 0}
.innrykk {margin: 0px 0px 10px 20px;}
.underskrift {margin-bottom: 30px;}
.navlogored {height: 16px;float: left;margin: 4px auto 2px auto;}
+@page {size: a4 portrait;margin-bottom:56px;}
+section {page-break-after: always; break-after: page;}
`;
const body = (formSummaryObject: SummaryPanel[], confirmation?: string, signatures?: string) => `
@@ -84,7 +86,7 @@ ${confirmation || ''}
${signatures || ''}
\n' +
- 'Generert 16. Nov 2024 kl 14:30:
\n' +
- ' av
\n' +
- '
diff --git a/packages/fyllut-backend/src/routers/api/helpers/pdfService.ts b/packages/fyllut-backend/src/routers/api/helpers/pdfService.ts
index 855e70623..59a5ad3a1 100644
--- a/packages/fyllut-backend/src/routers/api/helpers/pdfService.ts
+++ b/packages/fyllut-backend/src/routers/api/helpers/pdfService.ts
@@ -9,11 +9,12 @@ import correlator from 'express-correlation-id';
import FormData from 'form-data';
import { readFileSync } from 'fs';
import path from 'path';
-import { config } from '../../../config/config';
+import { config, defaultConfig } from '../../../config/config';
import { logger } from '../../../logger';
import { appMetrics } from '../../../services';
import { synchronousResponseToError } from '../../../utils/errorHandling';
import fetchWithRetry, { HeadersInit } from '../../../utils/fetchWithRetry';
+import { generateFooterHtml } from './footerBuilder';
import { createHtmlFromSubmission } from './htmlBuilder';
export const createPdfAsByteArray = async (
@@ -39,31 +40,6 @@ export const createPdf = async (
return Buffer.from(new Uint8Array(pdf));
};
-const footer: string =
- '\n' +
- '