From 9fe1ca96966fe29ebd59db6088465acc416a44c0 Mon Sep 17 00:00:00 2001 From: zou wendi <542095059@qq.com> Date: Thu, 30 Apr 2020 17:14:43 +0800 Subject: [PATCH 1/4] fix jiraSoftwareCloud fields.assignee --- packages/nodes-base/nodes/Jira/JiraSoftwareCloud.node.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nodes-base/nodes/Jira/JiraSoftwareCloud.node.ts b/packages/nodes-base/nodes/Jira/JiraSoftwareCloud.node.ts index 7335d24b6b..d2540c6bec 100644 --- a/packages/nodes-base/nodes/Jira/JiraSoftwareCloud.node.ts +++ b/packages/nodes-base/nodes/Jira/JiraSoftwareCloud.node.ts @@ -287,7 +287,7 @@ export class JiraSoftwareCloud implements INodeType { } if (additionalFields.assignee) { fields.assignee = { - id: additionalFields.assignee as string, + name: additionalFields.assignee as string, }; } if (additionalFields.description) { @@ -340,7 +340,7 @@ export class JiraSoftwareCloud implements INodeType { } if (updateFields.assignee) { fields.assignee = { - id: updateFields.assignee as string, + name: updateFields.assignee as string, }; } if (updateFields.description) { From 5228b7effdcfd00bb6e156f2c6c8948a2fb846cd Mon Sep 17 00:00:00 2001 From: zou wendi <542095059@qq.com> Date: Sat, 2 May 2020 11:08:39 +0800 Subject: [PATCH 2/4] add if branch statement for jira fields.assignee --- .../nodes/Jira/JiraSoftwareCloud.node.ts | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/packages/nodes-base/nodes/Jira/JiraSoftwareCloud.node.ts b/packages/nodes-base/nodes/Jira/JiraSoftwareCloud.node.ts index d2540c6bec..323993e7a1 100644 --- a/packages/nodes-base/nodes/Jira/JiraSoftwareCloud.node.ts +++ b/packages/nodes-base/nodes/Jira/JiraSoftwareCloud.node.ts @@ -258,6 +258,8 @@ export class JiraSoftwareCloud implements INodeType { const resource = this.getNodeParameter('resource', 0) as string; const operation = this.getNodeParameter('operation', 0) as string; + const jiraVersion = this.getNodeParameter('jiraVersion', 0) as string; + for (let i = 0; i < length; i++) { if (resource === 'issue') { @@ -286,9 +288,15 @@ export class JiraSoftwareCloud implements INodeType { }; } if (additionalFields.assignee) { - fields.assignee = { - name: additionalFields.assignee as string, - }; + if (jiraVersion === "server") { + fields.assignee = { + name: additionalFields.assignee as string, + }; + } else { + fields.assignee = { + id: additionalFields.assignee as string, + }; + } } if (additionalFields.description) { fields.description = additionalFields.description as string; @@ -339,9 +347,15 @@ export class JiraSoftwareCloud implements INodeType { }; } if (updateFields.assignee) { - fields.assignee = { - name: updateFields.assignee as string, - }; + if (jiraVersion === "server") { + fields.assignee = { + name: updateFields.assignee as string, + }; + } else { + fields.assignee = { + id: updateFields.assignee as string, + }; + } } if (updateFields.description) { fields.description = updateFields.description as string; From e4cc3a4bc9b8d414a75b504c72d70519e7d2fa0a Mon Sep 17 00:00:00 2001 From: zou wendi <542095059@qq.com> Date: Tue, 5 May 2020 12:07:19 +0800 Subject: [PATCH 3/4] features: support jira self-hosted server --- packages/cli/src/Server.ts | 2 +- .../cli/src/WorkflowExecuteAdditionalData.ts | 4 +- packages/core/src/NodeExecuteFunctions.ts | 6 +- .../nodes-base/nodes/Jira/GenericFunctions.ts | 12 +++- .../nodes-base/nodes/Jira/IssueDescription.ts | 50 +++++++++++++++ .../nodes/Jira/JiraSoftwareCloud.node.ts | 64 +++++++++++++++---- packages/workflow/src/Interfaces.ts | 2 +- 7 files changed, 117 insertions(+), 23 deletions(-) diff --git a/packages/cli/src/Server.ts b/packages/cli/src/Server.ts index ad2a3c1de5..d078c8594e 100644 --- a/packages/cli/src/Server.ts +++ b/packages/cli/src/Server.ts @@ -555,7 +555,7 @@ class App { this.app.get('/rest/node-parameter-options', ResponseHelper.send(async (req: express.Request, res: express.Response): Promise => { const nodeType = req.query.nodeType as string; let credentials: INodeCredentials | undefined = undefined; - const currentNodeParameters = req.query.currentNodeParameters as INodeParameters[]; + const currentNodeParameters = JSON.parse('' + req.query.currentNodeParameters) as INodeParameters; if (req.query.credentials !== undefined) { credentials = JSON.parse(req.query.credentials as string); } diff --git a/packages/cli/src/WorkflowExecuteAdditionalData.ts b/packages/cli/src/WorkflowExecuteAdditionalData.ts index 9665080ebd..7ac79310ba 100644 --- a/packages/cli/src/WorkflowExecuteAdditionalData.ts +++ b/packages/cli/src/WorkflowExecuteAdditionalData.ts @@ -387,10 +387,10 @@ export async function executeWorkflow(workflowInfo: IExecuteWorkflowInfo, additi * * @export * @param {IWorkflowCredentials} credentials - * @param {INodeParameters[]} [currentNodeParameters=[]] + * @param {INodeParameters} currentNodeParameters * @returns {Promise} */ -export async function getBase(credentials: IWorkflowCredentials, currentNodeParameters: INodeParameters[] = []): Promise { +export async function getBase(credentials: IWorkflowCredentials, currentNodeParameters?: INodeParameters): Promise { const urlBaseWebhook = WebhookHelpers.getWebhookBaseUrl(); const timezone = config.get('generic.timezone') as string; diff --git a/packages/core/src/NodeExecuteFunctions.ts b/packages/core/src/NodeExecuteFunctions.ts index 5b31f7bed8..640a75ca9a 100644 --- a/packages/core/src/NodeExecuteFunctions.ts +++ b/packages/core/src/NodeExecuteFunctions.ts @@ -152,7 +152,7 @@ export function getCredentials(workflow: Workflow, node: INode, type: string, ad throw new Error(`Node type "${node.type}" does not have any credentials of type "${type}" defined!`); } - if (NodeHelpers.displayParameter(node.parameters, nodeCredentialDescription, node.parameters) === false) { + if (NodeHelpers.displayParameter(additionalData.currentNodeParameters || node.parameters, nodeCredentialDescription, node.parameters) === false) { // Credentials should not be displayed so return undefined even if they would be defined return undefined; } @@ -666,14 +666,14 @@ export function getLoadOptionsFunctions(workflow: Workflow, node: INode, additio return getCredentials(workflow, node, type, additionalData); }, getCurrentNodeParameter: (parameterName: string): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] | object | undefined => { - const nodeParameters = JSON.parse('' + additionalData.currentNodeParameters); + const nodeParameters = additionalData.currentNodeParameters; if (nodeParameters && nodeParameters[parameterName]) { return nodeParameters[parameterName]; } return undefined; }, getCurrentNodeParameters: (): INodeParameters | undefined => { - return JSON.parse('' + additionalData.currentNodeParameters); + return additionalData.currentNodeParameters; }, getNode: () => { return getNode(node); diff --git a/packages/nodes-base/nodes/Jira/GenericFunctions.ts b/packages/nodes-base/nodes/Jira/GenericFunctions.ts index 3f2e6dd82a..e0a7d8871e 100644 --- a/packages/nodes-base/nodes/Jira/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Jira/GenericFunctions.ts @@ -1,4 +1,4 @@ -import { +import { OptionsWithUri, } from 'request'; @@ -9,13 +9,19 @@ import { ILoadOptionsFunctions, } from 'n8n-core'; -import { +import { IDataObject, + ICredentialDataDecryptedObject, } from 'n8n-workflow'; export async function jiraSoftwareCloudApiRequest(this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, endpoint: string, method: string, body: any = {}, query?: IDataObject, uri?: string): Promise { // tslint:disable-line:no-any let data; let domain; - const jiraCloudCredentials = this.getCredentials('jiraSoftwareCloudApi'); + let jiraCloudCredentials: ICredentialDataDecryptedObject | undefined; + try { + jiraCloudCredentials = this.getCredentials('jiraSoftwareCloudApi'); + } catch (error) { + + } const jiraServerCredentials = this.getCredentials('jiraSoftwareServerApi'); if (jiraCloudCredentials === undefined && jiraServerCredentials === undefined) { throw new Error('No credentials got returned!'); diff --git a/packages/nodes-base/nodes/Jira/IssueDescription.ts b/packages/nodes-base/nodes/Jira/IssueDescription.ts index cd788c886e..bdb06179df 100644 --- a/packages/nodes-base/nodes/Jira/IssueDescription.ts +++ b/packages/nodes-base/nodes/Jira/IssueDescription.ts @@ -174,6 +174,31 @@ export const issueFields = [ default: [], required : false, description: 'Labels', + displayOptions: { + show: { + '/jiraVersion': [ + 'cloud', + ], + }, + }, + }, + { + displayName: 'Labels', + name: 'serverLabels', + type: 'string', + default: [], + required : false, + description: 'Labels', + displayOptions: { + show: { + '/jiraVersion': [ + 'server', + ], + }, + }, + typeOptions: { + multipleValues: true, + }, }, { displayName: 'Parent Issue Key', @@ -284,6 +309,31 @@ export const issueFields = [ default: [], required : false, description: 'Labels', + displayOptions: { + show: { + '/jiraVersion': [ + 'cloud', + ], + }, + }, + }, + { + displayName: 'Labels', + name: 'serverLabels', + type: 'string', + default: [], + required : false, + description: 'Labels', + displayOptions: { + show: { + '/jiraVersion': [ + 'server', + ], + }, + }, + typeOptions: { + multipleValues: true, + }, }, { displayName: 'Parent Issue Key', diff --git a/packages/nodes-base/nodes/Jira/JiraSoftwareCloud.node.ts b/packages/nodes-base/nodes/Jira/JiraSoftwareCloud.node.ts index eff27bad6b..5b64de4f95 100644 --- a/packages/nodes-base/nodes/Jira/JiraSoftwareCloud.node.ts +++ b/packages/nodes-base/nodes/Jira/JiraSoftwareCloud.node.ts @@ -140,18 +140,31 @@ export class JiraSoftwareCloud implements INodeType { const returnData: INodePropertyOptions[] = []; const issueTypes = await jiraSoftwareCloudApiRequest.call(this, '/issuetype', 'GET'); - - for (const issueType of issueTypes) { - if (issueType.scope.project.id === projectId) { + const jiraVersion = this.getCurrentNodeParameter('jiraVersion') as string; + if (jiraVersion === "server") { + for (const issueType of issueTypes) { const issueTypeName = issueType.name; const issueTypeId = issueType.id; - + returnData.push({ name: issueTypeName, value: issueTypeId, }); } + } else { + for (const issueType of issueTypes) { + if (issueType.scope.project.id === projectId) { + const issueTypeName = issueType.name; + const issueTypeId = issueType.id; + + returnData.push({ + name: issueTypeName, + value: issueTypeId, + }); + } + } } + return returnData; }, @@ -197,18 +210,37 @@ export class JiraSoftwareCloud implements INodeType { // select them easily async getUsers(this: ILoadOptionsFunctions): Promise { const returnData: INodePropertyOptions[] = []; + const jiraVersion = this.getCurrentNodeParameter("jiraVersion") as string; + if (jiraVersion === "server") { + // the interface call must bring username + const users = await jiraSoftwareCloudApiRequest.call(this, "/user/search", "GET", {}, + { + username: "'", + } + ); + for (const user of users) { + const userName = user.displayName; + const userId = user.name; + + returnData.push({ + name: userName, + value: userId, + }); + } + } else { + const users = await jiraSoftwareCloudApiRequest.call(this, '/users/search', 'GET'); - const users = await jiraSoftwareCloudApiRequest.call(this, '/users/search', 'GET'); + for (const user of users) { + const userName = user.displayName; + const userId = user.accountId; - for (const user of users) { - const userName = user.displayName; - const userId = user.accountId; - - returnData.push({ - name: userName, - value: userId, - }); + returnData.push({ + name: userName, + value: userId, + }); + } } + return returnData; }, @@ -283,6 +315,9 @@ export class JiraSoftwareCloud implements INodeType { if (additionalFields.labels) { fields.labels = additionalFields.labels as string[]; } + if (additionalFields.serverLabels) { + fields.labels = additionalFields.serverLabels as string[]; + } if (additionalFields.priority) { fields.priority = { id: additionalFields.priority as string, @@ -342,6 +377,9 @@ export class JiraSoftwareCloud implements INodeType { if (updateFields.labels) { fields.labels = updateFields.labels as string[]; } + if (updateFields.serverLabels) { + fields.labels = updateFields.serverLabels as string[]; + } if (updateFields.priority) { fields.priority = { id: updateFields.priority as string, diff --git a/packages/workflow/src/Interfaces.ts b/packages/workflow/src/Interfaces.ts index 6a1500e0d7..373a40bcf7 100644 --- a/packages/workflow/src/Interfaces.ts +++ b/packages/workflow/src/Interfaces.ts @@ -680,7 +680,7 @@ export interface IWorkflowExecuteAdditionalData { timezone: string; webhookBaseUrl: string; webhookTestBaseUrl: string; - currentNodeParameters? : INodeParameters[]; + currentNodeParameters? : INodeParameters; } export type WorkflowExecuteMode = 'cli' | 'error' | 'integrated' | 'internal' | 'manual' | 'retry' | 'trigger' | 'webhook'; From 79a09c98a74beeff7aead636f0e3f0e07f78e42c Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Tue, 5 May 2020 22:56:24 +0200 Subject: [PATCH 4/4] :zap: Minor improvements to Jira-Node --- .../nodes-base/nodes/Jira/GenericFunctions.ts | 33 +++++++++++-------- .../nodes/Jira/JiraSoftwareCloud.node.ts | 22 ++++++------- 2 files changed, 30 insertions(+), 25 deletions(-) diff --git a/packages/nodes-base/nodes/Jira/GenericFunctions.ts b/packages/nodes-base/nodes/Jira/GenericFunctions.ts index e0a7d8871e..3ee49ac166 100644 --- a/packages/nodes-base/nodes/Jira/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Jira/GenericFunctions.ts @@ -1,4 +1,4 @@ -import { +import { OptionsWithUri, } from 'request'; @@ -9,30 +9,35 @@ import { ILoadOptionsFunctions, } from 'n8n-core'; -import { +import { IDataObject, ICredentialDataDecryptedObject, } from 'n8n-workflow'; export async function jiraSoftwareCloudApiRequest(this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, endpoint: string, method: string, body: any = {}, query?: IDataObject, uri?: string): Promise { // tslint:disable-line:no-any let data; let domain; - let jiraCloudCredentials: ICredentialDataDecryptedObject | undefined; - try { - jiraCloudCredentials = this.getCredentials('jiraSoftwareCloudApi'); - } catch (error) { - + + const jiraVersion = this.getNodeParameter('jiraVersion', 0) as string; + + let jiraCredentials: ICredentialDataDecryptedObject | undefined; + if (jiraVersion === 'server') { + jiraCredentials = this.getCredentials('jiraSoftwareServerApi'); + } else { + jiraCredentials = this.getCredentials('jiraSoftwareCloudApi'); } - const jiraServerCredentials = this.getCredentials('jiraSoftwareServerApi'); - if (jiraCloudCredentials === undefined && jiraServerCredentials === undefined) { + + if (jiraCredentials === undefined) { throw new Error('No credentials got returned!'); } - if (jiraCloudCredentials !== undefined) { - domain = jiraCloudCredentials!.domain; - data = Buffer.from(`${jiraCloudCredentials!.email}:${jiraCloudCredentials!.apiToken}`).toString('base64'); + + if (jiraVersion === 'server') { + domain = jiraCredentials!.domain; + data = Buffer.from(`${jiraCredentials!.email}:${jiraCredentials!.password}`).toString('base64'); } else { - domain = jiraServerCredentials!.domain; - data = Buffer.from(`${jiraServerCredentials!.email}:${jiraServerCredentials!.password}`).toString('base64'); + domain = jiraCredentials!.domain; + data = Buffer.from(`${jiraCredentials!.email}:${jiraCredentials!.apiToken}`).toString('base64'); } + const options: OptionsWithUri = { headers: { Authorization: `Basic ${data}`, diff --git a/packages/nodes-base/nodes/Jira/JiraSoftwareCloud.node.ts b/packages/nodes-base/nodes/Jira/JiraSoftwareCloud.node.ts index 5b64de4f95..d262ac0da9 100644 --- a/packages/nodes-base/nodes/Jira/JiraSoftwareCloud.node.ts +++ b/packages/nodes-base/nodes/Jira/JiraSoftwareCloud.node.ts @@ -141,11 +141,11 @@ export class JiraSoftwareCloud implements INodeType { const issueTypes = await jiraSoftwareCloudApiRequest.call(this, '/issuetype', 'GET'); const jiraVersion = this.getCurrentNodeParameter('jiraVersion') as string; - if (jiraVersion === "server") { + if (jiraVersion === 'server') { for (const issueType of issueTypes) { const issueTypeName = issueType.name; const issueTypeId = issueType.id; - + returnData.push({ name: issueTypeName, value: issueTypeId, @@ -156,7 +156,7 @@ export class JiraSoftwareCloud implements INodeType { if (issueType.scope.project.id === projectId) { const issueTypeName = issueType.name; const issueTypeId = issueType.id; - + returnData.push({ name: issueTypeName, value: issueTypeId, @@ -164,7 +164,7 @@ export class JiraSoftwareCloud implements INodeType { } } } - + return returnData; }, @@ -210,10 +210,10 @@ export class JiraSoftwareCloud implements INodeType { // select them easily async getUsers(this: ILoadOptionsFunctions): Promise { const returnData: INodePropertyOptions[] = []; - const jiraVersion = this.getCurrentNodeParameter("jiraVersion") as string; - if (jiraVersion === "server") { + const jiraVersion = this.getCurrentNodeParameter('jiraVersion') as string; + if (jiraVersion === 'server') { // the interface call must bring username - const users = await jiraSoftwareCloudApiRequest.call(this, "/user/search", "GET", {}, + const users = await jiraSoftwareCloudApiRequest.call(this, '/user/search', 'GET', {}, { username: "'", } @@ -221,7 +221,7 @@ export class JiraSoftwareCloud implements INodeType { for (const user of users) { const userName = user.displayName; const userId = user.name; - + returnData.push({ name: userName, value: userId, @@ -240,7 +240,7 @@ export class JiraSoftwareCloud implements INodeType { }); } } - + return returnData; }, @@ -324,7 +324,7 @@ export class JiraSoftwareCloud implements INodeType { }; } if (additionalFields.assignee) { - if (jiraVersion === "server") { + if (jiraVersion === 'server') { fields.assignee = { name: additionalFields.assignee as string, }; @@ -386,7 +386,7 @@ export class JiraSoftwareCloud implements INodeType { }; } if (updateFields.assignee) { - if (jiraVersion === "server") { + if (jiraVersion === 'server') { fields.assignee = { name: updateFields.assignee as string, };