mirror of
https://github.com/n8n-io/n8n.git
synced 2025-01-12 13:27:31 -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;
|
||||
|
||||
if (!this.activeNode || !this.isValueExpression || typeof value !== 'string') {
|
||||
if (
|
||||
!this.isForCredential &&
|
||||
(!this.activeNode || !this.isValueExpression || typeof value !== 'string')
|
||||
) {
|
||||
return { ok: false, error: new Error() };
|
||||
}
|
||||
|
||||
try {
|
||||
let opts;
|
||||
let opts = { isForCredential: this.isForCredential };
|
||||
if (this.ndvStore.isInputParentOfActiveNode) {
|
||||
opts = {
|
||||
...opts,
|
||||
targetItem: this.targetItem ?? undefined,
|
||||
inputNodeName: this.ndvStore.ndvInputNodeName,
|
||||
inputRunIndex: this.ndvStore.ndvInputRunIndex,
|
||||
|
|
|
@ -82,16 +82,51 @@ export function resolveParameter(
|
|||
inputRunIndex?: number;
|
||||
inputBranchIndex?: number;
|
||||
additionalKeys?: IWorkflowDataProxyAdditionalKeys;
|
||||
isForCredential?: boolean;
|
||||
} = {},
|
||||
): IDataObject | null {
|
||||
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 activeNode = useNDVStore().activeNode;
|
||||
let contextNode = activeNode;
|
||||
|
||||
const workflow = getCurrentWorkflow();
|
||||
|
||||
if (activeNode) {
|
||||
contextNode = workflow.getParentMainInputNode(activeNode);
|
||||
}
|
||||
|
@ -159,22 +194,6 @@ export function resolveParameter(
|
|||
_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) {
|
||||
const EMPTY_RESPONSE = { statusCode: 200, headers: {}, body: {} };
|
||||
const EMPTY_REQUEST = { headers: {}, body: {}, qs: {} };
|
||||
|
@ -793,6 +812,7 @@ export function useWorkflowHelpers(options: { router: ReturnType<typeof useRoute
|
|||
inputBranchIndex?: number;
|
||||
c?: number;
|
||||
additionalKeys?: IWorkflowDataProxyAdditionalKeys;
|
||||
isForCredential?: boolean;
|
||||
} = {},
|
||||
stringifyObject = true,
|
||||
) {
|
||||
|
|
|
@ -50,7 +50,7 @@ import { defineComponent } from 'vue';
|
|||
import ResourcesListLayout from '@/components/layouts/ResourcesListLayout.vue';
|
||||
import CredentialCard from '@/components/CredentialCard.vue';
|
||||
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 { useUIStore } from '@/stores/ui.store';
|
||||
import { useUsersStore } from '@/stores/users.store';
|
||||
|
@ -58,6 +58,8 @@ import { useNodeTypesStore } from '@/stores/nodeTypes.store';
|
|||
import { useCredentialsStore } from '@/stores/credentials.store';
|
||||
import { useExternalSecretsStore } from '@/stores/externalSecrets.ee.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>;
|
||||
|
||||
|
@ -123,11 +125,16 @@ export default defineComponent({
|
|||
});
|
||||
},
|
||||
async initialize() {
|
||||
const isVarsEnabled = useSettingsStore().isEnterpriseFeatureEnabled(
|
||||
EnterpriseEditionFeature.Variables,
|
||||
);
|
||||
|
||||
const loadPromises = [
|
||||
this.credentialsStore.fetchAllCredentials(),
|
||||
this.credentialsStore.fetchCredentialTypes(false),
|
||||
this.externalSecretsStore.fetchAllSecrets(),
|
||||
this.nodeTypesStore.loadNodeTypesIfNotLoaded(),
|
||||
isVarsEnabled ? useEnvironmentsStore().fetchAllVariables() : Promise.resolve(), // for expression resolution
|
||||
];
|
||||
|
||||
await Promise.all(loadPromises);
|
||||
|
|
|
@ -164,7 +164,9 @@ export class WorkflowDataProxy {
|
|||
const that = this;
|
||||
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,
|
||||
ownKeys(target) {
|
||||
return Reflect.ownKeys(target);
|
||||
|
|
Loading…
Reference in a new issue