2020-07-25 01:22:02 -07:00
import {
IHookFunctions ,
IWebhookFunctions ,
} from 'n8n-core' ;
import {
IDataObject ,
INodeType ,
2020-10-01 05:01:39 -07:00
INodeTypeDescription ,
2020-07-25 01:22:02 -07:00
IWebhookResponseData ,
} from 'n8n-workflow' ;
import {
2020-10-01 05:01:39 -07:00
allEvents ,
2020-07-25 01:22:02 -07:00
eventExists ,
getId ,
2020-10-01 05:01:39 -07:00
jiraSoftwareCloudApiRequest ,
2020-07-25 01:22:02 -07:00
} from './GenericFunctions' ;
import * as queryString from 'querystring' ;
export class JiraTrigger implements INodeType {
description : INodeTypeDescription = {
displayName : 'Jira Trigger' ,
name : 'jiraTrigger' ,
icon : 'file:jira.png' ,
group : [ 'trigger' ] ,
version : 1 ,
description : 'Starts the workflow when Jira events occurs.' ,
defaults : {
name : 'Jira Trigger' ,
color : '#4185f7' ,
} ,
inputs : [ ] ,
outputs : [ 'main' ] ,
credentials : [
{
name : 'jiraSoftwareCloudApi' ,
required : true ,
displayOptions : {
show : {
jiraVersion : [
'cloud' ,
] ,
} ,
} ,
} ,
{
name : 'jiraSoftwareServerApi' ,
required : true ,
displayOptions : {
show : {
jiraVersion : [
'server' ,
] ,
} ,
} ,
} ,
] ,
webhooks : [
{
name : 'default' ,
httpMethod : 'POST' ,
responseMode : 'onReceived' ,
path : 'webhook' ,
} ,
] ,
properties : [
{
displayName : 'Jira Version' ,
name : 'jiraVersion' ,
type : 'options' ,
options : [
{
name : 'Cloud' ,
value : 'cloud' ,
} ,
{
name : 'Server (Self Hosted)' ,
value : 'server' ,
} ,
] ,
default : 'cloud' ,
} ,
{
displayName : 'Events' ,
name : 'events' ,
type : 'multiOptions' ,
options : [
{
name : '*' ,
value : '*' ,
} ,
{
2020-07-25 01:22:24 -07:00
name : 'Board Configuration Changed' ,
value : 'board_configuration_changed' ,
2020-07-25 01:22:02 -07:00
} ,
{
2020-07-25 01:22:24 -07:00
name : 'Board Created' ,
value : 'board_created' ,
2020-07-25 01:22:02 -07:00
} ,
{
name : 'Board Deleted' ,
value : 'board_deleted' ,
} ,
{
2020-07-25 01:22:24 -07:00
name : 'Board Updated' ,
value : 'board_updated' ,
2020-07-25 01:22:02 -07:00
} ,
{
name : 'Comment Created' ,
value : 'comment_created' ,
} ,
{
name : 'Comment Deleted' ,
value : 'comment_deleted' ,
} ,
{
2020-07-25 01:22:24 -07:00
name : 'Comment Updated' ,
value : 'comment_updated' ,
2020-07-25 01:22:02 -07:00
} ,
{
2020-07-25 01:22:24 -07:00
name : 'Issue Created' ,
value : 'jira:issue_created' ,
2020-07-25 01:22:02 -07:00
} ,
{
name : 'Issue Deleted' ,
value : 'jira:issue_deleted' ,
} ,
{
2020-07-25 01:22:24 -07:00
name : 'Issue Link Created' ,
value : 'issuelink_created' ,
2020-07-25 01:22:02 -07:00
} ,
{
2020-07-25 01:22:24 -07:00
name : 'Issue Link Deleted' ,
value : 'issuelink_deleted' ,
2020-07-25 01:22:02 -07:00
} ,
{
2020-07-25 01:22:24 -07:00
name : 'Issue Updated' ,
value : 'jira:issue_updated' ,
2020-07-25 01:22:02 -07:00
} ,
{
name : 'Option Attachments Changed' ,
value : 'option_attachments_changed' ,
} ,
{
name : 'Option Issue Links Changed' ,
value : 'option_issuelinks_changed' ,
} ,
2020-07-25 01:22:24 -07:00
{
name : 'Option Subtasks Changed' ,
value : 'option_subtasks_changed' ,
} ,
2020-07-25 01:22:02 -07:00
{
name : 'Option Timetracking Changed' ,
value : 'option_timetracking_changed' ,
} ,
2020-07-25 01:22:24 -07:00
{
name : 'Option Unassigned Issues Changed' ,
value : 'option_unassigned_issues_changed' ,
} ,
{
name : 'Option Voting Changed' ,
value : 'option_voting_changed' ,
} ,
{
name : 'Option Watching Changed' ,
value : 'option_watching_changed' ,
} ,
2020-07-25 01:22:02 -07:00
{
name : 'Project Created' ,
value : 'project_created' ,
} ,
2020-07-25 01:22:24 -07:00
{
name : 'Project Deleted' ,
value : 'project_deleted' ,
} ,
2020-07-25 01:22:02 -07:00
{
name : 'Project Updated' ,
value : 'project_updated' ,
} ,
{
2020-07-25 01:22:24 -07:00
name : 'Sprint Closed' ,
value : 'sprint_closed' ,
2020-07-25 01:22:02 -07:00
} ,
{
name : 'Sprint Created' ,
value : 'sprint_created' ,
} ,
{
name : 'Sprint Deleted' ,
value : 'sprint_deleted' ,
} ,
{
name : 'Sprint Started' ,
value : 'sprint_started' ,
} ,
{
2020-07-25 01:22:24 -07:00
name : 'Sprint Updated' ,
value : 'sprint_updated' ,
2020-07-25 01:22:02 -07:00
} ,
{
name : 'User Created' ,
value : 'user_created' ,
} ,
{
name : 'User Deleted' ,
value : 'user_deleted' ,
} ,
{
2020-07-25 01:22:24 -07:00
name : 'User Updated' ,
value : 'user_updated' ,
2020-07-25 01:22:02 -07:00
} ,
{
name : 'Version Created' ,
value : 'jira:version_created' ,
} ,
{
2020-07-25 01:22:24 -07:00
name : 'Version Deleted' ,
value : 'jira:version_deleted' ,
2020-07-25 01:22:02 -07:00
} ,
{
2020-07-25 01:22:24 -07:00
name : 'Version Moved' ,
value : 'jira:version_moved' ,
2020-07-25 01:22:02 -07:00
} ,
{
2020-07-25 01:22:24 -07:00
name : 'Version Released' ,
value : 'jira:version_released' ,
2020-07-25 01:22:02 -07:00
} ,
{
2020-07-25 01:22:24 -07:00
name : 'Version Unreleased' ,
value : 'jira:version_unreleased' ,
2020-07-25 01:22:02 -07:00
} ,
{
2020-07-25 01:22:24 -07:00
name : 'Version Updated' ,
value : 'jira:version_updated' ,
2020-07-25 01:22:02 -07:00
} ,
{
name : 'Worklog Created' ,
value : 'worklog_created' ,
} ,
{
name : 'Worklog Deleted' ,
value : 'worklog_deleted' ,
} ,
2020-07-25 01:22:24 -07:00
{
name : 'Worklog Updated' ,
value : 'worklog_updated' ,
} ,
2020-07-25 01:22:02 -07:00
] ,
required : true ,
default : [ ] ,
description : 'The events to listen to.' ,
} ,
{
displayName : 'Additional Fields' ,
name : 'additionalFields' ,
type : 'collection' ,
placeholder : 'Add Field' ,
default : { } ,
options : [
{
displayName : 'Exclude Body' ,
name : 'excludeBody' ,
type : 'boolean' ,
default : false ,
description : 'Request with empty body will be sent to the URL. Leave unchecked if you want to receive JSON.' ,
} ,
{
displayName : 'Filter' ,
name : 'filter' ,
type : 'string' ,
typeOptions : {
alwaysOpenEditWindow : true ,
} ,
default : '' ,
placeholder : 'Project = JRA AND resolution = Fixed' ,
description : 'You can specify a JQL query to send only events triggered by matching issues. The JQL filter only applies to events under the Issue and Comment columns.' ,
} ,
{
displayName : 'Include Fields' ,
name : 'includeFields' ,
type : 'multiOptions' ,
options : [
{
name : 'Attachment ID' ,
value : 'attachment.id'
} ,
{
name : 'Board ID' ,
value : 'board.id'
} ,
{
name : 'Comment ID' ,
value : 'comment.id'
} ,
{
name : 'Issue ID' ,
value : 'issue.id'
} ,
{
name : 'Merge Version ID' ,
value : 'mergeVersion.id'
} ,
{
name : 'Modified User Account ID' ,
value : 'modifiedUser.accountId'
} ,
{
name : 'Modified User Key' ,
value : 'modifiedUser.key'
} ,
{
name : 'Modified User Name' ,
value : 'modifiedUser.name'
} ,
{
name : 'Project ID' ,
value : 'project.id'
} ,
{
name : 'Project Key' ,
value : 'project.key'
} ,
{
name : 'Propery Key' ,
value : 'property.key'
} ,
{
name : 'Sprint ID' ,
value : 'sprint.id'
} ,
{
name : 'Version ID' ,
value : 'version.id'
} ,
{
name : 'Worklog ID' ,
value : 'worklog.id'
} ,
] ,
default : [ ] ,
} ,
] ,
} ,
] ,
} ;
// @ts-ignore (because of request)
webhookMethods = {
default : {
async checkExists ( this : IHookFunctions ) : Promise < boolean > {
const webhookUrl = this . getNodeWebhookUrl ( 'default' ) as string ;
const webhookData = this . getWorkflowStaticData ( 'node' ) ;
const events = this . getNodeParameter ( 'events' ) as string [ ] ;
const endpoint = ` /webhooks/1.0/webhook ` ;
const webhooks = await jiraSoftwareCloudApiRequest . call ( this , endpoint , 'GET' , { } ) ;
for ( const webhook of webhooks ) {
if ( webhook . url === webhookUrl && eventExists ( events , webhook . events ) ) {
webhookData . webhookId = getId ( webhook . self ) ;
return true ;
}
}
return false ;
} ,
async create ( this : IHookFunctions ) : Promise < boolean > {
const webhookUrl = this . getNodeWebhookUrl ( 'default' ) as string ;
let events = this . getNodeParameter ( 'events' , [ ] ) as string [ ] ;
const additionalFields = this . getNodeParameter ( 'additionalFields' ) as IDataObject ;
const endpoint = ` /webhooks/1.0/webhook ` ;
const webhookData = this . getWorkflowStaticData ( 'node' ) ;
if ( events . includes ( '*' ) ) {
events = allEvents ;
}
const body = {
name : ` n8n-webhook: ${ webhookUrl } ` ,
url : webhookUrl ,
events ,
filters : {
} ,
excludeBody : false ,
} ;
if ( additionalFields . filter ) {
body . filters = {
'issue-related-events-section' : additionalFields . filter ,
} ;
}
if ( additionalFields . excludeBody ) {
body . excludeBody = additionalFields . excludeBody as boolean ;
}
if ( additionalFields . includeFields ) {
2020-08-12 03:19:41 -07:00
// tslint:disable-next-line: no-any
const parameters : any = { } ;
2020-07-25 01:22:02 -07:00
for ( const field of additionalFields . includeFields as string [ ] ) {
parameters [ field ] = '${' + field + '}' ;
}
body . url = ` ${ body . url } ? ${ queryString . unescape ( queryString . stringify ( parameters ) ) } ` ;
}
const responseData = await jiraSoftwareCloudApiRequest . call ( this , endpoint , 'POST' , body ) ;
webhookData . webhookId = getId ( responseData . self ) ;
return true ;
} ,
async delete ( this : IHookFunctions ) : Promise < boolean > {
const webhookData = this . getWorkflowStaticData ( 'node' ) ;
if ( webhookData . webhookId !== undefined ) {
const endpoint = ` /webhooks/1.0/webhook/ ${ webhookData . webhookId } ` ;
const body = { } ;
try {
await jiraSoftwareCloudApiRequest . call ( this , endpoint , 'DELETE' , body ) ;
} catch ( e ) {
return false ;
}
// Remove from the static workflow data so that it is clear
// that no webhooks are registred anymore
delete webhookData . webhookId ;
}
return true ;
} ,
} ,
} ;
async webhook ( this : IWebhookFunctions ) : Promise < IWebhookResponseData > {
const bodyData = this . getBodyData ( ) ;
const queryData = this . getQueryData ( ) ;
Object . assign ( bodyData , queryData ) ;
return {
workflowData : [
this . helpers . returnJsonArray ( bodyData )
] ,
} ;
}
}