From 04f1f262486125399997f404e597c3047c877ac2 Mon Sep 17 00:00:00 2001 From: Rupenieks Date: Tue, 16 Jun 2020 14:16:03 +0200 Subject: [PATCH 1/3] Fixed deprecated API calls & Added OAuth2 support --- .../EventbriteOAuth2Api.credentials.ts | 60 +++++++++++++++++++ .../Eventbrite/EventbriteTrigger.node.ts | 44 +++++++++++++- .../nodes/Eventbrite/GenericFunctions.ts | 23 ++++--- packages/nodes-base/package.json | 1 + 4 files changed, 117 insertions(+), 11 deletions(-) create mode 100644 packages/nodes-base/credentials/EventbriteOAuth2Api.credentials.ts diff --git a/packages/nodes-base/credentials/EventbriteOAuth2Api.credentials.ts b/packages/nodes-base/credentials/EventbriteOAuth2Api.credentials.ts new file mode 100644 index 0000000000..ff50a115d5 --- /dev/null +++ b/packages/nodes-base/credentials/EventbriteOAuth2Api.credentials.ts @@ -0,0 +1,60 @@ +import { + ICredentialType, + NodePropertyTypes, +} from 'n8n-workflow'; + + +export class EventbriteOAuth2Api implements ICredentialType { + name = 'eventbriteOAuth2Api'; + extends = [ + 'oAuth2Api', + ]; + displayName = 'Eventbrite OAuth2 API'; + properties = [ + { + displayName: 'Authorization URL', + name: 'authUrl', + type: 'hidden' as NodePropertyTypes, + default: 'https://www.eventbrite.com/oauth/authorize', + required: true, + }, + { + displayName: 'Access Token URL', + name: 'accessTokenUrl', + type: 'hidden' as NodePropertyTypes, + default: 'https://www.eventbrite.com/oauth/token', + required: true, + }, + { + displayName: 'Scope', + name: 'scope', + type: 'hidden' as NodePropertyTypes, + default: '', + }, + { + displayName: 'Auth URI Query Parameters', + name: 'authQueryParameters', + type: 'hidden' as NodePropertyTypes, + default: '', + }, + { + displayName: 'Authentication', + name: 'authentication', + type: 'options' as NodePropertyTypes, + options: [ + { + name: 'Body', + value: 'body', + description: 'Send credentials in body', + }, + { + name: 'Header', + value: 'header', + description: 'Send credentials as Basic Auth header', + }, + ], + default: 'header', + description: 'Resource to consume.', + }, + ]; +} diff --git a/packages/nodes-base/nodes/Eventbrite/EventbriteTrigger.node.ts b/packages/nodes-base/nodes/Eventbrite/EventbriteTrigger.node.ts index fdeae599c2..8299ae866d 100644 --- a/packages/nodes-base/nodes/Eventbrite/EventbriteTrigger.node.ts +++ b/packages/nodes-base/nodes/Eventbrite/EventbriteTrigger.node.ts @@ -35,7 +35,25 @@ export class EventbriteTrigger implements INodeType { { name: 'eventbriteApi', required: true, - } + displayOptions: { + show: { + authentication: [ + 'accessToken', + ], + }, + }, + }, + { + name: 'eventbriteOAuth2Api', + required: true, + displayOptions: { + show: { + authentication: [ + 'oAuth2', + ], + }, + }, + }, ], webhooks: [ { @@ -46,6 +64,23 @@ export class EventbriteTrigger implements INodeType { }, ], properties: [ + { + displayName: 'Authentication', + name: 'authentication', + type: 'options', + options: [ + { + name: 'Access Token', + value: 'accessToken', + }, + { + name: 'OAuth2', + value: 'oAuth2', + }, + ], + default: 'accessToken', + description: 'The resource to operate on.', + }, { displayName: 'Organization', name: 'organization', @@ -192,10 +227,12 @@ export class EventbriteTrigger implements INodeType { default: { async checkExists(this: IHookFunctions): Promise { const webhookData = this.getWorkflowStaticData('node'); + const organisation = this.getNodeParameter('organization') as string; + if (webhookData.webhookId === undefined) { return false; } - const endpoint = `/webhooks/${webhookData.webhookId}/`; + const endpoint = `/organizations/${organisation}/webhooks/`; try { await eventbriteApiRequest.call(this, 'GET', endpoint); } catch (e) { @@ -206,9 +243,10 @@ export class EventbriteTrigger implements INodeType { async create(this: IHookFunctions): Promise { const webhookUrl = this.getNodeWebhookUrl('default'); const webhookData = this.getWorkflowStaticData('node'); + const organisation = this.getNodeParameter('organization') as string; const event = this.getNodeParameter('event') as string; const actions = this.getNodeParameter('actions') as string[]; - const endpoint = `/webhooks/`; + const endpoint = `/organizations/${organisation}/webhooks/`; const body: IDataObject = { endpoint_url: webhookUrl, actions: actions.join(','), diff --git a/packages/nodes-base/nodes/Eventbrite/GenericFunctions.ts b/packages/nodes-base/nodes/Eventbrite/GenericFunctions.ts index 285c89b1f8..5bbb517c5d 100644 --- a/packages/nodes-base/nodes/Eventbrite/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Eventbrite/GenericFunctions.ts @@ -9,13 +9,8 @@ import { import { IDataObject } from 'n8n-workflow'; export async function eventbriteApiRequest(this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions | IWebhookFunctions, method: string, resource: string, body: any = {}, qs: IDataObject = {}, uri?: string, option: IDataObject = {}): Promise { // tslint:disable-line:no-any - const credentials = this.getCredentials('eventbriteApi'); - if (credentials === undefined) { - throw new Error('No credentials got returned!'); - } - let options: OptionsWithUri = { - headers: { 'Authorization': `Bearer ${credentials.apiKey}`}, + headers: {}, method, qs, body, @@ -27,14 +22,26 @@ export async function eventbriteApiRequest(this: IHookFunctions | IExecuteFuncti delete options.body; } + const authenticationMethod = this.getNodeParameter('authentication', 0); + try { - return await this.helpers.request!(options); + if (authenticationMethod === 'accessToken') { + const credentials = this.getCredentials('eventbriteApi'); + if (credentials === undefined) { + throw new Error('No credentials got returned!'); + } + + options.headers!['Authorization'] = `Bearer ${credentials.apiKey}`; + + return await this.helpers.request!(options); + } else { + return await this.helpers.requestOAuth2!.call(this, 'eventbriteOAuth2Api', options); + } } catch (error) { let errorMessage = error.message; if (error.response.body && error.response.body.error_description) { errorMessage = error.response.body.error_description; } - throw new Error('Eventbrite Error: ' + errorMessage); } } diff --git a/packages/nodes-base/package.json b/packages/nodes-base/package.json index dcfaeb2269..ba9899b2d1 100644 --- a/packages/nodes-base/package.json +++ b/packages/nodes-base/package.json @@ -49,6 +49,7 @@ "dist/credentials/DriftApi.credentials.js", "dist/credentials/DropboxApi.credentials.js", "dist/credentials/EventbriteApi.credentials.js", + "dist/credentials/EventbriteOAuth2Api.credentials.js", "dist/credentials/FacebookGraphApi.credentials.js", "dist/credentials/FreshdeskApi.credentials.js", "dist/credentials/FileMaker.credentials.js", From 755079c3607d06f2f4bbb780a003b12776f6754b Mon Sep 17 00:00:00 2001 From: Rupenieks Date: Tue, 16 Jun 2020 14:16:53 +0200 Subject: [PATCH 2/3] Update EventbriteOAuth2Api.credentials.ts --- .../EventbriteOAuth2Api.credentials.ts | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/packages/nodes-base/credentials/EventbriteOAuth2Api.credentials.ts b/packages/nodes-base/credentials/EventbriteOAuth2Api.credentials.ts index ff50a115d5..46a9df4266 100644 --- a/packages/nodes-base/credentials/EventbriteOAuth2Api.credentials.ts +++ b/packages/nodes-base/credentials/EventbriteOAuth2Api.credentials.ts @@ -40,21 +40,8 @@ export class EventbriteOAuth2Api implements ICredentialType { { displayName: 'Authentication', name: 'authentication', - type: 'options' as NodePropertyTypes, - options: [ - { - name: 'Body', - value: 'body', - description: 'Send credentials in body', - }, - { - name: 'Header', - value: 'header', - description: 'Send credentials as Basic Auth header', - }, - ], - default: 'header', - description: 'Resource to consume.', + type: 'hidden' as NodePropertyTypes, + default: 'body' }, ]; } From 28befc10346362b79e4ead8a7ec9d2efb3589b3e Mon Sep 17 00:00:00 2001 From: ricardo Date: Thu, 25 Jun 2020 19:43:49 -0400 Subject: [PATCH 3/3] :zap: Improvements to Eventbrite-Trigger --- .../credentials/EventbriteApi.credentials.ts | 2 +- .../Eventbrite/EventbriteTrigger.node.ts | 38 ++++++++++++------- .../nodes/Eventbrite/GenericFunctions.ts | 12 ++++-- 3 files changed, 35 insertions(+), 17 deletions(-) diff --git a/packages/nodes-base/credentials/EventbriteApi.credentials.ts b/packages/nodes-base/credentials/EventbriteApi.credentials.ts index 9fa48753fb..e54be8580c 100644 --- a/packages/nodes-base/credentials/EventbriteApi.credentials.ts +++ b/packages/nodes-base/credentials/EventbriteApi.credentials.ts @@ -8,7 +8,7 @@ export class EventbriteApi implements ICredentialType { displayName = 'Eventbrite API'; properties = [ { - displayName: 'API Key', + displayName: 'Private Key', name: 'apiKey', type: 'string' as NodePropertyTypes, default: '', diff --git a/packages/nodes-base/nodes/Eventbrite/EventbriteTrigger.node.ts b/packages/nodes-base/nodes/Eventbrite/EventbriteTrigger.node.ts index 8299ae866d..0c9158b6c3 100644 --- a/packages/nodes-base/nodes/Eventbrite/EventbriteTrigger.node.ts +++ b/packages/nodes-base/nodes/Eventbrite/EventbriteTrigger.node.ts @@ -38,7 +38,7 @@ export class EventbriteTrigger implements INodeType { displayOptions: { show: { authentication: [ - 'accessToken', + 'privateKey', ], }, }, @@ -70,15 +70,15 @@ export class EventbriteTrigger implements INodeType { type: 'options', options: [ { - name: 'Access Token', - value: 'accessToken', + name: 'Private Key', + value: 'privateKey', }, { name: 'OAuth2', value: 'oAuth2', }, ], - default: 'accessToken', + default: 'privateKey', description: 'The resource to operate on.', }, { @@ -184,7 +184,6 @@ export class EventbriteTrigger implements INodeType { description: 'By default does the webhook-data only contain the URL to receive
the object data manually. If this option gets activated it
will resolve the data automatically.', }, ], - }; methods = { @@ -227,18 +226,31 @@ export class EventbriteTrigger implements INodeType { default: { async checkExists(this: IHookFunctions): Promise { const webhookData = this.getWorkflowStaticData('node'); + const webhookUrl = this.getNodeWebhookUrl('default'); const organisation = this.getNodeParameter('organization') as string; + const actions = this.getNodeParameter('actions') as string[]; - if (webhookData.webhookId === undefined) { - return false; - } const endpoint = `/organizations/${organisation}/webhooks/`; - try { - await eventbriteApiRequest.call(this, 'GET', endpoint); - } catch (e) { - return false; + + const { webhooks } = await eventbriteApiRequest.call(this, 'GET', endpoint); + + const check = (currentActions: string[], webhookActions: string[]) => { + for (const currentAction of currentActions) { + if (!webhookActions.includes(currentAction)) { + return false; + } + } + return true; + }; + + for (const webhook of webhooks) { + if (webhook.endpoint_url === webhookUrl && check(actions, webhook.actions)) { + webhookData.webhookId = webhook.id; + return true; + } } - return true; + + return false; }, async create(this: IHookFunctions): Promise { const webhookUrl = this.getNodeWebhookUrl('default'); diff --git a/packages/nodes-base/nodes/Eventbrite/GenericFunctions.ts b/packages/nodes-base/nodes/Eventbrite/GenericFunctions.ts index 5bbb517c5d..2392a0ae20 100644 --- a/packages/nodes-base/nodes/Eventbrite/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Eventbrite/GenericFunctions.ts @@ -1,4 +1,7 @@ -import { OptionsWithUri } from 'request'; +import { + OptionsWithUri, +} from 'request'; + import { IExecuteFunctions, IExecuteSingleFunctions, @@ -6,7 +9,10 @@ import { ILoadOptionsFunctions, IWebhookFunctions, } from 'n8n-core'; -import { IDataObject } from 'n8n-workflow'; + +import { + IDataObject, +} from 'n8n-workflow'; export async function eventbriteApiRequest(this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions | IWebhookFunctions, method: string, resource: string, body: any = {}, qs: IDataObject = {}, uri?: string, option: IDataObject = {}): Promise { // tslint:disable-line:no-any let options: OptionsWithUri = { @@ -25,7 +31,7 @@ export async function eventbriteApiRequest(this: IHookFunctions | IExecuteFuncti const authenticationMethod = this.getNodeParameter('authentication', 0); try { - if (authenticationMethod === 'accessToken') { + if (authenticationMethod === 'privateKey') { const credentials = this.getCredentials('eventbriteApi'); if (credentials === undefined) { throw new Error('No credentials got returned!');