From 35968076304a209d4c2c39333f538053d244df4a Mon Sep 17 00:00:00 2001 From: ricardo Date: Wed, 22 Apr 2020 12:08:53 -0500 Subject: [PATCH] :zap: Mattermost improvements --- .../nodes/Mattermost/GenericFunctions.ts | 28 ++- .../nodes/Mattermost/Mattermost.node.ts | 220 +++++++++++++++++- 2 files changed, 242 insertions(+), 6 deletions(-) diff --git a/packages/nodes-base/nodes/Mattermost/GenericFunctions.ts b/packages/nodes-base/nodes/Mattermost/GenericFunctions.ts index 329e3ae83b..f34754bf73 100644 --- a/packages/nodes-base/nodes/Mattermost/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Mattermost/GenericFunctions.ts @@ -4,8 +4,13 @@ import { ILoadOptionsFunctions, } from 'n8n-core'; -import { OptionsWithUri } from 'request'; -import { IDataObject } from 'n8n-workflow'; +import { + OptionsWithUri, + } from 'request'; + +import { + IDataObject, + } from 'n8n-workflow'; export interface IAttachment { fields: { @@ -65,3 +70,22 @@ export async function apiRequest(this: IHookFunctions | IExecuteFunctions | ILoa throw error; } } + +export async function apiRequestAllItems(this: IExecuteFunctions | ILoadOptionsFunctions, method: string, endpoint: string, body: any = {}, query: IDataObject = {}): Promise { // tslint:disable-line:no-any + + const returnData: IDataObject[] = []; + + let responseData; + query.page = 0; + query.per_page = 100; + + do { + responseData = await apiRequest.call(this, method, endpoint, body, query); + query.page++; + returnData.push.apply(returnData, responseData); + } while ( + responseData.length !== 0 + ); + + return returnData; +} diff --git a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts index e9f81e7d8d..7da364f666 100644 --- a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts +++ b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts @@ -1,4 +1,7 @@ -import { IExecuteFunctions } from 'n8n-core'; +import { + IExecuteFunctions, + } from 'n8n-core'; + import { IDataObject, ILoadOptionsFunctions, @@ -10,9 +13,13 @@ import { import { apiRequest, + apiRequestAllItems, IAttachment, } from './GenericFunctions'; +import { + snakeCase, +} from 'change-case'; export class Mattermost implements INodeType { description: INodeTypeDescription = { @@ -837,6 +844,11 @@ export class Mattermost implements INodeType { value: 'deactive', description: 'Deactivates the user and revokes all its sessions by archiving its user object.', }, + { + name: 'Get All', + value: 'getAll', + description: 'Retrieve all users', + }, ], default: '', description: 'The operation to perform.', @@ -863,6 +875,122 @@ export class Mattermost implements INodeType { description: 'User GUID' }, + // ---------------------------------- + // user:getAll + // ---------------------------------- + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'getAll', + ], + }, + }, + default: true, + 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: [ + 'getAll', + ], + returnAll: [ + false, + ], + }, + }, + typeOptions: { + minValue: 1, + maxValue: 100, + }, + default: 100, + description: 'How many results to return.', + }, + { + displayName: 'Additional Fields', + name: 'additionalFields', + type: 'collection', + placeholder: 'Add Field', + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'getAll', + ], + }, + }, + default: {}, + options: [ + { + displayName: 'In Channel', + name: 'inChannel', + type: 'string', + default: '', + description: 'The ID of the channel to get users for.', + }, + { + displayName: 'In Team', + name: 'inTeam', + type: 'string', + default: '', + description: 'The ID of the team to get users for.', + }, + { + displayName: 'Not In Team', + name: 'notInTeam', + type: 'string', + default: '', + description: 'The ID of the team to exclude users for.', + }, + { + displayName: 'Not In Channel', + name: 'notInChannel', + type: 'string', + default: '', + description: 'The ID of the channel to exclude users for.', + }, + { + displayName: 'Sort', + name: 'sort', + type: 'options', + options: [ + { + name: 'Created At', + value: 'createdAt', + }, + { + name: 'Last Activity At', + value: 'lastActivityAt', + }, + { + name: 'Status', + value: 'status', + }, + { + name: 'username', + value: 'username', + }, + ], + default: 'username', + description: 'The ID of the channel to exclude users for.', + }, + ], + }, ], }; @@ -962,6 +1090,7 @@ export class Mattermost implements INodeType { let operation: string; let resource: string; let requestMethod = 'POST'; + let returnAll = false; // For Post let body: IDataObject; @@ -986,7 +1115,7 @@ export class Mattermost implements INodeType { endpoint = 'channels'; body.team_id = this.getNodeParameter('teamId', i) as string; - body.displayName = this.getNodeParameter('displayName', i) as string; + body.display_name = this.getNodeParameter('displayName', i) as string; body.name = this.getNodeParameter('channel', i) as string; const type = this.getNodeParameter('type', i) as string; @@ -1129,13 +1258,96 @@ export class Mattermost implements INodeType { requestMethod = 'DELETE'; endpoint = `users/${userId}`; } + + if (operation === 'getAll') { + // ---------------------------------- + // user:getAll + // ---------------------------------- + + requestMethod = 'GET'; + + returnAll = this.getNodeParameter('returnAll', i) as boolean; + const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; + + if (additionalFields.inTeam) { + qs.in_team = additionalFields.inTeam; + } + + if (additionalFields.notInTeam) { + qs.not_in_team = additionalFields.notInTeam; + } + + if (additionalFields.inChannel) { + qs.in_channel = additionalFields.inChannel; + } + + if (additionalFields.notInChannel) { + qs.not_in_channel = additionalFields.notInChannel; + } + + if (additionalFields.sort) { + qs.sort = snakeCase(additionalFields.sort as string); + } + + const validRules = { + inTeam: ['last_activity_at', 'created_at', 'username'], + inChannel: ['status', 'username'], + }; + + if (additionalFields.sort) { + if (additionalFields.inTeam !== undefined || additionalFields.inChannel !== undefined) { + + if (additionalFields.inTeam !== undefined + && !validRules.inTeam.includes(snakeCase(additionalFields.sort as string))) { + throw new Error(`When In Team is set the only valid values for sorting are ${validRules.inTeam.join(',')}`); + } + if (additionalFields.inChannel !== undefined + && !validRules.inChannel.includes(snakeCase(additionalFields.sort as string))) { + throw new Error(`When In Channel is set the only valid values for sorting are ${validRules.inChannel.join(',')}`); + } + if (additionalFields.inChannel !== undefined + && additionalFields.inChannel === '' + && additionalFields.sort !== 'username') { + throw new Error('When sort is different than username In Channel must be set'); + } + + if (additionalFields.inTeam !== undefined + && additionalFields.inTeam === '' + && additionalFields.sort !== 'username') { + throw new Error('When sort is different than username In Team must be set'); + } + + } else { + throw new Error(`When sort is defined either 'in team' or 'in channel' must be defined`); + } + } + + if (additionalFields.sort === 'username') { + qs.sort = ''; + } + + if (returnAll === false) { + qs.limit = this.getNodeParameter('limit', i) as number; + } + + endpoint = `/users`; + } } else { throw new Error(`The resource "${resource}" is not known!`); } - const responseData = await apiRequest.call(this, requestMethod, endpoint, body, qs); - returnData.push(responseData); + let responseData; + if (returnAll) { + responseData = await apiRequestAllItems.call(this, requestMethod, endpoint, body, qs); + } else { + responseData = await apiRequest.call(this, requestMethod, endpoint, body, qs); + } + if (Array.isArray(responseData)) { + returnData.push.apply(returnData, responseData); + } else { + returnData.push(responseData); + } } return [this.helpers.returnJsonArray(returnData)];