From 82a254a8d9295901e42ec999432a7f5b40f38281 Mon Sep 17 00:00:00 2001 From: agobrech <45268029+agobrech@users.noreply.github.com> Date: Sun, 10 Jul 2022 11:06:20 +0200 Subject: [PATCH] feat(Customer.io Node): Add support for tracking API region selection (#3378) * support for customer.io tracking api endpoint region selection If your account is based in our EU region use the EU endpoints (track-eu.customer.io) for US (other than EU) tracking endpoints (track.customer.io). * Changed name to keep constistency with other nodes * Switched to credentials injection * Add throwing error when unknow way of authenticating * Fixed url for http request * Add hint to region field about being omited with http node * Fix bug for credentials working with http node * Improve IF by deduplicating code Co-authored-by: h4ux Co-authored-by: Omar Ajoue --- .../credentials/CustomerIoApi.credentials.ts | 37 +++++++++++++++++++ .../nodes/CustomerIo/GenericFunctions.ts | 24 +++++------- 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/packages/nodes-base/credentials/CustomerIoApi.credentials.ts b/packages/nodes-base/credentials/CustomerIoApi.credentials.ts index 5158dcf47aa19..c3df8869c29ed 100644 --- a/packages/nodes-base/credentials/CustomerIoApi.credentials.ts +++ b/packages/nodes-base/credentials/CustomerIoApi.credentials.ts @@ -1,5 +1,7 @@ import { + ICredentialDataDecryptedObject, ICredentialType, + IHttpRequestOptions, INodeProperties, } from 'n8n-workflow'; @@ -17,6 +19,25 @@ export class CustomerIoApi implements ICredentialType { description: 'Required for tracking API', required: true, }, + { + displayName: 'Region', + name: 'region', + type: 'options', + options: [ + { + name: 'EU region', + value: 'track-eu.customer.io', + }, + { + name: 'Global region', + value: 'track.customer.io', + }, + ], + default: 'track.customer.io', + description: 'Should be set based on your account region', + hint: 'The region will be omited when being used with the HTTP node', + required: true, + }, { displayName: 'Tracking Site ID', name: 'trackingSiteId', @@ -32,4 +53,20 @@ export class CustomerIoApi implements ICredentialType { description: 'Required for App API', }, ]; + async authenticate(credentials: ICredentialDataDecryptedObject, requestOptions: IHttpRequestOptions): Promise { + // @ts-ignore + const url = requestOptions.url ? requestOptions.url : requestOptions.uri; + if (url.includes('track') || url.includes('api.customer.io')) { + const basicAuthKey = Buffer.from(`${credentials.trackingSiteId}:${credentials.trackingApiKey}`).toString('base64'); + // @ts-ignore + Object.assign(requestOptions.headers, { 'Authorization': `Basic ${basicAuthKey}` }); + } else if (url.includes('beta-api.customer.io')) { + // @ts-ignore + Object.assign(requestOptions.headers, { 'Authorization': `Bearer ${credentials.appApiKey as string}` }); + } else { + throw new Error('Unknown way of authenticating'); + } + + return requestOptions; + } } diff --git a/packages/nodes-base/nodes/CustomerIo/GenericFunctions.ts b/packages/nodes-base/nodes/CustomerIo/GenericFunctions.ts index e3b166d637020..903bf0026e26b 100644 --- a/packages/nodes-base/nodes/CustomerIo/GenericFunctions.ts +++ b/packages/nodes-base/nodes/CustomerIo/GenericFunctions.ts @@ -9,7 +9,7 @@ import { } from 'request'; import { - IDataObject, NodeApiError, NodeOperationError, + IDataObject, IHttpRequestMethods, IHttpRequestOptions, NodeApiError, NodeOperationError, } from 'n8n-workflow'; import { @@ -18,34 +18,28 @@ import { export async function customerIoApiRequest(this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions, method: string, endpoint: string, body: object, baseApi?: string, query?: IDataObject): Promise { // tslint:disable-line:no-any const credentials = await this.getCredentials('customerIoApi'); - query = query || {}; - - const options: OptionsWithUri = { + const options: IHttpRequestOptions = { headers: { 'Content-Type': 'application/json', }, - method, + method: method as IHttpRequestMethods, body, - uri: '', + url: '', json: true, }; if (baseApi === 'tracking') { - options.uri = `https://track.customer.io/api/v1${endpoint}`; - const basicAuthKey = Buffer.from(`${credentials.trackingSiteId}:${credentials.trackingApiKey}`).toString('base64'); - Object.assign(options.headers, { 'Authorization': `Basic ${basicAuthKey}` }); + const region = credentials.region; + options.url = `https://${region}/api/v1${endpoint}`; } else if (baseApi === 'api') { - options.uri = `https://api.customer.io/v1/api${endpoint}`; - const basicAuthKey = Buffer.from(`${credentials.trackingSiteId}:${credentials.trackingApiKey}`).toString('base64'); - Object.assign(options.headers, { 'Authorization': `Basic ${basicAuthKey}` }); + options.url = `https://api.customer.io/v1/api${endpoint}`; } else if (baseApi === 'beta') { - options.uri = `https://beta-api.customer.io/v1/api${endpoint}`; - Object.assign(options.headers, { 'Authorization': `Bearer ${credentials.appApiKey as string}` }); + options.url = `https://beta-api.customer.io/v1/api${endpoint}`; } try { - return await this.helpers.request!(options); + return await this.helpers.requestWithAuthentication.call(this, 'customerIoApi' ,options ); } catch (error) { throw new NodeApiError(this.getNode(), error); }