From 4ea807ee6ee162748048ee82349fd7ea16463700 Mon Sep 17 00:00:00 2001 From: Jason Sherman Date: Thu, 15 Aug 2024 15:34:01 -0700 Subject: [PATCH] Generate Proxy Headers lookup form/version Id when provided submissionId Signed-off-by: Jason Sherman --- app/src/forms/proxy/service.js | 31 ++++++++++++++++--- app/tests/unit/forms/proxy/controller.spec.js | 2 ++ app/tests/unit/forms/proxy/service.spec.js | 29 ++++++++++++----- 3 files changed, 51 insertions(+), 11 deletions(-) diff --git a/app/src/forms/proxy/service.js b/app/src/forms/proxy/service.js index f6cd334a1..6cfca7b27 100644 --- a/app/src/forms/proxy/service.js +++ b/app/src/forms/proxy/service.js @@ -1,7 +1,7 @@ const { encryptionService } = require('../../components/encryptionService'); const jwtService = require('../../components/jwtService'); const ProxyServiceError = require('./error'); -const { ExternalAPI } = require('../../forms/common/models'); +const { ExternalAPI, SubmissionMetadata } = require('../../forms/common/models'); const headerValue = (headers, key) => { if (headers && key) { @@ -19,15 +19,38 @@ const trimLeadingSlashes = (str) => str.replace(/^\/+|\$/g, ''); const trimTrailingSlashes = (str) => str.replace(/\/+$/g, ''); const service = { + _getIds: async (payload) => { + let formId = payload['formId']; + let versionId = payload['versionId']; + let submissionId = payload['submissionId']; + // when we are provided with a submission id (ex. submitting a draft submission) + // we need to fetch the related form and version id (if not provided) + if (submissionId) { + const meta = await SubmissionMetadata.query().where('submissionId', submissionId).first(); + if (meta) { + formId = meta.submissionId; + versionId = meta.formVersionId; + submissionId = meta.submissionId; + } + } + return { + formId: formId, + versionId: versionId, + submissionId: submissionId, + }; + }, + generateProxyHeaders: async (payload, currentUser, token) => { if (!payload || !currentUser || !currentUser.idp) { throw new ProxyServiceError('Cannot generate proxy headers with missing or incomplete parameters'); } + const { formId, versionId, submissionId } = await service._getIds(payload); + const headerData = { - formId: payload['formId'], - versionId: payload['versionId'], - submissionId: payload['submissionId'], + formId: formId, + versionId: versionId, + submissionId: submissionId, userId: currentUser.idpUserId, username: currentUser.username, firstName: currentUser.firstName, diff --git a/app/tests/unit/forms/proxy/controller.spec.js b/app/tests/unit/forms/proxy/controller.spec.js index d52ad6c68..8d2eec8bf 100644 --- a/app/tests/unit/forms/proxy/controller.spec.js +++ b/app/tests/unit/forms/proxy/controller.spec.js @@ -4,6 +4,7 @@ const { getMockReq, getMockRes } = require('@jest-mock/express'); const controller = require('../../../../src/forms/proxy/controller'); const service = require('../../../../src/forms/proxy/service'); const jwtService = require('../../../../src/components/jwtService'); + const { NotFoundError } = require('objection'); const bearerToken = Math.random().toString(36).substring(2); @@ -29,6 +30,7 @@ describe('generateProxyHeaders', () => { }; it('should generate headers', async () => { + service._getIds = jest.fn().mockReturnValue({ formId: '1234', versionId: '5678', submissionId: null }); service.generateProxyHeaders = jest.fn().mockReturnValue({}); await controller.generateProxyHeaders(req, {}, jest.fn()); diff --git a/app/tests/unit/forms/proxy/service.spec.js b/app/tests/unit/forms/proxy/service.spec.js index 7c3d953dc..5263e90a6 100644 --- a/app/tests/unit/forms/proxy/service.spec.js +++ b/app/tests/unit/forms/proxy/service.spec.js @@ -8,7 +8,7 @@ const { ExternalAPI } = require('../../../../src/forms/common/models'); const goodPayload = { formId: '123', - submissionId: '456', + submissionId: null, versionId: '789', }; @@ -61,8 +61,6 @@ afterEach(() => { describe('Proxy Service', () => { describe('generateProxyHeaders', () => { - beforeEach(() => {}); - it('should throw error with no payload', async () => { await expect(service.generateProxyHeaders(undefined, goodCurrentUser, token)).rejects.toThrow(); }); @@ -85,10 +83,27 @@ describe('Proxy Service', () => { const decrypted = encryptionService.decryptProxy(result['X-CHEFS-PROXY-DATA']); expect(JSON.parse(decrypted)).toMatchObject(goodProxyHeaderInfo); }); + it('should find formId and versionId when given submissionId', async () => { + const submissionPayload = { submissionId: '456' }; + const idsPaylad = { ...goodPayload, ...submissionPayload }; + service._getIds = jest.fn().mockResolvedValueOnce(idsPaylad); + const submissionProxyHeaderInfo = { + ...idsPaylad, + ...goodCurrentUser, + userId: goodCurrentUser.idpUserId, + token: token, + }; + delete submissionProxyHeaderInfo.idpUserId; + + const result = await service.generateProxyHeaders(submissionPayload, goodCurrentUser, token); + expect(result).toBeTruthy(); + expect(result['X-CHEFS-PROXY-DATA']).toBeTruthy(); + // check the encryption... + const decrypted = encryptionService.decryptProxy(result['X-CHEFS-PROXY-DATA']); + expect(JSON.parse(decrypted)).toMatchObject(submissionProxyHeaderInfo); + }); }); describe('readProxyHeaders', () => { - beforeEach(() => {}); - it('should throw error with no headers', async () => { await expect(service.readProxyHeaders(undefined)).rejects.toThrow(); }); @@ -108,6 +123,8 @@ describe('Proxy Service', () => { }); it('should return decrypted header data', async () => { + service._getIds = jest.fn().mockResolvedValueOnce({ ...goodPayload, submissionId: null }); + const headers = await service.generateProxyHeaders(goodPayload, goodCurrentUser, token); const decrypted = await service.readProxyHeaders(headers); expect(decrypted).toBeTruthy(); @@ -194,8 +211,6 @@ describe('Proxy Service', () => { }); }); describe('createExternalAPIHeaders', () => { - beforeEach(() => {}); - it('should throw error with no headers', async () => { const externalAPI = undefined; const proxyHeaderInfo = goodProxyHeaderInfo;