Add expression support to credentials

This commit is contained in:
Jan Oberhauser 2021-01-24 13:33:57 +01:00
parent b33a5fcd13
commit 1dedb3f4b8
6 changed files with 56 additions and 27 deletions

View file

@ -4,6 +4,7 @@ import {
import {
ICredentialDataDecryptedObject,
ICredentialsExpressionResolveValues,
ICredentialsHelper,
INode,
INodeParameters,
@ -100,7 +101,7 @@ export class CredentialsHelper extends ICredentialsHelper {
* @returns {ICredentialDataDecryptedObject}
* @memberof CredentialsHelper
*/
getDecrypted(name: string, type: string, raw?: boolean): ICredentialDataDecryptedObject {
getDecrypted(name: string, type: string, raw?: boolean, expressionResolveValues?: ICredentialsExpressionResolveValues): ICredentialDataDecryptedObject {
const credentials = this.getCredentials(name, type);
const decryptedDataOriginal = credentials.getData(this.encryptionKey);
@ -109,7 +110,7 @@ export class CredentialsHelper extends ICredentialsHelper {
return decryptedDataOriginal;
}
return this.applyDefaultsAndOverwrites(decryptedDataOriginal, type);
return this.applyDefaultsAndOverwrites(decryptedDataOriginal, type, expressionResolveValues);
}
@ -121,7 +122,7 @@ export class CredentialsHelper extends ICredentialsHelper {
* @returns {ICredentialDataDecryptedObject}
* @memberof CredentialsHelper
*/
applyDefaultsAndOverwrites(decryptedDataOriginal: ICredentialDataDecryptedObject, type: string): ICredentialDataDecryptedObject {
applyDefaultsAndOverwrites(decryptedDataOriginal: ICredentialDataDecryptedObject, type: string, expressionResolveValues?: ICredentialsExpressionResolveValues): ICredentialDataDecryptedObject {
const credentialsProperties = this.getCredentialsProperties(type);
// Add the default credential values
@ -133,17 +134,27 @@ export class CredentialsHelper extends ICredentialsHelper {
decryptedData.oauthTokenData = decryptedDataOriginal.oauthTokenData;
}
const mockNode: INode = {
name: '',
typeVersion: 1,
type: 'mock',
position: [0, 0],
parameters: decryptedData as INodeParameters,
};
if (expressionResolveValues) {
try {
decryptedData = expressionResolveValues.workflow.expression.getParameterValue(decryptedData as INodeParameters, expressionResolveValues.runExecutionData, expressionResolveValues.runIndex, expressionResolveValues.itemIndex, expressionResolveValues.node.name, expressionResolveValues.connectionInputData) as ICredentialDataDecryptedObject;
} catch (e) {
e.message += ' [Error resolving credentials]';
throw e;
}
} else {
const node = {
name: '',
typeVersion: 1,
type: 'mock',
position: [0, 0],
parameters: decryptedData as INodeParameters,
} as INode;
const workflow = new Workflow({ nodes: [mockNode], connections: {}, active: false, nodeTypes: mockNodeTypes});
// Resolve expressions if any are set
decryptedData = workflow.expression.getComplexParameterValue(mockNode, decryptedData as INodeParameters, undefined) as ICredentialDataDecryptedObject;
const workflow = new Workflow({ nodes: [node!], connections: {}, active: false, nodeTypes: mockNodeTypes });
// Resolve expressions if any are set
decryptedData = workflow.expression.getComplexParameterValue(node!, decryptedData as INodeParameters, undefined) as ICredentialDataDecryptedObject;
}
// Load and apply the credentials overwrites if any exist
const credentialsOverwrites = CredentialsOverwrites();

View file

@ -11,6 +11,7 @@ import {
IBinaryData,
IContextObject,
ICredentialDataDecryptedObject,
ICredentialsExpressionResolveValues,
IDataObject,
IExecuteFunctions,
IExecuteSingleFunctions,
@ -298,7 +299,7 @@ export function returnJsonArray(jsonData: IDataObject | IDataObject[]): INodeExe
* @param {IWorkflowExecuteAdditionalData} additionalData
* @returns {(ICredentialDataDecryptedObject | undefined)}
*/
export function getCredentials(workflow: Workflow, node: INode, type: string, additionalData: IWorkflowExecuteAdditionalData): ICredentialDataDecryptedObject | undefined {
export function getCredentials(workflow: Workflow, node: INode, type: string, additionalData: IWorkflowExecuteAdditionalData, runExecutionData?: IRunExecutionData | null, runIndex?: number, connectionInputData?: INodeExecutionData[], itemIndex?: number): ICredentialDataDecryptedObject | undefined {
// Get the NodeType as it has the information if the credentials are required
const nodeType = workflow.nodeTypes.getByName(node.type);
@ -338,9 +339,21 @@ export function getCredentials(workflow: Workflow, node: INode, type: string, ad
}
}
let expressionResolveValues: ICredentialsExpressionResolveValues | undefined;
if (connectionInputData && runExecutionData && runIndex !== undefined) {
expressionResolveValues = {
connectionInputData,
itemIndex: itemIndex || 0,
node,
runExecutionData,
runIndex,
workflow,
} as ICredentialsExpressionResolveValues;
}
const name = node.credentials[type];
const decryptedDataObject = additionalData.credentialsHelper.getDecrypted(name, type);
const decryptedDataObject = additionalData.credentialsHelper.getDecrypted(name, type, false, expressionResolveValues);
return decryptedDataObject;
}
@ -662,8 +675,8 @@ export function getExecuteFunctions(workflow: Workflow, runExecutionData: IRunEx
getContext(type: string): IContextObject {
return NodeHelpers.getContext(runExecutionData, type, node);
},
getCredentials(type: string): ICredentialDataDecryptedObject | undefined {
return getCredentials(workflow, node, type, additionalData);
getCredentials(type: string, itemIndex?: number): ICredentialDataDecryptedObject | undefined {
return getCredentials(workflow, node, type, additionalData, runExecutionData, runIndex, connectionInputData, itemIndex);
},
getInputData: (inputIndex = 0, inputName = 'main') => {
@ -758,7 +771,7 @@ export function getExecuteSingleFunctions(workflow: Workflow, runExecutionData:
return NodeHelpers.getContext(runExecutionData, type, node);
},
getCredentials(type: string): ICredentialDataDecryptedObject | undefined {
return getCredentials(workflow, node, type, additionalData);
return getCredentials(workflow, node, type, additionalData, runExecutionData, runIndex, connectionInputData, itemIndex);
},
getInputData: (inputIndex = 0, inputName = 'main') => {
if (!inputData.hasOwnProperty(inputName)) {

View file

@ -30,7 +30,7 @@
</el-tooltip>
</el-col>
<el-col :span="18">
<parameter-input :parameter="parameter" :value="propertyValue[parameter.name]" :path="parameter.name" :isCredential="true" @valueChanged="valueChanged" />
<parameter-input :parameter="parameter" :value="propertyValue[parameter.name]" :path="parameter.name" :isCredential="true" :displayOptions="true" @valueChanged="valueChanged" />
</el-col>
</el-row>
</div>

View file

@ -1,6 +1,6 @@
<template>
<div v-if="credentialTypesNodeDescriptionDisplayed.length" class="node-credentials">
<credentials-edit :dialogVisible="credentialNewDialogVisible" :editCredentials="editCredentials" :setCredentialType="addType" :nodesInit="nodesInit" @closeDialog="closeCredentialNewDialog" @credentialsCreated="credentialsCreated" @credentialsUpdated="credentialsUpdated"></credentials-edit>
<credentials-edit :dialogVisible="credentialNewDialogVisible" :editCredentials="editCredentials" :setCredentialType="addType" :nodesInit="nodesInit" :node="node" @closeDialog="closeCredentialNewDialog" @credentialsCreated="credentialsCreated" @credentialsUpdated="credentialsUpdated"></credentials-edit>
<div class="headline">
Credentials

View file

@ -240,10 +240,6 @@ export default mixins(
return returnValues.join('|');
},
node (): INodeUi | null {
if (this.isCredential === true) {
return null;
}
return this.$store.getters.activeNode;
},
displayTitle (): string {
@ -314,7 +310,7 @@ export default mixins(
return false;
},
expressionValueComputed (): NodeParameterValue | null {
if (this.isCredential === true || this.node === null) {
if (this.node === null) {
return null;
}

View file

@ -84,6 +84,15 @@ export interface ICredentialsEncrypted {
data?: string;
}
export interface ICredentialsExpressionResolveValues {
connectionInputData: INodeExecutionData[];
itemIndex: number;
node: INode;
runExecutionData: IRunExecutionData | null;
runIndex: number;
workflow: Workflow;
}
export abstract class ICredentialsHelper {
encryptionKey: string;
workflowCredentials: IWorkflowCredentials;
@ -94,7 +103,7 @@ export abstract class ICredentialsHelper {
}
abstract getCredentials(name: string, type: string): ICredentials;
abstract getDecrypted(name: string, type: string): ICredentialDataDecryptedObject;
abstract getDecrypted(name: string, type: string, raw?: boolean, expressionResolveValues?: ICredentialsExpressionResolveValues): ICredentialDataDecryptedObject;
abstract updateCredentials(name: string, type: string, data: ICredentialDataDecryptedObject): Promise<void>;
}
@ -203,7 +212,7 @@ export interface IExecuteFunctions {
evaluateExpression(expression: string, itemIndex: number): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[];
executeWorkflow(workflowInfo: IExecuteWorkflowInfo, inputData?: INodeExecutionData[]): Promise<any>; // tslint:disable-line:no-any
getContext(type: string): IContextObject;
getCredentials(type: string): ICredentialDataDecryptedObject | undefined;
getCredentials(type: string, itemIndex?: number): ICredentialDataDecryptedObject | undefined;
getInputData(inputIndex?: number, inputName?: string): INodeExecutionData[];
getMode(): WorkflowExecuteMode;
getNode(): INode;