enable selectively listening for a specific webhook

This commit is contained in:
Danny Martini 2024-11-07 14:40:49 +01:00
parent 105b5fe6e4
commit 9c010c1ce3
No known key found for this signature in database
5 changed files with 52 additions and 7 deletions

View file

@ -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;

View file

@ -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),
);
}

View file

@ -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,

View file

@ -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;
};

View file

@ -1968,6 +1968,7 @@ export interface INodeHookDescription {
export interface IWebhookData {
httpMethod: IHttpRequestMethods;
// TODO: rename to nodeName
node: string;
path: string;
webhookDescription: IWebhookDescription;