diff --git a/src/lib/services/addon-service.test.ts b/src/lib/services/addon-service.test.ts index b73fb24c32..902674420b 100644 --- a/src/lib/services/addon-service.test.ts +++ b/src/lib/services/addon-service.test.ts @@ -1,5 +1,5 @@ import { ValidationError } from 'joi'; - +import type { Logger } from '../../lib/logger'; import getLogger from '../../test/fixtures/no-logger'; import TagTypeService from '../features/tag-type/tag-type-service'; import { @@ -55,6 +55,7 @@ function getSetup() { getLogger, // @ts-ignore server: { unleashUrl: 'http://test' }, + flagResolver: {} as IFlagResolver, }, tagTypeService, eventService, @@ -67,6 +68,38 @@ function getSetup() { }; } +function getSetupWithLogger(logProvider: () => Logger) { + const stores = createStores(); + const eventService = createFakeEventsService(config); + const tagTypeService = new TagTypeService( + stores, + { getLogger: logProvider }, + eventService, + ); + const integrationEventsService = new IntegrationEventsService(stores, { + getLogger: logProvider, + flagResolver: {} as IFlagResolver, + }); + + return { + addonService: new AddonService( + stores, + { + getLogger: logProvider, + // @ts-ignore + server: { unleashUrl: 'http://test' }, + flagResolver: {} as IFlagResolver, + }, + tagTypeService, + eventService, + integrationEventsService, + ), + eventService, + stores, + tagTypeService, + }; +} + test('should load addon configurations', async () => { const { addonService } = getSetup(); @@ -814,3 +847,116 @@ test('Should reject addon config if a required parameter is just the empty strin addonService.createAddon(config, TEST_AUDIT_USER), ).rejects.toThrow(ValidationError); }); + +test('should log resolved domain', async () => { + const loggerMock = { + debug: jest.fn(), + info: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + fatal: jest.fn(), + }; + const getLogger = jest.fn(() => loggerMock); + const { addonService } = getSetupWithLogger(getLogger); + + const config: IAddonDto = { + provider: 'webhook', + description: '', + enabled: true, + parameters: { + url: 'http://localhost/wh', + var: 'some-value', + }, + events: [FEATURE_CREATED], + }; + await addonService.createAddon(config, TEST_AUDIT_USER); + expect(getLogger).toHaveBeenCalled(); + expect(loggerMock.info).toHaveBeenCalledWith(`Webhook created`, { + domain: 'localhost', + }); +}); + +test('should log resolved domain with last slash missing', async () => { + const loggerMock = { + debug: jest.fn(), + info: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + fatal: jest.fn(), + }; + const getLogger = jest.fn(() => loggerMock); + const { addonService } = getSetupWithLogger(getLogger); + + const config: IAddonDto = { + provider: 'webhook', + description: '', + enabled: true, + parameters: { + url: 'http://localhost', + var: 'some-value', + }, + events: [FEATURE_CREATED], + }; + await addonService.createAddon(config, TEST_AUDIT_USER); + expect(getLogger).toHaveBeenCalled(); + expect(loggerMock.info).toHaveBeenCalledWith(`Webhook created`, { + domain: 'localhost', + }); +}); + +test('will log with port if specified', async () => { + const loggerMock = { + debug: jest.fn(), + info: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + fatal: jest.fn(), + }; + const getLogger = jest.fn(() => loggerMock); + const { addonService } = getSetupWithLogger(getLogger); + + const config: IAddonDto = { + provider: 'webhook', + description: '', + enabled: true, + parameters: { + url: 'http://localhost:8080', + var: 'some-value', + }, + events: [FEATURE_CREATED], + }; + await addonService.createAddon(config, TEST_AUDIT_USER); + expect(getLogger).toHaveBeenCalled(); + expect(loggerMock.info).toHaveBeenCalledWith(`Webhook created`, { + domain: 'localhost:8080', + }); +}); + +test('should not log if protocol missing', async () => { + const loggerMock = { + debug: jest.fn(), + info: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + fatal: jest.fn(), + }; + const getLogger = jest.fn(() => loggerMock); + const { addonService } = getSetupWithLogger(getLogger); + + const config: IAddonDto = { + provider: 'webhook', + description: '', + enabled: true, + parameters: { + url: '://localhost/wh', + var: 'some-value', + }, + events: [FEATURE_CREATED], + }; + await addonService.createAddon(config, TEST_AUDIT_USER); + expect(getLogger).toHaveBeenCalled(); + expect(loggerMock.info).toHaveBeenCalledTimes(1); + expect(loggerMock.info).not.toHaveBeenCalledWith(`Webhook created`, { + domain: 'localhost', + }); +}); diff --git a/src/lib/services/addon-service.ts b/src/lib/services/addon-service.ts index 3bf4542e2c..5c677cd04b 100644 --- a/src/lib/services/addon-service.ts +++ b/src/lib/services/addon-service.ts @@ -225,6 +225,22 @@ export default class AddonService { `User ${auditUser.username} created addon ${addonConfig.provider}`, ); + if ( + addonConfig.provider === 'webhook' && + addonConfig.parameters.url && + addonConfig.parameters.url.indexOf('://') > 0 + ) { + const start = addonConfig.parameters.url.indexOf('://') + 3; + let end = addonConfig.parameters.url.indexOf('/', start); + if (end === -1) { + end = addonConfig.parameters.url.length; + } + const domain = addonConfig.parameters.url.substring(start, end); + this.logger.info(`Webhook created`, { + domain, + }); + } + await this.eventService.storeEvent( new AddonConfigCreatedEvent({ data: omitKeys(createdAddon, 'parameters'), @@ -259,6 +275,23 @@ export default class AddonService { ); } const result = await this.addonStore.update(id, addonConfig); + + if ( + addonConfig.provider === 'webhook' && + addonConfig.parameters.url && + addonConfig.parameters.url.indexOf('://') > 0 + ) { + const start = addonConfig.parameters.url.indexOf('://') + 3; + let end = addonConfig.parameters.url.indexOf('/', start); + if (end === -1) { + end = addonConfig.parameters.url.length; + } + const domain = addonConfig.parameters.url.substring(start, end); + this.logger.info(`Webhook updated`, { + domain, + }); + } + await this.eventService.storeEvent( new AddonConfigUpdatedEvent({ preData: omitKeys(existingConfig, 'parameters'),