diff --git a/packages/core/src/__tests__/credentials.test.ts b/packages/core/src/__tests__/credentials.test.ts index 366477def7fcf..8a5d1a1997bbd 100644 --- a/packages/core/src/__tests__/credentials.test.ts +++ b/packages/core/src/__tests__/credentials.test.ts @@ -2,6 +2,7 @@ import { Container } from '@n8n/di'; import { mock } from 'jest-mock-extended'; import type { CredentialInformation } from 'n8n-workflow'; +import { CREDENTIAL_ERRORS } from '@/constants'; import { Cipher } from '@/encryption/cipher'; import type { InstanceSettings } from '@/instance-settings'; @@ -57,4 +58,38 @@ describe('Credentials', () => { expect(credentials.getData().key1).toEqual(initialData); }); }); + + describe('getData', () => { + const nodeCredentials = { id: '123', name: 'testName' }; + const credentialType = 'testApi'; + + test('should throw an error when data is missing', () => { + const credentials = new Credentials(nodeCredentials, credentialType); + credentials.data = undefined; + + expect(() => credentials.getData()).toThrow(CREDENTIAL_ERRORS.NO_DATA); + }); + + test('should throw an error when decryption fails', () => { + const credentials = new Credentials(nodeCredentials, credentialType); + credentials.data = 'invalid-credentials-data'; + + expect(() => credentials.getData()).toThrow(CREDENTIAL_ERRORS.DECRYPTION_FAILED); + }); + + test('should throw an error when JSON parsing fails', () => { + const credentials = new Credentials(nodeCredentials, credentialType); + credentials.data = cipher.encrypt('invalid-json-string'); + + expect(() => credentials.getData()).toThrow(CREDENTIAL_ERRORS.INVALID_JSON); + }); + test('should successfully decrypt and parse valid JSON credentials', () => { + const credentials = new Credentials(nodeCredentials, credentialType); + credentials.setData({ username: 'testuser', password: 'testpass' }); + + const decryptedData = credentials.getData(); + expect(decryptedData.username).toBe('testuser'); + expect(decryptedData.password).toBe('testpass'); + }); + }); }); diff --git a/packages/core/src/constants.ts b/packages/core/src/constants.ts index feb630e306f55..f6ca2d8b674e7 100644 --- a/packages/core/src/constants.ts +++ b/packages/core/src/constants.ts @@ -14,3 +14,10 @@ export const CONFIG_FILES = 'N8N_CONFIG_FILES'; export const BINARY_DATA_STORAGE_PATH = 'N8N_BINARY_DATA_STORAGE_PATH'; export const UM_EMAIL_TEMPLATES_INVITE = 'N8N_UM_EMAIL_TEMPLATES_INVITE'; export const UM_EMAIL_TEMPLATES_PWRESET = 'N8N_UM_EMAIL_TEMPLATES_PWRESET'; + +export const CREDENTIAL_ERRORS = { + NO_DATA: 'No data is set on this credentials.', + DECRYPTION_FAILED: + 'Credentials could not be decrypted. The likely reason is that a different "encryptionKey" was used to encrypt the data.', + INVALID_JSON: 'Decrypted credentials data is not valid JSON.', +}; diff --git a/packages/core/src/credentials.ts b/packages/core/src/credentials.ts index 9b5b4c14553dc..9e66ae7519051 100644 --- a/packages/core/src/credentials.ts +++ b/packages/core/src/credentials.ts @@ -2,6 +2,7 @@ import { Container } from '@n8n/di'; import type { ICredentialDataDecryptedObject, ICredentialsEncrypted } from 'n8n-workflow'; import { ApplicationError, ICredentials, jsonParse } from 'n8n-workflow'; +import { CREDENTIAL_ERRORS } from '@/constants'; import { Cipher } from '@/encryption/cipher'; export class Credentials< @@ -21,17 +22,20 @@ export class Credentials< */ getData(): T { if (this.data === undefined) { - throw new ApplicationError('No data is set so nothing can be returned.'); + throw new ApplicationError(CREDENTIAL_ERRORS.NO_DATA); } + let decryptedData: string; try { - const decryptedData = this.cipher.decrypt(this.data); + decryptedData = this.cipher.decrypt(this.data); + } catch (e) { + throw new ApplicationError(CREDENTIAL_ERRORS.DECRYPTION_FAILED, { cause: e }); + } + try { return jsonParse(decryptedData); } catch (e) { - throw new ApplicationError( - 'Credentials could not be decrypted. The likely reason is that a different "encryptionKey" was used to encrypt the data.', - ); + throw new ApplicationError(CREDENTIAL_ERRORS.INVALID_JSON, { cause: e }); } }