diff --git a/packages/cli/src/eventbus/event-message-classes/event-message-audit.ts b/packages/cli/src/eventbus/event-message-classes/event-message-audit.ts index d0f89f40cef..2ee47aa41e3 100644 --- a/packages/cli/src/eventbus/event-message-classes/event-message-audit.ts +++ b/packages/cli/src/eventbus/event-message-classes/event-message-audit.ts @@ -20,6 +20,7 @@ export interface EventPayloadAudit extends AbstractEventPayload { credentialId?: string; workflowId?: string; workflowName?: string; + activeVersionId?: string | null; } export interface EventMessageAuditOptions extends AbstractEventMessageOptions { diff --git a/packages/cli/src/eventbus/event-message-classes/index.ts b/packages/cli/src/eventbus/event-message-classes/index.ts index e02f07bc010..f992df41124 100644 --- a/packages/cli/src/eventbus/event-message-classes/index.ts +++ b/packages/cli/src/eventbus/event-message-classes/index.ts @@ -81,6 +81,8 @@ export const eventNamesAudit = [ 'n8n.audit.workflow.updated', 'n8n.audit.workflow.archived', 'n8n.audit.workflow.unarchived', + 'n8n.audit.workflow.activated', + 'n8n.audit.workflow.deactivated', ] as const; export type EventNamesWorkflowType = (typeof eventNamesWorkflow)[number]; diff --git a/packages/cli/src/events/__tests__/log-streaming-event-relay.test.ts b/packages/cli/src/events/__tests__/log-streaming-event-relay.test.ts index af4b567144f..45e87eb8331 100644 --- a/packages/cli/src/events/__tests__/log-streaming-event-relay.test.ts +++ b/packages/cli/src/events/__tests__/log-streaming-event-relay.test.ts @@ -110,6 +110,76 @@ describe('LogStreamingEventRelay', () => { }); }); + it('should log on `workflow-activated` event', () => { + const event: RelayEventMap['workflow-activated'] = { + user: { + id: '123', + email: 'john@n8n.io', + firstName: 'John', + lastName: 'Doe', + role: { slug: 'owner' }, + }, + workflowId: 'wf123', + workflow: mock({ + id: 'wf123', + name: 'Test Workflow', + activeVersionId: 'version-abc-123', + }), + publicApi: false, + }; + + eventService.emit('workflow-activated', event); + + expect(eventBus.sendAuditEvent).toHaveBeenCalledWith({ + eventName: 'n8n.audit.workflow.activated', + payload: { + userId: '123', + _email: 'john@n8n.io', + _firstName: 'John', + _lastName: 'Doe', + globalRole: 'owner', + workflowId: 'wf123', + workflowName: 'Test Workflow', + activeVersionId: 'version-abc-123', + }, + }); + }); + + it('should log on `workflow-deactivated` event', () => { + const event: RelayEventMap['workflow-deactivated'] = { + user: { + id: '456', + email: 'jane@n8n.io', + firstName: 'Jane', + lastName: 'Smith', + role: { slug: 'user' }, + }, + workflowId: 'wf789', + workflow: mock({ + id: 'wf789', + name: 'Deactivated Workflow', + activeVersionId: 'version-xyz-789', + }), + publicApi: false, + }; + + eventService.emit('workflow-deactivated', event); + + expect(eventBus.sendAuditEvent).toHaveBeenCalledWith({ + eventName: 'n8n.audit.workflow.deactivated', + payload: { + userId: '456', + _email: 'jane@n8n.io', + _firstName: 'Jane', + _lastName: 'Smith', + globalRole: 'user', + workflowId: 'wf789', + workflowName: 'Deactivated Workflow', + activeVersionId: 'version-xyz-789', + }, + }); + }); + it('should log on `workflow-deleted` event', () => { const event: RelayEventMap['workflow-deleted'] = { user: { diff --git a/packages/cli/src/events/relays/log-streaming.event-relay.ts b/packages/cli/src/events/relays/log-streaming.event-relay.ts index c68034f8db5..d6f397dec04 100644 --- a/packages/cli/src/events/relays/log-streaming.event-relay.ts +++ b/packages/cli/src/events/relays/log-streaming.event-relay.ts @@ -24,6 +24,8 @@ export class LogStreamingEventRelay extends EventRelay { 'workflow-deleted': (event) => this.workflowDeleted(event), 'workflow-archived': (event) => this.workflowArchived(event), 'workflow-unarchived': (event) => this.workflowUnarchived(event), + 'workflow-activated': (event) => this.workflowActivated(event), + 'workflow-deactivated': (event) => this.workflowDeactivated(event), 'workflow-saved': (event) => this.workflowSaved(event), 'workflow-pre-execute': (event) => this.workflowPreExecute(event), 'workflow-post-execute': (event) => this.workflowPostExecute(event), @@ -112,6 +114,36 @@ export class LogStreamingEventRelay extends EventRelay { }); } + @Redactable() + private workflowActivated({ user, workflowId, workflow }: RelayEventMap['workflow-activated']) { + void this.eventBus.sendAuditEvent({ + eventName: 'n8n.audit.workflow.activated', + payload: { + ...user, + workflowId, + workflowName: workflow.name, + activeVersionId: workflow.activeVersionId, + }, + }); + } + + @Redactable() + private workflowDeactivated({ + user, + workflowId, + workflow, + }: RelayEventMap['workflow-deactivated']) { + void this.eventBus.sendAuditEvent({ + eventName: 'n8n.audit.workflow.deactivated', + payload: { + ...user, + workflowId, + workflowName: workflow.name, + activeVersionId: workflow.activeVersionId, + }, + }); + } + @Redactable() private workflowSaved({ user, workflow }: RelayEventMap['workflow-saved']) { void this.eventBus.sendAuditEvent({