Add support for webhook route parameters (#1343)

* 🚧 add webhookId to URL

* 🚧 add webhookId to webhook entity, 🔧 refactor migrations

* 🚧 🐘 postgres migration

* 🚧 add mySQL migration

* 🚧 refactor mongoDB

* 🚧 add webhookId to IWebhookDb

* 🚧 starting workflow with dynamic route works

*  production dynamic webhooks complete

* 🎨 fix lint issues

* 🔧 dynamic path for webhook-test complete

* 🎨 fix lint issues

* 🎨 fix typescript issue

*  add error message for dynamic webhook-test

* 🔨 improve handling of leading `/`

* 🚧 add webhookId to URL

* 🚧 add webhookId to webhook entity, 🔧 refactor migrations

* 🚧 🐘 postgres migration

* 🚧 add mySQL migration

* 🚧 refactor mongoDB

* 🚧 add webhookId to IWebhookDb

* 🚧 starting workflow with dynamic route works

*  production dynamic webhooks complete

* 🎨 fix lint issues

* 🔧 dynamic path for webhook-test complete

* 🎨 fix lint issues

* 🎨 fix typescript issue

*  add error message for dynamic webhook-test

* 🔨 improve handling of leading `/`

*  Fix issue that tab-title did not get reset on new workflow

* Revert " Fix issue that tab-title did not get reset on new workflow"

This reverts commit 699d0a8946e08339558c72b2714601329fbf5f2c.

* 🔧 reset params before extraction

* 🐘 removing unique constraint for webhookId

* 🚧 handle multiple webhooks per id

* 🔧 enable webhook-test for multiple WH with same id

* 🐘 add migration for postgres

*  add mysql migration

* 🎨 fix lint issue

Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
This commit is contained in:
Ben Hesseldieck
2021-01-23 20:00:32 +01:00
committed by GitHub
parent 1a68303319
commit d395498882
26 changed files with 327 additions and 88 deletions

View File

@@ -116,12 +116,49 @@ export class ActiveWorkflowRunner {
throw new ResponseHelper.ResponseError('The "activeWorkflows" instance did not get initialized yet.', 404, 404);
}
const webhook = await Db.collections.Webhook?.findOne({ webhookPath: path, method: httpMethod }) as IWebhookDb;
let webhook = await Db.collections.Webhook?.findOne({ webhookPath: path, method: httpMethod }) as IWebhookDb;
let webhookId: string | undefined;
// check if something exist
// check if path is dynamic
if (webhook === undefined) {
// The requested webhook is not registered
throw new ResponseHelper.ResponseError(`The requested webhook "${httpMethod} ${path}" is not registered.`, 404, 404);
// check if a dynamic webhook path exists
const pathElements = path.split('/');
webhookId = pathElements.shift();
const dynamicWebhooks = await Db.collections.Webhook?.find({ webhookId, method: httpMethod, pathLength: pathElements.length });
if (dynamicWebhooks === undefined) {
// The requested webhook is not registered
throw new ResponseHelper.ResponseError(`The requested webhook "${httpMethod} ${path}" is not registered.`, 404, 404);
}
// set webhook to the first webhook result
// if more results have been returned choose the one with the most route-matches
webhook = dynamicWebhooks[0];
if (dynamicWebhooks.length > 1) {
let maxMatches = 0;
const pathElementsSet = new Set(pathElements);
dynamicWebhooks.forEach(dynamicWebhook => {
const intersection =
dynamicWebhook.webhookPath
.split('/')
.reduce((acc, element) => pathElementsSet.has(element) ? acc += 1 : acc, 0);
if (intersection > maxMatches) {
maxMatches = intersection;
webhook = dynamicWebhook;
}
});
if (maxMatches === 0) {
throw new ResponseHelper.ResponseError(`The requested webhook "${httpMethod} ${path}" is not registered.`, 404, 404);
}
}
path = webhook.webhookPath;
// extracting params from path
webhook.webhookPath.split('/').forEach((ele, index) => {
if (ele.startsWith(':')) {
// write params to req.params
req.params[ele.slice(1)] = pathElements[index];
}
});
}
const workflowData = await Db.collections.Workflow!.findOne(webhook.workflowId);
@@ -253,6 +290,15 @@ export class ActiveWorkflowRunner {
method: webhookData.httpMethod,
} as IWebhookDb;
if (webhook.webhookPath.startsWith('/')) {
webhook.webhookPath = webhook.webhookPath.slice(1);
}
if ((path.startsWith(':') || path.includes('/:')) && node.webhookId) {
webhook.webhookId = node.webhookId;
webhook.pathLength = webhook.webhookPath.split('/').length;
}
try {
await Db.collections.Webhook?.insert(webhook);
@@ -273,10 +319,9 @@ export class ActiveWorkflowRunner {
let errorMessage = '';
// if it's a workflow from the the insert
// TODO check if there is standard error code for deplicate key violation that works
// TODO check if there is standard error code for duplicate key violation that works
// with all databases
if (error.name === 'MongoError' || error.name === 'QueryFailedError') {
errorMessage = `The webhook path [${webhook.webhookPath}] and method [${webhook.method}] already exist.`;
} else if (error.detail) {