Skip to content

Commit 41b3641

Browse files
authored
Merge pull request #953 from navikt/log-errors-from-formio-api
Log errors which stem from formio api
2 parents 59df642 + 2323e58 commit 41b3641

22 files changed

+3794
-3622
lines changed

packages/bygger-backend/src/fetchUtils.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import fetch, { RequestInfo, RequestInit, Response } from 'node-fetch';
2+
import { logger } from './logging/logger';
23

34
export class HttpError extends Error {
45
readonly response: Response;
@@ -10,11 +11,22 @@ export class HttpError extends Error {
1011
}
1112
}
1213

14+
const parseBody = async (res: Response): Promise<unknown | string> => {
15+
const contentType = res.headers.get('content-type');
16+
return contentType?.includes('application/json') ? await res.json() : await res.text();
17+
};
18+
1319
export async function fetchWithErrorHandling(url: RequestInfo, options: RequestInit) {
1420
const res = await fetch(url, options);
1521
if (!res.ok) {
16-
console.error(`Fetch ${options.method || 'GET'} ${url} failed with status: ${res.status}`);
17-
console.error(`${options.method} body: ${options.body}`);
22+
const responseBody = await parseBody(res);
23+
const method = options.method || 'GET';
24+
const logMeta = {
25+
responseBody,
26+
status: res.status,
27+
method,
28+
};
29+
logger.error(`Fetch ${method} ${url} failed`, logMeta);
1830
throw new HttpError(res);
1931
}
2032
if (res.status === 204) {
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { RequestHandler } from 'express';
2+
import { formioService } from '../../../services';
3+
import { BadRequest } from '../helpers/errors';
4+
5+
const OBJECT_ID_REGEX = /^[0-9a-fA-F]{24}$/;
6+
const isValidObjectId = (formId: string | undefined) => (formId ? OBJECT_ID_REGEX.test(formId) : false);
7+
8+
const get: RequestHandler = async (req, res, next) => {
9+
try {
10+
const { formPath } = req.params;
11+
const form = await formioService.getForm(formPath);
12+
if (form) {
13+
res.json(form);
14+
} else {
15+
res.sendStatus(404);
16+
}
17+
} catch (error) {
18+
next(error);
19+
}
20+
};
21+
22+
const put: RequestHandler = async (req, res, next) => {
23+
try {
24+
const form = req.body;
25+
if (!isValidObjectId(form._id)) {
26+
next(new BadRequest(`Invalid form id: '${form._id}'`));
27+
return;
28+
}
29+
const formioToken = req.getFormioToken?.();
30+
const userName = req.getUser?.().name;
31+
const savedForm = await formioService.saveForm(form, formioToken, userName, {}, true);
32+
res.json(savedForm);
33+
} catch (error) {
34+
next(error);
35+
}
36+
};
37+
38+
const form = {
39+
get,
40+
put,
41+
};
42+
43+
export default form;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { RequestHandler } from 'express';
2+
import { formioService } from '../../../services';
3+
4+
const get: RequestHandler = async (req, res, next) => {
5+
try {
6+
const { select } = req.query;
7+
const allForms = await formioService.getAllForms(1000, true, select as string);
8+
res.json(allForms);
9+
} catch (error) {
10+
next(error);
11+
}
12+
};
13+
14+
const forms = {
15+
get,
16+
};
17+
18+
export default forms;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import express from 'express';
2+
import authorizedPublisher from '../helpers/authorizedPublisher';
3+
import form from './form';
4+
import forms from './forms';
5+
6+
const formsRouter = express.Router();
7+
8+
formsRouter.get('/', forms.get);
9+
formsRouter.get('/:formPath', form.get);
10+
formsRouter.put('/:formPath', authorizedPublisher, form.put);
11+
12+
export default formsRouter;

packages/bygger-backend/src/routers/api/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import deprecatedPublishForm from './deprecated-publish-form';
66
import deprecatedUnpublishForm from './deprecated-unpublish-form';
77
import enhetsliste from './enhetsliste';
88
import formDiff from './formDiff';
9+
import formsRouter from './forms';
910
import apiErrorHandler from './helpers/apiErrorHandler';
1011
import authorizedPublisher from './helpers/authorizedPublisher';
1112
import log from './log';
@@ -38,6 +39,7 @@ apiRouter.get('/migrate', migrate);
3839
apiRouter.get('/migrate/preview/:formPath', migratePreview);
3940
apiRouter.post('/migrate/update', authorizedPublisher, migrateUpdate);
4041
apiRouter.get('/form/:formPath/diff', formDiff);
42+
apiRouter.use('/forms', formsRouter);
4143
apiRouter.post('/log/:level', rateLimiter(60000, 60), log);
4244

4345
apiRouter.use(apiErrorHandler);

packages/bygger/cypress/e2e/diff.spec.cy.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
describe('Diff', () => {
22
beforeEach(() => {
33
cy.intercept('GET', '/api/config', { fixture: 'config.json' }).as('getConfig');
4-
cy.intercept('GET', '/form?*', { fixture: 'form123456.json' }).as('getForm');
4+
cy.intercept('GET', '/api/forms/dif123456', { fixture: 'form123456.json' }).as('getForm');
55
cy.intercept('GET', '/api/published-forms/dif123456', { fixture: 'form123456-published.json' }).as(
66
'getPublishedForm',
77
);

packages/bygger/cypress/e2e/form-builder.spec.cy.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,20 @@ import { expect } from 'chai';
44
describe('Form Builder', () => {
55
beforeEach(() => {
66
cy.intercept('GET', '/api/config', { fixture: 'config.json' }).as('getConfig');
7-
cy.intercept('GET', '/form?*', { fixture: 'form123456.json' }).as('getForm');
8-
cy.intercept('GET', '/api/published-forms/dif123456', { statusCode: 404 }).as('getPublishedForm');
7+
cy.intercept('GET', '/api/forms/tst123456', { fixture: 'form123456.json' }).as('getForm');
8+
cy.intercept('GET', '/api/published-forms/tst123456', { statusCode: 404 }).as('getPublishedForm');
99
cy.intercept('GET', /language\/submission?.*/, { fixture: 'globalTranslations.json' }).as('getTranslations');
1010
cy.intercept('GET', '/api/countries*', { fixture: 'getCountriesLangNb.json' }).as('getCountriesLangNb');
1111

12-
cy.visit('forms/dif123456');
12+
cy.visit('forms/tst123456');
1313
cy.wait('@getConfig');
1414
cy.wait('@getForm');
1515
cy.wait('@getPublishedForm');
1616
cy.wait('@getCountriesLangNb');
1717
});
1818

1919
it('Trims properties "vedleggskode" and "vedleggstittel" before save', () => {
20-
cy.intercept('PUT', '/form/63c7abd51578ad48a6dc00cc', (req) => {
20+
cy.intercept('PUT', '/api/forms/tst123456', (req) => {
2121
const vedlegg = navFormUtils
2222
.flattenComponents(req.body.components)
2323
.find((comp) => comp.key === 'annenDokumentasjon');
@@ -40,7 +40,7 @@ describe('Form Builder', () => {
4040

4141
describe('Textfield', () => {
4242
it('should save changes made in edit modal', () => {
43-
cy.intercept('PUT', '/form/63c7abd51578ad48a6dc00cc', (req) => {
43+
cy.intercept('PUT', '/api/forms/tst123456', (req) => {
4444
const fodselsdato = navFormUtils
4545
.flattenComponents(req.body.components)
4646
.find((comp) => comp.key === 'fornavnSoker');
@@ -58,7 +58,7 @@ describe('Form Builder', () => {
5858

5959
describe('Nav datepicker', () => {
6060
it('should save changes made in edit modal', () => {
61-
cy.intercept('PUT', '/form/63c7abd51578ad48a6dc00cc', (req) => {
61+
cy.intercept('PUT', '/api/forms/tst123456', (req) => {
6262
const fodselsdato = navFormUtils
6363
.flattenComponents(req.body.components)
6464
.find((comp) => comp.key === 'fodselsdatoDdMmAaaaSoker');

packages/bygger/cypress/e2e/settings.spec.cy.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const _submitData = {
1515
describe('FormSettingsPage', () => {
1616
beforeEach(() => {
1717
cy.intercept('GET', '/api/config', { fixture: 'config.json' }).as('getConfig');
18-
cy.intercept('GET', '/form?*', {
18+
cy.intercept('GET', '/api/forms/cypresssettings', {
1919
fixture: 'getForm.json',
2020
}).as('getForm');
2121
cy.intercept('GET', '/api/published-forms/*', { statusCode: 404 }).as('getPublishedForm');
@@ -27,7 +27,7 @@ describe('FormSettingsPage', () => {
2727
});
2828

2929
it('Fills all elements in settings page', () => {
30-
cy.intercept('PUT', 'form/*', (req) => {
30+
cy.intercept('PUT', '/api/forms/cypresssettings', (req) => {
3131
expect(req.body.properties.tema).to.include(_submitData.tema);
3232
expect(req.body.title).to.include(_submitData.title);
3333
expect(req.body.properties.skjemanummer).to.include(_submitData.skjemanummer);

packages/bygger/cypress/e2e/translations.spec.cy.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ describe('Translations', () => {
55

66
describe('Form translations', () => {
77
beforeEach(() => {
8-
cy.intercept('GET', '/form?*', { fixture: 'form123456.json' }).as('getForm');
9-
cy.intercept('GET', '/api/published-forms/dif123456', { statusCode: 404 }).as('getPublishedForm');
8+
cy.intercept('GET', '/api/forms/tst123456', { fixture: 'form123456.json' }).as('getForm');
9+
cy.intercept('GET', '/api/published-forms/tst123456', { statusCode: 404 }).as('getPublishedForm');
1010
cy.intercept('GET', '/api/countries?*', { fixture: 'getCountriesLangNb.json' }).as('getCountriesLangNb');
1111

12-
cy.visit('/forms/dif123456');
12+
cy.visit('/forms/tst123456');
1313
cy.wait('@getForm');
1414
});
1515

@@ -45,7 +45,7 @@ describe('Translations', () => {
4545

4646
describe('Global translations', () => {
4747
beforeEach(() => {
48-
cy.intercept('GET', '/form?*', { body: [] }).as('getForms');
48+
cy.intercept('GET', /\/api\/forms\\?.+/, { body: [] }).as('getForms');
4949
cy.visit('/');
5050
});
5151

0 commit comments

Comments
 (0)