n8n/packages/cli/src/ActiveWorkflowRunner.ts

590 lines
20 KiB
TypeScript
Raw Normal View History

2019-06-23 03:35:23 -07:00
import {
Db,
2020-10-22 06:46:03 -07:00
IActivationError,
2019-06-23 03:35:23 -07:00
IResponseCallbackData,
2020-10-22 06:46:03 -07:00
IWebhookDb,
2019-06-23 03:35:23 -07:00
IWorkflowDb,
IWorkflowExecutionDataProcess,
2020-10-22 06:46:03 -07:00
NodeTypes,
2019-06-23 03:35:23 -07:00
ResponseHelper,
WebhookHelpers,
WorkflowCredentials,
2020-10-22 06:46:03 -07:00
WorkflowExecuteAdditionalData,
2019-06-23 03:35:23 -07:00
WorkflowHelpers,
WorkflowRunner,
2019-06-23 03:35:23 -07:00
} from './';
import {
ActiveWorkflows,
NodeExecuteFunctions,
2019-06-23 03:35:23 -07:00
} from 'n8n-core';
import {
IExecuteData,
IGetExecutePollFunctions,
IGetExecuteTriggerFunctions,
INode,
INodeExecutionData,
IRunExecutionData,
2019-06-23 03:35:23 -07:00
IWorkflowExecuteAdditionalData as IWorkflowExecuteAdditionalDataWorkflow,
2020-10-22 06:46:03 -07:00
NodeHelpers,
2019-06-23 03:35:23 -07:00
WebhookHttpMethod,
Workflow,
WorkflowActivateMode,
2019-06-23 03:35:23 -07:00
WorkflowExecuteMode,
} from 'n8n-workflow';
import * as express from 'express';
2021-05-12 16:01:12 -07:00
import {
:sparkles: Added logging to n8n (#1381) * Added logging to n8n This commit adds logging to n8n using the Winston library. For now, this commit only allows logging to console (default behavior) or file (need to pass in config via environment variables). Other logging methods can be further implemented using hooks. These were skipped for now as it would require adding more dependencies. Logging level is notice by default, meaning no additional messages would be displayed at the moment. Logging level can be set to info or debug as well to enrich the generated logs. The ILogger interface was added to the workflow project as it would make it available for all other projects but the implementation was done on the cli project. * Lint fixes and logging level naming. Also fixed the way we use the logger as it was not working previously * Improvements to logging framework Using appropriate single quotes Improving the way the logger is declared * Improved naming for Log Types * Removed logger global variable, replacing it by a proxy * Add logging to CLI commands * Remove unused GenericHelpers * Changed back some messages to console instead of logger and added npm shortcuts for worker and webhook * Fix typos * Adding basic file rotation to logs as suggested by @mutdmour * Fixed linting issues * Correcting comment to correctly reflect space usage * Added settings for log files rotation * Correcting config type from String to Number * Changed default file settings to number To reflect previous changes to the type * Changed the way log messages are added to be called statically. Also minor naming improvements * Applying latest corrections sent by @ivov * :zap: Some logging improvements * Saving logs to a folder inside n8n home instead of root * Fixed broken tests and linting * Changed some log messages to improve formatting * Adding quotes to names on log messages * Added execution and session IDs to logs. Also removed unnecessary line breaks * :zap: Added file caller to log messages (#1657) This is done using callsites library which already existed in the project as another library's dependency. So in fact it does not add any new dependency. * Adding logs to help debug Salesforce node * :zap: Add function name to logs and add more logs * :zap: Improve some error messages * :zap: Improve some more log messages * :zap: Rename logging env variables to match others Co-authored-by: dali <servfrdali@yahoo.fr> Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
2021-05-01 20:43:01 -07:00
LoggerProxy as Logger,
} from 'n8n-workflow';
2019-06-23 03:35:23 -07:00
const WEBHOOK_PROD_UNREGISTERED_HINT = `The workflow must be active for a production URL to run successfully. You can activate the workflow using the toggle in the top-right of the editor. Note that unlike test URL calls, production URL calls aren't shown on the canvas (only in the executions list)`;
2019-06-23 03:35:23 -07:00
export class ActiveWorkflowRunner {
private activeWorkflows: ActiveWorkflows | null = null;
2020-05-27 16:32:49 -07:00
2019-06-23 03:35:23 -07:00
private activationErrors: {
[key: string]: IActivationError;
} = {};
async init() {
2020-05-27 16:32:49 -07:00
2019-06-23 03:35:23 -07:00
// Get the active workflows from database
2020-05-27 16:32:49 -07:00
// NOTE
// Here I guess we can have a flag on the workflow table like hasTrigger
// so intead of pulling all the active wehhooks just pull the actives that have a trigger
const workflowsData: IWorkflowDb[] = await Db.collections.Workflow!.find({ active: true }) as IWorkflowDb[];
2019-06-23 03:35:23 -07:00
// Clear up active workflow table
await Db.collections.Webhook?.clear();
2019-06-23 03:35:23 -07:00
this.activeWorkflows = new ActiveWorkflows();
if (workflowsData.length !== 0) {
:sparkles: Added logging to n8n (#1381) * Added logging to n8n This commit adds logging to n8n using the Winston library. For now, this commit only allows logging to console (default behavior) or file (need to pass in config via environment variables). Other logging methods can be further implemented using hooks. These were skipped for now as it would require adding more dependencies. Logging level is notice by default, meaning no additional messages would be displayed at the moment. Logging level can be set to info or debug as well to enrich the generated logs. The ILogger interface was added to the workflow project as it would make it available for all other projects but the implementation was done on the cli project. * Lint fixes and logging level naming. Also fixed the way we use the logger as it was not working previously * Improvements to logging framework Using appropriate single quotes Improving the way the logger is declared * Improved naming for Log Types * Removed logger global variable, replacing it by a proxy * Add logging to CLI commands * Remove unused GenericHelpers * Changed back some messages to console instead of logger and added npm shortcuts for worker and webhook * Fix typos * Adding basic file rotation to logs as suggested by @mutdmour * Fixed linting issues * Correcting comment to correctly reflect space usage * Added settings for log files rotation * Correcting config type from String to Number * Changed default file settings to number To reflect previous changes to the type * Changed the way log messages are added to be called statically. Also minor naming improvements * Applying latest corrections sent by @ivov * :zap: Some logging improvements * Saving logs to a folder inside n8n home instead of root * Fixed broken tests and linting * Changed some log messages to improve formatting * Adding quotes to names on log messages * Added execution and session IDs to logs. Also removed unnecessary line breaks * :zap: Added file caller to log messages (#1657) This is done using callsites library which already existed in the project as another library's dependency. So in fact it does not add any new dependency. * Adding logs to help debug Salesforce node * :zap: Add function name to logs and add more logs * :zap: Improve some error messages * :zap: Improve some more log messages * :zap: Rename logging env variables to match others Co-authored-by: dali <servfrdali@yahoo.fr> Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
2021-05-01 20:43:01 -07:00
console.info(' ================================');
console.info(' Start Active Workflows:');
console.info(' ================================');
2019-06-23 03:35:23 -07:00
for (const workflowData of workflowsData) {
console.log(` - ${workflowData.name}`);
2021-05-12 16:01:12 -07:00
Logger.debug(`Initializing active workflow "${workflowData.name}" (startup)`, { workflowName: workflowData.name, workflowId: workflowData.id });
try {
await this.add(workflowData.id.toString(), 'init', workflowData);
2021-05-12 16:01:12 -07:00
Logger.verbose(`Successfully started workflow "${workflowData.name}"`, { workflowName: workflowData.name, workflowId: workflowData.id });
console.log(` => Started`);
} catch (error) {
console.log(` => ERROR: Workflow could not be activated:`);
console.log(` ${error.message}`);
2021-05-12 16:01:12 -07:00
Logger.error(`Unable to initialize workflow "${workflowData.name}" (startup)`, { workflowName: workflowData.name, workflowId: workflowData.id });
2019-06-23 03:35:23 -07:00
}
}
:sparkles: Added logging to n8n (#1381) * Added logging to n8n This commit adds logging to n8n using the Winston library. For now, this commit only allows logging to console (default behavior) or file (need to pass in config via environment variables). Other logging methods can be further implemented using hooks. These were skipped for now as it would require adding more dependencies. Logging level is notice by default, meaning no additional messages would be displayed at the moment. Logging level can be set to info or debug as well to enrich the generated logs. The ILogger interface was added to the workflow project as it would make it available for all other projects but the implementation was done on the cli project. * Lint fixes and logging level naming. Also fixed the way we use the logger as it was not working previously * Improvements to logging framework Using appropriate single quotes Improving the way the logger is declared * Improved naming for Log Types * Removed logger global variable, replacing it by a proxy * Add logging to CLI commands * Remove unused GenericHelpers * Changed back some messages to console instead of logger and added npm shortcuts for worker and webhook * Fix typos * Adding basic file rotation to logs as suggested by @mutdmour * Fixed linting issues * Correcting comment to correctly reflect space usage * Added settings for log files rotation * Correcting config type from String to Number * Changed default file settings to number To reflect previous changes to the type * Changed the way log messages are added to be called statically. Also minor naming improvements * Applying latest corrections sent by @ivov * :zap: Some logging improvements * Saving logs to a folder inside n8n home instead of root * Fixed broken tests and linting * Changed some log messages to improve formatting * Adding quotes to names on log messages * Added execution and session IDs to logs. Also removed unnecessary line breaks * :zap: Added file caller to log messages (#1657) This is done using callsites library which already existed in the project as another library's dependency. So in fact it does not add any new dependency. * Adding logs to help debug Salesforce node * :zap: Add function name to logs and add more logs * :zap: Improve some error messages * :zap: Improve some more log messages * :zap: Rename logging env variables to match others Co-authored-by: dali <servfrdali@yahoo.fr> Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
2021-05-01 20:43:01 -07:00
Logger.verbose('Finished initializing active workflows (startup)');
2019-06-23 03:35:23 -07:00
}
}
:sparkles: Separate webhooks from core (#1408) * Unify execution ID across executions * Fix indentation and improved comments * WIP: saving data after each node execution * Added on/off to save data after each step, saving initial data and retries working * Fixing lint issues * Fixing more lint issues * :sparkles: Add bull to execute workflows * :shirt: Fix lint issue * :zap: Add graceful shutdown to worker * :zap: Add loading staticData to worker * :shirt: Fix lint issue * :zap: Fix import * Changed tables metadata to add nullable to stoppedAt * Reload database on migration run * Fixed reloading database schema for sqlite by reconnecting and fixing postgres migration * Added checks to Redis and exiting process if connection is unavailable * Fixing error with new installations * Fix issue with data not being sent back to browser on manual executions with defined destination * Merging bull and unify execution id branch fixes * Main process will now get execution success from database instead of redis * Omit execution duration if execution did not stop * Fix issue with execution list displaying inconsistant information information while a workflow is running * Remove unused hooks to clarify for developers that these wont run in queue mode * Added active pooling to help recover from Redis crashes * Lint issues * Changing default polling interval to 60 seconds * Removed unnecessary attributes from bull job * Added webhooks service and setting to disable webhooks from main process * Fixed executions list when running with queues. Now we get the list of actively running workflows from bull. * Add option to disable deregistration of webhooks on shutdown * Rename WEBHOOK_TUNNEL_URL to WEBHOOK_URL keeping backwards compat. * Added auto refresh to executions list * Improvements to workflow stop process when running with queues * Refactor queue system to use a singleton and avoid code duplication * Improve comments and remove unnecessary commits * Remove console.log from vue file * Blocking webhook process to run without queues * Handling execution stop graciously when possible * Removing initialization of all workflows from webhook process * Refactoring code to remove code duplication for job stop * Improved execution list to be more fluid and less intrusive * Fixing workflow name for current executions when auto updating * :zap: Right align autorefresh checkbox Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
2021-02-09 14:32:40 -08:00
async initWebhooks() {
this.activeWorkflows = new ActiveWorkflows();
}
2019-06-23 03:35:23 -07:00
/**
* Removes all the currently active workflows
*
* @returns {Promise<void>}
* @memberof ActiveWorkflowRunner
*/
async removeAll(): Promise<void> {
const activeWorkflowId: string[] = [];
:sparkles: Added logging to n8n (#1381) * Added logging to n8n This commit adds logging to n8n using the Winston library. For now, this commit only allows logging to console (default behavior) or file (need to pass in config via environment variables). Other logging methods can be further implemented using hooks. These were skipped for now as it would require adding more dependencies. Logging level is notice by default, meaning no additional messages would be displayed at the moment. Logging level can be set to info or debug as well to enrich the generated logs. The ILogger interface was added to the workflow project as it would make it available for all other projects but the implementation was done on the cli project. * Lint fixes and logging level naming. Also fixed the way we use the logger as it was not working previously * Improvements to logging framework Using appropriate single quotes Improving the way the logger is declared * Improved naming for Log Types * Removed logger global variable, replacing it by a proxy * Add logging to CLI commands * Remove unused GenericHelpers * Changed back some messages to console instead of logger and added npm shortcuts for worker and webhook * Fix typos * Adding basic file rotation to logs as suggested by @mutdmour * Fixed linting issues * Correcting comment to correctly reflect space usage * Added settings for log files rotation * Correcting config type from String to Number * Changed default file settings to number To reflect previous changes to the type * Changed the way log messages are added to be called statically. Also minor naming improvements * Applying latest corrections sent by @ivov * :zap: Some logging improvements * Saving logs to a folder inside n8n home instead of root * Fixed broken tests and linting * Changed some log messages to improve formatting * Adding quotes to names on log messages * Added execution and session IDs to logs. Also removed unnecessary line breaks * :zap: Added file caller to log messages (#1657) This is done using callsites library which already existed in the project as another library's dependency. So in fact it does not add any new dependency. * Adding logs to help debug Salesforce node * :zap: Add function name to logs and add more logs * :zap: Improve some error messages * :zap: Improve some more log messages * :zap: Rename logging env variables to match others Co-authored-by: dali <servfrdali@yahoo.fr> Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
2021-05-01 20:43:01 -07:00
Logger.verbose('Call to remove all active workflows received (removeAll)');
if (this.activeWorkflows !== null) {
// TODO: This should be renamed!
activeWorkflowId.push.apply(activeWorkflowId, this.activeWorkflows.allActiveWorkflows());
2019-06-23 03:35:23 -07:00
}
const activeWorkflows = await this.getActiveWorkflows();
activeWorkflowId.push.apply(activeWorkflowId, activeWorkflows.map(workflow => workflow.id));
2019-06-23 03:35:23 -07:00
const removePromises = [];
for (const workflowId of activeWorkflowId) {
2019-06-23 03:35:23 -07:00
removePromises.push(this.remove(workflowId));
}
await Promise.all(removePromises);
return;
}
/**
* Checks if a webhook for the given method and path exists and executes the workflow.
*
* @param {WebhookHttpMethod} httpMethod
* @param {string} path
* @param {express.Request} req
* @param {express.Response} res
* @returns {Promise<object>}
* @memberof ActiveWorkflowRunner
*/
async executeWebhook(httpMethod: WebhookHttpMethod, path: string, req: express.Request, res: express.Response): Promise<IResponseCallbackData> {
:sparkles: Added logging to n8n (#1381) * Added logging to n8n This commit adds logging to n8n using the Winston library. For now, this commit only allows logging to console (default behavior) or file (need to pass in config via environment variables). Other logging methods can be further implemented using hooks. These were skipped for now as it would require adding more dependencies. Logging level is notice by default, meaning no additional messages would be displayed at the moment. Logging level can be set to info or debug as well to enrich the generated logs. The ILogger interface was added to the workflow project as it would make it available for all other projects but the implementation was done on the cli project. * Lint fixes and logging level naming. Also fixed the way we use the logger as it was not working previously * Improvements to logging framework Using appropriate single quotes Improving the way the logger is declared * Improved naming for Log Types * Removed logger global variable, replacing it by a proxy * Add logging to CLI commands * Remove unused GenericHelpers * Changed back some messages to console instead of logger and added npm shortcuts for worker and webhook * Fix typos * Adding basic file rotation to logs as suggested by @mutdmour * Fixed linting issues * Correcting comment to correctly reflect space usage * Added settings for log files rotation * Correcting config type from String to Number * Changed default file settings to number To reflect previous changes to the type * Changed the way log messages are added to be called statically. Also minor naming improvements * Applying latest corrections sent by @ivov * :zap: Some logging improvements * Saving logs to a folder inside n8n home instead of root * Fixed broken tests and linting * Changed some log messages to improve formatting * Adding quotes to names on log messages * Added execution and session IDs to logs. Also removed unnecessary line breaks * :zap: Added file caller to log messages (#1657) This is done using callsites library which already existed in the project as another library's dependency. So in fact it does not add any new dependency. * Adding logs to help debug Salesforce node * :zap: Add function name to logs and add more logs * :zap: Improve some error messages * :zap: Improve some more log messages * :zap: Rename logging env variables to match others Co-authored-by: dali <servfrdali@yahoo.fr> Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
2021-05-01 20:43:01 -07:00
Logger.debug(`Received webhoook "${httpMethod}" for path "${path}"`);
2019-06-23 03:35:23 -07:00
if (this.activeWorkflows === null) {
2019-08-28 08:16:09 -07:00
throw new ResponseHelper.ResponseError('The "activeWorkflows" instance did not get initialized yet.', 404, 404);
2019-06-23 03:35:23 -07:00
}
// Reset request parameters
req.params = {};
// Remove trailing slash
if (path.endsWith('/')) {
path = path.slice(0, -1);
}
:sparkles: Add support for webhook route parameters (#1343) * :construction: add webhookId to URL * :construction: add webhookId to webhook entity, :wrench: refactor migrations * :construction: :elephant: postgres migration * :construction: add mySQL migration * :construction: refactor mongoDB * :construction: add webhookId to IWebhookDb * :construction: starting workflow with dynamic route works * :zap: production dynamic webhooks complete * :art: fix lint issues * :wrench: dynamic path for webhook-test complete * :art: fix lint issues * :art: fix typescript issue * :zap: add error message for dynamic webhook-test * :hammer: improve handling of leading `/` * :construction: add webhookId to URL * :construction: add webhookId to webhook entity, :wrench: refactor migrations * :construction: :elephant: postgres migration * :construction: add mySQL migration * :construction: refactor mongoDB * :construction: add webhookId to IWebhookDb * :construction: starting workflow with dynamic route works * :zap: production dynamic webhooks complete * :art: fix lint issues * :wrench: dynamic path for webhook-test complete * :art: fix lint issues * :art: fix typescript issue * :zap: add error message for dynamic webhook-test * :hammer: improve handling of leading `/` * :zap: Fix issue that tab-title did not get reset on new workflow * Revert ":zap: Fix issue that tab-title did not get reset on new workflow" This reverts commit 699d0a8946e08339558c72b2714601329fbf5f2c. * :wrench: reset params before extraction * :elephant: removing unique constraint for webhookId * :construction: handle multiple webhooks per id * :wrench: enable webhook-test for multiple WH with same id * :elephant: add migration for postgres * :zap: add mysql migration * :art: fix lint issue Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
2021-01-23 11:00:32 -08:00
let webhook = await Db.collections.Webhook?.findOne({ webhookPath: path, method: httpMethod }) as IWebhookDb;
let webhookId: string | undefined;
2019-06-23 03:35:23 -07:00
:sparkles: Add support for webhook route parameters (#1343) * :construction: add webhookId to URL * :construction: add webhookId to webhook entity, :wrench: refactor migrations * :construction: :elephant: postgres migration * :construction: add mySQL migration * :construction: refactor mongoDB * :construction: add webhookId to IWebhookDb * :construction: starting workflow with dynamic route works * :zap: production dynamic webhooks complete * :art: fix lint issues * :wrench: dynamic path for webhook-test complete * :art: fix lint issues * :art: fix typescript issue * :zap: add error message for dynamic webhook-test * :hammer: improve handling of leading `/` * :construction: add webhookId to URL * :construction: add webhookId to webhook entity, :wrench: refactor migrations * :construction: :elephant: postgres migration * :construction: add mySQL migration * :construction: refactor mongoDB * :construction: add webhookId to IWebhookDb * :construction: starting workflow with dynamic route works * :zap: production dynamic webhooks complete * :art: fix lint issues * :wrench: dynamic path for webhook-test complete * :art: fix lint issues * :art: fix typescript issue * :zap: add error message for dynamic webhook-test * :hammer: improve handling of leading `/` * :zap: Fix issue that tab-title did not get reset on new workflow * Revert ":zap: Fix issue that tab-title did not get reset on new workflow" This reverts commit 699d0a8946e08339558c72b2714601329fbf5f2c. * :wrench: reset params before extraction * :elephant: removing unique constraint for webhookId * :construction: handle multiple webhooks per id * :wrench: enable webhook-test for multiple WH with same id * :elephant: add migration for postgres * :zap: add mysql migration * :art: fix lint issue Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
2021-01-23 11:00:32 -08:00
// check if path is dynamic
2020-05-27 16:32:49 -07:00
if (webhook === undefined) {
:sparkles: Add support for webhook route parameters (#1343) * :construction: add webhookId to URL * :construction: add webhookId to webhook entity, :wrench: refactor migrations * :construction: :elephant: postgres migration * :construction: add mySQL migration * :construction: refactor mongoDB * :construction: add webhookId to IWebhookDb * :construction: starting workflow with dynamic route works * :zap: production dynamic webhooks complete * :art: fix lint issues * :wrench: dynamic path for webhook-test complete * :art: fix lint issues * :art: fix typescript issue * :zap: add error message for dynamic webhook-test * :hammer: improve handling of leading `/` * :construction: add webhookId to URL * :construction: add webhookId to webhook entity, :wrench: refactor migrations * :construction: :elephant: postgres migration * :construction: add mySQL migration * :construction: refactor mongoDB * :construction: add webhookId to IWebhookDb * :construction: starting workflow with dynamic route works * :zap: production dynamic webhooks complete * :art: fix lint issues * :wrench: dynamic path for webhook-test complete * :art: fix lint issues * :art: fix typescript issue * :zap: add error message for dynamic webhook-test * :hammer: improve handling of leading `/` * :zap: Fix issue that tab-title did not get reset on new workflow * Revert ":zap: Fix issue that tab-title did not get reset on new workflow" This reverts commit 699d0a8946e08339558c72b2714601329fbf5f2c. * :wrench: reset params before extraction * :elephant: removing unique constraint for webhookId * :construction: handle multiple webhooks per id * :wrench: enable webhook-test for multiple WH with same id * :elephant: add migration for postgres * :zap: add mysql migration * :art: fix lint issue Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
2021-01-23 11:00:32 -08:00
// 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 || dynamicWebhooks.length === 0) {
:sparkles: Add support for webhook route parameters (#1343) * :construction: add webhookId to URL * :construction: add webhookId to webhook entity, :wrench: refactor migrations * :construction: :elephant: postgres migration * :construction: add mySQL migration * :construction: refactor mongoDB * :construction: add webhookId to IWebhookDb * :construction: starting workflow with dynamic route works * :zap: production dynamic webhooks complete * :art: fix lint issues * :wrench: dynamic path for webhook-test complete * :art: fix lint issues * :art: fix typescript issue * :zap: add error message for dynamic webhook-test * :hammer: improve handling of leading `/` * :construction: add webhookId to URL * :construction: add webhookId to webhook entity, :wrench: refactor migrations * :construction: :elephant: postgres migration * :construction: add mySQL migration * :construction: refactor mongoDB * :construction: add webhookId to IWebhookDb * :construction: starting workflow with dynamic route works * :zap: production dynamic webhooks complete * :art: fix lint issues * :wrench: dynamic path for webhook-test complete * :art: fix lint issues * :art: fix typescript issue * :zap: add error message for dynamic webhook-test * :hammer: improve handling of leading `/` * :zap: Fix issue that tab-title did not get reset on new workflow * Revert ":zap: Fix issue that tab-title did not get reset on new workflow" This reverts commit 699d0a8946e08339558c72b2714601329fbf5f2c. * :wrench: reset params before extraction * :elephant: removing unique constraint for webhookId * :construction: handle multiple webhooks per id * :wrench: enable webhook-test for multiple WH with same id * :elephant: add migration for postgres * :zap: add mysql migration * :art: fix lint issue Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
2021-01-23 11:00:32 -08:00
// The requested webhook is not registered
throw new ResponseHelper.ResponseError(`The requested webhook "${httpMethod} ${path}" is not registered.`, 404, 404, WEBHOOK_PROD_UNREGISTERED_HINT);
:sparkles: Add support for webhook route parameters (#1343) * :construction: add webhookId to URL * :construction: add webhookId to webhook entity, :wrench: refactor migrations * :construction: :elephant: postgres migration * :construction: add mySQL migration * :construction: refactor mongoDB * :construction: add webhookId to IWebhookDb * :construction: starting workflow with dynamic route works * :zap: production dynamic webhooks complete * :art: fix lint issues * :wrench: dynamic path for webhook-test complete * :art: fix lint issues * :art: fix typescript issue * :zap: add error message for dynamic webhook-test * :hammer: improve handling of leading `/` * :construction: add webhookId to URL * :construction: add webhookId to webhook entity, :wrench: refactor migrations * :construction: :elephant: postgres migration * :construction: add mySQL migration * :construction: refactor mongoDB * :construction: add webhookId to IWebhookDb * :construction: starting workflow with dynamic route works * :zap: production dynamic webhooks complete * :art: fix lint issues * :wrench: dynamic path for webhook-test complete * :art: fix lint issues * :art: fix typescript issue * :zap: add error message for dynamic webhook-test * :hammer: improve handling of leading `/` * :zap: Fix issue that tab-title did not get reset on new workflow * Revert ":zap: Fix issue that tab-title did not get reset on new workflow" This reverts commit 699d0a8946e08339558c72b2714601329fbf5f2c. * :wrench: reset params before extraction * :elephant: removing unique constraint for webhookId * :construction: handle multiple webhooks per id * :wrench: enable webhook-test for multiple WH with same id * :elephant: add migration for postgres * :zap: add mysql migration * :art: fix lint issue Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
2021-01-23 11:00:32 -08:00
}
let maxMatches = 0;
const pathElementsSet = new Set(pathElements);
// check if static elements match in path
// if more results have been returned choose the one with the most static-route matches
dynamicWebhooks.forEach(dynamicWebhook => {
const staticElements = dynamicWebhook.webhookPath.split('/').filter(ele => !ele.startsWith(':'));
const allStaticExist = staticElements.every(staticEle => pathElementsSet.has(staticEle));
if (allStaticExist && staticElements.length > maxMatches) {
maxMatches = staticElements.length;
webhook = dynamicWebhook;
}
// handle routes with no static elements
else if (staticElements.length === 0 && !webhook) {
webhook = dynamicWebhook;
:sparkles: Add support for webhook route parameters (#1343) * :construction: add webhookId to URL * :construction: add webhookId to webhook entity, :wrench: refactor migrations * :construction: :elephant: postgres migration * :construction: add mySQL migration * :construction: refactor mongoDB * :construction: add webhookId to IWebhookDb * :construction: starting workflow with dynamic route works * :zap: production dynamic webhooks complete * :art: fix lint issues * :wrench: dynamic path for webhook-test complete * :art: fix lint issues * :art: fix typescript issue * :zap: add error message for dynamic webhook-test * :hammer: improve handling of leading `/` * :construction: add webhookId to URL * :construction: add webhookId to webhook entity, :wrench: refactor migrations * :construction: :elephant: postgres migration * :construction: add mySQL migration * :construction: refactor mongoDB * :construction: add webhookId to IWebhookDb * :construction: starting workflow with dynamic route works * :zap: production dynamic webhooks complete * :art: fix lint issues * :wrench: dynamic path for webhook-test complete * :art: fix lint issues * :art: fix typescript issue * :zap: add error message for dynamic webhook-test * :hammer: improve handling of leading `/` * :zap: Fix issue that tab-title did not get reset on new workflow * Revert ":zap: Fix issue that tab-title did not get reset on new workflow" This reverts commit 699d0a8946e08339558c72b2714601329fbf5f2c. * :wrench: reset params before extraction * :elephant: removing unique constraint for webhookId * :construction: handle multiple webhooks per id * :wrench: enable webhook-test for multiple WH with same id * :elephant: add migration for postgres * :zap: add mysql migration * :art: fix lint issue Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
2021-01-23 11:00:32 -08:00
}
});
if (webhook === undefined) {
throw new ResponseHelper.ResponseError(`The requested webhook "${httpMethod} ${path}" is not registered.`, 404, 404, WEBHOOK_PROD_UNREGISTERED_HINT);
:sparkles: Add support for webhook route parameters (#1343) * :construction: add webhookId to URL * :construction: add webhookId to webhook entity, :wrench: refactor migrations * :construction: :elephant: postgres migration * :construction: add mySQL migration * :construction: refactor mongoDB * :construction: add webhookId to IWebhookDb * :construction: starting workflow with dynamic route works * :zap: production dynamic webhooks complete * :art: fix lint issues * :wrench: dynamic path for webhook-test complete * :art: fix lint issues * :art: fix typescript issue * :zap: add error message for dynamic webhook-test * :hammer: improve handling of leading `/` * :construction: add webhookId to URL * :construction: add webhookId to webhook entity, :wrench: refactor migrations * :construction: :elephant: postgres migration * :construction: add mySQL migration * :construction: refactor mongoDB * :construction: add webhookId to IWebhookDb * :construction: starting workflow with dynamic route works * :zap: production dynamic webhooks complete * :art: fix lint issues * :wrench: dynamic path for webhook-test complete * :art: fix lint issues * :art: fix typescript issue * :zap: add error message for dynamic webhook-test * :hammer: improve handling of leading `/` * :zap: Fix issue that tab-title did not get reset on new workflow * Revert ":zap: Fix issue that tab-title did not get reset on new workflow" This reverts commit 699d0a8946e08339558c72b2714601329fbf5f2c. * :wrench: reset params before extraction * :elephant: removing unique constraint for webhookId * :construction: handle multiple webhooks per id * :wrench: enable webhook-test for multiple WH with same id * :elephant: add migration for postgres * :zap: add mysql migration * :art: fix lint issue Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
2021-01-23 11:00:32 -08:00
}
path = webhook!.webhookPath;
:sparkles: Add support for webhook route parameters (#1343) * :construction: add webhookId to URL * :construction: add webhookId to webhook entity, :wrench: refactor migrations * :construction: :elephant: postgres migration * :construction: add mySQL migration * :construction: refactor mongoDB * :construction: add webhookId to IWebhookDb * :construction: starting workflow with dynamic route works * :zap: production dynamic webhooks complete * :art: fix lint issues * :wrench: dynamic path for webhook-test complete * :art: fix lint issues * :art: fix typescript issue * :zap: add error message for dynamic webhook-test * :hammer: improve handling of leading `/` * :construction: add webhookId to URL * :construction: add webhookId to webhook entity, :wrench: refactor migrations * :construction: :elephant: postgres migration * :construction: add mySQL migration * :construction: refactor mongoDB * :construction: add webhookId to IWebhookDb * :construction: starting workflow with dynamic route works * :zap: production dynamic webhooks complete * :art: fix lint issues * :wrench: dynamic path for webhook-test complete * :art: fix lint issues * :art: fix typescript issue * :zap: add error message for dynamic webhook-test * :hammer: improve handling of leading `/` * :zap: Fix issue that tab-title did not get reset on new workflow * Revert ":zap: Fix issue that tab-title did not get reset on new workflow" This reverts commit 699d0a8946e08339558c72b2714601329fbf5f2c. * :wrench: reset params before extraction * :elephant: removing unique constraint for webhookId * :construction: handle multiple webhooks per id * :wrench: enable webhook-test for multiple WH with same id * :elephant: add migration for postgres * :zap: add mysql migration * :art: fix lint issue Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
2021-01-23 11:00:32 -08:00
// extracting params from path
webhook!.webhookPath.split('/').forEach((ele, index) => {
:sparkles: Add support for webhook route parameters (#1343) * :construction: add webhookId to URL * :construction: add webhookId to webhook entity, :wrench: refactor migrations * :construction: :elephant: postgres migration * :construction: add mySQL migration * :construction: refactor mongoDB * :construction: add webhookId to IWebhookDb * :construction: starting workflow with dynamic route works * :zap: production dynamic webhooks complete * :art: fix lint issues * :wrench: dynamic path for webhook-test complete * :art: fix lint issues * :art: fix typescript issue * :zap: add error message for dynamic webhook-test * :hammer: improve handling of leading `/` * :construction: add webhookId to URL * :construction: add webhookId to webhook entity, :wrench: refactor migrations * :construction: :elephant: postgres migration * :construction: add mySQL migration * :construction: refactor mongoDB * :construction: add webhookId to IWebhookDb * :construction: starting workflow with dynamic route works * :zap: production dynamic webhooks complete * :art: fix lint issues * :wrench: dynamic path for webhook-test complete * :art: fix lint issues * :art: fix typescript issue * :zap: add error message for dynamic webhook-test * :hammer: improve handling of leading `/` * :zap: Fix issue that tab-title did not get reset on new workflow * Revert ":zap: Fix issue that tab-title did not get reset on new workflow" This reverts commit 699d0a8946e08339558c72b2714601329fbf5f2c. * :wrench: reset params before extraction * :elephant: removing unique constraint for webhookId * :construction: handle multiple webhooks per id * :wrench: enable webhook-test for multiple WH with same id * :elephant: add migration for postgres * :zap: add mysql migration * :art: fix lint issue Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
2021-01-23 11:00:32 -08:00
if (ele.startsWith(':')) {
// write params to req.params
req.params[ele.slice(1)] = pathElements[index];
}
});
2019-06-23 03:35:23 -07:00
}
2020-05-27 16:32:49 -07:00
const workflowData = await Db.collections.Workflow!.findOne(webhook.workflowId);
if (workflowData === undefined) {
2020-05-27 16:32:49 -07:00
throw new ResponseHelper.ResponseError(`Could not find workflow with id "${webhook.workflowId}"`, 404, 404);
}
const nodeTypes = NodeTypes();
2021-05-12 16:01:12 -07:00
const workflow = new Workflow({ id: webhook.workflowId.toString(), name: workflowData.name, nodes: workflowData.nodes, connections: workflowData.connections, active: workflowData.active, nodeTypes, staticData: workflowData.staticData, settings: workflowData.settings });
2020-05-27 16:32:49 -07:00
const additionalData = await WorkflowExecuteAdditionalData.getBase();
2020-05-27 16:32:49 -07:00
const webhookData = NodeHelpers.getNodeWebhooks(workflow, workflow.getNode(webhook.node as string) as INode, additionalData).filter((webhook) => {
return (webhook.httpMethod === httpMethod && webhook.path === path);
})[0];
2019-06-23 03:35:23 -07:00
// Get the node which has the webhook defined to know where to start from and to
// get additional data
const workflowStartNode = workflow.getNode(webhookData.node);
2020-05-27 16:32:49 -07:00
2019-06-23 03:35:23 -07:00
if (workflowStartNode === null) {
2019-08-28 08:16:09 -07:00
throw new ResponseHelper.ResponseError('Could not find node to process webhook.', 404, 404);
2019-06-23 03:35:23 -07:00
}
return new Promise((resolve, reject) => {
const executionMode = 'webhook';
2020-05-27 16:32:49 -07:00
//@ts-ignore
WebhookHelpers.executeWebhook(workflow, webhookData, workflowData, workflowStartNode, executionMode, undefined, req, res, (error: Error | null, data: object) => {
2019-06-23 03:35:23 -07:00
if (error !== null) {
return reject(error);
}
resolve(data);
});
});
}
/**
* Gets all request methods associated with a single webhook
*
* @param {string} path webhook path
* @returns {Promise<string[]>}
* @memberof ActiveWorkflowRunner
*/
2021-05-12 16:01:12 -07:00
async getWebhookMethods(path: string): Promise<string[]> {
const webhooks = await Db.collections.Webhook?.find({ webhookPath: path }) as IWebhookDb[];
// Gather all request methods in string array
const webhookMethods: string[] = webhooks.map(webhook => webhook.method);
return webhookMethods;
}
2019-06-23 03:35:23 -07:00
/**
* Returns the ids of the currently active workflows
*
* @returns {string[]}
* @memberof ActiveWorkflowRunner
*/
async getActiveWorkflows(): Promise<IWorkflowDb[]> {
const activeWorkflows = await Db.collections.Workflow?.find({ where: { active: true }, select: ['id'] }) as IWorkflowDb[];
return activeWorkflows.filter(workflow => this.activationErrors[workflow.id.toString()] === undefined);
2019-06-23 03:35:23 -07:00
}
/**
* Returns if the workflow is active
*
* @param {string} id The id of the workflow to check
* @returns {boolean}
* @memberof ActiveWorkflowRunner
*/
2020-05-27 16:32:49 -07:00
async isActive(id: string): Promise<boolean> {
:sparkles: Add tagging of workflows (#1647) * clean up dropdown * clean up focusoncreate * :zap: Ignore mistaken ID in POST /workflows * :zap: Fix undefined tag ID in PATCH /workflows * :zap: Shorten response for POST /tags * remove scss mixins * clean up imports * :zap: Implement validation with class-validator * address ivan's comments * implement modals * Fix lint issues * fix disabling shortcuts * fix focus issues * fix focus issues * fix focus issues with modal * fix linting issues * use dispatch * use constants for modal keys * fix focus * fix lint issues * remove unused prop * add modal root * fix lint issues * remove unused methods * fix shortcut * remove max width * :zap: Fix duplicate entry error for pg and MySQL * update rename messaging * update order of buttons * fix firefox overflow on windows * fix dropdown height * :hammer: refactor tag crud controllers * 🧹 remove unused imports * use variable for number of items * fix dropdown spacing * :zap: Restore type to fix build * :zap: Fix post-refactor PATCH /workflows/:id * :zap: Fix PATCH /workflows/:id for zero tags * :zap: Fix usage count becoming stringified * address max's comments * fix filter spacing * fix blur bug * address most of ivan's comments * address tags type concern * remove defaults * :zap: return tag id as string * :hammer: add hooks to tag CUD operations * 🏎 simplify timestamp pruning * remove blur event * fix onblur bug * :zap: Fix fs import to fix build * address max's comments * implement responsive tag container * fix lint issues * Set default dates in entities * :shirt: Fix lint in migrations * update tag limits * address ivan's comments * remove rename, refactor header, implement new designs for save, remove responsive tag container * update styling * update styling * implement responsive tag container * implement header tags edit * implement header tags edit * fix lint issues * implement expandable input * minor fixes * minor fixes * use variable * rename save as * duplicate fixes * :zap: Implement unique workflow names * :zap: Create /workflows/new endpoint * minor edit fixes * lint fixes * style fixes * hook up saving name * hook up tags * clean up impl * fix dirty state bug * update limit * update notification messages * on click outside * fix minor bug with count * lint fixes * :zap: Add query string params to /workflows/new * handle minor edge cases * handle minor edge cases * handle minor bugs; fix firefox dropdown issue * Fix min width * apply tags only after api success * remove count fix * :construction: Adjust to new qs requirements * clean up workflow tags impl, fix tags delete bug * fix minor issue * fix minor spacing issue * disable wrap for ops * fix viewport root; save on click in dropdown * save button loading when saving name/tags * implement max width on tags container * implement cleaner create experience * disable edit while updating * codacy hex color * refactor tags container * fix clickability * fix workflow open and count * clean up structure * fix up lint issues * :zap: Create migrations for unique workflow names * fix button size * increase workflow name limit for larger screen * tslint fixes * disable responsiveness for workflow modal * rename event * change min width for tags * clean up pr * :zap: Adjust quotes in MySQL migration * :zap: Adjust quotes in Postgres migration * address max's comments on styles * remove success toasts * add hover mode to name * minor fixes * refactor name preview * fix name input not to jiggle * finish up name input * Fix up add tags * clean up param * clean up scss * fix resizing name * fix resizing name * fix resize bug * clean up edit spacing * ignore on esc * fix input bug * focus input on clear * build * fix up add tags clickablity * remove scrollbars * move into folders * clean up multiple patch req * remove padding top from edit * update tags on enter * build * rollout blur on enter behavior * rollout esc behavior * fix tags bug when duplicating tags * move key to reload tags * update header spacing * build * update hex case * refactor workflow title * remove unusued prop * keep focus on error, fix bug on error * Fix bug with name / tags toggle on error * impl creating new workflow name * :zap: Refactor endpoint per new guidelines * support naming endpoint * :zap: Refactor to support numeric suffixes * :shirt: Lint migrations for unique workflow names * :zap: Add migrations set default dates to indexes * fix connection push bug * :zap: Lowercase default workflow name * :zap: Add prefixes to set default dates migration * :zap: Fix indentation on default dates migrations * :zap: Add temp ts-ignore for unrelated change * :zap: Adjust default dates migration for MySQL Remove change to data column in credentials_entity, already covered by Omar's migration. Also, fix quotes from table prefix addition. * :zap: Adjust quotes in dates migration for PG * fix safari color bug * fix count bug * fix scroll bugs in dropdown * expand filter size * apply box-sizing to main header * update workflow names in executions to be wrapped by quotes * fix bug where key is same in dropdown * fix firefox bug * move up push connection session * :hammer: Remove mistakenly added nullable property * :fire: Remove unneeded index drop-create (PG) * :fire: Remove unneeded table copying * :zap: Merge dates migration with tags migration * :hammer: Refactor endpoint and make wf name env * dropdown colors in firefox * update colors to use variables * update thumb color * change error message * remove 100 char maximum * fix bug with saving tags dropdowns multiple times * update error message when no name * :zap: Update name missing toast message * :zap: Update workflow already exists message * disable saving for executions * fix bug causing modal to close * make tags in workflow open clickable * increase workflow limit to 3 * remove success notifications * update header spacing * escape tag names * update tag and table colors * remove tags from export * build * clean up push connection dependencies * address ben's comments * revert tags optional interface * address comments * update duplicate message * build * fix eol * add one more eol * :zap: Update comment * add hover style for workflow open, fix up font weight Co-authored-by: Mutasem <mutdmour@gmail.com> Co-authored-by: Iván Ovejero <ivov.src@gmail.com> Co-authored-by: Mutasem Aldmour <4711238+mutdmour@users.noreply.github.com>
2021-05-29 11:31:21 -07:00
const workflow = await Db.collections.Workflow?.findOne({ id: Number(id) }) as IWorkflowDb;
2020-05-27 16:32:49 -07:00
return workflow?.active as boolean;
2019-06-23 03:35:23 -07:00
}
/**
* Return error if there was a problem activating the workflow
*
* @param {string} id The id of the workflow to return the error of
* @returns {(IActivationError | undefined)}
* @memberof ActiveWorkflowRunner
*/
getActivationError(id: string): IActivationError | undefined {
if (this.activationErrors[id] === undefined) {
return undefined;
}
return this.activationErrors[id];
}
/**
* Adds all the webhooks of the workflow
*
* @param {Workflow} workflow
* @param {IWorkflowExecuteAdditionalDataWorkflow} additionalData
* @param {WorkflowExecuteMode} mode
* @returns {Promise<void>}
* @memberof ActiveWorkflowRunner
*/
async addWorkflowWebhooks(workflow: Workflow, additionalData: IWorkflowExecuteAdditionalDataWorkflow, mode: WorkflowExecuteMode, activation: WorkflowActivateMode): Promise<void> {
2019-06-23 03:35:23 -07:00
const webhooks = WebhookHelpers.getWorkflowWebhooks(workflow, additionalData);
let path = '' as string | undefined;
2019-06-23 03:35:23 -07:00
for (const webhookData of webhooks) {
2020-05-27 16:32:49 -07:00
const node = workflow.getNode(webhookData.node) as INode;
node.name = webhookData.node;
path = webhookData.path;
2020-05-27 16:32:49 -07:00
const webhook = {
workflowId: webhookData.workflowId,
webhookPath: path,
2020-05-27 16:32:49 -07:00
node: node.name,
method: webhookData.httpMethod,
} as IWebhookDb;
:sparkles: Add support for webhook route parameters (#1343) * :construction: add webhookId to URL * :construction: add webhookId to webhook entity, :wrench: refactor migrations * :construction: :elephant: postgres migration * :construction: add mySQL migration * :construction: refactor mongoDB * :construction: add webhookId to IWebhookDb * :construction: starting workflow with dynamic route works * :zap: production dynamic webhooks complete * :art: fix lint issues * :wrench: dynamic path for webhook-test complete * :art: fix lint issues * :art: fix typescript issue * :zap: add error message for dynamic webhook-test * :hammer: improve handling of leading `/` * :construction: add webhookId to URL * :construction: add webhookId to webhook entity, :wrench: refactor migrations * :construction: :elephant: postgres migration * :construction: add mySQL migration * :construction: refactor mongoDB * :construction: add webhookId to IWebhookDb * :construction: starting workflow with dynamic route works * :zap: production dynamic webhooks complete * :art: fix lint issues * :wrench: dynamic path for webhook-test complete * :art: fix lint issues * :art: fix typescript issue * :zap: add error message for dynamic webhook-test * :hammer: improve handling of leading `/` * :zap: Fix issue that tab-title did not get reset on new workflow * Revert ":zap: Fix issue that tab-title did not get reset on new workflow" This reverts commit 699d0a8946e08339558c72b2714601329fbf5f2c. * :wrench: reset params before extraction * :elephant: removing unique constraint for webhookId * :construction: handle multiple webhooks per id * :wrench: enable webhook-test for multiple WH with same id * :elephant: add migration for postgres * :zap: add mysql migration * :art: fix lint issue Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
2021-01-23 11:00:32 -08:00
if (webhook.webhookPath.startsWith('/')) {
webhook.webhookPath = webhook.webhookPath.slice(1);
}
if (webhook.webhookPath.endsWith('/')) {
webhook.webhookPath = webhook.webhookPath.slice(0, -1);
}
:sparkles: Add support for webhook route parameters (#1343) * :construction: add webhookId to URL * :construction: add webhookId to webhook entity, :wrench: refactor migrations * :construction: :elephant: postgres migration * :construction: add mySQL migration * :construction: refactor mongoDB * :construction: add webhookId to IWebhookDb * :construction: starting workflow with dynamic route works * :zap: production dynamic webhooks complete * :art: fix lint issues * :wrench: dynamic path for webhook-test complete * :art: fix lint issues * :art: fix typescript issue * :zap: add error message for dynamic webhook-test * :hammer: improve handling of leading `/` * :construction: add webhookId to URL * :construction: add webhookId to webhook entity, :wrench: refactor migrations * :construction: :elephant: postgres migration * :construction: add mySQL migration * :construction: refactor mongoDB * :construction: add webhookId to IWebhookDb * :construction: starting workflow with dynamic route works * :zap: production dynamic webhooks complete * :art: fix lint issues * :wrench: dynamic path for webhook-test complete * :art: fix lint issues * :art: fix typescript issue * :zap: add error message for dynamic webhook-test * :hammer: improve handling of leading `/` * :zap: Fix issue that tab-title did not get reset on new workflow * Revert ":zap: Fix issue that tab-title did not get reset on new workflow" This reverts commit 699d0a8946e08339558c72b2714601329fbf5f2c. * :wrench: reset params before extraction * :elephant: removing unique constraint for webhookId * :construction: handle multiple webhooks per id * :wrench: enable webhook-test for multiple WH with same id * :elephant: add migration for postgres * :zap: add mysql migration * :art: fix lint issue Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
2021-01-23 11:00:32 -08:00
if ((path.startsWith(':') || path.includes('/:')) && node.webhookId) {
webhook.webhookId = node.webhookId;
webhook.pathLength = webhook.webhookPath.split('/').length;
}
2020-05-27 16:32:49 -07:00
try {
await Db.collections.Webhook?.insert(webhook);
const webhookExists = await workflow.runWebhookMethod('checkExists', webhookData, NodeExecuteFunctions, mode, activation, false);
if (webhookExists !== true) {
2020-05-27 16:32:49 -07:00
// If webhook does not exist yet create it
await workflow.runWebhookMethod('create', webhookData, NodeExecuteFunctions, mode, activation, false);
2020-05-27 16:32:49 -07:00
}
} catch (error) {
try {
await this.removeWorkflowWebhooks(workflow.id as string);
} catch (error) {
console.error(`Could not remove webhooks of workflow "${workflow.id}" because of error: "${error.message}"`);
}
2020-05-30 16:03:58 -07:00
let errorMessage = '';
2020-05-27 16:32:49 -07:00
2020-05-30 16:03:58 -07:00
// if it's a workflow from the the insert
:sparkles: Add support for webhook route parameters (#1343) * :construction: add webhookId to URL * :construction: add webhookId to webhook entity, :wrench: refactor migrations * :construction: :elephant: postgres migration * :construction: add mySQL migration * :construction: refactor mongoDB * :construction: add webhookId to IWebhookDb * :construction: starting workflow with dynamic route works * :zap: production dynamic webhooks complete * :art: fix lint issues * :wrench: dynamic path for webhook-test complete * :art: fix lint issues * :art: fix typescript issue * :zap: add error message for dynamic webhook-test * :hammer: improve handling of leading `/` * :construction: add webhookId to URL * :construction: add webhookId to webhook entity, :wrench: refactor migrations * :construction: :elephant: postgres migration * :construction: add mySQL migration * :construction: refactor mongoDB * :construction: add webhookId to IWebhookDb * :construction: starting workflow with dynamic route works * :zap: production dynamic webhooks complete * :art: fix lint issues * :wrench: dynamic path for webhook-test complete * :art: fix lint issues * :art: fix typescript issue * :zap: add error message for dynamic webhook-test * :hammer: improve handling of leading `/` * :zap: Fix issue that tab-title did not get reset on new workflow * Revert ":zap: Fix issue that tab-title did not get reset on new workflow" This reverts commit 699d0a8946e08339558c72b2714601329fbf5f2c. * :wrench: reset params before extraction * :elephant: removing unique constraint for webhookId * :construction: handle multiple webhooks per id * :wrench: enable webhook-test for multiple WH with same id * :elephant: add migration for postgres * :zap: add mysql migration * :art: fix lint issue Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
2021-01-23 11:00:32 -08:00
// TODO check if there is standard error code for duplicate key violation that works
2020-05-30 16:03:58 -07:00
// with all databases
2021-01-23 11:35:38 -08:00
if (error.name === 'QueryFailedError') {
errorMessage = `The webhook path [${webhook.webhookPath}] and method [${webhook.method}] already exist.`;
2020-05-30 16:03:58 -07:00
} else if (error.detail) {
// it's a error runnig the webhook methods (checkExists, create)
errorMessage = error.detail;
} else {
errorMessage = error.message;
2020-05-30 16:03:58 -07:00
}
throw error;
2020-05-27 16:32:49 -07:00
}
2019-06-23 03:35:23 -07:00
}
2020-05-27 16:32:49 -07:00
// Save static data!
await WorkflowHelpers.saveStaticData(workflow);
2019-06-23 03:35:23 -07:00
}
/**
* Remove all the webhooks of the workflow
*
* @param {string} workflowId
* @returns
* @memberof ActiveWorkflowRunner
*/
async removeWorkflowWebhooks(workflowId: string): Promise<void> {
const workflowData = await Db.collections.Workflow!.findOne(workflowId);
if (workflowData === undefined) {
throw new Error(`Could not find workflow with id "${workflowId}"`);
}
const nodeTypes = NodeTypes();
const workflow = new Workflow({ id: workflowId, name: workflowData.name, nodes: workflowData.nodes, connections: workflowData.connections, active: workflowData.active, nodeTypes, staticData: workflowData.staticData, settings: workflowData.settings });
2020-05-27 16:32:49 -07:00
const mode = 'internal';
const additionalData = await WorkflowExecuteAdditionalData.getBase();
2020-05-27 16:32:49 -07:00
const webhooks = WebhookHelpers.getWorkflowWebhooks(workflow, additionalData);
for (const webhookData of webhooks) {
await workflow.runWebhookMethod('delete', webhookData, NodeExecuteFunctions, mode, 'update', false);
2020-05-27 16:32:49 -07:00
}
await WorkflowHelpers.saveStaticData(workflow);
2020-05-27 16:32:49 -07:00
const webhook = {
workflowId: workflowData.id,
} as IWebhookDb;
await Db.collections.Webhook?.delete(webhook);
2019-06-23 03:35:23 -07:00
}
/**
* Runs the given workflow
*
* @param {IWorkflowDb} workflowData
* @param {INode} node
* @param {INodeExecutionData[][]} data
* @param {IWorkflowExecuteAdditionalDataWorkflow} additionalData
* @param {WorkflowExecuteMode} mode
* @returns
* @memberof ActiveWorkflowRunner
*/
runWorkflow(workflowData: IWorkflowDb, node: INode, data: INodeExecutionData[][], additionalData: IWorkflowExecuteAdditionalDataWorkflow, mode: WorkflowExecuteMode) {
const nodeExecutionStack: IExecuteData[] = [
{
node,
data: {
main: data,
2020-10-22 06:46:03 -07:00
},
},
];
const executionData: IRunExecutionData = {
startData: {},
resultData: {
runData: {},
},
executionData: {
contextData: {},
nodeExecutionStack,
waitingExecution: {},
},
};
// Start the workflow
const runData: IWorkflowExecutionDataProcess = {
executionMode: mode,
executionData,
workflowData,
};
const workflowRunner = new WorkflowRunner();
return workflowRunner.run(runData, true);
}
/**
* Return poll function which gets the global functions from n8n-core
* and overwrites the __emit to be able to start it in subprocess
*
* @param {IWorkflowDb} workflowData
* @param {IWorkflowExecuteAdditionalDataWorkflow} additionalData
* @param {WorkflowExecuteMode} mode
* @returns {IGetExecutePollFunctions}
* @memberof ActiveWorkflowRunner
*/
getExecutePollFunctions(workflowData: IWorkflowDb, additionalData: IWorkflowExecuteAdditionalDataWorkflow, mode: WorkflowExecuteMode, activation: WorkflowActivateMode): IGetExecutePollFunctions {
return ((workflow: Workflow, node: INode) => {
const returnFunctions = NodeExecuteFunctions.getExecutePollFunctions(workflow, node, additionalData, mode, activation);
returnFunctions.__emit = (data: INodeExecutionData[][]): void => {
:sparkles: Added logging to n8n (#1381) * Added logging to n8n This commit adds logging to n8n using the Winston library. For now, this commit only allows logging to console (default behavior) or file (need to pass in config via environment variables). Other logging methods can be further implemented using hooks. These were skipped for now as it would require adding more dependencies. Logging level is notice by default, meaning no additional messages would be displayed at the moment. Logging level can be set to info or debug as well to enrich the generated logs. The ILogger interface was added to the workflow project as it would make it available for all other projects but the implementation was done on the cli project. * Lint fixes and logging level naming. Also fixed the way we use the logger as it was not working previously * Improvements to logging framework Using appropriate single quotes Improving the way the logger is declared * Improved naming for Log Types * Removed logger global variable, replacing it by a proxy * Add logging to CLI commands * Remove unused GenericHelpers * Changed back some messages to console instead of logger and added npm shortcuts for worker and webhook * Fix typos * Adding basic file rotation to logs as suggested by @mutdmour * Fixed linting issues * Correcting comment to correctly reflect space usage * Added settings for log files rotation * Correcting config type from String to Number * Changed default file settings to number To reflect previous changes to the type * Changed the way log messages are added to be called statically. Also minor naming improvements * Applying latest corrections sent by @ivov * :zap: Some logging improvements * Saving logs to a folder inside n8n home instead of root * Fixed broken tests and linting * Changed some log messages to improve formatting * Adding quotes to names on log messages * Added execution and session IDs to logs. Also removed unnecessary line breaks * :zap: Added file caller to log messages (#1657) This is done using callsites library which already existed in the project as another library's dependency. So in fact it does not add any new dependency. * Adding logs to help debug Salesforce node * :zap: Add function name to logs and add more logs * :zap: Improve some error messages * :zap: Improve some more log messages * :zap: Rename logging env variables to match others Co-authored-by: dali <servfrdali@yahoo.fr> Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
2021-05-01 20:43:01 -07:00
Logger.debug(`Received event to trigger execution for workflow "${workflow.name}"`);
this.runWorkflow(workflowData, node, data, additionalData, mode);
};
return returnFunctions;
});
}
/**
* Return trigger function which gets the global functions from n8n-core
* and overwrites the emit to be able to start it in subprocess
*
* @param {IWorkflowDb} workflowData
* @param {IWorkflowExecuteAdditionalDataWorkflow} additionalData
* @param {WorkflowExecuteMode} mode
* @returns {IGetExecuteTriggerFunctions}
* @memberof ActiveWorkflowRunner
*/
2021-05-12 16:01:12 -07:00
getExecuteTriggerFunctions(workflowData: IWorkflowDb, additionalData: IWorkflowExecuteAdditionalDataWorkflow, mode: WorkflowExecuteMode, activation: WorkflowActivateMode): IGetExecuteTriggerFunctions {
return ((workflow: Workflow, node: INode) => {
const returnFunctions = NodeExecuteFunctions.getExecuteTriggerFunctions(workflow, node, additionalData, mode, activation);
returnFunctions.emit = (data: INodeExecutionData[][]): void => {
:sparkles: Added logging to n8n (#1381) * Added logging to n8n This commit adds logging to n8n using the Winston library. For now, this commit only allows logging to console (default behavior) or file (need to pass in config via environment variables). Other logging methods can be further implemented using hooks. These were skipped for now as it would require adding more dependencies. Logging level is notice by default, meaning no additional messages would be displayed at the moment. Logging level can be set to info or debug as well to enrich the generated logs. The ILogger interface was added to the workflow project as it would make it available for all other projects but the implementation was done on the cli project. * Lint fixes and logging level naming. Also fixed the way we use the logger as it was not working previously * Improvements to logging framework Using appropriate single quotes Improving the way the logger is declared * Improved naming for Log Types * Removed logger global variable, replacing it by a proxy * Add logging to CLI commands * Remove unused GenericHelpers * Changed back some messages to console instead of logger and added npm shortcuts for worker and webhook * Fix typos * Adding basic file rotation to logs as suggested by @mutdmour * Fixed linting issues * Correcting comment to correctly reflect space usage * Added settings for log files rotation * Correcting config type from String to Number * Changed default file settings to number To reflect previous changes to the type * Changed the way log messages are added to be called statically. Also minor naming improvements * Applying latest corrections sent by @ivov * :zap: Some logging improvements * Saving logs to a folder inside n8n home instead of root * Fixed broken tests and linting * Changed some log messages to improve formatting * Adding quotes to names on log messages * Added execution and session IDs to logs. Also removed unnecessary line breaks * :zap: Added file caller to log messages (#1657) This is done using callsites library which already existed in the project as another library's dependency. So in fact it does not add any new dependency. * Adding logs to help debug Salesforce node * :zap: Add function name to logs and add more logs * :zap: Improve some error messages * :zap: Improve some more log messages * :zap: Rename logging env variables to match others Co-authored-by: dali <servfrdali@yahoo.fr> Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
2021-05-01 20:43:01 -07:00
Logger.debug(`Received trigger for workflow "${workflow.name}"`);
WorkflowHelpers.saveStaticData(workflow);
this.runWorkflow(workflowData, node, data, additionalData, mode).catch((err) => console.error(err));
};
return returnFunctions;
});
}
2019-06-23 03:35:23 -07:00
/**
* Makes a workflow active
*
* @param {string} workflowId The id of the workflow to activate
* @param {IWorkflowDb} [workflowData] If workflowData is given it saves the DB query
* @returns {Promise<void>}
* @memberof ActiveWorkflowRunner
*/
async add(workflowId: string, activation: WorkflowActivateMode, workflowData?: IWorkflowDb): Promise<void> {
2019-06-23 03:35:23 -07:00
if (this.activeWorkflows === null) {
throw new Error(`The "activeWorkflows" instance did not get initialized yet.`);
}
let workflowInstance: Workflow;
try {
if (workflowData === undefined) {
workflowData = await Db.collections.Workflow!.findOne(workflowId) as IWorkflowDb;
}
if (!workflowData) {
throw new Error(`Could not find workflow with id "${workflowId}".`);
}
const nodeTypes = NodeTypes();
workflowInstance = new Workflow({ id: workflowId, name: workflowData.name, nodes: workflowData.nodes, connections: workflowData.connections, active: workflowData.active, nodeTypes, staticData: workflowData.staticData, settings: workflowData.settings });
2019-06-23 03:35:23 -07:00
const canBeActivated = workflowInstance.checkIfWorkflowCanBeActivated(['n8n-nodes-base.start']);
if (canBeActivated === false) {
:sparkles: Added logging to n8n (#1381) * Added logging to n8n This commit adds logging to n8n using the Winston library. For now, this commit only allows logging to console (default behavior) or file (need to pass in config via environment variables). Other logging methods can be further implemented using hooks. These were skipped for now as it would require adding more dependencies. Logging level is notice by default, meaning no additional messages would be displayed at the moment. Logging level can be set to info or debug as well to enrich the generated logs. The ILogger interface was added to the workflow project as it would make it available for all other projects but the implementation was done on the cli project. * Lint fixes and logging level naming. Also fixed the way we use the logger as it was not working previously * Improvements to logging framework Using appropriate single quotes Improving the way the logger is declared * Improved naming for Log Types * Removed logger global variable, replacing it by a proxy * Add logging to CLI commands * Remove unused GenericHelpers * Changed back some messages to console instead of logger and added npm shortcuts for worker and webhook * Fix typos * Adding basic file rotation to logs as suggested by @mutdmour * Fixed linting issues * Correcting comment to correctly reflect space usage * Added settings for log files rotation * Correcting config type from String to Number * Changed default file settings to number To reflect previous changes to the type * Changed the way log messages are added to be called statically. Also minor naming improvements * Applying latest corrections sent by @ivov * :zap: Some logging improvements * Saving logs to a folder inside n8n home instead of root * Fixed broken tests and linting * Changed some log messages to improve formatting * Adding quotes to names on log messages * Added execution and session IDs to logs. Also removed unnecessary line breaks * :zap: Added file caller to log messages (#1657) This is done using callsites library which already existed in the project as another library's dependency. So in fact it does not add any new dependency. * Adding logs to help debug Salesforce node * :zap: Add function name to logs and add more logs * :zap: Improve some error messages * :zap: Improve some more log messages * :zap: Rename logging env variables to match others Co-authored-by: dali <servfrdali@yahoo.fr> Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
2021-05-01 20:43:01 -07:00
Logger.error(`Unable to activate workflow "${workflowData.name}"`);
2019-06-23 03:35:23 -07:00
throw new Error(`The workflow can not be activated because it does not contain any nodes which could start the workflow. Only workflows which have trigger or webhook nodes can be activated.`);
}
const mode = 'trigger';
const additionalData = await WorkflowExecuteAdditionalData.getBase();
const getTriggerFunctions = this.getExecuteTriggerFunctions(workflowData, additionalData, mode, activation);
const getPollFunctions = this.getExecutePollFunctions(workflowData, additionalData, mode, activation);
2019-06-23 03:35:23 -07:00
// Add the workflows which have webhooks defined
await this.addWorkflowWebhooks(workflowInstance, additionalData, mode, activation);
2020-05-27 16:32:49 -07:00
if (workflowInstance.getTriggerNodes().length !== 0
|| workflowInstance.getPollNodes().length !== 0) {
await this.activeWorkflows.add(workflowId, workflowInstance, additionalData, mode, activation, getTriggerFunctions, getPollFunctions);
Logger.verbose(`Successfully activated workflow "${workflowData.name}"`, { workflowId, workflowName: workflowData.name });
2020-05-27 16:32:49 -07:00
}
2019-06-23 03:35:23 -07:00
if (this.activationErrors[workflowId] !== undefined) {
// If there were activation errors delete them
2019-06-23 03:35:23 -07:00
delete this.activationErrors[workflowId];
}
} catch (error) {
// There was a problem activating the workflow
// Save the error
this.activationErrors[workflowId] = {
time: new Date().getTime(),
error: {
message: error.message,
},
};
throw error;
}
// If for example webhooks get created it sometimes has to save the
// id of them in the static data. So make sure that data gets persisted.
2019-06-23 03:35:23 -07:00
await WorkflowHelpers.saveStaticData(workflowInstance!);
}
/**
* Makes a workflow inactive
*
* @param {string} workflowId The id of the workflow to deactivate
* @returns {Promise<void>}
* @memberof ActiveWorkflowRunner
*/
async remove(workflowId: string): Promise<void> {
2020-05-27 16:32:49 -07:00
2019-06-23 03:35:23 -07:00
if (this.activeWorkflows !== null) {
// Remove all the webhooks of the workflow
try {
await this.removeWorkflowWebhooks(workflowId);
} catch (error) {
console.error(`Could not remove webhooks of workflow "${workflowId}" because of error: "${error.message}"`);
}
2019-06-23 03:35:23 -07:00
if (this.activationErrors[workflowId] !== undefined) {
// If there were any activation errors delete them
delete this.activationErrors[workflowId];
}
2020-05-27 16:32:49 -07:00
// if it's active in memory then it's a trigger
// so remove from list of actives workflows
if (this.activeWorkflows.isActive(workflowId)) {
await this.activeWorkflows.remove(workflowId);
Logger.verbose(`Successfully deactivated workflow "${workflowId}"`, { workflowId });
2020-05-27 16:32:49 -07:00
}
return;
2019-06-23 03:35:23 -07:00
}
throw new Error(`The "activeWorkflows" instance did not get initialized yet.`);
}
}
let workflowRunnerInstance: ActiveWorkflowRunner | undefined;
export function getInstance(): ActiveWorkflowRunner {
if (workflowRunnerInstance === undefined) {
workflowRunnerInstance = new ActiveWorkflowRunner();
}
return workflowRunnerInstance;
}