mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
Merge branch 'master' into save-changes-warning
This commit is contained in:
commit
18c8c408e2
1
.github/workflows/tests.yml
vendored
1
.github/workflows/tests.yml
vendored
|
@ -23,5 +23,6 @@ jobs:
|
||||||
npm run bootstrap
|
npm run bootstrap
|
||||||
npm run build --if-present
|
npm run build --if-present
|
||||||
npm test
|
npm test
|
||||||
|
npm run tslint
|
||||||
env:
|
env:
|
||||||
CI: true
|
CI: true
|
||||||
|
|
|
@ -119,6 +119,10 @@ To start n8n execute:
|
||||||
npm run start
|
npm run start
|
||||||
```
|
```
|
||||||
|
|
||||||
|
To start n8n with tunnel:
|
||||||
|
```
|
||||||
|
./packages/cli/bin/n8n start --tunnel
|
||||||
|
```
|
||||||
|
|
||||||
## Development Cycle
|
## Development Cycle
|
||||||
|
|
||||||
|
@ -213,23 +217,7 @@ If you'd like to submit a new node, please go through the following checklist. T
|
||||||
|
|
||||||
## Extend Documentation
|
## Extend Documentation
|
||||||
|
|
||||||
All the files which get used in the n8n documentation on [https://docs.n8n.io](https://docs.n8n.io)
|
The repository for the n8n documentation on https://docs.n8n.io can be found [here](https://github.com/n8n-io/n8n-docs).
|
||||||
can be found in the [/docs](https://github.com/n8n-io/n8n/tree/master/docs) folder. So all changes
|
|
||||||
and additions can directly be made in there
|
|
||||||
|
|
||||||
That the markdown docs look pretty we use [docsify](https://docsify.js.org). It is possible to test
|
|
||||||
locally how it looks like rendered with the following commands:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. Install docisify
|
|
||||||
npm i docsify-cli -g
|
|
||||||
|
|
||||||
# 2. Go into n8n folder (the same folder which contains this file). For example:
|
|
||||||
cd /data/n8n
|
|
||||||
|
|
||||||
# 3. Start docsificy
|
|
||||||
docsify serve ./docs
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Contributor License Agreement
|
## Contributor License Agreement
|
||||||
|
|
17
README.md
17
README.md
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
n8n is a free and open [fair-code](http://faircode.io) licensed node based Workflow Automation Tool. It can be self-hosted, easily extended, and so also used with internal tools.
|
n8n is an extendable workflow automation tool. With a [fair-code](http://faircode.io) distribution model, n8n will always have visible source code, be available to self-host, and allow you to add your own custom functions, logic and apps. n8n's node-based approach makes it highly versatile, enabling you to connect anything to everything.
|
||||||
|
|
||||||
<a href="https://raw.githubusercontent.com/n8n-io/n8n/master/assets/n8n-screenshot.png"><img src="https://raw.githubusercontent.com/n8n-io/n8n/master/assets/n8n-screenshot.png" width="550" alt="n8n.io - Screenshot"></a>
|
<a href="https://raw.githubusercontent.com/n8n-io/n8n/master/assets/n8n-screenshot.png"><img src="https://raw.githubusercontent.com/n8n-io/n8n/master/assets/n8n-screenshot.png" width="550" alt="n8n.io - Screenshot"></a>
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ received or lost a star.
|
||||||
|
|
||||||
## Available integrations
|
## Available integrations
|
||||||
|
|
||||||
n8n has 100+ different nodes to automate workflows. The list can be found on: [https://n8n.io/nodes](https://n8n.io/nodes)
|
n8n has 170+ different nodes to automate workflows. The list can be found on: [https://n8n.io/nodes](https://n8n.io/nodes)
|
||||||
|
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
@ -67,16 +67,15 @@ check out our job posts:
|
||||||
|
|
||||||
**Short answer:** It means "nodemation" and it is pronounced as n-eight-n.
|
**Short answer:** It means "nodemation" and it is pronounced as n-eight-n.
|
||||||
|
|
||||||
**Long answer:** I get that question quite often (more often than I expected)
|
**Long answer:** "I get that question quite often (more often than I expected)
|
||||||
so I decided it is probably best to answer it here. While looking for a
|
so I decided it is probably best to answer it here. While looking for a
|
||||||
good name for the project with a free domain I realized very quickly that all the
|
good name for the project with a free domain I realized very quickly that all the
|
||||||
good ones I could think of were already taken. So, in the end, I chose
|
good ones I could think of were already taken. So, in the end, I chose
|
||||||
nodemation. "node-" in the sense that it uses a Node-View and that it uses
|
nodemation. 'node-' in the sense that it uses a Node-View and that it uses
|
||||||
Node.js and "-mation" for "automation" which is what the project is supposed to help with.
|
Node.js and '-mation' for 'automation' which is what the project is supposed to help with.
|
||||||
However, I did not like how long the name was and I could not imagine writing
|
However, I did not like how long the name was and I could not imagine writing
|
||||||
something that long every time in the CLI. That is when I then ended up on
|
something that long every time in the CLI. That is when I then ended up on
|
||||||
"n8n". Sure does not work perfectly but does neither for Kubernetes (k8s) and
|
'n8n'." - **Jan Oberhauser, Founder and CEO, n8n.io**
|
||||||
did not hear anybody complain there. So I guess it should be ok.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -88,6 +87,6 @@ Have you found a bug :bug: ? Or maybe you have a nice feature :sparkles: to cont
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
n8n is [fair-code](http://faircode.io) licensed under [**Apache 2.0 with Commons Clause**](https://github.com/n8n-io/n8n/blob/master/packages/cli/LICENSE.md)
|
n8n is [fair-code](http://faircode.io) licensed under [**Apache 2.0 with Commons Clause**](https://github.com/n8n-io/n8n/blob/master/packages/cli/LICENSE.md).
|
||||||
|
|
||||||
Additional information about license can be found in the [FAQ](https://docs.n8n.io/#/faq?id=license)
|
Additional information about license can be found in the [FAQ](https://docs.n8n.io/#/faq?id=license).
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "n8n",
|
"name": "n8n",
|
||||||
"version": "0.79.0",
|
"version": "0.79.3",
|
||||||
"description": "n8n Workflow Automation Tool",
|
"description": "n8n Workflow Automation Tool",
|
||||||
"license": "SEE LICENSE IN LICENSE.md",
|
"license": "SEE LICENSE IN LICENSE.md",
|
||||||
"homepage": "https://n8n.io",
|
"homepage": "https://n8n.io",
|
||||||
|
@ -102,7 +102,7 @@
|
||||||
"mysql2": "^2.0.1",
|
"mysql2": "^2.0.1",
|
||||||
"n8n-core": "~0.43.0",
|
"n8n-core": "~0.43.0",
|
||||||
"n8n-editor-ui": "~0.55.0",
|
"n8n-editor-ui": "~0.55.0",
|
||||||
"n8n-nodes-base": "~0.74.0",
|
"n8n-nodes-base": "~0.74.1",
|
||||||
"n8n-workflow": "~0.39.0",
|
"n8n-workflow": "~0.39.0",
|
||||||
"oauth-1.0a": "^2.2.6",
|
"oauth-1.0a": "^2.2.6",
|
||||||
"open": "^7.0.0",
|
"open": "^7.0.0",
|
||||||
|
|
|
@ -52,6 +52,9 @@ export class ActiveWorkflowRunner {
|
||||||
// so intead of pulling all the active wehhooks just pull the actives that have a trigger
|
// 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[];
|
const workflowsData: IWorkflowDb[] = await Db.collections.Workflow!.find({ active: true }) as IWorkflowDb[];
|
||||||
|
|
||||||
|
// Clear up active workflow table
|
||||||
|
await Db.collections.Webhook?.clear();
|
||||||
|
|
||||||
this.activeWorkflows = new ActiveWorkflows();
|
this.activeWorkflows = new ActiveWorkflows();
|
||||||
|
|
||||||
if (workflowsData.length !== 0) {
|
if (workflowsData.length !== 0) {
|
||||||
|
@ -59,22 +62,14 @@ export class ActiveWorkflowRunner {
|
||||||
console.log(' Start Active Workflows:');
|
console.log(' Start Active Workflows:');
|
||||||
console.log(' ================================');
|
console.log(' ================================');
|
||||||
|
|
||||||
const nodeTypes = NodeTypes();
|
|
||||||
|
|
||||||
for (const workflowData of workflowsData) {
|
for (const workflowData of workflowsData) {
|
||||||
|
console.log(` - ${workflowData.name}`);
|
||||||
const workflow = new Workflow({ id: workflowData.id.toString(), name: workflowData.name, nodes: workflowData.nodes, connections: workflowData.connections, active: workflowData.active, nodeTypes, staticData: workflowData.staticData, settings: workflowData.settings});
|
try {
|
||||||
|
await this.add(workflowData.id.toString(), workflowData);
|
||||||
if (workflow.getTriggerNodes().length !== 0
|
console.log(` => Started`);
|
||||||
|| workflow.getPollNodes().length !== 0) {
|
} catch (error) {
|
||||||
console.log(` - ${workflowData.name}`);
|
console.log(` => ERROR: Workflow could not be activated:`);
|
||||||
try {
|
console.log(` ${error.message}`);
|
||||||
await this.add(workflowData.id.toString(), workflowData);
|
|
||||||
console.log(` => Started`);
|
|
||||||
} catch (error) {
|
|
||||||
console.log(` => ERROR: Workflow could not be activated:`);
|
|
||||||
console.log(` ${error.message}`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,14 +82,18 @@ export class ActiveWorkflowRunner {
|
||||||
* @memberof ActiveWorkflowRunner
|
* @memberof ActiveWorkflowRunner
|
||||||
*/
|
*/
|
||||||
async removeAll(): Promise<void> {
|
async removeAll(): Promise<void> {
|
||||||
if (this.activeWorkflows === null) {
|
const activeWorkflowId: string[] = [];
|
||||||
return;
|
|
||||||
|
if (this.activeWorkflows !== null) {
|
||||||
|
// TODO: This should be renamed!
|
||||||
|
activeWorkflowId.push.apply(activeWorkflowId, this.activeWorkflows.allActiveWorkflows());
|
||||||
}
|
}
|
||||||
|
|
||||||
const activeWorkflows = this.activeWorkflows.allActiveWorkflows();
|
const activeWorkflows = await this.getActiveWorkflows();
|
||||||
|
activeWorkflowId.push.apply(activeWorkflowId, activeWorkflows.map(workflow => workflow.id));
|
||||||
|
|
||||||
const removePromises = [];
|
const removePromises = [];
|
||||||
for (const workflowId of activeWorkflows) {
|
for (const workflowId of activeWorkflowId) {
|
||||||
removePromises.push(this.remove(workflowId));
|
removePromises.push(this.remove(workflowId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,7 +182,7 @@ export class ActiveWorkflowRunner {
|
||||||
* @memberof ActiveWorkflowRunner
|
* @memberof ActiveWorkflowRunner
|
||||||
*/
|
*/
|
||||||
getActiveWorkflows(): Promise<IWorkflowDb[]> {
|
getActiveWorkflows(): Promise<IWorkflowDb[]> {
|
||||||
return Db.collections.Workflow?.find({ select: ['id'] }) as Promise<IWorkflowDb[]>;
|
return Db.collections.Workflow?.find({ where: { active: true }, select: ['id'] }) as Promise<IWorkflowDb[]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -249,7 +249,7 @@ class App {
|
||||||
if (token === undefined || token === '') {
|
if (token === undefined || token === '') {
|
||||||
return ResponseHelper.jwtAuthAuthorizationError(res, "Missing token");
|
return ResponseHelper.jwtAuthAuthorizationError(res, "Missing token");
|
||||||
}
|
}
|
||||||
if (jwtHeaderValuePrefix != '' && token.startsWith(jwtHeaderValuePrefix)) {
|
if (jwtHeaderValuePrefix !== '' && token.startsWith(jwtHeaderValuePrefix)) {
|
||||||
token = token.replace(jwtHeaderValuePrefix + ' ', '').trimLeft();
|
token = token.replace(jwtHeaderValuePrefix + ' ', '').trimLeft();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,7 +340,12 @@ class App {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
//support application/x-www-form-urlencoded post data
|
//support application/x-www-form-urlencoded post data
|
||||||
this.app.use(bodyParser.urlencoded({ extended: false }));
|
this.app.use(bodyParser.urlencoded({ extended: false,
|
||||||
|
verify: (req, res, buf) => {
|
||||||
|
// @ts-ignore
|
||||||
|
req.rawBody = buf;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
if (process.env['NODE_ENV'] !== 'production') {
|
if (process.env['NODE_ENV'] !== 'production') {
|
||||||
this.app.use((req: express.Request, res: express.Response, next: express.NextFunction) => {
|
this.app.use((req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||||
|
|
|
@ -2,20 +2,6 @@ import {
|
||||||
MigrationInterface,
|
MigrationInterface,
|
||||||
} from 'typeorm';
|
} from 'typeorm';
|
||||||
|
|
||||||
import {
|
|
||||||
IWorkflowDb,
|
|
||||||
NodeTypes,
|
|
||||||
WebhookHelpers,
|
|
||||||
} from '../../..';
|
|
||||||
|
|
||||||
import {
|
|
||||||
Workflow,
|
|
||||||
} from 'n8n-workflow/dist/src/Workflow';
|
|
||||||
|
|
||||||
import {
|
|
||||||
IWebhookDb,
|
|
||||||
} from '../../../Interfaces';
|
|
||||||
|
|
||||||
import * as config from '../../../../config';
|
import * as config from '../../../../config';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -27,26 +13,6 @@ export class WebhookModel1592679094242 implements MigrationInterface {
|
||||||
|
|
||||||
async up(queryRunner: MongoQueryRunner): Promise<void> {
|
async up(queryRunner: MongoQueryRunner): Promise<void> {
|
||||||
const tablePrefix = config.get('database.tablePrefix');
|
const tablePrefix = config.get('database.tablePrefix');
|
||||||
const workflows = await queryRunner.cursor( `${tablePrefix}workflow_entity`, { active: true }).toArray() as IWorkflowDb[];
|
|
||||||
const data: IWebhookDb[] = [];
|
|
||||||
const nodeTypes = NodeTypes();
|
|
||||||
for (const workflow of workflows) {
|
|
||||||
const workflowInstance = new Workflow({ id: workflow.id as string, name: workflow.name, nodes: workflow.nodes, connections: workflow.connections, active: workflow.active, nodeTypes, staticData: workflow.staticData, settings: workflow.settings });
|
|
||||||
const webhooks = WebhookHelpers.getWorkflowWebhooksBasic(workflowInstance);
|
|
||||||
for (const webhook of webhooks) {
|
|
||||||
data.push({
|
|
||||||
workflowId: workflowInstance.id as string,
|
|
||||||
webhookPath: webhook.path,
|
|
||||||
method: webhook.httpMethod,
|
|
||||||
node: webhook.node,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.length !== 0) {
|
|
||||||
await queryRunner.manager.insertMany(`${tablePrefix}webhook_entity`, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
await queryRunner.manager.createCollectionIndex(`${tablePrefix}webhook_entity`, ['webhookPath', 'method'], { unique: true, background: false });
|
await queryRunner.manager.createCollectionIndex(`${tablePrefix}webhook_entity`, ['webhookPath', 'method'], { unique: true, background: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,20 +5,6 @@ import {
|
||||||
|
|
||||||
import * as config from '../../../../config';
|
import * as config from '../../../../config';
|
||||||
|
|
||||||
import {
|
|
||||||
IWorkflowDb,
|
|
||||||
NodeTypes,
|
|
||||||
WebhookHelpers,
|
|
||||||
} from '../../..';
|
|
||||||
|
|
||||||
import {
|
|
||||||
Workflow,
|
|
||||||
} from 'n8n-workflow';
|
|
||||||
|
|
||||||
import {
|
|
||||||
IWebhookDb,
|
|
||||||
} from '../../../Interfaces';
|
|
||||||
|
|
||||||
export class WebhookModel1592447867632 implements MigrationInterface {
|
export class WebhookModel1592447867632 implements MigrationInterface {
|
||||||
name = 'WebhookModel1592447867632';
|
name = 'WebhookModel1592447867632';
|
||||||
|
|
||||||
|
@ -26,30 +12,6 @@ export class WebhookModel1592447867632 implements MigrationInterface {
|
||||||
const tablePrefix = config.get('database.tablePrefix');
|
const tablePrefix = config.get('database.tablePrefix');
|
||||||
|
|
||||||
await queryRunner.query(`CREATE TABLE IF NOT EXISTS ${tablePrefix}webhook_entity (workflowId int NOT NULL, webhookPath varchar(255) NOT NULL, method varchar(255) NOT NULL, node varchar(255) NOT NULL, PRIMARY KEY (webhookPath, method)) ENGINE=InnoDB`);
|
await queryRunner.query(`CREATE TABLE IF NOT EXISTS ${tablePrefix}webhook_entity (workflowId int NOT NULL, webhookPath varchar(255) NOT NULL, method varchar(255) NOT NULL, node varchar(255) NOT NULL, PRIMARY KEY (webhookPath, method)) ENGINE=InnoDB`);
|
||||||
|
|
||||||
const workflows = await queryRunner.query(`SELECT * FROM ${tablePrefix}workflow_entity WHERE active=true`) as IWorkflowDb[];
|
|
||||||
const data: IWebhookDb[] = [];
|
|
||||||
const nodeTypes = NodeTypes();
|
|
||||||
for (const workflow of workflows) {
|
|
||||||
const workflowInstance = new Workflow({ id: workflow.id as string, name: workflow.name, nodes: workflow.nodes, connections: workflow.connections, active: workflow.active, nodeTypes, staticData: workflow.staticData, settings: workflow.settings });
|
|
||||||
const webhooks = WebhookHelpers.getWorkflowWebhooksBasic(workflowInstance);
|
|
||||||
for (const webhook of webhooks) {
|
|
||||||
data.push({
|
|
||||||
workflowId: workflowInstance.id as string,
|
|
||||||
webhookPath: webhook.path,
|
|
||||||
method: webhook.httpMethod,
|
|
||||||
node: webhook.node,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.length !== 0) {
|
|
||||||
await queryRunner.manager.createQueryBuilder()
|
|
||||||
.insert()
|
|
||||||
.into(`${tablePrefix}webhook_entity`)
|
|
||||||
.values(data)
|
|
||||||
.execute();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async down(queryRunner: QueryRunner): Promise<void> {
|
async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
|
|
@ -3,20 +3,6 @@ import {
|
||||||
QueryRunner,
|
QueryRunner,
|
||||||
} from 'typeorm';
|
} from 'typeorm';
|
||||||
|
|
||||||
import {
|
|
||||||
IWorkflowDb,
|
|
||||||
NodeTypes,
|
|
||||||
WebhookHelpers,
|
|
||||||
} from '../../..';
|
|
||||||
|
|
||||||
import {
|
|
||||||
Workflow,
|
|
||||||
} from 'n8n-workflow';
|
|
||||||
|
|
||||||
import {
|
|
||||||
IWebhookDb,
|
|
||||||
} from '../../../Interfaces';
|
|
||||||
|
|
||||||
import * as config from '../../../../config';
|
import * as config from '../../../../config';
|
||||||
|
|
||||||
export class WebhookModel1589476000887 implements MigrationInterface {
|
export class WebhookModel1589476000887 implements MigrationInterface {
|
||||||
|
@ -31,30 +17,6 @@ export class WebhookModel1589476000887 implements MigrationInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
await queryRunner.query(`CREATE TABLE ${tablePrefix}webhook_entity ("workflowId" integer NOT NULL, "webhookPath" character varying NOT NULL, "method" character varying NOT NULL, "node" character varying NOT NULL, CONSTRAINT "PK_${tablePrefixIndex}b21ace2e13596ccd87dc9bf4ea6" PRIMARY KEY ("webhookPath", "method"))`, undefined);
|
await queryRunner.query(`CREATE TABLE ${tablePrefix}webhook_entity ("workflowId" integer NOT NULL, "webhookPath" character varying NOT NULL, "method" character varying NOT NULL, "node" character varying NOT NULL, CONSTRAINT "PK_${tablePrefixIndex}b21ace2e13596ccd87dc9bf4ea6" PRIMARY KEY ("webhookPath", "method"))`, undefined);
|
||||||
|
|
||||||
const workflows = await queryRunner.query(`SELECT * FROM ${tablePrefix}workflow_entity WHERE active=true`) as IWorkflowDb[];
|
|
||||||
const data: IWebhookDb[] = [];
|
|
||||||
const nodeTypes = NodeTypes();
|
|
||||||
for (const workflow of workflows) {
|
|
||||||
const workflowInstance = new Workflow({ id: workflow.id as string, name: workflow.name, nodes: workflow.nodes, connections: workflow.connections, active: workflow.active, nodeTypes, staticData: workflow.staticData, settings: workflow.settings });
|
|
||||||
const webhooks = WebhookHelpers.getWorkflowWebhooksBasic(workflowInstance);
|
|
||||||
for (const webhook of webhooks) {
|
|
||||||
data.push({
|
|
||||||
workflowId: workflowInstance.id as string,
|
|
||||||
webhookPath: webhook.path,
|
|
||||||
method: webhook.httpMethod,
|
|
||||||
node: webhook.node,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.length !== 0) {
|
|
||||||
await queryRunner.manager.createQueryBuilder()
|
|
||||||
.insert()
|
|
||||||
.into(`${tablePrefix}webhook_entity`)
|
|
||||||
.values(data)
|
|
||||||
.execute();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async down(queryRunner: QueryRunner): Promise<void> {
|
async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
|
|
@ -5,20 +5,6 @@ import {
|
||||||
|
|
||||||
import * as config from '../../../../config';
|
import * as config from '../../../../config';
|
||||||
|
|
||||||
import {
|
|
||||||
IWorkflowDb,
|
|
||||||
NodeTypes,
|
|
||||||
WebhookHelpers,
|
|
||||||
} from '../../..';
|
|
||||||
|
|
||||||
import {
|
|
||||||
Workflow,
|
|
||||||
} from 'n8n-workflow';
|
|
||||||
|
|
||||||
import {
|
|
||||||
IWebhookDb,
|
|
||||||
} from '../../../Interfaces';
|
|
||||||
|
|
||||||
export class WebhookModel1592445003908 implements MigrationInterface {
|
export class WebhookModel1592445003908 implements MigrationInterface {
|
||||||
name = 'WebhookModel1592445003908';
|
name = 'WebhookModel1592445003908';
|
||||||
|
|
||||||
|
@ -26,34 +12,6 @@ export class WebhookModel1592445003908 implements MigrationInterface {
|
||||||
const tablePrefix = config.get('database.tablePrefix');
|
const tablePrefix = config.get('database.tablePrefix');
|
||||||
|
|
||||||
await queryRunner.query(`CREATE TABLE IF NOT EXISTS ${tablePrefix}webhook_entity ("workflowId" integer NOT NULL, "webhookPath" varchar NOT NULL, "method" varchar NOT NULL, "node" varchar NOT NULL, PRIMARY KEY ("webhookPath", "method"))`);
|
await queryRunner.query(`CREATE TABLE IF NOT EXISTS ${tablePrefix}webhook_entity ("workflowId" integer NOT NULL, "webhookPath" varchar NOT NULL, "method" varchar NOT NULL, "node" varchar NOT NULL, PRIMARY KEY ("webhookPath", "method"))`);
|
||||||
|
|
||||||
const workflows = await queryRunner.query(`SELECT * FROM ${tablePrefix}workflow_entity WHERE active=true`) as IWorkflowDb[];
|
|
||||||
const data: IWebhookDb[] = [];
|
|
||||||
const nodeTypes = NodeTypes();
|
|
||||||
for (const workflow of workflows) {
|
|
||||||
workflow.nodes = JSON.parse(workflow.nodes as unknown as string);
|
|
||||||
workflow.connections = JSON.parse(workflow.connections as unknown as string);
|
|
||||||
workflow.staticData = JSON.parse(workflow.staticData as unknown as string);
|
|
||||||
workflow.settings = JSON.parse(workflow.settings as unknown as string);
|
|
||||||
const workflowInstance = new Workflow({ id: workflow.id as string, name: workflow.name, nodes: workflow.nodes, connections: workflow.connections, active: workflow.active, nodeTypes, staticData: workflow.staticData, settings: workflow.settings });
|
|
||||||
const webhooks = WebhookHelpers.getWorkflowWebhooksBasic(workflowInstance);
|
|
||||||
for (const webhook of webhooks) {
|
|
||||||
data.push({
|
|
||||||
workflowId: workflowInstance.id as string,
|
|
||||||
webhookPath: webhook.path,
|
|
||||||
method: webhook.httpMethod,
|
|
||||||
node: webhook.node,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.length !== 0) {
|
|
||||||
await queryRunner.manager.createQueryBuilder()
|
|
||||||
.insert()
|
|
||||||
.into(`${tablePrefix}webhook_entity`)
|
|
||||||
.values(data)
|
|
||||||
.execute();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async down(queryRunner: QueryRunner): Promise<void> {
|
async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
|
|
@ -58,7 +58,7 @@
|
||||||
"change-case": "^4.1.1",
|
"change-case": "^4.1.1",
|
||||||
"copyfiles": "^2.1.1",
|
"copyfiles": "^2.1.1",
|
||||||
"inquirer": "^7.0.1",
|
"inquirer": "^7.0.1",
|
||||||
"n8n-core": "^0.36.0",
|
"n8n-core": "^0.43.0",
|
||||||
"n8n-workflow": "^0.33.0",
|
"n8n-workflow": "^0.33.0",
|
||||||
"replace-in-file": "^6.0.0",
|
"replace-in-file": "^6.0.0",
|
||||||
"request": "^2.88.2",
|
"request": "^2.88.2",
|
||||||
|
|
|
@ -24,7 +24,7 @@ export async function acuitySchedulingApiRequest(this: IHookFunctions | IExecute
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (authenticationMethod === 'accessToken') {
|
if (authenticationMethod === 'apiKey') {
|
||||||
const credentials = this.getCredentials('acuitySchedulingApi');
|
const credentials = this.getCredentials('acuitySchedulingApi');
|
||||||
if (credentials === undefined) {
|
if (credentials === undefined) {
|
||||||
throw new Error('No credentials got returned!');
|
throw new Error('No credentials got returned!');
|
||||||
|
|
|
@ -371,8 +371,8 @@ export class ClickUp implements INodeType {
|
||||||
const body: IDataObject = {
|
const body: IDataObject = {
|
||||||
name,
|
name,
|
||||||
};
|
};
|
||||||
if (additionalFields.assigneeId) {
|
if (additionalFields.assignee) {
|
||||||
body.assignee = parseInt(additionalFields.assigneeId as string, 10);
|
body.assignee = parseInt(additionalFields.assignee as string, 10);
|
||||||
}
|
}
|
||||||
responseData = await clickupApiRequest.call(this, 'POST', `/checklist/${checklistId}/checklist_item`, body);
|
responseData = await clickupApiRequest.call(this, 'POST', `/checklist/${checklistId}/checklist_item`, body);
|
||||||
responseData = responseData.checklist;
|
responseData = responseData.checklist;
|
||||||
|
@ -414,7 +414,7 @@ export class ClickUp implements INodeType {
|
||||||
comment_text: commentText,
|
comment_text: commentText,
|
||||||
};
|
};
|
||||||
if (additionalFields.assignee) {
|
if (additionalFields.assignee) {
|
||||||
body.assigneeId = additionalFields.assignee as string;
|
body.assignee = parseInt(additionalFields.assignee as string, 10);
|
||||||
}
|
}
|
||||||
if (additionalFields.notifyAll) {
|
if (additionalFields.notifyAll) {
|
||||||
body.notify_all = additionalFields.notifyAll as boolean;
|
body.notify_all = additionalFields.notifyAll as boolean;
|
||||||
|
|
|
@ -192,26 +192,6 @@ export const fields = [
|
||||||
default: '',
|
default: '',
|
||||||
description: ' Full-text search is case insensitive and might return more results than expected. A query will only take values with more than 1 character.',
|
description: ' Full-text search is case insensitive and might return more results than expected. A query will only take values with more than 1 character.',
|
||||||
},
|
},
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
displayName: 'Options',
|
|
||||||
name: 'options',
|
|
||||||
type: 'collection',
|
|
||||||
placeholder: 'Select Option',
|
|
||||||
default: {},
|
|
||||||
displayOptions: {
|
|
||||||
show: {
|
|
||||||
resource: [
|
|
||||||
resource.value,
|
|
||||||
],
|
|
||||||
operation: [
|
|
||||||
'getAll',
|
|
||||||
'get'
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
options: [
|
|
||||||
{
|
{
|
||||||
displayName: 'RAW Data',
|
displayName: 'RAW Data',
|
||||||
name: 'rawData',
|
name: 'rawData',
|
||||||
|
|
|
@ -67,10 +67,10 @@ export const fields = [
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Options',
|
displayName: 'Additional Fields',
|
||||||
name: 'options',
|
name: 'additionalFields',
|
||||||
type: 'collection',
|
type: 'collection',
|
||||||
placeholder: 'Select Option',
|
placeholder: 'Add Field',
|
||||||
default: {},
|
default: {},
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
show: {
|
show: {
|
||||||
|
|
|
@ -118,11 +118,11 @@ export class Contentful implements INodeType {
|
||||||
|
|
||||||
const id = this.getNodeParameter('contentTypeId', 0) as string;
|
const id = this.getNodeParameter('contentTypeId', 0) as string;
|
||||||
|
|
||||||
const options = this.getNodeParameter('options', i) as IDataObject;
|
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
|
||||||
|
|
||||||
responseData = await contentfulApiRequest.call(this, 'GET', `/spaces/${credentials?.spaceId}/environments/${env}/content_types/${id}`);
|
responseData = await contentfulApiRequest.call(this, 'GET', `/spaces/${credentials?.spaceId}/environments/${env}/content_types/${id}`);
|
||||||
|
|
||||||
if (!options.rawData) {
|
if (!additionalFields.rawData) {
|
||||||
responseData = responseData.fields;
|
responseData = responseData.fields;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,11 +137,11 @@ export class Contentful implements INodeType {
|
||||||
|
|
||||||
const id = this.getNodeParameter('entryId', 0) as string;
|
const id = this.getNodeParameter('entryId', 0) as string;
|
||||||
|
|
||||||
const options = this.getNodeParameter('options', i) as IDataObject;
|
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
|
||||||
|
|
||||||
responseData = await contentfulApiRequest.call(this, 'GET', `/spaces/${credentials?.spaceId}/environments/${env}/entries/${id}`, {}, qs);
|
responseData = await contentfulApiRequest.call(this, 'GET', `/spaces/${credentials?.spaceId}/environments/${env}/entries/${id}`, {}, qs);
|
||||||
|
|
||||||
if (!options.rawData) {
|
if (!additionalFields.rawData) {
|
||||||
responseData = responseData.fields;
|
responseData = responseData.fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,11 +151,11 @@ export class Contentful implements INodeType {
|
||||||
const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
|
const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
|
||||||
|
|
||||||
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
|
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
|
||||||
|
const rawData = additionalFields.rawData;
|
||||||
|
additionalFields.rawData = undefined;
|
||||||
|
|
||||||
const env = this.getNodeParameter('environmentId', i) as string;
|
const env = this.getNodeParameter('environmentId', i) as string;
|
||||||
|
|
||||||
const options = this.getNodeParameter('options', i) as IDataObject;
|
|
||||||
|
|
||||||
Object.assign(qs, additionalFields);
|
Object.assign(qs, additionalFields);
|
||||||
|
|
||||||
if (qs.equal) {
|
if (qs.equal) {
|
||||||
|
@ -185,7 +185,7 @@ export class Contentful implements INodeType {
|
||||||
if (returnAll) {
|
if (returnAll) {
|
||||||
responseData = await contenfulApiRequestAllItems.call(this, 'items', 'GET', `/spaces/${credentials?.spaceId}/environments/${env}/entries`, {}, qs);
|
responseData = await contenfulApiRequestAllItems.call(this, 'items', 'GET', `/spaces/${credentials?.spaceId}/environments/${env}/entries`, {}, qs);
|
||||||
|
|
||||||
if (!options.rawData) {
|
if (!rawData) {
|
||||||
const assets : IDataObject[] = [];
|
const assets : IDataObject[] = [];
|
||||||
// tslint:disable-next-line: no-any
|
// tslint:disable-next-line: no-any
|
||||||
responseData.map((asset : any) => {
|
responseData.map((asset : any) => {
|
||||||
|
@ -199,7 +199,7 @@ export class Contentful implements INodeType {
|
||||||
responseData = await contentfulApiRequest.call(this, 'GET', `/spaces/${credentials?.spaceId}/environments/${env}/entries`, {}, qs);
|
responseData = await contentfulApiRequest.call(this, 'GET', `/spaces/${credentials?.spaceId}/environments/${env}/entries`, {}, qs);
|
||||||
responseData = responseData.items;
|
responseData = responseData.items;
|
||||||
|
|
||||||
if (!options.rawData) {
|
if (!rawData) {
|
||||||
const assets : IDataObject[] = [];
|
const assets : IDataObject[] = [];
|
||||||
// tslint:disable-next-line: no-any
|
// tslint:disable-next-line: no-any
|
||||||
responseData.map((asset : any) => {
|
responseData.map((asset : any) => {
|
||||||
|
@ -219,11 +219,11 @@ export class Contentful implements INodeType {
|
||||||
|
|
||||||
const id = this.getNodeParameter('assetId', 0) as string;
|
const id = this.getNodeParameter('assetId', 0) as string;
|
||||||
|
|
||||||
const options = this.getNodeParameter('options', i) as IDataObject;
|
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
|
||||||
|
|
||||||
responseData = await contentfulApiRequest.call(this, 'GET', `/spaces/${credentials?.spaceId}/environments/${env}/assets/${id}`, {}, qs);
|
responseData = await contentfulApiRequest.call(this, 'GET', `/spaces/${credentials?.spaceId}/environments/${env}/assets/${id}`, {}, qs);
|
||||||
|
|
||||||
if (!options.rawData) {
|
if (!additionalFields.rawData) {
|
||||||
responseData = responseData.fields;
|
responseData = responseData.fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,11 +234,11 @@ export class Contentful implements INodeType {
|
||||||
const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
|
const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
|
||||||
|
|
||||||
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
|
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
|
||||||
|
const rawData = additionalFields.rawData;
|
||||||
|
additionalFields.rawData = undefined;
|
||||||
|
|
||||||
const env = this.getNodeParameter('environmentId', i) as string;
|
const env = this.getNodeParameter('environmentId', i) as string;
|
||||||
|
|
||||||
const options = this.getNodeParameter('options', i) as IDataObject;
|
|
||||||
|
|
||||||
Object.assign(qs, additionalFields);
|
Object.assign(qs, additionalFields);
|
||||||
|
|
||||||
if (qs.equal) {
|
if (qs.equal) {
|
||||||
|
@ -268,7 +268,7 @@ export class Contentful implements INodeType {
|
||||||
if (returnAll) {
|
if (returnAll) {
|
||||||
responseData = await contenfulApiRequestAllItems.call(this, 'items', 'GET', `/spaces/${credentials?.spaceId}/environments/${env}/assets`, {}, qs);
|
responseData = await contenfulApiRequestAllItems.call(this, 'items', 'GET', `/spaces/${credentials?.spaceId}/environments/${env}/assets`, {}, qs);
|
||||||
|
|
||||||
if (!options.rawData) {
|
if (!rawData) {
|
||||||
const assets : IDataObject[] = [];
|
const assets : IDataObject[] = [];
|
||||||
// tslint:disable-next-line: no-any
|
// tslint:disable-next-line: no-any
|
||||||
responseData.map((asset : any) => {
|
responseData.map((asset : any) => {
|
||||||
|
@ -277,12 +277,12 @@ export class Contentful implements INodeType {
|
||||||
responseData = assets;
|
responseData = assets;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const limit = this.getNodeParameter('limit', 0) as number;
|
const limit = this.getNodeParameter('limit', i) as number;
|
||||||
qs.limit = limit;
|
qs.limit = limit;
|
||||||
responseData = await contentfulApiRequest.call(this, 'GET', `/spaces/${credentials?.spaceId}/environments/${env}/assets`, {}, qs);
|
responseData = await contentfulApiRequest.call(this, 'GET', `/spaces/${credentials?.spaceId}/environments/${env}/assets`, {}, qs);
|
||||||
responseData = responseData.items;
|
responseData = responseData.items;
|
||||||
|
|
||||||
if (!options.rawData) {
|
if (!rawData) {
|
||||||
const assets : IDataObject[] = [];
|
const assets : IDataObject[] = [];
|
||||||
// tslint:disable-next-line: no-any
|
// tslint:disable-next-line: no-any
|
||||||
responseData.map((asset : any) => {
|
responseData.map((asset : any) => {
|
||||||
|
|
|
@ -182,6 +182,13 @@ export const fields = [
|
||||||
default: '',
|
default: '',
|
||||||
description: ' Full-text search is case insensitive and might return more results than expected. A query will only take values with more than 1 character.',
|
description: ' Full-text search is case insensitive and might return more results than expected. A query will only take values with more than 1 character.',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
displayName: 'RAW Data',
|
||||||
|
name: 'rawData',
|
||||||
|
type: 'boolean',
|
||||||
|
default: false,
|
||||||
|
description: 'If the data should be returned RAW instead of parsed.',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -201,31 +208,4 @@ export const fields = [
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
displayName: 'Options',
|
|
||||||
name: 'options',
|
|
||||||
type: 'collection',
|
|
||||||
placeholder: 'Select Option',
|
|
||||||
default: {},
|
|
||||||
displayOptions: {
|
|
||||||
show: {
|
|
||||||
resource: [
|
|
||||||
resource.value,
|
|
||||||
],
|
|
||||||
operation: [
|
|
||||||
'get',
|
|
||||||
'getAll',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
displayName: 'RAW Data',
|
|
||||||
name: 'rawData',
|
|
||||||
type: 'boolean',
|
|
||||||
default: false,
|
|
||||||
description: 'If the data should be returned RAW instead of parsed.',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
] as INodeProperties[];
|
] as INodeProperties[];
|
||||||
|
|
|
@ -797,13 +797,14 @@ export class HttpRequest implements INodeType {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (responseFormat === 'json') {
|
if (requestOptions.headers!['accept'] === undefined) {
|
||||||
|
if (responseFormat === 'json') {
|
||||||
requestOptions.headers!['accept'] = 'application/json,text/*;q=0.99';
|
requestOptions.headers!['accept'] = 'application/json,text/*;q=0.99';
|
||||||
} else if (responseFormat === 'string') {
|
} else if (responseFormat === 'string') {
|
||||||
requestOptions.headers!['accept'] = 'application/json,text/html,application/xhtml+xml,application/xml,text/*;q=0.9, */*;q=0.1';
|
requestOptions.headers!['accept'] = 'application/json,text/html,application/xhtml+xml,application/xml,text/*;q=0.9, */*;q=0.1';
|
||||||
} else {
|
} else {
|
||||||
requestOptions.headers!['accept'] = 'application/json,text/html,application/xhtml+xml,application/xml,text/*;q=0.9, image/*;q=0.8, */*;q=0.7';
|
requestOptions.headers!['accept'] = 'application/json,text/html,application/xhtml+xml,application/xml,text/*;q=0.9, image/*;q=0.8, */*;q=0.7';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (responseFormat === 'file') {
|
if (responseFormat === 'file') {
|
||||||
|
|
|
@ -10,7 +10,7 @@ import {
|
||||||
|
|
||||||
export async function salesforceApiRequest(this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, method: string, resource: string, body: any = {}, qs: IDataObject = {}, uri?: string, option: IDataObject = {}): Promise<any> { // tslint:disable-line:no-any
|
export async function salesforceApiRequest(this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, method: string, resource: string, body: any = {}, qs: IDataObject = {}, uri?: string, option: IDataObject = {}): Promise<any> { // tslint:disable-line:no-any
|
||||||
const credentials = this.getCredentials('salesforceOAuth2Api');
|
const credentials = this.getCredentials('salesforceOAuth2Api');
|
||||||
const subdomain = ((credentials!.accessTokenUrl as string).match(/https:\/\/(.+).salesforce\.com/) || [])[1]
|
const subdomain = ((credentials!.accessTokenUrl as string).match(/https:\/\/(.+).salesforce\.com/) || [])[1];
|
||||||
const options: OptionsWithUri = {
|
const options: OptionsWithUri = {
|
||||||
method,
|
method,
|
||||||
body: method === "GET" ? undefined : body,
|
body: method === "GET" ? undefined : body,
|
||||||
|
|
|
@ -35,6 +35,11 @@ export const userOperations = [
|
||||||
value: 'getAll',
|
value: 'getAll',
|
||||||
description: 'Get all users',
|
description: 'Get all users',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'Search',
|
||||||
|
value: 'search',
|
||||||
|
description: 'Search users',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'Update',
|
name: 'Update',
|
||||||
value: 'update',
|
value: 'update',
|
||||||
|
@ -667,7 +672,81 @@ export const userFields = [
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/* user:search */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
{
|
||||||
|
displayName: 'Return All',
|
||||||
|
name: 'returnAll',
|
||||||
|
type: 'boolean',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
resource: [
|
||||||
|
'user',
|
||||||
|
],
|
||||||
|
operation: [
|
||||||
|
'search',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
default: false,
|
||||||
|
description: 'If all results should be returned or only up to a given limit.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Limit',
|
||||||
|
name: 'limit',
|
||||||
|
type: 'number',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
resource: [
|
||||||
|
'user',
|
||||||
|
],
|
||||||
|
operation: [
|
||||||
|
'search',
|
||||||
|
],
|
||||||
|
returnAll: [
|
||||||
|
false,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
typeOptions: {
|
||||||
|
minValue: 1,
|
||||||
|
maxValue: 100,
|
||||||
|
},
|
||||||
|
default: 100,
|
||||||
|
description: 'How many results to return.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Filters',
|
||||||
|
name: 'filters',
|
||||||
|
type: 'collection',
|
||||||
|
placeholder: 'Add Filter',
|
||||||
|
default: {},
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
resource: [
|
||||||
|
'user',
|
||||||
|
],
|
||||||
|
operation: [
|
||||||
|
'search',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
displayName: 'Query',
|
||||||
|
name: 'query',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'External ID',
|
||||||
|
name: 'external_id',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* user:delete */
|
/* user:delete */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
|
@ -477,6 +477,22 @@ export class Zendesk implements INodeType {
|
||||||
responseData = responseData.users;
|
responseData = responseData.users;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//https://developer.zendesk.com/rest_api/docs/support/users#search-users
|
||||||
|
if (operation === 'search') {
|
||||||
|
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
|
||||||
|
const options = this.getNodeParameter('filters', i) as IDataObject;
|
||||||
|
|
||||||
|
Object.assign(qs, options);
|
||||||
|
|
||||||
|
if (returnAll) {
|
||||||
|
responseData = await zendeskApiRequestAllItems.call(this, 'users', 'GET', `/users/search`, {}, qs);
|
||||||
|
} else {
|
||||||
|
const limit = this.getNodeParameter('limit', i) as number;
|
||||||
|
qs.per_page = limit;
|
||||||
|
responseData = await zendeskApiRequest.call(this, 'GET', `/users/search`, {}, qs);
|
||||||
|
responseData = responseData.users;
|
||||||
|
}
|
||||||
|
}
|
||||||
//https://developer.zendesk.com/rest_api/docs/support/users#delete-user
|
//https://developer.zendesk.com/rest_api/docs/support/users#delete-user
|
||||||
if (operation === 'delete') {
|
if (operation === 'delete') {
|
||||||
const userId = this.getNodeParameter('id', i) as string;
|
const userId = this.getNodeParameter('id', i) as string;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "n8n-nodes-base",
|
"name": "n8n-nodes-base",
|
||||||
"version": "0.74.0",
|
"version": "0.74.1",
|
||||||
"description": "Base nodes of n8n",
|
"description": "Base nodes of n8n",
|
||||||
"license": "SEE LICENSE IN LICENSE.md",
|
"license": "SEE LICENSE IN LICENSE.md",
|
||||||
"homepage": "https://n8n.io",
|
"homepage": "https://n8n.io",
|
||||||
|
|
Loading…
Reference in a new issue