From 00f54e780400e2f70db3b9be1f14b05e92d10e8b Mon Sep 17 00:00:00 2001 From: ricardo Date: Mon, 13 Jul 2020 16:03:41 -0400 Subject: [PATCH] :zap: Improvements --- packages/core/src/Interfaces.ts | 15 +++--- packages/core/src/NodeExecuteFunctions.ts | 47 ++++++++++++------- .../nodes-base/nodes/Box/GenericFunctions.ts | 10 +++- .../nodes/Hubspot/GenericFunctions.ts | 2 +- .../nodes/Mailchimp/GenericFunctions.ts | 2 +- .../nodes/Slack/GenericFunctions.ts | 9 +++- packages/workflow/src/Interfaces.ts | 1 - 7 files changed, 55 insertions(+), 31 deletions(-) diff --git a/packages/core/src/Interfaces.ts b/packages/core/src/Interfaces.ts index 5aa0e10a64..483cc1c0cd 100644 --- a/packages/core/src/Interfaces.ts +++ b/packages/core/src/Interfaces.ts @@ -15,6 +15,7 @@ import { ITriggerResponse, IWebhookFunctions as IWebhookFunctionsBase, IWorkflowSettings as IWorkflowSettingsWorkflow, + IOAuth2Options, } from 'n8n-workflow'; @@ -36,7 +37,7 @@ export interface IExecuteFunctions extends IExecuteFunctionsBase { helpers: { prepareBinaryData(binaryData: Buffer, filePath?: string, mimeType?: string): Promise; request: requestPromise.RequestPromiseAPI, - requestOAuth2(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUri | requestPromise.RequestPromiseOptions): Promise, // tslint:disable-line:no-any + requestOAuth2(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUri | requestPromise.RequestPromiseOptions, oAuth2Options?: IOAuth2Options): Promise, // tslint:disable-line:no-any requestOAuth1(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUrl | requestPromise.RequestPromiseOptions): Promise, // tslint:disable-line:no-any returnJsonArray(jsonData: IDataObject | IDataObject[]): INodeExecutionData[]; }; @@ -47,7 +48,7 @@ export interface IExecuteSingleFunctions extends IExecuteSingleFunctionsBase { helpers: { prepareBinaryData(binaryData: Buffer, filePath?: string, mimeType?: string): Promise; request: requestPromise.RequestPromiseAPI, - requestOAuth2(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUri | requestPromise.RequestPromiseOptions): Promise, // tslint:disable-line:no-any + requestOAuth2(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUri | requestPromise.RequestPromiseOptions, oAuth2Options?: IOAuth2Options): Promise, // tslint:disable-line:no-any requestOAuth1(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUrl | requestPromise.RequestPromiseOptions): Promise, // tslint:disable-line:no-any }; } @@ -57,7 +58,7 @@ export interface IPollFunctions extends IPollFunctionsBase { helpers: { prepareBinaryData(binaryData: Buffer, filePath?: string, mimeType?: string): Promise; request: requestPromise.RequestPromiseAPI, - requestOAuth2(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUri | requestPromise.RequestPromiseOptions): Promise, // tslint:disable-line:no-any + requestOAuth2(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUri | requestPromise.RequestPromiseOptions, oAuth2Options?: IOAuth2Options): Promise, // tslint:disable-line:no-any requestOAuth1(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUrl | requestPromise.RequestPromiseOptions): Promise, // tslint:disable-line:no-any returnJsonArray(jsonData: IDataObject | IDataObject[]): INodeExecutionData[]; }; @@ -73,7 +74,7 @@ export interface ITriggerFunctions extends ITriggerFunctionsBase { helpers: { prepareBinaryData(binaryData: Buffer, filePath?: string, mimeType?: string): Promise; request: requestPromise.RequestPromiseAPI, - requestOAuth2(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUri | requestPromise.RequestPromiseOptions): Promise, // tslint:disable-line:no-any + requestOAuth2(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUri | requestPromise.RequestPromiseOptions, oAuth2Options?: IOAuth2Options): Promise, // tslint:disable-line:no-any requestOAuth1(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUrl | requestPromise.RequestPromiseOptions): Promise, // tslint:disable-line:no-any returnJsonArray(jsonData: IDataObject | IDataObject[]): INodeExecutionData[]; }; @@ -98,7 +99,7 @@ export interface IUserSettings { export interface ILoadOptionsFunctions extends ILoadOptionsFunctionsBase { helpers: { request?: requestPromise.RequestPromiseAPI, - requestOAuth2?: (this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUri | requestPromise.RequestPromiseOptions) => Promise, // tslint:disable-line:no-any + requestOAuth2?: (this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUri | requestPromise.RequestPromiseOptions, oAuth2Options?: IOAuth2Options) => Promise, // tslint:disable-line:no-any requestOAuth1?(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUrl | requestPromise.RequestPromiseOptions): Promise, // tslint:disable-line:no-any }; } @@ -107,7 +108,7 @@ export interface ILoadOptionsFunctions extends ILoadOptionsFunctionsBase { export interface IHookFunctions extends IHookFunctionsBase { helpers: { request: requestPromise.RequestPromiseAPI, - requestOAuth2(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUri | requestPromise.RequestPromiseOptions): Promise, // tslint:disable-line:no-any + requestOAuth2(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUri | requestPromise.RequestPromiseOptions, oAuth2Options?: IOAuth2Options): Promise, // tslint:disable-line:no-any requestOAuth1(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUrl | requestPromise.RequestPromiseOptions): Promise, // tslint:disable-line:no-any }; } @@ -117,7 +118,7 @@ export interface IWebhookFunctions extends IWebhookFunctionsBase { helpers: { prepareBinaryData(binaryData: Buffer, filePath?: string, mimeType?: string): Promise; request: requestPromise.RequestPromiseAPI, - requestOAuth2(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUri | requestPromise.RequestPromiseOptions): Promise, // tslint:disable-line:no-any + requestOAuth2(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUri | requestPromise.RequestPromiseOptions, oAuth2Options?: IOAuth2Options): Promise, // tslint:disable-line:no-any requestOAuth1(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUrl | requestPromise.RequestPromiseOptions): Promise, // tslint:disable-line:no-any returnJsonArray(jsonData: IDataObject | IDataObject[]): INodeExecutionData[]; }; diff --git a/packages/core/src/NodeExecuteFunctions.ts b/packages/core/src/NodeExecuteFunctions.ts index d500d56f88..bbb445790e 100644 --- a/packages/core/src/NodeExecuteFunctions.ts +++ b/packages/core/src/NodeExecuteFunctions.ts @@ -34,6 +34,7 @@ import { Workflow, WorkflowDataProxy, WorkflowExecuteMode, + IOAuth2Options, } from 'n8n-workflow'; import * as clientOAuth1 from 'oauth-1.0a'; @@ -119,9 +120,10 @@ export async function prepareBinaryData(binaryData: Buffer, filePath?: string, m * @param {(OptionsWithUri | requestPromise.RequestPromiseOptions)} requestOptions * @param {INode} node * @param {IWorkflowExecuteAdditionalData} additionalData + * * @returns */ -export function requestOAuth2(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUri | requestPromise.RequestPromiseOptions, node: INode, additionalData: IWorkflowExecuteAdditionalData, tokenType?: string, property?: string) { +export function requestOAuth2(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUri | requestPromise.RequestPromiseOptions, node: INode, additionalData: IWorkflowExecuteAdditionalData, oAuth2Options?: IOAuth2Options) { const credentials = this.getCredentials(credentialsType) as ICredentialDataDecryptedObject; if (credentials === undefined) { @@ -140,7 +142,7 @@ export function requestOAuth2(this: IAllExecuteFunctions, credentialsType: strin const oauthTokenData = credentials.oauthTokenData as clientOAuth2.Data; - const token = oAuthClient.createToken(get(oauthTokenData, property as string) || oauthTokenData.accessToken, oauthTokenData.refreshToken, tokenType || oauthTokenData.tokenType, oauthTokenData); + const token = oAuthClient.createToken(get(oauthTokenData, oAuth2Options?.property as string) || oauthTokenData.accessToken, oauthTokenData.refreshToken, oAuth2Options?.tokenType || oauthTokenData.tokenType, oauthTokenData); // Signs the request by adding authorization headers or query parameters depending // on the token-type used. const newRequestOptions = token.sign(requestOptions as clientOAuth2.RequestObject); @@ -151,7 +153,18 @@ export function requestOAuth2(this: IAllExecuteFunctions, credentialsType: strin if (error.statusCode === 401) { // TODO: Whole refresh process is not tested yet // Token is probably not valid anymore. So try refresh it. - const newToken = await token.refresh(); + + const tokenRefreshOptions: IDataObject = {}; + + if (oAuth2Options?.includeCredentialsOnRefreshOnBody) { + const body: IDataObject = { + client_id: credentials.clientId as string, + client_secret: credentials.clientSecret as string, + }; + tokenRefreshOptions.body = body; + } + + const newToken = await token.refresh(tokenRefreshOptions); credentials.oauthTokenData = newToken.data; @@ -529,8 +542,8 @@ export function getExecutePollFunctions(workflow: Workflow, node: INode, additio helpers: { prepareBinaryData, request: requestPromise, - requestOAuth2(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUri | requestPromise.RequestPromiseOptions, tokenType?: string, property?: string): Promise { // tslint:disable-line:no-any - return requestOAuth2.call(this, credentialsType, requestOptions, node, additionalData, tokenType, property); + requestOAuth2(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUri | requestPromise.RequestPromiseOptions, oAuth2Options?: IOAuth2Options): Promise { // tslint:disable-line:no-any + return requestOAuth2.call(this, credentialsType, requestOptions, node, additionalData, oAuth2Options); }, requestOAuth1(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUrl | requestPromise.RequestPromiseOptions): Promise { // tslint:disable-line:no-any return requestOAuth1.call(this, credentialsType, requestOptions); @@ -592,8 +605,8 @@ export function getExecuteTriggerFunctions(workflow: Workflow, node: INode, addi helpers: { prepareBinaryData, request: requestPromise, - requestOAuth2(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUri | requestPromise.RequestPromiseOptions, tokenType?: string, property?: string): Promise { // tslint:disable-line:no-any - return requestOAuth2.call(this, credentialsType, requestOptions, node, additionalData, tokenType, property); + requestOAuth2(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUri | requestPromise.RequestPromiseOptions, oAuth2Options?: IOAuth2Options): Promise { // tslint:disable-line:no-any + return requestOAuth2.call(this, credentialsType, requestOptions, node, additionalData, oAuth2Options); }, requestOAuth1(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUrl | requestPromise.RequestPromiseOptions): Promise { // tslint:disable-line:no-any return requestOAuth1.call(this, credentialsType, requestOptions); @@ -688,8 +701,8 @@ export function getExecuteFunctions(workflow: Workflow, runExecutionData: IRunEx helpers: { prepareBinaryData, request: requestPromise, - requestOAuth2(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUri | requestPromise.RequestPromiseOptions, tokenType?: string, property?: string): Promise { // tslint:disable-line:no-any - return requestOAuth2.call(this, credentialsType, requestOptions, node, additionalData, tokenType, property); + requestOAuth2(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUri | requestPromise.RequestPromiseOptions, oAuth2Options?: IOAuth2Options): Promise { // tslint:disable-line:no-any + return requestOAuth2.call(this, credentialsType, requestOptions, node, additionalData, oAuth2Options); }, requestOAuth1(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUrl | requestPromise.RequestPromiseOptions): Promise { // tslint:disable-line:no-any return requestOAuth1.call(this, credentialsType, requestOptions); @@ -786,8 +799,8 @@ export function getExecuteSingleFunctions(workflow: Workflow, runExecutionData: helpers: { prepareBinaryData, request: requestPromise, - requestOAuth2(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUri | requestPromise.RequestPromiseOptions, tokenType?: string, property?: string): Promise { // tslint:disable-line:no-any - return requestOAuth2.call(this, credentialsType, requestOptions, node, additionalData, tokenType, property); + requestOAuth2(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUri | requestPromise.RequestPromiseOptions, oAuth2Options?: IOAuth2Options): Promise { // tslint:disable-line:no-any + return requestOAuth2.call(this, credentialsType, requestOptions, node, additionalData, oAuth2Options); }, requestOAuth1(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUrl | requestPromise.RequestPromiseOptions): Promise { // tslint:disable-line:no-any return requestOAuth1.call(this, credentialsType, requestOptions); @@ -842,8 +855,8 @@ export function getLoadOptionsFunctions(workflow: Workflow, node: INode, additio }, helpers: { request: requestPromise, - requestOAuth2(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUri | requestPromise.RequestPromiseOptions, tokenType?: string, property?: string): Promise { // tslint:disable-line:no-any - return requestOAuth2.call(this, credentialsType, requestOptions, node, additionalData, tokenType, property); + requestOAuth2(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUri | requestPromise.RequestPromiseOptions, oAuth2Options?: IOAuth2Options): Promise { // tslint:disable-line:no-any + return requestOAuth2.call(this, credentialsType, requestOptions, node, additionalData, oAuth2Options); }, requestOAuth1(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUrl | requestPromise.RequestPromiseOptions): Promise { // tslint:disable-line:no-any return requestOAuth1.call(this, credentialsType, requestOptions); @@ -909,8 +922,8 @@ export function getExecuteHookFunctions(workflow: Workflow, node: INode, additio }, helpers: { request: requestPromise, - requestOAuth2(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUri | requestPromise.RequestPromiseOptions, tokenType?: string, property?: string): Promise { // tslint:disable-line:no-any - return requestOAuth2.call(this, credentialsType, requestOptions, node, additionalData, tokenType, property); + requestOAuth2(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUri | requestPromise.RequestPromiseOptions, oAuth2Options?: IOAuth2Options): Promise { // tslint:disable-line:no-any + return requestOAuth2.call(this, credentialsType, requestOptions, node, additionalData, oAuth2Options); }, requestOAuth1(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUrl | requestPromise.RequestPromiseOptions): Promise { // tslint:disable-line:no-any return requestOAuth1.call(this, credentialsType, requestOptions); @@ -1003,8 +1016,8 @@ export function getExecuteWebhookFunctions(workflow: Workflow, node: INode, addi helpers: { prepareBinaryData, request: requestPromise, - requestOAuth2(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUri | requestPromise.RequestPromiseOptions, tokenType?: string, property?: string): Promise { // tslint:disable-line:no-any - return requestOAuth2.call(this, credentialsType, requestOptions, node, additionalData, tokenType, property); + requestOAuth2(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUri | requestPromise.RequestPromiseOptions, oAuth2Options?: IOAuth2Options): Promise { // tslint:disable-line:no-any + return requestOAuth2.call(this, credentialsType, requestOptions, node, additionalData, oAuth2Options); }, requestOAuth1(this: IAllExecuteFunctions, credentialsType: string, requestOptions: OptionsWithUrl | requestPromise.RequestPromiseOptions): Promise { // tslint:disable-line:no-any return requestOAuth1.call(this, credentialsType, requestOptions); diff --git a/packages/nodes-base/nodes/Box/GenericFunctions.ts b/packages/nodes-base/nodes/Box/GenericFunctions.ts index 878dabe68c..4581c26c4f 100644 --- a/packages/nodes-base/nodes/Box/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Box/GenericFunctions.ts @@ -10,7 +10,7 @@ import { } from 'n8n-core'; import { - IDataObject, + IDataObject, IOAuth2Options, } from 'n8n-workflow'; export async function boxApiRequest(this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions | IHookFunctions, method: string, resource: string, body: any = {}, qs: IDataObject = {}, uri?: string, option: IDataObject = {}): Promise { // tslint:disable-line:no-any @@ -31,10 +31,16 @@ export async function boxApiRequest(this: IExecuteFunctions | IExecuteSingleFunc if (Object.keys(body).length === 0) { delete options.body; } + + const oAuth2Options: IOAuth2Options = { + includeCredentialsOnRefreshOnBody: true, + }; + //@ts-ignore - return await this.helpers.requestOAuth2.call(this, 'boxOAuth2Api', options); + return await this.helpers.requestOAuth2.call(this, 'boxOAuth2Api', options, oAuth2Options); } catch (error) { + console.log(error); let errorMessage; diff --git a/packages/nodes-base/nodes/Hubspot/GenericFunctions.ts b/packages/nodes-base/nodes/Hubspot/GenericFunctions.ts index d8d68abfb6..b47956d24f 100644 --- a/packages/nodes-base/nodes/Hubspot/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Hubspot/GenericFunctions.ts @@ -45,7 +45,7 @@ export async function hubspotApiRequest(this: IHookFunctions | IExecuteFunctions return await this.helpers.request!(options); } else { // @ts-ignore - return await this.helpers.requestOAuth2!.call(this, 'hubspotOAuth2Api', options, 'Bearer'); + return await this.helpers.requestOAuth2!.call(this, 'hubspotOAuth2Api', options, { tokenType: 'Bearer' }); } } catch (error) { let errorMessages; diff --git a/packages/nodes-base/nodes/Mailchimp/GenericFunctions.ts b/packages/nodes-base/nodes/Mailchimp/GenericFunctions.ts index 59362b50d6..4a8b4e0e77 100644 --- a/packages/nodes-base/nodes/Mailchimp/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Mailchimp/GenericFunctions.ts @@ -58,7 +58,7 @@ export async function mailchimpApiRequest(this: IHookFunctions | IExecuteFunctio options.url = `${api_endpoint}/3.0${endpoint}`; //@ts-ignore - return await this.helpers.requestOAuth2!.call(this, 'mailchimpOAuth2Api', options, 'Bearer'); + return await this.helpers.requestOAuth2!.call(this, 'mailchimpOAuth2Api', options, { tokenType: 'Bearer' }); } } catch (error) { if (error.respose && error.response.body && error.response.body.detail) { diff --git a/packages/nodes-base/nodes/Slack/GenericFunctions.ts b/packages/nodes-base/nodes/Slack/GenericFunctions.ts index ad04536b36..40825e4885 100644 --- a/packages/nodes-base/nodes/Slack/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Slack/GenericFunctions.ts @@ -9,7 +9,7 @@ import { } from 'n8n-core'; import { - IDataObject + IDataObject, IOAuth2Options } from 'n8n-workflow'; import * as _ from 'lodash'; @@ -42,8 +42,13 @@ export async function slackApiRequest(this: IExecuteFunctions | IExecuteSingleFu //@ts-ignore return await this.helpers.request(options); } else { + + const oAuth2Options: IOAuth2Options = { + tokenType: 'Bearer', + property: 'authed_user.access_token', + }; //@ts-ignore - return await this.helpers.requestOAuth2.call(this, 'slackOAuth2Api', options, 'bearer', 'authed_user.access_token'); + return await this.helpers.requestOAuth2.call(this, 'slackOAuth2Api', options, oAuth2Options); } } catch (error) { if (error.statusCode === 401) { diff --git a/packages/workflow/src/Interfaces.ts b/packages/workflow/src/Interfaces.ts index f8a6cc5e82..b3ddd9bb91 100644 --- a/packages/workflow/src/Interfaces.ts +++ b/packages/workflow/src/Interfaces.ts @@ -180,7 +180,6 @@ export interface IExecuteData { node: INode; } - export type IContextObject = { [key: string]: any; // tslint:disable-line:no-any };