mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-20 11:22:15 +00:00
Merge branch 'Master' into 'Pipedrive-OAuth2-support'
This commit is contained in:
@@ -5,10 +5,16 @@ import {
|
||||
|
||||
import {
|
||||
IDataObject,
|
||||
ILoadOptionsFunctions,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
import { OptionsWithUri } from 'request';
|
||||
import {
|
||||
OptionsWithUri,
|
||||
} from 'request';
|
||||
<<<<<<< HEAD
|
||||
|
||||
=======
|
||||
>>>>>>> master
|
||||
|
||||
export interface ICustomInterface {
|
||||
name: string;
|
||||
@@ -32,10 +38,27 @@ export interface ICustomProperties {
|
||||
* @param {object} body
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
<<<<<<< HEAD
|
||||
export async function pipedriveApiRequest(this: IHookFunctions | IExecuteFunctions, method: string, endpoint: string, body: IDataObject, query?: IDataObject, formData?: IDataObject, downloadFile?: boolean): Promise<any> { // tslint:disable-line:no-any
|
||||
const authenticationMethod = this.getNodeParameter('authentication', 0);
|
||||
=======
|
||||
export async function pipedriveApiRequest(this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions, method: string, endpoint: string, body: IDataObject, query?: IDataObject, formData?: IDataObject, downloadFile?: boolean): Promise<any> { // tslint:disable-line:no-any
|
||||
const credentials = this.getCredentials('pipedriveApi');
|
||||
if (credentials === undefined) {
|
||||
throw new Error('No credentials got returned!');
|
||||
}
|
||||
|
||||
if (query === undefined) {
|
||||
query = {};
|
||||
}
|
||||
|
||||
query.api_token = credentials.apiToken;
|
||||
>>>>>>> master
|
||||
|
||||
const options: OptionsWithUri = {
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
},
|
||||
method,
|
||||
qs: query,
|
||||
uri: `https://api.pipedrive.com/v1${endpoint}`,
|
||||
@@ -62,7 +85,8 @@ export async function pipedriveApiRequest(this: IHookFunctions | IExecuteFunctio
|
||||
let responseData;
|
||||
|
||||
try {
|
||||
if (authenticationMethod === 'basicAuth') {
|
||||
<<<<<<< HEAD
|
||||
if (authenticationMethod === 'basicAuth' || authenticationMethod === 'apiToken') {
|
||||
|
||||
const credentials = this.getCredentials('pipedriveApi');
|
||||
if (credentials === undefined) {
|
||||
@@ -76,6 +100,10 @@ export async function pipedriveApiRequest(this: IHookFunctions | IExecuteFunctio
|
||||
} else {
|
||||
responseData = await this.helpers.requestOAuth2!.call(this, 'pipedriveOAuth2Api', options);
|
||||
}
|
||||
=======
|
||||
//@ts-ignore
|
||||
const responseData = await this.helpers.request(options);
|
||||
>>>>>>> master
|
||||
|
||||
if (downloadFile === true) {
|
||||
return {
|
||||
@@ -99,7 +127,7 @@ export async function pipedriveApiRequest(this: IHookFunctions | IExecuteFunctio
|
||||
|
||||
if (error.response && error.response.body && error.response.body.error) {
|
||||
// Try to return the error prettier
|
||||
let errorMessage = `Pipedrive error response [${error.statusCode}]: ${error.response.body.error}`;
|
||||
let errorMessage = `Pipedrive error response [${error.statusCode}]: ${error.response.body.error.message}`;
|
||||
if (error.response.body.error_info) {
|
||||
errorMessage += ` - ${error.response.body.error_info}`;
|
||||
}
|
||||
@@ -128,7 +156,7 @@ export async function pipedriveApiRequestAllItems(this: IHookFunctions | IExecut
|
||||
if (query === undefined) {
|
||||
query = {};
|
||||
}
|
||||
query.limit = 500;
|
||||
query.limit = 100;
|
||||
query.start = 0;
|
||||
|
||||
const returnData: IDataObject[] = [];
|
||||
@@ -137,7 +165,12 @@ export async function pipedriveApiRequestAllItems(this: IHookFunctions | IExecut
|
||||
|
||||
do {
|
||||
responseData = await pipedriveApiRequest.call(this, method, endpoint, body, query);
|
||||
returnData.push.apply(returnData, responseData.data);
|
||||
// the search path returns data diferently
|
||||
if (responseData.data.items) {
|
||||
returnData.push.apply(returnData, responseData.data.items);
|
||||
} else {
|
||||
returnData.push.apply(returnData, responseData.data);
|
||||
}
|
||||
|
||||
query.start = responseData.additionalData.pagination.next_start;
|
||||
} while (
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
import {
|
||||
BINARY_ENCODING,
|
||||
IExecuteFunctions,
|
||||
ILoadOptionsFunctions,
|
||||
} from 'n8n-core';
|
||||
import {
|
||||
IDataObject,
|
||||
INodeTypeDescription,
|
||||
INodeExecutionData,
|
||||
INodeType,
|
||||
INodePropertyOptions,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
import {
|
||||
@@ -23,7 +25,6 @@ interface CustomProperty {
|
||||
value: string;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add the additional fields to the body
|
||||
*
|
||||
@@ -64,7 +65,7 @@ export class Pipedrive implements INodeType {
|
||||
displayOptions: {
|
||||
show: {
|
||||
authentication: [
|
||||
'basicAuth',
|
||||
'apiToken',
|
||||
],
|
||||
},
|
||||
},
|
||||
@@ -88,19 +89,15 @@ export class Pipedrive implements INodeType {
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Basic Auth',
|
||||
value: 'basicAuth'
|
||||
name: 'API Token',
|
||||
value: 'apiToken'
|
||||
},
|
||||
{
|
||||
name: 'OAuth2',
|
||||
value: 'oAuth2',
|
||||
},
|
||||
{
|
||||
name: 'None',
|
||||
value: 'none',
|
||||
},
|
||||
],
|
||||
default: 'basicAuth',
|
||||
default: 'apiToken',
|
||||
description: 'Method of authentication.',
|
||||
},
|
||||
{
|
||||
@@ -399,6 +396,11 @@ export class Pipedrive implements INodeType {
|
||||
value: 'getAll',
|
||||
description: 'Get data of all persons',
|
||||
},
|
||||
{
|
||||
name: 'Search',
|
||||
value: 'search',
|
||||
description: 'Search all persons',
|
||||
},
|
||||
{
|
||||
name: 'Update',
|
||||
value: 'update',
|
||||
@@ -2058,6 +2060,7 @@ export class Pipedrive implements INodeType {
|
||||
show: {
|
||||
operation: [
|
||||
'getAll',
|
||||
'search',
|
||||
],
|
||||
},
|
||||
},
|
||||
@@ -2072,6 +2075,7 @@ export class Pipedrive implements INodeType {
|
||||
show: {
|
||||
operation: [
|
||||
'getAll',
|
||||
'search',
|
||||
],
|
||||
returnAll: [
|
||||
false,
|
||||
@@ -2086,9 +2090,143 @@ export class Pipedrive implements INodeType {
|
||||
description: 'How many results to return.',
|
||||
},
|
||||
|
||||
// ----------------------------------
|
||||
// person:getAll
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: [
|
||||
'getAll',
|
||||
],
|
||||
resource: [
|
||||
'person',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: {},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Filter ID',
|
||||
name: 'filterId',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getFilters',
|
||||
},
|
||||
default: '',
|
||||
description: 'ID of the filter to use.',
|
||||
},
|
||||
{
|
||||
displayName: 'First Char',
|
||||
name: 'firstChar',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'If supplied, only persons whose name starts with the specified letter will be returned ',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// ----------------------------------
|
||||
// person:search
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'Term',
|
||||
name: 'term',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: [
|
||||
'search',
|
||||
],
|
||||
resource: [
|
||||
'person',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'The search term to look for. Minimum 2 characters (or 1 if using exact_match).',
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: [
|
||||
'search',
|
||||
],
|
||||
resource: [
|
||||
'person',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: {},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Exact Match',
|
||||
name: 'exactMatch',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'When enabled, only full exact matches against the given term are returned. It is not case sensitive.',
|
||||
},
|
||||
{
|
||||
displayName: 'Fields',
|
||||
name: 'fields',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'A comma-separated string array. The fields to perform the search from. Defaults to all of them.',
|
||||
},
|
||||
{
|
||||
displayName: 'Include Fields',
|
||||
name: 'includeFields',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Supports including optional fields in the results which are not provided by default.',
|
||||
},
|
||||
{
|
||||
displayName: 'Organization ID',
|
||||
name: 'organizationId',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Will filter Deals by the provided Organization ID.',
|
||||
},
|
||||
{
|
||||
displayName: 'RAW Data',
|
||||
name: 'rawData',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: `Returns the data exactly in the way it got received from the API.`,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
methods = {
|
||||
loadOptions: {
|
||||
// Get all the filters to display them to user so that he can
|
||||
// select them easily
|
||||
async getFilters(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||
const returnData: INodePropertyOptions[] = [];
|
||||
const { data } = await pipedriveApiRequest.call(this, 'GET', '/filters', {}, { type: 'people' });
|
||||
for (const filter of data) {
|
||||
const filterName = filter.name;
|
||||
const filterId = filter.id;
|
||||
returnData.push({
|
||||
name: filterName,
|
||||
value: filterId,
|
||||
});
|
||||
}
|
||||
return returnData;
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||
const items = this.getInputData();
|
||||
@@ -2492,8 +2630,51 @@ export class Pipedrive implements INodeType {
|
||||
qs.limit = this.getNodeParameter('limit', i) as number;
|
||||
}
|
||||
|
||||
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
|
||||
|
||||
if (additionalFields.filterId) {
|
||||
qs.filter_id = additionalFields.filterId as string;
|
||||
}
|
||||
|
||||
if (additionalFields.firstChar) {
|
||||
qs.first_char = additionalFields.firstChar as string;
|
||||
}
|
||||
|
||||
endpoint = `/persons`;
|
||||
|
||||
} else if (operation === 'search') {
|
||||
// ----------------------------------
|
||||
// persons:search
|
||||
// ----------------------------------
|
||||
|
||||
requestMethod = 'GET';
|
||||
|
||||
qs.term = this.getNodeParameter('term', i) as string;
|
||||
returnAll = this.getNodeParameter('returnAll', i) as boolean;
|
||||
if (returnAll === false) {
|
||||
qs.limit = this.getNodeParameter('limit', i) as number;
|
||||
}
|
||||
|
||||
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
|
||||
|
||||
if (additionalFields.fields) {
|
||||
qs.fields = additionalFields.fields as string;
|
||||
}
|
||||
|
||||
if (additionalFields.exactMatch) {
|
||||
qs.exact_match = additionalFields.exactMatch as boolean;
|
||||
}
|
||||
|
||||
if (additionalFields.organizationId) {
|
||||
qs.organization_id = parseInt(additionalFields.organizationId as string, 10);
|
||||
}
|
||||
|
||||
if (additionalFields.includeFields) {
|
||||
qs.include_fields = additionalFields.includeFields as string;
|
||||
}
|
||||
|
||||
endpoint = `/persons/search`;
|
||||
|
||||
} else if (operation === 'update') {
|
||||
// ----------------------------------
|
||||
// person:update
|
||||
@@ -2530,7 +2711,9 @@ export class Pipedrive implements INodeType {
|
||||
|
||||
let responseData;
|
||||
if (returnAll === true) {
|
||||
|
||||
responseData = await pipedriveApiRequestAllItems.call(this, requestMethod, endpoint, body, qs);
|
||||
|
||||
} else {
|
||||
|
||||
if (customProperties !== undefined) {
|
||||
@@ -2538,6 +2721,13 @@ export class Pipedrive implements INodeType {
|
||||
}
|
||||
|
||||
responseData = await pipedriveApiRequest.call(this, requestMethod, endpoint, body, qs, formData, downloadFile);
|
||||
|
||||
<<<<<<< HEAD
|
||||
if (responseData.data === null) {
|
||||
responseData.data = [];
|
||||
}
|
||||
=======
|
||||
>>>>>>> master
|
||||
}
|
||||
|
||||
if (resource === 'file' && operation === 'download') {
|
||||
@@ -2559,6 +2749,24 @@ export class Pipedrive implements INodeType {
|
||||
|
||||
items[i].binary![binaryPropertyName] = await this.helpers.prepareBinaryData(responseData.data);
|
||||
} else {
|
||||
|
||||
if (responseData.data === null) {
|
||||
responseData.data = [];
|
||||
}
|
||||
|
||||
if (operation === 'search' && responseData.data && responseData.data.items) {
|
||||
responseData.data = responseData.data.items;
|
||||
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
|
||||
if (additionalFields.rawData !== true) {
|
||||
responseData.data = responseData.data.map((item: { result_score: number, item: object }) => {
|
||||
return {
|
||||
result_score: item.result_score,
|
||||
...item.item,
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (Array.isArray(responseData.data)) {
|
||||
returnData.push.apply(returnData, responseData.data as IDataObject[]);
|
||||
} else {
|
||||
|
||||
@@ -14,8 +14,10 @@ import {
|
||||
} from './GenericFunctions';
|
||||
|
||||
import * as basicAuth from 'basic-auth';
|
||||
import { Response } from 'express';
|
||||
|
||||
import {
|
||||
Response,
|
||||
} from 'express';
|
||||
|
||||
function authorizationError(resp: Response, realm: string, responseCode: number, message?: string) {
|
||||
if (message === undefined) {
|
||||
@@ -52,6 +54,10 @@ export class PipedriveTrigger implements INodeType {
|
||||
{
|
||||
name: 'pipedriveApi',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'httpBasicAuth',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
authentication: [
|
||||
@@ -60,18 +66,6 @@ export class PipedriveTrigger implements INodeType {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'pipedriveOAuth2Api',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
authentication: [
|
||||
'oAuth2',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
webhooks: [
|
||||
{
|
||||
@@ -91,17 +85,13 @@ export class PipedriveTrigger implements INodeType {
|
||||
name: 'Basic Auth',
|
||||
value: 'basicAuth'
|
||||
},
|
||||
{
|
||||
name: 'OAuth2',
|
||||
value: 'oAuth2',
|
||||
},
|
||||
{
|
||||
name: 'None',
|
||||
value: 'none',
|
||||
value: 'none'
|
||||
},
|
||||
],
|
||||
default: 'basicAuth',
|
||||
description: 'Method of authentication.',
|
||||
default: 'none',
|
||||
description: 'If authentication should be activated for the webhook (makes it more scure).',
|
||||
},
|
||||
{
|
||||
displayName: 'Action',
|
||||
@@ -191,7 +181,6 @@ export class PipedriveTrigger implements INodeType {
|
||||
description: 'Type of object to receive notifications about.',
|
||||
},
|
||||
],
|
||||
|
||||
};
|
||||
|
||||
// @ts-ignore (because of request)
|
||||
@@ -288,8 +277,6 @@ export class PipedriveTrigger implements INodeType {
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
||||
async webhook(this: IWebhookFunctions): Promise<IWebhookResponseData> {
|
||||
const req = this.getRequestObject();
|
||||
const resp = this.getResponseObject();
|
||||
|
||||
Reference in New Issue
Block a user