mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-16 17:46:45 +00:00
refactor(core): Decouple Public API events from internal hooks (no-changelog) (#10121)
This commit is contained in:
@@ -504,29 +504,6 @@ export class InternalHooks {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async onUserInvokedApi(userInvokedApiData: {
|
|
||||||
user_id: string;
|
|
||||||
path: string;
|
|
||||||
method: string;
|
|
||||||
api_version: string;
|
|
||||||
}): Promise<void> {
|
|
||||||
return await this.telemetry.track('User invoked API', userInvokedApiData);
|
|
||||||
}
|
|
||||||
|
|
||||||
async onApiKeyDeleted(apiKeyDeletedData: { user: User; public_api: boolean }): Promise<void> {
|
|
||||||
void this.telemetry.track('API key deleted', {
|
|
||||||
user_id: apiKeyDeletedData.user.id,
|
|
||||||
public_api: apiKeyDeletedData.public_api,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async onApiKeyCreated(apiKeyCreatedData: { user: User; public_api: boolean }): Promise<void> {
|
|
||||||
void this.telemetry.track('API key created', {
|
|
||||||
user_id: apiKeyCreatedData.user.id,
|
|
||||||
public_api: apiKeyCreatedData.public_api,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async onUserPasswordResetRequestClick(userPasswordResetData: { user: User }): Promise<void> {
|
async onUserPasswordResetRequestClick(userPasswordResetData: { user: User }): Promise<void> {
|
||||||
void this.telemetry.track('User requested password reset while logged out', {
|
void this.telemetry.track('User requested password reset while logged out', {
|
||||||
user_id: userPasswordResetData.user.id,
|
user_id: userPasswordResetData.user.id,
|
||||||
|
|||||||
@@ -12,12 +12,12 @@ import type { JsonObject } from 'swagger-ui-express';
|
|||||||
|
|
||||||
import config from '@/config';
|
import config from '@/config';
|
||||||
|
|
||||||
import { InternalHooks } from '@/InternalHooks';
|
|
||||||
import { License } from '@/License';
|
import { License } from '@/License';
|
||||||
import { UserRepository } from '@db/repositories/user.repository';
|
import { UserRepository } from '@db/repositories/user.repository';
|
||||||
import { UrlService } from '@/services/url.service';
|
import { UrlService } from '@/services/url.service';
|
||||||
import type { AuthenticatedRequest } from '@/requests';
|
import type { AuthenticatedRequest } from '@/requests';
|
||||||
import { GlobalConfig } from '@n8n/config';
|
import { GlobalConfig } from '@n8n/config';
|
||||||
|
import { EventService } from '@/eventbus/event.service';
|
||||||
|
|
||||||
async function createApiRouter(
|
async function createApiRouter(
|
||||||
version: string,
|
version: string,
|
||||||
@@ -100,11 +100,11 @@ async function createApiRouter(
|
|||||||
|
|
||||||
if (!user) return false;
|
if (!user) return false;
|
||||||
|
|
||||||
void Container.get(InternalHooks).onUserInvokedApi({
|
Container.get(EventService).emit('public-api-invoked', {
|
||||||
user_id: user.id,
|
userId: user.id,
|
||||||
path: req.path,
|
path: req.path,
|
||||||
method: req.method,
|
method: req.method,
|
||||||
api_version: version,
|
apiVersion: version,
|
||||||
});
|
});
|
||||||
|
|
||||||
req.user = user;
|
req.user = user;
|
||||||
|
|||||||
@@ -198,8 +198,7 @@ export class MeController {
|
|||||||
|
|
||||||
await this.userService.update(req.user.id, { apiKey });
|
await this.userService.update(req.user.id, { apiKey });
|
||||||
|
|
||||||
void this.internalHooks.onApiKeyCreated({ user: req.user, public_api: false });
|
this.eventService.emit('public-api-key-created', { user: req.user, publicApi: false });
|
||||||
this.eventService.emit('api-key-created', { user: req.user });
|
|
||||||
|
|
||||||
return { apiKey };
|
return { apiKey };
|
||||||
}
|
}
|
||||||
@@ -219,8 +218,7 @@ export class MeController {
|
|||||||
async deleteAPIKey(req: AuthenticatedRequest) {
|
async deleteAPIKey(req: AuthenticatedRequest) {
|
||||||
await this.userService.update(req.user.id, { apiKey: null });
|
await this.userService.update(req.user.id, { apiKey: null });
|
||||||
|
|
||||||
void this.internalHooks.onApiKeyDeleted({ user: req.user, public_api: false });
|
this.eventService.emit('public-api-key-deleted', { user: req.user, publicApi: false });
|
||||||
this.eventService.emit('api-key-deleted', { user: req.user });
|
|
||||||
|
|
||||||
return { success: true };
|
return { success: true };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ export class AuditEventRelay {
|
|||||||
this.eventService.on('user-password-reset-request-click', (event) =>
|
this.eventService.on('user-password-reset-request-click', (event) =>
|
||||||
this.userPasswordResetRequestClick(event),
|
this.userPasswordResetRequestClick(event),
|
||||||
);
|
);
|
||||||
this.eventService.on('api-key-created', (event) => this.apiKeyCreated(event));
|
this.eventService.on('public-api-key-created', (event) => this.apiKeyCreated(event));
|
||||||
this.eventService.on('api-key-deleted', (event) => this.apiKeyDeleted(event));
|
this.eventService.on('public-api-key-deleted', (event) => this.apiKeyDeleted(event));
|
||||||
this.eventService.on('email-failed', (event) => this.emailFailed(event));
|
this.eventService.on('email-failed', (event) => this.emailFailed(event));
|
||||||
this.eventService.on('credentials-created', (event) => this.credentialsCreated(event));
|
this.eventService.on('credentials-created', (event) => this.credentialsCreated(event));
|
||||||
this.eventService.on('credentials-deleted', (event) => this.credentialsDeleted(event));
|
this.eventService.on('credentials-deleted', (event) => this.credentialsDeleted(event));
|
||||||
@@ -257,18 +257,22 @@ export class AuditEventRelay {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
@Redactable()
|
@Redactable()
|
||||||
private apiKeyCreated({ user }: Event['api-key-created']) {
|
private apiKeyCreated(event: Event['public-api-key-created']) {
|
||||||
|
if ('publicApi' in event) return;
|
||||||
|
|
||||||
void this.eventBus.sendAuditEvent({
|
void this.eventBus.sendAuditEvent({
|
||||||
eventName: 'n8n.audit.user.api.created',
|
eventName: 'n8n.audit.user.api.created',
|
||||||
payload: user,
|
payload: event.user,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Redactable()
|
@Redactable()
|
||||||
private apiKeyDeleted({ user }: Event['api-key-deleted']) {
|
private apiKeyDeleted(event: Event['public-api-key-deleted']) {
|
||||||
|
if ('publicApi' in event) return;
|
||||||
|
|
||||||
void this.eventBus.sendAuditEvent({
|
void this.eventBus.sendAuditEvent({
|
||||||
eventName: 'n8n.audit.user.api.deleted',
|
eventName: 'n8n.audit.user.api.deleted',
|
||||||
payload: user,
|
payload: event.user,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -105,13 +105,20 @@ export type Event = {
|
|||||||
user: UserLike;
|
user: UserLike;
|
||||||
};
|
};
|
||||||
|
|
||||||
'api-key-created': {
|
'public-api-invoked': {
|
||||||
user: UserLike;
|
userId: string;
|
||||||
|
path: string;
|
||||||
|
method: string;
|
||||||
|
apiVersion: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
'api-key-deleted': {
|
'public-api-key-created':
|
||||||
user: UserLike;
|
| { user: UserLike } // audit
|
||||||
};
|
| { user: UserLike; publicApi: boolean }; // telemetry
|
||||||
|
|
||||||
|
'public-api-key-deleted':
|
||||||
|
| { user: UserLike } // audit
|
||||||
|
| { user: UserLike; publicApi: boolean }; // telemetry
|
||||||
|
|
||||||
'email-failed': {
|
'email-failed': {
|
||||||
user: UserLike;
|
user: UserLike;
|
||||||
|
|||||||
@@ -50,6 +50,15 @@ export class TelemetryEventRelay {
|
|||||||
this.eventService.on('external-secrets-provider-settings-saved', (event) => {
|
this.eventService.on('external-secrets-provider-settings-saved', (event) => {
|
||||||
this.externalSecretsProviderSettingsSaved(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);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private teamProjectUpdated({ userId, role, members, projectId }: Event['team-project-updated']) {
|
private teamProjectUpdated({ userId, role, members, projectId }: Event['team-project-updated']) {
|
||||||
@@ -190,4 +199,35 @@ export class TelemetryEventRelay {
|
|||||||
error_message: errorMessage,
|
error_message: errorMessage,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private publicApiInvoked({ userId, path, method, apiVersion }: Event['public-api-invoked']) {
|
||||||
|
void this.telemetry.track('User invoked API', {
|
||||||
|
user_id: userId,
|
||||||
|
path,
|
||||||
|
method,
|
||||||
|
api_version: apiVersion,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private publicApiKeyCreated(event: Event['public-api-key-created']) {
|
||||||
|
if (!('publicApi' in event)) return;
|
||||||
|
|
||||||
|
const { user, publicApi } = event;
|
||||||
|
|
||||||
|
void this.telemetry.track('API key created', {
|
||||||
|
user_id: user.id,
|
||||||
|
public_api: publicApi,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private publicApiKeyDeleted(event: Event['public-api-key-deleted']) {
|
||||||
|
if (!('publicApi' in event)) return;
|
||||||
|
|
||||||
|
const { user, publicApi } = event;
|
||||||
|
|
||||||
|
void this.telemetry.track('API key deleted', {
|
||||||
|
user_id: user.id,
|
||||||
|
public_api: publicApi,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user