🔀 Merge branch 'master' of github.com:n8n-io/n8n

This commit is contained in:
Jan Oberhauser 2021-01-27 09:03:18 +01:00
commit 3f6d4b6c08
9 changed files with 42 additions and 26 deletions

View file

@ -137,10 +137,7 @@ export class CredentialsHelper extends ICredentialsHelper {
if (expressionResolveValues) {
try {
const workflow = new Workflow({ nodes: Object.values(expressionResolveValues.workflow.nodes), connections: expressionResolveValues.workflow.connectionsBySourceNode, active: false, nodeTypes: expressionResolveValues.workflow.nodeTypes });
// TODO: Find a better way for that!
// Add the credential data to the parameters of the node so that they can get accessed by expressions
Object.assign(workflow.nodes[expressionResolveValues.node.name].parameters, decryptedData);
decryptedData = workflow.expression.getParameterValue(decryptedData as INodeParameters, expressionResolveValues.runExecutionData, expressionResolveValues.runIndex, expressionResolveValues.itemIndex, expressionResolveValues.node.name, expressionResolveValues.connectionInputData) as ICredentialDataDecryptedObject;
decryptedData = workflow.expression.getParameterValue(decryptedData as INodeParameters, expressionResolveValues.runExecutionData, expressionResolveValues.runIndex, expressionResolveValues.itemIndex, expressionResolveValues.node.name, expressionResolveValues.connectionInputData, false, decryptedData) as ICredentialDataDecryptedObject;
} catch (e) {
e.message += ' [Error resolving credentials]';
throw e;
@ -151,13 +148,13 @@ export class CredentialsHelper extends ICredentialsHelper {
typeVersion: 1,
type: 'mock',
position: [0, 0],
parameters: decryptedData as INodeParameters,
parameters: {} as INodeParameters,
} as INode;
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;
decryptedData = workflow.expression.getComplexParameterValue(node!, decryptedData as INodeParameters, undefined, decryptedData) as ICredentialDataDecryptedObject;
}
// Load and apply the credentials overwrites if any exist

View file

@ -23,14 +23,14 @@ export class GithubOAuth2Api implements ICredentialType {
displayName: 'Authorization URL',
name: 'authUrl',
type: 'hidden' as NodePropertyTypes,
default: '={{$parameter["server"] === "https://api.github.com" ? "https://github.com" : $parameter["server"]}}/login/oauth/authorize',
default: '={{$self["server"] === "https://api.github.com" ? "https://github.com" : $self["server"]}}/login/oauth/authorize',
required: true,
},
{
displayName: 'Access Token URL',
name: 'accessTokenUrl',
type: 'hidden' as NodePropertyTypes,
default: '={{$parameter["server"] === "https://api.github.com" ? "https://github.com" : $parameter["server"]}}/login/oauth/access_token',
default: '={{$self["server"] === "https://api.github.com" ? "https://github.com" : $self["server"]}}/login/oauth/access_token',
required: true,
},
{

View file

@ -22,14 +22,14 @@ export class GitlabOAuth2Api implements ICredentialType {
displayName: 'Authorization URL',
name: 'authUrl',
type: 'hidden' as NodePropertyTypes,
default: '={{$parameter["server"]}}/oauth/authorize',
default: '={{$self["server"]}}/oauth/authorize',
required: true,
},
{
displayName: 'Access Token URL',
name: 'accessTokenUrl',
type: 'hidden' as NodePropertyTypes,
default: '={{$parameter["server"]}}/oauth/token',
default: '={{$self["server"]}}/oauth/token',
required: true,
},
{

View file

@ -37,7 +37,7 @@ export class LinkedInOAuth2Api implements ICredentialType {
displayName: 'Scope',
name: 'scope',
type: 'hidden' as NodePropertyTypes,
default: '=r_liteprofile,r_emailaddress,w_member_social{{$parameter["organizationSupport"] === true ? ",w_organization_social":""}}',
default: '=r_liteprofile,r_emailaddress,w_member_social{{$self["organizationSupport"] === true ? ",w_organization_social":""}}',
description: 'Standard scopes for posting on behalf of a user or organization. See <a href="https://docs.microsoft.com/en-us/linkedin/marketing/getting-started#available-permissions"> this resource </a>.',
},
{

View file

@ -22,14 +22,14 @@ export class MauticOAuth2Api implements ICredentialType {
displayName: 'Authorization URL',
name: 'authUrl',
type: 'hidden' as NodePropertyTypes,
default: '={{$parameter["url"]}}/oauth/v2/authorize',
default: '={{$self["url"]}}/oauth/v2/authorize',
required: true,
},
{
displayName: 'Access Token URL',
name: 'accessTokenUrl',
type: 'hidden' as NodePropertyTypes,
default: '={{$parameter["url"]}}/oauth/v2/token',
default: '={{$self["url"]}}/oauth/v2/token',
required: true,
},
{

View file

@ -33,7 +33,7 @@ export class PhilipsHueOAuth2Api implements ICredentialType {
displayName: 'Auth URI Query Parameters',
name: 'authQueryParameters',
type: 'hidden' as NodePropertyTypes,
default: '={{"appid="+$parameter["appId"]}}',
default: '={{"appid="+$self["appId"]}}',
},
{
displayName: 'Scope',

View file

@ -29,7 +29,7 @@ export class ZendeskOAuth2Api implements ICredentialType {
displayName: 'Authorization URL',
name: 'authUrl',
type: 'hidden' as NodePropertyTypes,
default: '=https://{{$parameter["subdomain"]}}.zendesk.com/oauth/authorizations/new',
default: '=https://{{$self["subdomain"]}}.zendesk.com/oauth/authorizations/new',
description: 'URL to get authorization code. Replace {SUBDOMAIN_HERE} with your subdomain.',
required: true,
},
@ -37,7 +37,7 @@ export class ZendeskOAuth2Api implements ICredentialType {
displayName: 'Access Token URL',
name: 'accessTokenUrl',
type: 'hidden' as NodePropertyTypes,
default: '=https://{{$parameter["subdomain"]}}.zendesk.com/oauth/tokens',
default: '=https://{{$self["subdomain"]}}.zendesk.com/oauth/tokens',
description: 'URL to get access token. Replace {SUBDOMAIN_HERE} with your subdomain.',
required: true,
},

View file

@ -1,5 +1,6 @@
import {
IDataObject,
INode,
INodeExecutionData,
INodeParameters,
@ -58,7 +59,7 @@ export class Expression {
* @returns {(NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[])}
* @memberof Workflow
*/
resolveSimpleParameterValue(parameterValue: NodeParameterValue, runExecutionData: IRunExecutionData | null, runIndex: number, itemIndex: number, activeNodeName: string, connectionInputData: INodeExecutionData[], returnObjectAsString = false): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] {
resolveSimpleParameterValue(parameterValue: NodeParameterValue, runExecutionData: IRunExecutionData | null, runIndex: number, itemIndex: number, activeNodeName: string, connectionInputData: INodeExecutionData[], returnObjectAsString = false, selfData = {}): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] {
// Check if it is an expression
if (typeof parameterValue !== 'string' || parameterValue.charAt(0) !== '=') {
// Is no expression so return value
@ -71,7 +72,7 @@ export class Expression {
parameterValue = parameterValue.substr(1);
// Generate a data proxy which allows to query workflow data
const dataProxy = new WorkflowDataProxy(this.workflow, runExecutionData, runIndex, itemIndex, activeNodeName, connectionInputData);
const dataProxy = new WorkflowDataProxy(this.workflow, runExecutionData, runIndex, itemIndex, activeNodeName, connectionInputData, -1, selfData);
const data = dataProxy.getDataProxy();
// Execute the expression
@ -131,7 +132,7 @@ export class Expression {
* @returns {(NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] | undefined)}
* @memberof Workflow
*/
getComplexParameterValue(node: INode, parameterValue: NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[], defaultValue: NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] | undefined = undefined): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] | undefined {
getComplexParameterValue(node: INode, parameterValue: NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[], defaultValue: NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] | undefined = undefined, selfData = {}): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] | undefined {
if (parameterValue === undefined) {
// Value is not set so return the default
return defaultValue;
@ -148,10 +149,10 @@ export class Expression {
};
// Resolve the "outer" main values
const returnData = this.getParameterValue(parameterValue, runData, runIndex, itemIndex, node.name, connectionInputData);
const returnData = this.getParameterValue(parameterValue, runData, runIndex, itemIndex, node.name, connectionInputData, false, selfData);
// Resolve the "inner" values
return this.getParameterValue(returnData, runData, runIndex, itemIndex, node.name, connectionInputData);
return this.getParameterValue(returnData, runData, runIndex, itemIndex, node.name, connectionInputData, false, selfData);
}
@ -171,7 +172,7 @@ export class Expression {
* @returns {(NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[])}
* @memberof Workflow
*/
getParameterValue(parameterValue: NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[], runExecutionData: IRunExecutionData | null, runIndex: number, itemIndex: number, activeNodeName: string, connectionInputData: INodeExecutionData[], returnObjectAsString = false): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] {
getParameterValue(parameterValue: NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[], runExecutionData: IRunExecutionData | null, runIndex: number, itemIndex: number, activeNodeName: string, connectionInputData: INodeExecutionData[], returnObjectAsString = false, selfData = {}): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] {
// Helper function which returns true when the parameter is a complex one or array
const isComplexParameter = (value: NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[]) => {
return typeof value === 'object';
@ -180,15 +181,15 @@ export class Expression {
// Helper function which resolves a parameter value depending on if it is simply or not
const resolveParameterValue = (value: NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[]) => {
if (isComplexParameter(value)) {
return this.getParameterValue(value, runExecutionData, runIndex, itemIndex, activeNodeName, connectionInputData, returnObjectAsString);
return this.getParameterValue(value, runExecutionData, runIndex, itemIndex, activeNodeName, connectionInputData, returnObjectAsString, selfData);
} else {
return this.resolveSimpleParameterValue(value as NodeParameterValue, runExecutionData, runIndex, itemIndex, activeNodeName, connectionInputData, returnObjectAsString);
return this.resolveSimpleParameterValue(value as NodeParameterValue, runExecutionData, runIndex, itemIndex, activeNodeName, connectionInputData, returnObjectAsString, selfData);
}
};
// Check if it value is a simple one that we can get it resolved directly
if (!isComplexParameter(parameterValue)) {
return this.resolveSimpleParameterValue(parameterValue as NodeParameterValue, runExecutionData, runIndex, itemIndex, activeNodeName, connectionInputData, returnObjectAsString);
return this.resolveSimpleParameterValue(parameterValue as NodeParameterValue, runExecutionData, runIndex, itemIndex, activeNodeName, connectionInputData, returnObjectAsString, selfData);
}
// The parameter value is complex so resolve depending on type

View file

@ -17,10 +17,11 @@ export class WorkflowDataProxy {
private itemIndex: number;
private activeNodeName: string;
private connectionInputData: INodeExecutionData[];
private selfData: IDataObject;
constructor(workflow: Workflow, runExecutionData: IRunExecutionData | null, runIndex: number, itemIndex: number, activeNodeName: string, connectionInputData: INodeExecutionData[], defaultReturnRunIndex = -1) {
constructor(workflow: Workflow, runExecutionData: IRunExecutionData | null, runIndex: number, itemIndex: number, activeNodeName: string, connectionInputData: INodeExecutionData[], defaultReturnRunIndex = -1, selfData = {}) {
this.workflow = workflow;
this.runExecutionData = runExecutionData;
this.defaultReturnRunIndex = defaultReturnRunIndex;
@ -28,6 +29,7 @@ export class WorkflowDataProxy {
this.itemIndex = itemIndex;
this.activeNodeName = activeNodeName;
this.connectionInputData = connectionInputData;
this.selfData = selfData;
}
@ -69,6 +71,21 @@ export class WorkflowDataProxy {
private selfGetter() {
const that = this;
return new Proxy({}, {
ownKeys(target) {
return Reflect.ownKeys(target);
},
get(target, name, receiver) {
name = name.toString();
return that.selfData[name];
},
});
}
/**
* Returns a proxy which allows to query parameter data of a given node
*
@ -359,6 +376,7 @@ export class WorkflowDataProxy {
},
$json: {}, // Placeholder
$node: this.nodeGetter(),
$self: this.selfGetter(),
$parameter: this.nodeParameterGetter(this.activeNodeName),
$runIndex: this.runIndex,
$workflow: this.workflowGetter(),