From 1f9a6b067af85935a5fb4b5f3a3c62d138a1d460 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Mon, 8 Dec 2025 09:48:44 +0100 Subject: [PATCH] fix: make impersonation audit logging non-blocking (#16390) ## Summary This PR makes the Clickhouse audit logging in the impersonation flow **non-blocking** (fire-and-forget). ## Problem When the Clickhouse server is unavailable or slow, the impersonation feature becomes blocked because all audit logging calls use `await`, causing the entire impersonation flow to hang. ## Solution Remove the `await` keyword from all audit logging calls in the impersonation flow. The `ClickHouseService.insert()` method already handles errors internally (catches and logs them), so there's no risk of unhandled promise rejections. ## Changes - **`impersonation.service.ts`**: 4 audit calls made non-blocking - **`auth.resolver.ts`**: 5 audit calls made non-blocking - **`auth.service.ts`**: 2 audit calls made non-blocking ## Testing - Impersonation flow continues to work when Clickhouse is available - Impersonation flow no longer blocks when Clickhouse is unavailable --- .../src/engine/core-modules/auth/auth.resolver.ts | 10 +++++----- .../engine/core-modules/auth/services/auth.service.ts | 4 ++-- .../impersonation/services/impersonation.service.ts | 8 ++++---- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/twenty-server/src/engine/core-modules/auth/auth.resolver.ts b/packages/twenty-server/src/engine/core-modules/auth/auth.resolver.ts index 695cc967f6..07cc4eb936 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/auth.resolver.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/auth.resolver.ts @@ -706,7 +706,7 @@ export class AuthResolver { userId: impersonatorUserWorkspace.user.id, }); - await auditService.insertWorkspaceEvent(MONITORING_EVENT, { + auditService.insertWorkspaceEvent(MONITORING_EVENT, { eventName: `${isServerLevelImpersonation ? 'server' : 'workspace'}.impersonation.token_exchange_attempt`, message: `Impersonation token exchange attempt for ${targetUserEmail} by ${impersonatorUserWorkspace.user.id}`, }); @@ -717,7 +717,7 @@ export class AuthResolver { if (isServerLevelImpersonation) { if (!hasServerLevelImpersonatePermission) { - await auditService.insertWorkspaceEvent(MONITORING_EVENT, { + auditService.insertWorkspaceEvent(MONITORING_EVENT, { eventName: 'server.impersonation.token_exchange_failed', message: `Server level impersonation not allowed for ${targetUserEmail} by userId ${impersonatorUserWorkspace.user.id}`, }); @@ -728,7 +728,7 @@ export class AuthResolver { ); } - await auditService.insertWorkspaceEvent(MONITORING_EVENT, { + auditService.insertWorkspaceEvent(MONITORING_EVENT, { eventName: `server.impersonation.token_exchange_success`, message: `Impersonation token exchanged for ${targetUserEmail} by userId ${impersonatorUserWorkspace.user.id}`, }); @@ -750,7 +750,7 @@ export class AuthResolver { }); if (!hasWorkspaceLevelImpersonatePermission) { - await auditService.insertWorkspaceEvent(MONITORING_EVENT, { + auditService.insertWorkspaceEvent(MONITORING_EVENT, { eventName: 'workspace.impersonation.token_exchange_failed', message: `Impersonation not allowed for ${targetUserEmail} by userId ${impersonatorUserWorkspace.user.id}`, }); @@ -760,7 +760,7 @@ export class AuthResolver { ); } - await auditService.insertWorkspaceEvent(MONITORING_EVENT, { + auditService.insertWorkspaceEvent(MONITORING_EVENT, { eventName: 'workspace.impersonation.token_exchange_success', message: `Impersonation token exchanged for ${targetUserEmail} by userId ${impersonatorUserWorkspace.user.id}`, }); diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/auth.service.ts b/packages/twenty-server/src/engine/core-modules/auth/services/auth.service.ts index ba9b33af24..0723bd66b6 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/auth.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/auth.service.ts @@ -410,7 +410,7 @@ export class AuthService { userId: impersonatorUserId, }); - await analytics.insertWorkspaceEvent('Monitoring', { + analytics.insertWorkspaceEvent('Monitoring', { eventName: 'workspace.impersonation.attempted', message: `correlationId=${correlationId}; impersonatorUserWorkspaceId=${impersonatorUserWorkspaceId}; targetUserWorkspaceId=${impersonatedUserWorkspaceId}; workspaceId=${workspaceId}`, }); @@ -436,7 +436,7 @@ export class AuthService { true, ); - await analytics.insertWorkspaceEvent('Monitoring', { + analytics.insertWorkspaceEvent('Monitoring', { eventName: 'workspace.impersonation.issued', message: `correlationId=${correlationId}; impersonatorUserWorkspaceId=${impersonatorUserWorkspaceId}; targetUserWorkspaceId=${impersonatedUserWorkspaceId}; workspaceId=${workspaceId}`, }); diff --git a/packages/twenty-server/src/engine/core-modules/impersonation/services/impersonation.service.ts b/packages/twenty-server/src/engine/core-modules/impersonation/services/impersonation.service.ts index 5c5bd22cc5..e9ae50afc8 100644 --- a/packages/twenty-server/src/engine/core-modules/impersonation/services/impersonation.service.ts +++ b/packages/twenty-server/src/engine/core-modules/impersonation/services/impersonation.service.ts @@ -144,13 +144,13 @@ export class ImpersonationService { userId: impersonatorUserWorkspace.user.id, }); - await auditService.insertWorkspaceEvent(MONITORING_EVENT, { + auditService.insertWorkspaceEvent(MONITORING_EVENT, { eventName: `${impersonationLevel}.impersonation.attempt`, message: `Impersonation attempt: targetUserId=${toImpersonateUserWorkspace.user.id}, workspaceId=${toImpersonateUserWorkspace.workspace.id}, impersonatorUserId=${impersonatorUserWorkspace.user.id}`, }); try { - await auditService.insertWorkspaceEvent(MONITORING_EVENT, { + auditService.insertWorkspaceEvent(MONITORING_EVENT, { eventName: `${impersonationLevel}.impersonation.login_token_attempt`, message: `Impersonation token generation attempt for user ${toImpersonateUserWorkspace.user.id}`, }); @@ -164,7 +164,7 @@ export class ImpersonationService { }, ); - await auditService.insertWorkspaceEvent(MONITORING_EVENT, { + auditService.insertWorkspaceEvent(MONITORING_EVENT, { eventName: `${impersonationLevel}.impersonation.login_token_generated`, message: `Impersonation token generated successfully for user ${toImpersonateUserWorkspace.user.id}`, }); @@ -179,7 +179,7 @@ export class ImpersonationService { loginToken, }; } catch { - await auditService.insertWorkspaceEvent(MONITORING_EVENT, { + auditService.insertWorkspaceEvent(MONITORING_EVENT, { eventName: `${impersonationLevel}.impersonation.login_token_failed`, message: `Impersonation token generation failed for targetUserId=${toImpersonateUserWorkspace.user.id}`, });