n8n
Version:
n8n Workflow Automation Tool
892 lines • 43 kB
JavaScript
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.InternalHooks = void 0;
const typedi_1 = require("typedi");
const change_case_1 = require("change-case");
const node_os_1 = __importDefault(require("node:os"));
const psl_1 = require("psl");
const n8n_workflow_1 = require("n8n-workflow");
const n8n_core_1 = require("n8n-core");
const config_1 = __importDefault(require("./config"));
const constants_1 = require("./constants");
const sharedWorkflow_repository_1 = require("./databases/repositories/sharedWorkflow.repository");
const workflow_repository_1 = require("./databases/repositories/workflow.repository");
const MessageEventBus_1 = require("./eventbus/MessageEventBus/MessageEventBus");
const sharedHookFunctions_1 = require("./executionLifecycleHooks/shared/sharedHookFunctions");
const License_1 = require("./License");
const events_service_1 = require("./services/events.service");
const NodeTypes_1 = require("./NodeTypes");
const telemetry_1 = require("./telemetry");
const projectRelation_repository_1 = require("./databases/repositories/projectRelation.repository");
const sharedCredentials_repository_1 = require("./databases/repositories/sharedCredentials.repository");
function userToPayload(user) {
return {
userId: user.id,
_email: user.email,
_firstName: user.firstName,
_lastName: user.lastName,
globalRole: user.role,
};
}
let InternalHooks = class InternalHooks {
constructor(telemetry, nodeTypes, sharedWorkflowRepository, workflowRepository, eventsService, instanceSettings, eventBus, license, projectRelationRepository, sharedCredentialsRepository) {
this.telemetry = telemetry;
this.nodeTypes = nodeTypes;
this.sharedWorkflowRepository = sharedWorkflowRepository;
this.workflowRepository = workflowRepository;
this.instanceSettings = instanceSettings;
this.eventBus = eventBus;
this.license = license;
this.projectRelationRepository = projectRelationRepository;
this.sharedCredentialsRepository = sharedCredentialsRepository;
eventsService.on('telemetry.onFirstProductionWorkflowSuccess', async (metrics) => await this.onFirstProductionWorkflowSuccess(metrics));
eventsService.on('telemetry.onFirstWorkflowDataLoad', async (metrics) => await this.onFirstWorkflowDataLoad(metrics));
}
async init() {
await this.telemetry.init();
}
async onServerStarted() {
const cpus = node_os_1.default.cpus();
const binaryDataConfig = config_1.default.getEnv('binaryDataManager');
const isS3Selected = config_1.default.getEnv('binaryDataManager.mode') === 's3';
const isS3Available = config_1.default.getEnv('binaryDataManager.availableModes').includes('s3');
const isS3Licensed = this.license.isBinaryDataS3Licensed();
const authenticationMethod = config_1.default.getEnv('userManagement.authenticationMethod');
const info = {
version_cli: constants_1.N8N_VERSION,
db_type: config_1.default.getEnv('database.type'),
n8n_version_notifications_enabled: config_1.default.getEnv('versionNotifications.enabled'),
n8n_disable_production_main_process: config_1.default.getEnv('endpoints.disableProductionWebhooksOnMainProcess'),
system_info: {
os: {
type: node_os_1.default.type(),
version: node_os_1.default.version(),
},
memory: node_os_1.default.totalmem() / 1024,
cpus: {
count: cpus.length,
model: cpus[0].model,
speed: cpus[0].speed,
},
},
execution_variables: {
executions_mode: config_1.default.getEnv('executions.mode'),
executions_timeout: config_1.default.getEnv('executions.timeout'),
executions_timeout_max: config_1.default.getEnv('executions.maxTimeout'),
executions_data_save_on_error: config_1.default.getEnv('executions.saveDataOnError'),
executions_data_save_on_success: config_1.default.getEnv('executions.saveDataOnSuccess'),
executions_data_save_on_progress: config_1.default.getEnv('executions.saveExecutionProgress'),
executions_data_save_manual_executions: config_1.default.getEnv('executions.saveDataManualExecutions'),
executions_data_prune: config_1.default.getEnv('executions.pruneData'),
executions_data_max_age: config_1.default.getEnv('executions.pruneDataMaxAge'),
},
n8n_deployment_type: config_1.default.getEnv('deployment.type'),
n8n_binary_data_mode: binaryDataConfig.mode,
smtp_set_up: config_1.default.getEnv('userManagement.emails.mode') === 'smtp',
ldap_allowed: authenticationMethod === 'ldap',
saml_enabled: authenticationMethod === 'saml',
license_plan_name: this.license.getPlanName(),
license_tenant_id: config_1.default.getEnv('license.tenantId'),
binary_data_s3: isS3Available && isS3Selected && isS3Licensed,
multi_main_setup_enabled: config_1.default.getEnv('multiMainSetup.enabled'),
};
const firstWorkflow = await this.workflowRepository.findOne({
select: ['createdAt'],
order: { createdAt: 'ASC' },
where: {},
});
return await Promise.all([
this.telemetry.identify(info),
this.telemetry.track('Instance started', {
...info,
earliest_workflow_created: firstWorkflow === null || firstWorkflow === void 0 ? void 0 : firstWorkflow.createdAt,
}),
]);
}
async onFrontendSettingsAPI(pushRef) {
return await this.telemetry.track('Session started', { session_id: pushRef });
}
async onPersonalizationSurveySubmitted(userId, answers) {
const camelCaseKeys = Object.keys(answers);
const personalizationSurveyData = { user_id: userId };
camelCaseKeys.forEach((camelCaseKey) => {
personalizationSurveyData[(0, change_case_1.snakeCase)(camelCaseKey)] = answers[camelCaseKey];
});
return await this.telemetry.track('User responded to personalization questions', personalizationSurveyData);
}
async onWorkflowCreated(user, workflow, project, publicApi) {
const { nodeGraph } = n8n_workflow_1.TelemetryHelpers.generateNodesGraph(workflow, this.nodeTypes);
void Promise.all([
this.eventBus.sendAuditEvent({
eventName: 'n8n.audit.workflow.created',
payload: {
...userToPayload(user),
workflowId: workflow.id,
workflowName: workflow.name,
},
}),
this.telemetry.track('User created workflow', {
user_id: user.id,
workflow_id: workflow.id,
node_graph_string: JSON.stringify(nodeGraph),
public_api: publicApi,
project_id: project.id,
project_type: project.type,
}),
]);
}
async onWorkflowDeleted(user, workflowId, publicApi) {
void Promise.all([
this.eventBus.sendAuditEvent({
eventName: 'n8n.audit.workflow.deleted',
payload: {
...userToPayload(user),
workflowId,
},
}),
this.telemetry.track('User deleted workflow', {
user_id: user.id,
workflow_id: workflowId,
public_api: publicApi,
}),
]);
}
async onWorkflowSaved(user, workflow, publicApi) {
var _a, _b;
const isCloudDeployment = config_1.default.getEnv('deployment.type') === 'cloud';
const { nodeGraph } = n8n_workflow_1.TelemetryHelpers.generateNodesGraph(workflow, this.nodeTypes, {
isCloudDeployment,
});
let userRole = undefined;
const role = await this.sharedWorkflowRepository.findSharingRole(user.id, workflow.id);
if (role) {
userRole = role === 'workflow:owner' ? 'owner' : 'sharee';
}
else {
const workflowOwner = await this.sharedWorkflowRepository.getWorkflowOwningProject(workflow.id);
if (workflowOwner) {
const projectRole = await this.projectRelationRepository.findProjectRole({
userId: user.id,
projectId: workflowOwner.id,
});
if (projectRole && projectRole !== 'project:personalOwner') {
userRole = 'member';
}
}
}
const notesCount = Object.keys(nodeGraph.notes).length;
const overlappingCount = Object.values(nodeGraph.notes).filter((note) => note.overlapping).length;
void Promise.all([
this.eventBus.sendAuditEvent({
eventName: 'n8n.audit.workflow.updated',
payload: {
...userToPayload(user),
workflowId: workflow.id,
workflowName: workflow.name,
},
}),
this.telemetry.track('User saved workflow', {
user_id: user.id,
workflow_id: workflow.id,
node_graph_string: JSON.stringify(nodeGraph),
notes_count_overlapping: overlappingCount,
notes_count_non_overlapping: notesCount - overlappingCount,
version_cli: constants_1.N8N_VERSION,
num_tags: (_b = (_a = workflow.tags) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0,
public_api: publicApi,
sharing_role: userRole,
}),
]);
}
async onNodeBeforeExecute(executionId, workflow, nodeName) {
var _a;
const nodeInWorkflow = workflow.nodes.find((node) => node.name === nodeName);
void this.eventBus.sendNodeEvent({
eventName: 'n8n.node.started',
payload: {
executionId,
nodeName,
workflowId: (_a = workflow.id) === null || _a === void 0 ? void 0 : _a.toString(),
workflowName: workflow.name,
nodeType: nodeInWorkflow === null || nodeInWorkflow === void 0 ? void 0 : nodeInWorkflow.type,
},
});
}
async onNodePostExecute(executionId, workflow, nodeName) {
var _a;
const nodeInWorkflow = workflow.nodes.find((node) => node.name === nodeName);
void this.eventBus.sendNodeEvent({
eventName: 'n8n.node.finished',
payload: {
executionId,
nodeName,
workflowId: (_a = workflow.id) === null || _a === void 0 ? void 0 : _a.toString(),
workflowName: workflow.name,
nodeType: nodeInWorkflow === null || nodeInWorkflow === void 0 ? void 0 : nodeInWorkflow.type,
},
});
}
async onWorkflowBeforeExecute(executionId, data) {
var _a, _b, _c;
let payload;
if ('executionData' in data) {
payload = {
executionId,
userId: (_a = data.userId) !== null && _a !== void 0 ? _a : undefined,
workflowId: (_b = data.workflowData.id) === null || _b === void 0 ? void 0 : _b.toString(),
isManual: data.executionMode === 'manual',
workflowName: data.workflowData.name,
};
}
else {
payload = {
executionId,
userId: undefined,
workflowId: (_c = data.id) === null || _c === void 0 ? void 0 : _c.toString(),
isManual: false,
workflowName: data.name,
};
}
void this.eventBus.sendWorkflowEvent({
eventName: 'n8n.workflow.started',
payload,
});
}
async onWorkflowCrashed(executionId, executionMode, workflowData, executionMetadata) {
var _a;
let metaData;
try {
if (executionMetadata) {
metaData = executionMetadata.reduce((acc, meta) => {
return { ...acc, [meta.key]: meta.value };
}, {});
}
}
catch { }
void Promise.all([
this.eventBus.sendWorkflowEvent({
eventName: 'n8n.workflow.crashed',
payload: {
executionId,
isManual: executionMode === 'manual',
workflowId: (_a = workflowData === null || workflowData === void 0 ? void 0 : workflowData.id) === null || _a === void 0 ? void 0 : _a.toString(),
workflowName: workflowData === null || workflowData === void 0 ? void 0 : workflowData.name,
metaData,
},
}),
]);
}
async onWorkflowPostExecute(executionId, workflow, runData, userId) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
if (!workflow.id) {
return;
}
if ((runData === null || runData === void 0 ? void 0 : runData.status) === 'waiting') {
return;
}
const promises = [];
const telemetryProperties = {
workflow_id: workflow.id,
is_manual: false,
version_cli: constants_1.N8N_VERSION,
success: false,
};
if (userId) {
telemetryProperties.user_id = userId;
}
if ((_b = (_a = runData === null || runData === void 0 ? void 0 : runData.data.resultData.error) === null || _a === void 0 ? void 0 : _a.message) === null || _b === void 0 ? void 0 : _b.includes('canceled')) {
runData.status = 'canceled';
}
telemetryProperties.success = !!(runData === null || runData === void 0 ? void 0 : runData.finished);
const executionStatus = runData
? (0, sharedHookFunctions_1.determineFinalExecutionStatus)(runData)
: 'unknown';
if (runData !== undefined) {
telemetryProperties.execution_mode = runData.mode;
telemetryProperties.is_manual = runData.mode === 'manual';
let nodeGraphResult = null;
if (!telemetryProperties.success && (runData === null || runData === void 0 ? void 0 : runData.data.resultData.error)) {
telemetryProperties.error_message = runData === null || runData === void 0 ? void 0 : runData.data.resultData.error.message;
let errorNodeName = 'node' in (runData === null || runData === void 0 ? void 0 : runData.data.resultData.error)
? (_c = runData === null || runData === void 0 ? void 0 : runData.data.resultData.error.node) === null || _c === void 0 ? void 0 : _c.name
: undefined;
telemetryProperties.error_node_type =
'node' in (runData === null || runData === void 0 ? void 0 : runData.data.resultData.error)
? (_d = runData === null || runData === void 0 ? void 0 : runData.data.resultData.error.node) === null || _d === void 0 ? void 0 : _d.type
: undefined;
if (runData.data.resultData.lastNodeExecuted) {
const lastNode = n8n_workflow_1.TelemetryHelpers.getNodeTypeForName(workflow, runData.data.resultData.lastNodeExecuted);
if (lastNode !== undefined) {
telemetryProperties.error_node_type = lastNode.type;
errorNodeName = lastNode.name;
}
}
if (telemetryProperties.is_manual) {
nodeGraphResult = n8n_workflow_1.TelemetryHelpers.generateNodesGraph(workflow, this.nodeTypes);
telemetryProperties.node_graph = nodeGraphResult.nodeGraph;
telemetryProperties.node_graph_string = JSON.stringify(nodeGraphResult.nodeGraph);
if (errorNodeName) {
telemetryProperties.error_node_id = nodeGraphResult.nameIndices[errorNodeName];
}
}
}
if (telemetryProperties.is_manual) {
if (!nodeGraphResult) {
nodeGraphResult = n8n_workflow_1.TelemetryHelpers.generateNodesGraph(workflow, this.nodeTypes);
}
let userRole = undefined;
if (userId) {
const role = await this.sharedWorkflowRepository.findSharingRole(userId, workflow.id);
if (role) {
userRole = role === 'workflow:owner' ? 'owner' : 'sharee';
}
}
const manualExecEventProperties = {
user_id: userId,
workflow_id: workflow.id,
status: executionStatus,
executionStatus: (_e = runData === null || runData === void 0 ? void 0 : runData.status) !== null && _e !== void 0 ? _e : 'unknown',
error_message: telemetryProperties.error_message,
error_node_type: telemetryProperties.error_node_type,
node_graph_string: telemetryProperties.node_graph_string,
error_node_id: telemetryProperties.error_node_id,
webhook_domain: null,
sharing_role: userRole,
};
if (!manualExecEventProperties.node_graph_string) {
nodeGraphResult = n8n_workflow_1.TelemetryHelpers.generateNodesGraph(workflow, this.nodeTypes);
manualExecEventProperties.node_graph_string = JSON.stringify(nodeGraphResult.nodeGraph);
}
if ((_f = runData.data.startData) === null || _f === void 0 ? void 0 : _f.destinationNode) {
const telemetryPayload = {
...manualExecEventProperties,
node_type: (_h = n8n_workflow_1.TelemetryHelpers.getNodeTypeForName(workflow, (_g = runData.data.startData) === null || _g === void 0 ? void 0 : _g.destinationNode)) === null || _h === void 0 ? void 0 : _h.type,
node_id: nodeGraphResult.nameIndices[(_j = runData.data.startData) === null || _j === void 0 ? void 0 : _j.destinationNode],
};
promises.push(this.telemetry.track('Manual node exec finished', telemetryPayload));
}
else {
nodeGraphResult.webhookNodeNames.forEach((name) => {
var _a, _b, _c, _d, _e, _f, _g;
const execJson = (_f = (_e = (_d = (_c = (_b = (_a = runData.data.resultData.runData[name]) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.main) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.json;
if (((_g = execJson === null || execJson === void 0 ? void 0 : execJson.headers) === null || _g === void 0 ? void 0 : _g.origin) && execJson.headers.origin !== '') {
manualExecEventProperties.webhook_domain = (0, psl_1.get)(execJson.headers.origin.replace(/^https?:\/\//, ''));
}
});
promises.push(this.telemetry.track('Manual workflow exec finished', manualExecEventProperties));
}
}
}
const sharedEventPayload = {
executionId,
success: telemetryProperties.success,
userId: telemetryProperties.user_id,
workflowId: workflow.id,
isManual: telemetryProperties.is_manual,
workflowName: workflow.name,
metaData: (_l = (_k = runData === null || runData === void 0 ? void 0 : runData.data) === null || _k === void 0 ? void 0 : _k.resultData) === null || _l === void 0 ? void 0 : _l.metadata,
};
let event;
if (telemetryProperties.success) {
event = this.eventBus.sendWorkflowEvent({
eventName: 'n8n.workflow.success',
payload: sharedEventPayload,
});
}
else {
event = this.eventBus.sendWorkflowEvent({
eventName: 'n8n.workflow.failed',
payload: {
...sharedEventPayload,
lastNodeExecuted: runData === null || runData === void 0 ? void 0 : runData.data.resultData.lastNodeExecuted,
errorNodeType: telemetryProperties.error_node_type,
errorNodeId: (_m = telemetryProperties.error_node_id) === null || _m === void 0 ? void 0 : _m.toString(),
errorMessage: (_o = telemetryProperties.error_message) === null || _o === void 0 ? void 0 : _o.toString(),
},
});
}
promises.push(event);
void Promise.all([...promises, this.telemetry.trackWorkflowExecution(telemetryProperties)]);
}
async onWorkflowSharingUpdate(workflowId, userId, userList) {
const properties = {
workflow_id: workflowId,
user_id_sharer: userId,
user_id_list: userList,
};
return await this.telemetry.track('User updated workflow sharing', properties);
}
async onN8nStop() {
const timeoutPromise = new Promise((resolve) => {
setTimeout(() => {
resolve();
}, 3000);
});
return await Promise.race([timeoutPromise, this.telemetry.trackN8nStop()]);
}
async onUserDeletion(userDeletionData) {
void Promise.all([
this.eventBus.sendAuditEvent({
eventName: 'n8n.audit.user.deleted',
payload: {
...userToPayload(userDeletionData.user),
},
}),
this.telemetry.track('User deleted user', {
...userDeletionData.telemetryData,
user_id: userDeletionData.user.id,
public_api: userDeletionData.publicApi,
}),
]);
}
async onUserInvite(userInviteData) {
void Promise.all([
this.eventBus.sendAuditEvent({
eventName: 'n8n.audit.user.invited',
payload: {
...userToPayload(userInviteData.user),
targetUserId: userInviteData.target_user_id,
},
}),
this.telemetry.track('User invited new user', {
user_id: userInviteData.user.id,
target_user_id: userInviteData.target_user_id,
public_api: userInviteData.public_api,
email_sent: userInviteData.email_sent,
invitee_role: userInviteData.invitee_role,
}),
]);
}
async onUserRoleChange(userRoleChangeData) {
const { user, ...rest } = userRoleChangeData;
void this.telemetry.track('User changed role', { user_id: user.id, ...rest });
}
async onUserReinvite(userReinviteData) {
void Promise.all([
this.eventBus.sendAuditEvent({
eventName: 'n8n.audit.user.reinvited',
payload: {
...userToPayload(userReinviteData.user),
targetUserId: userReinviteData.target_user_id,
},
}),
this.telemetry.track('User resent new user invite email', {
user_id: userReinviteData.user.id,
target_user_id: userReinviteData.target_user_id,
public_api: userReinviteData.public_api,
}),
]);
}
async onUserRetrievedUser(userRetrievedData) {
return await this.telemetry.track('User retrieved user', userRetrievedData);
}
async onUserRetrievedAllUsers(userRetrievedData) {
return await this.telemetry.track('User retrieved all users', userRetrievedData);
}
async onUserRetrievedExecution(userRetrievedData) {
return await this.telemetry.track('User retrieved execution', userRetrievedData);
}
async onUserRetrievedAllExecutions(userRetrievedData) {
return await this.telemetry.track('User retrieved all executions', userRetrievedData);
}
async onUserRetrievedWorkflow(userRetrievedData) {
return await this.telemetry.track('User retrieved workflow', userRetrievedData);
}
async onUserRetrievedAllWorkflows(userRetrievedData) {
return await this.telemetry.track('User retrieved all workflows', userRetrievedData);
}
async onUserUpdate(userUpdateData) {
void Promise.all([
this.eventBus.sendAuditEvent({
eventName: 'n8n.audit.user.updated',
payload: {
...userToPayload(userUpdateData.user),
fieldsChanged: userUpdateData.fields_changed,
},
}),
this.telemetry.track('User changed personal settings', {
user_id: userUpdateData.user.id,
fields_changed: userUpdateData.fields_changed,
}),
]);
}
async onUserInviteEmailClick(userInviteClickData) {
void Promise.all([
this.eventBus.sendAuditEvent({
eventName: 'n8n.audit.user.invitation.accepted',
payload: {
invitee: {
...userToPayload(userInviteClickData.invitee),
},
inviter: {
...userToPayload(userInviteClickData.inviter),
},
},
}),
this.telemetry.track('User clicked invite link from email', {
user_id: userInviteClickData.invitee.id,
}),
]);
}
async onUserPasswordResetEmailClick(userPasswordResetData) {
void Promise.all([
this.eventBus.sendAuditEvent({
eventName: 'n8n.audit.user.reset',
payload: {
...userToPayload(userPasswordResetData.user),
},
}),
this.telemetry.track('User clicked password reset link from email', {
user_id: userPasswordResetData.user.id,
}),
]);
}
async onUserTransactionalEmail(userTransactionalEmailData) {
return await this.telemetry.track('Instance sent transactional email to user', userTransactionalEmailData);
}
async onUserInvokedApi(userInvokedApiData) {
return await this.telemetry.track('User invoked API', userInvokedApiData);
}
async onApiKeyDeleted(apiKeyDeletedData) {
void Promise.all([
this.eventBus.sendAuditEvent({
eventName: 'n8n.audit.user.api.deleted',
payload: {
...userToPayload(apiKeyDeletedData.user),
},
}),
this.telemetry.track('API key deleted', {
user_id: apiKeyDeletedData.user.id,
public_api: apiKeyDeletedData.public_api,
}),
]);
}
async onApiKeyCreated(apiKeyCreatedData) {
void Promise.all([
this.eventBus.sendAuditEvent({
eventName: 'n8n.audit.user.api.created',
payload: {
...userToPayload(apiKeyCreatedData.user),
},
}),
this.telemetry.track('API key created', {
user_id: apiKeyCreatedData.user.id,
public_api: apiKeyCreatedData.public_api,
}),
]);
}
async onUserPasswordResetRequestClick(userPasswordResetData) {
void Promise.all([
this.eventBus.sendAuditEvent({
eventName: 'n8n.audit.user.reset.requested',
payload: {
...userToPayload(userPasswordResetData.user),
},
}),
this.telemetry.track('User requested password reset while logged out', {
user_id: userPasswordResetData.user.id,
}),
]);
}
async onInstanceOwnerSetup(instanceOwnerSetupData) {
return await this.telemetry.track('Owner finished instance setup', instanceOwnerSetupData);
}
async onUserSignup(user, userSignupData) {
void Promise.all([
this.eventBus.sendAuditEvent({
eventName: 'n8n.audit.user.signedup',
payload: {
...userToPayload(user),
},
}),
this.telemetry.track('User signed up', {
user_id: user.id,
...userSignupData,
}),
]);
}
async onEmailFailed(failedEmailData) {
void Promise.all([
this.eventBus.sendAuditEvent({
eventName: 'n8n.audit.user.email.failed',
payload: {
messageType: failedEmailData.message_type,
...userToPayload(failedEmailData.user),
},
}),
this.telemetry.track('Instance failed to send transactional email to user', {
user_id: failedEmailData.user.id,
}),
]);
}
async onUserLoginSuccess(userLoginData) {
void Promise.all([
this.eventBus.sendAuditEvent({
eventName: 'n8n.audit.user.login.success',
payload: {
authenticationMethod: userLoginData.authenticationMethod,
...userToPayload(userLoginData.user),
},
}),
]);
}
async onUserLoginFailed(userLoginData) {
void Promise.all([
this.eventBus.sendAuditEvent({
eventName: 'n8n.audit.user.login.failed',
payload: {
authenticationMethod: userLoginData.authenticationMethod,
user: userLoginData.user,
reason: userLoginData.reason,
},
}),
]);
}
async onUserCreatedCredentials(userCreatedCredentialsData) {
const project = await this.sharedCredentialsRepository.findCredentialOwningProject(userCreatedCredentialsData.credential_id);
void Promise.all([
this.eventBus.sendAuditEvent({
eventName: 'n8n.audit.user.credentials.created',
payload: {
...userToPayload(userCreatedCredentialsData.user),
credentialName: userCreatedCredentialsData.credential_name,
credentialType: userCreatedCredentialsData.credential_type,
credentialId: userCreatedCredentialsData.credential_id,
},
}),
this.telemetry.track('User created credentials', {
user_id: userCreatedCredentialsData.user.id,
credential_type: userCreatedCredentialsData.credential_type,
credential_id: userCreatedCredentialsData.credential_id,
instance_id: this.instanceSettings.instanceId,
project_id: project === null || project === void 0 ? void 0 : project.id,
project_type: project === null || project === void 0 ? void 0 : project.type,
}),
]);
}
async onUserSharedCredentials(userSharedCredentialsData) {
void Promise.all([
this.eventBus.sendAuditEvent({
eventName: 'n8n.audit.user.credentials.shared',
payload: {
...userToPayload(userSharedCredentialsData.user),
credentialName: userSharedCredentialsData.credential_name,
credentialType: userSharedCredentialsData.credential_type,
credentialId: userSharedCredentialsData.credential_id,
userIdSharer: userSharedCredentialsData.user_id_sharer,
userIdsShareesAdded: userSharedCredentialsData.user_ids_sharees_added,
shareesRemoved: userSharedCredentialsData.sharees_removed,
},
}),
this.telemetry.track('User updated cred sharing', {
user_id: userSharedCredentialsData.user.id,
credential_type: userSharedCredentialsData.credential_type,
credential_id: userSharedCredentialsData.credential_id,
user_id_sharer: userSharedCredentialsData.user_id_sharer,
user_ids_sharees_added: userSharedCredentialsData.user_ids_sharees_added,
sharees_removed: userSharedCredentialsData.sharees_removed,
instance_id: this.instanceSettings.instanceId,
}),
]);
}
async onUserUpdatedCredentials(userUpdatedCredentialsData) {
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) {
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,
}),
]);
}
async onCommunityPackageInstallFinished(installationData) {
void Promise.all([
this.eventBus.sendAuditEvent({
eventName: 'n8n.audit.package.installed',
payload: {
...userToPayload(installationData.user),
inputString: installationData.input_string,
packageName: installationData.package_name,
success: installationData.success,
packageVersion: installationData.package_version,
packageNodeNames: installationData.package_node_names,
packageAuthor: installationData.package_author,
packageAuthorEmail: installationData.package_author_email,
failureReason: installationData.failure_reason,
},
}),
this.telemetry.track('cnr package install finished', {
user_id: installationData.user.id,
input_string: installationData.input_string,
package_name: installationData.package_name,
success: installationData.success,
package_version: installationData.package_version,
package_node_names: installationData.package_node_names,
package_author: installationData.package_author,
package_author_email: installationData.package_author_email,
failure_reason: installationData.failure_reason,
}),
]);
}
async onCommunityPackageUpdateFinished(updateData) {
void Promise.all([
this.eventBus.sendAuditEvent({
eventName: 'n8n.audit.package.updated',
payload: {
...userToPayload(updateData.user),
packageName: updateData.package_name,
packageVersionCurrent: updateData.package_version_current,
packageVersionNew: updateData.package_version_new,
packageNodeNames: updateData.package_node_names,
packageAuthor: updateData.package_author,
packageAuthorEmail: updateData.package_author_email,
},
}),
this.telemetry.track('cnr package updated', {
user_id: updateData.user.id,
package_name: updateData.package_name,
package_version_current: updateData.package_version_current,
package_version_new: updateData.package_version_new,
package_node_names: updateData.package_node_names,
package_author: updateData.package_author,
package_author_email: updateData.package_author_email,
}),
]);
}
async onCommunityPackageDeleteFinished(deleteData) {
void Promise.all([
this.eventBus.sendAuditEvent({
eventName: 'n8n.audit.package.deleted',
payload: {
...userToPayload(deleteData.user),
packageName: deleteData.package_name,
packageVersion: deleteData.package_version,
packageNodeNames: deleteData.package_node_names,
packageAuthor: deleteData.package_author,
packageAuthorEmail: deleteData.package_author_email,
},
}),
this.telemetry.track('cnr package deleted', {
user_id: deleteData.user.id,
package_name: deleteData.package_name,
package_version: deleteData.package_version,
package_node_names: deleteData.package_node_names,
package_author: deleteData.package_author,
package_author_email: deleteData.package_author_email,
}),
]);
}
async onLdapSyncFinished(data) {
return await this.telemetry.track('Ldap general sync finished', data);
}
async onUserUpdatedLdapSettings(data) {
return await this.telemetry.track('Ldap general sync finished', data);
}
async onLdapLoginSyncFailed(data) {
return await this.telemetry.track('Ldap login sync failed', data);
}
async userLoginFailedDueToLdapDisabled(data) {
return await this.telemetry.track('User login failed since ldap disabled', data);
}
async onFirstProductionWorkflowSuccess(data) {
return await this.telemetry.track('Workflow first prod success', data);
}
async onFirstWorkflowDataLoad(data) {
return await this.telemetry.track('Workflow first data fetched', data);
}
async onLicenseRenewAttempt(data) {
await this.telemetry.track('Instance attempted to refresh license', data);
}
async onAuditGeneratedViaCli() {
return await this.telemetry.track('Instance generated security audit via CLI command');
}
async onVariableCreated(createData) {
return await this.telemetry.track('User created variable', createData);
}
async onSourceControlSettingsUpdated(data) {
return await this.telemetry.track('User updated source control settings', data);
}
async onSourceControlUserStartedPullUI(data) {
return await this.telemetry.track('User started pull via UI', data);
}
async onSourceControlUserFinishedPullUI(data) {
return await this.telemetry.track('User finished pull via UI', {
workflow_updates: data.workflow_updates,
});
}
async onSourceControlUserPulledAPI(data) {
return await this.telemetry.track('User pulled via API', data);
}
async onSourceControlUserStartedPushUI(data) {
return await this.telemetry.track('User started push via UI', data);
}
async onSourceControlUserFinishedPushUI(data) {
return await this.telemetry.track('User finished push via UI', data);
}
async onExternalSecretsProviderSettingsSaved(saveData) {
return await this.telemetry.track('User updated external secrets settings', saveData);
}
async onTeamProjectCreated(data) {
return await this.telemetry.track('User created project', data);
}
async onTeamProjectDeleted(data) {
return await this.telemetry.track('User deleted project', data);
}
async onTeamProjectUpdated(data) {
return await this.telemetry.track('Project settings updated', data);
}
};
exports.InternalHooks = InternalHooks;
exports.InternalHooks = InternalHooks = __decorate([
(0, typedi_1.Service)(),
__metadata("design:paramtypes", [telemetry_1.Telemetry,
NodeTypes_1.NodeTypes,
sharedWorkflow_repository_1.SharedWorkflowRepository,
workflow_repository_1.WorkflowRepository,
events_service_1.EventsService,
n8n_core_1.InstanceSettings,
MessageEventBus_1.MessageEventBus,
License_1.License,
projectRelation_repository_1.ProjectRelationRepository,
sharedCredentials_repository_1.SharedCredentialsRepository])
], InternalHooks);
//# sourceMappingURL=InternalHooks.js.map