diff --git a/services/tenant-management-service/src/__tests__/acceptance/webhook.controller.acceptance.ts b/services/tenant-management-service/src/__tests__/acceptance/webhook.controller.acceptance.ts index e651d56..ba793b6 100644 --- a/services/tenant-management-service/src/__tests__/acceptance/webhook.controller.acceptance.ts +++ b/services/tenant-management-service/src/__tests__/acceptance/webhook.controller.acceptance.ts @@ -4,7 +4,7 @@ import {ILogger, LOGGER, STATUS_CODE} from '@sourceloop/core'; import {createHmac, randomBytes} from 'crypto'; import {TenantMgmtServiceApplication} from '../../application'; import {TenantStatus} from '../../enums'; -import {WEBHOOK_CONFIG} from '../../keys'; +import {PostWebhookHandlerServiceKey, WEBHOOK_CONFIG} from '../../keys'; import { ContactRepository, ResourceRepository, @@ -24,6 +24,7 @@ describe('WebhookController', () => { let tenantRepo: TenantRepository; let contactRepo: ContactRepository; let webhookPayload: WebhookPayload; + let postWebhookHandlerServiceStub: sinon.SinonStub; const nonExistantTenant = 'non-existant-tenant'; const notifStub = sinon.stub(); @@ -49,6 +50,11 @@ describe('WebhookController', () => { createNotification: notifStub, getTemplateByName: (name: string) => testTemplates[name], }); + + postWebhookHandlerServiceStub = sinon.stub(); + app.bind(PostWebhookHandlerServiceKey).to({ + postWebhookHandler: postWebhookHandlerServiceStub, + }); }); after(async () => { @@ -70,6 +76,19 @@ describe('WebhookController', () => { }); describe('Common', () => { + it('should call postWebhookHandler on successful webhook processing', async () => { + const headers = await buildHeaders(webhookPayload); + await client + .post('/webhook') + .set(webhookConfig.signatureHeaderName, headers.signature) + .set(webhookConfig.timestampHeaderName, headers.timestamp) + .send(webhookPayload) + .expect(STATUS_CODE.NO_CONTENT); + + // Verify that postWebhookHandler is called + sinon.assert.calledOnce(postWebhookHandlerServiceStub); + sinon.assert.calledWith(postWebhookHandlerServiceStub, webhookPayload); + }); it('should return 204 status for a webhook call with valid token', async () => { const headers = await buildHeaders(webhookPayload); await client diff --git a/services/tenant-management-service/src/keys.ts b/services/tenant-management-service/src/keys.ts index d9edad1..655a903 100644 --- a/services/tenant-management-service/src/keys.ts +++ b/services/tenant-management-service/src/keys.ts @@ -1,7 +1,9 @@ import {VerifyFunction} from 'loopback4-authentication'; import { + IPostWebhookHandlerService, ITenantManagementServiceConfig, LeadUser, + ResourceProvisionedWebhookPayload, WebhookConfig, WebhookNotificationServiceType, } from './types'; @@ -74,3 +76,7 @@ export const WebhookNotificationService = export const EventConnectorBinding = BindingKey.create< IEventConnector >('arc-saas.services.tenant-management.event-connector'); + +export const PostWebhookHandlerServiceKey = BindingKey.create< + IPostWebhookHandlerService +>('services.PostWebhookHandlerService'); diff --git a/services/tenant-management-service/src/services/webhook/provisioning-webhook.handler.ts b/services/tenant-management-service/src/services/webhook/provisioning-webhook.handler.ts index 402b4f5..5d87c7b 100644 --- a/services/tenant-management-service/src/services/webhook/provisioning-webhook.handler.ts +++ b/services/tenant-management-service/src/services/webhook/provisioning-webhook.handler.ts @@ -15,6 +15,8 @@ import { } from '../../types'; import {CryptoHelperService} from '../crypto-helper.service'; import {NotificationService} from '../notifications'; +import {IPostWebhookHandlerService} from '../../types/i-post-webhook-handler-service.interface'; +import {PostWebhookHandlerServiceKey} from '../../keys'; /** * Handler for provisioning webhooks. @@ -41,6 +43,8 @@ export class ProvisioningWebhookHandler implements IWebhookHandler { public tenantRepository: TenantRepository, @inject('services.NotificationService') private notificationService: NotificationService, + @inject(PostWebhookHandlerServiceKey) + private postWebhookHandlerService: IPostWebhookHandlerService, @service(CryptoHelperService) private cryptoHelperService: CryptoHelperService, @inject(LOGGER.LOGGER_INJECT) @@ -97,6 +101,7 @@ export class ProvisioningWebhookHandler implements IWebhookHandler { {transaction}, ); } + await this.postWebhookHandlerService.postWebhookHandler(payload); await transaction.commit(); } catch (e) { diff --git a/services/tenant-management-service/src/types/i-post-webhook-handler-service.interface.ts b/services/tenant-management-service/src/types/i-post-webhook-handler-service.interface.ts new file mode 100644 index 0000000..1518066 --- /dev/null +++ b/services/tenant-management-service/src/types/i-post-webhook-handler-service.interface.ts @@ -0,0 +1,7 @@ +import {ResourceProvisionedWebhookPayload} from './webhook-payload.type'; + +export interface IPostWebhookHandlerService< + T extends ResourceProvisionedWebhookPayload, +> { + postWebhookHandler(dto: T): Promise; +} diff --git a/services/tenant-management-service/src/types/index.ts b/services/tenant-management-service/src/types/index.ts index 9cea043..0b6a3bf 100644 --- a/services/tenant-management-service/src/types/index.ts +++ b/services/tenant-management-service/src/types/index.ts @@ -38,3 +38,4 @@ export * from './resource.type'; export * from './i-provisioning-service.interface'; export * from './i-subscription.interface'; export * from './i-event-connector.interface'; +export * from './i-post-webhook-handler-service.interface';