fixes

This commit is contained in:
Ricardo Espinoza 2020-02-02 10:01:56 -05:00
parent 7d5bbadc9b
commit 960d439cbc
6 changed files with 264 additions and 74 deletions

View file

@ -5,77 +5,23 @@ import {
export class JiraSoftwareCloudApi implements ICredentialType { export class JiraSoftwareCloudApi implements ICredentialType {
name = 'jiraSoftwareCloudApi'; name = 'jiraSoftwareCloudApi';
displayName = 'Jira SW API'; displayName = 'Jira SW Cloud API';
properties = [ properties = [
{
displayName: 'Jira Version',
name: 'jiraVersion',
type: 'options' as NodePropertyTypes,
options: [
{
name: 'Cloud',
value: 'cloud',
},
{
name: 'Server (Self Hosted)',
value: 'server',
},
],
default: 'cloud',
},
{ {
displayName: 'Email', displayName: 'Email',
name: 'email', name: 'email',
displayOptions: {
show: {
jiraVersion: [
'cloud',
],
},
},
type: 'string' as NodePropertyTypes, type: 'string' as NodePropertyTypes,
default: '', default: '',
}, },
{ {
displayName: 'API Token', displayName: 'API Token',
name: 'apiToken', name: 'apiToken',
displayOptions: {
show: {
jiraVersion: [
'cloud',
],
},
},
type: 'string' as NodePropertyTypes,
default: '',
},
{
displayName: 'Password',
name: 'password',
displayOptions: {
show: {
jiraVersion: [
'server',
],
},
},
typeOptions: {
password: true,
},
type: 'string' as NodePropertyTypes, type: 'string' as NodePropertyTypes,
default: '', default: '',
}, },
{ {
displayName: 'Domain', displayName: 'Domain',
name: 'domain', name: 'domain',
displayOptions: {
show: {
jiraVersion: [
'cloud',
'server',
],
},
},
type: 'string' as NodePropertyTypes, type: 'string' as NodePropertyTypes,
default: '', default: '',
}, },

View file

@ -0,0 +1,32 @@
import {
ICredentialType,
NodePropertyTypes,
} from 'n8n-workflow';
export class JiraSoftwareServerApi implements ICredentialType {
name = 'jiraSoftwareServerApi';
displayName = 'Jira SW Server API';
properties = [
{
displayName: 'Email',
name: 'email',
type: 'string' as NodePropertyTypes,
default: '',
},
{
displayName: 'Password',
name: 'password',
typeOptions: {
password: true,
},
type: 'string' as NodePropertyTypes,
default: '',
},
{
displayName: 'Domain',
name: 'domain',
type: 'string' as NodePropertyTypes,
default: '',
},
];
}

View file

@ -13,18 +13,27 @@ import {
} from 'n8n-workflow'; } from 'n8n-workflow';
export async function jiraSoftwareCloudApiRequest(this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, endpoint: string, method: string, body: any = {}, query?: IDataObject, uri?: string): Promise<any> { // tslint:disable-line:no-any export async function jiraSoftwareCloudApiRequest(this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, endpoint: string, method: string, body: any = {}, query?: IDataObject, uri?: string): Promise<any> { // tslint:disable-line:no-any
const credentials = this.getCredentials('jiraSoftwareCloudApi'); let data; let domain;
if (credentials === undefined) { const jiraCloudCredentials = this.getCredentials('jiraSoftwareCloudApi');
const jiraServerCredentials = this.getCredentials('jiraSoftwareServerApi');
if (jiraCloudCredentials === undefined
&& jiraServerCredentials === undefined) {
throw new Error('No credentials got returned!'); throw new Error('No credentials got returned!');
} }
const data = Buffer.from(`${credentials!.email}:${(credentials.jiraVersion === 'server') ? credentials.password : credentials.apiToken }`).toString(BINARY_ENCODING); if (jiraCloudCredentials !== undefined) {
domain = jiraCloudCredentials!.domain;
data = Buffer.from(`${jiraCloudCredentials!.email}:${jiraCloudCredentials!.apiToken}`).toString(BINARY_ENCODING);
} else {
domain = jiraServerCredentials!.domain;
data = Buffer.from(`${jiraServerCredentials!.email}:${jiraServerCredentials!.password}`).toString(BINARY_ENCODING);
}
const headerWithAuthentication = Object.assign({}, const headerWithAuthentication = Object.assign({},
{ Authorization: `Basic ${data}`, Accept: 'application/json', 'Content-Type': 'application/json' }); { Authorization: `Basic ${data}`, Accept: 'application/json', 'Content-Type': 'application/json' });
const options: OptionsWithUri = { const options: OptionsWithUri = {
headers: headerWithAuthentication, headers: headerWithAuthentication,
method, method,
qs: query, qs: query,
uri: uri || `${credentials.domain}/rest/api/2${endpoint}`, uri: uri || `${domain}/rest/api/2${endpoint}`,
body, body,
json: true json: true
}; };
@ -32,13 +41,11 @@ export async function jiraSoftwareCloudApiRequest(this: IHookFunctions | IExecut
try { try {
return await this.helpers.request!(options); return await this.helpers.request!(options);
} catch (error) { } catch (error) {
const errorMessage = let errorMessage = error;
error.response.body.message || error.response.body.Message; if (error.error && error.error.errorMessages) {
errorMessage = error.error.errorMessages;
if (errorMessage !== undefined) {
throw errorMessage;
} }
throw error.response.body; throw new Error(errorMessage);
} }
} }
@ -48,18 +55,18 @@ export async function jiraSoftwareCloudApiRequestAllItems(this: IHookFunctions |
let responseData; let responseData;
query.startAt = 0;
body.startAt = 0;
query.maxResults = 100; query.maxResults = 100;
body.maxResults = 100;
let uri: string | undefined;
do { do {
responseData = await jiraSoftwareCloudApiRequest.call(this, endpoint, method, body, query, uri); responseData = await jiraSoftwareCloudApiRequest.call(this, endpoint, method, body, query);
uri = responseData.nextPage;
returnData.push.apply(returnData, responseData[propertyName]); returnData.push.apply(returnData, responseData[propertyName]);
query.startAt = responseData.startAt + responseData.maxResults;
body.startAt = responseData.startAt + responseData.maxResults;
} while ( } while (
responseData.isLast !== false && (responseData.startAt + responseData.maxResults < responseData.total)
responseData.nextPage !== undefined &&
responseData.nextPage !== null
); );
return returnData; return returnData;

View file

@ -28,6 +28,11 @@ export const issueOperations = [
value: 'get', value: 'get',
description: 'Get an issue', description: 'Get an issue',
}, },
{
name: 'Get All',
value: 'getAll',
description: 'Get all issues',
},
{ {
name: 'Changelog', name: 'Changelog',
value: 'changelog', value: 'changelog',
@ -452,6 +457,148 @@ export const issueFields = [
}, },
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/* issue:getAll */
/* -------------------------------------------------------------------------- */
{
displayName: 'Return All',
name: 'returnAll',
type: 'boolean',
displayOptions: {
show: {
resource: [
'issue',
],
operation: [
'getAll',
],
},
},
default: false,
description: 'If all results should be returned or only up to a given limit.',
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
displayOptions: {
show: {
resource: [
'issue',
],
operation: [
'getAll',
],
returnAll: [
false,
],
},
},
typeOptions: {
minValue: 1,
maxValue: 100,
},
default: 50,
description: 'How many results to return.',
},
{
displayName: 'Options',
name: 'options',
type: 'collection',
placeholder: 'Add Option',
displayOptions: {
show: {
operation: [
'getAll',
],
resource: [
'issue',
],
},
},
default: {},
options: [
{
displayName: ' JQL',
name: 'jql',
type: 'string',
default: '',
typeOptions: {
alwaysOpenEditWindow: true,
},
description: 'A JQL expression.',
},
{
displayName: 'Fields',
name: 'fields',
type: 'string',
default: '*navigable',
description: `A list of fields to return for each issue, use it to retrieve a subset of fields. This parameter accepts a comma-separated list. Expand options include:<br/>
*all Returns all fields.<br/>
*navigable Returns navigable fields.<br/>
Any issue field, prefixed with a minus to exclude.<br/>`,
},
{
displayName: 'Expand',
name: 'expand',
type: 'options',
default: '',
options: [
{
name: 'Rendered Fields',
valie: 'renderedFields',
description: ' Returns field values rendered in HTML format.',
},
{
name: 'Names',
valie: 'names',
description: 'Returns the display name of each field',
},
{
name: 'Schema',
valie: 'schema',
description: 'Returns the schema describing a field type.',
},
{
name: 'Transitions',
valie: 'transitions',
description: ' Returns all possible transitions for the issue.',
},
{
name: 'Operations',
valie: 'operations',
description: 'Returns all possible operations for the issue.',
},
{
name: 'Editmeta',
valie: 'editmeta',
description: 'Returns information about how each field can be edited',
},
{
name: 'Changelog',
valie: 'changelog',
description: 'Returns a list of recent updates to an issue, sorted by date, starting from the most recent.',
},
{
name: 'Versioned Representations',
valie: 'versionedRepresentations',
description: `JSON array containing each version of a field's value`,
},
],
description: `Use expand to include additional information about issues in the response`,
},
{
displayName: 'Fields By Key',
name: 'fieldsByKey',
type: 'boolean',
required: false,
default: false,
description: `Indicates whether fields in fields are referenced by keys rather than IDs.<br/>
This parameter is useful where fields have been added by a connect app and a field's key<br/>
may differ from its ID.`,
},
],
},
/* -------------------------------------------------------------------------- */
/* issue:changelog */ /* issue:changelog */
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
{ {

View file

@ -45,9 +45,43 @@ export class JiraSoftwareCloud implements INodeType {
{ {
name: 'jiraSoftwareCloudApi', name: 'jiraSoftwareCloudApi',
required: true, required: true,
displayOptions: {
show: {
jiraVersion: [
'cloud',
],
},
},
},
{
name: 'jiraSoftwareServerApi',
required: true,
displayOptions: {
show: {
jiraVersion: [
'server',
],
},
},
}, },
], ],
properties: [ properties: [
{
displayName: 'Jira Version',
name: 'jiraVersion',
type: 'options',
options: [
{
name: 'Cloud',
value: 'cloud',
},
{
name: 'Server (Self Hosted)',
value: 'server',
},
],
default: 'cloud',
},
{ {
displayName: 'Resource', displayName: 'Resource',
name: 'resource', name: 'resource',
@ -73,10 +107,10 @@ export class JiraSoftwareCloud implements INodeType {
// select them easily // select them easily
async getProjects(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> { async getProjects(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
const returnData: INodePropertyOptions[] = []; const returnData: INodePropertyOptions[] = [];
const credentials = this.getCredentials('jiraSoftwareCloudApi'); const jiraCloudCredentials = this.getCredentials('jiraSoftwareCloudApi');
let projects; let projects;
let endpoint = '/project/search'; let endpoint = '/project/search';
if (credentials!.jiraVersion === 'server') { if (jiraCloudCredentials === undefined) {
endpoint = '/project'; endpoint = '/project';
} }
try { try {
@ -360,6 +394,29 @@ export class JiraSoftwareCloud implements INodeType {
throw new Error(`Jira Error: ${JSON.stringify(err)}`); throw new Error(`Jira Error: ${JSON.stringify(err)}`);
} }
} }
//https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-search-post
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
const options = this.getNodeParameter('options', i) as IDataObject;
const body: IDataObject = {};
if (options.fields) {
body.fields = (options.fields as string).split(',') as string[];
}
if (options.jql) {
body.jql = options.jql as string;
}
if (options.expand) {
body.expand = options.expand as string;
}
if (returnAll) {
responseData = await jiraSoftwareCloudApiRequestAllItems.call(this, 'issues', `/search`, 'POST', body);
} else {
const limit = this.getNodeParameter('limit', i) as number;
body.maxResults = limit;
responseData = await jiraSoftwareCloudApiRequest.call(this, `/search`, 'POST', body);
responseData = responseData.issues;
}
}
//https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issue-issueIdOrKey-changelog-get //https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issue-issueIdOrKey-changelog-get
if (operation === 'changelog') { if (operation === 'changelog') {
const issueKey = this.getNodeParameter('issueKey', i) as string; const issueKey = this.getNodeParameter('issueKey', i) as string;

View file

@ -58,6 +58,7 @@
"dist/credentials/Imap.credentials.js", "dist/credentials/Imap.credentials.js",
"dist/credentials/IntercomApi.credentials.js", "dist/credentials/IntercomApi.credentials.js",
"dist/credentials/JiraSoftwareCloudApi.credentials.js", "dist/credentials/JiraSoftwareCloudApi.credentials.js",
"dist/credentials/JiraSoftwareServerApi.credentials.js",
"dist/credentials/JotFormApi.credentials.js", "dist/credentials/JotFormApi.credentials.js",
"dist/credentials/LinkFishApi.credentials.js", "dist/credentials/LinkFishApi.credentials.js",
"dist/credentials/MailchimpApi.credentials.js", "dist/credentials/MailchimpApi.credentials.js",