mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
Merge pull request #3215 from n8n-io/n8n-3481-re-version-http-request-node
Re-version HTTP request node
This commit is contained in:
commit
afe3c04e75
4
package-lock.json
generated
4
package-lock.json
generated
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "n8n",
|
||||
"version": "0.168.2",
|
||||
"version": "0.174.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "n8n",
|
||||
"version": "0.168.2",
|
||||
"version": "0.174.0",
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.14.6",
|
||||
"@fontsource/open-sans": "^4.5.0",
|
||||
|
|
|
@ -342,6 +342,7 @@ export class CredentialsHelper extends ICredentialsHelper {
|
|||
decryptedDataOriginal as INodeParameters,
|
||||
true,
|
||||
false,
|
||||
null,
|
||||
) as ICredentialDataDecryptedObject;
|
||||
|
||||
if (decryptedDataOriginal.oauthTokenData !== undefined) {
|
||||
|
@ -436,8 +437,6 @@ export class CredentialsHelper extends ICredentialsHelper {
|
|||
// Add special database related data
|
||||
newCredentialsData.updatedAt = new Date();
|
||||
|
||||
// TODO: also add user automatically depending on who is logged in, if anybody is logged in
|
||||
|
||||
// Save the credentials in DB
|
||||
const findQuery = {
|
||||
id: credentials.id,
|
||||
|
@ -562,7 +561,9 @@ export class CredentialsHelper extends ICredentialsHelper {
|
|||
parameters: {},
|
||||
name: 'Temp-Node',
|
||||
type: nodeType.description.name,
|
||||
typeVersion: nodeType.description.version,
|
||||
typeVersion: Array.isArray(nodeType.description.version)
|
||||
? nodeType.description.version.slice(-1)[0]
|
||||
: nodeType.description.version,
|
||||
position: [0, 0],
|
||||
};
|
||||
|
||||
|
|
|
@ -1298,6 +1298,7 @@ export async function getCredentials(
|
|||
!NodeHelpers.displayParameter(
|
||||
additionalData.currentNodeParameters || node.parameters,
|
||||
nodeCredentialDescription,
|
||||
node,
|
||||
node.parameters,
|
||||
)
|
||||
) {
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
<script lang="ts">
|
||||
import {
|
||||
INodeUi,
|
||||
IUpdateInformation,
|
||||
} from '@/Interface';
|
||||
|
||||
|
@ -87,6 +88,9 @@ export default mixins(
|
|||
return this.displayNodeParameter(option as INodeProperties);
|
||||
});
|
||||
},
|
||||
node (): INodeUi {
|
||||
return this.$store.getters.activeNode;
|
||||
},
|
||||
// Returns all the options which did not get added already
|
||||
parameterOptions (): Array<INodePropertyOptions | INodeProperties> {
|
||||
return (this.filteredOptions as Array<INodePropertyOptions | INodeProperties>).filter((option) => {
|
||||
|
@ -127,7 +131,7 @@ export default mixins(
|
|||
// If it is not defined no need to do a proper check
|
||||
return true;
|
||||
}
|
||||
return this.displayParameter(this.nodeValues, parameter, this.path);
|
||||
return this.displayParameter(this.nodeValues, parameter, this.path, this.node);
|
||||
},
|
||||
optionSelected (optionName: string) {
|
||||
const options = this.getOptionProperties(optionName);
|
||||
|
|
|
@ -395,6 +395,7 @@ export default mixins(showMessage, nodeHelpers).extend({
|
|||
this.credentialData as INodeParameters,
|
||||
parameter,
|
||||
'',
|
||||
null,
|
||||
);
|
||||
},
|
||||
getCredentialProperties(name: string): INodeProperties[] {
|
||||
|
@ -598,6 +599,7 @@ export default mixins(showMessage, nodeHelpers).extend({
|
|||
this.credentialData as INodeParameters,
|
||||
false,
|
||||
false,
|
||||
null,
|
||||
);
|
||||
|
||||
const credentialDetails: ICredentialsDecrypted = {
|
||||
|
|
|
@ -251,7 +251,7 @@ export default mixins(
|
|||
// If it is not defined no need to do a proper check
|
||||
return true;
|
||||
}
|
||||
return this.displayParameter(this.node.parameters, credentialTypeDescription, '');
|
||||
return this.displayParameter(this.node.parameters, credentialTypeDescription, '', this.node);
|
||||
},
|
||||
|
||||
getIssues (credentialTypeName: string): string[] {
|
||||
|
|
|
@ -379,7 +379,7 @@ export default mixins(
|
|||
}
|
||||
|
||||
// Get only the parameters which are different to the defaults
|
||||
let nodeParameters = NodeHelpers.getNodeParameters(nodeType.properties, node.parameters, false, false);
|
||||
let nodeParameters = NodeHelpers.getNodeParameters(nodeType.properties, node.parameters, false, false, node);
|
||||
const oldNodeParameters = Object.assign({}, nodeParameters);
|
||||
|
||||
// Copy the data because it is the data of vuex so make sure that
|
||||
|
@ -415,7 +415,7 @@ export default mixins(
|
|||
|
||||
// Get the parameters with the now new defaults according to the
|
||||
// from the user actually defined parameters
|
||||
nodeParameters = NodeHelpers.getNodeParameters(nodeType.properties, nodeParameters as INodeParameters, true, false);
|
||||
nodeParameters = NodeHelpers.getNodeParameters(nodeType.properties, nodeParameters as INodeParameters, true, false, node);
|
||||
|
||||
for (const key of Object.keys(nodeParameters as object)) {
|
||||
if (nodeParameters && nodeParameters[key] !== null && nodeParameters[key] !== undefined) {
|
||||
|
|
|
@ -110,6 +110,7 @@
|
|||
:size="inputSize"
|
||||
filterable
|
||||
:value="displayValue"
|
||||
:placeholder="parameter.placeholder ? getPlaceholder() : $locale.baseText('parameterInput.select')"
|
||||
:loading="remoteParameterOptionsLoading"
|
||||
:disabled="isReadOnly || remoteParameterOptionsLoading"
|
||||
:title="displayTitle"
|
||||
|
@ -468,7 +469,7 @@ export default mixins(
|
|||
const newPath = this.shortPath.split('.');
|
||||
newPath.pop();
|
||||
|
||||
const issues = NodeHelpers.getParameterIssues(this.parameter, this.node.parameters, newPath.join('.'));
|
||||
const issues = NodeHelpers.getParameterIssues(this.parameter, this.node.parameters, newPath.join('.'), this.node);
|
||||
|
||||
if (['options', 'multiOptions'].includes(this.parameter.type) && this.remoteParameterOptionsLoading === false && this.remoteParameterOptionsLoadingIssues === null) {
|
||||
// Check if the value resolves to a valid option
|
||||
|
|
|
@ -89,7 +89,7 @@ import {
|
|||
NodeParameterValue,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
import { IUpdateInformation } from '@/Interface';
|
||||
import { INodeUi, IUpdateInformation } from '@/Interface';
|
||||
|
||||
import MultipleParameter from '@/components/MultipleParameter.vue';
|
||||
import { genericHelpers } from '@/components/mixins/genericHelpers';
|
||||
|
@ -124,6 +124,9 @@ export default mixins(
|
|||
filteredParameterNames (): string[] {
|
||||
return this.filteredParameters.map(parameter => parameter.name);
|
||||
},
|
||||
node (): INodeUi {
|
||||
return this.$store.getters.activeNode;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
multipleValues (parameter: INodeProperties): boolean {
|
||||
|
@ -213,13 +216,13 @@ export default mixins(
|
|||
if (this.path) {
|
||||
rawValues = JSON.parse(JSON.stringify(this.nodeValues));
|
||||
set(rawValues, this.path, nodeValues);
|
||||
return this.displayParameter(rawValues, parameter, this.path);
|
||||
return this.displayParameter(rawValues, parameter, this.path, this.node);
|
||||
} else {
|
||||
return this.displayParameter(nodeValues, parameter, '');
|
||||
return this.displayParameter(nodeValues, parameter, '', this.node);
|
||||
}
|
||||
}
|
||||
|
||||
return this.displayParameter(this.nodeValues, parameter, this.path);
|
||||
return this.displayParameter(this.nodeValues, parameter, this.path, this.node);
|
||||
},
|
||||
valueChanged (parameterData: IUpdateInformation): void {
|
||||
this.$emit('valueChanged', parameterData);
|
||||
|
|
|
@ -48,8 +48,8 @@ export const nodeHelpers = mixins(
|
|||
},
|
||||
|
||||
// Returns if the given parameter should be displayed or not
|
||||
displayParameter (nodeValues: INodeParameters, parameter: INodeProperties | INodeCredentialDescription, path: string) {
|
||||
return NodeHelpers.displayParameterPath(nodeValues, parameter, path);
|
||||
displayParameter (nodeValues: INodeParameters, parameter: INodeProperties | INodeCredentialDescription, path: string, node: INodeUi | null) {
|
||||
return NodeHelpers.displayParameterPath(nodeValues, parameter, path, node);
|
||||
},
|
||||
|
||||
// Returns all the issues of the node
|
||||
|
@ -200,7 +200,7 @@ export const nodeHelpers = mixins(
|
|||
let selectedCredentials: INodeCredentialsDetails;
|
||||
for (const credentialTypeDescription of nodeType!.credentials!) {
|
||||
// Check if credentials should be displayed else ignore
|
||||
if (this.displayParameter(node.parameters, credentialTypeDescription, '') !== true) {
|
||||
if (this.displayParameter(node.parameters, credentialTypeDescription, '', node) !== true) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -323,7 +323,7 @@ export const workflowHelpers = mixins(
|
|||
if (nodeType !== null) {
|
||||
// Node-Type is known so we can save the parameters correctly
|
||||
|
||||
const nodeParameters = NodeHelpers.getNodeParameters(nodeType.properties, node.parameters, false, false);
|
||||
const nodeParameters = NodeHelpers.getNodeParameters(nodeType.properties, node.parameters, false, false, node);
|
||||
nodeData.parameters = nodeParameters !== null ? nodeParameters : {};
|
||||
|
||||
// Add the node credentials if there are some set and if they should be displayed
|
||||
|
@ -338,7 +338,7 @@ export const workflowHelpers = mixins(
|
|||
continue;
|
||||
}
|
||||
|
||||
if (this.displayParameter(node.parameters, credentialTypeDescription, '') === false) {
|
||||
if (this.displayParameter(node.parameters, credentialTypeDescription, '', node) === false) {
|
||||
// Credential should not be displayed so do also not save
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -645,7 +645,7 @@ export const store = new Vuex.Store({
|
|||
},
|
||||
|
||||
updateNodeTypes (state, nodeTypes: INodeTypeDescription[]) {
|
||||
const oldNodesToKeep = state.nodeTypes.filter(node => !nodeTypes.find(n => n.name === node.name && n.version === node.version));
|
||||
const oldNodesToKeep = state.nodeTypes.filter(node => !nodeTypes.find(n => n.name === node.name && n.version.toString() === node.version.toString()));
|
||||
const newNodesState = [...oldNodesToKeep, ...nodeTypes];
|
||||
Vue.set(state, 'nodeTypes', newNodesState);
|
||||
state.nodeTypes = newNodesState;
|
||||
|
@ -852,7 +852,11 @@ export const store = new Vuex.Store({
|
|||
|
||||
nodeType: (state, getters) => (nodeType: string, typeVersion?: number): INodeTypeDescription | null => {
|
||||
const foundType = state.nodeTypes.find(typeData => {
|
||||
return typeData.name === nodeType && typeData.version === (typeVersion || typeData.defaultVersion || DEFAULT_NODETYPE_VERSION);
|
||||
const typeVersion = Array.isArray(typeData.version)
|
||||
? typeData.version
|
||||
: [typeData.version];
|
||||
|
||||
return typeData.name === nodeType && typeVersion.some(versions => [typeVersion, typeData.defaultVersion, DEFAULT_NODETYPE_VERSION].includes(versions));
|
||||
});
|
||||
|
||||
if (foundType === undefined) {
|
||||
|
|
|
@ -1356,7 +1356,9 @@ export default mixins(
|
|||
const newNodeData: INodeUi = {
|
||||
name: nodeTypeData.defaults.name as string,
|
||||
type: nodeTypeData.name,
|
||||
typeVersion: nodeTypeData.version,
|
||||
typeVersion: Array.isArray(nodeTypeData.version)
|
||||
? nodeTypeData.version.slice(-1)[0]
|
||||
: nodeTypeData.version,
|
||||
position: [0, 0],
|
||||
parameters: {},
|
||||
};
|
||||
|
@ -2445,7 +2447,7 @@ export default mixins(
|
|||
if (nodeType !== null) {
|
||||
let nodeParameters = null;
|
||||
try {
|
||||
nodeParameters = NodeHelpers.getNodeParameters(nodeType.properties, node.parameters, true, false);
|
||||
nodeParameters = NodeHelpers.getNodeParameters(nodeType.properties, node.parameters, true, false, node);
|
||||
} catch (e) {
|
||||
console.error(this.$locale.baseText('nodeView.thereWasAProblemLoadingTheNodeParametersOfNode') + `: "${node.name}"`); // eslint-disable-line no-console
|
||||
console.error(e); // eslint-disable-line no-console
|
||||
|
@ -2753,10 +2755,13 @@ export default mixins(
|
|||
|
||||
const nodesToBeFetched:INodeTypeNameVersion[] = [];
|
||||
allNodes.forEach(node => {
|
||||
if(!!nodeInfos.find(n => n.name === node.name && n.version === node.version) && !node.hasOwnProperty('properties')) {
|
||||
const nodeVersions = Array.isArray(node.version) ? node.version : [node.version];
|
||||
if(!!nodeInfos.find(n => n.name === node.name && nodeVersions.includes(n.version)) && !node.hasOwnProperty('properties')) {
|
||||
nodesToBeFetched.push({
|
||||
name: node.name,
|
||||
version: node.version,
|
||||
version: Array.isArray(node.version)
|
||||
? node.version.slice(-1)[0]
|
||||
: node.version,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
import path from 'path';
|
||||
import {
|
||||
IExecuteFunctions,
|
||||
} from 'n8n-core';
|
||||
import {
|
||||
IAuthenticate,
|
||||
IBinaryData,
|
||||
IDataObject,
|
||||
ILoadOptionsFunctions,
|
||||
INodeExecutionData,
|
||||
INodePropertyOptions,
|
||||
INodeType,
|
||||
INodeTypeDescription,
|
||||
NodeApiError,
|
||||
|
@ -29,7 +33,7 @@ export class HttpRequest implements INodeType {
|
|||
name: 'httpRequest',
|
||||
icon: 'fa:at',
|
||||
group: ['input'],
|
||||
version: 1,
|
||||
version: [1, 2],
|
||||
subtitle: '={{$parameter["requestMethod"] + ": " + $parameter["url"]}}',
|
||||
description: 'Makes an HTTP request and returns the response data',
|
||||
defaults: {
|
||||
|
@ -39,6 +43,97 @@ export class HttpRequest implements INodeType {
|
|||
inputs: ['main'],
|
||||
outputs: ['main'],
|
||||
credentials: [
|
||||
// ----------------------------------
|
||||
// v2 creds
|
||||
// ----------------------------------
|
||||
{
|
||||
name: 'httpBasicAuth',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
authenticateWith: [
|
||||
'basicAuth',
|
||||
],
|
||||
'@version': [
|
||||
2,
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'httpDigestAuth',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
authenticateWith: [
|
||||
'digestAuth',
|
||||
],
|
||||
'@version': [
|
||||
2,
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'httpHeaderAuth',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
authenticateWith: [
|
||||
'headerAuth',
|
||||
],
|
||||
'@version': [
|
||||
2,
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'httpQueryAuth',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
authenticateWith: [
|
||||
'queryAuth',
|
||||
],
|
||||
'@version': [
|
||||
2,
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'oAuth1Api',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
authenticateWith: [
|
||||
'oAuth1',
|
||||
],
|
||||
'@version': [
|
||||
2,
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'oAuth2Api',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
authenticateWith: [
|
||||
'oAuth2',
|
||||
],
|
||||
'@version': [
|
||||
2,
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// ----------------------------------
|
||||
// v1 creds
|
||||
// ----------------------------------
|
||||
{
|
||||
name: 'httpBasicAuth',
|
||||
required: true,
|
||||
|
@ -47,6 +142,9 @@ export class HttpRequest implements INodeType {
|
|||
authentication: [
|
||||
'basicAuth',
|
||||
],
|
||||
'@version': [
|
||||
1,
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -58,6 +156,9 @@ export class HttpRequest implements INodeType {
|
|||
authentication: [
|
||||
'digestAuth',
|
||||
],
|
||||
'@version': [
|
||||
1,
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -69,6 +170,9 @@ export class HttpRequest implements INodeType {
|
|||
authentication: [
|
||||
'headerAuth',
|
||||
],
|
||||
'@version': [
|
||||
1,
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -80,6 +184,9 @@ export class HttpRequest implements INodeType {
|
|||
authentication: [
|
||||
'queryAuth',
|
||||
],
|
||||
'@version': [
|
||||
1,
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -91,6 +198,9 @@ export class HttpRequest implements INodeType {
|
|||
authentication: [
|
||||
'oAuth1',
|
||||
],
|
||||
'@version': [
|
||||
1,
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -107,6 +217,107 @@ export class HttpRequest implements INodeType {
|
|||
},
|
||||
],
|
||||
properties: [
|
||||
// ----------------------------------
|
||||
// v2 params
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'Authenticate with',
|
||||
name: 'authenticateWith',
|
||||
type: 'options',
|
||||
required: true,
|
||||
options: [
|
||||
{
|
||||
name: 'Node Credential',
|
||||
value: 'nodeCredential',
|
||||
description: 'Easiest. Use a credential from another node, like Google Sheets.',
|
||||
},
|
||||
{
|
||||
name: 'Generic Auth',
|
||||
value: 'genericAuth',
|
||||
description: 'Fully customizable. Choose between Basic, Header, OAuth2 and more.',
|
||||
},
|
||||
{
|
||||
name: 'None',
|
||||
value: 'none',
|
||||
},
|
||||
],
|
||||
default: 'none',
|
||||
displayOptions: {
|
||||
show: {
|
||||
'@version': [
|
||||
2,
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Node Credential Type',
|
||||
name: 'nodeCredentialType',
|
||||
type: 'options',
|
||||
required: true,
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getNodeCredentialTypes',
|
||||
},
|
||||
default: '',
|
||||
placeholder: 'None',
|
||||
displayOptions: {
|
||||
show: {
|
||||
authenticateWith: [
|
||||
'nodeCredential',
|
||||
],
|
||||
'@version': [
|
||||
2,
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Generic Auth Type',
|
||||
name: 'genericAuthType',
|
||||
type: 'options',
|
||||
required: true,
|
||||
options: [
|
||||
{
|
||||
name: 'Basic Auth',
|
||||
value: 'basicAuth',
|
||||
},
|
||||
{
|
||||
name: 'Digest Auth',
|
||||
value: 'digestAuth',
|
||||
},
|
||||
{
|
||||
name: 'Header Auth',
|
||||
value: 'headerAuth',
|
||||
},
|
||||
{
|
||||
name: 'Query Auth',
|
||||
value: 'queryAuth',
|
||||
},
|
||||
{
|
||||
name: 'OAuth1',
|
||||
value: 'oAuth1',
|
||||
},
|
||||
{
|
||||
name: 'OAuth2',
|
||||
value: 'oAuth2',
|
||||
},
|
||||
],
|
||||
default: 'basicAuth',
|
||||
displayOptions: {
|
||||
show: {
|
||||
authenticateWith: [
|
||||
'genericAuth',
|
||||
],
|
||||
'@version': [
|
||||
2,
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// ----------------------------------
|
||||
// v1 params
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'Authentication',
|
||||
name: 'authentication',
|
||||
|
@ -143,7 +354,18 @@ export class HttpRequest implements INodeType {
|
|||
],
|
||||
default: 'none',
|
||||
description: 'The way to authenticate.',
|
||||
displayOptions: {
|
||||
show: {
|
||||
'@version': [
|
||||
1,
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// ----------------------------------
|
||||
// versionless params
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'Request Method',
|
||||
name: 'requestMethod',
|
||||
|
@ -642,6 +864,13 @@ export class HttpRequest implements INodeType {
|
|||
],
|
||||
};
|
||||
|
||||
methods = {
|
||||
loadOptions: {
|
||||
getNodeCredentialTypes(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||
return Promise.resolve(CREDENTIAL_TYPES);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||
const items = this.getInputData();
|
||||
|
@ -653,47 +882,46 @@ export class HttpRequest implements INodeType {
|
|||
'statusMessage',
|
||||
];
|
||||
|
||||
// TODO: Should have a setting which makes clear that this parameter can not change for each item
|
||||
const requestMethod = this.getNodeParameter('requestMethod', 0) as string;
|
||||
const parametersAreJson = this.getNodeParameter('jsonParameters', 0) as boolean;
|
||||
let authenticateWith;
|
||||
const nodeVersion = this.getNode().typeVersion;
|
||||
|
||||
const responseFormat = this.getNodeParameter('responseFormat', 0) as string;
|
||||
|
||||
try {
|
||||
authenticateWith = this.getNodeParameter('authenticateWith', 0) as 'nodeCredential' | 'genericAuth' | 'none';
|
||||
} catch (_) {}
|
||||
|
||||
let httpBasicAuth;
|
||||
let httpDigestAuth;
|
||||
let httpHeaderAuth;
|
||||
let httpQueryAuth;
|
||||
let oAuth1Api;
|
||||
let oAuth2Api;
|
||||
let nodeCredentialType;
|
||||
|
||||
try {
|
||||
httpBasicAuth = await this.getCredentials('httpBasicAuth');
|
||||
} catch (error) {
|
||||
// Do nothing
|
||||
}
|
||||
try {
|
||||
httpDigestAuth = await this.getCredentials('httpDigestAuth');
|
||||
} catch (error) {
|
||||
// Do nothing
|
||||
}
|
||||
try {
|
||||
httpHeaderAuth = await this.getCredentials('httpHeaderAuth');
|
||||
} catch (error) {
|
||||
// Do nothing
|
||||
}
|
||||
try {
|
||||
httpQueryAuth = await this.getCredentials('httpQueryAuth');
|
||||
} catch (error) {
|
||||
// Do nothing
|
||||
}
|
||||
try {
|
||||
oAuth1Api = await this.getCredentials('oAuth1Api');
|
||||
} catch (error) {
|
||||
// Do nothing
|
||||
}
|
||||
try {
|
||||
oAuth2Api = await this.getCredentials('oAuth2Api');
|
||||
} catch (error) {
|
||||
// Do nothing
|
||||
if (authenticateWith === 'genericAuth' || nodeVersion === 1) {
|
||||
try {
|
||||
httpBasicAuth = await this.getCredentials('httpBasicAuth');
|
||||
} catch (_) {}
|
||||
try {
|
||||
httpDigestAuth = await this.getCredentials('httpDigestAuth');
|
||||
} catch (_) {}
|
||||
try {
|
||||
httpHeaderAuth = await this.getCredentials('httpHeaderAuth');
|
||||
} catch (_) {}
|
||||
try {
|
||||
httpQueryAuth = await this.getCredentials('httpQueryAuth');
|
||||
} catch (_) {}
|
||||
try {
|
||||
oAuth1Api = await this.getCredentials('oAuth1Api');
|
||||
} catch (_) {}
|
||||
try {
|
||||
oAuth2Api = await this.getCredentials('oAuth2Api');
|
||||
} catch (_) {}
|
||||
} else if (authenticateWith === 'nodeCredential') {
|
||||
try {
|
||||
nodeCredentialType = this.getNodeParameter('nodeCredentialType', 0) as string;
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
let requestOptions: OptionsWithUri;
|
||||
|
@ -723,6 +951,9 @@ export class HttpRequest implements INodeType {
|
|||
const returnItems: INodeExecutionData[] = [];
|
||||
const requestPromises = [];
|
||||
for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
|
||||
const requestMethod = this.getNodeParameter('requestMethod', itemIndex) as string;
|
||||
const parametersAreJson = this.getNodeParameter('jsonParameters', itemIndex) as boolean;
|
||||
|
||||
const options = this.getNodeParameter('options', itemIndex, {}) as IDataObject;
|
||||
const url = this.getNodeParameter('url', itemIndex) as string;
|
||||
|
||||
|
@ -983,13 +1214,30 @@ export class HttpRequest implements INodeType {
|
|||
this.sendMessageToUI(sendRequest);
|
||||
} catch (e) { }
|
||||
|
||||
// Now that the options are all set make the actual http request
|
||||
if (oAuth1Api !== undefined) {
|
||||
requestPromises.push(this.helpers.requestOAuth1.call(this, 'oAuth1Api', requestOptions));
|
||||
} else if (oAuth2Api !== undefined) {
|
||||
requestPromises.push(this.helpers.requestOAuth2.call(this, 'oAuth2Api', requestOptions, { tokenType: 'Bearer' }));
|
||||
} else {
|
||||
requestPromises.push(this.helpers.request(requestOptions));
|
||||
if (
|
||||
authenticateWith === 'genericAuth' ||
|
||||
authenticateWith === 'none' ||
|
||||
nodeVersion === 1
|
||||
) {
|
||||
if (oAuth1Api) {
|
||||
requestPromises.push(
|
||||
this.helpers.requestOAuth1.call(this, 'oAuth1Api', requestOptions),
|
||||
);
|
||||
} else if (oAuth2Api) {
|
||||
requestPromises.push(
|
||||
this.helpers.requestOAuth2.call(this, 'oAuth2Api', requestOptions, { tokenType: 'Bearer' }),
|
||||
);
|
||||
} else {
|
||||
// bearerAuth, queryAuth, headerAuth, digestAuth, none
|
||||
requestPromises.push(
|
||||
this.helpers.request(requestOptions),
|
||||
);
|
||||
}
|
||||
} else if (authenticateWith === 'nodeCredential' && nodeCredentialType) {
|
||||
// service-specific cred: OAuth1, OAuth2, plain
|
||||
requestPromises.push(
|
||||
this.helpers.requestWithAuthentication.call(this, nodeCredentialType, requestOptions),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1121,3 +1369,56 @@ export class HttpRequest implements INodeType {
|
|||
return this.prepareOutputData(returnItems);
|
||||
}
|
||||
}
|
||||
|
||||
const NODES_BASE_ROOT: Readonly<string> = path.resolve(__dirname, '..', '..', '..');
|
||||
|
||||
/**
|
||||
* Credential types shown as options for `Node Credential Type` parameter.
|
||||
*/
|
||||
const CREDENTIAL_TYPES = getCredPaths().reduce<INodePropertyOptions[]>((acc, credPath) => {
|
||||
const credential = new (getCredClass(credPath))();
|
||||
|
||||
if (!isSupportedByHttpRequestNode(credential)) return acc;
|
||||
|
||||
return [
|
||||
...acc,
|
||||
{
|
||||
name: credential.displayName,
|
||||
value: credential.name,
|
||||
},
|
||||
];
|
||||
}, []);
|
||||
|
||||
function getCredPaths(root = NODES_BASE_ROOT): string[] {
|
||||
const packageJson = require(path.resolve(root, 'package.json'));
|
||||
|
||||
return deduplicate(packageJson.n8n.credentials);
|
||||
}
|
||||
|
||||
function deduplicate<T>(array: T[]) {
|
||||
return [...new Set(array)];
|
||||
}
|
||||
|
||||
function getCredClass(credPath: string, root = NODES_BASE_ROOT): { new(): Credential } {
|
||||
const match = credPath.match(/(^dist\/credentials\/(?<credClassName>.*)\.credentials\.js$)/);
|
||||
|
||||
if (!match?.groups) {
|
||||
throw new Error(`Failed to extract credential class name from: ${credPath}`);
|
||||
}
|
||||
|
||||
const fullCredPath = path.resolve(root, credPath);
|
||||
|
||||
return require(fullCredPath)[match.groups.credClassName];
|
||||
}
|
||||
|
||||
function isSupportedByHttpRequestNode(cred: Credential) {
|
||||
if (cred.name.slice(0, -4).endsWith('OAuth')) return true;
|
||||
|
||||
return cred.authenticate !== undefined;
|
||||
}
|
||||
|
||||
type Credential = {
|
||||
displayName: string;
|
||||
name: string;
|
||||
authenticate?: IAuthenticate;
|
||||
};
|
||||
|
|
|
@ -271,7 +271,6 @@
|
|||
"dist/credentials/SplunkApi.credentials.js",
|
||||
"dist/credentials/SpontitApi.credentials.js",
|
||||
"dist/credentials/SpotifyOAuth2Api.credentials.js",
|
||||
"dist/credentials/SpotifyOAuth2Api.credentials.js",
|
||||
"dist/credentials/SshPassword.credentials.js",
|
||||
"dist/credentials/SshPrivateKey.credentials.js",
|
||||
"dist/credentials/StackbyApi.credentials.js",
|
||||
|
|
|
@ -1113,7 +1113,7 @@ export interface IRequestOptionsFromParameters {
|
|||
}
|
||||
|
||||
export interface INodeTypeDescription extends INodeTypeBaseDescription {
|
||||
version: number;
|
||||
version: number | number[];
|
||||
defaults: INodeParameters;
|
||||
eventTriggerDescription?: string;
|
||||
activationMessage?: string;
|
||||
|
|
|
@ -265,6 +265,7 @@ export function getSpecialNodeParameters(nodeType: INodeType): INodeProperties[]
|
|||
export function displayParameter(
|
||||
nodeValues: INodeParameters,
|
||||
parameter: INodeProperties | INodeCredentialDescription,
|
||||
node: INode | null, // Allow null as it does also get used by credentials and they do not have versioning yet
|
||||
nodeValuesRoot?: INodeParameters,
|
||||
) {
|
||||
if (!parameter.displayOptions) {
|
||||
|
@ -282,6 +283,8 @@ export function displayParameter(
|
|||
if (propertyName.charAt(0) === '/') {
|
||||
// Get the value from the root of the node
|
||||
value = get(nodeValuesRoot, propertyName.slice(1));
|
||||
} else if (propertyName === '@version') {
|
||||
value = node?.typeVersion || 0;
|
||||
} else {
|
||||
// Get the value from current level
|
||||
value = get(nodeValues, propertyName);
|
||||
|
@ -313,6 +316,8 @@ export function displayParameter(
|
|||
if (propertyName.charAt(0) === '/') {
|
||||
// Get the value from the root of the node
|
||||
value = get(nodeValuesRoot, propertyName.slice(1));
|
||||
} else if (propertyName === '@version') {
|
||||
value = node?.typeVersion || 0;
|
||||
} else {
|
||||
// Get the value from current level
|
||||
value = get(nodeValues, propertyName);
|
||||
|
@ -352,6 +357,7 @@ export function displayParameterPath(
|
|||
nodeValues: INodeParameters,
|
||||
parameter: INodeProperties | INodeCredentialDescription,
|
||||
path: string,
|
||||
node: INode | null,
|
||||
) {
|
||||
let resolvedNodeValues = nodeValues;
|
||||
if (path !== '') {
|
||||
|
@ -364,7 +370,7 @@ export function displayParameterPath(
|
|||
nodeValuesRoot = get(nodeValues, 'parameters') as INodeParameters;
|
||||
}
|
||||
|
||||
return displayParameter(resolvedNodeValues, parameter, nodeValuesRoot);
|
||||
return displayParameter(resolvedNodeValues, parameter, node, nodeValuesRoot);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -433,6 +439,10 @@ export function getParamterDependencies(
|
|||
// @ts-ignore
|
||||
for (parameterName of Object.keys(nodeProperties.displayOptions[displayRule])) {
|
||||
if (!dependencies[nodeProperties.name].includes(parameterName)) {
|
||||
if (parameterName.charAt(0) === '@') {
|
||||
// Is a special parameter so can be skipped
|
||||
continue;
|
||||
}
|
||||
dependencies[nodeProperties.name].push(parameterName);
|
||||
}
|
||||
}
|
||||
|
@ -532,6 +542,7 @@ export function getNodeParameters(
|
|||
nodeValues: INodeParameters,
|
||||
returnDefaults: boolean,
|
||||
returnNoneDisplayed: boolean,
|
||||
node: INode | null,
|
||||
onlySimpleTypes = false,
|
||||
dataIsResolved = false,
|
||||
nodeValuesRoot?: INodeParameters,
|
||||
|
@ -566,6 +577,7 @@ export function getNodeParameters(
|
|||
nodeValues,
|
||||
true,
|
||||
true,
|
||||
node,
|
||||
true,
|
||||
true,
|
||||
nodeValuesRoot,
|
||||
|
@ -594,7 +606,7 @@ export function getNodeParameters(
|
|||
|
||||
if (
|
||||
!returnNoneDisplayed &&
|
||||
!displayParameter(nodeValuesDisplayCheck, nodeProperties, nodeValuesRoot)
|
||||
!displayParameter(nodeValuesDisplayCheck, nodeProperties, node, nodeValuesRoot)
|
||||
) {
|
||||
if (!returnNoneDisplayed || !returnDefaults) {
|
||||
continue;
|
||||
|
@ -605,7 +617,7 @@ export function getNodeParameters(
|
|||
// Is a simple property so can be set as it is
|
||||
|
||||
if (duplicateParameterNames.includes(nodeProperties.name)) {
|
||||
if (!displayParameter(nodeValuesDisplayCheck, nodeProperties, nodeValuesRoot)) {
|
||||
if (!displayParameter(nodeValuesDisplayCheck, nodeProperties, node, nodeValuesRoot)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -677,6 +689,7 @@ export function getNodeParameters(
|
|||
nodeValues[nodeProperties.name] as INodeParameters,
|
||||
returnDefaults,
|
||||
returnNoneDisplayed,
|
||||
node,
|
||||
false,
|
||||
false,
|
||||
nodeValuesRoot,
|
||||
|
@ -737,6 +750,7 @@ export function getNodeParameters(
|
|||
nodeValue,
|
||||
returnDefaults,
|
||||
returnNoneDisplayed,
|
||||
node,
|
||||
false,
|
||||
false,
|
||||
nodeValuesRoot,
|
||||
|
@ -764,6 +778,7 @@ export function getNodeParameters(
|
|||
(nodeValues[nodeProperties.name] as INodeParameters)[itemName] as INodeParameters,
|
||||
returnDefaults,
|
||||
returnNoneDisplayed,
|
||||
node,
|
||||
false,
|
||||
false,
|
||||
nodeValuesRoot,
|
||||
|
@ -1021,7 +1036,7 @@ export function getNodeParametersIssues(
|
|||
}
|
||||
|
||||
for (const nodeProperty of nodePropertiesArray) {
|
||||
propertyIssues = getParameterIssues(nodeProperty, node.parameters, '');
|
||||
propertyIssues = getParameterIssues(nodeProperty, node.parameters, '', node);
|
||||
mergeIssues(foundIssues, propertyIssues);
|
||||
}
|
||||
|
||||
|
@ -1135,12 +1150,13 @@ export function getParameterIssues(
|
|||
nodeProperties: INodeProperties,
|
||||
nodeValues: INodeParameters,
|
||||
path: string,
|
||||
node: INode,
|
||||
): INodeIssues {
|
||||
const foundIssues: INodeIssues = {};
|
||||
let value;
|
||||
|
||||
if (nodeProperties.required === true) {
|
||||
if (displayParameterPath(nodeValues, nodeProperties, path)) {
|
||||
if (displayParameterPath(nodeValues, nodeProperties, path, node)) {
|
||||
value = getParameterValueByPath(nodeValues, nodeProperties.name, path);
|
||||
|
||||
if (
|
||||
|
@ -1235,7 +1251,7 @@ export function getParameterIssues(
|
|||
let propertyIssues;
|
||||
|
||||
for (const optionData of checkChildNodeProperties) {
|
||||
propertyIssues = getParameterIssues(optionData.data, nodeValues, optionData.basePath);
|
||||
propertyIssues = getParameterIssues(optionData.data, nodeValues, optionData.basePath, node);
|
||||
mergeIssues(foundIssues, propertyIssues);
|
||||
}
|
||||
|
||||
|
|
|
@ -586,7 +586,14 @@ export class RoutingNode {
|
|||
};
|
||||
let basePath = path ? `${path}.` : '';
|
||||
|
||||
if (!NodeHelpers.displayParameter(this.node.parameters, nodeProperties, this.node.parameters)) {
|
||||
if (
|
||||
!NodeHelpers.displayParameter(
|
||||
this.node.parameters,
|
||||
nodeProperties,
|
||||
this.node,
|
||||
this.node.parameters,
|
||||
)
|
||||
) {
|
||||
return undefined;
|
||||
}
|
||||
if (nodeProperties.routing) {
|
||||
|
|
|
@ -110,6 +110,7 @@ export class Workflow {
|
|||
node.parameters,
|
||||
true,
|
||||
false,
|
||||
node,
|
||||
);
|
||||
node.parameters = nodeParameters !== null ? nodeParameters : {};
|
||||
}
|
||||
|
|
|
@ -3018,6 +3018,7 @@ describe('Workflow', () => {
|
|||
testData.input.nodeValues,
|
||||
false,
|
||||
false,
|
||||
null,
|
||||
);
|
||||
expect(result).toEqual(testData.output.noneDisplayedFalse.defaultsFalse);
|
||||
|
||||
|
@ -3027,6 +3028,7 @@ describe('Workflow', () => {
|
|||
testData.input.nodeValues,
|
||||
true,
|
||||
false,
|
||||
null,
|
||||
);
|
||||
expect(result).toEqual(testData.output.noneDisplayedFalse.defaultsTrue);
|
||||
|
||||
|
@ -3036,6 +3038,7 @@ describe('Workflow', () => {
|
|||
testData.input.nodeValues,
|
||||
false,
|
||||
true,
|
||||
null,
|
||||
);
|
||||
expect(result).toEqual(testData.output.noneDisplayedTrue.defaultsFalse);
|
||||
|
||||
|
@ -3045,6 +3048,7 @@ describe('Workflow', () => {
|
|||
testData.input.nodeValues,
|
||||
true,
|
||||
true,
|
||||
null,
|
||||
);
|
||||
expect(result).toEqual(testData.output.noneDisplayedTrue.defaultsTrue);
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue