From 9c010c1ce3a04d2afa5aff9f2178146be9206c6a Mon Sep 17 00:00:00 2001 From: Danny Martini Date: Thu, 7 Nov 2024 14:40:49 +0100 Subject: [PATCH] enable selectively listening for a specific webhook --- packages/cli/src/webhooks/test-webhooks.ts | 25 ++++++++++++++++++- packages/cli/src/webhooks/webhook-helpers.ts | 5 ++-- .../workflows/workflow-execution.service.ts | 23 ++++++++++++++--- .../cli/src/workflows/workflow.request.ts | 5 ++++ packages/workflow/src/Interfaces.ts | 1 + 5 files changed, 52 insertions(+), 7 deletions(-) diff --git a/packages/cli/src/webhooks/test-webhooks.ts b/packages/cli/src/webhooks/test-webhooks.ts index bf2fa6c9d8..184d1fd47f 100644 --- a/packages/cli/src/webhooks/test-webhooks.ts +++ b/packages/cli/src/webhooks/test-webhooks.ts @@ -6,6 +6,7 @@ import type { IWorkflowExecuteAdditionalData, IHttpRequestMethods, IRunData, + INode, } from 'n8n-workflow'; import { Service } from 'typedi'; @@ -225,18 +226,23 @@ export class TestWebhooks implements IWebhookManager { runData?: IRunData, pushRef?: string, destinationNode?: string, + webhookNodeName?: string, ) { if (!workflowEntity.id) throw new WorkflowMissingIdError(workflowEntity); const workflow = this.toWorkflow(workflowEntity); - const webhooks = WebhookHelpers.getWorkflowWebhooks( + let webhooks = WebhookHelpers.getWorkflowWebhooks( workflow, additionalData, destinationNode, true, ); + if (webhookNodeName) { + webhooks = webhooks.filter((w) => w.node === webhookNodeName); + } + if (!webhooks.some((w) => w.webhookDescription.restartWebhook !== true)) { return false; // no webhooks found to start a workflow } @@ -309,6 +315,23 @@ export class TestWebhooks implements IWebhookManager { return true; } + /** + * + */ + async isNodeWebhook( + node: INode, + workflowEntity: IWorkflowDb, + additionalData: IWorkflowExecuteAdditionalData, + ) { + if (!workflowEntity.id) throw new WorkflowMissingIdError(workflowEntity); + + const workflow = this.toWorkflow(workflowEntity); + + const webhooks = WebhookHelpers.getWorkflowWebhooks(workflow, additionalData, undefined, true); + + return webhooks.some((w) => w.node === node.name); + } + async cancelWebhook(workflowId: string) { let foundWebhook = false; diff --git a/packages/cli/src/webhooks/webhook-helpers.ts b/packages/cli/src/webhooks/webhook-helpers.ts index 72628b8351..8a06041829 100644 --- a/packages/cli/src/webhooks/webhook-helpers.ts +++ b/packages/cli/src/webhooks/webhook-helpers.ts @@ -87,9 +87,8 @@ export function getWorkflowWebhooks( continue; } - returnData.push.apply( - returnData, - NodeHelpers.getNodeWebhooks(workflow, node, additionalData, ignoreRestartWebhooks), + returnData.push( + ...NodeHelpers.getNodeWebhooks(workflow, node, additionalData, ignoreRestartWebhooks), ); } diff --git a/packages/cli/src/workflows/workflow-execution.service.ts b/packages/cli/src/workflows/workflow-execution.service.ts index 48330dc08a..64fc1f75c9 100644 --- a/packages/cli/src/workflows/workflow-execution.service.ts +++ b/packages/cli/src/workflows/workflow-execution.service.ts @@ -110,7 +110,26 @@ export class WorkflowExecutionService { startNodes?.map((nodeData) => nodeData.name), pinData, ); - console.log('pinnedTrigger', pinnedTrigger); + + // If pinnedTrigger is a webhook + const additionalData = await WorkflowExecuteAdditionalData.getBase(user.id); + if ( + pinnedTrigger && + (await this.testWebhooks.isNodeWebhook(pinnedTrigger, workflowData, additionalData)) + ) { + const needsWebhook = await this.testWebhooks.needsWebhook( + user.id, + workflowData, + additionalData, + runData, + pushRef, + destinationNode, + pinnedTrigger.name, + ); + + if (needsWebhook) return { waitingForWebhook: true }; + } + // If webhooks nodes exist and are active we have to wait for till we receive a call if ( pinnedTrigger === null && @@ -119,8 +138,6 @@ export class WorkflowExecutionService { startNodes.length === 0 || destinationNode === undefined) ) { - const additionalData = await WorkflowExecuteAdditionalData.getBase(user.id); - const needsWebhook = await this.testWebhooks.needsWebhook( user.id, workflowData, diff --git a/packages/cli/src/workflows/workflow.request.ts b/packages/cli/src/workflows/workflow.request.ts index e917cc6655..08745ae9d5 100644 --- a/packages/cli/src/workflows/workflow.request.ts +++ b/packages/cli/src/workflows/workflow.request.ts @@ -22,6 +22,11 @@ export declare namespace WorkflowRequest { runData: IRunData; startNodes?: StartNodeData[]; destinationNode?: string; + /** + * Sending a preferredTrigger will override `startNodes`. The execution + * will start from that trigger and it will always be a full manual + * execution. + */ preferredTrigger?: string; }; diff --git a/packages/workflow/src/Interfaces.ts b/packages/workflow/src/Interfaces.ts index 4f92a219e6..d37f798a1e 100644 --- a/packages/workflow/src/Interfaces.ts +++ b/packages/workflow/src/Interfaces.ts @@ -1968,6 +1968,7 @@ export interface INodeHookDescription { export interface IWebhookData { httpMethod: IHttpRequestMethods; + // TODO: rename to nodeName node: string; path: string; webhookDescription: IWebhookDescription;