diff --git a/packages/nodes-base/credentials/ERPNextApi.credentials.ts b/packages/nodes-base/credentials/ERPNextApi.credentials.ts
index 6ca1016457..264aae74a7 100644
--- a/packages/nodes-base/credentials/ERPNextApi.credentials.ts
+++ b/packages/nodes-base/credentials/ERPNextApi.credentials.ts
@@ -1,4 +1,6 @@
import {
+ IAuthenticateGeneric,
+ ICredentialTestRequest,
ICredentialType,
INodeProperties,
} from 'n8n-workflow';
@@ -66,5 +68,27 @@ export class ERPNextApi implements ICredentialType {
},
},
},
+ {
+ displayName: 'Ignore SSL Issues',
+ name: 'allowUnauthorizedCerts',
+ type: 'boolean',
+ description: 'Whether to connect even if SSL certificate validation is not possible',
+ default: false,
+ },
];
+ authenticate: IAuthenticateGeneric = {
+ type: 'generic',
+ properties: {
+ headers: {
+ Authorization: '=token {{$credentials.apiKey}}:{{$credentials.apiSecret}}',
+ },
+ },
+ };
+ test: ICredentialTestRequest = {
+ request: {
+ baseURL: '={{$credentials.environment === "cloudHosted" ? "https://" + $credentials.subdomain + ".erpnext.com" : $credentials.domain}}',
+ url: '/api/resource/Doctype',
+ skipSslCertificateValidation: '={{ $credentials.allowUnauthorizedCerts }}',
+ },
+ };
}
diff --git a/packages/nodes-base/nodes/ERPNext/GenericFunctions.ts b/packages/nodes-base/nodes/ERPNext/GenericFunctions.ts
index 9afc73f5cc..81b799b35d 100644
--- a/packages/nodes-base/nodes/ERPNext/GenericFunctions.ts
+++ b/packages/nodes-base/nodes/ERPNext/GenericFunctions.ts
@@ -12,7 +12,6 @@ import {
IHookFunctions,
IWebhookFunctions,
NodeApiError,
- NodeOperationError
} from 'n8n-workflow';
export async function erpNextApiRequest(
@@ -31,13 +30,13 @@ export async function erpNextApiRequest(
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
- Authorization: `token ${credentials.apiKey}:${credentials.apiSecret}`,
},
method,
body,
qs: query,
uri: uri || `${baseUrl}${resource}`,
json: true,
+ rejectUnauthorized: !credentials.allowUnauthorizedCerts as boolean,
};
options = Object.assign({}, options, option);
@@ -50,7 +49,7 @@ export async function erpNextApiRequest(
delete options.qs;
}
try {
- return await this.helpers.request!(options);
+ return await this.helpers.requestWithAuthentication.call(this, 'erpNextApi',options);
} catch (error) {
if (error.statusCode === 403) {
throw new NodeApiError(this.getNode(), { message: 'DocType unavailable.' });
@@ -105,4 +104,5 @@ type ERPNextApiCredentials = {
environment: 'cloudHosted' | 'selfHosted';
subdomain?: string;
domain?: string;
+ allowUnauthorizedCerts?: boolean;
};
diff --git a/packages/workflow/src/Interfaces.ts b/packages/workflow/src/Interfaces.ts
index 0e8712d5ef..304466db49 100644
--- a/packages/workflow/src/Interfaces.ts
+++ b/packages/workflow/src/Interfaces.ts
@@ -261,8 +261,34 @@ export interface IAuthenticateRuleResponseSuccessBody extends IAuthenticateRuleB
value: any;
};
}
+
+type Override = Omit & B;
+
+export namespace DeclarativeRestApiSettings {
+ // The type below might be extended
+ // with new options that need to be parsed as expressions
+ export type HttpRequestOptions = Override<
+ IHttpRequestOptions,
+ { skipSslCertificateValidation?: string | boolean; url?: string }
+ >;
+
+ export type ResultOptions = {
+ maxResults?: number | string;
+ options: HttpRequestOptions;
+ paginate?: boolean | string;
+ preSend: PreSendAction[];
+ postReceive: Array<{
+ data: {
+ parameterValue: string | IDataObject | undefined;
+ };
+ actions: PostReceiveAction[];
+ }>;
+ requestOperations?: IN8nRequestOperations;
+ };
+}
+
export interface ICredentialTestRequest {
- request: IHttpRequestOptions;
+ request: DeclarativeRestApiSettings.HttpRequestOptions;
rules?: IAuthenticateRuleResponseCode[] | IAuthenticateRuleResponseSuccessBody[];
}
@@ -487,7 +513,7 @@ export interface IN8nRequestOperations {
| IN8nRequestOperationPaginationOffset
| ((
this: IExecutePaginationFunctions,
- requestOptions: IRequestOptionsFromParameters,
+ requestOptions: DeclarativeRestApiSettings.ResultOptions,
) => Promise);
}
@@ -600,7 +626,7 @@ export interface IExecuteSingleFunctions {
export interface IExecutePaginationFunctions extends IExecuteSingleFunctions {
makeRoutingRequest(
this: IAllExecuteFunctions,
- requestOptions: IRequestOptionsFromParameters,
+ requestOptions: DeclarativeRestApiSettings.ResultOptions,
): Promise;
}
export interface IExecuteWorkflowInfo {
@@ -889,7 +915,7 @@ export interface ILoadOptions {
routing?: {
operations?: IN8nRequestOperations;
output?: INodeRequestOutput;
- request?: IHttpRequestOptionsFromParameters;
+ request?: DeclarativeRestApiSettings.HttpRequestOptions;
};
}
@@ -1069,7 +1095,7 @@ export interface INodeTypeBaseDescription {
export interface INodePropertyRouting {
operations?: IN8nRequestOperations; // Should be changed, does not sound right
output?: INodeRequestOutput;
- request?: IHttpRequestOptionsFromParameters;
+ request?: DeclarativeRestApiSettings.HttpRequestOptions;
send?: INodeRequestSend;
}
@@ -1147,24 +1173,6 @@ export interface IPostReceiveSort extends IPostReceiveBase {
};
}
-export interface IHttpRequestOptionsFromParameters extends Partial {
- url?: string;
-}
-
-export interface IRequestOptionsFromParameters {
- maxResults?: number | string;
- options: IHttpRequestOptionsFromParameters;
- paginate?: boolean | string;
- preSend: PreSendAction[];
- postReceive: Array<{
- data: {
- parameterValue: string | IDataObject | undefined;
- };
- actions: PostReceiveAction[];
- }>;
- requestOperations?: IN8nRequestOperations;
-}
-
export interface INodeTypeDescription extends INodeTypeBaseDescription {
version: number | number[];
defaults: INodeParameters;
@@ -1178,7 +1186,7 @@ export interface INodeTypeDescription extends INodeTypeBaseDescription {
credentials?: INodeCredentialDescription[];
maxNodes?: number; // How many nodes of that type can be created in a workflow
polling?: boolean;
- requestDefaults?: IHttpRequestOptionsFromParameters;
+ requestDefaults?: DeclarativeRestApiSettings.HttpRequestOptions;
requestOperations?: IN8nRequestOperations;
hooks?: {
[key: string]: INodeHookDescription[] | undefined;
diff --git a/packages/workflow/src/NodeErrors.ts b/packages/workflow/src/NodeErrors.ts
index c8b0b52bbb..399c228460 100644
--- a/packages/workflow/src/NodeErrors.ts
+++ b/packages/workflow/src/NodeErrors.ts
@@ -292,7 +292,7 @@ export class NodeApiError extends NodeError {
}
// if it's an error generated by axios
// look for descriptions in the response object
- if (error.isAxiosError) {
+ if (error.isAxiosError && error.response) {
error = error.response as JsonObject;
}
diff --git a/packages/workflow/src/RoutingNode.ts b/packages/workflow/src/RoutingNode.ts
index a103dcabc3..683bd77721 100644
--- a/packages/workflow/src/RoutingNode.ts
+++ b/packages/workflow/src/RoutingNode.ts
@@ -24,7 +24,7 @@ import {
INodeParameters,
INodePropertyOptions,
INodeType,
- IRequestOptionsFromParameters,
+ DeclarativeRestApiSettings,
IRunExecutionData,
ITaskDataConnections,
IWorkflowDataProxyAdditionalKeys,
@@ -127,7 +127,7 @@ export class RoutingNode {
executeData,
this.mode,
);
- const requestData: IRequestOptionsFromParameters = {
+ const requestData: DeclarativeRestApiSettings.ResultOptions = {
options: {
qs: {},
body: {},
@@ -214,8 +214,8 @@ export class RoutingNode {
}
mergeOptions(
- destinationOptions: IRequestOptionsFromParameters,
- sourceOptions?: IRequestOptionsFromParameters,
+ destinationOptions: DeclarativeRestApiSettings.ResultOptions,
+ sourceOptions?: DeclarativeRestApiSettings.ResultOptions,
): void {
if (sourceOptions) {
destinationOptions.paginate = destinationOptions.paginate ?? sourceOptions.paginate;
@@ -375,7 +375,7 @@ export class RoutingNode {
async rawRoutingRequest(
executeSingleFunctions: IExecuteSingleFunctions,
- requestData: IRequestOptionsFromParameters,
+ requestData: DeclarativeRestApiSettings.ResultOptions,
itemIndex: number,
runIndex: number,
credentialType?: string,
@@ -434,7 +434,7 @@ export class RoutingNode {
}
async makeRoutingRequest(
- requestData: IRequestOptionsFromParameters,
+ requestData: DeclarativeRestApiSettings.ResultOptions,
executeSingleFunctions: IExecuteSingleFunctions,
itemIndex: number,
runIndex: number,
@@ -452,7 +452,7 @@ export class RoutingNode {
const executePaginationFunctions = {
...executeSingleFunctions,
- makeRoutingRequest: async (requestOptions: IRequestOptionsFromParameters) => {
+ makeRoutingRequest: async (requestOptions: DeclarativeRestApiSettings.ResultOptions) => {
return this.rawRoutingRequest(
executeSingleFunctions,
requestOptions,
@@ -591,8 +591,8 @@ export class RoutingNode {
runIndex: number,
path: string,
additionalKeys?: IWorkflowDataProxyAdditionalKeys,
- ): IRequestOptionsFromParameters | undefined {
- const returnData: IRequestOptionsFromParameters = {
+ ): DeclarativeRestApiSettings.ResultOptions | undefined {
+ const returnData: DeclarativeRestApiSettings.ResultOptions = {
options: {
qs: {},
body: {},
diff --git a/packages/workflow/test/RoutingNode.test.ts b/packages/workflow/test/RoutingNode.test.ts
index 8da36731a4..86b1afe720 100644
--- a/packages/workflow/test/RoutingNode.test.ts
+++ b/packages/workflow/test/RoutingNode.test.ts
@@ -2,7 +2,7 @@ import {
INode,
INodeExecutionData,
INodeParameters,
- IRequestOptionsFromParameters,
+ DeclarativeRestApiSettings,
IRunExecutionData,
RoutingNode,
Workflow,
@@ -46,7 +46,7 @@ describe('RoutingNode', () => {
nodeParameters: INodeParameters;
nodeTypeProperties: INodeProperties;
};
- output: IRequestOptionsFromParameters | undefined;
+ output: DeclarativeRestApiSettings.ResultOptions | undefined;
}> = [
{
description: 'single parameter, only send defined, fixed value',