mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
fix(editor): Resolve $vars
and $secrets
in expressions in credentials fields (#9289)
This commit is contained in:
parent
6ab3781570
commit
d92f994913
|
@ -202,14 +202,18 @@ export default defineComponent({
|
||||||
? this.modelValue.value
|
? this.modelValue.value
|
||||||
: this.modelValue;
|
: this.modelValue;
|
||||||
|
|
||||||
if (!this.activeNode || !this.isValueExpression || typeof value !== 'string') {
|
if (
|
||||||
|
!this.isForCredential &&
|
||||||
|
(!this.activeNode || !this.isValueExpression || typeof value !== 'string')
|
||||||
|
) {
|
||||||
return { ok: false, error: new Error() };
|
return { ok: false, error: new Error() };
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let opts;
|
let opts = { isForCredential: this.isForCredential };
|
||||||
if (this.ndvStore.isInputParentOfActiveNode) {
|
if (this.ndvStore.isInputParentOfActiveNode) {
|
||||||
opts = {
|
opts = {
|
||||||
|
...opts,
|
||||||
targetItem: this.targetItem ?? undefined,
|
targetItem: this.targetItem ?? undefined,
|
||||||
inputNodeName: this.ndvStore.ndvInputNodeName,
|
inputNodeName: this.ndvStore.ndvInputNodeName,
|
||||||
inputRunIndex: this.ndvStore.ndvInputRunIndex,
|
inputRunIndex: this.ndvStore.ndvInputRunIndex,
|
||||||
|
|
|
@ -82,16 +82,51 @@ export function resolveParameter(
|
||||||
inputRunIndex?: number;
|
inputRunIndex?: number;
|
||||||
inputBranchIndex?: number;
|
inputBranchIndex?: number;
|
||||||
additionalKeys?: IWorkflowDataProxyAdditionalKeys;
|
additionalKeys?: IWorkflowDataProxyAdditionalKeys;
|
||||||
|
isForCredential?: boolean;
|
||||||
} = {},
|
} = {},
|
||||||
): IDataObject | null {
|
): IDataObject | null {
|
||||||
let itemIndex = opts?.targetItem?.itemIndex || 0;
|
let itemIndex = opts?.targetItem?.itemIndex || 0;
|
||||||
|
|
||||||
|
const workflow = getCurrentWorkflow();
|
||||||
|
|
||||||
|
const additionalKeys: IWorkflowDataProxyAdditionalKeys = {
|
||||||
|
$execution: {
|
||||||
|
id: PLACEHOLDER_FILLED_AT_EXECUTION_TIME,
|
||||||
|
mode: 'test',
|
||||||
|
resumeUrl: PLACEHOLDER_FILLED_AT_EXECUTION_TIME,
|
||||||
|
resumeFormUrl: PLACEHOLDER_FILLED_AT_EXECUTION_TIME,
|
||||||
|
},
|
||||||
|
$vars: useEnvironmentsStore().variablesAsObject,
|
||||||
|
|
||||||
|
// deprecated
|
||||||
|
$executionId: PLACEHOLDER_FILLED_AT_EXECUTION_TIME,
|
||||||
|
$resumeWebhookUrl: PLACEHOLDER_FILLED_AT_EXECUTION_TIME,
|
||||||
|
|
||||||
|
...opts.additionalKeys,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (opts.isForCredential) {
|
||||||
|
// node-less expression resolution
|
||||||
|
return workflow.expression.getParameterValue(
|
||||||
|
parameter,
|
||||||
|
null,
|
||||||
|
0,
|
||||||
|
itemIndex,
|
||||||
|
'',
|
||||||
|
[],
|
||||||
|
'manual',
|
||||||
|
additionalKeys,
|
||||||
|
undefined,
|
||||||
|
false,
|
||||||
|
undefined,
|
||||||
|
'',
|
||||||
|
) as IDataObject;
|
||||||
|
}
|
||||||
|
|
||||||
const inputName = NodeConnectionType.Main;
|
const inputName = NodeConnectionType.Main;
|
||||||
const activeNode = useNDVStore().activeNode;
|
const activeNode = useNDVStore().activeNode;
|
||||||
let contextNode = activeNode;
|
let contextNode = activeNode;
|
||||||
|
|
||||||
const workflow = getCurrentWorkflow();
|
|
||||||
|
|
||||||
if (activeNode) {
|
if (activeNode) {
|
||||||
contextNode = workflow.getParentMainInputNode(activeNode);
|
contextNode = workflow.getParentMainInputNode(activeNode);
|
||||||
}
|
}
|
||||||
|
@ -159,22 +194,6 @@ export function resolveParameter(
|
||||||
_connectionInputData = [];
|
_connectionInputData = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const additionalKeys: IWorkflowDataProxyAdditionalKeys = {
|
|
||||||
$execution: {
|
|
||||||
id: PLACEHOLDER_FILLED_AT_EXECUTION_TIME,
|
|
||||||
mode: 'test',
|
|
||||||
resumeUrl: PLACEHOLDER_FILLED_AT_EXECUTION_TIME,
|
|
||||||
resumeFormUrl: PLACEHOLDER_FILLED_AT_EXECUTION_TIME,
|
|
||||||
},
|
|
||||||
$vars: useEnvironmentsStore().variablesAsObject,
|
|
||||||
|
|
||||||
// deprecated
|
|
||||||
$executionId: PLACEHOLDER_FILLED_AT_EXECUTION_TIME,
|
|
||||||
$resumeWebhookUrl: PLACEHOLDER_FILLED_AT_EXECUTION_TIME,
|
|
||||||
|
|
||||||
...opts.additionalKeys,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (activeNode?.type === HTTP_REQUEST_NODE_TYPE) {
|
if (activeNode?.type === HTTP_REQUEST_NODE_TYPE) {
|
||||||
const EMPTY_RESPONSE = { statusCode: 200, headers: {}, body: {} };
|
const EMPTY_RESPONSE = { statusCode: 200, headers: {}, body: {} };
|
||||||
const EMPTY_REQUEST = { headers: {}, body: {}, qs: {} };
|
const EMPTY_REQUEST = { headers: {}, body: {}, qs: {} };
|
||||||
|
@ -793,6 +812,7 @@ export function useWorkflowHelpers(options: { router: ReturnType<typeof useRoute
|
||||||
inputBranchIndex?: number;
|
inputBranchIndex?: number;
|
||||||
c?: number;
|
c?: number;
|
||||||
additionalKeys?: IWorkflowDataProxyAdditionalKeys;
|
additionalKeys?: IWorkflowDataProxyAdditionalKeys;
|
||||||
|
isForCredential?: boolean;
|
||||||
} = {},
|
} = {},
|
||||||
stringifyObject = true,
|
stringifyObject = true,
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -50,7 +50,7 @@ import { defineComponent } from 'vue';
|
||||||
import ResourcesListLayout from '@/components/layouts/ResourcesListLayout.vue';
|
import ResourcesListLayout from '@/components/layouts/ResourcesListLayout.vue';
|
||||||
import CredentialCard from '@/components/CredentialCard.vue';
|
import CredentialCard from '@/components/CredentialCard.vue';
|
||||||
import type { ICredentialType } from 'n8n-workflow';
|
import type { ICredentialType } from 'n8n-workflow';
|
||||||
import { CREDENTIAL_SELECT_MODAL_KEY } from '@/constants';
|
import { CREDENTIAL_SELECT_MODAL_KEY, EnterpriseEditionFeature } from '@/constants';
|
||||||
import { mapStores } from 'pinia';
|
import { mapStores } from 'pinia';
|
||||||
import { useUIStore } from '@/stores/ui.store';
|
import { useUIStore } from '@/stores/ui.store';
|
||||||
import { useUsersStore } from '@/stores/users.store';
|
import { useUsersStore } from '@/stores/users.store';
|
||||||
|
@ -58,6 +58,8 @@ import { useNodeTypesStore } from '@/stores/nodeTypes.store';
|
||||||
import { useCredentialsStore } from '@/stores/credentials.store';
|
import { useCredentialsStore } from '@/stores/credentials.store';
|
||||||
import { useExternalSecretsStore } from '@/stores/externalSecrets.ee.store';
|
import { useExternalSecretsStore } from '@/stores/externalSecrets.ee.store';
|
||||||
import { useSourceControlStore } from '@/stores/sourceControl.store';
|
import { useSourceControlStore } from '@/stores/sourceControl.store';
|
||||||
|
import useEnvironmentsStore from '@/stores/environments.ee.store';
|
||||||
|
import { useSettingsStore } from '@/stores/settings.store';
|
||||||
|
|
||||||
type IResourcesListLayoutInstance = InstanceType<typeof ResourcesListLayout>;
|
type IResourcesListLayoutInstance = InstanceType<typeof ResourcesListLayout>;
|
||||||
|
|
||||||
|
@ -123,11 +125,16 @@ export default defineComponent({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
async initialize() {
|
async initialize() {
|
||||||
|
const isVarsEnabled = useSettingsStore().isEnterpriseFeatureEnabled(
|
||||||
|
EnterpriseEditionFeature.Variables,
|
||||||
|
);
|
||||||
|
|
||||||
const loadPromises = [
|
const loadPromises = [
|
||||||
this.credentialsStore.fetchAllCredentials(),
|
this.credentialsStore.fetchAllCredentials(),
|
||||||
this.credentialsStore.fetchCredentialTypes(false),
|
this.credentialsStore.fetchCredentialTypes(false),
|
||||||
this.externalSecretsStore.fetchAllSecrets(),
|
this.externalSecretsStore.fetchAllSecrets(),
|
||||||
this.nodeTypesStore.loadNodeTypesIfNotLoaded(),
|
this.nodeTypesStore.loadNodeTypesIfNotLoaded(),
|
||||||
|
isVarsEnabled ? useEnvironmentsStore().fetchAllVariables() : Promise.resolve(), // for expression resolution
|
||||||
];
|
];
|
||||||
|
|
||||||
await Promise.all(loadPromises);
|
await Promise.all(loadPromises);
|
||||||
|
|
|
@ -164,7 +164,9 @@ export class WorkflowDataProxy {
|
||||||
const that = this;
|
const that = this;
|
||||||
const node = this.workflow.nodes[nodeName];
|
const node = this.workflow.nodes[nodeName];
|
||||||
|
|
||||||
return new Proxy(node.parameters, {
|
// `node` is `undefined` only in expressions in credentials
|
||||||
|
|
||||||
|
return new Proxy(node?.parameters ?? {}, {
|
||||||
has: () => true,
|
has: () => true,
|
||||||
ownKeys(target) {
|
ownKeys(target) {
|
||||||
return Reflect.ownKeys(target);
|
return Reflect.ownKeys(target);
|
||||||
|
|
Loading…
Reference in a new issue