From 2ab7bf1f43d6f75583eb5e2e2b6621499266b3d4 Mon Sep 17 00:00:00 2001 From: Win Date: Fri, 6 Sep 2024 15:20:42 +0700 Subject: [PATCH 1/6] MOL-358/PICT-242: update dockerfile location --- Dockerfile => processor/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename Dockerfile => processor/Dockerfile (91%) diff --git a/Dockerfile b/processor/Dockerfile similarity index 91% rename from Dockerfile rename to processor/Dockerfile index fa3edac..76c1d8f 100644 --- a/Dockerfile +++ b/processor/Dockerfile @@ -2,11 +2,11 @@ FROM node:18-alpine AS builder WORKDIR /app -COPY ./processor/package*.json ./ +COPY ./package*.json ./ RUN npm install --production --frozen-lockfile -COPY ./processor . +COPY . . RUN npm run build From 672c12f11097ef0a938b3681d030268257ba91fc Mon Sep 17 00:00:00 2001 From: Win Date: Mon, 9 Sep 2024 16:38:31 +0700 Subject: [PATCH 2/6] MOL-401: add mollie status checking endpoint --- .../src/controllers/connector.controller.ts | 27 +++++++-- processor/src/mollie/profile.mollie.ts | 22 +++++++ processor/src/routes/processor.route.ts | 4 +- processor/tests/mollie/profile.mollie.spec.ts | 59 +++++++++++++++++++ 4 files changed, 107 insertions(+), 5 deletions(-) create mode 100644 processor/src/mollie/profile.mollie.ts create mode 100644 processor/tests/mollie/profile.mollie.spec.ts diff --git a/processor/src/controllers/connector.controller.ts b/processor/src/controllers/connector.controller.ts index d38ccde..1b8b336 100644 --- a/processor/src/controllers/connector.controller.ts +++ b/processor/src/controllers/connector.controller.ts @@ -1,21 +1,38 @@ -import { apiSuccess } from '../api/success.api'; import { logger } from '../utils/logger.utils'; import { Request, Response } from 'express'; import CustomError from '../errors/custom.error'; import { apiError } from '../api/error.api'; import { formatErrorResponse } from '../errors/mollie.error'; import { createExtensionAndCustomFields, removeExtension } from '../service/connector.service'; +import { getProfile } from '../mollie/profile.mollie'; export const healthCheck = async (request: Request, response: Response) => { try { logger.debug('SCTM - healthCheck - The connector is running healthily.'); - return apiSuccess(200, response, []); + return response.status(200).json('The connector is running healthily.'); } catch (error) { logger.error('SCTM - healthCheck - Unexpected error occurred when processing request', error); return apiError(response, formatErrorResponse(error).errors); } }; +export const mollieStatus = async (request: Request, response: Response) => { + try { + logger.debug('SCTM - mollieStatus - Checking Mollie API status.'); + const profile = await getProfile(); + logger.debug('SCTM - mollieStatus - Mollie API status is functioning.'); + return response.status(200).json({ + mode: profile.mode, + name: profile.name, + website: profile.website, + status: profile.status, + }); + } catch (error) { + logger.error('SCTM - healthCheck - Unexpected error occurred when processing request', error); + return response.status(400).json(error).send(); + } +}; + export const install = async (request: Request, response: Response) => { const { extensionUrl } = request.body; @@ -29,7 +46,9 @@ export const install = async (request: Request, response: Response) => { logger.debug( 'SCTM - install - The connector was installed successfully with required extensions and custom fields.', ); - return apiSuccess(200, response, []); + return response + .status(200) + .json('The connector was installed successfully with required extensions and custom fields.'); } catch (error) { logger.error('SCTM - install - Unexpected error occurred when processing request', error); return apiError(response, formatErrorResponse(error).errors); @@ -40,7 +59,7 @@ export const uninstall = async (request: Request, response: Response) => { try { await removeExtension(); logger.debug('SCTM - uninstall - The connector was uninstalled successfully.'); - return apiSuccess(200, response, []); + return response.status(200).json('The connector was uninstalled successfully.'); } catch (error) { logger.error('SCTM - uninstallation - Unexpected error occurred when processing request', error); return apiError(response, formatErrorResponse(error).errors); diff --git a/processor/src/mollie/profile.mollie.ts b/processor/src/mollie/profile.mollie.ts new file mode 100644 index 0000000..ddef109 --- /dev/null +++ b/processor/src/mollie/profile.mollie.ts @@ -0,0 +1,22 @@ +import { initMollieClient } from '../client/mollie.client'; +import { MollieApiError, Profile } from '@mollie/api-client'; +import { logger } from '../utils/logger.utils'; +import CustomError from '../errors/custom.error'; + +export const getProfile = async (): Promise => { + try { + return await initMollieClient().profiles.getCurrent(); + } catch (error) { + let errorMessage; + if (error instanceof MollieApiError) { + errorMessage = `SCTM - getProfile - error: ${error.message}, field: ${error.field}`; + } else { + errorMessage = `SCTM - getProfile - Failed to get Mollie profile with unknown errors`; + } + + logger.error(errorMessage, { + error, + }); + throw new CustomError(400, errorMessage); + } +}; diff --git a/processor/src/routes/processor.route.ts b/processor/src/routes/processor.route.ts index 8ca5db6..8af5427 100644 --- a/processor/src/routes/processor.route.ts +++ b/processor/src/routes/processor.route.ts @@ -1,6 +1,6 @@ import { Router } from 'express'; import { post } from '../controllers/processor.controller'; -import { install, healthCheck, uninstall } from '../controllers/connector.controller'; +import { install, healthCheck, uninstall, mollieStatus } from '../controllers/connector.controller'; const serviceRouter = Router(); @@ -8,6 +8,8 @@ serviceRouter.post('/', post); serviceRouter.get('/health-check', healthCheck); +serviceRouter.get('/mollie/status', mollieStatus); + serviceRouter.post('/install', install); serviceRouter.post('/uninstall', uninstall); diff --git a/processor/tests/mollie/profile.mollie.spec.ts b/processor/tests/mollie/profile.mollie.spec.ts new file mode 100644 index 0000000..a30d469 --- /dev/null +++ b/processor/tests/mollie/profile.mollie.spec.ts @@ -0,0 +1,59 @@ +import { describe } from '@jest/globals'; +import { getProfile } from '../../src/mollie/profile.mollie'; +import { MollieApiError, Profile } from '@mollie/api-client'; +import { initMollieClient } from '../../src/client/mollie.client'; + +jest.mock('../../src/client/mollie.client', () => ({ + initMollieClient: jest.fn(), +})); + +describe('Test profile.mollie.ts', () => { + let mockProfile: Profile; + + beforeEach(() => { + mockProfile = { + mode: 'test', + name: 'Test Profile', + website: 'https://example.com', + status: 'verified', + } as unknown as Profile; + + (initMollieClient as jest.Mock).mockReturnValue({ + profiles: { + getCurrent: jest.fn().mockResolvedValue(mockProfile), + }, + }); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should return the current profile', async () => { + const profile = await getProfile(); + expect(profile).toEqual(mockProfile); + expect(initMollieClient).toHaveBeenCalled(); + }); + + it('should return Mollie API errors when fetching the profile', async () => { + const errorMessage = `SCTM - getProfile - error: Missing authentication, or failed to authenticate, field: undefined"`; + (initMollieClient as jest.Mock).mockReturnValue({ + profiles: { + getCurrent: jest.fn().mockRejectedValue(new MollieApiError(errorMessage)), + }, + }); + + await expect(getProfile()).rejects.toThrow(errorMessage); + }); + + it('should return unknown errors when fetching the profile', async () => { + const errorMessage = 'SCTM - getProfile - Failed to get Mollie profile with unknown errors'; + (initMollieClient as jest.Mock).mockReturnValue({ + profiles: { + getCurrent: jest.fn().mockRejectedValue(new Error(errorMessage)), + }, + }); + + await expect(getProfile()).rejects.toThrow(errorMessage); + }); +}); From 5cb1be9c26bed7939c98df3a6d36a8518c1662be Mon Sep 17 00:00:00 2001 From: Win Date: Mon, 9 Sep 2024 17:24:57 +0700 Subject: [PATCH 3/6] MOL-401: update --- processor/tests/mollie/profile.mollie.spec.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/processor/tests/mollie/profile.mollie.spec.ts b/processor/tests/mollie/profile.mollie.spec.ts index a30d469..b78e1a7 100644 --- a/processor/tests/mollie/profile.mollie.spec.ts +++ b/processor/tests/mollie/profile.mollie.spec.ts @@ -1,4 +1,4 @@ -import { describe } from '@jest/globals'; +import { describe, it, expect, beforeEach, afterEach, jest } from '@jest/globals'; import { getProfile } from '../../src/mollie/profile.mollie'; import { MollieApiError, Profile } from '@mollie/api-client'; import { initMollieClient } from '../../src/client/mollie.client'; @@ -20,7 +20,7 @@ describe('Test profile.mollie.ts', () => { (initMollieClient as jest.Mock).mockReturnValue({ profiles: { - getCurrent: jest.fn().mockResolvedValue(mockProfile), + getCurrent: jest.fn().mockReturnValue(mockProfile), }, }); }); @@ -39,7 +39,7 @@ describe('Test profile.mollie.ts', () => { const errorMessage = `SCTM - getProfile - error: Missing authentication, or failed to authenticate, field: undefined"`; (initMollieClient as jest.Mock).mockReturnValue({ profiles: { - getCurrent: jest.fn().mockRejectedValue(new MollieApiError(errorMessage)), + getCurrent: jest.fn().mockReturnValue(new MollieApiError(errorMessage)), }, }); @@ -50,7 +50,7 @@ describe('Test profile.mollie.ts', () => { const errorMessage = 'SCTM - getProfile - Failed to get Mollie profile with unknown errors'; (initMollieClient as jest.Mock).mockReturnValue({ profiles: { - getCurrent: jest.fn().mockRejectedValue(new Error(errorMessage)), + getCurrent: jest.fn().mockReturnValue(new Error(errorMessage)), }, }); From 0ba2e48f25e6fe6c0be414097e143e125747a914 Mon Sep 17 00:00:00 2001 From: Win Date: Mon, 9 Sep 2024 17:26:55 +0700 Subject: [PATCH 4/6] MOL-401: update test cases --- processor/tests/mollie/profile.mollie.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/processor/tests/mollie/profile.mollie.spec.ts b/processor/tests/mollie/profile.mollie.spec.ts index b78e1a7..d4f7cda 100644 --- a/processor/tests/mollie/profile.mollie.spec.ts +++ b/processor/tests/mollie/profile.mollie.spec.ts @@ -43,7 +43,7 @@ describe('Test profile.mollie.ts', () => { }, }); - await expect(getProfile()).rejects.toThrow(errorMessage); + await expect(getProfile()).resolves.toThrow(errorMessage); }); it('should return unknown errors when fetching the profile', async () => { @@ -54,6 +54,6 @@ describe('Test profile.mollie.ts', () => { }, }); - await expect(getProfile()).rejects.toThrow(errorMessage); + await expect(getProfile()).resolves.toThrow(errorMessage); }); }); From f443c109aaf1ba0baf52dc2de9007499cd29995a Mon Sep 17 00:00:00 2001 From: Win Date: Mon, 9 Sep 2024 18:13:06 +0700 Subject: [PATCH 5/6] MOL-363: temporary remove --- processor/src/utils/constant.utils.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/processor/src/utils/constant.utils.ts b/processor/src/utils/constant.utils.ts index 9cd855e..d91139a 100644 --- a/processor/src/utils/constant.utils.ts +++ b/processor/src/utils/constant.utils.ts @@ -23,11 +23,11 @@ export const CustomFields = { interfaceInteraction: { key: 'sctm_interface_interaction_type', fields: { - id: 'sctm_id', - actionType: 'sctm_action_type', - createdAt: 'sctm_created_at', - request: 'sctm_request', - response: 'sctm_response', + id: 'id', + actionType: 'actionType', + createdAt: 'createdAt', + request: 'request', + response: 'response', }, }, }, From 965b02012829c92e4f3d01505db6d667c22f1d00 Mon Sep 17 00:00:00 2001 From: Win Date: Mon, 9 Sep 2024 18:15:47 +0700 Subject: [PATCH 6/6] Revert "MOL-363: temporary remove" This reverts commit f443c109aaf1ba0baf52dc2de9007499cd29995a. --- processor/src/utils/constant.utils.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/processor/src/utils/constant.utils.ts b/processor/src/utils/constant.utils.ts index d91139a..9cd855e 100644 --- a/processor/src/utils/constant.utils.ts +++ b/processor/src/utils/constant.utils.ts @@ -23,11 +23,11 @@ export const CustomFields = { interfaceInteraction: { key: 'sctm_interface_interaction_type', fields: { - id: 'id', - actionType: 'actionType', - createdAt: 'createdAt', - request: 'request', - response: 'response', + id: 'sctm_id', + actionType: 'sctm_action_type', + createdAt: 'sctm_created_at', + request: 'sctm_request', + response: 'sctm_response', }, }, },