n8n
Version:
n8n Workflow Automation Tool
225 lines • 12 kB
JavaScript
"use strict";
const api_types_1 = require("@n8n/api-types");
const config_1 = require("@n8n/config");
const di_1 = require("@n8n/di");
const n8n_workflow_1 = require("n8n-workflow");
const aborted_execution_retry_error_1 = require("../../../../errors/aborted-execution-retry.error");
const missing_execution_stop_error_1 = require("../../../../errors/missing-execution-stop.error");
const queued_execution_retry_error_1 = require("../../../../errors/queued-execution-retry.error");
const conflict_error_1 = require("../../../../errors/response-errors/conflict.error");
const not_found_error_1 = require("../../../../errors/response-errors/not-found.error");
const event_service_1 = require("../../../../events/event.service");
const execution_redaction_proxy_service_1 = require("../../../../executions/execution-redaction-proxy.service");
const execution_service_1 = require("../../../../executions/execution.service");
const workflow_sharing_service_1 = require("../../../../workflows/workflow-sharing.service");
const global_middleware_1 = require("../../shared/middlewares/global.middleware");
const pagination_service_1 = require("../../shared/services/pagination.service");
const handleError = (error) => {
if (error instanceof queued_execution_retry_error_1.QueuedExecutionRetryError || error instanceof aborted_execution_retry_error_1.AbortedExecutionRetryError) {
throw new conflict_error_1.ConflictError(error.message);
}
if (error instanceof missing_execution_stop_error_1.MissingExecutionStopError) {
throw new not_found_error_1.NotFoundError(error.message);
}
throw error;
};
function isRedactableExecution(execution) {
return 'data' in execution && 'workflowData' in execution;
}
const executionHandlers = {
deleteExecution: [
(0, global_middleware_1.publicApiScope)('execution:delete'),
async (req, res) => {
const sharedWorkflowsIds = await di_1.Container.get(workflow_sharing_service_1.WorkflowSharingService).getSharedWorkflowIdsForScopes(req.user, ['workflow:delete']);
if (!sharedWorkflowsIds.length) {
throw new not_found_error_1.NotFoundError('Not Found');
}
const { id } = req.params;
const execution = await di_1.Container.get(execution_service_1.ExecutionService).deleteOne(id, sharedWorkflowsIds);
return res.json((0, n8n_workflow_1.replaceCircularReferences)({ ...execution, id }));
},
],
getExecution: [
(0, global_middleware_1.publicApiScope)('execution:read'),
async (req, res) => {
const sharedWorkflowsIds = await di_1.Container.get(workflow_sharing_service_1.WorkflowSharingService).getSharedWorkflowIdsForScopes(req.user, ['workflow:read']);
if (!sharedWorkflowsIds.length) {
throw new not_found_error_1.NotFoundError('Not Found');
}
const { id } = req.params;
const { includeData = false, ignoreDataSizeLimit = false } = req.query;
const maxDataSizeBytes = ignoreDataSizeLimit
? 0
: di_1.Container.get(config_1.ExecutionsConfig).maxDisplaySize;
const execution = await di_1.Container.get(execution_service_1.ExecutionService).findOneInWorkflows(id, sharedWorkflowsIds, {
includeData,
includeAnnotation: false,
maxDataSizeBytes,
});
if (!execution) {
throw new not_found_error_1.NotFoundError('Not Found');
}
if (includeData && isRedactableExecution(execution)) {
const redactQuery = api_types_1.ExecutionRedactionQueryDtoSchema.safeParse(req.query);
const redactExecutionData = redactQuery.success
? redactQuery.data.redactExecutionData
: undefined;
await di_1.Container.get(execution_redaction_proxy_service_1.ExecutionRedactionServiceProxy).processExecution(execution, {
user: req.user,
redactExecutionData,
ipAddress: req.ip ?? '',
userAgent: req.headers['user-agent'] ?? '',
});
}
di_1.Container.get(event_service_1.EventService).emit('user-retrieved-execution', {
userId: req.user.id,
publicApi: true,
});
return res.json((0, n8n_workflow_1.replaceCircularReferences)(execution));
},
],
getExecutions: [
(0, global_middleware_1.publicApiScope)('execution:list'),
global_middleware_1.validCursor,
async (req, res) => {
const { lastId = undefined, limit = 100, status = undefined, includeData = false, ignoreDataSizeLimit = false, workflowId = undefined, projectId, } = req.query;
const sharedWorkflowsIds = await di_1.Container.get(workflow_sharing_service_1.WorkflowSharingService).getSharedWorkflowIdsForScopes(req.user, ['workflow:read'], projectId);
if (!sharedWorkflowsIds.length || (workflowId && !sharedWorkflowsIds.includes(workflowId))) {
return res.status(200).json({ data: [], nextCursor: null });
}
const { executions, count } = await di_1.Container.get(execution_service_1.ExecutionService).findManyAndCount(workflowId ? [workflowId] : sharedWorkflowsIds, {
status,
limit,
lastId,
includeData,
excludeRunning: status !== 'running',
maxDataSizeBytes: ignoreDataSizeLimit
? 0
: di_1.Container.get(config_1.ExecutionsConfig).maxDisplaySize,
});
const newLastId = executions.length === 0 ? '0' : executions.at(-1).id;
if (includeData) {
const redactQuery = api_types_1.ExecutionRedactionQueryDtoSchema.safeParse(req.query);
const redactExecutionData = redactQuery.success
? redactQuery.data.redactExecutionData
: undefined;
const redactableExecutions = executions.filter(isRedactableExecution);
await di_1.Container.get(execution_redaction_proxy_service_1.ExecutionRedactionServiceProxy).processExecutions(redactableExecutions, {
user: req.user,
redactExecutionData,
ipAddress: req.ip ?? '',
userAgent: req.headers['user-agent'] ?? '',
});
}
di_1.Container.get(event_service_1.EventService).emit('user-retrieved-all-executions', {
userId: req.user.id,
publicApi: true,
});
return res.json({
data: (0, n8n_workflow_1.replaceCircularReferences)(executions),
nextCursor: (0, pagination_service_1.encodeNextCursor)({
lastId: newLastId,
limit,
numberOfNextRecords: count,
}),
});
},
],
retryExecution: [
(0, global_middleware_1.publicApiScope)('execution:retry'),
async (req, res) => {
const sharedWorkflowsIds = await di_1.Container.get(workflow_sharing_service_1.WorkflowSharingService).getSharedWorkflowIdsForScopes(req.user, ['workflow:execute']);
if (!sharedWorkflowsIds.length) {
throw new not_found_error_1.NotFoundError('Not Found');
}
try {
const retriedExecution = await di_1.Container.get(execution_service_1.ExecutionService).retry(req, sharedWorkflowsIds);
di_1.Container.get(event_service_1.EventService).emit('user-retried-execution', {
userId: req.user.id,
publicApi: true,
});
return res.json((0, n8n_workflow_1.replaceCircularReferences)(retriedExecution));
}
catch (error) {
return handleError(error);
}
},
],
getExecutionTags: [
(0, global_middleware_1.publicApiScope)('executionTags:list'),
async (req, res) => {
const sharedWorkflowsIds = await di_1.Container.get(workflow_sharing_service_1.WorkflowSharingService).getSharedWorkflowIdsForScopes(req.user, ['workflow:read']);
if (!sharedWorkflowsIds.length) {
throw new not_found_error_1.NotFoundError('Not Found');
}
const tags = await di_1.Container.get(execution_service_1.ExecutionService).getExecutionTags(req.params.id, sharedWorkflowsIds);
return res.json(tags);
},
],
updateExecutionTags: [
(0, global_middleware_1.publicApiScope)('executionTags:update'),
async (req, res) => {
const newTagIds = req.body.map((tag) => tag.id);
const sharedWorkflowsIds = await di_1.Container.get(workflow_sharing_service_1.WorkflowSharingService).getSharedWorkflowIdsForScopes(req.user, ['workflow:update']);
if (!sharedWorkflowsIds.length) {
throw new not_found_error_1.NotFoundError('Not Found');
}
try {
const tags = await di_1.Container.get(execution_service_1.ExecutionService).updateExecutionTags(req.params.id, newTagIds, sharedWorkflowsIds);
return res.json(tags);
}
catch (error) {
return handleError(error);
}
},
],
stopExecution: [
(0, global_middleware_1.publicApiScope)('execution:stop'),
async (req, res) => {
const sharedWorkflowsIds = await di_1.Container.get(workflow_sharing_service_1.WorkflowSharingService).getSharedWorkflowIdsForScopes(req.user, ['workflow:execute']);
if (!sharedWorkflowsIds.length) {
throw new not_found_error_1.NotFoundError('Not Found');
}
const { id } = req.params;
try {
const stopResult = await di_1.Container.get(execution_service_1.ExecutionService).stop(id, sharedWorkflowsIds);
return res.json((0, n8n_workflow_1.replaceCircularReferences)(stopResult));
}
catch (error) {
return handleError(error);
}
},
],
stopManyExecutions: [
(0, global_middleware_1.publicApiScope)('execution:stop'),
async (req, res) => {
const { status: rawStatus, workflowId, startedAfter, startedBefore } = req.body;
const status = rawStatus.map((x) => (x === 'queued' ? 'new' : x));
if (!status || status.length === 0) {
return res.status(400).json({
message: 'Status filter is required. Please provide at least one status to stop executions.',
example: {
status: ['running', 'waiting', 'queued'],
},
});
}
const sharedWorkflowsIds = await di_1.Container.get(workflow_sharing_service_1.WorkflowSharingService).getSharedWorkflowIdsForScopes(req.user, ['workflow:execute']);
if (!sharedWorkflowsIds.length) {
return res.json({ stopped: 0 });
}
if (workflowId && workflowId !== 'all' && !sharedWorkflowsIds.includes(workflowId)) {
throw new not_found_error_1.NotFoundError('Workflow not found or not accessible');
}
const filter = {
workflowId: workflowId ?? 'all',
status,
startedAfter,
startedBefore,
};
const stopped = await di_1.Container.get(execution_service_1.ExecutionService).stopMany(filter, sharedWorkflowsIds);
return res.json({ stopped });
},
],
};
module.exports = executionHandlers;
//# sourceMappingURL=executions.handler.js.map