add OAuth2

This commit is contained in:
shraddha shaligram
2020-06-18 12:29:16 -07:00
12 changed files with 854 additions and 706 deletions

View File

@@ -1,6 +1,11 @@
import { ICredentialType, NodePropertyTypes } from 'n8n-workflow'; import {
ICredentialType,
NodePropertyTypes,
} from 'n8n-workflow';
const scopes = ['https://www.googleapis.com/auth/tasks']; const scopes = [
'https://www.googleapis.com/auth/tasks',
];
export class GoogleTasksOAuth2Api implements ICredentialType { export class GoogleTasksOAuth2Api implements ICredentialType {
name = 'googleTasksOAuth2Api'; name = 'googleTasksOAuth2Api';
@@ -12,6 +17,6 @@ export class GoogleTasksOAuth2Api implements ICredentialType {
name: 'scope', name: 'scope',
type: 'hidden' as NodePropertyTypes, type: 'hidden' as NodePropertyTypes,
default: scopes.join(' ') default: scopes.join(' ')
} },
]; ];
} }

View File

@@ -44,7 +44,7 @@ export class ZoomOAuth2Api implements ICredentialType {
displayName: 'Authentication', displayName: 'Authentication',
name: 'authentication', name: 'authentication',
type: 'hidden' as NodePropertyTypes, type: 'hidden' as NodePropertyTypes,
default: 'body' default: 'header'
} }
]; ];
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,6 @@
import { IDataObject } from "n8n-workflow"; import {
IDataObject,
} from 'n8n-workflow';
export interface IReminder { export interface IReminder {
useDefault?: boolean; useDefault?: boolean;

View File

@@ -1,4 +1,6 @@
import { IExecuteFunctions } from 'n8n-core'; import {
IExecuteFunctions,
} from 'n8n-core';
import { import {
IDataObject, IDataObject,
@@ -6,14 +8,22 @@ import {
INodeTypeDescription, INodeTypeDescription,
INodeType, INodeType,
ILoadOptionsFunctions, ILoadOptionsFunctions,
INodePropertyOptions INodePropertyOptions,
} from 'n8n-workflow'; } from 'n8n-workflow';
import { googleApiRequest, googleApiRequestAllItems } from './GenericFunctions'; import {
googleApiRequest,
googleApiRequestAllItems,
} from './GenericFunctions';
import { eventOperations, eventFields } from './EventDescription'; import {
eventOperations,
eventFields,
} from './EventDescription';
import { IEvent } from './EventInterface'; import {
IEvent,
} from './EventInterface';
import * as moment from 'moment-timezone'; import * as moment from 'moment-timezone';
@@ -28,14 +38,14 @@ export class GoogleCalendar implements INodeType {
description: 'Consume Google Calendar API.', description: 'Consume Google Calendar API.',
defaults: { defaults: {
name: 'Google Calendar', name: 'Google Calendar',
color: '#3E87E4' color: '#3E87E4',
}, },
inputs: ['main'], inputs: ['main'],
outputs: ['main'], outputs: ['main'],
credentials: [ credentials: [
{ {
name: 'googleCalendarOAuth2Api', name: 'googleCalendarOAuth2Api',
required: true required: true,
} }
], ],
properties: [ properties: [
@@ -46,15 +56,15 @@ export class GoogleCalendar implements INodeType {
options: [ options: [
{ {
name: 'Event', name: 'Event',
value: 'event' value: 'event',
} },
], ],
default: 'event', default: 'event',
description: 'The resource to operate on.' description: 'The resource to operate on.'
}, },
...eventOperations, ...eventOperations,
...eventFields ...eventFields,
] ],
}; };
methods = { methods = {

View File

@@ -1,12 +1,16 @@
import { OptionsWithUri } from 'request'; import {
OptionsWithUri,
} from 'request';
import { import {
IExecuteFunctions, IExecuteFunctions,
IExecuteSingleFunctions, IExecuteSingleFunctions,
ILoadOptionsFunctions ILoadOptionsFunctions,
} from 'n8n-core'; } from 'n8n-core';
import { IDataObject } from 'n8n-workflow'; import {
IDataObject,
} from 'n8n-workflow';
export async function googleApiRequest( export async function googleApiRequest(
this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions,
@@ -27,6 +31,7 @@ export async function googleApiRequest(
uri: uri || `https://www.googleapis.com${resource}`, uri: uri || `https://www.googleapis.com${resource}`,
json: true json: true
}; };
try { try {
if (Object.keys(headers).length !== 0) { if (Object.keys(headers).length !== 0) {
options.headers = Object.assign({}, options.headers, headers); options.headers = Object.assign({}, options.headers, headers);
@@ -41,10 +46,14 @@ export async function googleApiRequest(
options options
); );
} catch (error) { } catch (error) {
if (error.response && error.response.body && error.response.body.message) { if (error.response && error.response.body && error.response.body.error) {
let errors = error.response.body.error.errors;
errors = errors.map((e: IDataObject) => e.message);
// Try to return the error prettier // Try to return the error prettier
throw new Error( throw new Error(
`Google Tasks error response [${error.statusCode}]: ${error.response.body.message}` `Google Tasks error response [${error.statusCode}]: ${errors.join('|')}`
); );
} }
throw error; throw error;

View File

@@ -1,16 +1,25 @@
import { IExecuteFunctions } from 'n8n-core'; import {
IExecuteFunctions,
} from 'n8n-core';
import { import {
IDataObject, IDataObject,
INodeExecutionData,
INodeTypeDescription,
INodeType,
ILoadOptionsFunctions, ILoadOptionsFunctions,
INodePropertyOptions INodeExecutionData,
INodePropertyOptions,
INodeType,
INodeTypeDescription,
} from 'n8n-workflow'; } from 'n8n-workflow';
import { taskOperations, taskFields } from './TaskDescription';
import { googleApiRequest, googleApiRequestAllItems } from './GenericFunctions'; import {
googleApiRequest,
googleApiRequestAllItems,
} from './GenericFunctions';
import {
taskOperations,
taskFields,
} from './TaskDescription';
export class GoogleTasks implements INodeType { export class GoogleTasks implements INodeType {
description: INodeTypeDescription = { description: INodeTypeDescription = {
@@ -98,43 +107,36 @@ export class GoogleTasks implements INodeType {
i i
) as IDataObject; ) as IDataObject;
if (additionalFields.parent) if (additionalFields.parent) {
qs.parent = additionalFields.parent as string; qs.parent = additionalFields.parent as string;
if (additionalFields.previous)
qs.previous = additionalFields.previous as string;
if (additionalFields.links) {
body.links = (additionalFields.links as string[]).map(link => {
return { link };
});
} }
if (additionalFields.status) if (additionalFields.previous) {
qs.previous = additionalFields.previous as string;
}
if (additionalFields.status) {
body.status = additionalFields.status as string; body.status = additionalFields.status as string;
}
if (additionalFields.notes) if (additionalFields.notes) {
body.notes = additionalFields.notes as string; body.notes = additionalFields.notes as string;
}
if (additionalFields.title) if (additionalFields.title) {
body.title = additionalFields.title as string; body.title = additionalFields.title as string;
}
if (additionalFields.dueDate) if (additionalFields.dueDate) {
body.dueDate = additionalFields.dueDate as string; body.dueDate = additionalFields.dueDate as string;
}
if (additionalFields.completed) if (additionalFields.completed) {
body.completed = additionalFields.completed as string; body.completed = additionalFields.completed as string;
}
if (additionalFields.deleted) if (additionalFields.deleted) {
body.deleted = additionalFields.deleted as boolean; body.deleted = additionalFields.deleted as boolean;
}
if (additionalFields.hidden)
body.hidden = additionalFields.hidden as boolean;
if (additionalFields.position)
body.position = additionalFields.position as string;
if (additionalFields.selfLink)
body.selfLink = additionalFields.selfLink as string;
responseData = await googleApiRequest.call( responseData = await googleApiRequest.call(
this, this,
@@ -189,9 +191,6 @@ export class GoogleTasks implements INodeType {
if (options.dueMax) { if (options.dueMax) {
qs.dueMax = options.dueMax as string; qs.dueMax = options.dueMax as string;
} }
if (options.pageToken) {
qs.pageToken = options.pageToken as string;
}
if (options.showCompleted) { if (options.showCompleted) {
qs.showCompleted = options.showCompleted as boolean; qs.showCompleted = options.showCompleted as boolean;
} }
@@ -201,10 +200,10 @@ export class GoogleTasks implements INodeType {
if (options.showHidden) { if (options.showHidden) {
qs.showHidden = options.showHidden as boolean; qs.showHidden = options.showHidden as boolean;
} }
if (options.updatedMin) { if (options.updatedMin) {
qs.updatedMin = options.updatedMin as string; qs.updatedMin = options.updatedMin as string;
} }
if (returnAll) { if (returnAll) {
responseData = await googleApiRequestAllItems.call( responseData = await googleApiRequestAllItems.call(
this, this,
@@ -236,38 +235,33 @@ export class GoogleTasks implements INodeType {
i i
) as IDataObject; ) as IDataObject;
if (updateFields.parent) qs.parent = updateFields.parent as string; if (updateFields.previous) {
if (updateFields.previous)
qs.previous = updateFields.previous as string; qs.previous = updateFields.previous as string;
if (updateFields.links) {
body.links = (updateFields.links as string[]).map(link => {
return { link: link };
});
} }
if (updateFields.status) body.status = updateFields.status as string;
if (updateFields.notes) body.notes = updateFields.notes as string; if (updateFields.status) {
body.status = updateFields.status as string;
}
if (updateFields.title) body.title = updateFields.title as string; if (updateFields.notes) {
body.notes = updateFields.notes as string;
}
if (updateFields.dueDate) if (updateFields.title) {
body.title = updateFields.title as string;
}
if (updateFields.dueDate) {
body.dueDate = updateFields.dueDate as string; body.dueDate = updateFields.dueDate as string;
}
if (updateFields.completed) if (updateFields.completed) {
body.completed = updateFields.completed as string; body.completed = updateFields.completed as string;
}
if (updateFields.deleted) if (updateFields.deleted) {
body.deleted = updateFields.deleted as boolean; body.deleted = updateFields.deleted as boolean;
}
if (updateFields.hidden) body.hidden = updateFields.hidden as boolean;
if (updateFields.position)
body.position = updateFields.position as string;
if (updateFields.selfLink)
body.selfLink = updateFields.selfLink as string;
responseData = await googleApiRequest.call( responseData = await googleApiRequest.call(
this, this,
@@ -278,12 +272,11 @@ export class GoogleTasks implements INodeType {
); );
} }
} }
} if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]);
if (Array.isArray(responseData)) { } else if (responseData !== undefined) {
returnData.push.apply(returnData, responseData as IDataObject[]); returnData.push(responseData as IDataObject);
} else if (responseData !== undefined) { }
returnData.push(responseData as IDataObject);
} }
return [this.helpers.returnJsonArray(returnData)]; return [this.helpers.returnJsonArray(returnData)];
} }

View File

@@ -1,4 +1,6 @@
import { INodeProperties } from 'n8n-workflow'; import {
INodeProperties,
} from 'n8n-workflow';
export const taskOperations = [ export const taskOperations = [
{ {
@@ -7,60 +9,66 @@ export const taskOperations = [
type: 'options', type: 'options',
displayOptions: { displayOptions: {
show: { show: {
resource: ['task'] resource: [
} 'task',
],
},
}, },
options: [ options: [
{ {
name: 'Create', name: 'Create',
value: 'create', value: 'create',
description: 'Add a task to tasklist' description: 'Add a task to tasklist',
}, },
{ {
name: 'Delete', name: 'Delete',
value: 'delete', value: 'delete',
description: 'Delete a task' description: 'Delete a task',
}, },
{ {
name: 'Get', name: 'Get',
value: 'get', value: 'get',
description: 'Retrieve a task' description: 'Retrieve a task',
}, },
{ {
name: 'Get All', name: 'Get All',
value: 'getAll', value: 'getAll',
description: 'Retrieve all tasks from a tasklist' description: 'Retrieve all tasks from a tasklist',
}, },
{ {
name: 'Update', name: 'Update',
value: 'update', value: 'update',
description: 'Update a task' description: 'Update a task',
} }
], ],
default: 'create', default: 'create',
description: 'The operation to perform.' description: 'The operation to perform.',
} }
] as INodeProperties[]; ] as INodeProperties[];
export const taskFields = [ export const taskFields = [
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/* task:create */ /* task:create */
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
{ {
displayName: 'TaskList', displayName: 'TaskList',
name: 'task', name: 'task',
type: 'options', type: 'options',
typeOptions: { typeOptions: {
loadOptionsMethod: 'getTasks' loadOptionsMethod: 'getTasks',
}, },
required: true, required: true,
displayOptions: { displayOptions: {
show: { show: {
operation: ['create'], operation: [
resource: ['task'] 'create',
} ],
resource: [
'task',
],
},
}, },
default: '' default: '',
}, },
{ {
displayName: 'Additional Fields', displayName: 'Additional Fields',
@@ -70,135 +78,105 @@ export const taskFields = [
default: {}, default: {},
displayOptions: { displayOptions: {
show: { show: {
operation: ['create'], operation: [
resource: ['task'] 'create',
],
resource: [
'task',
],
} }
}, },
options: [ options: [
{ {
displayName: 'Status', displayName: 'Completion Date',
name: 'status', name: 'completed',
type: 'options', type: 'dateTime',
options: [
{
name: 'needs Action',
value: 'needsAction'
},
{
name: 'completed',
value: 'completed'
}
],
default: '', default: '',
description: 'Current status of the task.' description: `Completion date of the task (as a RFC 3339 timestamp). This field is omitted if the task has not been completed.`,
}, },
{ {
displayName: 'Links', displayName: 'Deleted',
name: 'links', name: 'deleted',
type: 'string', type: 'boolean',
typeOptions: { default: false,
multipleValues: true, description: 'Flag indicating whether the task has been deleted.',
multipleValueButtonText: 'Add Link'
},
default: '',
description: 'The links to insert in the task.'
},
{
displayName: 'Notes',
name: 'notes',
type: 'string',
default: '',
description: 'Additional Notes.'
},
{
displayName: 'Title',
name: 'title',
type: 'string',
default: '',
description: 'Title of the task.'
}, },
{ {
displayName: 'Due Date', displayName: 'Due Date',
name: 'dueDate', name: 'dueDate',
type: 'dateTime', type: 'dateTime',
default: '', default: '',
description: 'Due date of the task.' description: 'Due date of the task.',
}, },
{ {
displayName: 'Completion date', displayName: 'Notes',
name: 'completed', name: 'notes',
type: 'dateTime', type: 'string',
default: '', default: '',
description: `Completion date of the task (as a RFC 3339 timestamp). This field is omitted if the task has not been completed.` description: 'Additional Notes.',
},
{
displayName: 'Deleted status',
name: 'deleted',
type: 'boolean',
default: false,
description: 'Flag indicating whether the task has been deleted.'
},
{
displayName: 'Hidden',
name: 'hidden',
type: 'boolean',
default: false,
description: 'Flag indicating whether the task is hidden.'
}, },
{ {
displayName: 'Parent', displayName: 'Parent',
name: 'parent', name: 'parent',
type: 'string', type: 'string',
default: '', default: '',
description: description: 'Parent task identifier. If the task is created at the top level, this parameter is omitted.',
'Parent task identifier.This field is omitted if it is a top-level task.'
},
{
displayName: 'Position',
name: 'position',
type: 'string',
default: '',
description:
'Parent task identifier.This field is omitted if it is a top-level task.'
},
{
displayName: 'Self Link',
name: 'selfLink',
type: 'string',
default: '',
description:
'URL pointing to this task. Used to retrieve, update, or delete this task.'
}, },
{ {
displayName: 'Previous', displayName: 'Previous',
name: 'previous', name: 'previous',
type: 'string', type: 'string',
default: '', default: '',
description: description: 'Previous sibling task identifier. If the task is created at the first position among its siblings, this parameter is omitted.',
'Previous sibling task identifier. If the task is created at the first position among its siblings, this parameter is omitted.' },
} {
] displayName: 'Status',
name: 'status',
type: 'options',
options: [
{
name: 'Needs Action',
value: 'needsAction',
},
{
name: 'Completed',
value: 'completed',
}
],
default: '',
description: 'Current status of the task.',
},
{
displayName: 'Title',
name: 'title',
type: 'string',
default: '',
description: 'Title of the task.',
},
],
}, },
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/* task:delete */ /* task:delete */
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
{ {
displayName: 'TaskList', displayName: 'TaskList',
name: 'task', name: 'task',
type: 'options', type: 'options',
typeOptions: { typeOptions: {
loadOptionsMethod: 'getTasks' loadOptionsMethod: 'getTasks',
}, },
required: true, required: true,
displayOptions: { displayOptions: {
show: { show: {
operation: ['delete'], operation: [
resource: ['task'] 'delete',
} ],
resource: [
'task',
],
},
}, },
default: '' default: '',
}, },
{ {
displayName: 'Task ID', displayName: 'Task ID',
@@ -207,30 +185,38 @@ export const taskFields = [
required: true, required: true,
displayOptions: { displayOptions: {
show: { show: {
operation: ['delete'], operation: [
resource: ['task'] 'delete',
} ],
resource: [
'task',
],
},
}, },
default: '' default: '',
}, },
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/* task:get */ /* task:get */
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
{ {
displayName: 'TaskList', displayName: 'TaskList',
name: 'task', name: 'task',
type: 'options', type: 'options',
typeOptions: { typeOptions: {
loadOptionsMethod: 'getTasks' loadOptionsMethod: 'getTasks',
}, },
required: true, required: true,
displayOptions: { displayOptions: {
show: { show: {
operation: ['get'], operation: [
resource: ['task'] 'get',
],
resource: [
'task',
],
} }
}, },
default: '' default: '',
}, },
{ {
displayName: 'Task ID', displayName: 'Task ID',
@@ -239,30 +225,38 @@ export const taskFields = [
required: true, required: true,
displayOptions: { displayOptions: {
show: { show: {
operation: ['get'], operation: [
resource: ['task'] 'get',
} ],
resource: [
'task',
],
},
}, },
default: '' default: '',
}, },
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/* task:getAll */ /* task:getAll */
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
{ {
displayName: 'TaskList', displayName: 'TaskList',
name: 'task', name: 'task',
type: 'options', type: 'options',
typeOptions: { typeOptions: {
loadOptionsMethod: 'getTasks' loadOptionsMethod: 'getTasks',
}, },
required: true, required: true,
displayOptions: { displayOptions: {
show: { show: {
operation: ['getAll'], operation: [
resource: ['task'] 'getAll',
} ],
resource: [
'task',
],
},
}, },
default: '' default: '',
}, },
{ {
displayName: 'Return All', displayName: 'Return All',
@@ -270,13 +264,16 @@ export const taskFields = [
type: 'boolean', type: 'boolean',
displayOptions: { displayOptions: {
show: { show: {
operation: ['getAll'], operation: [
resource: ['task'] 'getAll',
} ],
resource: [
'task',
],
},
}, },
default: false, default: false,
description: description: 'If all results should be returned or only up to a given limit.',
'If all results should be returned or only up to a given limit.'
}, },
{ {
displayName: 'Limit', displayName: 'Limit',
@@ -284,17 +281,23 @@ export const taskFields = [
type: 'number', type: 'number',
displayOptions: { displayOptions: {
show: { show: {
operation: ['getAll'], operation: [
resource: ['task'], 'getAll',
returnAll: [false] ],
} resource: [
'task',
],
returnAll: [
false,
],
},
}, },
typeOptions: { typeOptions: {
minValue: 1, minValue: 1,
maxValue: 100 maxValue: 100
}, },
default: 20, default: 20,
description: 'How many results to return.' description: 'How many results to return.',
}, },
{ {
displayName: 'Additional Fields', displayName: 'Additional Fields',
@@ -304,105 +307,95 @@ export const taskFields = [
default: {}, default: {},
displayOptions: { displayOptions: {
show: { show: {
operation: ['getAll'], operation: [
resource: ['task'] 'getAll',
} ],
resource: [
'task',
],
},
}, },
options: [ options: [
{ {
displayName: 'Completed Max', displayName: 'Completed Max',
name: 'completedMax', name: 'completedMax',
type: 'dateTime', type: 'dateTime',
default: '', default: '',
description: description: 'Upper bound for a task completion date (as a RFC 3339 timestamp) to filter by.',
'Upper bound for a task completion date (as a RFC 3339 timestamp) to filter by.'
}, },
{ {
displayName: 'Completed Min', displayName: 'Completed Min',
name: 'completedMin', name: 'completedMin',
type: 'dateTime', type: 'dateTime',
default: '', default: '',
description: description: 'Lower bound for a task completion date (as a RFC 3339 timestamp) to filter by.',
'Lower bound for a task completion date (as a RFC 3339 timestamp) to filter by.'
}, },
{ {
displayName: 'Due Min', displayName: 'Due Min',
name: 'dueMin', name: 'dueMin',
type: 'dateTime', type: 'dateTime',
default: '', default: '',
description: description: 'Lower bound for a task due date (as a RFC 3339 timestamp) to filter by.',
'Lower bound for a task due date (as a RFC 3339 timestamp) to filter by.'
}, },
{ {
displayName: 'Due Max', displayName: 'Due Max',
name: 'dueMax', name: 'dueMax',
type: 'dateTime', type: 'dateTime',
default: '', default: '',
description: description: 'Upper bound for a task due date (as a RFC 3339 timestamp) to filter by.',
'Upper bound for a task due date (as a RFC 3339 timestamp) to filter by.'
}, },
{
displayName: 'Page Token',
name: 'pageToken',
type: 'string',
default: '',
description: 'Token specifying the result page to return.'
},
{ {
displayName: 'Show Completed', displayName: 'Show Completed',
name: 'showCompleted', name: 'showCompleted',
type: 'boolean', type: 'boolean',
default: true, default: true,
description: description: 'Flag indicating whether completed tasks are returned in the result',
'Flag indicating whether completed tasks are returned in the result'
}, },
{ {
displayName: 'Show Deleted', displayName: 'Show Deleted',
name: 'showDeleted', name: 'showDeleted',
type: 'boolean', type: 'boolean',
default: false, default: false,
description: description: 'Flag indicating whether deleted tasks are returned in the result',
'Flag indicating whether deleted tasks are returned in the result'
}, },
{ {
displayName: 'Show Hidden', displayName: 'Show Hidden',
name: 'showHidden', name: 'showHidden',
type: 'boolean', type: 'boolean',
default: false, default: false,
description: description: 'Flag indicating whether hidden tasks are returned in the result',
'Flag indicating whether hidden tasks are returned in the result'
}, },
{ {
displayName: 'Updated Min', displayName: 'Updated Min',
name: 'updatedMin', name: 'updatedMin',
type: 'string', type: 'dateTime',
default: '',
description: description: 'Lower bound for a task last modification time (as a RFC 3339 timestamp) to filter by.',
'Lower bound for a task last modification time (as a RFC 3339 timestamp) to filter by.' },
}
] ]
}, },
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/* task:update */ /* task:update */
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
{ {
displayName: 'TaskList', displayName: 'TaskList',
name: 'task', name: 'task',
type: 'options', type: 'options',
typeOptions: { typeOptions: {
loadOptionsMethod: 'getTasks' loadOptionsMethod: 'getTasks',
}, },
required: true, required: true,
displayOptions: { displayOptions: {
show: { show: {
operation: ['update'], operation: [
resource: ['task'] 'update',
} ],
resource: [
'task',
],
},
}, },
default: '' default: '',
}, },
{ {
displayName: 'Task ID', displayName: 'Task ID',
@@ -411,11 +404,15 @@ export const taskFields = [
required: true, required: true,
displayOptions: { displayOptions: {
show: { show: {
operation: ['update'], operation: [
resource: ['task'] 'update',
} ],
resource: [
'task',
],
},
}, },
default: '' default: '',
}, },
{ {
displayName: 'Update Fields', displayName: 'Update Fields',
@@ -425,115 +422,71 @@ export const taskFields = [
default: {}, default: {},
displayOptions: { displayOptions: {
show: { show: {
operation: ['update'], operation: [
resource: ['task'] 'update',
],
resource: [
'task',
],
} }
}, },
options: [ options: [
{ {
displayName: 'Status', displayName: 'Completion Date',
name: 'status', name: 'completed',
type: 'options', type: 'dateTime',
options: [
{
name: 'needs Action',
value: 'needsAction'
},
{
name: 'completed',
value: 'completed'
}
],
default: '', default: '',
description: 'Current status of the task.' description: `Completion date of the task (as a RFC 3339 timestamp). This field is omitted if the task has not been completed.`,
},
{
displayName: 'Links',
name: 'links',
type: 'string',
typeOptions: {
multipleValues: true,
multipleValueButtonText: 'Add Link'
},
default: '',
description: 'The links to insert in the task.'
}, },
{
displayName: 'Deleted',
name: 'deleted',
type: 'boolean',
default: false,
description: 'Flag indicating whether the task has been deleted.',
},
{ {
displayName: 'Notes', displayName: 'Notes',
name: 'notes', name: 'notes',
type: 'string', type: 'string',
typeOptions: {
alwaysOpenEditWindow: true,
},
default: '', default: '',
description: 'Additional Notes.' description: 'Additional Notes.',
},
{
displayName: 'Title',
name: 'title',
type: 'string',
default: '',
description: 'Title of the task.'
},
{
displayName: 'Due Date',
name: 'dueDate',
type: 'dateTime',
default: '',
description: 'Due date of the task.'
},
{
displayName: 'Completion date',
name: 'completed',
type: 'dateTime',
default: '',
description: `Completion date of the task (as a RFC 3339 timestamp). This field is omitted if the task has not been completed.`
},
{
displayName: 'Deleted status',
name: 'deleted',
type: 'boolean',
default: false,
description: 'Flag indicating whether the task has been deleted.'
},
{
displayName: 'Hidden',
name: 'hidden',
type: 'boolean',
default: false,
description: 'Flag indicating whether the task is hidden.'
},
{
displayName: 'Parent',
name: 'parent',
type: 'string',
default: '',
description:
'Parent task identifier.This field is omitted if it is a top-level task.'
},
{
displayName: 'Position',
name: 'position',
type: 'string',
default: '',
description:
'Parent task identifier.This field is omitted if it is a top-level task.'
},
{
displayName: 'Self Link',
name: 'selfLink',
type: 'string',
default: '',
description:
'URL pointing to this task. Used to retrieve, update, or delete this task.'
}, },
{ {
displayName: 'Previous', displayName: 'Previous',
name: 'previous', name: 'previous',
type: 'string', type: 'string',
default: '', default: '',
description: description: 'Previous sibling task identifier. If the task is created at the first position among its siblings, this parameter is omitted.',
'Previous sibling task identifier. If the task is created at the first position among its siblings, this parameter is omitted.' },
} {
] displayName: 'Status',
} name: 'status',
type: 'options',
options: [
{
name: 'Needs Update',
value: 'needsAction',
},
{
name: 'Completed',
value: 'completed',
}
],
default: '',
description: 'Current status of the task.',
},
{
displayName: 'Title',
name: 'title',
type: 'string',
default: '',
description: 'Title of the task.',
},
],
},
] as INodeProperties[]; ] as INodeProperties[];

View File

@@ -1,13 +1,17 @@
import { IExecuteFunctions } from 'n8n-core'; import {
IExecuteFunctions,
} from 'n8n-core';
import { import {
IDataObject, IDataObject,
INodeTypeDescription, INodeTypeDescription,
INodeExecutionData, INodeExecutionData,
INodeType INodeType,
} from 'n8n-workflow'; } from 'n8n-workflow';
import { messageBirdApiRequest } from './GenericFunctions'; import {
messageBirdApiRequest,
} from './GenericFunctions';
export class MessageBird implements INodeType { export class MessageBird implements INodeType {
description: INodeTypeDescription = { description: INodeTypeDescription = {
@@ -20,15 +24,15 @@ export class MessageBird implements INodeType {
description: 'Sending SMS', description: 'Sending SMS',
defaults: { defaults: {
name: 'MessageBird', name: 'MessageBird',
color: '#2481d7' color: '#2481d7',
}, },
inputs: ['main'], inputs: ['main'],
outputs: ['main'], outputs: ['main'],
credentials: [ credentials: [
{ {
name: 'messageBirdApi', name: 'messageBirdApi',
required: true required: true,
} },
], ],
properties: [ properties: [
{ {
@@ -38,31 +42,32 @@ export class MessageBird implements INodeType {
options: [ options: [
{ {
name: 'SMS', name: 'SMS',
value: 'sms' value: 'sms',
} },
], ],
default: 'sms', default: 'sms',
description: 'The resource to operate on.' description: 'The resource to operate on.',
}, },
{ {
displayName: 'Operation', displayName: 'Operation',
name: 'operation', name: 'operation',
type: 'options', type: 'options',
displayOptions: { displayOptions: {
show: { show: {
resource: ['sms'] resource: [
} 'sms',
],
},
}, },
options: [ options: [
{ {
name: 'Send', name: 'Send',
value: 'send', value: 'send',
description: 'Send text messages (SMS)' description: 'Send text messages (SMS)',
} },
], ],
default: 'send', default: 'send',
description: 'The operation to perform.' description: 'The operation to perform.',
}, },
// ---------------------------------- // ----------------------------------
@@ -77,11 +82,15 @@ export class MessageBird implements INodeType {
required: true, required: true,
displayOptions: { displayOptions: {
show: { show: {
operation: ['send'], operation: [
resource: ['sms'] 'send',
} ],
resource: [
'sms',
],
},
}, },
description: 'The number from which to send the message.' description: 'The number from which to send the message.',
}, },
{ {
displayName: 'To', displayName: 'To',
@@ -92,13 +101,16 @@ export class MessageBird implements INodeType {
required: true, required: true,
displayOptions: { displayOptions: {
show: { show: {
operation: ['send'], operation: [
resource: ['sms'] 'send',
} ],
resource: [
'sms',
],
},
}, },
description: 'All recipients separated by commas.' description: 'All recipients separated by commas.',
}, },
{ {
displayName: 'Message', displayName: 'Message',
name: 'message', name: 'message',
@@ -107,11 +119,15 @@ export class MessageBird implements INodeType {
required: true, required: true,
displayOptions: { displayOptions: {
show: { show: {
operation: ['send'], operation: [
resource: ['sms'] 'send',
} ],
resource: [
'sms',
],
},
}, },
description: 'The message to be send.' description: 'The message to be send.',
}, },
{ {
displayName: 'Additional Fields', displayName: 'Additional Fields',
@@ -125,8 +141,7 @@ export class MessageBird implements INodeType {
name: 'createdDatetime', name: 'createdDatetime',
type: 'dateTime', type: 'dateTime',
default: '', default: '',
description: description: 'The date and time of the creation of the message in RFC3339 format (Y-m-dTH:i:sP).',
'The date and time of the creation of the message in RFC3339 format (Y-m-dTH:i:sP).'
}, },
{ {
displayName: 'Datacoding', displayName: 'Datacoding',
@@ -135,27 +150,26 @@ export class MessageBird implements INodeType {
options: [ options: [
{ {
name: 'Auto', name: 'Auto',
value: 'auto' value: 'auto',
}, },
{ {
name: 'Plain', name: 'Plain',
value: 'plain' value: 'plain',
}, },
{ {
name: 'Unicode', name: 'Unicode',
value: 'unicode' value: 'unicode',
} },
], ],
default: '', default: '',
description: description: 'Using unicode will limit the maximum number of characters to 70 instead of 160.',
'Using unicode will limit the maximum number of characters to 70 instead of 160.'
}, },
{ {
displayName: 'Gateway', displayName: 'Gateway',
name: 'gateway', name: 'gateway',
type: 'number', type: 'number',
default: '', default: '',
description: 'The SMS route that is used to send the message.' description: 'The SMS route that is used to send the message.',
}, },
{ {
displayName: 'Group IDs', displayName: 'Group IDs',
@@ -163,8 +177,7 @@ export class MessageBird implements INodeType {
placeholder: '1,2', placeholder: '1,2',
type: 'string', type: 'string',
default: '', default: '',
description: description: 'Group IDs separated by commas, If provided recipients can be omitted.',
'Group IDs separated by commas, If provided recipients can be omitted.'
}, },
{ {
displayName: 'Message Type', displayName: 'Message Type',
@@ -174,39 +187,36 @@ export class MessageBird implements INodeType {
options: [ options: [
{ {
name: 'Flash', name: 'Flash',
value: 1 value: 1,
}, },
{ {
name: 'Normal', name: 'Normal',
value: 0 value: 0,
} },
], ],
default: 1, default: 1,
description: description: 'Indicated the message type. 1 is a normal message, 0 is a flash message.',
'Indicated the message type. 1 is a normal message, 0 is a flash message.'
}, },
{ {
displayName: 'Reference', displayName: 'Reference',
name: 'reference', name: 'reference',
type: 'string', type: 'string',
default: '', default: '',
description: 'A client reference.' description: 'A client reference.',
}, },
{ {
displayName: 'Report Url', displayName: 'Report Url',
name: 'reportUrl', name: 'reportUrl',
type: 'string', type: 'string',
default: '', default: '',
description: description: 'The status report URL to be used on a per-message basis.<br /> Reference is required for a status report webhook to be sent.',
'The status report URL to be used on a per-message basis.<br /> Reference is required for a status report webhook to be sent.'
}, },
{ {
displayName: 'Scheduled Date-time', displayName: 'Scheduled Date-time',
name: 'scheduledDatetime', name: 'scheduledDatetime',
type: 'dateTime', type: 'dateTime',
default: '', default: '',
description: description: 'The scheduled date and time of the message in RFC3339 format (Y-m-dTH:i:sP).',
'The scheduled date and time of the message in RFC3339 format (Y-m-dTH:i:sP).'
}, },
{ {
displayName: 'Type', displayName: 'Type',
@@ -215,28 +225,26 @@ export class MessageBird implements INodeType {
options: [ options: [
{ {
name: 'Binary', name: 'Binary',
value: 'binary' value: 'binary',
}, },
{ {
name: 'Flash', name: 'Flash',
value: 'flash' value: 'flash',
}, },
{ {
name: 'SMS', name: 'SMS',
value: 'sms' value: 'sms',
} },
], ],
default: '', default: '',
description: description: 'The type of message.<br /> Values can be: sms, binary, or flash.',
'The type of message.<br /> Values can be: sms, binary, or flash.'
}, },
{ {
displayName: 'Type Details', displayName: 'Type Details',
name: 'typeDetails', name: 'typeDetails',
type: 'string', type: 'string',
default: '', default: '',
description: description: 'A hash with extra information.<br /> Is only used when a binary message is sent.',
'A hash with extra information.<br /> Is only used when a binary message is sent.'
}, },
{ {
displayName: 'Validity', displayName: 'Validity',
@@ -244,13 +252,13 @@ export class MessageBird implements INodeType {
type: 'number', type: 'number',
default: 1, default: 1,
typeOptions: { typeOptions: {
minValue: 1 minValue: 1,
}, },
description: 'The amount of seconds that the message is valid.' description: 'The amount of seconds that the message is valid.',
} },
] ],
} },
] ],
}; };
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> { async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {

View File

@@ -9,21 +9,11 @@ import {
import { IDataObject } from 'n8n-workflow'; import { IDataObject } from 'n8n-workflow';
import * as _ from 'lodash'; import * as _ from 'lodash';
export async function zoomApiRequest( export async function zoomApiRequest(this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, method: string, resource: string, body: object = {}, query: object = {}, headers: {} | undefined = undefined, option: {} = {}): Promise<any> { // tslint:disable-line:no-any
this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions,
method: string,
resource: string,
body: object = {},
query: object = {},
headers: {} | undefined = undefined,
option: {} = {}
): Promise<any> {
// tslint:disable-line:no-any // tslint:disable-line:no-any
const authenticationMethod = this.getNodeParameter( const authenticationMethod = this.getNodeParameter('authentication', 0, 'accessToken') as string;
'authentication',
0,
'accessToken'
) as string;
let options: OptionsWithUri = { let options: OptionsWithUri = {
method, method,
headers: headers || { headers: headers || {
@@ -31,7 +21,7 @@ export async function zoomApiRequest(
}, },
body, body,
qs: query, qs: query,
uri: `https://zoom.us/oauth${resource}`, uri: `https://api.zoom.us/v2${resource}`,
json: true json: true
}; };
options = Object.assign({}, options, option); options = Object.assign({}, options, option);
@@ -41,6 +31,8 @@ export async function zoomApiRequest(
if (Object.keys(query).length === 0) { if (Object.keys(query).length === 0) {
delete options.qs; delete options.qs;
} }
console.log("options");
console.log(options);
try { try {
if (authenticationMethod === 'accessToken') { if (authenticationMethod === 'accessToken') {
const credentials = this.getCredentials('zoomApi'); const credentials = this.getCredentials('zoomApi');
@@ -48,15 +40,24 @@ export async function zoomApiRequest(
throw new Error('No credentials got returned!'); throw new Error('No credentials got returned!');
} }
options.headers!.Authorization = `Bearer ${credentials.accessToken}`; options.headers!.Authorization = `Bearer ${credentials.accessToken}`;
console.log("options if");
console.log(options);
//@ts-ignore //@ts-ignore
return await this.helpers.request(options); return await this.helpers.request(options);
} else { } else {
console.log("options else");
console.log(options);
let credentials = this.getCredentials('zoomOAuth2Api');
// let oauthtoken1 = credentials!.oauthTokenData;
console.log(credentials);
console.log("credss");
//@ts-ignore //@ts-ignore
return await this.helpers.requestOAuth2.call(
this, return await this.helpers.requestOAuth2.call(this, 'zoomOAuth2Api', options);
'zoomOAuth2Api',
options
);
} }
} catch (error) { } catch (error) {
if (error.statusCode === 401) { if (error.statusCode === 401) {
@@ -66,16 +67,17 @@ export async function zoomApiRequest(
if (error.response && error.response.body && error.response.body.message) { if (error.response && error.response.body && error.response.body.message) {
// Try to return the error prettier // Try to return the error prettier
throw new Error( throw new Error(`Zoom error response [${error.statusCode}]: ${error.response.body.message}`);
`Zoom error response [${error.statusCode}]: ${error.response.body.message}`
);
} }
// If that data does not exist for some reason return the actual error // If that data does not exist for some reason return the actual error
throw error; throw error;
} }
} }
export async function zoomApiRequestAllItems( export async function zoomApiRequestAllItems(
this: IExecuteFunctions | ILoadOptionsFunctions, this: IExecuteFunctions | ILoadOptionsFunctions,
propertyName: string, propertyName: string,

View File

@@ -3,13 +3,18 @@ import {
IDataObject, IDataObject,
INodeExecutionData, INodeExecutionData,
INodeType, INodeType,
INodeTypeDescription INodeTypeDescription,
} from 'n8n-workflow'; } from 'n8n-workflow';
import { import {
zoomApiRequest, zoomApiRequest,
zoomApiRequestAllItems, zoomApiRequestAllItems,
validateJSON validateJSON,
} from './GenericFunctions'; } from './GenericFunctions';
import {
meetingOperations,
meetingFields,
} from './ZoomOperations';
export class Zoom implements INodeType { export class Zoom implements INodeType {
description: INodeTypeDescription = { description: INodeTypeDescription = {
displayName: 'Zoom', displayName: 'Zoom',
@@ -25,25 +30,49 @@ export class Zoom implements INodeType {
icon: 'file:zoom.png', icon: 'file:zoom.png',
inputs: ['main'], inputs: ['main'],
outputs: ['main'], outputs: ['main'],
// credentials: [
// {
// name: 'zoomApi',
// required: true,
// displayOptions: {
// show: {
// authentication: ['accessToken']
// }
// }
// },
// {
// name: 'zoomOAuth2Api',
// required: true,
// displayOptions: {
// show: {
// authentication: ['oAuth2']
// }
// }
// }
// ],
credentials: [ credentials: [
{ {
name: 'zoomApi', name: 'zoomApi',
required: true, required: true,
displayOptions: { displayOptions: {
show: { show: {
authentication: ['accessToken'] authentication: [
} 'accessToken',
} ],
},
},
}, },
{ {
name: 'zoomOAuth2Api', name: 'zoomOAuth2Api',
required: true, required: true,
displayOptions: { displayOptions: {
show: { show: {
authentication: ['oAuth2'] authentication: [
} 'oAuth2',
} ],
} },
},
},
], ],
properties: [ properties: [
{ {
@@ -53,15 +82,15 @@ export class Zoom implements INodeType {
options: [ options: [
{ {
name: 'Access Token', name: 'Access Token',
value: 'accessToken' value: 'accessToken',
}, },
{ {
name: 'OAuth2', name: 'OAuth2',
value: 'oAuth2' value: 'oAuth2',
} },
], ],
default: 'accessToken', default: 'accessToken',
description: 'The resource to operate on.' description: 'The resource to operate on.',
}, },
{ {
displayName: 'Resource', displayName: 'Resource',
@@ -69,14 +98,17 @@ export class Zoom implements INodeType {
type: 'options', type: 'options',
options: [ options: [
{ {
name: 'meeting', name: 'Meeting',
value: 'meeting' value: 'meeting'
} }
], ],
default: 'meeting', default: 'meeting',
description: 'The resource to operate on.' description: 'The resource to operate on.'
} },
...meetingOperations,
...meetingFields
] ]
}; };
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> { async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
@@ -85,29 +117,26 @@ export class Zoom implements INodeType {
const length = (items.length as unknown) as number; const length = (items.length as unknown) as number;
let qs: IDataObject; let qs: IDataObject;
let responseData; let responseData;
const authentication = this.getNodeParameter('authentication', 0) as string;
const resource = this.getNodeParameter('resource', 0) as string; const resource = this.getNodeParameter('resource', 0) as string;
// const operation = this.getNodeParameter('operation', 0) as string; const operation = this.getNodeParameter('operation', 0) as string;
console.log(this.getCredentials('zoomOAuth2Api')); console.log(this.getCredentials('zoomOAuth2Api'));
// for (let i = 0; i < length; i++) { for (let i = 0; i < length; i++) {
// qs = {}; qs = {};
// if (resource === 'channel') { if (resource === 'meeting') {
// //https://api.slack.com/methods/conversations.archive
// if (operation === 'archive') { if (operation === 'get') {
// const channel = this.getNodeParameter('channelId', i) as string; const userId = this.getNodeParameter('userId', i) as string;
// const body: IDataObject = {
// channel responseData = await zoomApiRequest.call(
// }; this,
// responseData = await zoomApiRequest.call( 'GET',
// this, `/meetings/${userId}`,
// 'POST', {},
// '/conversations.archive', qs
// body, );
// qs }
// ); }
// } }
// }
// }
if (Array.isArray(responseData)) { if (Array.isArray(responseData)) {
returnData.push.apply(returnData, responseData as IDataObject[]); returnData.push.apply(returnData, responseData as IDataObject[]);
} else { } else {

View File

@@ -0,0 +1,71 @@
import {
INodeProperties,
} from 'n8n-workflow';
export const meetingOperations = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
displayOptions: {
show: {
resource: [
'meeting',
],
},
},
options: [
{
name: 'Create',
value: 'create',
description: 'Create a meeting',
},
{
name: 'Delete',
value: 'delete',
description: 'Delete a meeting',
},
{
name: 'Get',
value: 'get',
description: 'Retrieve a meeting',
},
{
name: 'Get All',
value: 'getAll',
description: 'Retrieve all meetings',
},
{
name: 'Update',
value: 'update',
description: 'Update a meeting',
}
],
default: 'create',
description: 'The operation to perform.',
}
] as INodeProperties[];
export const meetingFields = [
/* -------------------------------------------------------------------------- */
/* meeting:get */
/* -------------------------------------------------------------------------- */
{
displayName: 'User Id',
name: 'userId',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
operation: [
'get',
],
resource: [
'meeting',
],
},
},
description: 'User ID.',
},
] as INodeProperties[];