diff --git a/packages/nodes-base/credentials/DiscourseApi.credentials.ts b/packages/nodes-base/credentials/DiscourseApi.credentials.ts index 3abf156799239..d34da38ea8fc5 100644 --- a/packages/nodes-base/credentials/DiscourseApi.credentials.ts +++ b/packages/nodes-base/credentials/DiscourseApi.credentials.ts @@ -1,5 +1,8 @@ import { + ICredentialDataDecryptedObject, + ICredentialTestRequest, ICredentialType, + IHttpRequestOptions, INodeProperties, } from 'n8n-workflow'; @@ -30,4 +33,25 @@ export class DiscourseApi implements ICredentialType { default: '', }, ]; + + async authenticate(credentials: ICredentialDataDecryptedObject, requestOptions: IHttpRequestOptions): Promise { + requestOptions.headers = { + 'Api-Key': credentials.apiKey, + 'Api-Username': credentials.username, + }; + + if (requestOptions.method === 'GET') { + delete requestOptions.body; + } + + return requestOptions; + } + + test: ICredentialTestRequest = { + request: { + baseURL: '={{$credentials.url}}', + url: '/admin/groups.json', + method: 'GET', + }, + }; } diff --git a/packages/nodes-base/credentials/ZendeskApi.credentials.ts b/packages/nodes-base/credentials/ZendeskApi.credentials.ts index f4c2898669a6f..8a6e21e29b6a5 100644 --- a/packages/nodes-base/credentials/ZendeskApi.credentials.ts +++ b/packages/nodes-base/credentials/ZendeskApi.credentials.ts @@ -38,7 +38,7 @@ export class ZendeskApi implements ICredentialType { password: credentials.apiToken as string, }; return requestOptions; - } + } test: ICredentialTestRequest = { request: { baseURL: '=https://{{$credentials.subdomain}}.zendesk.com/api/v2', diff --git a/packages/nodes-base/nodes/Discourse/Discourse.node.ts b/packages/nodes-base/nodes/Discourse/Discourse.node.ts index 5bc4d350af635..38ff72cb89888 100644 --- a/packages/nodes-base/nodes/Discourse/Discourse.node.ts +++ b/packages/nodes-base/nodes/Discourse/Discourse.node.ts @@ -3,12 +3,16 @@ import { } from 'n8n-core'; import { + ICredentialsDecrypted, + ICredentialTestFunctions, IDataObject, ILoadOptionsFunctions, + INodeCredentialTestResult, INodeExecutionData, INodePropertyOptions, INodeType, INodeTypeDescription, + JsonObject, } from 'n8n-workflow'; import { @@ -44,6 +48,7 @@ import { userGroupFields, userGroupOperations, } from './UserGroupDescription'; +import { OptionsWithUri } from 'request'; //import moment from 'moment'; @@ -117,6 +122,7 @@ export class Discourse implements INodeType { }; methods = { + loadOptions: { // Get all the calendars to display them to user so that he can // select them easily @@ -321,6 +327,7 @@ export class Discourse implements INodeType { //https://docs.discourse.org/#tag/Posts/paths/~1posts.json/get if (operation === 'getAll') { const returnAll = this.getNodeParameter('returnAll', i) as boolean; + const limit = this.getNodeParameter('limit', i, 0) as number; responseData = await discourseApiRequest.call( this, @@ -329,11 +336,29 @@ export class Discourse implements INodeType { {}, qs, ); - responseData = responseData.latest_posts; + //Getting all posts relying on https://github.com/discourse/discourse_api/blob/main/spec/discourse_api/api/posts_spec.rb + let lastPost = responseData.pop(); + let previousLastPostID; + while (lastPost.id !== previousLastPostID) { + if (limit && responseData.length > limit) { + break; + } + const chunk = await discourseApiRequest.call( + this, + 'GET', + `/posts.json?before=${lastPost.id}`, + {}, + qs, + ); + responseData = responseData.concat(chunk.latest_posts); + previousLastPostID = lastPost.id; + lastPost = responseData.pop(); + } + responseData.push(lastPost); + if (returnAll === false) { - const limit = this.getNodeParameter('limit', i) as number; responseData = responseData.splice(0, limit); } } @@ -495,7 +520,7 @@ export class Discourse implements INodeType { } } catch (error) { if (this.continueOnFail()) { - returnData.push({ error: error.message }); + returnData.push({ error: (error as JsonObject).message }); continue; } throw error; diff --git a/packages/nodes-base/nodes/Discourse/GenericFunctions.ts b/packages/nodes-base/nodes/Discourse/GenericFunctions.ts index 81462dd288710..94152fef57815 100644 --- a/packages/nodes-base/nodes/Discourse/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Discourse/GenericFunctions.ts @@ -9,18 +9,14 @@ import { } from 'n8n-core'; import { - IDataObject, NodeApiError, + IDataObject, JsonObject, NodeApiError, } from 'n8n-workflow'; export async function discourseApiRequest(this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, method: string, path: string, body: any = {}, qs: IDataObject = {}, option = {}): Promise { // tslint:disable-line:no-any - const credentials = await this.getCredentials('discourseApi'); + const credentials = await this.getCredentials('discourseApi') as { url: string }; const options: OptionsWithUri = { - headers: { - 'Api-Key': credentials.apiKey, - 'Api-Username': credentials.username, - }, method, body, qs, @@ -32,10 +28,9 @@ export async function discourseApiRequest(this: IExecuteFunctions | IExecuteSing if (Object.keys(body).length === 0) { delete options.body; } - //@ts-ignore - return await this.helpers.request.call(this, options); + return await this.helpers.requestWithAuthentication.call(this, 'discourseApi', options); } catch (error) { - throw new NodeApiError(this.getNode(), error); + throw new NodeApiError(this.getNode(), error as JsonObject); } } diff --git a/packages/nodes-base/nodes/Zendesk/Zendesk.node.ts b/packages/nodes-base/nodes/Zendesk/Zendesk.node.ts index 8e8c3b7a88e5c..11bd7637f7351 100644 --- a/packages/nodes-base/nodes/Zendesk/Zendesk.node.ts +++ b/packages/nodes-base/nodes/Zendesk/Zendesk.node.ts @@ -1,17 +1,10 @@ -import { - OptionsWithUri, -} from 'request'; - import { IExecuteFunctions, } from 'n8n-core'; import { - ICredentialsDecrypted, - ICredentialTestFunctions, IDataObject, ILoadOptionsFunctions, - INodeCredentialTestResult, INodeExecutionData, INodePropertyOptions, INodeType,