mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-25 04:34:06 -08:00
fix(core): Revert custom API option injecting (#5345)
Revert "feat(core): Fix populating of node custom api call options (#5303)"
This reverts commit e58bc41d24
.
This commit is contained in:
parent
b5154d9be5
commit
616074158c
|
@ -87,16 +87,4 @@ describe('NDV', () => {
|
|||
cy.get('[class*=hasIssues]').should('have.length', 1);
|
||||
});
|
||||
});
|
||||
|
||||
it('should show http node hint if node has custom api option', () => {
|
||||
workflowPage.actions.addNodeToCanvas('Manual Trigger');
|
||||
workflowPage.actions.addNodeToCanvas('Slack', true, true);
|
||||
ndv.getters.httpRequestNotice().should('not.exist');
|
||||
ndv.getters.parameterInput('operation').click();
|
||||
ndv.getters.parameterInput('operation').contains('Custom API').click();
|
||||
ndv.getters.httpRequestNotice().should('be.visible');
|
||||
ndv.getters.parameterInput('operation').click();
|
||||
ndv.getters.parameterInput('operation').contains('Post').click();
|
||||
ndv.getters.httpRequestNotice().should('not.exist');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -27,7 +27,6 @@ export class NDV extends BasePage {
|
|||
parameterInput: (parameterName: string) => cy.getByTestId(`parameter-input-${parameterName}`),
|
||||
nodeNameContainer: () => cy.getByTestId('node-title-container'),
|
||||
nodeRenameInput: () => cy.getByTestId('node-rename-input'),
|
||||
httpRequestNotice: () => cy.getByTestId('node-parameters-http-notice'),
|
||||
};
|
||||
|
||||
actions = {
|
||||
|
|
|
@ -2,13 +2,69 @@ import express from 'express';
|
|||
import { readFile } from 'fs/promises';
|
||||
import get from 'lodash.get';
|
||||
|
||||
import type { INodeTypeDescription, INodeTypeNameVersion } from 'n8n-workflow';
|
||||
import type { ICredentialType, 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
|
||||
|
@ -22,7 +78,7 @@ nodeTypesController.post(
|
|||
if (defaultLocale === 'en') {
|
||||
return nodeInfos.reduce<INodeTypeDescription[]>((acc, { name, version }) => {
|
||||
const { description } = NodeTypes().getByNameAndVersion(name, version);
|
||||
acc.push(description);
|
||||
acc.push(injectCustomApiCallOption(description));
|
||||
return acc;
|
||||
}, []);
|
||||
}
|
||||
|
@ -47,7 +103,7 @@ nodeTypesController.post(
|
|||
// ignore - no translation exists at path
|
||||
}
|
||||
|
||||
nodeTypes.push(description);
|
||||
nodeTypes.push(injectCustomApiCallOption(description));
|
||||
}
|
||||
|
||||
const nodeTypes: INodeTypeDescription[] = [];
|
||||
|
|
|
@ -11,8 +11,6 @@ export const PLACEHOLDER_EMPTY_EXECUTION_ID = '__UNKNOWN__';
|
|||
export const PLACEHOLDER_EMPTY_WORKFLOW_ID = '__EMPTY__';
|
||||
export const TUNNEL_SUBDOMAIN_ENV = 'N8N_TUNNEL_SUBDOMAIN';
|
||||
export const WAIT_TIME_UNLIMITED = '3000-01-01T00:00:00.000Z';
|
||||
export const CUSTOM_API_CALL_NAME = 'Custom API Call';
|
||||
export const CUSTOM_API_CALL_KEY = '__CUSTOM_API_CALL__';
|
||||
|
||||
export const RESPONSE_ERROR_MESSAGES = {
|
||||
NO_ENCRYPTION_KEY: 'Encryption key is missing or was not set',
|
||||
|
|
|
@ -15,7 +15,7 @@ import type {
|
|||
IVersionedNodeType,
|
||||
KnownNodesAndCredentials,
|
||||
} from 'n8n-workflow';
|
||||
import { CUSTOM_NODES_CATEGORY, CUSTOM_API_CALL_KEY, CUSTOM_API_CALL_NAME } from './Constants';
|
||||
import { CUSTOM_NODES_CATEGORY } from './Constants';
|
||||
import type { n8n } from './Interfaces';
|
||||
import { loadClassInIsolation } from './ClassLoader';
|
||||
|
||||
|
@ -54,48 +54,6 @@ export abstract class DirectoryLoader {
|
|||
return path.resolve(this.directory, file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether any of the node's credential types may be used to
|
||||
* make a request from a node other than itself.
|
||||
*/
|
||||
private supportsProxyAuth(description: INodeTypeDescription) {
|
||||
if (!description.credentials) return false;
|
||||
|
||||
return description.credentials.some(({ name }) => {
|
||||
const credType = this.credentialTypes[name].type;
|
||||
|
||||
if (credType.authenticate !== undefined) return true;
|
||||
|
||||
return (
|
||||
Array.isArray(credType.extends) &&
|
||||
credType.extends.some((parentType) =>
|
||||
['oAuth2Api', 'googleOAuth2Api', 'oAuth1Api'].includes(parentType),
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject a `Custom API Call` option into `resource` and `operation`
|
||||
* parameters in a node that supports proxy auth.
|
||||
*/
|
||||
private injectCustomApiCallOption(description: INodeTypeDescription) {
|
||||
if (!this.supportsProxyAuth(description)) return;
|
||||
|
||||
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,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected loadNodeFromFile(packageName: string, nodeName: string, filePath: string) {
|
||||
let tempNode: INodeType | IVersionedNodeType;
|
||||
let nodeVersion = 1;
|
||||
|
@ -131,7 +89,6 @@ export abstract class DirectoryLoader {
|
|||
|
||||
const currentVersionNode = tempNode.nodeVersions[tempNode.currentVersion];
|
||||
this.addCodex({ node: currentVersionNode, filePath, isCustom: packageName === 'CUSTOM' });
|
||||
this.injectCustomApiCallOption(currentVersionNode.description);
|
||||
nodeVersion = tempNode.currentVersion;
|
||||
|
||||
if (currentVersionNode.hasOwnProperty('executeSingle')) {
|
||||
|
@ -142,11 +99,10 @@ export abstract class DirectoryLoader {
|
|||
}
|
||||
} else {
|
||||
// Short renaming to avoid type issues
|
||||
|
||||
this.injectCustomApiCallOption(tempNode.description);
|
||||
nodeVersion = Array.isArray(tempNode.description.version)
|
||||
? tempNode.description.version.slice(-1)[0]
|
||||
: tempNode.description.version;
|
||||
const tmpNode = tempNode;
|
||||
nodeVersion = Array.isArray(tmpNode.description.version)
|
||||
? tmpNode.description.version.slice(-1)[0]
|
||||
: tmpNode.description.version;
|
||||
}
|
||||
|
||||
this.known.nodes[fullNodeName] = {
|
||||
|
|
|
@ -233,7 +233,7 @@ const telemetry = instance?.proxy.$telemetry;
|
|||
const { categorizedItems: allNodes, isTriggerNode } = useNodeTypesStore();
|
||||
const containsAPIAction = computed(
|
||||
() =>
|
||||
activeNodeActions.value?.properties.some((p) =>
|
||||
state.latestNodeData?.properties.some((p) =>
|
||||
p.options?.find((o) => o.name === CUSTOM_API_CALL_NAME),
|
||||
) === true,
|
||||
);
|
||||
|
@ -338,10 +338,27 @@ function getCustomAPICallHintLocale(key: string) {
|
|||
interpolate: { nodeNameTitle },
|
||||
});
|
||||
}
|
||||
// The nodes.json doesn't contain API CALL option so we need to fetch the node detail
|
||||
// to determine if need to render the API CALL hint
|
||||
async function fetchNodeDetails() {
|
||||
if (!state.activeNodeActions) return;
|
||||
|
||||
const { getNodesInformation } = useNodeTypesStore();
|
||||
const { version, name } = state.activeNodeActions;
|
||||
const payload = {
|
||||
name,
|
||||
version: Array.isArray(version) ? version?.slice(-1)[0] : version,
|
||||
} as INodeTypeNameVersion;
|
||||
|
||||
const nodesInfo = await getNodesInformation([payload], false);
|
||||
|
||||
state.latestNodeData = nodesInfo[0];
|
||||
}
|
||||
|
||||
function setActiveActionsNodeType(nodeType: INodeTypeDescription | null) {
|
||||
state.activeNodeActions = nodeType;
|
||||
setShowTabs(false);
|
||||
fetchNodeDetails();
|
||||
|
||||
if (nodeType) trackActionsView();
|
||||
}
|
||||
|
|
|
@ -116,11 +116,7 @@
|
|||
</n8n-text>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="isCustomApiCallSelected(nodeValues)"
|
||||
class="parameter-item parameter-notice"
|
||||
data-test-id="node-parameters-http-notice"
|
||||
>
|
||||
<div v-if="isCustomApiCallSelected(nodeValues)" class="parameter-item parameter-notice">
|
||||
<n8n-notice
|
||||
:content="
|
||||
$locale.baseText('nodeSettings.useTheHttpRequestNode', {
|
||||
|
|
|
@ -56,12 +56,9 @@ const customNodeActionsParsers: {
|
|||
},
|
||||
};
|
||||
|
||||
function filterActions(actions: INodeActionTypeDescription[]) {
|
||||
function filterSinglePlaceholderAction(actions: INodeActionTypeDescription[]) {
|
||||
return actions.filter(
|
||||
(action: INodeActionTypeDescription, _: number, arr: INodeActionTypeDescription[]) => {
|
||||
const isApiCall = action.actionKey === CUSTOM_API_CALL_KEY;
|
||||
if (isApiCall) return false;
|
||||
|
||||
const isPlaceholderTriggerAction = action.actionKey === PLACEHOLDER_RECOMMENDED_ACTION_KEY;
|
||||
return !isPlaceholderTriggerAction || (isPlaceholderTriggerAction && arr.length > 1);
|
||||
},
|
||||
|
@ -342,7 +339,7 @@ export const useNodeCreatorStore = defineStore(STORES.NODE_CREATOR, {
|
|||
|
||||
const filteredNodes = Object.values(mergedNodes).map((node) => ({
|
||||
...node,
|
||||
actions: filterActions(node.actions || []),
|
||||
actions: filterSinglePlaceholderAction(node.actions || []),
|
||||
}));
|
||||
|
||||
return filteredNodes;
|
||||
|
|
Loading…
Reference in a new issue