From 44f6ef2ed729ad39518cc85e068be03cd8b409ff Mon Sep 17 00:00:00 2001 From: Jon Date: Mon, 22 Jan 2024 12:39:19 +0000 Subject: [PATCH] fix(Asana Node): Fix issue when connecting to the new Asana environment (#8404) --- packages/nodes-base/nodes/Asana/Asana.node.ts | 276 +++++++++--------- .../nodes/Asana/AsanaTrigger.node.ts | 11 +- .../nodes/Asana/GenericFunctions.ts | 9 +- 3 files changed, 152 insertions(+), 144 deletions(-) diff --git a/packages/nodes-base/nodes/Asana/Asana.node.ts b/packages/nodes-base/nodes/Asana/Asana.node.ts index f5cffdd3b8f7c..a30897551c442 100644 --- a/packages/nodes-base/nodes/Asana/Asana.node.ts +++ b/packages/nodes-base/nodes/Asana/Asana.node.ts @@ -1,7 +1,6 @@ import type { IExecuteFunctions, IDataObject, - IHttpRequestMethods, ILoadOptionsFunctions, INodeExecutionData, INodePropertyOptions, @@ -143,7 +142,7 @@ export class Asana implements INodeType { { name: 'Get Many', value: 'getAll', - description: 'Get many substasks', + description: 'Get many subtasks', action: 'Get many subtasks', }, ], @@ -1686,8 +1685,7 @@ export class Asana implements INodeType { // Get all the available projects to display them to user so that they can be // selected easily async getProjects(this: ILoadOptionsFunctions): Promise { - const endpoint = '/projects'; - const responseData = await asanaApiRequest.call(this, 'GET', endpoint, {}); + const responseData = await asanaApiRequest.call(this, 'GET', '/projects', {}); if (responseData.data === undefined) { throw new NodeApiError(this.getNode(), responseData as JsonObject, { @@ -1727,8 +1725,12 @@ export class Asana implements INodeType { // can be selected easily async getSections(this: ILoadOptionsFunctions): Promise { const projectId = this.getNodeParameter('projectId') as string; - const endpoint = `/projects/${projectId}/sections`; - const responseData = await asanaApiRequest.call(this, 'GET', endpoint, {}); + const responseData = await asanaApiRequest.call( + this, + 'GET', + `/projects/${projectId}/sections`, + {}, + ); if (responseData.data === undefined) { throw new NodeApiError(this.getNode(), responseData as JsonObject, { @@ -1780,9 +1782,12 @@ export class Asana implements INodeType { ); } - const endpoint = `/organizations/${workspaceId}/teams`; - - const responseData = await asanaApiRequestAllItems.call(this, 'GET', endpoint, {}); + const responseData = await asanaApiRequestAllItems.call( + this, + 'GET', + `/organizations/${workspaceId}/teams`, + {}, + ); const returnData: INodePropertyOptions[] = []; for (const teamData of responseData) { @@ -1814,8 +1819,6 @@ export class Asana implements INodeType { // Get all tags to display them to user so that they can be selected easily // See: https://developers.asana.com/docs/get-multiple-tags async getTags(this: ILoadOptionsFunctions): Promise { - const endpoint = '/tags'; - const taskId = this.getNodeParameter('id') as string; let taskData; try { @@ -1827,7 +1830,7 @@ export class Asana implements INodeType { } const workspace = taskData.data.workspace.gid; - const responseData = await asanaApiRequest.call(this, 'GET', endpoint, {}, { workspace }); + const responseData = await asanaApiRequest.call(this, 'GET', '/tags', {}, { workspace }); if (responseData.data === undefined) { throw new NodeApiError(this.getNode(), responseData as JsonObject, { @@ -1864,8 +1867,7 @@ export class Asana implements INodeType { // Get all users to display them to user so that they can be selected easily // See: https://developers.asana.com/docs/get-multiple-users async getUsers(this: ILoadOptionsFunctions): Promise { - const endpoint = '/users'; - const responseData = await asanaApiRequest.call(this, 'GET', endpoint, {}); + const responseData = await asanaApiRequest.call(this, 'GET', '/users', {}); if (responseData.data === undefined) { throw new NodeApiError(this.getNode(), responseData as JsonObject, { @@ -1911,9 +1913,6 @@ export class Asana implements INodeType { const resource = this.getNodeParameter('resource', 0); const operation = this.getNodeParameter('operation', 0); - let endpoint = ''; - let requestMethod: IHttpRequestMethods = 'GET'; - let body: IDataObject; let qs: IDataObject; let responseData; @@ -1931,15 +1930,18 @@ export class Asana implements INodeType { const taskId = this.getNodeParameter('taskId', i) as string; - requestMethod = 'POST'; - endpoint = `/tasks/${taskId}/subtasks`; - body.name = this.getNodeParameter('name', i) as string; const otherProperties = this.getNodeParameter('otherProperties', i) as IDataObject; Object.assign(body, otherProperties); - responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs); + responseData = await asanaApiRequest.call( + this, + 'POST', + `/tasks/${taskId}/subtasks`, + body, + qs, + ); responseData = responseData.data; } @@ -1954,9 +1956,6 @@ export class Asana implements INodeType { const options = this.getNodeParameter('options', i); - requestMethod = 'GET'; - endpoint = `/tasks/${taskId}/subtasks`; - Object.assign(qs, options); if (qs.opt_fields) { @@ -1970,7 +1969,13 @@ export class Asana implements INodeType { } } - responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs); + responseData = await asanaApiRequest.call( + this, + 'GET', + `/tasks/${taskId}/subtasks`, + body, + qs, + ); responseData = responseData.data; @@ -1986,9 +1991,6 @@ export class Asana implements INodeType { // task:create // ---------------------------------- - requestMethod = 'POST'; - endpoint = '/tasks'; - body.name = this.getNodeParameter('name', i) as string; // body.notes = this.getNodeParameter('taskNotes', 0) as string; body.workspace = this.getNodeParameter('workspace', i) as string; @@ -1996,7 +1998,7 @@ export class Asana implements INodeType { const otherProperties = this.getNodeParameter('otherProperties', i) as IDataObject; Object.assign(body, otherProperties); - responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs); + responseData = await asanaApiRequest.call(this, 'POST', '/tasks', body, qs); responseData = responseData.data; } else if (operation === 'delete') { @@ -2004,11 +2006,13 @@ export class Asana implements INodeType { // task:delete // ---------------------------------- - requestMethod = 'DELETE'; - - endpoint = '/tasks/' + (this.getNodeParameter('id', i) as string); - - responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs); + responseData = await asanaApiRequest.call( + this, + 'DELETE', + `/tasks/${this.getNodeParameter('id', i) as string}`, + body, + qs, + ); responseData = responseData.data; } else if (operation === 'get') { @@ -2016,11 +2020,13 @@ export class Asana implements INodeType { // task:get // ---------------------------------- - requestMethod = 'GET'; - - endpoint = '/tasks/' + (this.getNodeParameter('id', i) as string); - - responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs); + responseData = await asanaApiRequest.call( + this, + 'GET', + `/tasks/${this.getNodeParameter('id', i) as string}`, + body, + qs, + ); responseData = responseData.data; } else if (operation === 'getAll') { @@ -2031,9 +2037,6 @@ export class Asana implements INodeType { const filters = this.getNodeParameter('filters', i); const returnAll = this.getNodeParameter('returnAll', i); - requestMethod = 'GET'; - endpoint = '/tasks'; - Object.assign(qs, filters); if (qs.opt_fields) { @@ -2056,17 +2059,11 @@ export class Asana implements INodeType { } if (returnAll) { - responseData = await asanaApiRequestAllItems.call( - this, - requestMethod, - endpoint, - body, - qs, - ); + responseData = await asanaApiRequestAllItems.call(this, 'GET', '/tasks', body, qs); } else { qs.limit = this.getNodeParameter('limit', i); - responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs); + responseData = await asanaApiRequest.call(this, 'GET', '/tasks', body, qs); responseData = responseData.data; } @@ -2077,15 +2074,17 @@ export class Asana implements INodeType { const sectionId = this.getNodeParameter('section', i) as string; - requestMethod = 'POST'; - - endpoint = `/sections/${sectionId}/addTask`; - body.task = this.getNodeParameter('id', i) as string; Object.assign(body); - responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs); + responseData = await asanaApiRequest.call( + this, + 'POST', + `/sections/${sectionId}/addTask`, + body, + qs, + ); responseData = { success: true }; } else if (operation === 'update') { @@ -2093,32 +2092,38 @@ export class Asana implements INodeType { // task:update // ---------------------------------- - requestMethod = 'PUT'; - endpoint = '/tasks/' + (this.getNodeParameter('id', i) as string); - const otherProperties = this.getNodeParameter('otherProperties', i) as IDataObject; Object.assign(body, otherProperties); - responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs); + responseData = await asanaApiRequest.call( + this, + 'PUT', + `/tasks/${this.getNodeParameter('id', i) as string}`, + body, + qs, + ); responseData = responseData.data; } else if (operation === 'search') { // ---------------------------------- - // tasksearch + // tasks:search // ---------------------------------- const workspaceId = this.getNodeParameter('workspace', i) as string; - requestMethod = 'GET'; - endpoint = `/workspaces/${workspaceId}/tasks/search`; - const searchTaskProperties = this.getNodeParameter( 'searchTaskProperties', i, ) as IDataObject; Object.assign(qs, searchTaskProperties); - responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs); + responseData = await asanaApiRequest.call( + this, + 'GET', + `/workspaces/${workspaceId}/tasks/search`, + body, + qs, + ); responseData = responseData.data; } @@ -2139,15 +2144,17 @@ export class Asana implements INodeType { body.html_text = this.getNodeParameter('text', i) as string; } - requestMethod = 'POST'; - - endpoint = `/tasks/${taskId}/stories`; - const additionalFields = this.getNodeParameter('additionalFields', i); Object.assign(body, additionalFields); - responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs); + responseData = await asanaApiRequest.call( + this, + 'POST', + `/tasks/${taskId}/stories`, + body, + qs, + ); responseData = responseData.data; } @@ -2159,11 +2166,13 @@ export class Asana implements INodeType { const commentId = this.getNodeParameter('id', i) as string; - requestMethod = 'DELETE'; - - endpoint = `/stories/${commentId}`; - - responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs); + responseData = await asanaApiRequest.call( + this, + 'DELETE', + `/stories/${commentId}`, + body, + qs, + ); responseData = { success: true }; } @@ -2176,13 +2185,15 @@ export class Asana implements INodeType { const taskId = this.getNodeParameter('id', i) as string; - requestMethod = 'POST'; - - endpoint = `/tasks/${taskId}/addTag`; - body.tag = this.getNodeParameter('tag', i) as string; - responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs); + responseData = await asanaApiRequest.call( + this, + 'POST', + `/tasks/${taskId}/addTag`, + body, + qs, + ); responseData = { success: true }; } @@ -2194,13 +2205,15 @@ export class Asana implements INodeType { const taskId = this.getNodeParameter('id', i) as string; - requestMethod = 'POST'; - - endpoint = `/tasks/${taskId}/removeTag`; - body.tag = this.getNodeParameter('tag', i) as string; - responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs); + responseData = await asanaApiRequest.call( + this, + 'POST', + `/tasks/${taskId}/removeTag`, + body, + qs, + ); responseData = { success: true }; } @@ -2215,15 +2228,17 @@ export class Asana implements INodeType { const additionalFields = this.getNodeParameter('additionalFields', i); - requestMethod = 'POST'; - - endpoint = `/tasks/${taskId}/addProject`; - body.project = this.getNodeParameter('project', i) as string; Object.assign(body, additionalFields); - responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs); + responseData = await asanaApiRequest.call( + this, + 'POST', + `/tasks/${taskId}/addProject`, + body, + qs, + ); responseData = { success: true }; } @@ -2235,13 +2250,15 @@ export class Asana implements INodeType { const taskId = this.getNodeParameter('id', i) as string; - requestMethod = 'POST'; - - endpoint = `/tasks/${taskId}/removeProject`; - body.project = this.getNodeParameter('project', i) as string; - responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs); + responseData = await asanaApiRequest.call( + this, + 'POST', + `/tasks/${taskId}/removeProject`, + body, + qs, + ); responseData = { success: true }; } @@ -2254,10 +2271,7 @@ export class Asana implements INodeType { const userId = this.getNodeParameter('userId', i) as string; - requestMethod = 'GET'; - endpoint = `/users/${userId}`; - - responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs); + responseData = await asanaApiRequest.call(this, 'GET', `/users/${userId}`, body, qs); responseData = responseData.data; } else if (operation === 'getAll') { // ---------------------------------- @@ -2266,10 +2280,13 @@ export class Asana implements INodeType { const workspaceId = this.getNodeParameter('workspace', i) as string; - requestMethod = 'GET'; - endpoint = `/workspaces/${workspaceId}/users`; - - responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs); + responseData = await asanaApiRequest.call( + this, + 'GET', + `/workspaces/${workspaceId}/users`, + body, + qs, + ); responseData = responseData.data; } } @@ -2281,10 +2298,6 @@ export class Asana implements INodeType { const additionalFields = this.getNodeParameter('additionalFields', i); const teamId = this.getNodeParameter('team', i); - // request parameters - requestMethod = 'POST'; - endpoint = `/teams/${teamId}/projects`; - // required parameters body.name = this.getNodeParameter('name', i); body.workspace = this.getNodeParameter('workspace', i); @@ -2298,7 +2311,13 @@ export class Asana implements INodeType { if (additionalFields.notes) { qs.notes = additionalFields.notes; } - responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs); + responseData = await asanaApiRequest.call( + this, + 'POST', + `/teams/${teamId}/projects`, + body, + qs, + ); responseData = responseData.data; } @@ -2308,11 +2327,7 @@ export class Asana implements INodeType { // ---------------------------------- const projectId = this.getNodeParameter('id', i) as string; - requestMethod = 'DELETE'; - - endpoint = `/projects/${projectId}`; - - await asanaApiRequest.call(this, requestMethod, endpoint, body, qs); + await asanaApiRequest.call(this, 'DELETE', `/projects/${projectId}`, body, qs); responseData = { success: true }; } @@ -2323,11 +2338,13 @@ export class Asana implements INodeType { // ---------------------------------- const projectId = this.getNodeParameter('id', i) as string; - requestMethod = 'GET'; - - endpoint = `/projects/${projectId}`; - - responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs); + responseData = await asanaApiRequest.call( + this, + 'GET', + `/projects/${projectId}`, + body, + qs, + ); responseData = responseData.data; } @@ -2340,9 +2357,6 @@ export class Asana implements INodeType { const additionalFields = this.getNodeParameter('additionalFields', i); const returnAll = this.getNodeParameter('returnAll', i); - requestMethod = 'GET'; - endpoint = '/projects'; - if (additionalFields.team) { qs.team = additionalFields.team; } else { @@ -2354,17 +2368,11 @@ export class Asana implements INodeType { } if (returnAll) { - responseData = await asanaApiRequestAllItems.call( - this, - requestMethod, - endpoint, - body, - qs, - ); + responseData = await asanaApiRequestAllItems.call(this, 'GET', '/projects', body, qs); } else { qs.limit = this.getNodeParameter('limit', i); - responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs); + responseData = await asanaApiRequest.call(this, 'GET', '/projects', body, qs); responseData = responseData.data; } @@ -2377,10 +2385,6 @@ export class Asana implements INodeType { const projectId = this.getNodeParameter('id', i) as string; const updateFields = this.getNodeParameter('updateFields', i); - // request parameters - requestMethod = 'PUT'; - endpoint = `/projects/${projectId}`; - // optional parameters if (updateFields.color) { qs.color = updateFields.color; @@ -2401,7 +2405,13 @@ export class Asana implements INodeType { body.team = updateFields.team; } - responseData = await asanaApiRequest.call(this, requestMethod, endpoint, body, qs); + responseData = await asanaApiRequest.call( + this, + 'PUT', + `/projects/${projectId}`, + body, + qs, + ); responseData = responseData.data; } } diff --git a/packages/nodes-base/nodes/Asana/AsanaTrigger.node.ts b/packages/nodes-base/nodes/Asana/AsanaTrigger.node.ts index 1da6807a411da..5af631543e8f0 100644 --- a/packages/nodes-base/nodes/Asana/AsanaTrigger.node.ts +++ b/packages/nodes-base/nodes/Asana/AsanaTrigger.node.ts @@ -123,9 +123,7 @@ export class AsanaTrigger implements INodeType { const workspace = this.getNodeParameter('workspace') as string; - const endpoint = '/webhooks'; - - const { data } = await asanaApiRequest.call(this, 'GET', endpoint, {}, { workspace }); + const { data } = await asanaApiRequest.call(this, 'GET', '/webhooks', {}, { workspace }); for (const webhook of data) { if (webhook.resource.gid === resource && webhook.target === webhookUrl) { @@ -151,14 +149,12 @@ export class AsanaTrigger implements INodeType { const resource = this.getNodeParameter('resource') as string; - const endpoint = '/webhooks'; - const body = { resource, target: webhookUrl, }; - const responseData = await asanaApiRequest.call(this, 'POST', endpoint, body); + const responseData = await asanaApiRequest.call(this, 'POST', '/webhooks', body); if (responseData.data === undefined || responseData.data.gid === undefined) { // Required data is missing so was not successful @@ -173,11 +169,10 @@ export class AsanaTrigger implements INodeType { const webhookData = this.getWorkflowStaticData('node'); if (webhookData.webhookId !== undefined) { - const endpoint = `/webhooks/${webhookData.webhookId}`; const body = {}; try { - await asanaApiRequest.call(this, 'DELETE', endpoint, body); + await asanaApiRequest.call(this, 'DELETE', `/webhooks/${webhookData.webhookId}`, body); } catch (error) { return false; } diff --git a/packages/nodes-base/nodes/Asana/GenericFunctions.ts b/packages/nodes-base/nodes/Asana/GenericFunctions.ts index ac89b8abce296..2b7c1b9a486bc 100644 --- a/packages/nodes-base/nodes/Asana/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Asana/GenericFunctions.ts @@ -17,7 +17,7 @@ import get from 'lodash/get'; export async function asanaApiRequest( this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions, method: IHttpRequestMethods, - endpoint: string, + endpoint: `/${string}`, body: object, query?: IDataObject, uri?: string | undefined, @@ -33,6 +33,10 @@ export async function asanaApiRequest( json: true, }; + if (options.body === null) { + delete options.body; + } + const credentialType = authenticationMethod === 'accessToken' ? 'asanaApi' : 'asanaOAuth2Api'; return await this.helpers.requestWithAuthentication.call(this, credentialType, options); } @@ -40,8 +44,7 @@ export async function asanaApiRequest( export async function asanaApiRequestAllItems( this: IExecuteFunctions | ILoadOptionsFunctions, method: IHttpRequestMethods, - endpoint: string, - + endpoint: `/${string}`, body: any = {}, query: IDataObject = {}, ): Promise {