n8n/packages/core/src/ActiveWebhooks.ts

152 lines
3.9 KiB
TypeScript
Raw Normal View History

2019-06-23 03:35:23 -07:00
import {
IWebhookData,
WebhookHttpMethod,
Workflow,
2019-06-23 03:35:23 -07:00
WorkflowExecuteMode,
} from 'n8n-workflow';
import {
NodeExecuteFunctions,
} from './';
export class ActiveWebhooks {
private workflowWebhooks: {
[key: string]: IWebhookData[];
} = {};
private webhookUrls: {
[key: string]: IWebhookData;
} = {};
testWebhooks = false;
/**
* Adds a new webhook
*
* @param {IWebhookData} webhookData
* @param {WorkflowExecuteMode} mode
* @returns {Promise<void>}
* @memberof ActiveWebhooks
*/
async add(workflow: Workflow, webhookData: IWebhookData, mode: WorkflowExecuteMode): Promise<void> {
if (workflow.id === undefined) {
2019-06-23 03:35:23 -07:00
throw new Error('Webhooks can only be added for saved workflows as an id is needed!');
}
2020-05-30 16:03:58 -07:00
const webhookKey = this.getWebhookKey(webhookData.httpMethod, webhookData.path);
//check that there is not a webhook already registed with that path/method
if (this.webhookUrls[webhookKey] !== undefined) {
2020-05-31 12:13:45 -07:00
throw new Error(`Test-Webhook can not be activated because another one with the same method "${webhookData.httpMethod}" and path "${webhookData.path}" is already active!`);
2020-05-30 16:03:58 -07:00
}
if (this.workflowWebhooks[webhookData.workflowId] === undefined) {
this.workflowWebhooks[webhookData.workflowId] = [];
2019-06-23 03:35:23 -07:00
}
// Make the webhook available directly because sometimes to create it successfully
// it gets called
2020-05-30 16:03:58 -07:00
this.webhookUrls[webhookKey] = webhookData;
2019-06-23 03:35:23 -07:00
const webhookExists = await workflow.runWebhookMethod('checkExists', webhookData, NodeExecuteFunctions, mode, this.testWebhooks);
2019-06-23 03:35:23 -07:00
if (webhookExists === false) {
// If webhook does not exist yet create it
await workflow.runWebhookMethod('create', webhookData, NodeExecuteFunctions, mode, this.testWebhooks);
2019-06-23 03:35:23 -07:00
}
this.workflowWebhooks[webhookData.workflowId].push(webhookData);
2019-06-23 03:35:23 -07:00
}
/**
* Returns webhookData if a webhook with matches is currently registered
*
* @param {WebhookHttpMethod} httpMethod
* @param {string} path
* @returns {(IWebhookData | undefined)}
* @memberof ActiveWebhooks
*/
get(httpMethod: WebhookHttpMethod, path: string): IWebhookData | undefined {
const webhookKey = this.getWebhookKey(httpMethod, path);
if (this.webhookUrls[webhookKey] === undefined) {
return undefined;
}
return this.webhookUrls[webhookKey];
}
/**
* Returns the ids of all the workflows which have active webhooks
*
* @returns {string[]}
* @memberof ActiveWebhooks
*/
getWorkflowIds(): string[] {
return Object.keys(this.workflowWebhooks);
}
2019-06-23 03:35:23 -07:00
/**
* Returns key to uniquely identify a webhook
*
* @param {WebhookHttpMethod} httpMethod
* @param {string} path
* @returns {string}
* @memberof ActiveWebhooks
*/
getWebhookKey(httpMethod: WebhookHttpMethod, path: string): string {
return `${httpMethod}|${path}`;
}
/**
* Removes all webhooks of a workflow
*
* @param {Workflow} workflow
2019-06-23 03:35:23 -07:00
* @returns {boolean}
* @memberof ActiveWebhooks
*/
async removeWorkflow(workflow: Workflow): Promise<boolean> {
const workflowId = workflow.id!.toString();
2019-06-23 03:35:23 -07:00
if (this.workflowWebhooks[workflowId] === undefined) {
// If it did not exist then there is nothing to remove
return false;
}
const webhooks = this.workflowWebhooks[workflowId];
const mode = 'internal';
// Go through all the registered webhooks of the workflow and remove them
for (const webhookData of webhooks) {
await workflow.runWebhookMethod('delete', webhookData, NodeExecuteFunctions, mode, this.testWebhooks);
2019-06-23 03:35:23 -07:00
delete this.webhookUrls[this.getWebhookKey(webhookData.httpMethod, webhookData.path)];
}
// Remove also the workflow-webhook entry
delete this.workflowWebhooks[workflowId];
return true;
}
/**
* Removes all the webhooks of the given workflow
2019-06-23 03:35:23 -07:00
*/
async removeAll(workflows: Workflow[]): Promise<void> {
2019-06-23 03:35:23 -07:00
const removePromises = [];
for (const workflow of workflows) {
removePromises.push(this.removeWorkflow(workflow));
2019-06-23 03:35:23 -07:00
}
await Promise.all(removePromises);
return;
}
}