From ccb2b076f8240b0712949b72ec57ae72a36ef62d Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Mon, 8 Jan 2024 10:48:20 +0100 Subject: [PATCH] fix: Resolve expressions in credentials following paired item (#8250) ## Summary Fixes the issue that pairedItem information was not available in expressions that got used in credentials ## Related tickets and issues [PAY-1207](https://linear.app/n8n/issue/PAY-1207/paireditem-expressions-not-working-correctly-in-credentials) ## Review / Merge checklist - [x] PR title and summary are descriptive. **Remember, the title automatically goes into the changelog. Use `(no-changelog)` otherwise.** ([conventions](https://github.com/n8n-io/n8n/blob/master/.github/pull_request_title_conventions.md)) - [ ] [Docs updated](https://github.com/n8n-io/n8n-docs) or follow-up ticket created. - [ ] Tests included. > A bug is not considered fixed, unless a test is added to prevent it from happening again. > A feature is not complete without tests. --------- Co-authored-by: Omar Ajoue --- packages/cli/BREAKING-CHANGES.md | 4 + packages/cli/src/CredentialsHelper.ts | 7 +- .../oauth/abstractOAuth.controller.ts | 1 + .../MessageEventBusDestinationWebhook.ee.ts | 1 + packages/core/src/NodeExecuteFunctions.ts | 5 ++ .../HttpRequest/V3/HttpRequestV3.node.ts | 76 +++++++++---------- packages/workflow/src/Interfaces.ts | 1 + 7 files changed, 56 insertions(+), 39 deletions(-) diff --git a/packages/cli/BREAKING-CHANGES.md b/packages/cli/BREAKING-CHANGES.md index a961e91fea..c947c30d65 100644 --- a/packages/cli/BREAKING-CHANGES.md +++ b/packages/cli/BREAKING-CHANGES.md @@ -8,10 +8,14 @@ This list shows all the versions which include breaking changes and how to upgra The flag `N8N_CACHE_ENABLED` was removed. The cache is now always enabled. +Additionally, expressions in credentials now follow the paired item, so if you have multiple input items, n8n will try to pair the matching row to fill in the credential details. + ### When is action necessary? If you are using the flag `N8N_CACHE_ENABLED`, remove it from your settings. +In regards to credentials, if you use expression in credentials, you might want to revisit them. Previously, n8n would stick to the first item only, but now it will try to match the proper paired item. + ## 1.22.0 ### What changed? diff --git a/packages/cli/src/CredentialsHelper.ts b/packages/cli/src/CredentialsHelper.ts index 5920986de9..dad6f9c3ef 100644 --- a/packages/cli/src/CredentialsHelper.ts +++ b/packages/cli/src/CredentialsHelper.ts @@ -32,6 +32,7 @@ import type { INodeTypes, IWorkflowExecuteAdditionalData, ICredentialTestFunctions, + IExecuteData, } from 'n8n-workflow'; import { ICredentialsHelper, @@ -339,6 +340,7 @@ export class CredentialsHelper extends ICredentialsHelper { nodeCredentials: INodeCredentialsDetails, type: string, mode: WorkflowExecuteMode, + executeData?: IExecuteData, raw?: boolean, expressionResolveValues?: ICredentialsExpressionResolveValues, ): Promise { @@ -358,6 +360,7 @@ export class CredentialsHelper extends ICredentialsHelper { decryptedDataOriginal, type, mode, + executeData, expressionResolveValues, canUseSecrets, ); @@ -371,6 +374,7 @@ export class CredentialsHelper extends ICredentialsHelper { decryptedDataOriginal: ICredentialDataDecryptedObject, type: string, mode: WorkflowExecuteMode, + executeData?: IExecuteData, expressionResolveValues?: ICredentialsExpressionResolveValues, canUseSecrets?: boolean, ): ICredentialDataDecryptedObject { @@ -412,7 +416,7 @@ export class CredentialsHelper extends ICredentialsHelper { expressionResolveValues.connectionInputData, mode, additionalKeys, - undefined, + executeData, false, decryptedData, ) as ICredentialDataDecryptedObject; @@ -579,6 +583,7 @@ export class CredentialsHelper extends ICredentialsHelper { credentialType, 'internal' as WorkflowExecuteMode, undefined, + undefined, user.hasGlobalScope('externalSecret:use'), ); } catch (error) { diff --git a/packages/cli/src/controllers/oauth/abstractOAuth.controller.ts b/packages/cli/src/controllers/oauth/abstractOAuth.controller.ts index 185a9afa01..c2e9ded77e 100644 --- a/packages/cli/src/controllers/oauth/abstractOAuth.controller.ts +++ b/packages/cli/src/controllers/oauth/abstractOAuth.controller.ts @@ -73,6 +73,7 @@ export abstract class AbstractOAuthController { credential, credential.type, 'internal', + undefined, true, ); } diff --git a/packages/cli/src/eventbus/MessageEventBusDestination/MessageEventBusDestinationWebhook.ee.ts b/packages/cli/src/eventbus/MessageEventBusDestination/MessageEventBusDestinationWebhook.ee.ts index 932ac90c04..348eb0ef66 100644 --- a/packages/cli/src/eventbus/MessageEventBusDestination/MessageEventBusDestinationWebhook.ee.ts +++ b/packages/cli/src/eventbus/MessageEventBusDestination/MessageEventBusDestinationWebhook.ee.ts @@ -107,6 +107,7 @@ export class MessageEventBusDestinationWebhook foundCredential[1], foundCredential[0], 'internal', + undefined, true, ); return credentialsDecrypted; diff --git a/packages/core/src/NodeExecuteFunctions.ts b/packages/core/src/NodeExecuteFunctions.ts index f43bac3889..7c9ae42b91 100644 --- a/packages/core/src/NodeExecuteFunctions.ts +++ b/packages/core/src/NodeExecuteFunctions.ts @@ -1882,6 +1882,7 @@ export async function getCredentials( type: string, additionalData: IWorkflowExecuteAdditionalData, mode: WorkflowExecuteMode, + executeData?: IExecuteData, runExecutionData?: IRunExecutionData | null, runIndex?: number, connectionInputData?: INodeExecutionData[], @@ -2001,6 +2002,7 @@ export async function getCredentials( nodeCredentials, type, mode, + executeData, false, expressionResolveValues, ); @@ -3149,6 +3151,7 @@ export function getExecuteFunctions( type, additionalData, mode, + executeData, runExecutionData, runIndex, connectionInputData, @@ -3281,6 +3284,7 @@ export function getExecuteFunctions( key, additionalData, mode, + executeData, runExecutionData, runIndex, connectionInputData, @@ -3608,6 +3612,7 @@ export function getExecuteSingleFunctions( type, additionalData, mode, + executeData, runExecutionData, runIndex, connectionInputData, diff --git a/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts b/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts index 3ccf4b55f9..0f60254037 100644 --- a/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts +++ b/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts @@ -1221,44 +1221,6 @@ export class HttpRequestV3 implements INodeType { let nodeCredentialType: string | undefined; let genericCredentialType: string | undefined; - if (authentication === 'genericCredentialType') { - genericCredentialType = this.getNodeParameter('genericAuthType', 0) as string; - - if (genericCredentialType === 'httpBasicAuth') { - try { - httpBasicAuth = await this.getCredentials('httpBasicAuth'); - } catch {} - } else if (genericCredentialType === 'httpDigestAuth') { - try { - httpDigestAuth = await this.getCredentials('httpDigestAuth'); - } catch {} - } else if (genericCredentialType === 'httpHeaderAuth') { - try { - httpHeaderAuth = await this.getCredentials('httpHeaderAuth'); - } catch {} - } else if (genericCredentialType === 'httpQueryAuth') { - try { - httpQueryAuth = await this.getCredentials('httpQueryAuth'); - } catch {} - } else if (genericCredentialType === 'httpCustomAuth') { - try { - httpCustomAuth = await this.getCredentials('httpCustomAuth'); - } catch {} - } else if (genericCredentialType === 'oAuth1Api') { - try { - oAuth1Api = await this.getCredentials('oAuth1Api'); - } catch {} - } else if (genericCredentialType === 'oAuth2Api') { - try { - oAuth2Api = await this.getCredentials('oAuth2Api'); - } catch {} - } - } else if (authentication === 'predefinedCredentialType') { - try { - nodeCredentialType = this.getNodeParameter('nodeCredentialType', 0) as string; - } catch {} - } - type RequestOptions = OptionsWithUri & { useStream?: boolean }; let requestOptions: RequestOptions = { uri: '', @@ -1293,6 +1255,44 @@ export class HttpRequestV3 implements INodeType { }; for (let itemIndex = 0; itemIndex < items.length; itemIndex++) { + if (authentication === 'genericCredentialType') { + genericCredentialType = this.getNodeParameter('genericAuthType', 0) as string; + + if (genericCredentialType === 'httpBasicAuth') { + try { + httpBasicAuth = await this.getCredentials('httpBasicAuth', itemIndex); + } catch {} + } else if (genericCredentialType === 'httpDigestAuth') { + try { + httpDigestAuth = await this.getCredentials('httpDigestAuth', itemIndex); + } catch {} + } else if (genericCredentialType === 'httpHeaderAuth') { + try { + httpHeaderAuth = await this.getCredentials('httpHeaderAuth', itemIndex); + } catch {} + } else if (genericCredentialType === 'httpQueryAuth') { + try { + httpQueryAuth = await this.getCredentials('httpQueryAuth', itemIndex); + } catch {} + } else if (genericCredentialType === 'httpCustomAuth') { + try { + httpCustomAuth = await this.getCredentials('httpCustomAuth', itemIndex); + } catch {} + } else if (genericCredentialType === 'oAuth1Api') { + try { + oAuth1Api = await this.getCredentials('oAuth1Api', itemIndex); + } catch {} + } else if (genericCredentialType === 'oAuth2Api') { + try { + oAuth2Api = await this.getCredentials('oAuth2Api', itemIndex); + } catch {} + } + } else if (authentication === 'predefinedCredentialType') { + try { + nodeCredentialType = this.getNodeParameter('nodeCredentialType', 0) as string; + } catch {} + } + const requestMethod = this.getNodeParameter('method', itemIndex) as string; const sendQuery = this.getNodeParameter('sendQuery', itemIndex, false) as boolean; diff --git a/packages/workflow/src/Interfaces.ts b/packages/workflow/src/Interfaces.ts index 725c783ed7..03febe4646 100644 --- a/packages/workflow/src/Interfaces.ts +++ b/packages/workflow/src/Interfaces.ts @@ -217,6 +217,7 @@ export abstract class ICredentialsHelper { nodeCredentials: INodeCredentialsDetails, type: string, mode: WorkflowExecuteMode, + executeData?: IExecuteData, raw?: boolean, expressionResolveValues?: ICredentialsExpressionResolveValues, ): Promise;