import { eventNamesAll } from './event-message-classes'; import express from 'express'; import type { MessageEventBusDestinationWebhookOptions, MessageEventBusDestinationOptions, } from 'n8n-workflow'; import { MessageEventBusDestinationTypeNames } from 'n8n-workflow'; import { RestController, Get, Post, Delete, GlobalScope, Licensed } from '@/decorators'; import { AuthenticatedRequest } from '@/requests'; import { BadRequestError } from '@/errors/response-errors/bad-request.error'; import { MessageEventBus } from './message-event-bus/message-event-bus'; import { isMessageEventBusDestinationSentryOptions, MessageEventBusDestinationSentry, } from './message-event-bus-destination/message-event-bus-destination-sentry.ee'; import { isMessageEventBusDestinationSyslogOptions, MessageEventBusDestinationSyslog, } from './message-event-bus-destination/message-event-bus-destination-syslog.ee'; import { MessageEventBusDestinationWebhook } from './message-event-bus-destination/message-event-bus-destination-webhook.ee'; import type { MessageEventBusDestination } from './message-event-bus-destination/message-event-bus-destination.ee'; const isWithIdString = (candidate: unknown): candidate is { id: string } => { const o = candidate as { id: string }; if (!o) return false; return o.id !== undefined; }; const isMessageEventBusDestinationWebhookOptions = ( candidate: unknown, ): candidate is MessageEventBusDestinationWebhookOptions => { const o = candidate as MessageEventBusDestinationWebhookOptions; if (!o) return false; return o.url !== undefined; }; const isMessageEventBusDestinationOptions = ( candidate: unknown, ): candidate is MessageEventBusDestinationOptions => { const o = candidate as MessageEventBusDestinationOptions; if (!o) return false; return o.__type !== undefined; }; @RestController('/eventbus') export class EventBusController { constructor(private readonly eventBus: MessageEventBus) {} @Get('/eventnames') async getEventNames(): Promise { return eventNamesAll; } @Licensed('feat:logStreaming') @Get('/destination') @GlobalScope('eventBusDestination:list') async getDestination(req: express.Request): Promise { if (isWithIdString(req.query)) { return await this.eventBus.findDestination(req.query.id); } else { return await this.eventBus.findDestination(); } } @Licensed('feat:logStreaming') @Post('/destination') @GlobalScope('eventBusDestination:create') async postDestination(req: AuthenticatedRequest): Promise { let result: MessageEventBusDestination | undefined; if (isMessageEventBusDestinationOptions(req.body)) { switch (req.body.__type) { case MessageEventBusDestinationTypeNames.sentry: if (isMessageEventBusDestinationSentryOptions(req.body)) { result = await this.eventBus.addDestination( new MessageEventBusDestinationSentry(this.eventBus, req.body), ); } break; case MessageEventBusDestinationTypeNames.webhook: if (isMessageEventBusDestinationWebhookOptions(req.body)) { result = await this.eventBus.addDestination( new MessageEventBusDestinationWebhook(this.eventBus, req.body), ); } break; case MessageEventBusDestinationTypeNames.syslog: if (isMessageEventBusDestinationSyslogOptions(req.body)) { result = await this.eventBus.addDestination( new MessageEventBusDestinationSyslog(this.eventBus, req.body), ); } break; default: throw new BadRequestError( `Body is missing ${req.body.__type} options or type ${req.body.__type} is unknown`, ); } if (result) { await result.saveToDb(); return { ...result.serialize(), eventBusInstance: undefined, }; } throw new BadRequestError('There was an error adding the destination'); } throw new BadRequestError('Body is not configuring MessageEventBusDestinationOptions'); } @Licensed('feat:logStreaming') @Get('/testmessage') @GlobalScope('eventBusDestination:test') async sendTestMessage(req: express.Request): Promise { if (isWithIdString(req.query)) { return await this.eventBus.testDestination(req.query.id); } return false; } @Licensed('feat:logStreaming') @Delete('/destination') @GlobalScope('eventBusDestination:delete') async deleteDestination(req: AuthenticatedRequest) { if (isWithIdString(req.query)) { return await this.eventBus.removeDestination(req.query.id); } else { throw new BadRequestError('Query is missing id'); } } }