From fcdb7f772d69e397926f20533e98806f038846cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Thu, 17 Aug 2023 16:07:17 +0200 Subject: [PATCH 1/3] fix(core): Set up OAuth2 cred test --- packages/cli/src/CredentialsHelper.ts | 37 ++++++++++++++++++- packages/cli/src/constants.ts | 2 + .../common/1659888469333-AddJsonKeyPinData.ts | 5 +-- packages/cli/src/utils.ts | 4 ++ 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/packages/cli/src/CredentialsHelper.ts b/packages/cli/src/CredentialsHelper.ts index 4b85896525ecf..cb515ff55ec72 100644 --- a/packages/cli/src/CredentialsHelper.ts +++ b/packages/cli/src/CredentialsHelper.ts @@ -31,6 +31,7 @@ import type { IHttpRequestHelper, INodeTypeData, INodeTypes, + ICredentialTestFunctions, } from 'n8n-workflow'; import { ICredentialsHelper, @@ -53,6 +54,9 @@ import { CredentialsOverwrites } from '@/CredentialsOverwrites'; import { whereClause } from './UserManagement/UserManagementHelper'; import { RESPONSE_ERROR_MESSAGES } from './constants'; import { Container } from 'typedi'; +import { isObjectLiteral } from './utils'; + +const { OAUTH2_CREDENTIAL_TEST_SUCCEEDED, OAUTH2_CREDENTIAL_TEST_FAILED } = RESPONSE_ERROR_MESSAGES; const mockNode = { name: '', @@ -466,8 +470,17 @@ export class CredentialsHelper extends ICredentialsHelper { await Db.collections.Credentials.update(findQuery, newCredentialsData); } + private static hasAccessToken(credentialsDecrypted: ICredentialsDecrypted) { + const oauthTokenData = credentialsDecrypted?.data?.oauthTokenData; + + if (!isObjectLiteral(oauthTokenData)) return false; + + return 'access_token' in oauthTokenData; + } + private getCredentialTestFunction( credentialType: string, + credentialsDecrypted: ICredentialsDecrypted, ): ICredentialTestFunction | ICredentialTestRequestData | undefined { // Check if test is defined on credentials const type = this.credentialTypes.getByName(credentialType); @@ -496,6 +509,25 @@ export class CredentialsHelper extends ICredentialsHelper { for (const nodeType of allNodeTypes) { // Check each of teh credentials for (const { name, testedBy } of nodeType.description.credentials ?? []) { + if (name === credentialType && name.endsWith('OAuth2Api')) { + const hasAccessToken = CredentialsHelper.hasAccessToken(credentialsDecrypted); + + return async function oauth2CredTest( + this: ICredentialTestFunctions, + __: ICredentialsDecrypted, + ): Promise { + return hasAccessToken + ? { + status: 'OK', + message: OAUTH2_CREDENTIAL_TEST_SUCCEEDED, + } + : { + status: 'Error', + message: OAUTH2_CREDENTIAL_TEST_FAILED, + }; + }; + } + if (name === credentialType && !!testedBy) { if (typeof testedBy === 'string') { if (node instanceof VersionedNodeType) { @@ -532,7 +564,10 @@ export class CredentialsHelper extends ICredentialsHelper { credentialType: string, credentialsDecrypted: ICredentialsDecrypted, ): Promise { - const credentialTestFunction = this.getCredentialTestFunction(credentialType); + const credentialTestFunction = this.getCredentialTestFunction( + credentialType, + credentialsDecrypted, + ); if (credentialTestFunction === undefined) { return { status: 'Error', diff --git a/packages/cli/src/constants.ts b/packages/cli/src/constants.ts index 12f08845575dd..caef03bcb2324 100644 --- a/packages/cli/src/constants.ts +++ b/packages/cli/src/constants.ts @@ -45,6 +45,8 @@ export const RESPONSE_ERROR_MESSAGES = { PACKAGE_LOADING_FAILED: 'The specified package could not be loaded', DISK_IS_FULL: 'There appears to be insufficient disk space', USERS_QUOTA_REACHED: 'Maximum number of users reached', + OAUTH2_CREDENTIAL_TEST_SUCCEEDED: 'Connection Successful!', + OAUTH2_CREDENTIAL_TEST_FAILED: 'This OAuth2 credential was not connected to an account.', }; export const AUTH_COOKIE_NAME = 'n8n-auth'; diff --git a/packages/cli/src/databases/migrations/common/1659888469333-AddJsonKeyPinData.ts b/packages/cli/src/databases/migrations/common/1659888469333-AddJsonKeyPinData.ts index fe6696386878e..bb21e758fa938 100644 --- a/packages/cli/src/databases/migrations/common/1659888469333-AddJsonKeyPinData.ts +++ b/packages/cli/src/databases/migrations/common/1659888469333-AddJsonKeyPinData.ts @@ -1,3 +1,4 @@ +import { isObjectLiteral } from '@/utils'; import type { IDataObject, INodeExecutionData } from 'n8n-workflow'; import type { MigrationContext, IrreversibleMigration } from '@db/types'; @@ -5,10 +6,6 @@ type OldPinnedData = { [nodeName: string]: IDataObject[] }; type NewPinnedData = { [nodeName: string]: INodeExecutionData[] }; type Workflow = { id: number; pinData: string | OldPinnedData }; -function isObjectLiteral(item: unknown): item is { [key: string]: string } { - return typeof item === 'object' && item !== null && !Array.isArray(item); -} - function isJsonKeyObject(item: unknown): item is { json: unknown; [keys: string]: unknown; diff --git a/packages/cli/src/utils.ts b/packages/cli/src/utils.ts index 0912b02582a05..5e4f38d01158a 100644 --- a/packages/cli/src/utils.ts +++ b/packages/cli/src/utils.ts @@ -97,3 +97,7 @@ export function isStringArray(value: unknown): value is string[] { } export const isIntegerString = (value: string) => /^\d+$/.test(value); + +export function isObjectLiteral(item: unknown): item is { [key: string]: string } { + return typeof item === 'object' && item !== null && !Array.isArray(item); +} From 9c70c0d1b41ef7e06d5bfbb6743186e68f049b47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Thu, 17 Aug 2023 17:19:29 +0200 Subject: [PATCH 2/3] Address feedback --- packages/cli/src/CredentialsHelper.ts | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/packages/cli/src/CredentialsHelper.ts b/packages/cli/src/CredentialsHelper.ts index cb515ff55ec72..8370edefc2797 100644 --- a/packages/cli/src/CredentialsHelper.ts +++ b/packages/cli/src/CredentialsHelper.ts @@ -480,7 +480,6 @@ export class CredentialsHelper extends ICredentialsHelper { private getCredentialTestFunction( credentialType: string, - credentialsDecrypted: ICredentialsDecrypted, ): ICredentialTestFunction | ICredentialTestRequestData | undefined { // Check if test is defined on credentials const type = this.credentialTypes.getByName(credentialType); @@ -510,13 +509,11 @@ export class CredentialsHelper extends ICredentialsHelper { // Check each of teh credentials for (const { name, testedBy } of nodeType.description.credentials ?? []) { if (name === credentialType && name.endsWith('OAuth2Api')) { - const hasAccessToken = CredentialsHelper.hasAccessToken(credentialsDecrypted); - return async function oauth2CredTest( this: ICredentialTestFunctions, - __: ICredentialsDecrypted, + cred: ICredentialsDecrypted, ): Promise { - return hasAccessToken + return CredentialsHelper.hasAccessToken(cred) ? { status: 'OK', message: OAUTH2_CREDENTIAL_TEST_SUCCEEDED, @@ -564,10 +561,7 @@ export class CredentialsHelper extends ICredentialsHelper { credentialType: string, credentialsDecrypted: ICredentialsDecrypted, ): Promise { - const credentialTestFunction = this.getCredentialTestFunction( - credentialType, - credentialsDecrypted, - ); + const credentialTestFunction = this.getCredentialTestFunction(credentialType); if (credentialTestFunction === undefined) { return { status: 'Error', From 41570c188496d4a0c4e371ecebd5ff861c533725 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Thu, 17 Aug 2023 17:23:33 +0200 Subject: [PATCH 3/3] Better oauth check --- packages/cli/src/CredentialsHelper.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/cli/src/CredentialsHelper.ts b/packages/cli/src/CredentialsHelper.ts index 8370edefc2797..303b7a0fcb632 100644 --- a/packages/cli/src/CredentialsHelper.ts +++ b/packages/cli/src/CredentialsHelper.ts @@ -508,7 +508,10 @@ export class CredentialsHelper extends ICredentialsHelper { for (const nodeType of allNodeTypes) { // Check each of teh credentials for (const { name, testedBy } of nodeType.description.credentials ?? []) { - if (name === credentialType && name.endsWith('OAuth2Api')) { + if ( + name === credentialType && + this.credentialTypes.getParentTypes(name).includes('oAuth2Api') + ) { return async function oauth2CredTest( this: ICredentialTestFunctions, cred: ICredentialsDecrypted,