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, IWorkflowExecuteAdditionalData,
IHttpRequestMethods, IHttpRequestMethods,
IRunData, IRunData,
INode,
} from 'n8n-workflow'; } from 'n8n-workflow';
import { Service } from 'typedi'; import { Service } from 'typedi';
@ -225,18 +226,23 @@ export class TestWebhooks implements IWebhookManager {
runData?: IRunData, runData?: IRunData,
pushRef?: string, pushRef?: string,
destinationNode?: string, destinationNode?: string,
webhookNodeName?: string,
) { ) {
if (!workflowEntity.id) throw new WorkflowMissingIdError(workflowEntity); if (!workflowEntity.id) throw new WorkflowMissingIdError(workflowEntity);
const workflow = this.toWorkflow(workflowEntity); const workflow = this.toWorkflow(workflowEntity);
const webhooks = WebhookHelpers.getWorkflowWebhooks( let webhooks = WebhookHelpers.getWorkflowWebhooks(
workflow, workflow,
additionalData, additionalData,
destinationNode, destinationNode,
true, true,
); );
if (webhookNodeName) {
webhooks = webhooks.filter((w) => w.node === webhookNodeName);
}
if (!webhooks.some((w) => w.webhookDescription.restartWebhook !== true)) { if (!webhooks.some((w) => w.webhookDescription.restartWebhook !== true)) {
return false; // no webhooks found to start a workflow return false; // no webhooks found to start a workflow
} }
@ -309,6 +315,23 @@ export class TestWebhooks implements IWebhookManager {
return true; 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) { async cancelWebhook(workflowId: string) {
let foundWebhook = false; let foundWebhook = false;

View file

@ -87,9 +87,8 @@ export function getWorkflowWebhooks(
continue; continue;
} }
returnData.push.apply( returnData.push(
returnData, ...NodeHelpers.getNodeWebhooks(workflow, node, additionalData, ignoreRestartWebhooks),
NodeHelpers.getNodeWebhooks(workflow, node, additionalData, ignoreRestartWebhooks),
); );
} }

View file

@ -110,7 +110,26 @@ export class WorkflowExecutionService {
startNodes?.map((nodeData) => nodeData.name), startNodes?.map((nodeData) => nodeData.name),
pinData, 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 webhooks nodes exist and are active we have to wait for till we receive a call
if ( if (
pinnedTrigger === null && pinnedTrigger === null &&
@ -119,8 +138,6 @@ export class WorkflowExecutionService {
startNodes.length === 0 || startNodes.length === 0 ||
destinationNode === undefined) destinationNode === undefined)
) { ) {
const additionalData = await WorkflowExecuteAdditionalData.getBase(user.id);
const needsWebhook = await this.testWebhooks.needsWebhook( const needsWebhook = await this.testWebhooks.needsWebhook(
user.id, user.id,
workflowData, workflowData,

View file

@ -22,6 +22,11 @@ export declare namespace WorkflowRequest {
runData: IRunData; runData: IRunData;
startNodes?: StartNodeData[]; startNodes?: StartNodeData[];
destinationNode?: string; 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; preferredTrigger?: string;
}; };

View file

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