From b7242d2c1d1571e15ab7f05a82f04ce3bbc44349 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Fri, 2 Aug 2024 12:25:07 +0200 Subject: [PATCH 1/7] refactor(core): Clean up event relays (no-changelog) --- .../ExternalSecretsManager.ee.ts | 2 +- packages/cli/src/InternalHooks.ts | 4 +- packages/cli/src/Ldap/ldap.controller.ee.ts | 2 +- packages/cli/src/Ldap/ldap.service.ee.ts | 2 +- packages/cli/src/PublicApi/index.ts | 2 +- .../credentials/credentials.service.ts | 2 +- .../sourceControl/sourceControl.handler.ts | 2 +- .../handlers/workflows/workflows.handler.ts | 2 +- packages/cli/src/Server.ts | 6 +- .../email/UserManagementMailer.ts | 2 +- .../cli/src/WorkflowExecuteAdditionalData.ts | 2 +- packages/cli/src/WorkflowRunner.ts | 2 +- packages/cli/src/auth/methods/email.ts | 2 +- packages/cli/src/auth/methods/ldap.ts | 2 +- packages/cli/src/commands/BaseCommand.ts | 2 +- packages/cli/src/commands/start.ts | 2 +- packages/cli/src/commands/worker.ts | 4 +- .../concurrency-control.service.test.ts | 2 +- .../concurrency-control.service.ts | 2 +- .../cli/src/controllers/auth.controller.ts | 2 +- .../communityPackages.controller.ts | 2 +- .../src/controllers/invitation.controller.ts | 2 +- packages/cli/src/controllers/me.controller.ts | 2 +- .../controllers/passwordReset.controller.ts | 2 +- .../cli/src/controllers/project.controller.ts | 2 +- .../cli/src/controllers/users.controller.ts | 2 +- .../src/credentials/credentials.controller.ts | 2 +- packages/cli/src/decorators/Redactable.ts | 4 +- .../sourceControl.controller.ee.ts | 2 +- .../sourceControl/sourceControl.service.ee.ts | 2 +- .../variables/variables.service.ee.ts | 2 +- packages/cli/src/errors/redactable.error.ts | 2 +- packages/cli/src/eventbus/event.service.ts | 6 - .../__tests__/log-event-relay.test.ts} | 50 ++-- packages/cli/src/events/event-relay.ts | 22 ++ packages/cli/src/events/event.service.ts | 6 + .../log-event-relay.ts} | 157 ++++++------ .../relay-event-map.ts} | 89 +++++-- .../telemetry-event-relay.ts} | 227 ++++++++---------- .../execution-recovery.service.test.ts | 2 +- .../executions/execution-recovery.service.ts | 2 +- packages/cli/src/license/license.service.ts | 2 +- packages/cli/src/services/user.service.ts | 2 +- .../src/sso/saml/routes/saml.controller.ee.ts | 2 +- .../cli/src/workflows/workflow.service.ts | 2 +- .../cli/src/workflows/workflows.controller.ts | 2 +- .../externalSecrets.api.test.ts | 2 +- .../integration/commands/worker.cmd.test.ts | 6 +- .../test/unit/license/license.service.test.ts | 2 +- 49 files changed, 349 insertions(+), 306 deletions(-) delete mode 100644 packages/cli/src/eventbus/event.service.ts rename packages/cli/src/{eventbus/__tests__/audit-event-relay.service.test.ts => events/__tests__/log-event-relay.test.ts} (91%) create mode 100644 packages/cli/src/events/event-relay.ts create mode 100644 packages/cli/src/events/event.service.ts rename packages/cli/src/{eventbus/audit-event-relay.service.ts => events/log-event-relay.ts} (53%) rename packages/cli/src/{eventbus/event.types.ts => events/relay-event-map.ts} (92%) rename packages/cli/src/{telemetry/telemetry-event-relay.service.ts => events/telemetry-event-relay.ts} (75%) diff --git a/packages/cli/src/ExternalSecrets/ExternalSecretsManager.ee.ts b/packages/cli/src/ExternalSecrets/ExternalSecretsManager.ee.ts index 03436f3d7acaf..2ae33be62aa9e 100644 --- a/packages/cli/src/ExternalSecrets/ExternalSecretsManager.ee.ts +++ b/packages/cli/src/ExternalSecrets/ExternalSecretsManager.ee.ts @@ -13,7 +13,7 @@ import { Logger } from '@/Logger'; import { jsonParse, type IDataObject, ApplicationError } from 'n8n-workflow'; import { EXTERNAL_SECRETS_INITIAL_BACKOFF, EXTERNAL_SECRETS_MAX_BACKOFF } from './constants'; import { License } from '@/License'; -import { EventService } from '@/eventbus/event.service'; +import { EventService } from '@/events/event.service'; import { updateIntervalTime } from './externalSecretsHelper.ee'; import { ExternalSecretsProviders } from './ExternalSecretsProviders.ee'; import { OrchestrationService } from '@/services/orchestration.service'; diff --git a/packages/cli/src/InternalHooks.ts b/packages/cli/src/InternalHooks.ts index 46637106b7a47..0c3c670373284 100644 --- a/packages/cli/src/InternalHooks.ts +++ b/packages/cli/src/InternalHooks.ts @@ -9,8 +9,8 @@ import { Telemetry } from '@/telemetry'; import { MessageEventBus } from './eventbus/MessageEventBus/MessageEventBus'; /** - * @deprecated Do not add to this class. To add audit or telemetry events, use - * `EventService` to emit the event and then use the `AuditEventRelay` or + * @deprecated Do not add to this class. To add log or telemetry events, use + * `EventService` to emit the event and then use the `LogEventRelay` or * `TelemetryEventRelay` to forward them to the event bus or telemetry. */ @Service() diff --git a/packages/cli/src/Ldap/ldap.controller.ee.ts b/packages/cli/src/Ldap/ldap.controller.ee.ts index 9bdbea39b2d99..7a56d8049d9ca 100644 --- a/packages/cli/src/Ldap/ldap.controller.ee.ts +++ b/packages/cli/src/Ldap/ldap.controller.ee.ts @@ -6,7 +6,7 @@ import { NON_SENSIBLE_LDAP_CONFIG_PROPERTIES } from './constants'; import { getLdapSynchronizations } from './helpers.ee'; import { LdapConfiguration } from './types'; import { LdapService } from './ldap.service.ee'; -import { EventService } from '@/eventbus/event.service'; +import { EventService } from '@/events/event.service'; @RestController('/ldap') export class LdapController { diff --git a/packages/cli/src/Ldap/ldap.service.ee.ts b/packages/cli/src/Ldap/ldap.service.ee.ts index 85c8c6c636ea6..32c3152fb5f47 100644 --- a/packages/cli/src/Ldap/ldap.service.ee.ts +++ b/packages/cli/src/Ldap/ldap.service.ee.ts @@ -44,7 +44,7 @@ import { LDAP_LOGIN_ENABLED, LDAP_LOGIN_LABEL, } from './constants'; -import { EventService } from '@/eventbus/event.service'; +import { EventService } from '@/events/event.service'; @Service() export class LdapService { diff --git a/packages/cli/src/PublicApi/index.ts b/packages/cli/src/PublicApi/index.ts index d484a34e36941..af4fc97fc7907 100644 --- a/packages/cli/src/PublicApi/index.ts +++ b/packages/cli/src/PublicApi/index.ts @@ -15,7 +15,7 @@ import { UserRepository } from '@db/repositories/user.repository'; import { UrlService } from '@/services/url.service'; import type { AuthenticatedRequest } from '@/requests'; import { GlobalConfig } from '@n8n/config'; -import { EventService } from '@/eventbus/event.service'; +import { EventService } from '@/events/event.service'; async function createApiRouter( version: string, diff --git a/packages/cli/src/PublicApi/v1/handlers/credentials/credentials.service.ts b/packages/cli/src/PublicApi/v1/handlers/credentials/credentials.service.ts index 668424530a516..2c4a35a6aa177 100644 --- a/packages/cli/src/PublicApi/v1/handlers/credentials/credentials.service.ts +++ b/packages/cli/src/PublicApi/v1/handlers/credentials/credentials.service.ts @@ -17,7 +17,7 @@ import { Container } from 'typedi'; import { CredentialsRepository } from '@db/repositories/credentials.repository'; import { SharedCredentialsRepository } from '@db/repositories/sharedCredentials.repository'; import { ProjectRepository } from '@/databases/repositories/project.repository'; -import { EventService } from '@/eventbus/event.service'; +import { EventService } from '@/events/event.service'; export async function getCredentials(credentialId: string): Promise { return await Container.get(CredentialsRepository).findOneBy({ id: credentialId }); diff --git a/packages/cli/src/PublicApi/v1/handlers/sourceControl/sourceControl.handler.ts b/packages/cli/src/PublicApi/v1/handlers/sourceControl/sourceControl.handler.ts index f54e8bd95d8e2..7a3cf08ec0eb5 100644 --- a/packages/cli/src/PublicApi/v1/handlers/sourceControl/sourceControl.handler.ts +++ b/packages/cli/src/PublicApi/v1/handlers/sourceControl/sourceControl.handler.ts @@ -10,7 +10,7 @@ import { getTrackingInformationFromPullResult, isSourceControlLicensed, } from '@/environments/sourceControl/sourceControlHelper.ee'; -import { EventService } from '@/eventbus/event.service'; +import { EventService } from '@/events/event.service'; export = { pull: [ diff --git a/packages/cli/src/PublicApi/v1/handlers/workflows/workflows.handler.ts b/packages/cli/src/PublicApi/v1/handlers/workflows/workflows.handler.ts index 4063d0b611d35..16434ef4e9a1e 100644 --- a/packages/cli/src/PublicApi/v1/handlers/workflows/workflows.handler.ts +++ b/packages/cli/src/PublicApi/v1/handlers/workflows/workflows.handler.ts @@ -32,7 +32,7 @@ import { SharedWorkflowRepository } from '@/databases/repositories/sharedWorkflo import { TagRepository } from '@/databases/repositories/tag.repository'; import { WorkflowRepository } from '@/databases/repositories/workflow.repository'; import { ProjectRepository } from '@/databases/repositories/project.repository'; -import { EventService } from '@/eventbus/event.service'; +import { EventService } from '@/events/event.service'; import { z } from 'zod'; import { EnterpriseWorkflowService } from '@/workflows/workflow.service.ee'; diff --git a/packages/cli/src/Server.ts b/packages/cli/src/Server.ts index 4c9628bc1bf1d..0fad10235e572 100644 --- a/packages/cli/src/Server.ts +++ b/packages/cli/src/Server.ts @@ -35,7 +35,7 @@ import { MessageEventBus } from '@/eventbus/MessageEventBus/MessageEventBus'; import { handleMfaDisable, isMfaFeatureEnabled } from '@/Mfa/helpers'; import type { FrontendService } from '@/services/frontend.service'; import { OrchestrationService } from '@/services/orchestration.service'; -import { AuditEventRelay } from './eventbus/audit-event-relay.service'; +import { LogEventRelay } from '@/events/log-event-relay'; import '@/controllers/activeWorkflows.controller'; import '@/controllers/auth.controller'; @@ -64,7 +64,7 @@ import '@/ExternalSecrets/ExternalSecrets.controller.ee'; import '@/license/license.controller'; import '@/workflows/workflowHistory/workflowHistory.controller.ee'; import '@/workflows/workflows.controller'; -import { EventService } from './eventbus/event.service'; +import { EventService } from './events/event.service'; const exec = promisify(callbackExec); @@ -250,7 +250,7 @@ export class Server extends AbstractServer { // ---------------------------------------- const eventBus = Container.get(MessageEventBus); await eventBus.initialize(); - Container.get(AuditEventRelay).init(); + Container.get(LogEventRelay).init(); if (this.endpointPresetCredentials !== '') { // POST endpoint to set preset credentials diff --git a/packages/cli/src/UserManagement/email/UserManagementMailer.ts b/packages/cli/src/UserManagement/email/UserManagementMailer.ts index 6d60c3b4907e1..1e092077b10de 100644 --- a/packages/cli/src/UserManagement/email/UserManagementMailer.ts +++ b/packages/cli/src/UserManagement/email/UserManagementMailer.ts @@ -16,7 +16,7 @@ import { toError } from '@/utils'; import type { InviteEmailData, PasswordResetData, SendEmailResult } from './Interfaces'; import { NodeMailer } from './NodeMailer'; -import { EventService } from '@/eventbus/event.service'; +import { EventService } from '@/events/event.service'; type Template = HandlebarsTemplateDelegate; type TemplateName = 'invite' | 'passwordReset' | 'workflowShared' | 'credentialsShared'; diff --git a/packages/cli/src/WorkflowExecuteAdditionalData.ts b/packages/cli/src/WorkflowExecuteAdditionalData.ts index 9538ec91988fd..74c469284a7eb 100644 --- a/packages/cli/src/WorkflowExecuteAdditionalData.ts +++ b/packages/cli/src/WorkflowExecuteAdditionalData.ts @@ -70,7 +70,7 @@ import { WorkflowRepository } from './databases/repositories/workflow.repository import { UrlService } from './services/url.service'; import { WorkflowExecutionService } from './workflows/workflowExecution.service'; import { MessageEventBus } from '@/eventbus/MessageEventBus/MessageEventBus'; -import { EventService } from './eventbus/event.service'; +import { EventService } from './events/event.service'; import { GlobalConfig } from '@n8n/config'; import { SubworkflowPolicyChecker } from './subworkflows/subworkflow-policy-checker.service'; diff --git a/packages/cli/src/WorkflowRunner.ts b/packages/cli/src/WorkflowRunner.ts index f51a44cc4d2a3..2f7976a073b30 100644 --- a/packages/cli/src/WorkflowRunner.ts +++ b/packages/cli/src/WorkflowRunner.ts @@ -36,7 +36,7 @@ import { generateFailedExecutionFromError } from '@/WorkflowHelpers'; import { PermissionChecker } from '@/UserManagement/PermissionChecker'; import { Logger } from '@/Logger'; import { WorkflowStaticDataService } from '@/workflows/workflowStaticData.service'; -import { EventService } from './eventbus/event.service'; +import { EventService } from './events/event.service'; @Service() export class WorkflowRunner { diff --git a/packages/cli/src/auth/methods/email.ts b/packages/cli/src/auth/methods/email.ts index a88d00186b06a..f954991974570 100644 --- a/packages/cli/src/auth/methods/email.ts +++ b/packages/cli/src/auth/methods/email.ts @@ -4,7 +4,7 @@ import { Container } from 'typedi'; import { isLdapLoginEnabled } from '@/Ldap/helpers.ee'; import { UserRepository } from '@db/repositories/user.repository'; import { AuthError } from '@/errors/response-errors/auth.error'; -import { EventService } from '@/eventbus/event.service'; +import { EventService } from '@/events/event.service'; export const handleEmailLogin = async ( email: string, diff --git a/packages/cli/src/auth/methods/ldap.ts b/packages/cli/src/auth/methods/ldap.ts index c8946aec9321e..c632557c95c85 100644 --- a/packages/cli/src/auth/methods/ldap.ts +++ b/packages/cli/src/auth/methods/ldap.ts @@ -12,7 +12,7 @@ import { updateLdapUserOnLocalDb, } from '@/Ldap/helpers.ee'; import type { User } from '@db/entities/User'; -import { EventService } from '@/eventbus/event.service'; +import { EventService } from '@/events/event.service'; export const handleLdapLogin = async ( loginId: string, diff --git a/packages/cli/src/commands/BaseCommand.ts b/packages/cli/src/commands/BaseCommand.ts index 4cebc7fbb66f6..9828e6207b525 100644 --- a/packages/cli/src/commands/BaseCommand.ts +++ b/packages/cli/src/commands/BaseCommand.ts @@ -23,7 +23,7 @@ import { initExpressionEvaluator } from '@/ExpressionEvaluator'; import { generateHostInstanceId } from '@db/utils/generators'; import { WorkflowHistoryManager } from '@/workflows/workflowHistory/workflowHistoryManager.ee'; import { ShutdownService } from '@/shutdown/Shutdown.service'; -import { TelemetryEventRelay } from '@/telemetry/telemetry-event-relay.service'; +import { TelemetryEventRelay } from '@/events/telemetry-event-relay'; export abstract class BaseCommand extends Command { protected logger = Container.get(Logger); diff --git a/packages/cli/src/commands/start.ts b/packages/cli/src/commands/start.ts index 4d7cd888b4cc0..39448920420ea 100644 --- a/packages/cli/src/commands/start.ts +++ b/packages/cli/src/commands/start.ts @@ -33,7 +33,7 @@ import { ExecutionService } from '@/executions/execution.service'; import { OwnershipService } from '@/services/ownership.service'; import { WorkflowRunner } from '@/WorkflowRunner'; import { ExecutionRecoveryService } from '@/executions/execution-recovery.service'; -import { EventService } from '@/eventbus/event.service'; +import { EventService } from '@/events/event.service'; // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires const open = require('open'); diff --git a/packages/cli/src/commands/worker.ts b/packages/cli/src/commands/worker.ts index 4f582904cddbb..9029f6b86e432 100644 --- a/packages/cli/src/commands/worker.ts +++ b/packages/cli/src/commands/worker.ts @@ -30,7 +30,7 @@ import type { WorkerJobStatusSummary } from '@/services/orchestration/worker/typ import { ServiceUnavailableError } from '@/errors/response-errors/service-unavailable.error'; import { BaseCommand } from './BaseCommand'; import { MaxStalledCountError } from '@/errors/max-stalled-count.error'; -import { AuditEventRelay } from '@/eventbus/audit-event-relay.service'; +import { LogEventRelay } from '@/events/log-event-relay'; export class Worker extends BaseCommand { static description = '\nStarts a n8n worker'; @@ -286,7 +286,7 @@ export class Worker extends BaseCommand { await Container.get(MessageEventBus).initialize({ workerId: this.queueModeId, }); - Container.get(AuditEventRelay).init(); + Container.get(LogEventRelay).init(); } /** diff --git a/packages/cli/src/concurrency/__tests__/concurrency-control.service.test.ts b/packages/cli/src/concurrency/__tests__/concurrency-control.service.test.ts index c694ab29406a3..08f58ac600324 100644 --- a/packages/cli/src/concurrency/__tests__/concurrency-control.service.test.ts +++ b/packages/cli/src/concurrency/__tests__/concurrency-control.service.test.ts @@ -12,7 +12,7 @@ import type { WorkflowExecuteMode as ExecutionMode } from 'n8n-workflow'; import type { ExecutionRepository } from '@/databases/repositories/execution.repository'; import type { IExecutingWorkflowData } from '@/Interfaces'; import type { Telemetry } from '@/telemetry'; -import type { EventService } from '@/eventbus/event.service'; +import type { EventService } from '@/events/event.service'; describe('ConcurrencyControlService', () => { const logger = mock(); diff --git a/packages/cli/src/concurrency/concurrency-control.service.ts b/packages/cli/src/concurrency/concurrency-control.service.ts index 50c73fa668b4e..6e62e9b78df54 100644 --- a/packages/cli/src/concurrency/concurrency-control.service.ts +++ b/packages/cli/src/concurrency/concurrency-control.service.ts @@ -8,7 +8,7 @@ import { ExecutionRepository } from '@/databases/repositories/execution.reposito import type { WorkflowExecuteMode as ExecutionMode } from 'n8n-workflow'; import type { IExecutingWorkflowData } from '@/Interfaces'; import { Telemetry } from '@/telemetry'; -import { EventService } from '@/eventbus/event.service'; +import { EventService } from '@/events/event.service'; export const CLOUD_TEMP_PRODUCTION_LIMIT = 999; export const CLOUD_TEMP_REPORTABLE_THRESHOLDS = [5, 10, 20, 50, 100, 200]; diff --git a/packages/cli/src/controllers/auth.controller.ts b/packages/cli/src/controllers/auth.controller.ts index 7711d95177e0f..e2a481fae9fe0 100644 --- a/packages/cli/src/controllers/auth.controller.ts +++ b/packages/cli/src/controllers/auth.controller.ts @@ -24,7 +24,7 @@ import { BadRequestError } from '@/errors/response-errors/bad-request.error'; import { ForbiddenError } from '@/errors/response-errors/forbidden.error'; import { ApplicationError } from 'n8n-workflow'; import { UserRepository } from '@/databases/repositories/user.repository'; -import { EventService } from '@/eventbus/event.service'; +import { EventService } from '@/events/event.service'; @RestController() export class AuthController { diff --git a/packages/cli/src/controllers/communityPackages.controller.ts b/packages/cli/src/controllers/communityPackages.controller.ts index 1860e1df86652..e6323c728cb40 100644 --- a/packages/cli/src/controllers/communityPackages.controller.ts +++ b/packages/cli/src/controllers/communityPackages.controller.ts @@ -13,7 +13,7 @@ import { Push } from '@/push'; import { CommunityPackagesService } from '@/services/communityPackages.service'; import { BadRequestError } from '@/errors/response-errors/bad-request.error'; import { InternalServerError } from '@/errors/response-errors/internal-server.error'; -import { EventService } from '@/eventbus/event.service'; +import { EventService } from '@/events/event.service'; const { PACKAGE_NOT_INSTALLED, diff --git a/packages/cli/src/controllers/invitation.controller.ts b/packages/cli/src/controllers/invitation.controller.ts index c32bf543002fd..edf3b5c151fcc 100644 --- a/packages/cli/src/controllers/invitation.controller.ts +++ b/packages/cli/src/controllers/invitation.controller.ts @@ -18,7 +18,7 @@ import { BadRequestError } from '@/errors/response-errors/bad-request.error'; import { ForbiddenError } from '@/errors/response-errors/forbidden.error'; import { InternalHooks } from '@/InternalHooks'; import { ExternalHooks } from '@/ExternalHooks'; -import { EventService } from '@/eventbus/event.service'; +import { EventService } from '@/events/event.service'; @RestController('/invitations') export class InvitationController { diff --git a/packages/cli/src/controllers/me.controller.ts b/packages/cli/src/controllers/me.controller.ts index 3f9366b441260..39dfc93ab7406 100644 --- a/packages/cli/src/controllers/me.controller.ts +++ b/packages/cli/src/controllers/me.controller.ts @@ -23,7 +23,7 @@ import { InternalHooks } from '@/InternalHooks'; import { BadRequestError } from '@/errors/response-errors/bad-request.error'; import { UserRepository } from '@/databases/repositories/user.repository'; import { isApiEnabled } from '@/PublicApi'; -import { EventService } from '@/eventbus/event.service'; +import { EventService } from '@/events/event.service'; export const API_KEY_PREFIX = 'n8n_api_'; diff --git a/packages/cli/src/controllers/passwordReset.controller.ts b/packages/cli/src/controllers/passwordReset.controller.ts index e17a0f15efe63..84d3b40124ad8 100644 --- a/packages/cli/src/controllers/passwordReset.controller.ts +++ b/packages/cli/src/controllers/passwordReset.controller.ts @@ -21,7 +21,7 @@ import { ForbiddenError } from '@/errors/response-errors/forbidden.error'; import { NotFoundError } from '@/errors/response-errors/not-found.error'; import { UnprocessableRequestError } from '@/errors/response-errors/unprocessable.error'; import { UserRepository } from '@/databases/repositories/user.repository'; -import { EventService } from '@/eventbus/event.service'; +import { EventService } from '@/events/event.service'; @RestController() export class PasswordResetController { diff --git a/packages/cli/src/controllers/project.controller.ts b/packages/cli/src/controllers/project.controller.ts index 848ba4b84c6eb..e93b919ecb8e3 100644 --- a/packages/cli/src/controllers/project.controller.ts +++ b/packages/cli/src/controllers/project.controller.ts @@ -23,7 +23,7 @@ import { ProjectRepository } from '@/databases/repositories/project.repository'; // eslint-disable-next-line n8n-local-rules/misplaced-n8n-typeorm-import import { In, Not } from '@n8n/typeorm'; import { BadRequestError } from '@/errors/response-errors/bad-request.error'; -import { EventService } from '@/eventbus/event.service'; +import { EventService } from '@/events/event.service'; @RestController('/projects') export class ProjectController { diff --git a/packages/cli/src/controllers/users.controller.ts b/packages/cli/src/controllers/users.controller.ts index f0815aa54d405..aee2fd28c2a27 100644 --- a/packages/cli/src/controllers/users.controller.ts +++ b/packages/cli/src/controllers/users.controller.ts @@ -28,7 +28,7 @@ import { Project } from '@/databases/entities/Project'; import { WorkflowService } from '@/workflows/workflow.service'; import { CredentialsService } from '@/credentials/credentials.service'; import { ProjectService } from '@/services/project.service'; -import { EventService } from '@/eventbus/event.service'; +import { EventService } from '@/events/event.service'; @RestController('/users') export class UsersController { diff --git a/packages/cli/src/credentials/credentials.controller.ts b/packages/cli/src/credentials/credentials.controller.ts index 1587fbd1ca426..9ac57bb2e3af3 100644 --- a/packages/cli/src/credentials/credentials.controller.ts +++ b/packages/cli/src/credentials/credentials.controller.ts @@ -30,7 +30,7 @@ import { SharedCredentialsRepository } from '@/databases/repositories/sharedCred import { SharedCredentials } from '@/databases/entities/SharedCredentials'; import { ProjectRelationRepository } from '@/databases/repositories/projectRelation.repository'; import { z } from 'zod'; -import { EventService } from '@/eventbus/event.service'; +import { EventService } from '@/events/event.service'; @RestController('/credentials') export class CredentialsController { diff --git a/packages/cli/src/decorators/Redactable.ts b/packages/cli/src/decorators/Redactable.ts index e5debeb7a1507..a6b6f708e7787 100644 --- a/packages/cli/src/decorators/Redactable.ts +++ b/packages/cli/src/decorators/Redactable.ts @@ -1,5 +1,5 @@ import { RedactableError } from '@/errors/redactable.error'; -import type { UserLike } from '@/eventbus/event.types'; +import type { UserLike } from '@/events/relay-event-map'; function toRedactable(userLike: UserLike) { return { @@ -14,7 +14,7 @@ function toRedactable(userLike: UserLike) { type FieldName = 'user' | 'inviter' | 'invitee'; /** - * Mark redactable properties in a `{ user: UserLike }` field in an `AuditEventRelay` + * Mark redactable properties in a `{ user: UserLike }` field in an `LogEventRelay` * method arg. These properties will be later redacted by the log streaming * destination based on user prefs. Only for `n8n.audit.*` logs. * diff --git a/packages/cli/src/environments/sourceControl/sourceControl.controller.ee.ts b/packages/cli/src/environments/sourceControl/sourceControl.controller.ee.ts index 0a1db892f60c9..f92b0bfb1f02f 100644 --- a/packages/cli/src/environments/sourceControl/sourceControl.controller.ee.ts +++ b/packages/cli/src/environments/sourceControl/sourceControl.controller.ee.ts @@ -12,7 +12,7 @@ import type { SourceControlPreferences } from './types/sourceControlPreferences' import type { SourceControlledFile } from './types/sourceControlledFile'; import { SOURCE_CONTROL_DEFAULT_BRANCH } from './constants'; import type { ImportResult } from './types/importResult'; -import { EventService } from '@/eventbus/event.service'; +import { EventService } from '@/events/event.service'; import { getRepoType } from './sourceControlHelper.ee'; import { SourceControlGetStatus } from './types/sourceControlGetStatus'; import { BadRequestError } from '@/errors/response-errors/bad-request.error'; diff --git a/packages/cli/src/environments/sourceControl/sourceControl.service.ee.ts b/packages/cli/src/environments/sourceControl/sourceControl.service.ee.ts index ac226a1b2eacc..0c9279ffbe7a3 100644 --- a/packages/cli/src/environments/sourceControl/sourceControl.service.ee.ts +++ b/packages/cli/src/environments/sourceControl/sourceControl.service.ee.ts @@ -30,7 +30,7 @@ import type { TagEntity } from '@db/entities/TagEntity'; import type { Variables } from '@db/entities/Variables'; import type { SourceControlWorkflowVersionId } from './types/sourceControlWorkflowVersionId'; import type { ExportableCredential } from './types/exportableCredential'; -import { EventService } from '@/eventbus/event.service'; +import { EventService } from '@/events/event.service'; import { TagRepository } from '@db/repositories/tag.repository'; import { Logger } from '@/Logger'; import { BadRequestError } from '@/errors/response-errors/bad-request.error'; diff --git a/packages/cli/src/environments/variables/variables.service.ee.ts b/packages/cli/src/environments/variables/variables.service.ee.ts index 94233da065839..78a3d23fbe55d 100644 --- a/packages/cli/src/environments/variables/variables.service.ee.ts +++ b/packages/cli/src/environments/variables/variables.service.ee.ts @@ -6,7 +6,7 @@ import { CacheService } from '@/services/cache/cache.service'; import { VariablesRepository } from '@db/repositories/variables.repository'; import { VariableCountLimitReachedError } from '@/errors/variable-count-limit-reached.error'; import { VariableValidationError } from '@/errors/variable-validation.error'; -import { EventService } from '@/eventbus/event.service'; +import { EventService } from '@/events/event.service'; @Service() export class VariablesService { diff --git a/packages/cli/src/errors/redactable.error.ts b/packages/cli/src/errors/redactable.error.ts index 0f6697a0652d6..4262f12b002f2 100644 --- a/packages/cli/src/errors/redactable.error.ts +++ b/packages/cli/src/errors/redactable.error.ts @@ -3,7 +3,7 @@ import { ApplicationError } from 'n8n-workflow'; export class RedactableError extends ApplicationError { constructor(fieldName: string, args: string) { super( - `Failed to find "${fieldName}" property in argument "${args.toString()}". Please set the decorator \`@Redactable()\` only on \`AuditEventRelay\` methods where the argument contains a "${fieldName}" property.`, + `Failed to find "${fieldName}" property in argument "${args.toString()}". Please set the decorator \`@Redactable()\` only on \`LogEventRelay\` methods where the argument contains a "${fieldName}" property.`, ); } } diff --git a/packages/cli/src/eventbus/event.service.ts b/packages/cli/src/eventbus/event.service.ts deleted file mode 100644 index 2b16ff06ab40c..0000000000000 --- a/packages/cli/src/eventbus/event.service.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { Service } from 'typedi'; -import { TypedEmitter } from '@/TypedEmitter'; -import type { Event } from './event.types'; - -@Service() -export class EventService extends TypedEmitter {} diff --git a/packages/cli/src/eventbus/__tests__/audit-event-relay.service.test.ts b/packages/cli/src/events/__tests__/log-event-relay.test.ts similarity index 91% rename from packages/cli/src/eventbus/__tests__/audit-event-relay.service.test.ts rename to packages/cli/src/events/__tests__/log-event-relay.test.ts index 44277f1de4d0d..c528758de2e3c 100644 --- a/packages/cli/src/eventbus/__tests__/audit-event-relay.service.test.ts +++ b/packages/cli/src/events/__tests__/log-event-relay.test.ts @@ -1,15 +1,15 @@ import { mock } from 'jest-mock-extended'; -import { AuditEventRelay } from '../audit-event-relay.service'; -import type { MessageEventBus } from '../MessageEventBus/MessageEventBus'; -import type { Event } from '../event.types'; -import { EventService } from '../event.service'; +import { LogEventRelay } from '@/events/log-event-relay'; +import { EventService } from '@/events/event.service'; import type { INode, IRun, IWorkflowBase } from 'n8n-workflow'; import type { IWorkflowDb } from '@/Interfaces'; +import type { MessageEventBus } from '@/eventbus/MessageEventBus/MessageEventBus'; +import type { RelayEventMap } from '@/events/relay-event-map'; -describe('AuditEventRelay', () => { +describe('LogEventRelay', () => { const eventBus = mock(); const eventService = new EventService(); - const auditor = new AuditEventRelay(eventService, eventBus); + const auditor = new LogEventRelay(eventService, eventBus); auditor.init(); afterEach(() => { @@ -18,7 +18,7 @@ describe('AuditEventRelay', () => { describe('workflow events', () => { it('should log on `workflow-created` event', () => { - const event: Event['workflow-created'] = { + const event: RelayEventMap['workflow-created'] = { user: { id: '123', email: 'john@n8n.io', @@ -52,7 +52,7 @@ describe('AuditEventRelay', () => { }); it('should log on `workflow-deleted` event', () => { - const event: Event['workflow-deleted'] = { + const event: RelayEventMap['workflow-deleted'] = { user: { id: '456', email: 'jane@n8n.io', @@ -80,7 +80,7 @@ describe('AuditEventRelay', () => { }); it('should log on `workflow-saved` event', () => { - const event: Event['workflow-saved'] = { + const event: RelayEventMap['workflow-saved'] = { user: { id: '789', email: 'alex@n8n.io', @@ -119,7 +119,7 @@ describe('AuditEventRelay', () => { settings: {}, }); - const event: Event['workflow-pre-execute'] = { + const event: RelayEventMap['workflow-pre-execute'] = { executionId: 'exec123', data: workflow, }; @@ -139,7 +139,7 @@ describe('AuditEventRelay', () => { }); it('should log on `workflow-post-execute` for successful execution', () => { - const payload = mock({ + const payload = mock({ executionId: 'some-id', userId: 'some-id', workflow: mock({ id: 'some-id', name: 'some-name' }), @@ -208,7 +208,7 @@ describe('AuditEventRelay', () => { describe('user events', () => { it('should log on `user-updated` event', () => { - const event: Event['user-updated'] = { + const event: RelayEventMap['user-updated'] = { user: { id: 'user456', email: 'updated@example.com', @@ -235,7 +235,7 @@ describe('AuditEventRelay', () => { }); it('should log on `user-deleted` event', () => { - const event: Event['user-deleted'] = { + const event: RelayEventMap['user-deleted'] = { user: { id: '123', email: 'john@n8n.io', @@ -262,7 +262,7 @@ describe('AuditEventRelay', () => { describe('click events', () => { it('should log on `user-password-reset-request-click` event', () => { - const event: Event['user-password-reset-request-click'] = { + const event: RelayEventMap['user-password-reset-request-click'] = { user: { id: 'user101', email: 'user101@example.com', @@ -287,7 +287,7 @@ describe('AuditEventRelay', () => { }); it('should log on `user-invite-email-click` event', () => { - const event: Event['user-invite-email-click'] = { + const event: RelayEventMap['user-invite-email-click'] = { inviter: { id: '123', email: 'john@n8n.io', @@ -354,7 +354,7 @@ describe('AuditEventRelay', () => { settings: {}, }); - const event: Event['node-pre-execute'] = { + const event: RelayEventMap['node-pre-execute'] = { executionId: 'exec456', nodeName: 'HTTP Request', workflow, @@ -399,7 +399,7 @@ describe('AuditEventRelay', () => { settings: {}, }); - const event: Event['node-post-execute'] = { + const event: RelayEventMap['node-post-execute'] = { executionId: 'exec789', nodeName: 'HTTP Response', workflow, @@ -422,7 +422,7 @@ describe('AuditEventRelay', () => { describe('credentials events', () => { it('should log on `credentials-shared` event', () => { - const event: Event['credentials-shared'] = { + const event: RelayEventMap['credentials-shared'] = { user: { id: 'user123', email: 'sharer@example.com', @@ -457,7 +457,7 @@ describe('AuditEventRelay', () => { }); it('should log on `credentials-created` event', () => { - const event: Event['credentials-created'] = { + const event: RelayEventMap['credentials-created'] = { user: { id: 'user123', email: 'user@example.com', @@ -494,7 +494,7 @@ describe('AuditEventRelay', () => { describe('auth events', () => { it('should log on `user-login-failed` event', () => { - const event: Event['user-login-failed'] = { + const event: RelayEventMap['user-login-failed'] = { userEmail: 'user@example.com', authenticationMethod: 'email', reason: 'Invalid password', @@ -515,7 +515,7 @@ describe('AuditEventRelay', () => { describe('community package events', () => { it('should log on `community-package-updated` event', () => { - const event: Event['community-package-updated'] = { + const event: RelayEventMap['community-package-updated'] = { user: { id: 'user202', email: 'packageupdater@example.com', @@ -552,7 +552,7 @@ describe('AuditEventRelay', () => { }); it('should log on `community-package-installed` event', () => { - const event: Event['community-package-installed'] = { + const event: RelayEventMap['community-package-installed'] = { user: { id: 'user789', email: 'admin@example.com', @@ -593,7 +593,7 @@ describe('AuditEventRelay', () => { describe('email events', () => { it('should log on `email-failed` event', () => { - const event: Event['email-failed'] = { + const event: RelayEventMap['email-failed'] = { user: { id: 'user789', email: 'recipient@example.com', @@ -622,7 +622,7 @@ describe('AuditEventRelay', () => { describe('public API events', () => { it('should log on `public-api-key-created` event', () => { - const event: Event['public-api-key-created'] = { + const event: RelayEventMap['public-api-key-created'] = { user: { id: 'user101', email: 'apiuser@example.com', @@ -650,7 +650,7 @@ describe('AuditEventRelay', () => { describe('execution events', () => { it('should log on `execution-throttled` event', () => { - const event: Event['execution-throttled'] = { + const event: RelayEventMap['execution-throttled'] = { executionId: 'exec123456', }; diff --git a/packages/cli/src/events/event-relay.ts b/packages/cli/src/events/event-relay.ts new file mode 100644 index 0000000000000..c67397ec2c636 --- /dev/null +++ b/packages/cli/src/events/event-relay.ts @@ -0,0 +1,22 @@ +import { EventService } from './event.service'; +import { Service } from 'typedi'; +import type { RelayEventMap } from '@/events/relay-event-map'; + +@Service() +export class EventRelay { + constructor(readonly eventService: EventService) {} + + protected setupListeners(map: { + [EventName in EventNames]?: (event: RelayEventMap[EventName]) => void | Promise; + }) { + for (const [eventName, handler] of Object.entries(map) as Array< + [EventNames, ((event: RelayEventMap[EventNames]) => void | Promise) | undefined] + >) { + if (!handler) continue; + + this.eventService.on(eventName, async (event) => { + await handler(event); + }); + } + } +} diff --git a/packages/cli/src/events/event.service.ts b/packages/cli/src/events/event.service.ts new file mode 100644 index 0000000000000..6744103a07799 --- /dev/null +++ b/packages/cli/src/events/event.service.ts @@ -0,0 +1,6 @@ +import { Service } from 'typedi'; +import { TypedEmitter } from '@/TypedEmitter'; +import type { RelayEventMap } from './relay-event-map'; + +@Service() +export class EventService extends TypedEmitter {} diff --git a/packages/cli/src/eventbus/audit-event-relay.service.ts b/packages/cli/src/events/log-event-relay.ts similarity index 53% rename from packages/cli/src/eventbus/audit-event-relay.service.ts rename to packages/cli/src/events/log-event-relay.ts index dcefeac0bd317..21691cbc6265c 100644 --- a/packages/cli/src/eventbus/audit-event-relay.service.ts +++ b/packages/cli/src/events/log-event-relay.ts @@ -1,64 +1,52 @@ import { Service } from 'typedi'; -import { MessageEventBus } from './MessageEventBus/MessageEventBus'; +import { MessageEventBus } from '@/eventbus/MessageEventBus/MessageEventBus'; import { Redactable } from '@/decorators/Redactable'; -import { EventService } from './event.service'; -import type { Event } from './event.types'; +import { EventRelay } from '@/events/event-relay'; +import type { RelayEventMap } from '@/events/relay-event-map'; import type { IWorkflowBase } from 'n8n-workflow'; +import { EventService } from './event.service'; @Service() -export class AuditEventRelay { +export class LogEventRelay extends EventRelay { constructor( - private readonly eventService: EventService, + readonly eventService: EventService, private readonly eventBus: MessageEventBus, - ) {} - - init() { - this.setupHandlers(); + ) { + super(eventService); } - private setupHandlers() { - this.eventService.on('workflow-created', (event) => this.workflowCreated(event)); - this.eventService.on('workflow-deleted', (event) => this.workflowDeleted(event)); - this.eventService.on('workflow-saved', (event) => this.workflowSaved(event)); - this.eventService.on('workflow-pre-execute', (event) => this.workflowPreExecute(event)); - this.eventService.on('workflow-post-execute', (event) => this.workflowPostExecute(event)); - this.eventService.on('node-pre-execute', (event) => this.nodePreExecute(event)); - this.eventService.on('node-post-execute', (event) => this.nodePostExecute(event)); - this.eventService.on('user-deleted', (event) => this.userDeleted(event)); - this.eventService.on('user-invited', (event) => this.userInvited(event)); - this.eventService.on('user-reinvited', (event) => this.userReinvited(event)); - this.eventService.on('user-updated', (event) => this.userUpdated(event)); - this.eventService.on('user-signed-up', (event) => this.userSignedUp(event)); - this.eventService.on('user-logged-in', (event) => this.userLoggedIn(event)); - this.eventService.on('user-login-failed', (event) => this.userLoginFailed(event)); - this.eventService.on('user-invite-email-click', (event) => this.userInviteEmailClick(event)); - this.eventService.on('user-password-reset-email-click', (event) => - this.userPasswordResetEmailClick(event), - ); - this.eventService.on('user-password-reset-request-click', (event) => - this.userPasswordResetRequestClick(event), - ); - this.eventService.on('public-api-key-created', (event) => this.publicApiKeyCreated(event)); - this.eventService.on('public-api-key-deleted', (event) => this.publicApiKeyDeleted(event)); - this.eventService.on('email-failed', (event) => this.emailFailed(event)); - this.eventService.on('credentials-created', (event) => this.credentialsCreated(event)); - this.eventService.on('credentials-deleted', (event) => this.credentialsDeleted(event)); - this.eventService.on('credentials-shared', (event) => this.credentialsShared(event)); - this.eventService.on('credentials-updated', (event) => this.credentialsUpdated(event)); - this.eventService.on('credentials-deleted', (event) => this.credentialsDeleted(event)); - this.eventService.on('community-package-installed', (event) => - this.communityPackageInstalled(event), - ); - this.eventService.on('community-package-updated', (event) => - this.communityPackageUpdated(event), - ); - this.eventService.on('community-package-deleted', (event) => - this.communityPackageDeleted(event), - ); - this.eventService.on('execution-throttled', (event) => this.executionThrottled(event)); - this.eventService.on('execution-started-during-bootup', (event) => - this.executionStartedDuringBootup(event), - ); + init() { + this.setupListeners({ + 'workflow-created': (event) => this.workflowCreated(event), + 'workflow-deleted': (event) => this.workflowDeleted(event), + 'workflow-saved': (event) => this.workflowSaved(event), + 'workflow-pre-execute': (event) => this.workflowPreExecute(event), + 'workflow-post-execute': (event) => this.workflowPostExecute(event), + 'node-pre-execute': (event) => this.nodePreExecute(event), + 'node-post-execute': (event) => this.nodePostExecute(event), + 'user-deleted': (event) => this.userDeleted(event), + 'user-invited': (event) => this.userInvited(event), + 'user-reinvited': (event) => this.userReinvited(event), + 'user-updated': (event) => this.userUpdated(event), + 'user-signed-up': (event) => this.userSignedUp(event), + 'user-logged-in': (event) => this.userLoggedIn(event), + 'user-login-failed': (event) => this.userLoginFailed(event), + 'user-invite-email-click': (event) => this.userInviteEmailClick(event), + 'user-password-reset-email-click': (event) => this.userPasswordResetEmailClick(event), + 'user-password-reset-request-click': (event) => this.userPasswordResetRequestClick(event), + 'public-api-key-created': (event) => this.publicApiKeyCreated(event), + 'public-api-key-deleted': (event) => this.publicApiKeyDeleted(event), + 'email-failed': (event) => this.emailFailed(event), + 'credentials-created': (event) => this.credentialsCreated(event), + 'credentials-deleted': (event) => this.credentialsDeleted(event), + 'credentials-shared': (event) => this.credentialsShared(event), + 'credentials-updated': (event) => this.credentialsUpdated(event), + 'community-package-installed': (event) => this.communityPackageInstalled(event), + 'community-package-updated': (event) => this.communityPackageUpdated(event), + 'community-package-deleted': (event) => this.communityPackageDeleted(event), + 'execution-throttled': (event) => this.executionThrottled(event), + 'execution-started-during-bootup': (event) => this.executionStartedDuringBootup(event), + }); } /** @@ -66,7 +54,7 @@ export class AuditEventRelay { */ @Redactable() - private workflowCreated({ user, workflow }: Event['workflow-created']) { + private workflowCreated({ user, workflow }: RelayEventMap['workflow-created']) { void this.eventBus.sendAuditEvent({ eventName: 'n8n.audit.workflow.created', payload: { @@ -78,7 +66,7 @@ export class AuditEventRelay { } @Redactable() - private workflowDeleted({ user, workflowId }: Event['workflow-deleted']) { + private workflowDeleted({ user, workflowId }: RelayEventMap['workflow-deleted']) { void this.eventBus.sendAuditEvent({ eventName: 'n8n.audit.workflow.deleted', payload: { ...user, workflowId }, @@ -86,7 +74,7 @@ export class AuditEventRelay { } @Redactable() - private workflowSaved({ user, workflow }: Event['workflow-saved']) { + private workflowSaved({ user, workflow }: RelayEventMap['workflow-saved']) { void this.eventBus.sendAuditEvent({ eventName: 'n8n.audit.workflow.updated', payload: { @@ -97,7 +85,7 @@ export class AuditEventRelay { }); } - private workflowPreExecute({ data, executionId }: Event['workflow-pre-execute']) { + private workflowPreExecute({ data, executionId }: RelayEventMap['workflow-pre-execute']) { const payload = 'executionData' in data ? { @@ -121,7 +109,7 @@ export class AuditEventRelay { }); } - private workflowPostExecute(event: Event['workflow-post-execute']) { + private workflowPostExecute(event: RelayEventMap['workflow-post-execute']) { const { runData, workflow, ...rest } = event; const payload = { @@ -159,7 +147,7 @@ export class AuditEventRelay { * Node */ - private nodePreExecute({ workflow, executionId, nodeName }: Event['node-pre-execute']) { + private nodePreExecute({ workflow, executionId, nodeName }: RelayEventMap['node-pre-execute']) { void this.eventBus.sendNodeEvent({ eventName: 'n8n.node.started', payload: { @@ -172,7 +160,7 @@ export class AuditEventRelay { }); } - private nodePostExecute({ workflow, executionId, nodeName }: Event['node-post-execute']) { + private nodePostExecute({ workflow, executionId, nodeName }: RelayEventMap['node-post-execute']) { void this.eventBus.sendNodeEvent({ eventName: 'n8n.node.finished', payload: { @@ -190,7 +178,7 @@ export class AuditEventRelay { */ @Redactable() - private userDeleted({ user }: Event['user-deleted']) { + private userDeleted({ user }: RelayEventMap['user-deleted']) { void this.eventBus.sendAuditEvent({ eventName: 'n8n.audit.user.deleted', payload: user, @@ -198,7 +186,7 @@ export class AuditEventRelay { } @Redactable() - private userInvited({ user, targetUserId }: Event['user-invited']) { + private userInvited({ user, targetUserId }: RelayEventMap['user-invited']) { void this.eventBus.sendAuditEvent({ eventName: 'n8n.audit.user.invited', payload: { ...user, targetUserId }, @@ -206,7 +194,7 @@ export class AuditEventRelay { } @Redactable() - private userReinvited({ user, targetUserId }: Event['user-reinvited']) { + private userReinvited({ user, targetUserId }: RelayEventMap['user-reinvited']) { void this.eventBus.sendAuditEvent({ eventName: 'n8n.audit.user.reinvited', payload: { ...user, targetUserId }, @@ -214,7 +202,7 @@ export class AuditEventRelay { } @Redactable() - private userUpdated({ user, fieldsChanged }: Event['user-updated']) { + private userUpdated({ user, fieldsChanged }: RelayEventMap['user-updated']) { void this.eventBus.sendAuditEvent({ eventName: 'n8n.audit.user.updated', payload: { ...user, fieldsChanged }, @@ -226,7 +214,7 @@ export class AuditEventRelay { */ @Redactable() - private userSignedUp({ user }: Event['user-signed-up']) { + private userSignedUp({ user }: RelayEventMap['user-signed-up']) { void this.eventBus.sendAuditEvent({ eventName: 'n8n.audit.user.signedup', payload: user, @@ -234,7 +222,7 @@ export class AuditEventRelay { } @Redactable() - private userLoggedIn({ user, authenticationMethod }: Event['user-logged-in']) { + private userLoggedIn({ user, authenticationMethod }: RelayEventMap['user-logged-in']) { void this.eventBus.sendAuditEvent({ eventName: 'n8n.audit.user.login.success', payload: { ...user, authenticationMethod }, @@ -242,7 +230,7 @@ export class AuditEventRelay { } private userLoginFailed( - event: Event['user-login-failed'] /* exception: no `UserLike` to redact */, + event: RelayEventMap['user-login-failed'] /* exception: no `UserLike` to redact */, ) { void this.eventBus.sendAuditEvent({ eventName: 'n8n.audit.user.login.failed', @@ -256,7 +244,7 @@ export class AuditEventRelay { @Redactable('inviter') @Redactable('invitee') - private userInviteEmailClick(event: Event['user-invite-email-click']) { + private userInviteEmailClick(event: RelayEventMap['user-invite-email-click']) { void this.eventBus.sendAuditEvent({ eventName: 'n8n.audit.user.invitation.accepted', payload: event, @@ -264,7 +252,7 @@ export class AuditEventRelay { } @Redactable() - private userPasswordResetEmailClick({ user }: Event['user-password-reset-email-click']) { + private userPasswordResetEmailClick({ user }: RelayEventMap['user-password-reset-email-click']) { void this.eventBus.sendAuditEvent({ eventName: 'n8n.audit.user.reset', payload: user, @@ -272,7 +260,9 @@ export class AuditEventRelay { } @Redactable() - private userPasswordResetRequestClick({ user }: Event['user-password-reset-request-click']) { + private userPasswordResetRequestClick({ + user, + }: RelayEventMap['user-password-reset-request-click']) { void this.eventBus.sendAuditEvent({ eventName: 'n8n.audit.user.reset.requested', payload: user, @@ -284,7 +274,7 @@ export class AuditEventRelay { */ @Redactable() - private publicApiKeyCreated({ user }: Event['public-api-key-created']) { + private publicApiKeyCreated({ user }: RelayEventMap['public-api-key-created']) { void this.eventBus.sendAuditEvent({ eventName: 'n8n.audit.user.api.created', payload: user, @@ -292,7 +282,7 @@ export class AuditEventRelay { } @Redactable() - private publicApiKeyDeleted({ user }: Event['public-api-key-deleted']) { + private publicApiKeyDeleted({ user }: RelayEventMap['public-api-key-deleted']) { void this.eventBus.sendAuditEvent({ eventName: 'n8n.audit.user.api.deleted', payload: user, @@ -304,7 +294,7 @@ export class AuditEventRelay { */ @Redactable() - private emailFailed({ user, messageType }: Event['email-failed']) { + private emailFailed({ user, messageType }: RelayEventMap['email-failed']) { void this.eventBus.sendAuditEvent({ eventName: 'n8n.audit.user.email.failed', payload: { ...user, messageType }, @@ -316,7 +306,7 @@ export class AuditEventRelay { */ @Redactable() - private credentialsCreated({ user, ...rest }: Event['credentials-created']) { + private credentialsCreated({ user, ...rest }: RelayEventMap['credentials-created']) { void this.eventBus.sendAuditEvent({ eventName: 'n8n.audit.user.credentials.created', payload: { ...user, ...rest }, @@ -324,7 +314,7 @@ export class AuditEventRelay { } @Redactable() - private credentialsDeleted({ user, ...rest }: Event['credentials-deleted']) { + private credentialsDeleted({ user, ...rest }: RelayEventMap['credentials-deleted']) { void this.eventBus.sendAuditEvent({ eventName: 'n8n.audit.user.credentials.deleted', payload: { ...user, ...rest }, @@ -332,7 +322,7 @@ export class AuditEventRelay { } @Redactable() - private credentialsShared({ user, ...rest }: Event['credentials-shared']) { + private credentialsShared({ user, ...rest }: RelayEventMap['credentials-shared']) { void this.eventBus.sendAuditEvent({ eventName: 'n8n.audit.user.credentials.shared', payload: { ...user, ...rest }, @@ -340,7 +330,7 @@ export class AuditEventRelay { } @Redactable() - private credentialsUpdated({ user, ...rest }: Event['credentials-updated']) { + private credentialsUpdated({ user, ...rest }: RelayEventMap['credentials-updated']) { void this.eventBus.sendAuditEvent({ eventName: 'n8n.audit.user.credentials.updated', payload: { ...user, ...rest }, @@ -352,7 +342,10 @@ export class AuditEventRelay { */ @Redactable() - private communityPackageInstalled({ user, ...rest }: Event['community-package-installed']) { + private communityPackageInstalled({ + user, + ...rest + }: RelayEventMap['community-package-installed']) { void this.eventBus.sendAuditEvent({ eventName: 'n8n.audit.package.installed', payload: { ...user, ...rest }, @@ -360,7 +353,7 @@ export class AuditEventRelay { } @Redactable() - private communityPackageUpdated({ user, ...rest }: Event['community-package-updated']) { + private communityPackageUpdated({ user, ...rest }: RelayEventMap['community-package-updated']) { void this.eventBus.sendAuditEvent({ eventName: 'n8n.audit.package.updated', payload: { ...user, ...rest }, @@ -368,7 +361,7 @@ export class AuditEventRelay { } @Redactable() - private communityPackageDeleted({ user, ...rest }: Event['community-package-deleted']) { + private communityPackageDeleted({ user, ...rest }: RelayEventMap['community-package-deleted']) { void this.eventBus.sendAuditEvent({ eventName: 'n8n.audit.package.deleted', payload: { ...user, ...rest }, @@ -379,14 +372,16 @@ export class AuditEventRelay { * Execution */ - private executionThrottled({ executionId }: Event['execution-throttled']) { + private executionThrottled({ executionId }: RelayEventMap['execution-throttled']) { void this.eventBus.sendExecutionEvent({ eventName: 'n8n.execution.throttled', payload: { executionId }, }); } - private executionStartedDuringBootup({ executionId }: Event['execution-started-during-bootup']) { + private executionStartedDuringBootup({ + executionId, + }: RelayEventMap['execution-started-during-bootup']) { void this.eventBus.sendExecutionEvent({ eventName: 'n8n.execution.started-during-bootup', payload: { executionId }, diff --git a/packages/cli/src/eventbus/event.types.ts b/packages/cli/src/events/relay-event-map.ts similarity index 92% rename from packages/cli/src/eventbus/event.types.ts rename to packages/cli/src/events/relay-event-map.ts index bcca98b919637..fb7c3c9c1e65d 100644 --- a/packages/cli/src/eventbus/event.types.ts +++ b/packages/cli/src/events/relay-event-map.ts @@ -11,12 +11,13 @@ export type UserLike = { role: string; }; -/** - * Events sent by `EventService` and forwarded by relays, e.g. `AuditEventRelay` and `TelemetryEventRelay`. - */ -export type Event = { +export type RelayEventMap = { 'server-started': {}; + /** + * Workflow + */ + 'workflow-created': { user: UserLike; workflow: IWorkflowBase; @@ -49,6 +50,10 @@ export type Event = { runData?: IRun; }; + /** + * Node + */ + 'node-pre-execute': { executionId: string; workflow: IWorkflowBase; @@ -61,6 +66,10 @@ export type Event = { nodeName: string; }; + /** + * User + */ + 'user-deleted': { user: UserLike; }; @@ -95,6 +104,10 @@ export type Event = { reason?: string; }; + /** + * Click + */ + 'user-invite-email-click': { inviter: UserLike; invitee: UserLike; @@ -108,6 +121,20 @@ export type Event = { user: UserLike; }; + /** + * Public API + */ + + 'public-api-key-created': { + user: UserLike; + publicApi: boolean; + }; + + 'public-api-key-deleted': { + user: UserLike; + publicApi: boolean; + }; + 'public-api-invoked': { userId: string; path: string; @@ -115,6 +142,10 @@ export type Event = { apiVersion: string; }; + /** + * Email + */ + 'email-failed': { user: UserLike; messageType: @@ -125,6 +156,10 @@ export type Event = { | 'Credentials shared'; }; + /** + * Credentials + */ + 'credentials-created': { user: UserLike; credentialType: string; @@ -155,6 +190,10 @@ export type Event = { credentialId: string; }; + /** + * Community package + */ + 'community-package-installed': { user: UserLike; inputString: string; @@ -186,6 +225,10 @@ export type Event = { packageAuthorEmail?: string; }; + /** + * Execution + */ + 'execution-throttled': { executionId: string; }; @@ -194,6 +237,10 @@ export type Event = { executionId: string; }; + /** + * Project + */ + 'team-project-updated': { userId: string; role: GlobalRole; @@ -217,6 +264,10 @@ export type Event = { role: GlobalRole; }; + /** + * Source control + */ + 'source-control-settings-updated': { branchName: string; readOnlyInstance: boolean; @@ -254,12 +305,24 @@ export type Event = { variablesPushed: number; }; + /** + * License + */ + 'license-renewal-attempted': { success: boolean; }; + /** + * Variable + */ + 'variable-created': {}; + /** + * External secrets + */ + 'external-secrets-provider-settings-saved': { userId?: string; vaultType: string; @@ -268,6 +331,10 @@ export type Event = { errorMessage?: string; }; + /** + * LDAP + */ + 'ldap-general-sync-finished': { type: string; succeeded: boolean; @@ -297,18 +364,4 @@ export type Event = { 'login-failed-due-to-ldap-disabled': { userId: string; }; - - /** - * Events listened to by more than one relay - */ - - 'public-api-key-created': { - user: UserLike; // audit and telemetry - publicApi: boolean; // telemetry only - }; - - 'public-api-key-deleted': { - user: UserLike; // audit and telemetry - publicApi: boolean; // telemetry only - }; }; diff --git a/packages/cli/src/telemetry/telemetry-event-relay.service.ts b/packages/cli/src/events/telemetry-event-relay.ts similarity index 75% rename from packages/cli/src/telemetry/telemetry-event-relay.service.ts rename to packages/cli/src/events/telemetry-event-relay.ts index f92b38987b1e3..19338470ea27b 100644 --- a/packages/cli/src/telemetry/telemetry-event-relay.service.ts +++ b/packages/cli/src/events/telemetry-event-relay.ts @@ -1,7 +1,7 @@ import { Service } from 'typedi'; -import { EventService } from '@/eventbus/event.service'; -import type { Event } from '@/eventbus/event.types'; -import { Telemetry } from '.'; +import { EventService } from '@/events/event.service'; +import type { RelayEventMap } from '@/events/relay-event-map'; +import { Telemetry } from '../telemetry'; import config from '@/config'; import os from 'node:os'; import { License } from '@/License'; @@ -16,11 +16,12 @@ import { SharedWorkflowRepository } from '@/databases/repositories/sharedWorkflo import { ProjectRelationRepository } from '@/databases/repositories/projectRelation.repository'; import type { IExecutionTrackProperties } from '@/Interfaces'; import { determineFinalExecutionStatus } from '@/executionLifecycleHooks/shared/sharedHookFunctions'; +import { EventRelay } from './event-relay'; @Service() -export class TelemetryEventRelay { +export class TelemetryEventRelay extends EventRelay { constructor( - private readonly eventService: EventService, + readonly eventService: EventService, private readonly telemetry: Telemetry, private readonly license: License, private readonly globalConfig: GlobalConfig, @@ -28,106 +29,59 @@ export class TelemetryEventRelay { private readonly nodeTypes: NodeTypes, private readonly sharedWorkflowRepository: SharedWorkflowRepository, private readonly projectRelationRepository: ProjectRelationRepository, - ) {} + ) { + super(eventService); + } async init() { if (!config.getEnv('diagnostics.enabled')) return; await this.telemetry.init(); - this.setupHandlers(); - } - - private setupHandlers() { - this.eventService.on('server-started', async () => await this.serverStarted()); - - this.eventService.on('team-project-updated', (event) => this.teamProjectUpdated(event)); - this.eventService.on('team-project-deleted', (event) => this.teamProjectDeleted(event)); - this.eventService.on('team-project-created', (event) => this.teamProjectCreated(event)); - this.eventService.on('source-control-settings-updated', (event) => - this.sourceControlSettingsUpdated(event), - ); - this.eventService.on('source-control-user-started-pull-ui', (event) => - this.sourceControlUserStartedPullUi(event), - ); - this.eventService.on('source-control-user-finished-pull-ui', (event) => - this.sourceControlUserFinishedPullUi(event), - ); - this.eventService.on('source-control-user-pulled-api', (event) => - this.sourceControlUserPulledApi(event), - ); - this.eventService.on('source-control-user-started-push-ui', (event) => - this.sourceControlUserStartedPushUi(event), - ); - this.eventService.on('source-control-user-finished-push-ui', (event) => - this.sourceControlUserFinishedPushUi(event), - ); - this.eventService.on('license-renewal-attempted', (event) => { - this.licenseRenewalAttempted(event); - }); - this.eventService.on('variable-created', () => this.variableCreated()); - this.eventService.on('external-secrets-provider-settings-saved', (event) => { - this.externalSecretsProviderSettingsSaved(event); - }); - this.eventService.on('public-api-invoked', (event) => { - this.publicApiInvoked(event); - }); - this.eventService.on('public-api-key-created', (event) => { - this.publicApiKeyCreated(event); - }); - this.eventService.on('public-api-key-deleted', (event) => { - this.publicApiKeyDeleted(event); - }); - this.eventService.on('community-package-installed', (event) => { - this.communityPackageInstalled(event); - }); - this.eventService.on('community-package-updated', (event) => { - this.communityPackageUpdated(event); - }); - this.eventService.on('community-package-deleted', (event) => { - this.communityPackageDeleted(event); - }); - - this.eventService.on('credentials-created', (event) => { - this.credentialsCreated(event); - }); - this.eventService.on('credentials-shared', (event) => { - this.credentialsShared(event); - }); - this.eventService.on('credentials-updated', (event) => { - this.credentialsUpdated(event); - }); - this.eventService.on('credentials-deleted', (event) => { - this.credentialsDeleted(event); - }); - this.eventService.on('ldap-general-sync-finished', (event) => { - this.ldapGeneralSyncFinished(event); - }); - this.eventService.on('ldap-settings-updated', (event) => { - this.ldapSettingsUpdated(event); - }); - this.eventService.on('ldap-login-sync-failed', (event) => { - this.ldapLoginSyncFailed(event); - }); - this.eventService.on('login-failed-due-to-ldap-disabled', (event) => { - this.loginFailedDueToLdapDisabled(event); - }); - - this.eventService.on('workflow-created', (event) => { - this.workflowCreated(event); - }); - this.eventService.on('workflow-deleted', (event) => { - this.workflowDeleted(event); - }); - this.eventService.on('workflow-saved', async (event) => { - await this.workflowSaved(event); - }); - this.eventService.on('workflow-post-execute', async (event) => { - await this.workflowPostExecute(event); - }); - } - - private teamProjectUpdated({ userId, role, members, projectId }: Event['team-project-updated']) { + this.setupListeners({ + 'team-project-updated': (event) => this.teamProjectUpdated(event), + 'team-project-deleted': (event) => this.teamProjectDeleted(event), + 'team-project-created': (event) => this.teamProjectCreated(event), + 'source-control-settings-updated': (event) => this.sourceControlSettingsUpdated(event), + 'source-control-user-started-pull-ui': (event) => this.sourceControlUserStartedPullUi(event), + 'source-control-user-finished-pull-ui': (event) => + this.sourceControlUserFinishedPullUi(event), + 'source-control-user-pulled-api': (event) => this.sourceControlUserPulledApi(event), + 'source-control-user-started-push-ui': (event) => this.sourceControlUserStartedPushUi(event), + 'source-control-user-finished-push-ui': (event) => + this.sourceControlUserFinishedPushUi(event), + 'license-renewal-attempted': (event) => this.licenseRenewalAttempted(event), + 'variable-created': () => this.variableCreated(), + 'external-secrets-provider-settings-saved': (event) => + this.externalSecretsProviderSettingsSaved(event), + 'public-api-invoked': (event) => this.publicApiInvoked(event), + 'public-api-key-created': (event) => this.publicApiKeyCreated(event), + 'public-api-key-deleted': (event) => this.publicApiKeyDeleted(event), + 'community-package-installed': (event) => this.communityPackageInstalled(event), + 'community-package-updated': (event) => this.communityPackageUpdated(event), + 'community-package-deleted': (event) => this.communityPackageDeleted(event), + 'credentials-created': (event) => this.credentialsCreated(event), + 'credentials-shared': (event) => this.credentialsShared(event), + 'credentials-updated': (event) => this.credentialsUpdated(event), + 'credentials-deleted': (event) => this.credentialsDeleted(event), + 'ldap-general-sync-finished': (event) => this.ldapGeneralSyncFinished(event), + 'ldap-settings-updated': (event) => this.ldapSettingsUpdated(event), + 'ldap-login-sync-failed': (event) => this.ldapLoginSyncFailed(event), + 'login-failed-due-to-ldap-disabled': (event) => this.loginFailedDueToLdapDisabled(event), + 'workflow-created': (event) => this.workflowCreated(event), + 'workflow-deleted': (event) => this.workflowDeleted(event), + 'workflow-saved': async (event) => await this.workflowSaved(event), + 'server-started': async () => await this.serverStarted(), + 'workflow-post-execute': async (event) => await this.workflowPostExecute(event), + }); + } + + private teamProjectUpdated({ + userId, + role, + members, + projectId, + }: RelayEventMap['team-project-updated']) { this.telemetry.track('Project settings updated', { user_id: userId, role, @@ -143,7 +97,7 @@ export class TelemetryEventRelay { projectId, removalType, targetProjectId, - }: Event['team-project-deleted']) { + }: RelayEventMap['team-project-deleted']) { this.telemetry.track('User deleted project', { user_id: userId, role, @@ -153,7 +107,7 @@ export class TelemetryEventRelay { }); } - private teamProjectCreated({ userId, role }: Event['team-project-created']) { + private teamProjectCreated({ userId, role }: RelayEventMap['team-project-created']) { this.telemetry.track('User created project', { user_id: userId, role, @@ -165,7 +119,7 @@ export class TelemetryEventRelay { readOnlyInstance, repoType, connected, - }: Event['source-control-settings-updated']) { + }: RelayEventMap['source-control-settings-updated']) { this.telemetry.track('User updated source control settings', { branch_name: branchName, read_only_instance: readOnlyInstance, @@ -178,7 +132,7 @@ export class TelemetryEventRelay { workflowUpdates, workflowConflicts, credConflicts, - }: Event['source-control-user-started-pull-ui']) { + }: RelayEventMap['source-control-user-started-pull-ui']) { this.telemetry.track('User started pull via UI', { workflow_updates: workflowUpdates, workflow_conflicts: workflowConflicts, @@ -188,7 +142,7 @@ export class TelemetryEventRelay { private sourceControlUserFinishedPullUi({ workflowUpdates, - }: Event['source-control-user-finished-pull-ui']) { + }: RelayEventMap['source-control-user-finished-pull-ui']) { this.telemetry.track('User finished pull via UI', { workflow_updates: workflowUpdates, }); @@ -197,7 +151,7 @@ export class TelemetryEventRelay { private sourceControlUserPulledApi({ workflowUpdates, forced, - }: Event['source-control-user-pulled-api']) { + }: RelayEventMap['source-control-user-pulled-api']) { console.log('source-control-user-pulled-api', { workflow_updates: workflowUpdates, forced, @@ -214,7 +168,7 @@ export class TelemetryEventRelay { credsEligible, credsEligibleWithConflicts, variablesEligible, - }: Event['source-control-user-started-push-ui']) { + }: RelayEventMap['source-control-user-started-push-ui']) { this.telemetry.track('User started push via UI', { workflows_eligible: workflowsEligible, workflows_eligible_with_conflicts: workflowsEligibleWithConflicts, @@ -229,7 +183,7 @@ export class TelemetryEventRelay { workflowsPushed, credsPushed, variablesPushed, - }: Event['source-control-user-finished-push-ui']) { + }: RelayEventMap['source-control-user-finished-push-ui']) { this.telemetry.track('User finished push via UI', { workflows_eligible: workflowsEligible, workflows_pushed: workflowsPushed, @@ -238,7 +192,7 @@ export class TelemetryEventRelay { }); } - private licenseRenewalAttempted({ success }: Event['license-renewal-attempted']) { + private licenseRenewalAttempted({ success }: RelayEventMap['license-renewal-attempted']) { this.telemetry.track('Instance attempted to refresh license', { success, }); @@ -254,7 +208,7 @@ export class TelemetryEventRelay { isValid, isNew, errorMessage, - }: Event['external-secrets-provider-settings-saved']) { + }: RelayEventMap['external-secrets-provider-settings-saved']) { this.telemetry.track('User updated external secrets settings', { user_id: userId, vault_type: vaultType, @@ -264,7 +218,12 @@ export class TelemetryEventRelay { }); } - private publicApiInvoked({ userId, path, method, apiVersion }: Event['public-api-invoked']) { + private publicApiInvoked({ + userId, + path, + method, + apiVersion, + }: RelayEventMap['public-api-invoked']) { this.telemetry.track('User invoked API', { user_id: userId, path, @@ -273,7 +232,7 @@ export class TelemetryEventRelay { }); } - private publicApiKeyCreated(event: Event['public-api-key-created']) { + private publicApiKeyCreated(event: RelayEventMap['public-api-key-created']) { const { user, publicApi } = event; this.telemetry.track('API key created', { @@ -282,7 +241,7 @@ export class TelemetryEventRelay { }); } - private publicApiKeyDeleted(event: Event['public-api-key-deleted']) { + private publicApiKeyDeleted(event: RelayEventMap['public-api-key-deleted']) { const { user, publicApi } = event; this.telemetry.track('API key deleted', { @@ -301,7 +260,7 @@ export class TelemetryEventRelay { packageAuthor, packageAuthorEmail, failureReason, - }: Event['community-package-installed']) { + }: RelayEventMap['community-package-installed']) { this.telemetry.track('cnr package install finished', { user_id: user.id, input_string: inputString, @@ -323,7 +282,7 @@ export class TelemetryEventRelay { packageNodeNames, packageAuthor, packageAuthorEmail, - }: Event['community-package-updated']) { + }: RelayEventMap['community-package-updated']) { this.telemetry.track('cnr package updated', { user_id: user.id, package_name: packageName, @@ -342,7 +301,7 @@ export class TelemetryEventRelay { packageNodeNames, packageAuthor, packageAuthorEmail, - }: Event['community-package-deleted']) { + }: RelayEventMap['community-package-deleted']) { this.telemetry.track('cnr package deleted', { user_id: user.id, package_name: packageName, @@ -359,7 +318,7 @@ export class TelemetryEventRelay { credentialId, projectId, projectType, - }: Event['credentials-created']) { + }: RelayEventMap['credentials-created']) { this.telemetry.track('User created credentials', { user_id: user.id, credential_type: credentialType, @@ -376,7 +335,7 @@ export class TelemetryEventRelay { userIdSharer, userIdsShareesAdded, shareesRemoved, - }: Event['credentials-shared']) { + }: RelayEventMap['credentials-shared']) { this.telemetry.track('User updated cred sharing', { user_id: user.id, credential_type: credentialType, @@ -387,7 +346,11 @@ export class TelemetryEventRelay { }); } - private credentialsUpdated({ user, credentialId, credentialType }: Event['credentials-updated']) { + private credentialsUpdated({ + user, + credentialId, + credentialType, + }: RelayEventMap['credentials-updated']) { this.telemetry.track('User updated credentials', { user_id: user.id, credential_type: credentialType, @@ -395,7 +358,11 @@ export class TelemetryEventRelay { }); } - private credentialsDeleted({ user, credentialId, credentialType }: Event['credentials-deleted']) { + private credentialsDeleted({ + user, + credentialId, + credentialType, + }: RelayEventMap['credentials-deleted']) { this.telemetry.track('User deleted credentials', { user_id: user.id, credential_type: credentialType, @@ -408,7 +375,7 @@ export class TelemetryEventRelay { succeeded, usersSynced, error, - }: Event['ldap-general-sync-finished']) { + }: RelayEventMap['ldap-general-sync-finished']) { this.telemetry.track('Ldap general sync finished', { type, succeeded, @@ -430,7 +397,7 @@ export class TelemetryEventRelay { synchronizationInterval, loginLabel, loginEnabled, - }: Event['ldap-settings-updated']) { + }: RelayEventMap['ldap-settings-updated']) { this.telemetry.track('User updated Ldap settings', { user_id: userId, loginIdAttribute, @@ -447,11 +414,13 @@ export class TelemetryEventRelay { }); } - private ldapLoginSyncFailed({ error }: Event['ldap-login-sync-failed']) { + private ldapLoginSyncFailed({ error }: RelayEventMap['ldap-login-sync-failed']) { this.telemetry.track('Ldap login sync failed', { error }); } - private loginFailedDueToLdapDisabled({ userId }: Event['login-failed-due-to-ldap-disabled']) { + private loginFailedDueToLdapDisabled({ + userId, + }: RelayEventMap['login-failed-due-to-ldap-disabled']) { this.telemetry.track('User login failed since ldap disabled', { user_ud: userId }); } @@ -461,7 +430,7 @@ export class TelemetryEventRelay { publicApi, projectId, projectType, - }: Event['workflow-created']) { + }: RelayEventMap['workflow-created']) { const { nodeGraph } = TelemetryHelpers.generateNodesGraph(workflow, this.nodeTypes); this.telemetry.track('User created workflow', { @@ -474,7 +443,7 @@ export class TelemetryEventRelay { }); } - private workflowDeleted({ user, workflowId, publicApi }: Event['workflow-deleted']) { + private workflowDeleted({ user, workflowId, publicApi }: RelayEventMap['workflow-deleted']) { this.telemetry.track('User deleted workflow', { user_id: user.id, workflow_id: workflowId, @@ -482,7 +451,7 @@ export class TelemetryEventRelay { }); } - private async workflowSaved({ user, workflow, publicApi }: Event['workflow-saved']) { + private async workflowSaved({ user, workflow, publicApi }: RelayEventMap['workflow-saved']) { const isCloudDeployment = config.getEnv('deployment.type') === 'cloud'; const { nodeGraph } = TelemetryHelpers.generateNodesGraph(workflow, this.nodeTypes, { @@ -593,7 +562,11 @@ export class TelemetryEventRelay { } // eslint-disable-next-line complexity - private async workflowPostExecute({ workflow, runData, userId }: Event['workflow-post-execute']) { + private async workflowPostExecute({ + workflow, + runData, + userId, + }: RelayEventMap['workflow-post-execute']) { if (!workflow.id) { return; } diff --git a/packages/cli/src/executions/__tests__/execution-recovery.service.test.ts b/packages/cli/src/executions/__tests__/execution-recovery.service.test.ts index 7e33c6ac74a8a..81112cf0d1c6a 100644 --- a/packages/cli/src/executions/__tests__/execution-recovery.service.test.ts +++ b/packages/cli/src/executions/__tests__/execution-recovery.service.test.ts @@ -21,7 +21,7 @@ import { EventMessageNode } from '@/eventbus/EventMessageClasses/EventMessageNod import { IN_PROGRESS_EXECUTION_DATA, OOM_WORKFLOW } from './constants'; import { setupMessages } from './utils'; -import type { EventService } from '@/eventbus/event.service'; +import type { EventService } from '@/events/event.service'; import type { EventMessageTypes as EventMessage } from '@/eventbus/EventMessageClasses'; import type { Logger } from '@/Logger'; diff --git a/packages/cli/src/executions/execution-recovery.service.ts b/packages/cli/src/executions/execution-recovery.service.ts index 615c65ea6ef5f..b366bab44a2e0 100644 --- a/packages/cli/src/executions/execution-recovery.service.ts +++ b/packages/cli/src/executions/execution-recovery.service.ts @@ -15,7 +15,7 @@ import config from '@/config'; import { OnShutdown } from '@/decorators/OnShutdown'; import type { QueueRecoverySettings } from './execution.types'; import { OrchestrationService } from '@/services/orchestration.service'; -import { EventService } from '@/eventbus/event.service'; +import { EventService } from '@/events/event.service'; /** * Service for recovering key properties in executions. diff --git a/packages/cli/src/license/license.service.ts b/packages/cli/src/license/license.service.ts index 01d2a73c48941..0555597a9d3b3 100644 --- a/packages/cli/src/license/license.service.ts +++ b/packages/cli/src/license/license.service.ts @@ -3,7 +3,7 @@ import axios from 'axios'; import { Logger } from '@/Logger'; import { License } from '@/License'; -import { EventService } from '@/eventbus/event.service'; +import { EventService } from '@/events/event.service'; import type { User } from '@db/entities/User'; import { WorkflowRepository } from '@db/repositories/workflow.repository'; import { BadRequestError } from '@/errors/response-errors/bad-request.error'; diff --git a/packages/cli/src/services/user.service.ts b/packages/cli/src/services/user.service.ts index 007054c6aa980..25be080ca05bf 100644 --- a/packages/cli/src/services/user.service.ts +++ b/packages/cli/src/services/user.service.ts @@ -12,7 +12,7 @@ import { InternalHooks } from '@/InternalHooks'; import { UrlService } from '@/services/url.service'; import type { UserRequest } from '@/requests'; import { InternalServerError } from '@/errors/response-errors/internal-server.error'; -import { EventService } from '@/eventbus/event.service'; +import { EventService } from '@/events/event.service'; @Service() export class UserService { diff --git a/packages/cli/src/sso/saml/routes/saml.controller.ee.ts b/packages/cli/src/sso/saml/routes/saml.controller.ee.ts index 344bd34e92b72..8169ee317bfee 100644 --- a/packages/cli/src/sso/saml/routes/saml.controller.ee.ts +++ b/packages/cli/src/sso/saml/routes/saml.controller.ee.ts @@ -27,7 +27,7 @@ import { import { SamlService } from '../saml.service.ee'; import { SamlConfiguration } from '../types/requests'; import { getInitSSOFormView } from '../views/initSsoPost'; -import { EventService } from '@/eventbus/event.service'; +import { EventService } from '@/events/event.service'; @RestController('/sso/saml') export class SamlController { diff --git a/packages/cli/src/workflows/workflow.service.ts b/packages/cli/src/workflows/workflow.service.ts index 4f59f8238fe68..20917e60cbc16 100644 --- a/packages/cli/src/workflows/workflow.service.ts +++ b/packages/cli/src/workflows/workflow.service.ts @@ -33,7 +33,7 @@ import type { EntityManager } from '@n8n/typeorm'; // eslint-disable-next-line n8n-local-rules/misplaced-n8n-typeorm-import import { In } from '@n8n/typeorm'; import { SharedWorkflow } from '@/databases/entities/SharedWorkflow'; -import { EventService } from '@/eventbus/event.service'; +import { EventService } from '@/events/event.service'; @Service() export class WorkflowService { diff --git a/packages/cli/src/workflows/workflows.controller.ts b/packages/cli/src/workflows/workflows.controller.ts index c774b21917c98..60dbbf8191c4f 100644 --- a/packages/cli/src/workflows/workflows.controller.ts +++ b/packages/cli/src/workflows/workflows.controller.ts @@ -42,7 +42,7 @@ import { In, type FindOptionsRelations } from '@n8n/typeorm'; import type { Project } from '@/databases/entities/Project'; import { ProjectRelationRepository } from '@/databases/repositories/projectRelation.repository'; import { z } from 'zod'; -import { EventService } from '@/eventbus/event.service'; +import { EventService } from '@/events/event.service'; import { GlobalConfig } from '@n8n/config'; @RestController('/workflows') diff --git a/packages/cli/test/integration/ExternalSecrets/externalSecrets.api.test.ts b/packages/cli/test/integration/ExternalSecrets/externalSecrets.api.test.ts index 7a49e61fa1b01..190ab437fa5f6 100644 --- a/packages/cli/test/integration/ExternalSecrets/externalSecrets.api.test.ts +++ b/packages/cli/test/integration/ExternalSecrets/externalSecrets.api.test.ts @@ -21,7 +21,7 @@ import { TestFailProvider, } from '../../shared/ExternalSecrets/utils'; import type { SuperAgentTest } from '../shared/types'; -import type { EventService } from '@/eventbus/event.service'; +import type { EventService } from '@/events/event.service'; let authOwnerAgent: SuperAgentTest; let authMemberAgent: SuperAgentTest; diff --git a/packages/cli/test/integration/commands/worker.cmd.test.ts b/packages/cli/test/integration/commands/worker.cmd.test.ts index 0ffad7bc056ec..bd84d48b7f039 100644 --- a/packages/cli/test/integration/commands/worker.cmd.test.ts +++ b/packages/cli/test/integration/commands/worker.cmd.test.ts @@ -15,7 +15,7 @@ import { type JobQueue, Queue } from '@/Queue'; import { setupTestCommand } from '@test-integration/utils/testCommand'; import { mockInstance } from '../../shared/mocking'; -import { AuditEventRelay } from '@/eventbus/audit-event-relay.service'; +import { LogEventRelay } from '@/events/log-event-relay'; config.set('executions.mode', 'queue'); config.set('binaryDataManager.availableModes', 'filesystem'); @@ -26,7 +26,7 @@ const externalHooks = mockInstance(ExternalHooks); const externalSecretsManager = mockInstance(ExternalSecretsManager); const license = mockInstance(License); const messageEventBus = mockInstance(MessageEventBus); -const auditEventRelay = mockInstance(AuditEventRelay); +const logEventRelay = mockInstance(LogEventRelay); const orchestrationHandlerWorkerService = mockInstance(OrchestrationHandlerWorkerService); const queue = mockInstance(Queue); const orchestrationWorkerService = mockInstance(OrchestrationWorkerService); @@ -45,7 +45,7 @@ test('worker initializes all its components', async () => { expect(externalHooks.init).toHaveBeenCalledTimes(1); expect(externalSecretsManager.init).toHaveBeenCalledTimes(1); expect(messageEventBus.initialize).toHaveBeenCalledTimes(1); - expect(auditEventRelay.init).toHaveBeenCalledTimes(1); + expect(logEventRelay.init).toHaveBeenCalledTimes(1); expect(queue.init).toHaveBeenCalledTimes(1); expect(queue.process).toHaveBeenCalledTimes(1); expect(orchestrationWorkerService.init).toHaveBeenCalledTimes(1); diff --git a/packages/cli/test/unit/license/license.service.test.ts b/packages/cli/test/unit/license/license.service.test.ts index e28895025ffbe..fb75c6a27d692 100644 --- a/packages/cli/test/unit/license/license.service.test.ts +++ b/packages/cli/test/unit/license/license.service.test.ts @@ -1,6 +1,6 @@ import { LicenseErrors, LicenseService } from '@/license/license.service'; import type { License } from '@/License'; -import type { EventService } from '@/eventbus/event.service'; +import type { EventService } from '@/events/event.service'; import type { WorkflowRepository } from '@db/repositories/workflow.repository'; import type { TEntitlement } from '@n8n_io/license-sdk'; import { mock } from 'jest-mock-extended'; From a7cc35ff79bb75f04a820d6b687ca3b9850f16e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Fri, 2 Aug 2024 13:18:29 +0200 Subject: [PATCH 2/7] Fix import --- packages/cli/test/integration/shared/utils/testCommand.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/test/integration/shared/utils/testCommand.ts b/packages/cli/test/integration/shared/utils/testCommand.ts index 7a8477c4dd1b8..2d25d837cc928 100644 --- a/packages/cli/test/integration/shared/utils/testCommand.ts +++ b/packages/cli/test/integration/shared/utils/testCommand.ts @@ -4,7 +4,7 @@ import { mock } from 'jest-mock-extended'; import type { BaseCommand } from '@/commands/BaseCommand'; import * as testDb from '../testDb'; -import { TelemetryEventRelay } from '@/telemetry/telemetry-event-relay.service'; +import { TelemetryEventRelay } from '@/events/telemetry-event-relay'; import { mockInstance } from '@test/mocking'; export const setupTestCommand = (Command: Class) => { From f3fd9374fc34b090274f51803c6d505e6f17cb22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Fri, 2 Aug 2024 13:34:23 +0200 Subject: [PATCH 3/7] Missed spot --- packages/cli/src/events/__tests__/log-event-relay.test.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/cli/src/events/__tests__/log-event-relay.test.ts b/packages/cli/src/events/__tests__/log-event-relay.test.ts index c528758de2e3c..70d4df572be00 100644 --- a/packages/cli/src/events/__tests__/log-event-relay.test.ts +++ b/packages/cli/src/events/__tests__/log-event-relay.test.ts @@ -9,8 +9,7 @@ import type { RelayEventMap } from '@/events/relay-event-map'; describe('LogEventRelay', () => { const eventBus = mock(); const eventService = new EventService(); - const auditor = new LogEventRelay(eventService, eventBus); - auditor.init(); + new LogEventRelay(eventService, eventBus).init(); afterEach(() => { jest.clearAllMocks(); From dd2df991dab2c59605ee2973f4d54f2e00073c1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Fri, 2 Aug 2024 15:10:47 +0200 Subject: [PATCH 4/7] Better name --- packages/cli/src/InternalHooks.ts | 2 +- packages/cli/src/Server.ts | 4 ++-- packages/cli/src/commands/worker.ts | 4 ++-- packages/cli/src/decorators/Redactable.ts | 2 +- packages/cli/src/errors/redactable.error.ts | 2 +- ...vent-relay.test.ts => log-streaming-event-relay.test.ts} | 6 +++--- .../{log-event-relay.ts => log-streaming-event-relay.ts} | 2 +- packages/cli/test/integration/commands/worker.cmd.test.ts | 6 +++--- 8 files changed, 14 insertions(+), 14 deletions(-) rename packages/cli/src/events/__tests__/{log-event-relay.test.ts => log-streaming-event-relay.test.ts} (98%) rename packages/cli/src/events/{log-event-relay.ts => log-streaming-event-relay.ts} (99%) diff --git a/packages/cli/src/InternalHooks.ts b/packages/cli/src/InternalHooks.ts index 0c3c670373284..d9f1e6f4fc8f8 100644 --- a/packages/cli/src/InternalHooks.ts +++ b/packages/cli/src/InternalHooks.ts @@ -10,7 +10,7 @@ import { MessageEventBus } from './eventbus/MessageEventBus/MessageEventBus'; /** * @deprecated Do not add to this class. To add log or telemetry events, use - * `EventService` to emit the event and then use the `LogEventRelay` or + * `EventService` to emit the event and then use the `LogStreamingEventRelay` or * `TelemetryEventRelay` to forward them to the event bus or telemetry. */ @Service() diff --git a/packages/cli/src/Server.ts b/packages/cli/src/Server.ts index 0fad10235e572..0eb2040e7f1bb 100644 --- a/packages/cli/src/Server.ts +++ b/packages/cli/src/Server.ts @@ -35,7 +35,7 @@ import { MessageEventBus } from '@/eventbus/MessageEventBus/MessageEventBus'; import { handleMfaDisable, isMfaFeatureEnabled } from '@/Mfa/helpers'; import type { FrontendService } from '@/services/frontend.service'; import { OrchestrationService } from '@/services/orchestration.service'; -import { LogEventRelay } from '@/events/log-event-relay'; +import { LogStreamingEventRelay } from '@/events/log-streaming-event-relay'; import '@/controllers/activeWorkflows.controller'; import '@/controllers/auth.controller'; @@ -250,7 +250,7 @@ export class Server extends AbstractServer { // ---------------------------------------- const eventBus = Container.get(MessageEventBus); await eventBus.initialize(); - Container.get(LogEventRelay).init(); + Container.get(LogStreamingEventRelay).init(); if (this.endpointPresetCredentials !== '') { // POST endpoint to set preset credentials diff --git a/packages/cli/src/commands/worker.ts b/packages/cli/src/commands/worker.ts index 9029f6b86e432..cf4c23a0859a7 100644 --- a/packages/cli/src/commands/worker.ts +++ b/packages/cli/src/commands/worker.ts @@ -30,7 +30,7 @@ import type { WorkerJobStatusSummary } from '@/services/orchestration/worker/typ import { ServiceUnavailableError } from '@/errors/response-errors/service-unavailable.error'; import { BaseCommand } from './BaseCommand'; import { MaxStalledCountError } from '@/errors/max-stalled-count.error'; -import { LogEventRelay } from '@/events/log-event-relay'; +import { LogStreamingEventRelay } from '@/events/log-streaming-event-relay'; export class Worker extends BaseCommand { static description = '\nStarts a n8n worker'; @@ -286,7 +286,7 @@ export class Worker extends BaseCommand { await Container.get(MessageEventBus).initialize({ workerId: this.queueModeId, }); - Container.get(LogEventRelay).init(); + Container.get(LogStreamingEventRelay).init(); } /** diff --git a/packages/cli/src/decorators/Redactable.ts b/packages/cli/src/decorators/Redactable.ts index a6b6f708e7787..51d02c5c3d6fc 100644 --- a/packages/cli/src/decorators/Redactable.ts +++ b/packages/cli/src/decorators/Redactable.ts @@ -14,7 +14,7 @@ function toRedactable(userLike: UserLike) { type FieldName = 'user' | 'inviter' | 'invitee'; /** - * Mark redactable properties in a `{ user: UserLike }` field in an `LogEventRelay` + * Mark redactable properties in a `{ user: UserLike }` field in an `LogStreamingEventRelay` * method arg. These properties will be later redacted by the log streaming * destination based on user prefs. Only for `n8n.audit.*` logs. * diff --git a/packages/cli/src/errors/redactable.error.ts b/packages/cli/src/errors/redactable.error.ts index 4262f12b002f2..0d5b07ac504fb 100644 --- a/packages/cli/src/errors/redactable.error.ts +++ b/packages/cli/src/errors/redactable.error.ts @@ -3,7 +3,7 @@ import { ApplicationError } from 'n8n-workflow'; export class RedactableError extends ApplicationError { constructor(fieldName: string, args: string) { super( - `Failed to find "${fieldName}" property in argument "${args.toString()}". Please set the decorator \`@Redactable()\` only on \`LogEventRelay\` methods where the argument contains a "${fieldName}" property.`, + `Failed to find "${fieldName}" property in argument "${args.toString()}". Please set the decorator \`@Redactable()\` only on \`LogStreamingEventRelay\` methods where the argument contains a "${fieldName}" property.`, ); } } diff --git a/packages/cli/src/events/__tests__/log-event-relay.test.ts b/packages/cli/src/events/__tests__/log-streaming-event-relay.test.ts similarity index 98% rename from packages/cli/src/events/__tests__/log-event-relay.test.ts rename to packages/cli/src/events/__tests__/log-streaming-event-relay.test.ts index 70d4df572be00..4084bebeb228f 100644 --- a/packages/cli/src/events/__tests__/log-event-relay.test.ts +++ b/packages/cli/src/events/__tests__/log-streaming-event-relay.test.ts @@ -1,15 +1,15 @@ import { mock } from 'jest-mock-extended'; -import { LogEventRelay } from '@/events/log-event-relay'; +import { LogStreamingEventRelay } from '@/events/log-streaming-event-relay'; import { EventService } from '@/events/event.service'; import type { INode, IRun, IWorkflowBase } from 'n8n-workflow'; import type { IWorkflowDb } from '@/Interfaces'; import type { MessageEventBus } from '@/eventbus/MessageEventBus/MessageEventBus'; import type { RelayEventMap } from '@/events/relay-event-map'; -describe('LogEventRelay', () => { +describe('LogStreamingEventRelay', () => { const eventBus = mock(); const eventService = new EventService(); - new LogEventRelay(eventService, eventBus).init(); + new LogStreamingEventRelay(eventService, eventBus).init(); afterEach(() => { jest.clearAllMocks(); diff --git a/packages/cli/src/events/log-event-relay.ts b/packages/cli/src/events/log-streaming-event-relay.ts similarity index 99% rename from packages/cli/src/events/log-event-relay.ts rename to packages/cli/src/events/log-streaming-event-relay.ts index 21691cbc6265c..e0402011c3b0e 100644 --- a/packages/cli/src/events/log-event-relay.ts +++ b/packages/cli/src/events/log-streaming-event-relay.ts @@ -7,7 +7,7 @@ import type { IWorkflowBase } from 'n8n-workflow'; import { EventService } from './event.service'; @Service() -export class LogEventRelay extends EventRelay { +export class LogStreamingEventRelay extends EventRelay { constructor( readonly eventService: EventService, private readonly eventBus: MessageEventBus, diff --git a/packages/cli/test/integration/commands/worker.cmd.test.ts b/packages/cli/test/integration/commands/worker.cmd.test.ts index bd84d48b7f039..54c15d381de95 100644 --- a/packages/cli/test/integration/commands/worker.cmd.test.ts +++ b/packages/cli/test/integration/commands/worker.cmd.test.ts @@ -15,7 +15,7 @@ import { type JobQueue, Queue } from '@/Queue'; import { setupTestCommand } from '@test-integration/utils/testCommand'; import { mockInstance } from '../../shared/mocking'; -import { LogEventRelay } from '@/events/log-event-relay'; +import { LogStreamingEventRelay } from '@/events/log-streaming-event-relay'; config.set('executions.mode', 'queue'); config.set('binaryDataManager.availableModes', 'filesystem'); @@ -26,7 +26,7 @@ const externalHooks = mockInstance(ExternalHooks); const externalSecretsManager = mockInstance(ExternalSecretsManager); const license = mockInstance(License); const messageEventBus = mockInstance(MessageEventBus); -const logEventRelay = mockInstance(LogEventRelay); +const logStreamingEventRelay = mockInstance(LogStreamingEventRelay); const orchestrationHandlerWorkerService = mockInstance(OrchestrationHandlerWorkerService); const queue = mockInstance(Queue); const orchestrationWorkerService = mockInstance(OrchestrationWorkerService); @@ -45,7 +45,7 @@ test('worker initializes all its components', async () => { expect(externalHooks.init).toHaveBeenCalledTimes(1); expect(externalSecretsManager.init).toHaveBeenCalledTimes(1); expect(messageEventBus.initialize).toHaveBeenCalledTimes(1); - expect(logEventRelay.init).toHaveBeenCalledTimes(1); + expect(logStreamingEventRelay.init).toHaveBeenCalledTimes(1); expect(queue.init).toHaveBeenCalledTimes(1); expect(queue.process).toHaveBeenCalledTimes(1); expect(orchestrationWorkerService.init).toHaveBeenCalledTimes(1); From 190b6787c0978582cf0f7ed71b6bba2a4c337780 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Fri, 2 Aug 2024 15:12:24 +0200 Subject: [PATCH 5/7] No optional handler --- packages/cli/src/events/event-relay.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/cli/src/events/event-relay.ts b/packages/cli/src/events/event-relay.ts index c67397ec2c636..1a8a17b8930f2 100644 --- a/packages/cli/src/events/event-relay.ts +++ b/packages/cli/src/events/event-relay.ts @@ -10,10 +10,8 @@ export class EventRelay { [EventName in EventNames]?: (event: RelayEventMap[EventName]) => void | Promise; }) { for (const [eventName, handler] of Object.entries(map) as Array< - [EventNames, ((event: RelayEventMap[EventNames]) => void | Promise) | undefined] + [EventNames, (event: RelayEventMap[EventNames]) => void | Promise] >) { - if (!handler) continue; - this.eventService.on(eventName, async (event) => { await handler(event); }); From 1bc813086ea5f32b998861b57b785ae2a3f213af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Fri, 2 Aug 2024 15:21:41 +0200 Subject: [PATCH 6/7] Use VSCode regions --- .../src/events/log-streaming-event-relay.ts | 60 +++--- packages/cli/src/events/relay-event-map.ts | 94 +++++----- .../cli/src/events/telemetry-event-relay.ts | 174 +++++++++++------- 3 files changed, 189 insertions(+), 139 deletions(-) diff --git a/packages/cli/src/events/log-streaming-event-relay.ts b/packages/cli/src/events/log-streaming-event-relay.ts index e0402011c3b0e..85d5a8cb8fb3c 100644 --- a/packages/cli/src/events/log-streaming-event-relay.ts +++ b/packages/cli/src/events/log-streaming-event-relay.ts @@ -49,9 +49,7 @@ export class LogStreamingEventRelay extends EventRelay { }); } - /** - * Workflow - */ + // #region Workflow @Redactable() private workflowCreated({ user, workflow }: RelayEventMap['workflow-created']) { @@ -143,9 +141,9 @@ export class LogStreamingEventRelay extends EventRelay { }); } - /** - * Node - */ + // #endregion + + // #region Node private nodePreExecute({ workflow, executionId, nodeName }: RelayEventMap['node-pre-execute']) { void this.eventBus.sendNodeEvent({ @@ -173,9 +171,9 @@ export class LogStreamingEventRelay extends EventRelay { }); } - /** - * User - */ + // #endregion + + // #region User @Redactable() private userDeleted({ user }: RelayEventMap['user-deleted']) { @@ -209,9 +207,9 @@ export class LogStreamingEventRelay extends EventRelay { }); } - /** - * Auth - */ + // #endregion + + // #region Auth @Redactable() private userSignedUp({ user }: RelayEventMap['user-signed-up']) { @@ -238,9 +236,9 @@ export class LogStreamingEventRelay extends EventRelay { }); } - /** - * Click - */ + // #endregion + + // #region Click @Redactable('inviter') @Redactable('invitee') @@ -269,9 +267,9 @@ export class LogStreamingEventRelay extends EventRelay { }); } - /** - * Public API - */ + // #endregion + + // #region Public API @Redactable() private publicApiKeyCreated({ user }: RelayEventMap['public-api-key-created']) { @@ -289,9 +287,9 @@ export class LogStreamingEventRelay extends EventRelay { }); } - /** - * Emailing - */ + // #endregion + + // #region Email @Redactable() private emailFailed({ user, messageType }: RelayEventMap['email-failed']) { @@ -301,9 +299,9 @@ export class LogStreamingEventRelay extends EventRelay { }); } - /** - * Credentials - */ + // #endregion + + // #region Credentials @Redactable() private credentialsCreated({ user, ...rest }: RelayEventMap['credentials-created']) { @@ -337,9 +335,9 @@ export class LogStreamingEventRelay extends EventRelay { }); } - /** - * Community package - */ + // #endregion + + // #region Community package @Redactable() private communityPackageInstalled({ @@ -368,9 +366,9 @@ export class LogStreamingEventRelay extends EventRelay { }); } - /** - * Execution - */ + // #endregion + + // #region Execution private executionThrottled({ executionId }: RelayEventMap['execution-throttled']) { void this.eventBus.sendExecutionEvent({ @@ -387,4 +385,6 @@ export class LogStreamingEventRelay extends EventRelay { payload: { executionId }, }); } + + // #endregion } diff --git a/packages/cli/src/events/relay-event-map.ts b/packages/cli/src/events/relay-event-map.ts index fb7c3c9c1e65d..193e85c9a4ed8 100644 --- a/packages/cli/src/events/relay-event-map.ts +++ b/packages/cli/src/events/relay-event-map.ts @@ -12,11 +12,13 @@ export type UserLike = { }; export type RelayEventMap = { + // #region Server + 'server-started': {}; - /** - * Workflow - */ + // #endregion + + // #region Workflow 'workflow-created': { user: UserLike; @@ -50,9 +52,9 @@ export type RelayEventMap = { runData?: IRun; }; - /** - * Node - */ + // #endregion + + // #region Node 'node-pre-execute': { executionId: string; @@ -66,9 +68,9 @@ export type RelayEventMap = { nodeName: string; }; - /** - * User - */ + // #endregion + + // #region User 'user-deleted': { user: UserLike; @@ -104,9 +106,9 @@ export type RelayEventMap = { reason?: string; }; - /** - * Click - */ + // #endregion + + // #region Click 'user-invite-email-click': { inviter: UserLike; @@ -121,9 +123,9 @@ export type RelayEventMap = { user: UserLike; }; - /** - * Public API - */ + // #endregion + + // #region Public API 'public-api-key-created': { user: UserLike; @@ -142,9 +144,9 @@ export type RelayEventMap = { apiVersion: string; }; - /** - * Email - */ + // #endregion + + // #region Email 'email-failed': { user: UserLike; @@ -156,9 +158,9 @@ export type RelayEventMap = { | 'Credentials shared'; }; - /** - * Credentials - */ + // #endregion + + // #region Credentials 'credentials-created': { user: UserLike; @@ -190,9 +192,9 @@ export type RelayEventMap = { credentialId: string; }; - /** - * Community package - */ + // #endregion + + // #region Community package 'community-package-installed': { user: UserLike; @@ -225,9 +227,9 @@ export type RelayEventMap = { packageAuthorEmail?: string; }; - /** - * Execution - */ + // #endregion + + // #region Execution 'execution-throttled': { executionId: string; @@ -237,9 +239,9 @@ export type RelayEventMap = { executionId: string; }; - /** - * Project - */ + // #endregion + + // #region Project 'team-project-updated': { userId: string; @@ -264,9 +266,9 @@ export type RelayEventMap = { role: GlobalRole; }; - /** - * Source control - */ + // #endregion + + // #region Source control 'source-control-settings-updated': { branchName: string; @@ -305,23 +307,23 @@ export type RelayEventMap = { variablesPushed: number; }; - /** - * License - */ + // #endregion + + // #region License 'license-renewal-attempted': { success: boolean; }; - /** - * Variable - */ + // #endregion + + // #region Variable 'variable-created': {}; - /** - * External secrets - */ + // #endregion + + // #region External secrets 'external-secrets-provider-settings-saved': { userId?: string; @@ -331,9 +333,9 @@ export type RelayEventMap = { errorMessage?: string; }; - /** - * LDAP - */ + // #endregion + + // #region LDAP 'ldap-general-sync-finished': { type: string; @@ -364,4 +366,6 @@ export type RelayEventMap = { 'login-failed-due-to-ldap-disabled': { userId: string; }; + + // #endregion }; diff --git a/packages/cli/src/events/telemetry-event-relay.ts b/packages/cli/src/events/telemetry-event-relay.ts index 19338470ea27b..91f82a0c127a5 100644 --- a/packages/cli/src/events/telemetry-event-relay.ts +++ b/packages/cli/src/events/telemetry-event-relay.ts @@ -76,6 +76,10 @@ export class TelemetryEventRelay extends EventRelay { }); } + // #endregion + + // #region Team + private teamProjectUpdated({ userId, role, @@ -114,6 +118,10 @@ export class TelemetryEventRelay extends EventRelay { }); } + // #endregion + + // #region Source control + private sourceControlSettingsUpdated({ branchName, readOnlyInstance, @@ -192,16 +200,28 @@ export class TelemetryEventRelay extends EventRelay { }); } + // #endregion + + // #region License + private licenseRenewalAttempted({ success }: RelayEventMap['license-renewal-attempted']) { this.telemetry.track('Instance attempted to refresh license', { success, }); } + // #endregion + + // #region Variable + private variableCreated() { this.telemetry.track('User created variable'); } + // #endregion + + // #region External secrets + private externalSecretsProviderSettingsSaved({ userId, vaultType, @@ -218,6 +238,10 @@ export class TelemetryEventRelay extends EventRelay { }); } + // #endregion + + // #region Public API + private publicApiInvoked({ userId, path, @@ -250,6 +274,10 @@ export class TelemetryEventRelay extends EventRelay { }); } + // #endregion + + // #region Community package + private communityPackageInstalled({ user, inputString, @@ -312,6 +340,10 @@ export class TelemetryEventRelay extends EventRelay { }); } + // #endregion + + // #region Credentials + private credentialsCreated({ user, credentialType, @@ -370,6 +402,10 @@ export class TelemetryEventRelay extends EventRelay { }); } + // #endregion + + // #region LDAP + private ldapGeneralSyncFinished({ type, succeeded, @@ -424,6 +460,10 @@ export class TelemetryEventRelay extends EventRelay { this.telemetry.track('User login failed since ldap disabled', { user_ud: userId }); } + // #endregion + + // #region Workflow + private workflowCreated({ user, workflow, @@ -497,70 +537,6 @@ export class TelemetryEventRelay extends EventRelay { }); } - private async serverStarted() { - const cpus = os.cpus(); - const binaryDataConfig = config.getEnv('binaryDataManager'); - - const isS3Selected = config.getEnv('binaryDataManager.mode') === 's3'; - const isS3Available = config.getEnv('binaryDataManager.availableModes').includes('s3'); - const isS3Licensed = this.license.isBinaryDataS3Licensed(); - const authenticationMethod = config.getEnv('userManagement.authenticationMethod'); - - const info = { - version_cli: N8N_VERSION, - db_type: this.globalConfig.database.type, - n8n_version_notifications_enabled: this.globalConfig.versionNotifications.enabled, - n8n_disable_production_main_process: - this.globalConfig.endpoints.disableProductionWebhooksOnMainProcess, - system_info: { - os: { - type: os.type(), - version: os.version(), - }, - memory: os.totalmem() / 1024, - cpus: { - count: cpus.length, - model: cpus[0].model, - speed: cpus[0].speed, - }, - }, - execution_variables: { - executions_mode: config.getEnv('executions.mode'), - executions_timeout: config.getEnv('executions.timeout'), - executions_timeout_max: config.getEnv('executions.maxTimeout'), - executions_data_save_on_error: config.getEnv('executions.saveDataOnError'), - executions_data_save_on_success: config.getEnv('executions.saveDataOnSuccess'), - executions_data_save_on_progress: config.getEnv('executions.saveExecutionProgress'), - executions_data_save_manual_executions: config.getEnv( - 'executions.saveDataManualExecutions', - ), - executions_data_prune: config.getEnv('executions.pruneData'), - executions_data_max_age: config.getEnv('executions.pruneDataMaxAge'), - }, - n8n_deployment_type: config.getEnv('deployment.type'), - n8n_binary_data_mode: binaryDataConfig.mode, - smtp_set_up: this.globalConfig.userManagement.emails.mode === 'smtp', - ldap_allowed: authenticationMethod === 'ldap', - saml_enabled: authenticationMethod === 'saml', - license_plan_name: this.license.getPlanName(), - license_tenant_id: config.getEnv('license.tenantId'), - binary_data_s3: isS3Available && isS3Selected && isS3Licensed, - multi_main_setup_enabled: config.getEnv('multiMainSetup.enabled'), - }; - - const firstWorkflow = await this.workflowRepository.findOne({ - select: ['createdAt'], - order: { createdAt: 'ASC' }, - where: {}, - }); - - this.telemetry.identify(info); - this.telemetry.track('Instance started', { - ...info, - earliest_workflow_created: firstWorkflow?.createdAt, - }); - } - // eslint-disable-next-line complexity private async workflowPostExecute({ workflow, @@ -698,4 +674,74 @@ export class TelemetryEventRelay extends EventRelay { this.telemetry.trackWorkflowExecution(telemetryProperties); } + + // #endregion + + // #region Server + + private async serverStarted() { + const cpus = os.cpus(); + const binaryDataConfig = config.getEnv('binaryDataManager'); + + const isS3Selected = config.getEnv('binaryDataManager.mode') === 's3'; + const isS3Available = config.getEnv('binaryDataManager.availableModes').includes('s3'); + const isS3Licensed = this.license.isBinaryDataS3Licensed(); + const authenticationMethod = config.getEnv('userManagement.authenticationMethod'); + + const info = { + version_cli: N8N_VERSION, + db_type: this.globalConfig.database.type, + n8n_version_notifications_enabled: this.globalConfig.versionNotifications.enabled, + n8n_disable_production_main_process: + this.globalConfig.endpoints.disableProductionWebhooksOnMainProcess, + system_info: { + os: { + type: os.type(), + version: os.version(), + }, + memory: os.totalmem() / 1024, + cpus: { + count: cpus.length, + model: cpus[0].model, + speed: cpus[0].speed, + }, + }, + execution_variables: { + executions_mode: config.getEnv('executions.mode'), + executions_timeout: config.getEnv('executions.timeout'), + executions_timeout_max: config.getEnv('executions.maxTimeout'), + executions_data_save_on_error: config.getEnv('executions.saveDataOnError'), + executions_data_save_on_success: config.getEnv('executions.saveDataOnSuccess'), + executions_data_save_on_progress: config.getEnv('executions.saveExecutionProgress'), + executions_data_save_manual_executions: config.getEnv( + 'executions.saveDataManualExecutions', + ), + executions_data_prune: config.getEnv('executions.pruneData'), + executions_data_max_age: config.getEnv('executions.pruneDataMaxAge'), + }, + n8n_deployment_type: config.getEnv('deployment.type'), + n8n_binary_data_mode: binaryDataConfig.mode, + smtp_set_up: this.globalConfig.userManagement.emails.mode === 'smtp', + ldap_allowed: authenticationMethod === 'ldap', + saml_enabled: authenticationMethod === 'saml', + license_plan_name: this.license.getPlanName(), + license_tenant_id: config.getEnv('license.tenantId'), + binary_data_s3: isS3Available && isS3Selected && isS3Licensed, + multi_main_setup_enabled: config.getEnv('multiMainSetup.enabled'), + }; + + const firstWorkflow = await this.workflowRepository.findOne({ + select: ['createdAt'], + order: { createdAt: 'ASC' }, + where: {}, + }); + + this.telemetry.identify(info); + this.telemetry.track('Instance started', { + ...info, + earliest_workflow_created: firstWorkflow?.createdAt, + }); + } + + // #endregion } From 06b991e10a499c1bc8797e176fb5802e8fe44567 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Fri, 2 Aug 2024 15:26:37 +0200 Subject: [PATCH 7/7] Missed a spot --- packages/cli/src/InternalHooks.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/src/InternalHooks.ts b/packages/cli/src/InternalHooks.ts index d9f1e6f4fc8f8..af72d6bfece78 100644 --- a/packages/cli/src/InternalHooks.ts +++ b/packages/cli/src/InternalHooks.ts @@ -9,7 +9,7 @@ import { Telemetry } from '@/telemetry'; import { MessageEventBus } from './eventbus/MessageEventBus/MessageEventBus'; /** - * @deprecated Do not add to this class. To add log or telemetry events, use + * @deprecated Do not add to this class. To add log streaming or telemetry events, use * `EventService` to emit the event and then use the `LogStreamingEventRelay` or * `TelemetryEventRelay` to forward them to the event bus or telemetry. */