mirror of
https://github.com/n8n-io/n8n.git
synced 2025-01-11 21:07:28 -08:00
refactor(core): Delete unused code, and fix typings in tests (no-changelog) (#8142)
This commit is contained in:
parent
5778b3bac8
commit
4007163651
|
@ -1,51 +0,0 @@
|
||||||
import Container from 'typedi';
|
|
||||||
import { ApplicationError, type INode, type IWorkflowCredentials } from 'n8n-workflow';
|
|
||||||
import { CredentialsRepository } from '@db/repositories/credentials.repository';
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
||||||
export async function WorkflowCredentials(nodes: INode[]): Promise<IWorkflowCredentials> {
|
|
||||||
// Go through all nodes to find which credentials are needed to execute the workflow
|
|
||||||
const returnCredentials: IWorkflowCredentials = {};
|
|
||||||
|
|
||||||
let node;
|
|
||||||
let type;
|
|
||||||
let nodeCredentials;
|
|
||||||
let foundCredentials;
|
|
||||||
|
|
||||||
for (node of nodes) {
|
|
||||||
if (node.disabled === true || !node.credentials) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (type of Object.keys(node.credentials)) {
|
|
||||||
if (!returnCredentials[type]) {
|
|
||||||
returnCredentials[type] = {};
|
|
||||||
}
|
|
||||||
nodeCredentials = node.credentials[type];
|
|
||||||
|
|
||||||
if (!nodeCredentials.id) {
|
|
||||||
throw new ApplicationError(
|
|
||||||
`Credentials with name "${nodeCredentials.name}" for type "${type}" miss an ID.`,
|
|
||||||
{ extra: { credentialName: nodeCredentials.name }, tags: { credentialType: type } },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!returnCredentials[type][nodeCredentials.id]) {
|
|
||||||
foundCredentials = await Container.get(CredentialsRepository).findOneBy({
|
|
||||||
id: nodeCredentials.id,
|
|
||||||
type,
|
|
||||||
});
|
|
||||||
if (!foundCredentials) {
|
|
||||||
throw new ApplicationError('Could not find credential.', {
|
|
||||||
tags: { credentialType: type },
|
|
||||||
extra: { credentialId: nodeCredentials.id },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
returnCredentials[type][nodeCredentials.id] = foundCredentials;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return returnCredentials;
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
import type { Credentials } from '@/requests';
|
import type { ListQuery } from '@/requests';
|
||||||
import type { User } from '@db/entities/User';
|
import type { User } from '@db/entities/User';
|
||||||
import * as testDb from './shared/testDb';
|
import * as testDb from './shared/testDb';
|
||||||
import { setupTestServer } from './shared/utils/';
|
import { setupTestServer } from './shared/utils/';
|
||||||
|
@ -21,7 +21,7 @@ beforeEach(async () => {
|
||||||
member = await createMember();
|
member = await createMember();
|
||||||
});
|
});
|
||||||
|
|
||||||
type GetAllResponse = { body: { data: Credentials.WithOwnedByAndSharedWith[] } };
|
type GetAllResponse = { body: { data: ListQuery.Credentials.WithOwnedByAndSharedWith[] } };
|
||||||
|
|
||||||
describe('GET /credentials', () => {
|
describe('GET /credentials', () => {
|
||||||
describe('should return', () => {
|
describe('should return', () => {
|
||||||
|
@ -278,7 +278,7 @@ describe('GET /credentials', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function validateCredential(credential: Credentials.WithOwnedByAndSharedWith) {
|
function validateCredential(credential: ListQuery.Credentials.WithOwnedByAndSharedWith) {
|
||||||
const { name, type, nodesAccess, sharedWith, ownedBy } = credential;
|
const { name, type, nodesAccess, sharedWith, ownedBy } = credential;
|
||||||
|
|
||||||
expect(typeof name).toBe('string');
|
expect(typeof name).toBe('string');
|
||||||
|
|
|
@ -24,6 +24,7 @@ describe('ExecutionRepository', () => {
|
||||||
const executionId = await executionRepo.createNewExecution({
|
const executionId = await executionRepo.createNewExecution({
|
||||||
workflowId: workflow.id,
|
workflowId: workflow.id,
|
||||||
data: {
|
data: {
|
||||||
|
//@ts-expect-error This is not needed for tests
|
||||||
resultData: {},
|
resultData: {},
|
||||||
},
|
},
|
||||||
workflowData: workflow,
|
workflowData: workflow,
|
||||||
|
|
|
@ -271,6 +271,7 @@ describe('CredentialsHelper', () => {
|
||||||
|
|
||||||
for (const testData of tests) {
|
for (const testData of tests) {
|
||||||
test(testData.description, async () => {
|
test(testData.description, async () => {
|
||||||
|
//@ts-expect-error `loadedCredentials` is a getter and we are replacing it here with a property
|
||||||
mockNodesAndCredentials.loadedCredentials = {
|
mockNodesAndCredentials.loadedCredentials = {
|
||||||
[testData.input.credentialType.name]: {
|
[testData.input.credentialType.name]: {
|
||||||
type: testData.input.credentialType,
|
type: testData.input.credentialType,
|
||||||
|
|
|
@ -41,6 +41,7 @@ describe('InternalHooks', () => {
|
||||||
licensePlanName,
|
licensePlanName,
|
||||||
licenseTenantId,
|
licenseTenantId,
|
||||||
binary_data_s3: false,
|
binary_data_s3: false,
|
||||||
|
multi_main_setup_enabled: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
const parameters = {
|
const parameters = {
|
||||||
|
|
|
@ -48,7 +48,7 @@ describe('Telemetry', () => {
|
||||||
const postHog = new PostHogClient(instanceSettings);
|
const postHog = new PostHogClient(instanceSettings);
|
||||||
await postHog.init();
|
await postHog.init();
|
||||||
|
|
||||||
telemetry = new Telemetry(mock(), postHog, mock(), instanceSettings);
|
telemetry = new Telemetry(mock(), postHog, mock(), instanceSettings, mock());
|
||||||
(telemetry as any).rudderStack = mockRudderStack;
|
(telemetry as any).rudderStack = mockRudderStack;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,147 +0,0 @@
|
||||||
import type { FindOptionsWhere } from 'typeorm';
|
|
||||||
import type { INode } from 'n8n-workflow';
|
|
||||||
import { WorkflowCredentials } from '@/WorkflowCredentials';
|
|
||||||
import type { CredentialsEntity } from '@db/entities/CredentialsEntity';
|
|
||||||
import { CredentialsRepository } from '@db/repositories/credentials.repository';
|
|
||||||
import { mockInstance } from '../shared/mocking';
|
|
||||||
|
|
||||||
const credentialsRepository = mockInstance(CredentialsRepository);
|
|
||||||
credentialsRepository.findOneBy.mockImplementation(
|
|
||||||
async (where: FindOptionsWhere<CredentialsEntity>) => {
|
|
||||||
const { id, type } = where as {
|
|
||||||
id: string;
|
|
||||||
type: string;
|
|
||||||
};
|
|
||||||
// Simple statement that maps a return value based on the `id` parameter
|
|
||||||
if (id === notFoundNode.credentials!.test.id) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise just build some kind of credential object and return it
|
|
||||||
return {
|
|
||||||
[type]: {
|
|
||||||
[id]: {
|
|
||||||
id,
|
|
||||||
name: type,
|
|
||||||
type,
|
|
||||||
nodesAccess: [],
|
|
||||||
data: '',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} as unknown as CredentialsEntity;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
// Create an array of Nodes with info that pass or fail the checks as required.
|
|
||||||
// DB returns an object of type { [id: string]: ICredentialsEncrypted } but as it isn't checked
|
|
||||||
// All the mock will need to return is some form of Object when successful
|
|
||||||
|
|
||||||
describe('WorkflowCredentials', () => {
|
|
||||||
afterEach(() => {
|
|
||||||
jest.clearAllMocks();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Should return an error if any node has no credential ID', async () => {
|
|
||||||
const credentials = noIdNode.credentials!.test;
|
|
||||||
const expectedError = new Error(
|
|
||||||
`Credentials with name "${credentials.name}" for type "test" miss an ID.`,
|
|
||||||
);
|
|
||||||
await expect(WorkflowCredentials([noIdNode])).rejects.toEqual(expectedError);
|
|
||||||
expect(credentialsRepository.findOneBy).toHaveBeenCalledTimes(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Should return an error if credentials cannot be found in the DB', async () => {
|
|
||||||
const expectedError = new Error('Could not find credential.');
|
|
||||||
await expect(WorkflowCredentials([notFoundNode])).rejects.toEqual(expectedError);
|
|
||||||
expect(credentialsRepository.findOneBy).toHaveBeenCalledTimes(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Should ignore duplicates', async () => {
|
|
||||||
const response = await WorkflowCredentials([validNode, validNode, validNode]);
|
|
||||||
expect(Object.keys(response)).toEqual(['test']);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Should ignore Nodes with no credentials set', async () => {
|
|
||||||
const response = await WorkflowCredentials([validNode, noCredentialsNode]);
|
|
||||||
expect(Object.keys(response)).toEqual(['test']);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Should work for Nodes with multiple credentials', async () => {
|
|
||||||
const response = await WorkflowCredentials([multiCredNode]);
|
|
||||||
expect(Object.keys(response)).toEqual(['mcTest', 'mcTest2']);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const validNode: INode = {
|
|
||||||
id: '1',
|
|
||||||
name: 'Node with Valid Credentials',
|
|
||||||
typeVersion: 1,
|
|
||||||
type: '',
|
|
||||||
position: [0, 0],
|
|
||||||
credentials: {
|
|
||||||
test: {
|
|
||||||
id: 'cred#1',
|
|
||||||
name: 'Test Credentials',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
parameters: {},
|
|
||||||
};
|
|
||||||
|
|
||||||
const noIdNode: INode = {
|
|
||||||
id: '2',
|
|
||||||
name: 'Node with no Credential ID',
|
|
||||||
typeVersion: 1,
|
|
||||||
type: '',
|
|
||||||
position: [0, 0],
|
|
||||||
credentials: {
|
|
||||||
test: {
|
|
||||||
id: null,
|
|
||||||
name: 'NOFIND',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
parameters: {},
|
|
||||||
};
|
|
||||||
|
|
||||||
const notFoundNode: INode = {
|
|
||||||
id: '3',
|
|
||||||
name: 'Node that will not be found in the DB',
|
|
||||||
typeVersion: 1,
|
|
||||||
type: '',
|
|
||||||
position: [0, 0],
|
|
||||||
credentials: {
|
|
||||||
test: {
|
|
||||||
id: 'noDB',
|
|
||||||
name: 'Not in Database',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
parameters: {},
|
|
||||||
};
|
|
||||||
|
|
||||||
const noCredentialsNode: INode = {
|
|
||||||
id: '4',
|
|
||||||
name: 'Node that has no credentials',
|
|
||||||
typeVersion: 1,
|
|
||||||
type: '',
|
|
||||||
position: [0, 0],
|
|
||||||
parameters: {},
|
|
||||||
};
|
|
||||||
|
|
||||||
// Reference this as a DataObject so I can provide a null credential for testing
|
|
||||||
const multiCredNode: INode = {
|
|
||||||
id: '5',
|
|
||||||
name: 'Node that has mutliple credential elements',
|
|
||||||
typeVersion: 1,
|
|
||||||
type: '',
|
|
||||||
position: [0, 0],
|
|
||||||
credentials: {
|
|
||||||
mcTest: {
|
|
||||||
id: 'multicred#1',
|
|
||||||
name: 'First of Multiple Credentials',
|
|
||||||
},
|
|
||||||
mcTest2: {
|
|
||||||
id: 'multicred#2',
|
|
||||||
name: 'Second of Multiple Credentials',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
parameters: {},
|
|
||||||
};
|
|
Loading…
Reference in a new issue