fix(core): Fix populating of node custom api call options (#5347)
* feat(core): Fix populating of node custom api call options * lint fixes * Adress PR comments * Add e2e test and only inject custom API options for latest version * Make sure to injectCustomApiCallOption for the latest version of node * feat(cli): Move apiCallOption injection to LoadNodesAndCredentials and add e2e tests to check for custom nodes credentials * Load nodes and credentials fixtures from a single place * Console warning if credential is invalid during customApiOptions injection
This commit is contained in:
@@ -2,69 +2,13 @@ import express from 'express';
|
||||
import { readFile } from 'fs/promises';
|
||||
import get from 'lodash.get';
|
||||
|
||||
import type { ICredentialType, INodeTypeDescription, INodeTypeNameVersion } from 'n8n-workflow';
|
||||
import type { INodeTypeDescription, INodeTypeNameVersion } from 'n8n-workflow';
|
||||
|
||||
import { CredentialTypes } from '@/CredentialTypes';
|
||||
import config from '@/config';
|
||||
import { NodeTypes } from '@/NodeTypes';
|
||||
import * as ResponseHelper from '@/ResponseHelper';
|
||||
import { getNodeTranslationPath } from '@/TranslationHelpers';
|
||||
|
||||
function isOAuth(credType: ICredentialType) {
|
||||
return (
|
||||
Array.isArray(credType.extends) &&
|
||||
credType.extends.some((parentType) =>
|
||||
['oAuth2Api', 'googleOAuth2Api', 'oAuth1Api'].includes(parentType),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether any of the node's credential types may be used to
|
||||
* make a request from a node other than itself.
|
||||
*/
|
||||
function supportsProxyAuth(description: INodeTypeDescription) {
|
||||
if (!description.credentials) return false;
|
||||
|
||||
const credentialTypes = CredentialTypes();
|
||||
|
||||
return description.credentials.some(({ name }) => {
|
||||
const credType = credentialTypes.getByName(name);
|
||||
|
||||
if (credType.authenticate !== undefined) return true;
|
||||
|
||||
return isOAuth(credType);
|
||||
});
|
||||
}
|
||||
|
||||
const CUSTOM_API_CALL_NAME = 'Custom API Call';
|
||||
const CUSTOM_API_CALL_KEY = '__CUSTOM_API_CALL__';
|
||||
|
||||
/**
|
||||
* Inject a `Custom API Call` option into `resource` and `operation`
|
||||
* parameters in a node that supports proxy auth.
|
||||
*/
|
||||
function injectCustomApiCallOption(description: INodeTypeDescription) {
|
||||
if (!supportsProxyAuth(description)) return description;
|
||||
|
||||
description.properties.forEach((p) => {
|
||||
if (
|
||||
['resource', 'operation'].includes(p.name) &&
|
||||
Array.isArray(p.options) &&
|
||||
p.options[p.options.length - 1].name !== CUSTOM_API_CALL_NAME
|
||||
) {
|
||||
p.options.push({
|
||||
name: CUSTOM_API_CALL_NAME,
|
||||
value: CUSTOM_API_CALL_KEY,
|
||||
});
|
||||
}
|
||||
|
||||
return p;
|
||||
});
|
||||
|
||||
return description;
|
||||
}
|
||||
|
||||
export const nodeTypesController = express.Router();
|
||||
|
||||
// Returns node information based on node names and versions
|
||||
@@ -78,7 +22,7 @@ nodeTypesController.post(
|
||||
if (defaultLocale === 'en') {
|
||||
return nodeInfos.reduce<INodeTypeDescription[]>((acc, { name, version }) => {
|
||||
const { description } = NodeTypes().getByNameAndVersion(name, version);
|
||||
acc.push(injectCustomApiCallOption(description));
|
||||
acc.push(description);
|
||||
return acc;
|
||||
}, []);
|
||||
}
|
||||
@@ -103,7 +47,7 @@ nodeTypesController.post(
|
||||
// ignore - no translation exists at path
|
||||
}
|
||||
|
||||
nodeTypes.push(injectCustomApiCallOption(description));
|
||||
nodeTypes.push(description);
|
||||
}
|
||||
|
||||
const nodeTypes: INodeTypeDescription[] = [];
|
||||
|
||||
Reference in New Issue
Block a user