From f4f0a36fe1f8a792e3581849a0d8a78ce1e6f21a Mon Sep 17 00:00:00 2001 From: Val <68596159+valya@users.noreply.github.com> Date: Mon, 8 Apr 2024 08:13:39 +0100 Subject: [PATCH] feat: Add credential update and delete events to log streaming (#9026) --- packages/cli/src/InternalHooks.ts | 49 +++++++++++++++++++ .../credentials/credentials.handler.ts | 2 +- .../credentials/credentials.service.ts | 19 ++++++- .../src/credentials/credentials.controller.ts | 14 ++++++ .../src/eventbus/EventMessageClasses/index.ts | 2 + 5 files changed, 84 insertions(+), 2 deletions(-) diff --git a/packages/cli/src/InternalHooks.ts b/packages/cli/src/InternalHooks.ts index a7baaf24b..6d01bd65d 100644 --- a/packages/cli/src/InternalHooks.ts +++ b/packages/cli/src/InternalHooks.ts @@ -917,6 +917,55 @@ export class InternalHooks { ]); } + async onUserUpdatedCredentials(userUpdatedCredentialsData: { + user: User; + credential_name: string; + credential_type: string; + credential_id: string; + }): Promise { + void Promise.all([ + this.eventBus.sendAuditEvent({ + eventName: 'n8n.audit.user.credentials.updated', + payload: { + ...userToPayload(userUpdatedCredentialsData.user), + credentialName: userUpdatedCredentialsData.credential_name, + credentialType: userUpdatedCredentialsData.credential_type, + credentialId: userUpdatedCredentialsData.credential_id, + }, + }), + this.telemetry.track('User updated credentials', { + user_id: userUpdatedCredentialsData.user.id, + credential_type: userUpdatedCredentialsData.credential_type, + credential_id: userUpdatedCredentialsData.credential_id, + }), + ]); + } + + async onUserDeletedCredentials(userUpdatedCredentialsData: { + user: User; + credential_name: string; + credential_type: string; + credential_id: string; + }): Promise { + void Promise.all([ + this.eventBus.sendAuditEvent({ + eventName: 'n8n.audit.user.credentials.deleted', + payload: { + ...userToPayload(userUpdatedCredentialsData.user), + credentialName: userUpdatedCredentialsData.credential_name, + credentialType: userUpdatedCredentialsData.credential_type, + credentialId: userUpdatedCredentialsData.credential_id, + }, + }), + this.telemetry.track('User deleted credentials', { + user_id: userUpdatedCredentialsData.user.id, + credential_type: userUpdatedCredentialsData.credential_type, + credential_id: userUpdatedCredentialsData.credential_id, + instance_id: this.instanceSettings.instanceId, + }), + ]); + } + /** * Community nodes backend telemetry events */ diff --git a/packages/cli/src/PublicApi/v1/handlers/credentials/credentials.handler.ts b/packages/cli/src/PublicApi/v1/handlers/credentials/credentials.handler.ts index 1a4275f94..165c7f911 100644 --- a/packages/cli/src/PublicApi/v1/handlers/credentials/credentials.handler.ts +++ b/packages/cli/src/PublicApi/v1/handlers/credentials/credentials.handler.ts @@ -69,7 +69,7 @@ export = { return res.status(404).json({ message: 'Not Found' }); } - await removeCredential(credential); + await removeCredential(req.user, credential); return res.json(sanitizeCredentials(credential)); }, ], 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 9fe0df30d..38a241371 100644 --- a/packages/cli/src/PublicApi/v1/handlers/credentials/credentials.service.ts +++ b/packages/cli/src/PublicApi/v1/handlers/credentials/credentials.service.ts @@ -16,6 +16,7 @@ import type { CredentialRequest } from '@/requests'; import { Container } from 'typedi'; import { CredentialsRepository } from '@db/repositories/credentials.repository'; import { SharedCredentialsRepository } from '@db/repositories/sharedCredentials.repository'; +import { InternalHooks } from '@/InternalHooks'; export async function getCredentials(credentialId: string): Promise { return await Container.get(CredentialsRepository).findOneBy({ id: credentialId }); @@ -50,6 +51,13 @@ export async function saveCredential( encryptedData: ICredentialsDb, ): Promise { await Container.get(ExternalHooks).run('credentials.create', [encryptedData]); + void Container.get(InternalHooks).onUserCreatedCredentials({ + user, + credential_name: credential.name, + credential_type: credential.type, + credential_id: credential.id, + public_api: true, + }); return await Db.transaction(async (transactionManager) => { const savedCredential = await transactionManager.save(credential); @@ -70,8 +78,17 @@ export async function saveCredential( }); } -export async function removeCredential(credentials: CredentialsEntity): Promise { +export async function removeCredential( + user: User, + credentials: CredentialsEntity, +): Promise { await Container.get(ExternalHooks).run('credentials.delete', [credentials.id]); + void Container.get(InternalHooks).onUserDeletedCredentials({ + user, + credential_name: credentials.name, + credential_type: credentials.type, + credential_id: credentials.id, + }); return await Container.get(CredentialsRepository).remove(credentials); } diff --git a/packages/cli/src/credentials/credentials.controller.ts b/packages/cli/src/credentials/credentials.controller.ts index f7fae043c..aba4e1543 100644 --- a/packages/cli/src/credentials/credentials.controller.ts +++ b/packages/cli/src/credentials/credentials.controller.ts @@ -252,6 +252,13 @@ export class CredentialsController { this.logger.verbose('Credential updated', { credentialId }); + void this.internalHooks.onUserUpdatedCredentials({ + user: req.user, + credential_name: credential.name, + credential_type: credential.type, + credential_id: credential.id, + }); + return { ...rest }; } @@ -291,6 +298,13 @@ export class CredentialsController { await this.credentialsService.delete(credential); + void this.internalHooks.onUserDeletedCredentials({ + user: req.user, + credential_name: credential.name, + credential_type: credential.type, + credential_id: credential.id, + }); + return true; } diff --git a/packages/cli/src/eventbus/EventMessageClasses/index.ts b/packages/cli/src/eventbus/EventMessageClasses/index.ts index 51ab91fb0..cecfcdbaf 100644 --- a/packages/cli/src/eventbus/EventMessageClasses/index.ts +++ b/packages/cli/src/eventbus/EventMessageClasses/index.ts @@ -27,6 +27,8 @@ export const eventNamesAudit = [ 'n8n.audit.user.reset', 'n8n.audit.user.credentials.created', 'n8n.audit.user.credentials.shared', + 'n8n.audit.user.credentials.updated', + 'n8n.audit.user.credentials.deleted', 'n8n.audit.user.api.created', 'n8n.audit.user.api.deleted', 'n8n.audit.package.installed',