From 000e76e3b48c5a89c5909f0c71c6baae1d6692dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=A4=95=E0=A4=BE=E0=A4=B0=E0=A4=A4=E0=A5=8B=E0=A4=AB?= =?UTF-8?q?=E0=A5=8D=E0=A4=AB=E0=A5=87=E0=A4=B2=E0=A4=B8=E0=A5=8D=E0=A4=95?= =?UTF-8?q?=E0=A5=8D=E0=A4=B0=E0=A4=BF=E0=A4=AA=E0=A5=8D=E0=A4=9F=E2=84=A2?= Date: Fri, 10 Nov 2023 15:04:26 +0100 Subject: [PATCH] ci(core): Reduce memory usage in tests (part-2) (no-changelog) (#7671) This also gets rid of `Db.collection`, which was another source of circular dependencies. --- .github/workflows/units-tests-reusable.yml | 3 + package.json | 3 +- packages/cli/src/ActiveExecutions.ts | 2 +- packages/cli/src/ActiveWorkflowRunner.ts | 11 +-- packages/cli/src/CredentialsHelper.ts | 21 +++--- packages/cli/src/Db.ts | 51 -------------- packages/cli/src/ExternalHooks.ts | 35 +++++++--- .../ExternalSecretsManager.ee.ts | 2 +- packages/cli/src/GenericHelpers.ts | 9 +-- packages/cli/src/Interfaces.ts | 62 ++++------------- packages/cli/src/Ldap/helpers.ts | 28 ++++---- packages/cli/src/License.ts | 12 ++-- packages/cli/src/Mfa/helpers.ts | 5 +- packages/cli/src/Mfa/mfa.service.ts | 2 +- packages/cli/src/PublicApi/index.ts | 4 +- .../credentials/credentials.service.ts | 8 ++- .../handlers/executions/executions.handler.ts | 2 +- .../handlers/executions/executions.service.ts | 5 +- .../v1/handlers/users/users.service.ee.ts | 2 +- .../handlers/workflows/workflows.service.ts | 26 ++++--- packages/cli/src/Server.ts | 32 +++++---- .../src/UserManagement/PermissionChecker.ts | 10 +-- .../UserManagement/UserManagementHelper.ts | 6 +- packages/cli/src/WaitTracker.ts | 2 +- packages/cli/src/WaitingWebhooks.ts | 2 +- packages/cli/src/WorkflowCredentials.ts | 5 +- .../cli/src/WorkflowExecuteAdditionalData.ts | 2 +- packages/cli/src/WorkflowHelpers.ts | 41 ++++++----- packages/cli/src/WorkflowRunner.ts | 2 +- packages/cli/src/audit/index.ts | 5 +- .../cli/src/audit/risks/credentials.risk.ts | 8 +-- packages/cli/src/auth/jwt.ts | 4 +- packages/cli/src/auth/methods/email.ts | 4 +- .../src/collaboration/collaboration.state.ts | 2 +- packages/cli/src/commands/BaseCommand.ts | 2 +- packages/cli/src/commands/execute.ts | 4 +- packages/cli/src/commands/executeBatch.ts | 4 +- .../cli/src/commands/export/credentials.ts | 6 +- packages/cli/src/commands/export/workflow.ts | 5 +- .../cli/src/commands/import/credentials.ts | 5 +- packages/cli/src/commands/import/workflow.ts | 8 ++- packages/cli/src/commands/ldap/reset.ts | 19 ++--- packages/cli/src/commands/license/clear.ts | 5 +- packages/cli/src/commands/list/workflow.ts | 5 +- packages/cli/src/commands/mfa/disable.ts | 5 +- packages/cli/src/commands/start.ts | 9 ++- packages/cli/src/commands/update/workflow.ts | 5 +- .../cli/src/commands/user-management/reset.ts | 38 +++++----- packages/cli/src/commands/worker.ts | 5 +- .../cli/src/controllers/e2e.controller.ts | 4 +- .../oauth/abstractOAuth.controller.ts | 3 +- .../cli/src/controllers/owner.controller.ts | 2 +- .../cli/src/controllers/users.controller.ts | 3 +- .../workflowStatistics.controller.ts | 3 +- .../credentials/credentials.controller.ee.ts | 2 +- .../src/credentials/credentials.service.ee.ts | 6 +- .../src/credentials/credentials.service.ts | 24 ++++--- .../cli/src/databases/repositories/index.ts | 21 ------ .../sourceControl/sourceControl.service.ee.ts | 2 +- .../sourceControlExport.service.ee.ts | 17 +++-- .../sourceControlImport.service.ee.ts | 56 +++++++++------ .../sourceControlPreferences.service.ee.ts | 8 +-- .../variables/variables.service.ts | 2 +- .../MessageEventBus/MessageEventBus.ts | 7 +- .../eventbus/MessageEventBus/recoverEvents.ts | 2 +- .../MessageEventBusDestination.ee.ts | 6 +- .../MessageEventBusDestinationFromDb.ts | 2 +- .../shared/sharedHookFunctions.ts | 2 +- .../cli/src/executions/executions.service.ts | 6 +- packages/cli/src/license/License.service.ts | 6 +- packages/cli/src/push/abstract.push.ts | 2 +- packages/cli/src/push/index.ts | 2 +- packages/cli/src/push/sse.push.ts | 2 +- packages/cli/src/push/types.ts | 2 +- packages/cli/src/push/websocket.push.ts | 2 +- packages/cli/src/requests.ts | 6 +- .../src/services/communityPackages.service.ts | 4 +- packages/cli/src/services/events.service.ts | 2 +- .../src/services/executionMetadata.service.ts | 4 +- .../cli/src/services/ownership.service.ts | 8 +-- packages/cli/src/services/pruning.service.ts | 4 +- packages/cli/src/services/role.service.ts | 5 +- packages/cli/src/services/tag.service.ts | 4 +- packages/cli/src/services/user.service.ts | 2 +- packages/cli/src/services/webhook.service.ts | 4 +- packages/cli/src/sso/saml/saml.service.ee.ts | 15 ++-- packages/cli/src/sso/saml/samlHelpers.ts | 11 +-- packages/cli/src/sso/ssoHelpers.ts | 5 +- .../workflowHistory.service.ee.ts | 10 +-- .../workflowHistoryManager.ee.ts | 2 +- .../cli/src/workflows/workflows.controller.ts | 3 +- .../src/workflows/workflows.services.ee.ts | 6 +- .../cli/src/workflows/workflows.services.ts | 43 +++++++----- .../integration/ActiveWorkflowRunner.test.ts | 13 ++-- .../externalSecrets.api.test.ts | 24 ++++--- .../audit/credentials.risk.test.ts | 30 ++++---- .../integration/audit/database.risk.test.ts | 9 +-- .../integration/audit/filesystem.risk.test.ts | 7 +- .../integration/audit/instance.risk.test.ts | 9 +-- .../test/integration/audit/nodes.risk.test.ts | 13 ++-- packages/cli/test/integration/audit/utils.ts | 5 +- .../cli/test/integration/auth.api.test.ts | 4 +- .../test/integration/binaryData.api.test.ts | 4 +- .../commands/credentials.cmd.test.ts | 3 +- .../integration/commands/import.cmd.test.ts | 3 +- .../integration/commands/reset.cmd.test.ts | 10 +-- .../integration/commands/start.cmd.test.ts | 7 +- .../integration/commands/worker.cmd.test.ts | 3 +- .../community-packages.api.test.ts | 9 +-- .../test/integration/credentials.ee.test.ts | 15 ++-- .../cli/test/integration/credentials.test.ts | 40 ++++++----- .../integration/executions.controller.test.ts | 2 +- .../test/integration/ldap/ldap.api.test.ts | 20 ++++-- packages/cli/test/integration/me.api.test.ts | 37 +++++----- .../cli/test/integration/mfa/mfa.api.test.ts | 8 +-- .../cli/test/integration/owner.api.test.ts | 7 +- .../integration/passwordReset.api.test.ts | 21 +++--- .../test/integration/pruning.service.test.ts | 10 +-- .../integration/publicApi/credentials.test.ts | 32 +++++---- .../integration/publicApi/users.ee.test.ts | 5 +- .../integration/publicApi/workflows.test.ts | 51 +++++++------- .../test/integration/shared/db/credentials.ts | 3 +- .../test/integration/shared/db/executions.ts | 3 +- .../cli/test/integration/shared/db/tags.ts | 3 +- .../cli/test/integration/shared/db/users.ts | 3 +- .../integration/shared/db/workflowHistory.ts | 2 +- .../test/integration/shared/db/workflows.ts | 3 +- .../cli/test/integration/shared/testDb.ts | 49 ++++++++----- packages/cli/test/integration/shared/types.ts | 7 +- .../shared/utils/communityNodes.ts | 3 +- .../test/integration/shared/utils/index.ts | 9 ++- .../integration/shared/utils/testServer.ts | 15 ++-- .../cli/test/integration/tags.api.test.ts | 2 +- .../cli/test/integration/users.api.test.ts | 57 ++++++++------- .../test/integration/users.controller.test.ts | 2 +- .../cli/test/integration/variables.test.ts | 6 +- .../cli/test/integration/webhooks.api.test.ts | 3 +- .../integration/workflowHistory.api.test.ts | 9 +-- .../workflowHistoryManager.test.ts | 4 +- .../workflows.controller.ee.test.ts | 9 +-- .../integration/workflows.controller.test.ts | 11 +-- .../shared/utils => shared}/mocking.ts | 0 .../cli/test/unit/ActiveExecutions.test.ts | 2 +- .../cli/test/unit/CredentialTypes.test.ts | 2 +- .../cli/test/unit/CredentialsHelper.test.ts | 8 ++- .../ExternalSecretsManager.test.ts | 4 +- packages/cli/test/unit/InternalHooks.test.ts | 2 +- packages/cli/test/unit/License.test.ts | 7 +- .../cli/test/unit/PermissionChecker.test.ts | 9 +-- packages/cli/test/unit/PostHog.test.ts | 2 +- packages/cli/test/unit/SourceControl.test.ts | 10 +-- packages/cli/test/unit/Telemetry.test.ts | 2 +- .../cli/test/unit/WorkflowCredentials.test.ts | 69 +++++++++---------- .../WorkflowExecuteAdditionalData.test.ts | 4 +- packages/cli/test/unit/WorkflowRunner.test.ts | 9 +-- .../collaboration.service.test.ts | 2 +- .../unit/controllers/me.controller.test.ts | 4 +- .../oAuth1Credential.controller.test.ts | 5 +- .../oAuth2Credential.controller.test.ts | 5 +- .../unit/controllers/owner.controller.test.ts | 9 ++- .../cli/test/unit/execution.lifecycle.test.ts | 2 +- .../cli/test/unit/push/websocket.push.test.ts | 4 +- .../unit/repositories/role.repository.test.ts | 2 +- .../sharedCredentials.repository.test.ts | 2 +- .../communityPackages.service.test.ts | 8 ++- .../test/unit/services/events.service.test.ts | 4 +- .../services/orchestration.service.test.ts | 2 +- .../unit/services/ownership.service.test.ts | 20 +++--- .../test/unit/services/redis.service.test.ts | 2 +- .../test/unit/services/role.service.test.ts | 6 +- .../test/unit/services/user.service.test.ts | 4 +- .../unit/services/webhook.service.test.ts | 6 +- packages/cli/test/unit/webhooks.test.ts | 2 +- .../test/unit/workflowHistoryHelper.test.ts | 2 +- 174 files changed, 892 insertions(+), 808 deletions(-) delete mode 100644 packages/cli/src/databases/repositories/index.ts rename packages/cli/test/{integration/shared/utils => shared}/mocking.ts (100%) diff --git a/.github/workflows/units-tests-reusable.yml b/.github/workflows/units-tests-reusable.yml index eb180f65cb..81aec86184 100644 --- a/.github/workflows/units-tests-reusable.yml +++ b/.github/workflows/units-tests-reusable.yml @@ -60,6 +60,9 @@ jobs: - name: Test Backend run: pnpm test:backend + - name: Test Nodes + run: pnpm test:nodes + - name: Test Frontend run: pnpm test:frontend diff --git a/package.json b/package.json index 0f44cb0aa4..e771a05e4f 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,8 @@ "start:tunnel": "./packages/cli/bin/n8n start --tunnel", "start:windows": "cd packages/cli/bin && n8n", "test": "turbo run test", - "test:backend": "pnpm --filter=!n8n-design-system --filter=!n8n-editor-ui test", + "test:backend": "pnpm --filter=!n8n-design-system --filter=!n8n-editor-ui --filter=!n8n-nodes-base test", + "test:nodes": "pnpm --filter=n8n-nodes-base test", "test:frontend": "pnpm --filter=n8n-design-system --filter=n8n-editor-ui test", "watch": "turbo run watch", "webhook": "./packages/cli/bin/n8n webhook", diff --git a/packages/cli/src/ActiveExecutions.ts b/packages/cli/src/ActiveExecutions.ts index 5a5f83ee3a..9d606aab7d 100644 --- a/packages/cli/src/ActiveExecutions.ts +++ b/packages/cli/src/ActiveExecutions.ts @@ -19,7 +19,7 @@ import type { IWorkflowExecutionDataProcess, } from '@/Interfaces'; import { isWorkflowIdValid } from '@/utils'; -import { ExecutionRepository } from '@db/repositories'; +import { ExecutionRepository } from '@db/repositories/execution.repository'; import { Logger } from '@/Logger'; @Service() diff --git a/packages/cli/src/ActiveWorkflowRunner.ts b/packages/cli/src/ActiveWorkflowRunner.ts index e59c28ab59..4cbcda2a89 100644 --- a/packages/cli/src/ActiveWorkflowRunner.ts +++ b/packages/cli/src/ActiveWorkflowRunner.ts @@ -33,7 +33,6 @@ import { import type express from 'express'; -import * as Db from '@/Db'; import type { IResponseCallbackData, IWebhookManager, @@ -63,7 +62,8 @@ import { webhookNotFoundErrorMessage } from './utils'; import { In } from 'typeorm'; import { WebhookService } from './services/webhook.service'; import { Logger } from './Logger'; -import { WorkflowRepository } from '@/databases/repositories'; +import { SharedWorkflowRepository } from '@db/repositories/sharedWorkflow.repository'; +import { WorkflowRepository } from '@db/repositories/workflow.repository'; import config from '@/config'; import type { MultiMainInstancePublisher } from './services/orchestration/main/MultiMainInstance.publisher.ee'; @@ -104,6 +104,7 @@ export class ActiveWorkflowRunner implements IWebhookManager { private readonly nodeTypes: NodeTypes, private readonly webhookService: WebhookService, private readonly workflowRepository: WorkflowRepository, + private readonly sharedWorkflowRepository: SharedWorkflowRepository, ) {} async init() { @@ -188,7 +189,7 @@ export class ActiveWorkflowRunner implements IWebhookManager { }); } - const workflowData = await Db.collections.Workflow.findOne({ + const workflowData = await this.workflowRepository.findOne({ where: { id: webhook.workflowId }, relations: ['shared', 'shared.user', 'shared.user.globalRole'], }); @@ -296,7 +297,7 @@ export class ActiveWorkflowRunner implements IWebhookManager { Object.assign(where, { workflowId: In(activeIds) }); - const sharings = await Db.collections.SharedWorkflow.find({ + const sharings = await this.sharedWorkflowRepository.find({ select: ['workflowId'], where, }); @@ -416,7 +417,7 @@ export class ActiveWorkflowRunner implements IWebhookManager { * Clear workflow-defined webhooks from the `webhook_entity` table. */ async clearWebhooks(workflowId: string) { - const workflowData = await Db.collections.Workflow.findOne({ + const workflowData = await this.workflowRepository.findOne({ where: { id: workflowId }, relations: ['shared', 'shared.user', 'shared.user.globalRole'], }); diff --git a/packages/cli/src/CredentialsHelper.ts b/packages/cli/src/CredentialsHelper.ts index 920bcbdcbc..bd1a175dd6 100644 --- a/packages/cli/src/CredentialsHelper.ts +++ b/packages/cli/src/CredentialsHelper.ts @@ -43,7 +43,6 @@ import { ErrorReporterProxy as ErrorReporter, } from 'n8n-workflow'; -import * as Db from '@/Db'; import type { ICredentialsDb } from '@/Interfaces'; import * as WorkflowExecuteAdditionalData from '@/WorkflowExecuteAdditionalData'; import type { User } from '@db/entities/User'; @@ -54,6 +53,8 @@ import { CredentialsOverwrites } from '@/CredentialsOverwrites'; import { RESPONSE_ERROR_MESSAGES } from './constants'; import { isObjectLiteral } from './utils'; import { Logger } from '@/Logger'; +import { CredentialsRepository } from '@db/repositories/credentials.repository'; +import { SharedCredentialsRepository } from '@db/repositories/sharedCredentials.repository'; const { OAUTH2_CREDENTIAL_TEST_SUCCEEDED, OAUTH2_CREDENTIAL_TEST_FAILED } = RESPONSE_ERROR_MESSAGES; @@ -102,6 +103,8 @@ export class CredentialsHelper extends ICredentialsHelper { private readonly credentialTypes: CredentialTypes, private readonly nodeTypes: NodeTypes, private readonly credentialsOverwrites: CredentialsOverwrites, + private readonly credentialsRepository: CredentialsRepository, + private readonly sharedCredentialsRepository: SharedCredentialsRepository, ) { super(); } @@ -271,11 +274,13 @@ export class CredentialsHelper extends ICredentialsHelper { try { credential = userId - ? await Db.collections.SharedCredentials.findOneOrFail({ - relations: ['credentials'], - where: { credentials: { id: nodeCredential.id, type }, userId }, - }).then((shared) => shared.credentials) - : await Db.collections.Credentials.findOneByOrFail({ id: nodeCredential.id, type }); + ? await this.sharedCredentialsRepository + .findOneOrFail({ + relations: ['credentials'], + where: { credentials: { id: nodeCredential.id, type }, userId }, + }) + .then((shared) => shared.credentials) + : await this.credentialsRepository.findOneByOrFail({ id: nodeCredential.id, type }); } catch (error) { throw new CredentialNotFoundError(nodeCredential.id, type); } @@ -463,7 +468,7 @@ export class CredentialsHelper extends ICredentialsHelper { type, }; - await Db.collections.Credentials.update(findQuery, newCredentialsData); + await this.credentialsRepository.update(findQuery, newCredentialsData); } private static hasAccessToken(credentialsDecrypted: ICredentialsDecrypted) { @@ -774,7 +779,7 @@ export class CredentialsHelper extends ICredentialsHelper { return false; } - const credential = await Db.collections.SharedCredentials.findOne({ + const credential = await this.sharedCredentialsRepository.findOne({ where: { role: { scope: 'credential', diff --git a/packages/cli/src/Db.ts b/packages/cli/src/Db.ts index daebfa031d..e9b06499bd 100644 --- a/packages/cli/src/Db.ts +++ b/packages/cli/src/Db.ts @@ -1,13 +1,10 @@ /* eslint-disable @typescript-eslint/restrict-template-expressions */ - import { Container } from 'typedi'; import type { DataSourceOptions as ConnectionOptions, EntityManager, LoggerOptions } from 'typeorm'; import { DataSource as Connection } from 'typeorm'; import type { TlsOptions } from 'tls'; import { ErrorReporterProxy as ErrorReporter } from 'n8n-workflow'; -import type { IDatabaseCollections } from '@/Interfaces'; - import config from '@/config'; import { entities } from '@db/entities'; @@ -21,28 +18,6 @@ import { import { inTest } from '@/constants'; import { wrapMigration } from '@db/utils/migrationHelpers'; import type { DatabaseType, Migration } from '@db/types'; -import { - AuthIdentityRepository, - AuthProviderSyncHistoryRepository, - CredentialsRepository, - EventDestinationsRepository, - ExecutionDataRepository, - ExecutionMetadataRepository, - ExecutionRepository, - InstalledNodesRepository, - InstalledPackagesRepository, - RoleRepository, - SettingsRepository, - SharedCredentialsRepository, - SharedWorkflowRepository, - UserRepository, - VariablesRepository, - WorkflowRepository, - WorkflowStatisticsRepository, - WorkflowTagMappingRepository, -} from '@db/repositories'; - -export const collections = {} as IDatabaseCollections; let connection: Connection; @@ -165,32 +140,6 @@ export async function init(testConnectionOptions?: ConnectionOptions): Promise {}>; } = {}; - initDidRun = false; + private initDidRun = false; + + private dbCollections: IExternalHooksFunctions['dbCollections']; + + constructor( + userRepository: UserRepository, + settingsRepository: SettingsRepository, + credentialsRepository: CredentialsRepository, + workflowRepository: WorkflowRepository, + ) { + /* eslint-disable @typescript-eslint/naming-convention */ + this.dbCollections = { + User: userRepository, + Settings: settingsRepository, + Credentials: credentialsRepository, + Workflow: workflowRepository, + }; + /* eslint-enable @typescript-eslint/naming-convention */ + } async init(): Promise { if (this.initDidRun) { @@ -83,14 +102,14 @@ export class ExternalHooks implements IExternalHooksClass { } async run(hookName: string, hookParameters?: any[]): Promise { - const externalHookFunctions: IExternalHooksFunctions = { - dbCollections: Db.collections, - }; - if (this.externalHooks[hookName] === undefined) { return; } + const externalHookFunctions: IExternalHooksFunctions = { + dbCollections: this.dbCollections, + }; + for (const externalHookFunction of this.externalHooks[hookName]) { await externalHookFunction.apply(externalHookFunctions, hookParameters); } diff --git a/packages/cli/src/ExternalSecrets/ExternalSecretsManager.ee.ts b/packages/cli/src/ExternalSecrets/ExternalSecretsManager.ee.ts index 0d505a921d..8f8879a174 100644 --- a/packages/cli/src/ExternalSecrets/ExternalSecretsManager.ee.ts +++ b/packages/cli/src/ExternalSecrets/ExternalSecretsManager.ee.ts @@ -1,4 +1,4 @@ -import { SettingsRepository } from '@/databases/repositories'; +import { SettingsRepository } from '@db/repositories/settings.repository'; import type { ExternalSecretsSettings, SecretsProvider, diff --git a/packages/cli/src/GenericHelpers.ts b/packages/cli/src/GenericHelpers.ts index 63edec827f..e27ad52967 100644 --- a/packages/cli/src/GenericHelpers.ts +++ b/packages/cli/src/GenericHelpers.ts @@ -10,7 +10,6 @@ import { validate } from 'class-validator'; import { Container } from 'typedi'; import { Like } from 'typeorm'; import config from '@/config'; -import * as Db from '@/Db'; import type { ExecutionPayload, ICredentialsDb, IWorkflowDb } from '@/Interfaces'; import * as ResponseHelper from '@/ResponseHelper'; import type { WorkflowEntity } from '@db/entities/WorkflowEntity'; @@ -18,7 +17,9 @@ import type { CredentialsEntity } from '@db/entities/CredentialsEntity'; import type { TagEntity } from '@db/entities/TagEntity'; import type { User } from '@db/entities/User'; import type { UserUpdatePayload } from '@/requests'; -import { ExecutionRepository } from '@db/repositories'; +import { CredentialsRepository } from '@db/repositories/credentials.repository'; +import { ExecutionRepository } from '@db/repositories/execution.repository'; +import { WorkflowRepository } from '@db/repositories/workflow.repository'; /** * Returns the base URL n8n is reachable from @@ -64,8 +65,8 @@ export async function generateUniqueName( const found: Array = entityType === 'workflow' - ? await Db.collections.Workflow.find(findConditions) - : await Db.collections.Credentials.find(findConditions); + ? await Container.get(WorkflowRepository).find(findConditions) + : await Container.get(CredentialsRepository).find(findConditions); // name is unique if (found.length === 0) { diff --git a/packages/cli/src/Interfaces.ts b/packages/cli/src/Interfaces.ts index e569cc7f4b..846604bd1a 100644 --- a/packages/cli/src/Interfaces.ts +++ b/packages/cli/src/Interfaces.ts @@ -30,7 +30,7 @@ import type { ActiveWorkflowRunner } from '@/ActiveWorkflowRunner'; import type { WorkflowExecute } from 'n8n-core'; import type PCancelable from 'p-cancelable'; -import type { FindOperator, Repository } from 'typeorm'; +import type { FindOperator } from 'typeorm'; import type { ChildProcess } from 'child_process'; @@ -40,26 +40,10 @@ import type { Role } from '@db/entities/Role'; import type { SharedCredentials } from '@db/entities/SharedCredentials'; import type { TagEntity } from '@db/entities/TagEntity'; import type { User } from '@db/entities/User'; -import type { - AuthIdentityRepository, - AuthProviderSyncHistoryRepository, - CredentialsRepository, - EventDestinationsRepository, - ExecutionDataRepository, - ExecutionMetadataRepository, - ExecutionRepository, - InstalledNodesRepository, - InstalledPackagesRepository, - RoleRepository, - SettingsRepository, - SharedCredentialsRepository, - SharedWorkflowRepository, - UserRepository, - VariablesRepository, - WorkflowRepository, - WorkflowStatisticsRepository, - WorkflowTagMappingRepository, -} from '@db/repositories'; +import type { CredentialsRepository } from '@db/repositories/credentials.repository'; +import type { SettingsRepository } from '@db/repositories/settings.repository'; +import type { UserRepository } from '@db/repositories/user.repository'; +import type { WorkflowRepository } from '@db/repositories/workflow.repository'; import type { LICENSE_FEATURES, LICENSE_QUOTAS } from './constants'; import type { WorkflowWithSharingsAndCredentials } from './workflows/workflows.types'; @@ -71,33 +55,6 @@ export interface ICredentialsOverwrite { [key: string]: ICredentialDataDecryptedObject; } -/** - * @important Do not add to these collections. Inject the repository as a dependency instead. - */ - -/* eslint-disable @typescript-eslint/naming-convention */ -export interface IDatabaseCollections extends Record> { - AuthIdentity: AuthIdentityRepository; - AuthProviderSyncHistory: AuthProviderSyncHistoryRepository; - Credentials: CredentialsRepository; - EventDestinations: EventDestinationsRepository; - Execution: ExecutionRepository; - ExecutionData: ExecutionDataRepository; - ExecutionMetadata: ExecutionMetadataRepository; - InstalledNodes: InstalledNodesRepository; - InstalledPackages: InstalledPackagesRepository; - Role: RoleRepository; - Settings: SettingsRepository; - SharedCredentials: SharedCredentialsRepository; - SharedWorkflow: SharedWorkflowRepository; - User: UserRepository; - Variables: VariablesRepository; - Workflow: WorkflowRepository; - WorkflowStatistics: WorkflowStatisticsRepository; - WorkflowTagMapping: WorkflowTagMappingRepository; -} -/* eslint-enable @typescript-eslint/naming-convention */ - // ---------------------------------- // tags // ---------------------------------- @@ -285,7 +242,14 @@ export interface IExternalHooksFileData { } export interface IExternalHooksFunctions { - dbCollections: IDatabaseCollections; + dbCollections: { + /* eslint-disable @typescript-eslint/naming-convention */ + User: UserRepository; + Settings: SettingsRepository; + Credentials: CredentialsRepository; + Workflow: WorkflowRepository; + /* eslint-enable @typescript-eslint/naming-convention */ + }; } export interface IExternalHooksClass { diff --git a/packages/cli/src/Ldap/helpers.ts b/packages/cli/src/Ldap/helpers.ts index ea8bad5479..b43533c9d4 100644 --- a/packages/cli/src/Ldap/helpers.ts +++ b/packages/cli/src/Ldap/helpers.ts @@ -32,6 +32,10 @@ import { import { BadRequestError, InternalServerError } from '../ResponseHelper'; import { RoleService } from '@/services/role.service'; import { Logger } from '@/Logger'; +import { UserRepository } from '@db/repositories/user.repository'; +import { SettingsRepository } from '@db/repositories/settings.repository'; +import { AuthProviderSyncHistoryRepository } from '@db/repositories/authProviderSyncHistory.repository'; +import { AuthIdentityRepository } from '@db/repositories/authIdentity.repository'; /** * Check whether the LDAP feature is disabled in the instance @@ -114,7 +118,7 @@ export const validateLdapConfigurationSchema = ( * Retrieve the LDAP configuration (decrypted) form the database */ export const getLdapConfig = async (): Promise => { - const configuration = await Db.collections.Settings.findOneByOrFail({ + const configuration = await Container.get(SettingsRepository).findOneByOrFail({ key: LDAP_FEATURE_NAME, }); const configurationData = jsonParse(configuration.value); @@ -171,7 +175,7 @@ export const updateLdapConfig = async (ldapConfig: LdapConfig): Promise => } } - await Db.collections.Settings.update( + await Container.get(SettingsRepository).update( { key: LDAP_FEATURE_NAME }, { value: JSON.stringify(ldapConfig), loadOnStartup: true }, ); @@ -284,7 +288,7 @@ export const findAndAuthenticateLdapUser = async ( export const getAuthIdentityByLdapId = async ( idAttributeValue: string, ): Promise => { - return Db.collections.AuthIdentity.findOne({ + return Container.get(AuthIdentityRepository).findOne({ relations: ['user', 'user.globalRole'], where: { providerId: idAttributeValue, @@ -294,7 +298,7 @@ export const getAuthIdentityByLdapId = async ( }; export const getUserByEmail = async (email: string): Promise => { - return Db.collections.User.findOne({ + return Container.get(UserRepository).findOne({ where: { email }, relations: ['globalRole'], }); @@ -322,7 +326,7 @@ export const mapLdapAttributesToUser = ( * Retrieve LDAP ID of all LDAP users in the database */ export const getLdapIds = async (): Promise => { - const identities = await Db.collections.AuthIdentity.find({ + const identities = await Container.get(AuthIdentityRepository).find({ select: ['providerId'], where: { providerType: 'ldap', @@ -332,7 +336,7 @@ export const getLdapIds = async (): Promise => { }; export const getLdapUsers = async (): Promise => { - const identities = await Db.collections.AuthIdentity.find({ + const identities = await Container.get(AuthIdentityRepository).find({ relations: ['user'], where: { providerType: 'ldap', @@ -409,7 +413,7 @@ export const processUsers = async ( export const saveLdapSynchronization = async ( data: Omit, ): Promise => { - await Db.collections.AuthProviderSyncHistory.save({ + await Container.get(AuthProviderSyncHistoryRepository).save({ ...data, providerType: 'ldap', }); @@ -423,7 +427,7 @@ export const getLdapSynchronizations = async ( perPage: number, ): Promise => { const _page = Math.abs(page); - return Db.collections.AuthProviderSyncHistory.find({ + return Container.get(AuthProviderSyncHistoryRepository).find({ where: { providerType: 'ldap' }, order: { id: 'DESC' }, take: perPage, @@ -450,11 +454,11 @@ export const getMappingAttributes = (ldapConfig: LdapConfig): string[] => { }; export const createLdapAuthIdentity = async (user: User, ldapId: string) => { - return Db.collections.AuthIdentity.save(AuthIdentity.create(user, ldapId)); + return Container.get(AuthIdentityRepository).save(AuthIdentity.create(user, ldapId)); }; export const createLdapUserOnLocalDb = async (role: Role, data: Partial, ldapId: string) => { - const user = await Db.collections.User.save({ + const user = await Container.get(UserRepository).save({ password: randomPassword(), globalRole: role, ...data, @@ -466,10 +470,10 @@ export const createLdapUserOnLocalDb = async (role: Role, data: Partial, l export const updateLdapUserOnLocalDb = async (identity: AuthIdentity, data: Partial) => { const userId = identity?.user?.id; if (userId) { - await Db.collections.User.update({ id: userId }, data); + await Container.get(UserRepository).update({ id: userId }, data); } }; const deleteAllLdapIdentities = async () => { - return Db.collections.AuthIdentity.delete({ providerType: 'ldap' }); + return Container.get(AuthIdentityRepository).delete({ providerType: 'ldap' }); }; diff --git a/packages/cli/src/License.ts b/packages/cli/src/License.ts index 25d9b97e99..5c45894dbb 100644 --- a/packages/cli/src/License.ts +++ b/packages/cli/src/License.ts @@ -4,7 +4,6 @@ import { InstanceSettings, ObjectStoreService } from 'n8n-core'; import Container, { Service } from 'typedi'; import { Logger } from '@/Logger'; import config from '@/config'; -import * as Db from '@/Db'; import { LICENSE_FEATURES, LICENSE_QUOTAS, @@ -12,7 +11,8 @@ import { SETTINGS_LICENSE_CERT_KEY, UNLIMITED_LICENSE_QUOTA, } from './constants'; -import { WorkflowRepository } from '@/databases/repositories'; +import { SettingsRepository } from '@db/repositories/settings.repository'; +import { WorkflowRepository } from '@db/repositories/workflow.repository'; import type { BooleanLicenseFeature, N8nInstanceType, NumericLicenseFeature } from './Interfaces'; import type { RedisServicePubSubPublisher } from './services/redis/RedisServicePubSubPublisher'; import { RedisService } from './services/redis.service'; @@ -40,6 +40,8 @@ export class License { constructor( private readonly logger: Logger, private readonly instanceSettings: InstanceSettings, + private readonly settingsRepository: SettingsRepository, + private readonly workflowRepository: WorkflowRepository, ) {} async init(instanceType: N8nInstanceType = 'main') { @@ -91,7 +93,7 @@ export class License { return [ { name: 'activeWorkflows', - value: await Container.get(WorkflowRepository).count({ where: { active: true } }), + value: await this.workflowRepository.count({ where: { active: true } }), }, ]; } @@ -102,7 +104,7 @@ export class License { if (ephemeralLicense) { return ephemeralLicense; } - const databaseSettings = await Db.collections.Settings.findOne({ + const databaseSettings = await this.settingsRepository.findOne({ where: { key: SETTINGS_LICENSE_CERT_KEY, }, @@ -153,7 +155,7 @@ export class License { async saveCertStr(value: TLicenseBlock): Promise { // if we have an ephemeral license, we don't want to save it to the database if (config.get('license.cert')) return; - await Db.collections.Settings.upsert( + await this.settingsRepository.upsert( { key: SETTINGS_LICENSE_CERT_KEY, value, diff --git a/packages/cli/src/Mfa/helpers.ts b/packages/cli/src/Mfa/helpers.ts index 8484572533..34d117ed5c 100644 --- a/packages/cli/src/Mfa/helpers.ts +++ b/packages/cli/src/Mfa/helpers.ts @@ -1,13 +1,14 @@ +import Container from 'typedi'; import config from '@/config'; -import * as Db from '@/Db'; import { MFA_FEATURE_ENABLED } from './constants'; +import { UserRepository } from '@db/repositories/user.repository'; export const isMfaFeatureEnabled = () => config.get(MFA_FEATURE_ENABLED); const isMfaFeatureDisabled = () => !isMfaFeatureEnabled(); const getUsersWithMfaEnabled = async () => - Db.collections.User.count({ where: { mfaEnabled: true } }); + Container.get(UserRepository).count({ where: { mfaEnabled: true } }); export const handleMfaDisable = async () => { if (isMfaFeatureDisabled()) { diff --git a/packages/cli/src/Mfa/mfa.service.ts b/packages/cli/src/Mfa/mfa.service.ts index 7e2ce1dd82..452a3d7071 100644 --- a/packages/cli/src/Mfa/mfa.service.ts +++ b/packages/cli/src/Mfa/mfa.service.ts @@ -1,7 +1,7 @@ import { v4 as uuid } from 'uuid'; import { Service } from 'typedi'; import { Cipher } from 'n8n-core'; -import { UserRepository } from '@db/repositories'; +import { UserRepository } from '@db/repositories/user.repository'; import { TOTPService } from './totp.service'; @Service() diff --git a/packages/cli/src/PublicApi/index.ts b/packages/cli/src/PublicApi/index.ts index 585955c401..8a88a51e07 100644 --- a/packages/cli/src/PublicApi/index.ts +++ b/packages/cli/src/PublicApi/index.ts @@ -11,11 +11,11 @@ import type { OpenAPIV3 } from 'openapi-types'; import type { JsonObject } from 'swagger-ui-express'; import config from '@/config'; -import * as Db from '@/Db'; import { getInstanceBaseUrl } from '@/UserManagement/UserManagementHelper'; import { Container } from 'typedi'; import { InternalHooks } from '@/InternalHooks'; import { License } from '@/License'; +import { UserRepository } from '@db/repositories/user.repository'; async function createApiRouter( version: string, @@ -95,7 +95,7 @@ async function createApiRouter( schema: OpenAPIV3.ApiKeySecurityScheme, ): Promise => { const apiKey = req.headers[schema.name.toLowerCase()] as string; - const user = await Db.collections.User.findOne({ + const user = await Container.get(UserRepository).findOne({ where: { apiKey }, relations: ['globalRole'], }); diff --git a/packages/cli/src/PublicApi/v1/handlers/credentials/credentials.service.ts b/packages/cli/src/PublicApi/v1/handlers/credentials/credentials.service.ts index 25ab1e6dba..398254be59 100644 --- a/packages/cli/src/PublicApi/v1/handlers/credentials/credentials.service.ts +++ b/packages/cli/src/PublicApi/v1/handlers/credentials/credentials.service.ts @@ -10,9 +10,11 @@ import type { IDependency, IJsonSchema } from '../../../types'; import type { CredentialRequest } from '@/requests'; import { Container } from 'typedi'; import { RoleService } from '@/services/role.service'; +import { CredentialsRepository } from '@db/repositories/credentials.repository'; +import { SharedCredentialsRepository } from '@db/repositories/sharedCredentials.repository'; export async function getCredentials(credentialId: string): Promise { - return Db.collections.Credentials.findOneBy({ id: credentialId }); + return Container.get(CredentialsRepository).findOneBy({ id: credentialId }); } export async function getSharedCredentials( @@ -20,7 +22,7 @@ export async function getSharedCredentials( credentialId: string, relations?: string[], ): Promise { - return Db.collections.SharedCredentials.findOne({ + return Container.get(SharedCredentialsRepository).findOne({ where: { userId, credentialsId: credentialId, @@ -83,7 +85,7 @@ export async function saveCredential( export async function removeCredential(credentials: CredentialsEntity): Promise { await Container.get(ExternalHooks).run('credentials.delete', [credentials.id]); - return Db.collections.Credentials.remove(credentials); + return Container.get(CredentialsRepository).remove(credentials); } export async function encryptCredential(credential: CredentialsEntity): Promise { diff --git a/packages/cli/src/PublicApi/v1/handlers/executions/executions.handler.ts b/packages/cli/src/PublicApi/v1/handlers/executions/executions.handler.ts index 111638d716..af6dd968d8 100644 --- a/packages/cli/src/PublicApi/v1/handlers/executions/executions.handler.ts +++ b/packages/cli/src/PublicApi/v1/handlers/executions/executions.handler.ts @@ -8,7 +8,7 @@ import { getSharedWorkflowIds } from '../workflows/workflows.service'; import { encodeNextCursor } from '../../shared/services/pagination.service'; import { Container } from 'typedi'; import { InternalHooks } from '@/InternalHooks'; -import { ExecutionRepository } from '@/databases/repositories'; +import { ExecutionRepository } from '@db/repositories/execution.repository'; export = { deleteExecution: [ diff --git a/packages/cli/src/PublicApi/v1/handlers/executions/executions.service.ts b/packages/cli/src/PublicApi/v1/handlers/executions/executions.service.ts index de08c9095a..b2811bdcda 100644 --- a/packages/cli/src/PublicApi/v1/handlers/executions/executions.service.ts +++ b/packages/cli/src/PublicApi/v1/handlers/executions/executions.service.ts @@ -3,9 +3,8 @@ import { In, Not, Raw, LessThan } from 'typeorm'; import { Container } from 'typedi'; import type { ExecutionStatus } from 'n8n-workflow'; -import * as Db from '@/Db'; import type { IExecutionBase, IExecutionFlattedDb } from '@/Interfaces'; -import { ExecutionRepository } from '@db/repositories'; +import { ExecutionRepository } from '@db/repositories/execution.repository'; function getStatusCondition(status: ExecutionStatus) { const condition: Pick, 'status'> = {}; @@ -83,7 +82,7 @@ export async function getExecutionsCount(data: { excludedWorkflowIds?: string[]; }): Promise { // TODO: Consider moving this to the repository as well - const executions = await Db.collections.Execution.count({ + const executions = await Container.get(ExecutionRepository).count({ where: { ...(data.lastId && { id: LessThan(data.lastId) }), ...(data.status && { ...getStatusCondition(data.status) }), diff --git a/packages/cli/src/PublicApi/v1/handlers/users/users.service.ee.ts b/packages/cli/src/PublicApi/v1/handlers/users/users.service.ee.ts index 69c2fa8515..678727e693 100644 --- a/packages/cli/src/PublicApi/v1/handlers/users/users.service.ee.ts +++ b/packages/cli/src/PublicApi/v1/handlers/users/users.service.ee.ts @@ -1,5 +1,5 @@ import { Container } from 'typedi'; -import { UserRepository } from '@db/repositories'; +import { UserRepository } from '@db/repositories/user.repository'; import type { User } from '@db/entities/User'; import pick from 'lodash/pick'; import { validate as uuidValidate } from 'uuid'; diff --git a/packages/cli/src/PublicApi/v1/handlers/workflows/workflows.service.ts b/packages/cli/src/PublicApi/v1/handlers/workflows/workflows.service.ts index e2dd27bf71..94938be25c 100644 --- a/packages/cli/src/PublicApi/v1/handlers/workflows/workflows.service.ts +++ b/packages/cli/src/PublicApi/v1/handlers/workflows/workflows.service.ts @@ -10,6 +10,8 @@ import type { Role } from '@db/entities/Role'; import config from '@/config'; import { TagService } from '@/services/tag.service'; import Container from 'typedi'; +import { WorkflowRepository } from '@db/repositories/workflow.repository'; +import { SharedWorkflowRepository } from '@db/repositories/sharedWorkflow.repository'; function insertIf(condition: boolean, elements: string[]): string[] { return condition ? elements : []; @@ -17,7 +19,7 @@ function insertIf(condition: boolean, elements: string[]): string[] { export async function getSharedWorkflowIds(user: User): Promise { const where = user.globalRole.name === 'owner' ? {} : { userId: user.id }; - const sharedWorkflows = await Db.collections.SharedWorkflow.find({ + const sharedWorkflows = await Container.get(SharedWorkflowRepository).find({ where, select: ['workflowId'], }); @@ -28,7 +30,7 @@ export async function getSharedWorkflow( user: User, workflowId?: string | undefined, ): Promise { - return Db.collections.SharedWorkflow.findOne({ + return Container.get(SharedWorkflowRepository).findOne({ where: { ...(!user.isOwner && { userId: user.id }), ...(workflowId && { workflowId }), @@ -44,7 +46,7 @@ export async function getSharedWorkflows( workflowIds?: string[]; }, ): Promise { - return Db.collections.SharedWorkflow.find({ + return Container.get(SharedWorkflowRepository).find({ where: { ...(!user.isOwner && { userId: user.id }), ...(options.workflowIds && { workflowId: In(options.workflowIds) }), @@ -54,7 +56,7 @@ export async function getSharedWorkflows( } export async function getWorkflowById(id: string): Promise { - return Db.collections.Workflow.findOne({ + return Container.get(WorkflowRepository).findOne({ where: { id }, }); } @@ -97,28 +99,34 @@ export async function createWorkflow( } export async function setWorkflowAsActive(workflow: WorkflowEntity): Promise { - return Db.collections.Workflow.update(workflow.id, { active: true, updatedAt: new Date() }); + return Container.get(WorkflowRepository).update(workflow.id, { + active: true, + updatedAt: new Date(), + }); } export async function setWorkflowAsInactive(workflow: WorkflowEntity): Promise { - return Db.collections.Workflow.update(workflow.id, { active: false, updatedAt: new Date() }); + return Container.get(WorkflowRepository).update(workflow.id, { + active: false, + updatedAt: new Date(), + }); } export async function deleteWorkflow(workflow: WorkflowEntity): Promise { - return Db.collections.Workflow.remove(workflow); + return Container.get(WorkflowRepository).remove(workflow); } export async function getWorkflowsAndCount( options: FindManyOptions, ): Promise<[WorkflowEntity[], number]> { - return Db.collections.Workflow.findAndCount(options); + return Container.get(WorkflowRepository).findAndCount(options); } export async function updateWorkflow( workflowId: string, updateData: WorkflowEntity, ): Promise { - return Db.collections.Workflow.update(workflowId, updateData); + return Container.get(WorkflowRepository).update(workflowId, updateData); } export function parseTagNames(tags: string): string[] { diff --git a/packages/cli/src/Server.ts b/packages/cli/src/Server.ts index 3df0781de6..c00fb4558b 100644 --- a/packages/cli/src/Server.ts +++ b/packages/cli/src/Server.ts @@ -85,7 +85,6 @@ import { executionsController } from '@/executions/executions.controller'; import { isApiEnabled, loadPublicApiVersions } from '@/PublicApi'; import { whereClause } from '@/UserManagement/UserManagementHelper'; import { UserManagementMailer } from '@/UserManagement/email'; -import * as Db from '@/Db'; import type { ICredentialsOverwrite, IDiagnosticInfo, IExecutionsStopData } from '@/Interfaces'; import { ActiveExecutions } from '@/ActiveExecutions'; import { CredentialsOverwrites } from '@/CredentialsOverwrites'; @@ -119,8 +118,14 @@ import { } from './sso/ssoHelpers'; import { SourceControlService } from '@/environments/sourceControl/sourceControl.service.ee'; import { SourceControlController } from '@/environments/sourceControl/sourceControl.controller.ee'; -import { ExecutionRepository, SettingsRepository } from '@db/repositories'; + import type { ExecutionEntity } from '@db/entities/ExecutionEntity'; +import { ExecutionRepository } from '@db/repositories/execution.repository'; +import { SettingsRepository } from '@db/repositories/settings.repository'; +import { SharedCredentialsRepository } from '@db/repositories/sharedCredentials.repository'; +import { SharedWorkflowRepository } from '@db/repositories/sharedWorkflow.repository'; +import { WorkflowRepository } from '@db/repositories/workflow.repository'; + import { MfaService } from './Mfa/mfa.service'; import { handleMfaDisable, isMfaFeatureEnabled } from './Mfa/helpers'; import type { FrontendService } from './services/frontend.service'; @@ -236,18 +241,19 @@ export class Server extends AbstractServer { void this.loadNodesAndCredentials.setupHotReload(); } - void Db.collections.Workflow.findOne({ - select: ['createdAt'], - order: { createdAt: 'ASC' }, - where: {}, - }).then(async (workflow) => - Container.get(InternalHooks).onServerStarted(diagnosticInfo, workflow?.createdAt), - ); + void Container.get(WorkflowRepository) + .findOne({ + select: ['createdAt'], + order: { createdAt: 'ASC' }, + where: {}, + }) + .then(async (workflow) => + Container.get(InternalHooks).onServerStarted(diagnosticInfo, workflow?.createdAt), + ); } private async registerControllers(ignoredEndpoints: Readonly) { const { app, externalHooks, activeWorkflowRunner, nodeTypes, logger } = this; - const repositories = Db.collections; setupAuthMiddlewares(app, ignoredEndpoints, this.restEndpoint); const internalHooks = Container.get(InternalHooks); @@ -281,8 +287,8 @@ export class Server extends AbstractServer { logger, externalHooks, internalHooks, - repositories.SharedCredentials, - repositories.SharedWorkflow, + Container.get(SharedCredentialsRepository), + Container.get(SharedWorkflowRepository), activeWorkflowRunner, mailer, jwtService, @@ -623,7 +629,7 @@ export class Server extends AbstractServer { ResponseHelper.send(async (req: WorkflowRequest.GetAllActivationErrors) => { const { id: workflowId } = req.params; - const shared = await Db.collections.SharedWorkflow.findOne({ + const shared = await Container.get(SharedWorkflowRepository).findOne({ relations: ['workflow'], where: whereClause({ user: req.user, diff --git a/packages/cli/src/UserManagement/PermissionChecker.ts b/packages/cli/src/UserManagement/PermissionChecker.ts index 36dff30e2f..792d1ef727 100644 --- a/packages/cli/src/UserManagement/PermissionChecker.ts +++ b/packages/cli/src/UserManagement/PermissionChecker.ts @@ -2,13 +2,15 @@ import type { INode, Workflow } from 'n8n-workflow'; import { NodeOperationError, SubworkflowOperationError } from 'n8n-workflow'; import type { FindOptionsWhere } from 'typeorm'; import { In } from 'typeorm'; -import * as Db from '@/Db'; import config from '@/config'; import type { SharedCredentials } from '@db/entities/SharedCredentials'; import { isSharingEnabled } from './UserManagementHelper'; import { OwnershipService } from '@/services/ownership.service'; import Container from 'typedi'; import { RoleService } from '@/services/role.service'; +import { UserRepository } from '@db/repositories/user.repository'; +import { SharedCredentialsRepository } from '@db/repositories/sharedCredentials.repository'; +import { SharedWorkflowRepository } from '@db/repositories/sharedWorkflow.repository'; export class PermissionChecker { /** @@ -25,7 +27,7 @@ export class PermissionChecker { // allow if requesting user is instance owner - const user = await Db.collections.User.findOneOrFail({ + const user = await Container.get(UserRepository).findOneOrFail({ where: { id: userId }, relations: ['globalRole'], }); @@ -38,7 +40,7 @@ export class PermissionChecker { let workflowUserIds = [userId]; if (workflow.id && isSharingEnabled()) { - const workflowSharings = await Db.collections.SharedWorkflow.find({ + const workflowSharings = await Container.get(SharedWorkflowRepository).find({ relations: ['workflow'], where: { workflowId: workflow.id }, select: ['userId'], @@ -54,7 +56,7 @@ export class PermissionChecker { credentialsWhere.roleId = role.id; } - const credentialSharings = await Db.collections.SharedCredentials.find({ + const credentialSharings = await Container.get(SharedCredentialsRepository).find({ where: credentialsWhere, }); diff --git a/packages/cli/src/UserManagement/UserManagementHelper.ts b/packages/cli/src/UserManagement/UserManagementHelper.ts index 724943f573..50de670329 100644 --- a/packages/cli/src/UserManagement/UserManagementHelper.ts +++ b/packages/cli/src/UserManagement/UserManagementHelper.ts @@ -2,7 +2,6 @@ import { In } from 'typeorm'; import { compare, genSaltSync, hash } from 'bcryptjs'; import { Container } from 'typedi'; -import * as Db from '@/Db'; import * as ResponseHelper from '@/ResponseHelper'; import type { WhereClause } from '@/Interfaces'; import type { User } from '@db/entities/User'; @@ -11,6 +10,7 @@ import config from '@/config'; import { License } from '@/License'; import { getWebhookBaseUrl } from '@/WebhookHelpers'; import { RoleService } from '@/services/role.service'; +import { UserRepository } from '@db/repositories/user.repository'; export function isSharingEnabled(): boolean { return Container.get(License).isSharingEnabled(); @@ -19,7 +19,7 @@ export function isSharingEnabled(): boolean { export async function getInstanceOwner() { const globalOwnerRole = await Container.get(RoleService).findGlobalOwnerRole(); - return Db.collections.User.findOneOrFail({ + return Container.get(UserRepository).findOneOrFail({ relations: ['globalRole'], where: { globalRoleId: globalOwnerRole.id, @@ -77,7 +77,7 @@ export function validatePassword(password?: string): string { } export async function getUserById(userId: string): Promise { - const user = await Db.collections.User.findOneOrFail({ + const user = await Container.get(UserRepository).findOneOrFail({ where: { id: userId }, relations: ['globalRole'], }); diff --git a/packages/cli/src/WaitTracker.ts b/packages/cli/src/WaitTracker.ts index cbf21f51ff..c5bc493fc6 100644 --- a/packages/cli/src/WaitTracker.ts +++ b/packages/cli/src/WaitTracker.ts @@ -13,7 +13,7 @@ import type { } from '@/Interfaces'; import { WorkflowRunner } from '@/WorkflowRunner'; import { recoverExecutionDataFromEventLogMessages } from './eventbus/MessageEventBus/recoverEvents'; -import { ExecutionRepository } from '@db/repositories'; +import { ExecutionRepository } from '@db/repositories/execution.repository'; import type { ExecutionEntity } from '@db/entities/ExecutionEntity'; import { OwnershipService } from './services/ownership.service'; import { Logger } from '@/Logger'; diff --git a/packages/cli/src/WaitingWebhooks.ts b/packages/cli/src/WaitingWebhooks.ts index 501724dffb..a37f76ad51 100644 --- a/packages/cli/src/WaitingWebhooks.ts +++ b/packages/cli/src/WaitingWebhooks.ts @@ -12,7 +12,7 @@ import type { WaitingWebhookRequest, } from '@/Interfaces'; import * as WorkflowExecuteAdditionalData from '@/WorkflowExecuteAdditionalData'; -import { ExecutionRepository } from '@db/repositories'; +import { ExecutionRepository } from '@db/repositories/execution.repository'; import { OwnershipService } from './services/ownership.service'; import { Logger } from '@/Logger'; diff --git a/packages/cli/src/WorkflowCredentials.ts b/packages/cli/src/WorkflowCredentials.ts index cb0fc4c4b7..b05b5e18ec 100644 --- a/packages/cli/src/WorkflowCredentials.ts +++ b/packages/cli/src/WorkflowCredentials.ts @@ -1,5 +1,6 @@ +import Container from 'typedi'; import type { INode, IWorkflowCredentials } from 'n8n-workflow'; -import * as Db from '@/Db'; +import { CredentialsRepository } from '@db/repositories/credentials.repository'; // eslint-disable-next-line @typescript-eslint/naming-convention export async function WorkflowCredentials(nodes: INode[]): Promise { @@ -29,7 +30,7 @@ export async function WorkflowCredentials(nodes: INode[]): Promise { const skippedTypes = ['n8n-nodes-base.start', 'n8n-nodes-base.stickyNote']; const workflowOwnerRole = await Container.get(RoleService).findWorkflowOwnerRole(); - const ownedWorkflowsIds = await Db.collections.SharedWorkflow.find({ - where: { - userId: user.id, - roleId: workflowOwnerRole?.id, - }, - select: ['workflowId'], - }).then((ownedWorkflows) => ownedWorkflows.map(({ workflowId }) => workflowId)); + const ownedWorkflowsIds = await Container.get(SharedWorkflowRepository) + .find({ + where: { + userId: user.id, + roleId: workflowOwnerRole?.id, + }, + select: ['workflowId'], + }) + .then((ownedWorkflows) => ownedWorkflows.map(({ workflowId }) => workflowId)); if (ownedWorkflowsIds.length > 15) { belowThreshold = false; } else { // just fetch workflows' nodes to keep memory footprint low - const workflows = await Db.collections.Workflow.find({ + const workflows = await Container.get(WorkflowRepository).find({ where: { id: In(ownedWorkflowsIds) }, select: ['nodes'], }); diff --git a/packages/cli/src/WorkflowRunner.ts b/packages/cli/src/WorkflowRunner.ts index ed1608b110..74fab551b7 100644 --- a/packages/cli/src/WorkflowRunner.ts +++ b/packages/cli/src/WorkflowRunner.ts @@ -48,7 +48,7 @@ import { PermissionChecker } from '@/UserManagement/PermissionChecker'; import { Push } from '@/push'; import { Container } from 'typedi'; import { InternalHooks } from './InternalHooks'; -import { ExecutionRepository } from '@db/repositories'; +import { ExecutionRepository } from '@db/repositories/execution.repository'; import { Logger } from './Logger'; export class WorkflowRunner { diff --git a/packages/cli/src/audit/index.ts b/packages/cli/src/audit/index.ts index a8c3e79e18..0d73b8a542 100644 --- a/packages/cli/src/audit/index.ts +++ b/packages/cli/src/audit/index.ts @@ -1,4 +1,3 @@ -import * as Db from '@/Db'; import { separate } from '@/utils'; import config from '@/config'; import { RISK_CATEGORIES } from '@/audit/constants'; @@ -9,6 +8,8 @@ import { reportNodesRisk } from '@/audit/risks/nodes.risk'; import { reportFilesystemRisk } from '@/audit/risks/filesystem.risk'; import { reportInstanceRisk } from '@/audit/risks/instance.risk'; import type { Risk } from '@/audit/types'; +import Container from 'typedi'; +import { WorkflowRepository } from '@db/repositories/workflow.repository'; export const SYNC_MAP: Record = { database: reportDatabaseRisk, @@ -35,7 +36,7 @@ export async function audit( config.set('security.audit.daysAbandonedWorkflow', daysAbandonedWorkflow); } - const workflows = await Db.collections.Workflow.find({ + const workflows = await Container.get(WorkflowRepository).find({ select: ['id', 'name', 'active', 'nodes', 'connections'], }); diff --git a/packages/cli/src/audit/risks/credentials.risk.ts b/packages/cli/src/audit/risks/credentials.risk.ts index 57cfb4049f..31df1f44fe 100644 --- a/packages/cli/src/audit/risks/credentials.risk.ts +++ b/packages/cli/src/audit/risks/credentials.risk.ts @@ -6,11 +6,9 @@ import config from '@/config'; import { CREDENTIALS_REPORT } from '@/audit/constants'; import type { Risk } from '@/audit/types'; import type { WorkflowEntity } from '@db/entities/WorkflowEntity'; -import { - CredentialsRepository, - ExecutionDataRepository, - ExecutionRepository, -} from '@db/repositories'; +import { CredentialsRepository } from '@db/repositories/credentials.repository'; +import { ExecutionRepository } from '@db/repositories/execution.repository'; +import { ExecutionDataRepository } from '@db/repositories/executionData.repository'; async function getAllCredsInUse(workflows: WorkflowEntity[]) { const credsInAnyUse = new Set(); diff --git a/packages/cli/src/auth/jwt.ts b/packages/cli/src/auth/jwt.ts index 7a1113170f..844dbc420a 100644 --- a/packages/cli/src/auth/jwt.ts +++ b/packages/cli/src/auth/jwt.ts @@ -1,7 +1,6 @@ import jwt from 'jsonwebtoken'; import type { Response } from 'express'; import { createHash } from 'crypto'; -import * as Db from '@/Db'; import { AUTH_COOKIE_NAME, RESPONSE_ERROR_MESSAGES } from '@/constants'; import type { JwtPayload, JwtToken } from '@/Interfaces'; import type { User } from '@db/entities/User'; @@ -9,6 +8,7 @@ import config from '@/config'; import * as ResponseHelper from '@/ResponseHelper'; import { License } from '@/License'; import { Container } from 'typedi'; +import { UserRepository } from '@db/repositories/user.repository'; export function issueJWT(user: User): JwtToken { const { id, email, password } = user; @@ -50,7 +50,7 @@ export const createPasswordSha = (user: User) => .digest('hex'); export async function resolveJwtContent(jwtPayload: JwtPayload): Promise { - const user = await Db.collections.User.findOne({ + const user = await Container.get(UserRepository).findOne({ where: { id: jwtPayload.id }, relations: ['globalRole'], }); diff --git a/packages/cli/src/auth/methods/email.ts b/packages/cli/src/auth/methods/email.ts index d1e7475381..5f8f79005d 100644 --- a/packages/cli/src/auth/methods/email.ts +++ b/packages/cli/src/auth/methods/email.ts @@ -1,16 +1,16 @@ -import * as Db from '@/Db'; import type { User } from '@db/entities/User'; import { compareHash } from '@/UserManagement/UserManagementHelper'; import * as ResponseHelper from '@/ResponseHelper'; import { Container } from 'typedi'; import { InternalHooks } from '@/InternalHooks'; import { isLdapLoginEnabled } from '@/Ldap/helpers'; +import { UserRepository } from '@db/repositories/user.repository'; export const handleEmailLogin = async ( email: string, password: string, ): Promise => { - const user = await Db.collections.User.findOne({ + const user = await Container.get(UserRepository).findOne({ where: { email }, relations: ['globalRole', 'authIdentities'], }); diff --git a/packages/cli/src/collaboration/collaboration.state.ts b/packages/cli/src/collaboration/collaboration.state.ts index e5262ade12..02dff0d450 100644 --- a/packages/cli/src/collaboration/collaboration.state.ts +++ b/packages/cli/src/collaboration/collaboration.state.ts @@ -1,4 +1,4 @@ -import type { User } from '@/databases/entities/User'; +import type { User } from '@db/entities/User'; import type { Workflow } from 'n8n-workflow'; import { Service } from 'typedi'; diff --git a/packages/cli/src/commands/BaseCommand.ts b/packages/cli/src/commands/BaseCommand.ts index 445685d1d5..eb3f32de1f 100644 --- a/packages/cli/src/commands/BaseCommand.ts +++ b/packages/cli/src/commands/BaseCommand.ts @@ -20,7 +20,7 @@ import { PostHogClient } from '@/posthog'; import { License } from '@/License'; import { ExternalSecretsManager } from '@/ExternalSecrets/ExternalSecretsManager.ee'; import { initExpressionEvaluator } from '@/ExpressionEvalator'; -import { generateHostInstanceId } from '../databases/utils/generators'; +import { generateHostInstanceId } from '@db/utils/generators'; import { WorkflowHistoryManager } from '@/workflows/workflowHistory/workflowHistoryManager.ee'; export abstract class BaseCommand extends Command { diff --git a/packages/cli/src/commands/execute.ts b/packages/cli/src/commands/execute.ts index f50d6c7f53..042632d4ea 100644 --- a/packages/cli/src/commands/execute.ts +++ b/packages/cli/src/commands/execute.ts @@ -5,13 +5,13 @@ import type { IWorkflowBase } from 'n8n-workflow'; import { ExecutionBaseError } from 'n8n-workflow'; import { ActiveExecutions } from '@/ActiveExecutions'; -import * as Db from '@/Db'; import { WorkflowRunner } from '@/WorkflowRunner'; import type { IWorkflowExecutionDataProcess } from '@/Interfaces'; import { getInstanceOwner } from '@/UserManagement/UserManagementHelper'; import { findCliWorkflowStart, isWorkflowIdValid } from '@/utils'; import { BaseCommand } from './BaseCommand'; import { Container } from 'typedi'; +import { WorkflowRepository } from '@db/repositories/workflow.repository'; export class Execute extends BaseCommand { static description = '\nExecutes a given workflow'; @@ -81,7 +81,7 @@ export class Execute extends BaseCommand { if (flags.id) { // Id of workflow is given workflowId = flags.id; - workflowData = await Db.collections.Workflow.findOneBy({ id: workflowId }); + workflowData = await Container.get(WorkflowRepository).findOneBy({ id: workflowId }); if (workflowData === null) { this.logger.info(`The workflow with the id "${workflowId}" does not exist.`); process.exit(1); diff --git a/packages/cli/src/commands/executeBatch.ts b/packages/cli/src/commands/executeBatch.ts index a20348c92e..4af312cbab 100644 --- a/packages/cli/src/commands/executeBatch.ts +++ b/packages/cli/src/commands/executeBatch.ts @@ -9,7 +9,6 @@ import { diff } from 'json-diff'; import pick from 'lodash/pick'; import { ActiveExecutions } from '@/ActiveExecutions'; -import * as Db from '@/Db'; import { WorkflowRunner } from '@/WorkflowRunner'; import type { IWorkflowDb, IWorkflowExecutionDataProcess } from '@/Interfaces'; import type { User } from '@db/entities/User'; @@ -24,6 +23,7 @@ import type { IResult, IWorkflowExecutionProgress, } from '../types/commands.types'; +import { WorkflowRepository } from '@db/repositories/workflow.repository'; const re = /\d+/; @@ -278,7 +278,7 @@ export class ExecuteBatch extends BaseCommand { ExecuteBatch.instanceOwner = await getInstanceOwner(); - const query = Db.collections.Workflow.createQueryBuilder('workflows'); + const query = Container.get(WorkflowRepository).createQueryBuilder('workflows'); if (ids.length > 0) { query.andWhere('workflows.id in (:...ids)', { ids }); diff --git a/packages/cli/src/commands/export/credentials.ts b/packages/cli/src/commands/export/credentials.ts index 6c1304e671..1004e0d617 100644 --- a/packages/cli/src/commands/export/credentials.ts +++ b/packages/cli/src/commands/export/credentials.ts @@ -3,9 +3,10 @@ import fs from 'fs'; import path from 'path'; import type { FindOptionsWhere } from 'typeorm'; import { Credentials } from 'n8n-core'; -import * as Db from '@/Db'; import type { ICredentialsDb, ICredentialsDecryptedDb } from '@/Interfaces'; import { BaseCommand } from '../BaseCommand'; +import { CredentialsRepository } from '@db/repositories/credentials.repository'; +import Container from 'typedi'; export class ExportCredentialsCommand extends BaseCommand { static description = 'Export credentials'; @@ -110,7 +111,8 @@ export class ExportCredentialsCommand extends BaseCommand { findQuery.id = flags.id; } - const credentials: ICredentialsDb[] = await Db.collections.Credentials.findBy(findQuery); + const credentials: ICredentialsDb[] = + await Container.get(CredentialsRepository).findBy(findQuery); if (flags.decrypted) { for (let i = 0; i < credentials.length; i++) { diff --git a/packages/cli/src/commands/export/workflow.ts b/packages/cli/src/commands/export/workflow.ts index 873b69b80c..ab8ad60283 100644 --- a/packages/cli/src/commands/export/workflow.ts +++ b/packages/cli/src/commands/export/workflow.ts @@ -2,9 +2,10 @@ import { flags } from '@oclif/command'; import fs from 'fs'; import path from 'path'; import type { FindOptionsWhere } from 'typeorm'; -import * as Db from '@/Db'; import type { WorkflowEntity } from '@db/entities/WorkflowEntity'; import { BaseCommand } from '../BaseCommand'; +import { WorkflowRepository } from '@db/repositories/workflow.repository'; +import Container from 'typedi'; export class ExportWorkflowsCommand extends BaseCommand { static description = 'Export workflows'; @@ -104,7 +105,7 @@ export class ExportWorkflowsCommand extends BaseCommand { findQuery.id = flags.id; } - const workflows = await Db.collections.Workflow.find({ + const workflows = await Container.get(WorkflowRepository).find({ where: findQuery, relations: ['tags'], }); diff --git a/packages/cli/src/commands/import/credentials.ts b/packages/cli/src/commands/import/credentials.ts index 5e97e000df..3751903038 100644 --- a/packages/cli/src/commands/import/credentials.ts +++ b/packages/cli/src/commands/import/credentials.ts @@ -15,6 +15,7 @@ import type { ICredentialsEncrypted } from 'n8n-workflow'; import { jsonParse } from 'n8n-workflow'; import { RoleService } from '@/services/role.service'; import { UM_FIX_INSTRUCTION } from '@/constants'; +import { UserRepository } from '@db/repositories/user.repository'; export class ImportCredentialsCommand extends BaseCommand { static description = 'Import credentials'; @@ -175,7 +176,7 @@ export class ImportCredentialsCommand extends BaseCommand { const owner = ownerGlobalRole && - (await Db.collections.User.findOneBy({ globalRoleId: ownerGlobalRole.id })); + (await Container.get(UserRepository).findOneBy({ globalRoleId: ownerGlobalRole.id })); if (!owner) { throw new Error(`Failed to find owner. ${UM_FIX_INSTRUCTION}`); @@ -185,7 +186,7 @@ export class ImportCredentialsCommand extends BaseCommand { } private async getAssignee(userId: string) { - const user = await Db.collections.User.findOneBy({ id: userId }); + const user = await Container.get(UserRepository).findOneBy({ id: userId }); if (!user) { throw new Error(`Failed to find user with ID ${userId}`); diff --git a/packages/cli/src/commands/import/workflow.ts b/packages/cli/src/commands/import/workflow.ts index 177014e460..42c0158484 100644 --- a/packages/cli/src/commands/import/workflow.ts +++ b/packages/cli/src/commands/import/workflow.ts @@ -19,6 +19,8 @@ import { generateNanoId } from '@db/utils/generators'; import { RoleService } from '@/services/role.service'; import { TagService } from '@/services/tag.service'; import { UM_FIX_INSTRUCTION } from '@/constants'; +import { UserRepository } from '@db/repositories/user.repository'; +import { CredentialsRepository } from '@db/repositories/credentials.repository'; function assertHasWorkflowsToImport(workflows: unknown): asserts workflows is IWorkflowToImport[] { if (!Array.isArray(workflows)) { @@ -95,7 +97,7 @@ export class ImportWorkflowsCommand extends BaseCommand { await this.initOwnerWorkflowRole(); const user = flags.userId ? await this.getAssignee(flags.userId) : await this.getOwner(); - const credentials = await Db.collections.Credentials.find(); + const credentials = await Container.get(CredentialsRepository).find(); const tags = await this.tagService.getAll(); let totalImported = 0; @@ -239,7 +241,7 @@ export class ImportWorkflowsCommand extends BaseCommand { const owner = ownerGlobalRole && - (await Db.collections.User.findOneBy({ globalRoleId: ownerGlobalRole?.id })); + (await Container.get(UserRepository).findOneBy({ globalRoleId: ownerGlobalRole?.id })); if (!owner) { throw new Error(`Failed to find owner. ${UM_FIX_INSTRUCTION}`); @@ -249,7 +251,7 @@ export class ImportWorkflowsCommand extends BaseCommand { } private async getAssignee(userId: string) { - const user = await Db.collections.User.findOneBy({ id: userId }); + const user = await Container.get(UserRepository).findOneBy({ id: userId }); if (!user) { throw new Error(`Failed to find user with ID ${userId}`); diff --git a/packages/cli/src/commands/ldap/reset.ts b/packages/cli/src/commands/ldap/reset.ts index c024bcf0ba..c67b9973e2 100644 --- a/packages/cli/src/commands/ldap/reset.ts +++ b/packages/cli/src/commands/ldap/reset.ts @@ -1,22 +1,25 @@ -import * as Db from '@/Db'; +import Container from 'typedi'; import { LDAP_DEFAULT_CONFIGURATION, LDAP_FEATURE_NAME } from '@/Ldap/constants'; import { In } from 'typeorm'; +import { AuthIdentityRepository } from '@db/repositories/authIdentity.repository'; +import { AuthProviderSyncHistoryRepository } from '@db/repositories/authProviderSyncHistory.repository'; +import { SettingsRepository } from '@db/repositories/settings.repository'; +import { UserRepository } from '@db/repositories/user.repository'; import { BaseCommand } from '../BaseCommand'; export class Reset extends BaseCommand { static description = '\nResets the database to the default ldap state'; async run(): Promise { - const { AuthIdentity, AuthProviderSyncHistory, Settings, User } = Db.collections; - const ldapIdentities = await AuthIdentity.find({ + const ldapIdentities = await Container.get(AuthIdentityRepository).find({ where: { providerType: 'ldap' }, select: ['userId'], }); - await AuthProviderSyncHistory.delete({ providerType: 'ldap' }); - await AuthIdentity.delete({ providerType: 'ldap' }); - await User.delete({ id: In(ldapIdentities.map((i) => i.userId)) }); - await Settings.delete({ key: LDAP_FEATURE_NAME }); - await Settings.insert({ + await Container.get(AuthProviderSyncHistoryRepository).delete({ providerType: 'ldap' }); + await Container.get(AuthIdentityRepository).delete({ providerType: 'ldap' }); + await Container.get(UserRepository).delete({ id: In(ldapIdentities.map((i) => i.userId)) }); + await Container.get(SettingsRepository).delete({ key: LDAP_FEATURE_NAME }); + await Container.get(SettingsRepository).insert({ key: LDAP_FEATURE_NAME, value: JSON.stringify(LDAP_DEFAULT_CONFIGURATION), loadOnStartup: true, diff --git a/packages/cli/src/commands/license/clear.ts b/packages/cli/src/commands/license/clear.ts index d7e3bf51d3..e25fb94dc4 100644 --- a/packages/cli/src/commands/license/clear.ts +++ b/packages/cli/src/commands/license/clear.ts @@ -1,6 +1,7 @@ -import * as Db from '@/Db'; import { SETTINGS_LICENSE_CERT_KEY } from '@/constants'; import { BaseCommand } from '../BaseCommand'; +import { SettingsRepository } from '@db/repositories/settings.repository'; +import Container from 'typedi'; export class ClearLicenseCommand extends BaseCommand { static description = 'Clear license'; @@ -9,7 +10,7 @@ export class ClearLicenseCommand extends BaseCommand { async run() { this.logger.info('Clearing license from database.'); - await Db.collections.Settings.delete({ + await Container.get(SettingsRepository).delete({ key: SETTINGS_LICENSE_CERT_KEY, }); this.logger.info('Done. Restart n8n to take effect.'); diff --git a/packages/cli/src/commands/list/workflow.ts b/packages/cli/src/commands/list/workflow.ts index da9d37f81c..ce0659dcd9 100644 --- a/packages/cli/src/commands/list/workflow.ts +++ b/packages/cli/src/commands/list/workflow.ts @@ -1,8 +1,9 @@ import { flags } from '@oclif/command'; import type { FindOptionsWhere } from 'typeorm'; -import * as Db from '@/Db'; import type { WorkflowEntity } from '@db/entities/WorkflowEntity'; import { BaseCommand } from '../BaseCommand'; +import { WorkflowRepository } from '@db/repositories/workflow.repository'; +import Container from 'typedi'; export class ListWorkflowCommand extends BaseCommand { static description = '\nList workflows'; @@ -36,7 +37,7 @@ export class ListWorkflowCommand extends BaseCommand { findQuery.active = flags.active === 'true'; } - const workflows = await Db.collections.Workflow.findBy(findQuery); + const workflows = await Container.get(WorkflowRepository).findBy(findQuery); if (flags.onlyId) { workflows.forEach((workflow) => this.logger.info(workflow.id)); } else { diff --git a/packages/cli/src/commands/mfa/disable.ts b/packages/cli/src/commands/mfa/disable.ts index 6c5eb2fb9c..a9a51db5ba 100644 --- a/packages/cli/src/commands/mfa/disable.ts +++ b/packages/cli/src/commands/mfa/disable.ts @@ -1,6 +1,7 @@ import { flags } from '@oclif/command'; -import * as Db from '@/Db'; import { BaseCommand } from '../BaseCommand'; +import Container from 'typedi'; +import { UserRepository } from '@db/repositories/user.repository'; export class DisableMFACommand extends BaseCommand { static description = 'Disable MFA authentication for a user'; @@ -27,7 +28,7 @@ export class DisableMFACommand extends BaseCommand { return; } - const updateOperationResult = await Db.collections.User.update( + const updateOperationResult = await Container.get(UserRepository).update( { email: flags.email }, { mfaSecret: null, mfaRecoveryCodes: [], mfaEnabled: false }, ); diff --git a/packages/cli/src/commands/start.ts b/packages/cli/src/commands/start.ts index 6d1c4b46b5..aacc1f7dd9 100644 --- a/packages/cli/src/commands/start.ts +++ b/packages/cli/src/commands/start.ts @@ -18,7 +18,6 @@ import config from '@/config'; import { ActiveExecutions } from '@/ActiveExecutions'; import { ActiveWorkflowRunner } from '@/ActiveWorkflowRunner'; -import * as Db from '@/Db'; import * as GenericHelpers from '@/GenericHelpers'; import { Server } from '@/Server'; import { EDITOR_UI_DIST_DIR, LICENSE_FEATURES } from '@/constants'; @@ -30,6 +29,8 @@ import { IConfig } from '@oclif/config'; import { SingleMainInstancePublisher } from '@/services/orchestration/main/SingleMainInstance.publisher'; import { OrchestrationHandlerMainService } from '@/services/orchestration/main/orchestration.handler.main.service'; import { PruningService } from '@/services/pruning.service'; +import { SettingsRepository } from '@db/repositories/settings.repository'; +import { ExecutionRepository } from '@db/repositories/execution.repository'; // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires const open = require('open'); @@ -286,7 +287,9 @@ export class Start extends BaseCommand { } // Load settings from database and set them to config. - const databaseSettings = await Db.collections.Settings.findBy({ loadOnStartup: true }); + const databaseSettings = await Container.get(SettingsRepository).findBy({ + loadOnStartup: true, + }); databaseSettings.forEach((setting) => { config.set(setting.key, jsonParse(setting.value, { fallbackValue: setting.value })); }); @@ -304,7 +307,7 @@ export class Start extends BaseCommand { if (dbType === 'sqlite') { const shouldRunVacuum = config.getEnv('database.sqlite.executeVacuumOnStartup'); if (shouldRunVacuum) { - await Db.collections.Execution.query('VACUUM;'); + await Container.get(ExecutionRepository).query('VACUUM;'); } } diff --git a/packages/cli/src/commands/update/workflow.ts b/packages/cli/src/commands/update/workflow.ts index b293e266e3..e78a6ebc77 100644 --- a/packages/cli/src/commands/update/workflow.ts +++ b/packages/cli/src/commands/update/workflow.ts @@ -1,9 +1,10 @@ import { flags } from '@oclif/command'; import type { FindOptionsWhere } from 'typeorm'; import type { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity'; -import * as Db from '@/Db'; import type { WorkflowEntity } from '@db/entities/WorkflowEntity'; import { BaseCommand } from '../BaseCommand'; +import { WorkflowRepository } from '@db/repositories/workflow.repository'; +import Container from 'typedi'; export class UpdateWorkflowCommand extends BaseCommand { static description = 'Update workflows'; @@ -64,7 +65,7 @@ export class UpdateWorkflowCommand extends BaseCommand { findQuery.active = true; } - await Db.collections.Workflow.update(findQuery, updateQuery); + await Container.get(WorkflowRepository).update(findQuery, updateQuery); this.logger.info('Done'); } diff --git a/packages/cli/src/commands/user-management/reset.ts b/packages/cli/src/commands/user-management/reset.ts index 64b1be3cf3..d04b561fdc 100644 --- a/packages/cli/src/commands/user-management/reset.ts +++ b/packages/cli/src/commands/user-management/reset.ts @@ -1,10 +1,14 @@ import { Container } from 'typedi'; import { Not } from 'typeorm'; -import * as Db from '@/Db'; import type { CredentialsEntity } from '@db/entities/CredentialsEntity'; import { User } from '@db/entities/User'; -import { BaseCommand } from '../BaseCommand'; +import { CredentialsRepository } from '@db/repositories/credentials.repository'; +import { SettingsRepository } from '@db/repositories/settings.repository'; +import { SharedCredentialsRepository } from '@db/repositories/sharedCredentials.repository'; +import { SharedWorkflowRepository } from '@db/repositories/sharedWorkflow.repository'; +import { UserRepository } from '@db/repositories/user.repository'; import { RoleService } from '@/services/role.service'; +import { BaseCommand } from '../BaseCommand'; const defaultUserProps = { firstName: null, @@ -24,34 +28,34 @@ export class Reset extends BaseCommand { const ownerWorkflowRole = await Container.get(RoleService).findWorkflowOwnerRole(); const ownerCredentialRole = await Container.get(RoleService).findCredentialOwnerRole(); - await Db.collections.SharedWorkflow.update( + await Container.get(SharedWorkflowRepository).update( { userId: Not(owner.id), roleId: ownerWorkflowRole.id }, { user: owner }, ); - await Db.collections.SharedCredentials.update( + await Container.get(SharedCredentialsRepository).update( { userId: Not(owner.id), roleId: ownerCredentialRole.id }, { user: owner }, ); - await Db.collections.User.delete({ id: Not(owner.id) }); - await Db.collections.User.save(Object.assign(owner, defaultUserProps)); + await Container.get(UserRepository).delete({ id: Not(owner.id) }); + await Container.get(UserRepository).save(Object.assign(owner, defaultUserProps)); - const danglingCredentials: CredentialsEntity[] = - await Db.collections.Credentials.createQueryBuilder('credentials') - .leftJoinAndSelect('credentials.shared', 'shared') - .where('shared.credentialsId is null') - .getMany(); + const danglingCredentials: CredentialsEntity[] = await Container.get(CredentialsRepository) + .createQueryBuilder('credentials') + .leftJoinAndSelect('credentials.shared', 'shared') + .where('shared.credentialsId is null') + .getMany(); const newSharedCredentials = danglingCredentials.map((credentials) => - Db.collections.SharedCredentials.create({ + Container.get(SharedCredentialsRepository).create({ credentials, user: owner, role: ownerCredentialRole, }), ); - await Db.collections.SharedCredentials.save(newSharedCredentials); + await Container.get(SharedCredentialsRepository).save(newSharedCredentials); - await Db.collections.Settings.update( + await Container.get(SettingsRepository).update( { key: 'userManagement.isInstanceOwnerSetUp' }, { value: 'false' }, ); @@ -62,7 +66,7 @@ export class Reset extends BaseCommand { async getInstanceOwner(): Promise { const globalRole = await Container.get(RoleService).findGlobalOwnerRole(); - const owner = await Db.collections.User.findOneBy({ globalRoleId: globalRole.id }); + const owner = await Container.get(UserRepository).findOneBy({ globalRoleId: globalRole.id }); if (owner) return owner; @@ -70,9 +74,9 @@ export class Reset extends BaseCommand { Object.assign(user, { ...defaultUserProps, globalRole }); - await Db.collections.User.save(user); + await Container.get(UserRepository).save(user); - return Db.collections.User.findOneByOrFail({ globalRoleId: globalRole.id }); + return Container.get(UserRepository).findOneByOrFail({ globalRoleId: globalRole.id }); } async catch(error: Error): Promise { diff --git a/packages/cli/src/commands/worker.ts b/packages/cli/src/commands/worker.ts index 5fb75b2c96..cc18c1cda3 100644 --- a/packages/cli/src/commands/worker.ts +++ b/packages/cli/src/commands/worker.ts @@ -27,7 +27,8 @@ import { Queue } from '@/Queue'; import { generateFailedExecutionFromError } from '@/WorkflowHelpers'; import { N8N_VERSION } from '@/constants'; import { BaseCommand } from './BaseCommand'; -import { ExecutionRepository } from '@db/repositories'; +import { ExecutionRepository } from '@db/repositories/execution.repository'; +import { WorkflowRepository } from '@db/repositories/workflow.repository'; import { OwnershipService } from '@/services/ownership.service'; import type { ICredentialsOverwrite } from '@/Interfaces'; import { CredentialsOverwrites } from '@/CredentialsOverwrites'; @@ -137,7 +138,7 @@ export class Worker extends BaseCommand { let { staticData } = fullExecutionData.workflowData; if (loadStaticData) { - const workflowData = await Db.collections.Workflow.findOne({ + const workflowData = await Container.get(WorkflowRepository).findOne({ select: ['id', 'staticData'], where: { id: workflowId, diff --git a/packages/cli/src/controllers/e2e.controller.ts b/packages/cli/src/controllers/e2e.controller.ts index f4a0c71e26..3b736e7038 100644 --- a/packages/cli/src/controllers/e2e.controller.ts +++ b/packages/cli/src/controllers/e2e.controller.ts @@ -3,7 +3,9 @@ import { Service } from 'typedi'; import { v4 as uuid } from 'uuid'; import config from '@/config'; import type { Role } from '@db/entities/Role'; -import { RoleRepository, SettingsRepository, UserRepository } from '@db/repositories'; +import { RoleRepository } from '@db/repositories/role.repository'; +import { SettingsRepository } from '@db/repositories/settings.repository'; +import { UserRepository } from '@db/repositories/user.repository'; import { ActiveWorkflowRunner } from '@/ActiveWorkflowRunner'; import { hashPassword } from '@/UserManagement/UserManagementHelper'; import { eventBus } from '@/eventbus/MessageEventBus/MessageEventBus'; diff --git a/packages/cli/src/controllers/oauth/abstractOAuth.controller.ts b/packages/cli/src/controllers/oauth/abstractOAuth.controller.ts index 274a2186f0..babf90f4c6 100644 --- a/packages/cli/src/controllers/oauth/abstractOAuth.controller.ts +++ b/packages/cli/src/controllers/oauth/abstractOAuth.controller.ts @@ -4,7 +4,8 @@ import type { ICredentialDataDecryptedObject, IWorkflowExecuteAdditionalData } f import config from '@/config'; import type { CredentialsEntity } from '@db/entities/CredentialsEntity'; import type { User } from '@db/entities/User'; -import { CredentialsRepository, SharedCredentialsRepository } from '@db/repositories'; +import { CredentialsRepository } from '@db/repositories/credentials.repository'; +import { SharedCredentialsRepository } from '@db/repositories/sharedCredentials.repository'; import type { ICredentialsDb } from '@/Interfaces'; import { getInstanceBaseUrl } from '@/UserManagement/UserManagementHelper'; import type { OAuthRequest } from '@/requests'; diff --git a/packages/cli/src/controllers/owner.controller.ts b/packages/cli/src/controllers/owner.controller.ts index 5578a60d4b..f16588d9f6 100644 --- a/packages/cli/src/controllers/owner.controller.ts +++ b/packages/cli/src/controllers/owner.controller.ts @@ -8,7 +8,7 @@ import { Response } from 'express'; import { Config } from '@/config'; import { OwnerRequest } from '@/requests'; import { IInternalHooksClass } from '@/Interfaces'; -import { SettingsRepository } from '@db/repositories'; +import { SettingsRepository } from '@db/repositories/settings.repository'; import { PostHogClient } from '@/posthog'; import { UserService } from '@/services/user.service'; import { Logger } from '@/Logger'; diff --git a/packages/cli/src/controllers/users.controller.ts b/packages/cli/src/controllers/users.controller.ts index 5382f4de6d..51acd9cfe5 100644 --- a/packages/cli/src/controllers/users.controller.ts +++ b/packages/cli/src/controllers/users.controller.ts @@ -29,7 +29,8 @@ import type { PublicUser, ITelemetryUserDeletionData } from '@/Interfaces'; import { AuthIdentity } from '@db/entities/AuthIdentity'; import { PostHogClient } from '@/posthog'; import { isSamlLicensedAndEnabled } from '../sso/saml/samlHelpers'; -import { SharedCredentialsRepository, SharedWorkflowRepository } from '@db/repositories'; +import { SharedCredentialsRepository } from '@db/repositories/sharedCredentials.repository'; +import { SharedWorkflowRepository } from '@db/repositories/sharedWorkflow.repository'; import { plainToInstance } from 'class-transformer'; import { License } from '@/License'; import { Container } from 'typedi'; diff --git a/packages/cli/src/controllers/workflowStatistics.controller.ts b/packages/cli/src/controllers/workflowStatistics.controller.ts index b506ac15df..ef80374296 100644 --- a/packages/cli/src/controllers/workflowStatistics.controller.ts +++ b/packages/cli/src/controllers/workflowStatistics.controller.ts @@ -3,7 +3,8 @@ import { Response, NextFunction } from 'express'; import { Get, Middleware, RestController } from '@/decorators'; import type { WorkflowStatistics } from '@db/entities/WorkflowStatistics'; import { StatisticsNames } from '@db/entities/WorkflowStatistics'; -import { SharedWorkflowRepository, WorkflowStatisticsRepository } from '@db/repositories'; +import { SharedWorkflowRepository } from '@db/repositories/sharedWorkflow.repository'; +import { WorkflowStatisticsRepository } from '@db/repositories/workflowStatistics.repository'; import { ExecutionRequest } from '@/requests'; import { whereClause } from '@/UserManagement/UserManagementHelper'; import { NotFoundError } from '@/ResponseHelper'; diff --git a/packages/cli/src/credentials/credentials.controller.ee.ts b/packages/cli/src/credentials/credentials.controller.ee.ts index b19000aee1..8ebfcb657b 100644 --- a/packages/cli/src/credentials/credentials.controller.ee.ts +++ b/packages/cli/src/credentials/credentials.controller.ee.ts @@ -10,7 +10,7 @@ import { EECredentialsService as EECredentials } from './credentials.service.ee' import { OwnershipService } from '@/services/ownership.service'; import { Container } from 'typedi'; import { InternalHooks } from '@/InternalHooks'; -import type { CredentialsEntity } from '@/databases/entities/CredentialsEntity'; +import type { CredentialsEntity } from '@db/entities/CredentialsEntity'; export const EECredentialsController = express.Router(); diff --git a/packages/cli/src/credentials/credentials.service.ee.ts b/packages/cli/src/credentials/credentials.service.ee.ts index 94bcaa29c3..67b65dcfb7 100644 --- a/packages/cli/src/credentials/credentials.service.ee.ts +++ b/packages/cli/src/credentials/credentials.service.ee.ts @@ -1,6 +1,5 @@ import type { DeleteResult, EntityManager, FindOptionsWhere } from 'typeorm'; import { In, Not } from 'typeorm'; -import * as Db from '@/Db'; import { CredentialsEntity } from '@db/entities/CredentialsEntity'; import { SharedCredentials } from '@db/entities/SharedCredentials'; import type { User } from '@db/entities/User'; @@ -8,6 +7,7 @@ import { UserService } from '@/services/user.service'; import { CredentialsService } from './credentials.service'; import { RoleService } from '@/services/role.service'; import Container from 'typedi'; +import { SharedCredentialsRepository } from '@db/repositories/sharedCredentials.repository'; export class EECredentialsService extends CredentialsService { static async isOwned( @@ -43,7 +43,7 @@ export class EECredentialsService extends CredentialsService { where.userId = user.id; } - return Db.collections.SharedCredentials.findOne({ + return Container.get(SharedCredentialsRepository).findOne({ where, relations, }); @@ -83,7 +83,7 @@ export class EECredentialsService extends CredentialsService { const newSharedCredentials = users .filter((user) => !user.isPending) .map((user) => - Db.collections.SharedCredentials.create({ + Container.get(SharedCredentialsRepository).create({ credentialsId: credential.id, userId: user.id, roleId: role?.id, diff --git a/packages/cli/src/credentials/credentials.service.ts b/packages/cli/src/credentials/credentials.service.ts index 13358a9f73..7c1c816ee8 100644 --- a/packages/cli/src/credentials/credentials.service.ts +++ b/packages/cli/src/credentials/credentials.service.ts @@ -25,13 +25,15 @@ import { CredentialTypes } from '@/CredentialTypes'; import { RoleService } from '@/services/role.service'; import { OwnershipService } from '@/services/ownership.service'; import { Logger } from '@/Logger'; +import { CredentialsRepository } from '@db/repositories/credentials.repository'; +import { SharedCredentialsRepository } from '@db/repositories/sharedCredentials.repository'; export class CredentialsService { static async get( where: FindOptionsWhere, options?: { relations: string[] }, ): Promise { - return Db.collections.Credentials.findOne({ + return Container.get(CredentialsRepository).findOne({ relations: options?.relations, where, }); @@ -88,14 +90,14 @@ export class CredentialsService { const isDefaultSelect = !options.listQueryOptions?.select; if (returnAll) { - const credentials = await Db.collections.Credentials.find(findManyOptions); + const credentials = await Container.get(CredentialsRepository).find(findManyOptions); return isDefaultSelect ? this.addOwnedByAndSharedWith(credentials) : credentials; } const ids = await this.getAccessibleCredentials(user.id); - const credentials = await Db.collections.Credentials.find({ + const credentials = await Container.get(CredentialsRepository).find({ ...findManyOptions, where: { ...findManyOptions.where, id: In(ids) }, // only accessible credentials }); @@ -107,7 +109,7 @@ export class CredentialsService { * Get the IDs of all credentials owned by or shared with a user. */ private static async getAccessibleCredentials(userId: string) { - const sharings = await Db.collections.SharedCredentials.find({ + const sharings = await Container.get(SharedCredentialsRepository).find({ relations: ['role'], where: { userId, @@ -125,7 +127,7 @@ export class CredentialsService { options.relations = ['shared', 'shared.user', 'shared.role']; } - return Db.collections.Credentials.find(options); + return Container.get(CredentialsRepository).find(options); } /** @@ -152,7 +154,7 @@ export class CredentialsService { } } - return Db.collections.SharedCredentials.findOne({ where, relations }); + return Container.get(SharedCredentialsRepository).findOne({ where, relations }); } static async prepareCreateData( @@ -162,7 +164,7 @@ export class CredentialsService { // This saves us a merge but requires some type casting. These // types are compatible for this case. - const newCredentials = Db.collections.Credentials.create(rest as ICredentialsDb); + const newCredentials = Container.get(CredentialsRepository).create(rest as ICredentialsDb); await validateEntity(newCredentials); @@ -185,7 +187,7 @@ export class CredentialsService { // This saves us a merge but requires some type casting. These // types are compatible for this case. - const updateData = Db.collections.Credentials.create(mergedData as ICredentialsDb); + const updateData = Container.get(CredentialsRepository).create(mergedData as ICredentialsDb); await validateEntity(updateData); @@ -234,11 +236,11 @@ export class CredentialsService { await Container.get(ExternalHooks).run('credentials.update', [newCredentialData]); // Update the credentials in DB - await Db.collections.Credentials.update(credentialId, newCredentialData); + await Container.get(CredentialsRepository).update(credentialId, newCredentialData); // We sadly get nothing back from "update". Neither if it updated a record // nor the new value. So query now the updated entry. - return Db.collections.Credentials.findOneBy({ id: credentialId }); + return Container.get(CredentialsRepository).findOneBy({ id: credentialId }); } static async save( @@ -281,7 +283,7 @@ export class CredentialsService { static async delete(credentials: CredentialsEntity): Promise { await Container.get(ExternalHooks).run('credentials.delete', [credentials.id]); - await Db.collections.Credentials.remove(credentials); + await Container.get(CredentialsRepository).remove(credentials); } static async test( diff --git a/packages/cli/src/databases/repositories/index.ts b/packages/cli/src/databases/repositories/index.ts deleted file mode 100644 index 5fc7499caf..0000000000 --- a/packages/cli/src/databases/repositories/index.ts +++ /dev/null @@ -1,21 +0,0 @@ -export { AuthIdentityRepository } from './authIdentity.repository'; -export { AuthProviderSyncHistoryRepository } from './authProviderSyncHistory.repository'; -export { CredentialsRepository } from './credentials.repository'; -export { EventDestinationsRepository } from './eventDestinations.repository'; -export { ExecutionDataRepository } from './executionData.repository'; -export { ExecutionMetadataRepository } from './executionMetadata.repository'; -export { ExecutionRepository } from './execution.repository'; -export { InstalledNodesRepository } from './installedNodes.repository'; -export { InstalledPackagesRepository } from './installedPackages.repository'; -export { RoleRepository } from './role.repository'; -export { SettingsRepository } from './settings.repository'; -export { SharedCredentialsRepository } from './sharedCredentials.repository'; -export { SharedWorkflowRepository } from './sharedWorkflow.repository'; -export { TagRepository } from './tag.repository'; -export { UserRepository } from './user.repository'; -export { VariablesRepository } from './variables.repository'; -export { WebhookRepository } from './webhook.repository'; -export { WorkflowHistoryRepository } from './workflowHistory.repository'; -export { WorkflowRepository } from './workflow.repository'; -export { WorkflowStatisticsRepository } from './workflowStatistics.repository'; -export { WorkflowTagMappingRepository } from './workflowTagMapping.repository'; diff --git a/packages/cli/src/environments/sourceControl/sourceControl.service.ee.ts b/packages/cli/src/environments/sourceControl/sourceControl.service.ee.ts index 67dac2945e..d3c5c48155 100644 --- a/packages/cli/src/environments/sourceControl/sourceControl.service.ee.ts +++ b/packages/cli/src/environments/sourceControl/sourceControl.service.ee.ts @@ -33,7 +33,7 @@ import type { Variables } from '@db/entities/Variables'; import type { SourceControlWorkflowVersionId } from './types/sourceControlWorkflowVersionId'; import type { ExportableCredential } from './types/exportableCredential'; import { InternalHooks } from '@/InternalHooks'; -import { TagRepository } from '@/databases/repositories'; +import { TagRepository } from '@db/repositories/tag.repository'; import { Logger } from '@/Logger'; @Service() diff --git a/packages/cli/src/environments/sourceControl/sourceControlExport.service.ee.ts b/packages/cli/src/environments/sourceControl/sourceControlExport.service.ee.ts index 025cf4b70d..767e7f3c3d 100644 --- a/packages/cli/src/environments/sourceControl/sourceControlExport.service.ee.ts +++ b/packages/cli/src/environments/sourceControl/sourceControlExport.service.ee.ts @@ -1,4 +1,4 @@ -import { Service } from 'typedi'; +import Container, { Service } from 'typedi'; import path from 'path'; import { SOURCE_CONTROL_CREDENTIAL_EXPORT_FOLDER, @@ -6,7 +6,6 @@ import { SOURCE_CONTROL_TAGS_EXPORT_FILE, SOURCE_CONTROL_WORKFLOW_EXPORT_FOLDER, } from './constants'; -import * as Db from '@/Db'; import type { ICredentialDataDecryptedObject } from 'n8n-workflow'; import { writeFile as fsWriteFile, rm as fsRm } from 'fs/promises'; import { rmSync } from 'fs'; @@ -25,8 +24,12 @@ import type { WorkflowEntity } from '@db/entities/WorkflowEntity'; import { In } from 'typeorm'; import type { SourceControlledFile } from './types/sourceControlledFile'; import { VariablesService } from '../variables/variables.service'; -import { TagRepository } from '@/databases/repositories'; +import { TagRepository } from '@db/repositories/tag.repository'; +import { WorkflowRepository } from '@db/repositories/workflow.repository'; import { Logger } from '@/Logger'; +import { SharedCredentialsRepository } from '@db/repositories/sharedCredentials.repository'; +import { SharedWorkflowRepository } from '@db/repositories/sharedWorkflow.repository'; +import { WorkflowTagMappingRepository } from '@db/repositories/workflowTagMapping.repository'; @Service() export class SourceControlExportService { @@ -102,7 +105,7 @@ export class SourceControlExportService { try { sourceControlFoldersExistCheck([this.workflowExportFolder]); const workflowIds = candidates.map((e) => e.id); - const sharedWorkflows = await Db.collections.SharedWorkflow.find({ + const sharedWorkflows = await Container.get(SharedWorkflowRepository).find({ relations: ['role', 'user'], where: { role: { @@ -112,7 +115,7 @@ export class SourceControlExportService { workflowId: In(workflowIds), }, }); - const workflows = await Db.collections.Workflow.find({ + const workflows = await Container.get(WorkflowRepository).find({ where: { id: In(workflowIds), }, @@ -181,7 +184,7 @@ export class SourceControlExportService { files: [], }; } - const mappings = await Db.collections.WorkflowTagMapping.find(); + const mappings = await Container.get(WorkflowTagMappingRepository).find(); const fileName = path.join(this.gitFolder, SOURCE_CONTROL_TAGS_EXPORT_FILE); await fsWriteFile( fileName, @@ -236,7 +239,7 @@ export class SourceControlExportService { try { sourceControlFoldersExistCheck([this.credentialExportFolder]); const credentialIds = candidates.map((e) => e.id); - const credentialsToBeExported = await Db.collections.SharedCredentials.find({ + const credentialsToBeExported = await Container.get(SharedCredentialsRepository).find({ relations: ['credentials', 'role', 'user'], where: { credentialsId: In(credentialIds), diff --git a/packages/cli/src/environments/sourceControl/sourceControlImport.service.ee.ts b/packages/cli/src/environments/sourceControl/sourceControlImport.service.ee.ts index efc17ab7c3..41e14da8a4 100644 --- a/packages/cli/src/environments/sourceControl/sourceControlImport.service.ee.ts +++ b/packages/cli/src/environments/sourceControl/sourceControlImport.service.ee.ts @@ -7,7 +7,6 @@ import { SOURCE_CONTROL_VARIABLES_EXPORT_FILE, SOURCE_CONTROL_WORKFLOW_EXPORT_FOLDER, } from './constants'; -import * as Db from '@/Db'; import glob from 'fast-glob'; import { jsonParse } from 'n8n-workflow'; import { readFile as fsReadFile } from 'fs/promises'; @@ -26,9 +25,16 @@ import { getCredentialExportPath, getWorkflowExportPath } from './sourceControlH import type { SourceControlledFile } from './types/sourceControlledFile'; import { RoleService } from '@/services/role.service'; import { VariablesService } from '../variables/variables.service'; -import { TagRepository } from '@/databases/repositories'; +import { TagRepository } from '@db/repositories/tag.repository'; +import { WorkflowRepository } from '@db/repositories/workflow.repository'; +import { UserRepository } from '@db/repositories/user.repository'; import { UM_FIX_INSTRUCTION } from '@/constants'; import { Logger } from '@/Logger'; +import { CredentialsRepository } from '@db/repositories/credentials.repository'; +import { SharedCredentialsRepository } from '@db/repositories/sharedCredentials.repository'; +import { SharedWorkflowRepository } from '@db/repositories/sharedWorkflow.repository'; +import { WorkflowTagMappingRepository } from '@db/repositories/workflowTagMapping.repository'; +import { VariablesRepository } from '@db/repositories/variables.repository'; @Service() export class SourceControlImportService { @@ -110,7 +116,7 @@ export class SourceControlImportService { } public async getLocalVersionIdsFromDb(): Promise { - const localWorkflows = await Db.collections.Workflow.find({ + const localWorkflows = await Container.get(WorkflowRepository).find({ select: ['id', 'name', 'versionId', 'updatedAt'], }); return localWorkflows.map((local) => ({ @@ -153,7 +159,7 @@ export class SourceControlImportService { public async getLocalCredentialsFromDb(): Promise< Array > { - const localCredentials = await Db.collections.Credentials.find({ + const localCredentials = await Container.get(CredentialsRepository).find({ select: ['id', 'name', 'type', 'nodesAccess'], }); return localCredentials.map((local) => ({ @@ -209,7 +215,7 @@ export class SourceControlImportService { const localTags = await this.tagRepository.find({ select: ['id', 'name'], }); - const localMappings = await Db.collections.WorkflowTagMapping.find({ + const localMappings = await Container.get(WorkflowTagMappingRepository).find({ select: ['workflowId', 'tagId'], }); return { tags: localTags, mappings: localMappings }; @@ -219,13 +225,13 @@ export class SourceControlImportService { const ownerWorkflowRole = await this.getWorkflowOwnerRole(); const workflowRunner = this.activeWorkflowRunner; const candidateIds = candidates.map((c) => c.id); - const existingWorkflows = await Db.collections.Workflow.find({ + const existingWorkflows = await Container.get(WorkflowRepository).find({ where: { id: In(candidateIds), }, select: ['id', 'name', 'versionId', 'active'], }); - const allSharedWorkflows = await Db.collections.SharedWorkflow.find({ + const allSharedWorkflows = await Container.get(SharedWorkflowRepository).find({ where: { workflowId: In(candidateIds), }, @@ -244,7 +250,10 @@ export class SourceControlImportService { const existingWorkflow = existingWorkflows.find((e) => e.id === importedWorkflow.id); importedWorkflow.active = existingWorkflow?.active ?? false; this.logger.debug(`Updating workflow id ${importedWorkflow.id ?? 'new'}`); - const upsertResult = await Db.collections.Workflow.upsert({ ...importedWorkflow }, ['id']); + const upsertResult = await Container.get(WorkflowRepository).upsert( + { ...importedWorkflow }, + ['id'], + ); if (upsertResult?.identifiers?.length !== 1) { throw new Error(`Failed to upsert workflow ${importedWorkflow.id ?? 'new'}`); } @@ -254,7 +263,7 @@ export class SourceControlImportService { if (cachedOwnerIds.has(importedWorkflow.owner)) { workflowOwnerId = cachedOwnerIds.get(importedWorkflow.owner) ?? userId; } else { - const foundUser = await Db.collections.User.findOne({ + const foundUser = await Container.get(UserRepository).findOne({ where: { email: importedWorkflow.owner, }, @@ -278,7 +287,7 @@ export class SourceControlImportService { ); if (!existingSharedWorkflowOwnerByUserId && !existingSharedWorkflowOwnerByRoleId) { // no owner exists yet, so create one - await Db.collections.SharedWorkflow.insert({ + await Container.get(SharedWorkflowRepository).insert({ workflowId: importedWorkflow.id, userId: workflowOwnerId, roleId: ownerWorkflowRole.id, @@ -288,7 +297,7 @@ export class SourceControlImportService { } else if (existingSharedWorkflowOwnerByUserId && !existingSharedWorkflowOwnerByRoleId) { // if the worklflow has a non-global owner that is referenced by the owner file, // and no existing global owner, update the owner to the user referenced in the owner file - await Db.collections.SharedWorkflow.update( + await Container.get(SharedWorkflowRepository).update( { workflowId: importedWorkflow.id, userId: workflowOwnerId, @@ -310,7 +319,7 @@ export class SourceControlImportService { } catch (error) { this.logger.error(`Failed to activate workflow ${existingWorkflow.id}`, error as Error); } finally { - await Db.collections.Workflow.update( + await Container.get(WorkflowRepository).update( { id: existingWorkflow.id }, { versionId: importedWorkflow.versionId }, ); @@ -331,7 +340,7 @@ export class SourceControlImportService { public async importCredentialsFromWorkFolder(candidates: SourceControlledFile[], userId: string) { const candidateIds = candidates.map((c) => c.id); - const existingCredentials = await Db.collections.Credentials.find({ + const existingCredentials = await Container.get(CredentialsRepository).find({ where: { id: In(candidateIds), }, @@ -339,7 +348,7 @@ export class SourceControlImportService { }); const ownerCredentialRole = await this.getCredentialOwnerRole(); const ownerGlobalRole = await this.getOwnerGlobalRole(); - const existingSharedCredentials = await Db.collections.SharedCredentials.find({ + const existingSharedCredentials = await Container.get(SharedCredentialsRepository).find({ select: ['userId', 'credentialsId', 'roleId'], where: { credentialsId: In(candidateIds), @@ -370,7 +379,7 @@ export class SourceControlImportService { newCredentialObject.nodesAccess = nodesAccess || existingCredential?.nodesAccess || []; this.logger.debug(`Updating credential id ${newCredentialObject.id as string}`); - await Db.collections.Credentials.upsert(newCredentialObject, ['id']); + await Container.get(CredentialsRepository).upsert(newCredentialObject, ['id']); if (!sharedOwner) { const newSharedCredential = new SharedCredentials(); @@ -378,7 +387,7 @@ export class SourceControlImportService { newSharedCredential.userId = userId; newSharedCredential.roleId = ownerCredentialRole.id; - await Db.collections.SharedCredentials.upsert({ ...newSharedCredential }, [ + await Container.get(SharedCredentialsRepository).upsert({ ...newSharedCredential }, [ 'credentialsId', 'userId', ]); @@ -413,7 +422,7 @@ export class SourceControlImportService { const existingWorkflowIds = new Set( ( - await Db.collections.Workflow.find({ + await Container.get(WorkflowRepository).find({ select: ['id'], }) ).map((e) => e.id), @@ -442,7 +451,7 @@ export class SourceControlImportService { await Promise.all( mappedTags.mappings.map(async (mapping) => { if (!existingWorkflowIds.has(String(mapping.workflowId))) return; - await Db.collections.WorkflowTagMapping.upsert( + await Container.get(WorkflowTagMappingRepository).upsert( { tagId: String(mapping.tagId), workflowId: String(mapping.workflowId) }, { skipUpdateIfNoValuesChanged: true, @@ -489,12 +498,12 @@ export class SourceControlImportService { overriddenKeys.splice(overriddenKeys.indexOf(variable.key), 1); } try { - await Db.collections.Variables.upsert({ ...variable }, ['id']); + await Container.get(VariablesRepository).upsert({ ...variable }, ['id']); } catch (errorUpsert) { if (isUniqueConstraintError(errorUpsert as Error)) { this.logger.debug(`Variable ${variable.key} already exists, updating instead`); try { - await Db.collections.Variables.update({ key: variable.key }, { ...variable }); + await Container.get(VariablesRepository).update({ key: variable.key }, { ...variable }); } catch (errorUpdate) { this.logger.debug(`Failed to update variable ${variable.key}, skipping`); this.logger.debug((errorUpdate as Error).message); @@ -509,8 +518,11 @@ export class SourceControlImportService { if (overriddenKeys.length > 0 && valueOverrides) { for (const key of overriddenKeys) { result.imported.push(key); - const newVariable = Db.collections.Variables.create({ key, value: valueOverrides[key] }); - await Db.collections.Variables.save(newVariable); + const newVariable = Container.get(VariablesRepository).create({ + key, + value: valueOverrides[key], + }); + await Container.get(VariablesRepository).save(newVariable); } } diff --git a/packages/cli/src/environments/sourceControl/sourceControlPreferences.service.ee.ts b/packages/cli/src/environments/sourceControl/sourceControlPreferences.service.ee.ts index 52b5549aae..3b385b0b81 100644 --- a/packages/cli/src/environments/sourceControl/sourceControlPreferences.service.ee.ts +++ b/packages/cli/src/environments/sourceControl/sourceControlPreferences.service.ee.ts @@ -1,4 +1,4 @@ -import { Service } from 'typedi'; +import Container, { Service } from 'typedi'; import { SourceControlPreferences } from './types/sourceControlPreferences'; import type { ValidationError } from 'class-validator'; import { validate } from 'class-validator'; @@ -11,7 +11,6 @@ import { } from './sourceControlHelper.ee'; import { InstanceSettings } from 'n8n-core'; import { jsonParse } from 'n8n-workflow'; -import * as Db from '@/Db'; import { SOURCE_CONTROL_SSH_FOLDER, SOURCE_CONTROL_GIT_FOLDER, @@ -22,6 +21,7 @@ import path from 'path'; import type { KeyPairType } from './types/keyPairType'; import config from '@/config'; import { Logger } from '@/Logger'; +import { SettingsRepository } from '@db/repositories/settings.repository'; @Service() export class SourceControlPreferencesService { @@ -171,7 +171,7 @@ export class SourceControlPreferencesService { if (saveToDb) { const settingsValue = JSON.stringify(this._sourceControlPreferences); try { - await Db.collections.Settings.save({ + await Container.get(SettingsRepository).save({ key: SOURCE_CONTROL_PREFERENCES_DB_KEY, value: settingsValue, loadOnStartup: true, @@ -186,7 +186,7 @@ export class SourceControlPreferencesService { async loadFromDbAndApplySourceControlPreferences(): Promise< SourceControlPreferences | undefined > { - const loadedPreferences = await Db.collections.Settings.findOne({ + const loadedPreferences = await Container.get(SettingsRepository).findOne({ where: { key: SOURCE_CONTROL_PREFERENCES_DB_KEY }, }); if (loadedPreferences) { diff --git a/packages/cli/src/environments/variables/variables.service.ts b/packages/cli/src/environments/variables/variables.service.ts index c05d9bb08b..31d5f473d7 100644 --- a/packages/cli/src/environments/variables/variables.service.ts +++ b/packages/cli/src/environments/variables/variables.service.ts @@ -1,7 +1,7 @@ import type { Variables } from '@db/entities/Variables'; import { CacheService } from '@/services/cache.service'; import Container, { Service } from 'typedi'; -import { VariablesRepository } from '@/databases/repositories'; +import { VariablesRepository } from '@db/repositories/variables.repository'; import type { DeepPartial } from 'typeorm'; @Service() diff --git a/packages/cli/src/eventbus/MessageEventBus/MessageEventBus.ts b/packages/cli/src/eventbus/MessageEventBus/MessageEventBus.ts index 43cd1b5d4a..fd37bf1a39 100644 --- a/packages/cli/src/eventbus/MessageEventBus/MessageEventBus.ts +++ b/packages/cli/src/eventbus/MessageEventBus/MessageEventBus.ts @@ -11,7 +11,6 @@ import type { MessageEventBusDestination } from '../MessageEventBusDestination/M import { MessageEventBusLogWriter } from '../MessageEventBusWriter/MessageEventBusLogWriter'; import EventEmitter from 'events'; import config from '@/config'; -import * as Db from '@/Db'; import { messageEventBusDestinationFromDb } from '../MessageEventBusDestination/MessageEventBusDestinationFromDb'; import uniqby from 'lodash/uniqBy'; import type { EventMessageConfirmSource } from '../EventMessageClasses/EventMessageConfirm'; @@ -29,11 +28,13 @@ import { import { recoverExecutionDataFromEventLogMessages } from './recoverEvents'; import { METRICS_EVENT_NAME } from '../MessageEventBusDestination/Helpers.ee'; import { Container, Service } from 'typedi'; -import { ExecutionRepository, WorkflowRepository } from '@/databases/repositories'; +import { ExecutionRepository } from '@db/repositories/execution.repository'; +import { WorkflowRepository } from '@db/repositories/workflow.repository'; import type { AbstractEventMessageOptions } from '../EventMessageClasses/AbstractEventMessageOptions'; import { getEventMessageObjectByType } from '../EventMessageClasses/Helpers'; import { SingleMainInstancePublisher } from '@/services/orchestration/main/SingleMainInstance.publisher'; import { Logger } from '@/Logger'; +import { EventDestinationsRepository } from '@db/repositories/eventDestinations.repository'; export type EventMessageReturnMode = 'sent' | 'unsent' | 'all' | 'unfinished'; @@ -79,7 +80,7 @@ export class MessageEventBus extends EventEmitter { this.logger.debug('Initializing event bus...'); - const savedEventDestinations = await Db.collections.EventDestinations.find({}); + const savedEventDestinations = await Container.get(EventDestinationsRepository).find({}); if (savedEventDestinations.length > 0) { for (const destinationData of savedEventDestinations) { try { diff --git a/packages/cli/src/eventbus/MessageEventBus/recoverEvents.ts b/packages/cli/src/eventbus/MessageEventBus/recoverEvents.ts index 14d7611a8b..6aa3fe616c 100644 --- a/packages/cli/src/eventbus/MessageEventBus/recoverEvents.ts +++ b/packages/cli/src/eventbus/MessageEventBus/recoverEvents.ts @@ -6,7 +6,7 @@ import { Push } from '@/push'; import { Container } from 'typedi'; import { InternalHooks } from '@/InternalHooks'; import { getWorkflowHooksMain } from '@/WorkflowExecuteAdditionalData'; -import { ExecutionRepository } from '@db/repositories'; +import { ExecutionRepository } from '@db/repositories/execution.repository'; export async function recoverExecutionDataFromEventLogMessages( executionId: string, diff --git a/packages/cli/src/eventbus/MessageEventBusDestination/MessageEventBusDestination.ee.ts b/packages/cli/src/eventbus/MessageEventBusDestination/MessageEventBusDestination.ee.ts index 1aea086b3d..33efb6e6e2 100644 --- a/packages/cli/src/eventbus/MessageEventBusDestination/MessageEventBusDestination.ee.ts +++ b/packages/cli/src/eventbus/MessageEventBusDestination/MessageEventBusDestination.ee.ts @@ -6,13 +6,13 @@ import { MessageEventBusDestinationTypeNames, MessageEventBusDestinationOptions, } from 'n8n-workflow'; -import * as Db from '@/Db'; import { Logger } from '@/Logger'; import type { AbstractEventMessage } from '../EventMessageClasses/AbstractEventMessage'; import type { EventMessageTypes } from '../EventMessageClasses'; import type { EventMessageConfirmSource } from '../EventMessageClasses/EventMessageConfirm'; import { MessageEventBus } from '../MessageEventBus/MessageEventBus'; import type { MessageWithCallback } from '../MessageEventBus/MessageEventBus'; +import { EventDestinationsRepository } from '@db/repositories/eventDestinations.repository'; export abstract class MessageEventBusDestination implements MessageEventBusDestinationOptions { // Since you can't have static abstract functions - this just serves as a reminder that you need to implement these. Please. @@ -96,7 +96,7 @@ export abstract class MessageEventBusDestination implements MessageEventBusDesti id: this.getId(), destination: this.serialize(), }; - const dbResult: InsertResult = await Db.collections.EventDestinations.upsert(data, { + const dbResult: InsertResult = await Container.get(EventDestinationsRepository).upsert(data, { skipUpdateIfNoValuesChanged: true, conflictPaths: ['id'], }); @@ -108,7 +108,7 @@ export abstract class MessageEventBusDestination implements MessageEventBusDesti } static async deleteFromDb(id: string): Promise { - const dbResult = await Db.collections.EventDestinations.delete({ id }); + const dbResult = await Container.get(EventDestinationsRepository).delete({ id }); return dbResult; } diff --git a/packages/cli/src/eventbus/MessageEventBusDestination/MessageEventBusDestinationFromDb.ts b/packages/cli/src/eventbus/MessageEventBusDestination/MessageEventBusDestinationFromDb.ts index 348e5cf8c6..27951448ce 100644 --- a/packages/cli/src/eventbus/MessageEventBusDestination/MessageEventBusDestinationFromDb.ts +++ b/packages/cli/src/eventbus/MessageEventBusDestination/MessageEventBusDestinationFromDb.ts @@ -1,5 +1,5 @@ import { MessageEventBusDestinationTypeNames } from 'n8n-workflow'; -import type { EventDestinations } from '@/databases/entities/EventDestinations'; +import type { EventDestinations } from '@db/entities/EventDestinations'; import type { MessageEventBus } from '../MessageEventBus/MessageEventBus'; import type { MessageEventBusDestination } from './MessageEventBusDestination.ee'; import { MessageEventBusDestinationSentry } from './MessageEventBusDestinationSentry.ee'; diff --git a/packages/cli/src/executionLifecycleHooks/shared/sharedHookFunctions.ts b/packages/cli/src/executionLifecycleHooks/shared/sharedHookFunctions.ts index fed83fca36..38497128a5 100644 --- a/packages/cli/src/executionLifecycleHooks/shared/sharedHookFunctions.ts +++ b/packages/cli/src/executionLifecycleHooks/shared/sharedHookFunctions.ts @@ -3,7 +3,7 @@ import type { ExecutionStatus, IRun, IWorkflowBase } from 'n8n-workflow'; import type { ExecutionPayload, IExecutionDb } from '@/Interfaces'; import pick from 'lodash/pick'; import { isWorkflowIdValid } from '@/utils'; -import { ExecutionRepository } from '@db/repositories'; +import { ExecutionRepository } from '@db/repositories/execution.repository'; import { ExecutionMetadataService } from '@/services/executionMetadata.service'; import { Logger } from '@/Logger'; diff --git a/packages/cli/src/executions/executions.service.ts b/packages/cli/src/executions/executions.service.ts index a9f9cfdf2a..04479b0539 100644 --- a/packages/cli/src/executions/executions.service.ts +++ b/packages/cli/src/executions/executions.service.ts @@ -18,11 +18,11 @@ import type { ExecutionRequest } from '@/requests'; import * as ResponseHelper from '@/ResponseHelper'; import { getSharedWorkflowIds } from '@/WorkflowHelpers'; import { WorkflowRunner } from '@/WorkflowRunner'; -import * as Db from '@/Db'; import * as GenericHelpers from '@/GenericHelpers'; import { Container } from 'typedi'; import { getStatusUsingPreviousExecutionStatusMethod } from './executionHelpers'; -import { ExecutionRepository } from '@db/repositories'; +import { ExecutionRepository } from '@db/repositories/execution.repository'; +import { WorkflowRepository } from '@db/repositories/workflow.repository'; import { Logger } from '@/Logger'; export interface IGetExecutionsQueryFilter { @@ -274,7 +274,7 @@ export class ExecutionsService { // Loads the currently saved workflow to execute instead of the // one saved at the time of the execution. const workflowId = execution.workflowData.id as string; - const workflowData = (await Db.collections.Workflow.findOneBy({ + const workflowData = (await Container.get(WorkflowRepository).findOneBy({ id: workflowId, })) as IWorkflowBase; diff --git a/packages/cli/src/license/License.service.ts b/packages/cli/src/license/License.service.ts index adba06ca9c..20437a5a38 100644 --- a/packages/cli/src/license/License.service.ts +++ b/packages/cli/src/license/License.service.ts @@ -1,11 +1,13 @@ import { Container } from 'typedi'; import { License } from '@/License'; import type { ILicenseReadResponse } from '@/Interfaces'; -import * as Db from '@/Db'; +import { WorkflowRepository } from '@db/repositories/workflow.repository'; export class LicenseService { static async getActiveTriggerCount(): Promise { - const totalTriggerCount = await Db.collections.Workflow.sum('triggerCount', { active: true }); + const totalTriggerCount = await Container.get(WorkflowRepository).sum('triggerCount', { + active: true, + }); return totalTriggerCount ?? 0; } diff --git a/packages/cli/src/push/abstract.push.ts b/packages/cli/src/push/abstract.push.ts index 8204cdb688..71db6aa8ee 100644 --- a/packages/cli/src/push/abstract.push.ts +++ b/packages/cli/src/push/abstract.push.ts @@ -2,7 +2,7 @@ import { EventEmitter } from 'events'; import { assert, jsonStringify } from 'n8n-workflow'; import type { IPushDataType } from '@/Interfaces'; import { Logger } from '@/Logger'; -import type { User } from '@/databases/entities/User'; +import type { User } from '@db/entities/User'; /** * Abstract class for two-way push communication. diff --git a/packages/cli/src/push/index.ts b/packages/cli/src/push/index.ts index 5d8c0b7db6..451a0e2e79 100644 --- a/packages/cli/src/push/index.ts +++ b/packages/cli/src/push/index.ts @@ -13,7 +13,7 @@ import { SSEPush } from './sse.push'; import { WebSocketPush } from './websocket.push'; import type { PushResponse, SSEPushRequest, WebSocketPushRequest } from './types'; import type { IPushDataType } from '@/Interfaces'; -import type { User } from '@/databases/entities/User'; +import type { User } from '@db/entities/User'; const useWebSockets = config.getEnv('push.backend') === 'websocket'; diff --git a/packages/cli/src/push/sse.push.ts b/packages/cli/src/push/sse.push.ts index c19d916b86..f4c75a3205 100644 --- a/packages/cli/src/push/sse.push.ts +++ b/packages/cli/src/push/sse.push.ts @@ -3,7 +3,7 @@ import { Service } from 'typedi'; import { Logger } from '@/Logger'; import { AbstractPush } from './abstract.push'; import type { PushRequest, PushResponse } from './types'; -import type { User } from '@/databases/entities/User'; +import type { User } from '@db/entities/User'; type Connection = { req: PushRequest; res: PushResponse }; diff --git a/packages/cli/src/push/types.ts b/packages/cli/src/push/types.ts index 58c19c91c4..2a65b08131 100644 --- a/packages/cli/src/push/types.ts +++ b/packages/cli/src/push/types.ts @@ -1,4 +1,4 @@ -import type { User } from '@/databases/entities/User'; +import type { User } from '@db/entities/User'; import type { Request, Response } from 'express'; import type { WebSocket } from 'ws'; diff --git a/packages/cli/src/push/websocket.push.ts b/packages/cli/src/push/websocket.push.ts index 96b916b2c4..08ebad2e9d 100644 --- a/packages/cli/src/push/websocket.push.ts +++ b/packages/cli/src/push/websocket.push.ts @@ -2,7 +2,7 @@ import type WebSocket from 'ws'; import { Service } from 'typedi'; import { Logger } from '@/Logger'; import { AbstractPush } from './abstract.push'; -import type { User } from '@/databases/entities/User'; +import type { User } from '@db/entities/User'; function heartbeat(this: WebSocket) { this.isAlive = true; diff --git a/packages/cli/src/requests.ts b/packages/cli/src/requests.ts index de675a4a14..9131cc2fa3 100644 --- a/packages/cli/src/requests.ts +++ b/packages/cli/src/requests.ts @@ -26,9 +26,9 @@ import type { Role } from '@db/entities/Role'; import type { User } from '@db/entities/User'; import type { UserManagementMailer } from '@/UserManagement/email'; import type { Variables } from '@db/entities/Variables'; -import type { WorkflowEntity } from './databases/entities/WorkflowEntity'; -import type { CredentialsEntity } from './databases/entities/CredentialsEntity'; -import type { WorkflowHistory } from './databases/entities/WorkflowHistory'; +import type { WorkflowEntity } from '@db/entities/WorkflowEntity'; +import type { CredentialsEntity } from '@db/entities/CredentialsEntity'; +import type { WorkflowHistory } from '@db/entities/WorkflowHistory'; export class UserUpdatePayload implements Pick { @IsEmail() diff --git a/packages/cli/src/services/communityPackages.service.ts b/packages/cli/src/services/communityPackages.service.ts index 8c1cdd123d..2455a885e4 100644 --- a/packages/cli/src/services/communityPackages.service.ts +++ b/packages/cli/src/services/communityPackages.service.ts @@ -10,8 +10,8 @@ import { InstanceSettings } from 'n8n-core'; import type { PackageDirectoryLoader } from 'n8n-core'; import { toError } from '@/utils'; -import { InstalledPackagesRepository } from '@/databases/repositories/installedPackages.repository'; -import type { InstalledPackages } from '@/databases/entities/InstalledPackages'; +import { InstalledPackagesRepository } from '@db/repositories/installedPackages.repository'; +import type { InstalledPackages } from '@db/entities/InstalledPackages'; import { NODE_PACKAGE_PREFIX, NPM_COMMAND_TOKENS, diff --git a/packages/cli/src/services/events.service.ts b/packages/cli/src/services/events.service.ts index 72cd10f983..3f2504366e 100644 --- a/packages/cli/src/services/events.service.ts +++ b/packages/cli/src/services/events.service.ts @@ -2,7 +2,7 @@ import { EventEmitter } from 'events'; import { Container, Service } from 'typedi'; import type { INode, IRun, IWorkflowBase } from 'n8n-workflow'; import { StatisticsNames } from '@db/entities/WorkflowStatistics'; -import { WorkflowStatisticsRepository } from '@db/repositories'; +import { WorkflowStatisticsRepository } from '@db/repositories/workflowStatistics.repository'; import { UserService } from '@/services/user.service'; import { Logger } from '@/Logger'; import { OwnershipService } from './ownership.service'; diff --git a/packages/cli/src/services/executionMetadata.service.ts b/packages/cli/src/services/executionMetadata.service.ts index bccb7172ee..6b62ee2365 100644 --- a/packages/cli/src/services/executionMetadata.service.ts +++ b/packages/cli/src/services/executionMetadata.service.ts @@ -1,6 +1,6 @@ -import { ExecutionMetadataRepository } from '@/databases/repositories'; import { Service } from 'typedi'; -import type { ExecutionMetadata } from '@/databases/entities/ExecutionMetadata'; +import { ExecutionMetadataRepository } from '@db/repositories/executionMetadata.repository'; +import type { ExecutionMetadata } from '@db/entities/ExecutionMetadata'; @Service() export class ExecutionMetadataService { diff --git a/packages/cli/src/services/ownership.service.ts b/packages/cli/src/services/ownership.service.ts index 3d0e59c166..6d46e5911f 100644 --- a/packages/cli/src/services/ownership.service.ts +++ b/packages/cli/src/services/ownership.service.ts @@ -1,12 +1,12 @@ import { Service } from 'typedi'; import { CacheService } from './cache.service'; -import { SharedWorkflowRepository } from '@/databases/repositories'; -import type { User } from '@/databases/entities/User'; +import { SharedWorkflowRepository } from '@db/repositories/sharedWorkflow.repository'; +import type { User } from '@db/entities/User'; import { RoleService } from './role.service'; import { UserService } from './user.service'; import type { Credentials, ListQuery } from '@/requests'; -import type { Role } from '@/databases/entities/Role'; -import type { CredentialsEntity } from '@/databases/entities/CredentialsEntity'; +import type { Role } from '@db/entities/Role'; +import type { CredentialsEntity } from '@db/entities/CredentialsEntity'; @Service() export class OwnershipService { diff --git a/packages/cli/src/services/pruning.service.ts b/packages/cli/src/services/pruning.service.ts index 96bed63927..ea3091a1b4 100644 --- a/packages/cli/src/services/pruning.service.ts +++ b/packages/cli/src/services/pruning.service.ts @@ -6,9 +6,9 @@ import type { FindOptionsWhere } from 'typeorm'; import { TIME, inTest } from '@/constants'; import config from '@/config'; -import { ExecutionRepository } from '@/databases/repositories'; +import { ExecutionRepository } from '@db/repositories/execution.repository'; import { Logger } from '@/Logger'; -import { ExecutionEntity } from '@/databases/entities/ExecutionEntity'; +import { ExecutionEntity } from '@db/entities/ExecutionEntity'; @Service() export class PruningService { diff --git a/packages/cli/src/services/role.service.ts b/packages/cli/src/services/role.service.ts index d30f47c499..d27f658174 100644 --- a/packages/cli/src/services/role.service.ts +++ b/packages/cli/src/services/role.service.ts @@ -1,7 +1,8 @@ -import { RoleRepository, SharedWorkflowRepository } from '@/databases/repositories'; import { Service } from 'typedi'; +import { RoleRepository } from '@db/repositories/role.repository'; +import { SharedWorkflowRepository } from '@db/repositories/sharedWorkflow.repository'; import { CacheService } from './cache.service'; -import type { RoleNames, RoleScopes } from '@/databases/entities/Role'; +import type { RoleNames, RoleScopes } from '@db/entities/Role'; class InvalidRoleError extends Error {} diff --git a/packages/cli/src/services/tag.service.ts b/packages/cli/src/services/tag.service.ts index 5bf94da7de..8d3e40ad93 100644 --- a/packages/cli/src/services/tag.service.ts +++ b/packages/cli/src/services/tag.service.ts @@ -1,8 +1,8 @@ -import { TagRepository } from '@/databases/repositories'; +import { TagRepository } from '@db/repositories/tag.repository'; import { Service } from 'typedi'; import { validateEntity } from '@/GenericHelpers'; import type { ITagToImport, ITagWithCountDb, IWorkflowToImport } from '@/Interfaces'; -import type { TagEntity } from '@/databases/entities/TagEntity'; +import type { TagEntity } from '@db/entities/TagEntity'; import type { EntityManager, FindManyOptions, FindOneOptions } from 'typeorm'; import type { UpsertOptions } from 'typeorm/repository/UpsertOptions'; import { ExternalHooks } from '@/ExternalHooks'; diff --git a/packages/cli/src/services/user.service.ts b/packages/cli/src/services/user.service.ts index 0badb9cd9e..a5b12dee72 100644 --- a/packages/cli/src/services/user.service.ts +++ b/packages/cli/src/services/user.service.ts @@ -3,7 +3,7 @@ import type { EntityManager, FindManyOptions, FindOneOptions, FindOptionsWhere } import { In } from 'typeorm'; import { User } from '@db/entities/User'; import type { IUserSettings } from 'n8n-workflow'; -import { UserRepository } from '@/databases/repositories'; +import { UserRepository } from '@db/repositories/user.repository'; import { getInstanceBaseUrl } from '@/UserManagement/UserManagementHelper'; import type { PublicUser } from '@/Interfaces'; import type { PostHogClient } from '@/posthog'; diff --git a/packages/cli/src/services/webhook.service.ts b/packages/cli/src/services/webhook.service.ts index 30f0de294f..741c6b42ad 100644 --- a/packages/cli/src/services/webhook.service.ts +++ b/packages/cli/src/services/webhook.service.ts @@ -1,7 +1,7 @@ -import { WebhookRepository } from '@/databases/repositories'; +import { WebhookRepository } from '@db/repositories/webhook.repository'; import { Service } from 'typedi'; import { CacheService } from './cache.service'; -import type { WebhookEntity } from '@/databases/entities/WebhookEntity'; +import type { WebhookEntity } from '@db/entities/WebhookEntity'; import type { IHttpRequestMethods } from 'n8n-workflow'; import type { DeepPartial } from 'typeorm'; diff --git a/packages/cli/src/sso/saml/saml.service.ee.ts b/packages/cli/src/sso/saml/saml.service.ee.ts index f1929cda2d..354686cbb3 100644 --- a/packages/cli/src/sso/saml/saml.service.ee.ts +++ b/packages/cli/src/sso/saml/saml.service.ee.ts @@ -1,6 +1,5 @@ import type express from 'express'; -import { Service } from 'typedi'; -import * as Db from '@/Db'; +import Container, { Service } from 'typedi'; import type { User } from '@db/entities/User'; import { jsonParse } from 'n8n-workflow'; import { AuthError, BadRequestError } from '@/ResponseHelper'; @@ -28,6 +27,8 @@ import type { SamlLoginBinding } from './types'; import { validateMetadata, validateResponse } from './samlValidator'; import { getInstanceBaseUrl } from '@/UserManagement/UserManagementHelper'; import { Logger } from '@/Logger'; +import { UserRepository } from '@db/repositories/user.repository'; +import { SettingsRepository } from '@db/repositories/settings.repository'; @Service() export class SamlService { @@ -167,7 +168,7 @@ export class SamlService { const attributes = await this.getAttributesFromLoginResponse(req, binding); if (attributes.email) { const lowerCasedEmail = attributes.email.toLowerCase(); - const user = await Db.collections.User.findOne({ + const user = await Container.get(UserRepository).findOne({ where: { email: lowerCasedEmail }, relations: ['globalRole', 'authIdentities'], }); @@ -257,7 +258,7 @@ export class SamlService { } async loadFromDbAndApplySamlPreferences(apply = true): Promise { - const samlPreferences = await Db.collections.Settings.findOne({ + const samlPreferences = await Container.get(SettingsRepository).findOne({ where: { key: SAML_PREFERENCES_DB_KEY }, }); if (samlPreferences) { @@ -275,16 +276,16 @@ export class SamlService { } async saveSamlPreferencesToDb(): Promise { - const samlPreferences = await Db.collections.Settings.findOne({ + const samlPreferences = await Container.get(SettingsRepository).findOne({ where: { key: SAML_PREFERENCES_DB_KEY }, }); const settingsValue = JSON.stringify(this.samlPreferences); let result: Settings; if (samlPreferences) { samlPreferences.value = settingsValue; - result = await Db.collections.Settings.save(samlPreferences); + result = await Container.get(SettingsRepository).save(samlPreferences); } else { - result = await Db.collections.Settings.save({ + result = await Container.get(SettingsRepository).save({ key: SAML_PREFERENCES_DB_KEY, value: settingsValue, loadOnStartup: true, diff --git a/packages/cli/src/sso/saml/samlHelpers.ts b/packages/cli/src/sso/saml/samlHelpers.ts index 6c9f76648c..d55b751be7 100644 --- a/packages/cli/src/sso/saml/samlHelpers.ts +++ b/packages/cli/src/sso/saml/samlHelpers.ts @@ -1,6 +1,5 @@ import { Container } from 'typedi'; import config from '@/config'; -import * as Db from '@/Db'; import { AuthIdentity } from '@db/entities/AuthIdentity'; import { User } from '@db/entities/User'; import { License } from '@/License'; @@ -20,6 +19,8 @@ import { import { getServiceProviderConfigTestReturnUrl } from './serviceProvider.ee'; import type { SamlConfiguration } from './types/requests'; import { RoleService } from '@/services/role.service'; +import { UserRepository } from '@db/repositories/user.repository'; +import { AuthIdentityRepository } from '@db/repositories/authIdentity.repository'; /** * Check whether the SAML feature is licensed and enabled in the instance */ @@ -107,10 +108,10 @@ export async function createUserFromSamlAttributes(attributes: SamlUserAttribute authIdentity.providerId = attributes.userPrincipalName; authIdentity.providerType = 'saml'; authIdentity.user = user; - const resultAuthIdentity = await Db.collections.AuthIdentity.save(authIdentity); + const resultAuthIdentity = await Container.get(AuthIdentityRepository).save(authIdentity); if (!resultAuthIdentity) throw new AuthError('Could not create AuthIdentity'); user.authIdentities = [authIdentity]; - const resultUser = await Db.collections.User.save(user); + const resultUser = await Container.get(UserRepository).save(user); if (!resultUser) throw new AuthError('Could not create User'); return resultUser; } @@ -131,10 +132,10 @@ export async function updateUserFromSamlAttributes( } else { samlAuthIdentity.providerId = attributes.userPrincipalName; } - await Db.collections.AuthIdentity.save(samlAuthIdentity); + await Container.get(AuthIdentityRepository).save(samlAuthIdentity); user.firstName = attributes.firstName; user.lastName = attributes.lastName; - const resultUser = await Db.collections.User.save(user); + const resultUser = await Container.get(UserRepository).save(user); if (!resultUser) throw new AuthError('Could not create User'); return resultUser; } diff --git a/packages/cli/src/sso/ssoHelpers.ts b/packages/cli/src/sso/ssoHelpers.ts index 30636c533d..fa1abf2371 100644 --- a/packages/cli/src/sso/ssoHelpers.ts +++ b/packages/cli/src/sso/ssoHelpers.ts @@ -1,6 +1,7 @@ import config from '@/config'; -import * as Db from '@/Db'; +import { SettingsRepository } from '@db/repositories/settings.repository'; import type { AuthProviderType } from '@db/entities/AuthIdentity'; +import Container from 'typedi'; /** * Only one authentication method can be active at a time. This function sets the current authentication method @@ -12,7 +13,7 @@ export async function setCurrentAuthenticationMethod( authenticationMethod: AuthProviderType, ): Promise { config.set('userManagement.authenticationMethod', authenticationMethod); - await Db.collections.Settings.save({ + await Container.get(SettingsRepository).save({ key: 'userManagement.authenticationMethod', value: authenticationMethod, loadOnStartup: true, diff --git a/packages/cli/src/workflows/workflowHistory/workflowHistory.service.ee.ts b/packages/cli/src/workflows/workflowHistory/workflowHistory.service.ee.ts index d2093ba4c7..89b0698748 100644 --- a/packages/cli/src/workflows/workflowHistory/workflowHistory.service.ee.ts +++ b/packages/cli/src/workflows/workflowHistory/workflowHistory.service.ee.ts @@ -1,8 +1,8 @@ -import type { SharedWorkflow } from '@/databases/entities/SharedWorkflow'; -import type { User } from '@/databases/entities/User'; -import type { WorkflowEntity } from '@/databases/entities/WorkflowEntity'; -import type { WorkflowHistory } from '@/databases/entities/WorkflowHistory'; -import { SharedWorkflowRepository } from '@/databases/repositories'; +import type { SharedWorkflow } from '@db/entities/SharedWorkflow'; +import type { User } from '@db/entities/User'; +import type { WorkflowEntity } from '@db/entities/WorkflowEntity'; +import type { WorkflowHistory } from '@db/entities/WorkflowHistory'; +import { SharedWorkflowRepository } from '@db/repositories/sharedWorkflow.repository'; import { WorkflowHistoryRepository } from '@db/repositories/workflowHistory.repository'; import { Service } from 'typedi'; import { isWorkflowHistoryEnabled } from './workflowHistoryHelper.ee'; diff --git a/packages/cli/src/workflows/workflowHistory/workflowHistoryManager.ee.ts b/packages/cli/src/workflows/workflowHistory/workflowHistoryManager.ee.ts index a7af16f5bc..8075c2461d 100644 --- a/packages/cli/src/workflows/workflowHistory/workflowHistoryManager.ee.ts +++ b/packages/cli/src/workflows/workflowHistory/workflowHistoryManager.ee.ts @@ -1,7 +1,7 @@ import { Service } from 'typedi'; import { LessThan } from 'typeorm'; import { DateTime } from 'luxon'; -import { WorkflowHistoryRepository } from '@/databases/repositories'; +import { WorkflowHistoryRepository } from '@db/repositories/workflowHistory.repository'; import { WORKFLOW_HISTORY_PRUNE_INTERVAL } from './constants'; import { getWorkflowHistoryPruneTime, isWorkflowHistoryEnabled } from './workflowHistoryHelper.ee'; diff --git a/packages/cli/src/workflows/workflows.controller.ts b/packages/cli/src/workflows/workflows.controller.ts index 9537855f80..fc187b9b84 100644 --- a/packages/cli/src/workflows/workflows.controller.ts +++ b/packages/cli/src/workflows/workflows.controller.ts @@ -26,6 +26,7 @@ import { listQueryMiddleware } from '@/middlewares'; import { TagService } from '@/services/tag.service'; import { WorkflowHistoryService } from './workflowHistory/workflowHistory.service.ee'; import { Logger } from '@/Logger'; +import { SharedWorkflowRepository } from '@db/repositories/sharedWorkflow.repository'; export const workflowsController = express.Router(); workflowsController.use('/', EEWorkflowController); @@ -205,7 +206,7 @@ workflowsController.get( relations = relations.filter((relation) => relation !== 'workflow.tags'); } - const shared = await Db.collections.SharedWorkflow.findOne({ + const shared = await Container.get(SharedWorkflowRepository).findOne({ relations, where: whereClause({ user: req.user, diff --git a/packages/cli/src/workflows/workflows.services.ee.ts b/packages/cli/src/workflows/workflows.services.ee.ts index 1c13d9f8b6..04448e76cb 100644 --- a/packages/cli/src/workflows/workflows.services.ee.ts +++ b/packages/cli/src/workflows/workflows.services.ee.ts @@ -1,6 +1,5 @@ import type { DeleteResult, EntityManager } from 'typeorm'; import { In, Not } from 'typeorm'; -import * as Db from '@/Db'; import * as ResponseHelper from '@/ResponseHelper'; import * as WorkflowHelpers from '@/WorkflowHelpers'; import { SharedWorkflow } from '@db/entities/SharedWorkflow'; @@ -16,7 +15,8 @@ import { CredentialsService } from '@/credentials/credentials.service'; import { NodeOperationError } from 'n8n-workflow'; import { RoleService } from '@/services/role.service'; import Container from 'typedi'; -import type { CredentialsEntity } from '@/databases/entities/CredentialsEntity'; +import type { CredentialsEntity } from '@db/entities/CredentialsEntity'; +import { SharedWorkflowRepository } from '@db/repositories/sharedWorkflow.repository'; export class EEWorkflowsService extends WorkflowsService { static async isOwned( @@ -73,7 +73,7 @@ export class EEWorkflowsService extends WorkflowsService { userId: user.id, roleId: role?.id, }; - acc.push(Db.collections.SharedWorkflow.create(entity)); + acc.push(Container.get(SharedWorkflowRepository).create(entity)); return acc; }, []); diff --git a/packages/cli/src/workflows/workflows.services.ts b/packages/cli/src/workflows/workflows.services.ts index 3b039c09cc..1976adb478 100644 --- a/packages/cli/src/workflows/workflows.services.ts +++ b/packages/cli/src/workflows/workflows.services.ts @@ -6,7 +6,6 @@ import { In, Like } from 'typeorm'; import pick from 'lodash/pick'; import { v4 as uuid } from 'uuid'; import { ActiveWorkflowRunner } from '@/ActiveWorkflowRunner'; -import * as Db from '@/Db'; import * as ResponseHelper from '@/ResponseHelper'; import * as WorkflowHelpers from '@/WorkflowHelpers'; import config from '@/config'; @@ -24,13 +23,16 @@ import * as WorkflowExecuteAdditionalData from '@/WorkflowExecuteAdditionalData' import { TestWebhooks } from '@/TestWebhooks'; import { whereClause } from '@/UserManagement/UserManagementHelper'; import { InternalHooks } from '@/InternalHooks'; -import { WorkflowRepository } from '@/databases/repositories'; +import { WorkflowRepository } from '@db/repositories/workflow.repository'; import { RoleService } from '@/services/role.service'; import { OwnershipService } from '@/services/ownership.service'; import { isStringArray, isWorkflowIdValid } from '@/utils'; import { WorkflowHistoryService } from './workflowHistory/workflowHistory.service.ee'; import { BinaryDataService } from 'n8n-core'; import { Logger } from '@/Logger'; +import { SharedWorkflowRepository } from '@db/repositories/sharedWorkflow.repository'; +import { WorkflowTagMappingRepository } from '@db/repositories/workflowTagMapping.repository'; +import { ExecutionRepository } from '@db/repositories/execution.repository'; export class WorkflowsService { static async getSharing( @@ -48,7 +50,7 @@ export class WorkflowsService { where.userId = user.id; } - return Db.collections.SharedWorkflow.findOne({ where, relations }); + return Container.get(SharedWorkflowRepository).findOne({ where, relations }); } /** @@ -94,7 +96,10 @@ export class WorkflowsService { } static async get(workflow: FindOptionsWhere, options?: { relations: string[] }) { - return Db.collections.Workflow.findOne({ where: workflow, relations: options?.relations }); + return Container.get(WorkflowRepository).findOne({ + where: workflow, + relations: options?.relations, + }); } static async getMany(sharedWorkflowIds: string[], options?: ListQuery.Options) { @@ -186,7 +191,7 @@ export class WorkflowsService { forceSave?: boolean, roles?: string[], ): Promise { - const shared = await Db.collections.SharedWorkflow.findOne({ + const shared = await Container.get(SharedWorkflowRepository).findOne({ relations: ['workflow', 'role'], where: whereClause({ user, @@ -282,7 +287,7 @@ export class WorkflowsService { await validateEntity(workflow); } - await Db.collections.Workflow.update( + await Container.get(WorkflowRepository).update( workflowId, pick(workflow, [ 'name', @@ -297,8 +302,8 @@ export class WorkflowsService { ); if (tagIds && !config.getEnv('workflowTagsDisabled')) { - await Db.collections.WorkflowTagMapping.delete({ workflowId }); - await Db.collections.WorkflowTagMapping.insert( + await Container.get(WorkflowTagMappingRepository).delete({ workflowId }); + await Container.get(WorkflowTagMappingRepository).insert( tagIds.map((tagId) => ({ tagId, workflowId })), ); } @@ -311,7 +316,7 @@ export class WorkflowsService { // We sadly get nothing back from "update". Neither if it updated a record // nor the new value. So query now the hopefully updated entry. - const updatedWorkflow = await Db.collections.Workflow.findOne({ + const updatedWorkflow = await Container.get(WorkflowRepository).findOne({ where: { id: workflowId }, relations, }); @@ -342,7 +347,7 @@ export class WorkflowsService { } catch (error) { // If workflow could not be activated set it again to inactive // and revert the versionId change so UI remains consistent - await Db.collections.Workflow.update(workflowId, { + await Container.get(WorkflowRepository).update(workflowId, { active: false, versionId: shared.workflow.versionId, }); @@ -447,7 +452,7 @@ export class WorkflowsService { static async delete(user: User, workflowId: string): Promise { await Container.get(ExternalHooks).run('workflow.delete', [workflowId]); - const sharedWorkflow = await Db.collections.SharedWorkflow.findOne({ + const sharedWorkflow = await Container.get(SharedWorkflowRepository).findOne({ relations: ['workflow', 'role'], where: whereClause({ user, @@ -466,12 +471,14 @@ export class WorkflowsService { await Container.get(ActiveWorkflowRunner).remove(workflowId); } - const idsForDeletion = await Db.collections.Execution.find({ - select: ['id'], - where: { workflowId }, - }).then((rows) => rows.map(({ id: executionId }) => ({ workflowId, executionId }))); + const idsForDeletion = await Container.get(ExecutionRepository) + .find({ + select: ['id'], + where: { workflowId }, + }) + .then((rows) => rows.map(({ id: executionId }) => ({ workflowId, executionId }))); - await Db.collections.Workflow.delete(workflowId); + await Container.get(WorkflowRepository).delete(workflowId); await Container.get(BinaryDataService).deleteMany(idsForDeletion); void Container.get(InternalHooks).onWorkflowDeleted(user, workflowId, false); @@ -481,7 +488,7 @@ export class WorkflowsService { } static async updateWorkflowTriggerCount(id: string, triggerCount: number): Promise { - const qb = Db.collections.Workflow.createQueryBuilder('workflow'); + const qb = Container.get(WorkflowRepository).createQueryBuilder('workflow'); return qb .update() .set({ @@ -527,7 +534,7 @@ export class WorkflowsService { * @param {IDataObject} newStaticData The static data to save */ static async saveStaticDataById(workflowId: string, newStaticData: IDataObject): Promise { - await Db.collections.Workflow.update(workflowId, { + await Container.get(WorkflowRepository).update(workflowId, { staticData: newStaticData, }); } diff --git a/packages/cli/test/integration/ActiveWorkflowRunner.test.ts b/packages/cli/test/integration/ActiveWorkflowRunner.test.ts index 33c2ffad3e..b069a8f839 100644 --- a/packages/cli/test/integration/ActiveWorkflowRunner.test.ts +++ b/packages/cli/test/integration/ActiveWorkflowRunner.test.ts @@ -14,14 +14,15 @@ import { WebhookService } from '@/services/webhook.service'; import * as WebhookHelpers from '@/WebhookHelpers'; import * as AdditionalData from '@/WorkflowExecuteAdditionalData'; import { WorkflowRunner } from '@/WorkflowRunner'; - -import { mockInstance, setSchedulerAsLoadedNode } from './shared/utils'; -import * as testDb from './shared/testDb'; -import type { User } from '@/databases/entities/User'; -import type { WebhookEntity } from '@/databases/entities/WebhookEntity'; +import type { User } from '@db/entities/User'; +import type { WebhookEntity } from '@db/entities/WebhookEntity'; import { NodeTypes } from '@/NodeTypes'; -import { chooseRandomly } from './shared/random'; import { MultiMainInstancePublisher } from '@/services/orchestration/main/MultiMainInstance.publisher.ee'; + +import { mockInstance } from '../shared/mocking'; +import { chooseRandomly } from './shared/random'; +import { setSchedulerAsLoadedNode } from './shared/utils'; +import * as testDb from './shared/testDb'; import { createOwner } from './shared/db/users'; import { createWorkflow } from './shared/db/workflows'; diff --git a/packages/cli/test/integration/ExternalSecrets/externalSecrets.api.test.ts b/packages/cli/test/integration/ExternalSecrets/externalSecrets.api.test.ts index f07b948a4b..c3ec7ffb07 100644 --- a/packages/cli/test/integration/ExternalSecrets/externalSecrets.api.test.ts +++ b/packages/cli/test/integration/ExternalSecrets/externalSecrets.api.test.ts @@ -1,36 +1,38 @@ import type { SuperAgentTest } from 'supertest'; import { License } from '@/License'; -import * as utils from '../shared/utils/'; import type { ExternalSecretsSettings, SecretsProviderState } from '@/Interfaces'; import { Cipher } from 'n8n-core'; -import { SettingsRepository } from '@/databases/repositories/settings.repository'; +import { SettingsRepository } from '@db/repositories/settings.repository'; import { Container } from 'typedi'; import { ExternalSecretsProviders } from '@/ExternalSecrets/ExternalSecretsProviders.ee'; +import config from '@/config'; +import { ExternalSecretsManager } from '@/ExternalSecrets/ExternalSecretsManager.ee'; +import { CREDENTIAL_BLANKING_VALUE } from '@/constants'; +import { jsonParse, type IDataObject } from 'n8n-workflow'; +import { mock } from 'jest-mock-extended'; + +import { mockInstance } from '../../shared/mocking'; +import { setupTestServer } from '../shared/utils'; +import { createOwner, createUser } from '../shared/db/users'; import { DummyProvider, FailedProvider, MockProviders, TestFailProvider, } from '../../shared/ExternalSecrets/utils'; -import config from '@/config'; -import { ExternalSecretsManager } from '@/ExternalSecrets/ExternalSecretsManager.ee'; -import { CREDENTIAL_BLANKING_VALUE } from '@/constants'; -import { jsonParse, type IDataObject } from 'n8n-workflow'; -import { mock } from 'jest-mock-extended'; -import { createOwner, createUser } from '../shared/db/users'; let authOwnerAgent: SuperAgentTest; let authMemberAgent: SuperAgentTest; -const licenseLike = utils.mockInstance(License, { +const licenseLike = mockInstance(License, { isExternalSecretsEnabled: jest.fn().mockReturnValue(true), isWithinUsersLimit: jest.fn().mockReturnValue(true), }); const mockProvidersInstance = new MockProviders(); -utils.mockInstance(ExternalSecretsProviders, mockProvidersInstance); +mockInstance(ExternalSecretsProviders, mockProvidersInstance); -const testServer = utils.setupTestServer({ endpointGroups: ['externalSecrets'] }); +const testServer = setupTestServer({ endpointGroups: ['externalSecrets'] }); const connectedDate = '2023-08-01T12:32:29.000Z'; diff --git a/packages/cli/test/integration/audit/credentials.risk.test.ts b/packages/cli/test/integration/audit/credentials.risk.test.ts index 10d1d9ecbd..104ac00476 100644 --- a/packages/cli/test/integration/audit/credentials.risk.test.ts +++ b/packages/cli/test/integration/audit/credentials.risk.test.ts @@ -1,11 +1,15 @@ import { v4 as uuid } from 'uuid'; -import * as Db from '@/Db'; import config from '@/config'; import { audit } from '@/audit'; import { CREDENTIALS_REPORT } from '@/audit/constants'; import { getRiskSection } from './utils'; import * as testDb from '../shared/testDb'; import { generateNanoId } from '@db/utils/generators'; +import { WorkflowRepository } from '@db/repositories/workflow.repository'; +import Container from 'typedi'; +import { CredentialsRepository } from '@db/repositories/credentials.repository'; +import { ExecutionRepository } from '@db/repositories/execution.repository'; +import { ExecutionDataRepository } from '@db/repositories/executionData.repository'; beforeAll(async () => { await testDb.init(); @@ -46,8 +50,8 @@ test('should report credentials not in any use', async () => { }; await Promise.all([ - Db.collections.Credentials.save(credentialDetails), - Db.collections.Workflow.save(workflowDetails), + Container.get(CredentialsRepository).save(credentialDetails), + Container.get(WorkflowRepository).save(workflowDetails), ]); const testAudit = await audit(['credentials']); @@ -74,7 +78,7 @@ test('should report credentials not in active use', async () => { nodesAccess: [{ nodeType: 'n8n-nodes-base.slack', date: '2022-12-21T11:23:00.561Z' }], }; - const credential = await Db.collections.Credentials.save(credentialDetails); + const credential = await Container.get(CredentialsRepository).save(credentialDetails); const workflowDetails = { id: generateNanoId(), @@ -93,7 +97,7 @@ test('should report credentials not in active use', async () => { ], }; - await Db.collections.Workflow.save(workflowDetails); + await Container.get(WorkflowRepository).save(workflowDetails); const testAudit = await audit(['credentials']); @@ -119,7 +123,7 @@ test('should report credential in not recently executed workflow', async () => { nodesAccess: [{ nodeType: 'n8n-nodes-base.slack', date: '2022-12-21T11:23:00.561Z' }], }; - const credential = await Db.collections.Credentials.save(credentialDetails); + const credential = await Container.get(CredentialsRepository).save(credentialDetails); const workflowDetails = { id: generateNanoId(), @@ -144,12 +148,12 @@ test('should report credential in not recently executed workflow', async () => { ], }; - const workflow = await Db.collections.Workflow.save(workflowDetails); + const workflow = await Container.get(WorkflowRepository).save(workflowDetails); const date = new Date(); date.setDate(date.getDate() - config.getEnv('security.audit.daysAbandonedWorkflow') - 1); - const savedExecution = await Db.collections.Execution.save({ + const savedExecution = await Container.get(ExecutionRepository).save({ finished: true, mode: 'manual', startedAt: date, @@ -157,7 +161,7 @@ test('should report credential in not recently executed workflow', async () => { workflowId: workflow.id, waitTill: null, }); - await Db.collections.ExecutionData.save({ + await Container.get(ExecutionDataRepository).save({ execution: savedExecution, data: '[]', workflowData: workflow, @@ -187,7 +191,7 @@ test('should not report credentials in recently executed workflow', async () => nodesAccess: [{ nodeType: 'n8n-nodes-base.slack', date: '2022-12-21T11:23:00.561Z' }], }; - const credential = await Db.collections.Credentials.save(credentialDetails); + const credential = await Container.get(CredentialsRepository).save(credentialDetails); const workflowDetails = { id: generateNanoId(), @@ -212,12 +216,12 @@ test('should not report credentials in recently executed workflow', async () => ], }; - const workflow = await Db.collections.Workflow.save(workflowDetails); + const workflow = await Container.get(WorkflowRepository).save(workflowDetails); const date = new Date(); date.setDate(date.getDate() - config.getEnv('security.audit.daysAbandonedWorkflow') + 1); - const savedExecution = await Db.collections.Execution.save({ + const savedExecution = await Container.get(ExecutionRepository).save({ finished: true, mode: 'manual', startedAt: date, @@ -226,7 +230,7 @@ test('should not report credentials in recently executed workflow', async () => waitTill: null, }); - await Db.collections.ExecutionData.save({ + await Container.get(ExecutionDataRepository).save({ execution: savedExecution, data: '[]', workflowData: workflow, diff --git a/packages/cli/test/integration/audit/database.risk.test.ts b/packages/cli/test/integration/audit/database.risk.test.ts index a4068f5d77..7a496edc4b 100644 --- a/packages/cli/test/integration/audit/database.risk.test.ts +++ b/packages/cli/test/integration/audit/database.risk.test.ts @@ -1,5 +1,4 @@ import { v4 as uuid } from 'uuid'; -import * as Db from '@/Db'; import { audit } from '@/audit'; import { DATABASE_REPORT, @@ -9,6 +8,8 @@ import { import { getRiskSection, saveManualTriggerWorkflow } from './utils'; import * as testDb from '../shared/testDb'; import { generateNanoId } from '@db/utils/generators'; +import { WorkflowRepository } from '@db/repositories/workflow.repository'; +import Container from 'typedi'; beforeAll(async () => { await testDb.init(); @@ -50,7 +51,7 @@ test('should report expressions in queries', async () => { ], }; - return Db.collections.Workflow.save(details); + return Container.get(WorkflowRepository).save(details); }); await Promise.all(promises); @@ -105,7 +106,7 @@ test('should report expressions in query params', async () => { ], }; - return Db.collections.Workflow.save(details); + return Container.get(WorkflowRepository).save(details); }); await Promise.all(promises); @@ -157,7 +158,7 @@ test('should report unused query params', async () => { ], }; - return Db.collections.Workflow.save(details); + return Container.get(WorkflowRepository).save(details); }); await Promise.all(promises); diff --git a/packages/cli/test/integration/audit/filesystem.risk.test.ts b/packages/cli/test/integration/audit/filesystem.risk.test.ts index d8f3e711e7..440a4bdba0 100644 --- a/packages/cli/test/integration/audit/filesystem.risk.test.ts +++ b/packages/cli/test/integration/audit/filesystem.risk.test.ts @@ -1,9 +1,10 @@ import { v4 as uuid } from 'uuid'; -import * as Db from '@/Db'; import { audit } from '@/audit'; import { FILESYSTEM_INTERACTION_NODE_TYPES, FILESYSTEM_REPORT } from '@/audit/constants'; import { getRiskSection, saveManualTriggerWorkflow } from './utils'; import * as testDb from '../shared/testDb'; +import { WorkflowRepository } from '@db/repositories/workflow.repository'; +import Container from 'typedi'; beforeAll(async () => { await testDb.init(); @@ -26,7 +27,7 @@ test('should report filesystem interaction nodes', async () => { ); const promises = Object.entries(map).map(async ([nodeType, nodeId]) => { - const details = Db.collections.Workflow.create({ + const details = Container.get(WorkflowRepository).create({ name: 'My Test Workflow', active: false, connections: {}, @@ -42,7 +43,7 @@ test('should report filesystem interaction nodes', async () => { ], }); - return Db.collections.Workflow.save(details); + return Container.get(WorkflowRepository).save(details); }); await Promise.all(promises); diff --git a/packages/cli/test/integration/audit/instance.risk.test.ts b/packages/cli/test/integration/audit/instance.risk.test.ts index aa186c4d7c..bdd25a6f29 100644 --- a/packages/cli/test/integration/audit/instance.risk.test.ts +++ b/packages/cli/test/integration/audit/instance.risk.test.ts @@ -1,5 +1,4 @@ import { v4 as uuid } from 'uuid'; -import * as Db from '@/Db'; import { audit } from '@/audit'; import { INSTANCE_REPORT, WEBHOOK_VALIDATOR_NODE_TYPES } from '@/audit/constants'; import { @@ -13,6 +12,8 @@ import * as testDb from '../shared/testDb'; import { toReportTitle } from '@/audit/utils'; import config from '@/config'; import { generateNanoId } from '@db/utils/generators'; +import { WorkflowRepository } from '@db/repositories/workflow.repository'; +import Container from 'typedi'; beforeAll(async () => { await testDb.init(); @@ -53,7 +54,7 @@ test('should report webhook lacking authentication', async () => { ], }; - await Db.collections.Workflow.save(details); + await Container.get(WorkflowRepository).save(details); const testAudit = await audit(['instance']); @@ -97,7 +98,7 @@ test('should not report webhooks having basic or header auth', async () => { ], }; - return Db.collections.Workflow.save(details); + return Container.get(WorkflowRepository).save(details); }); await Promise.all(promises); @@ -158,7 +159,7 @@ test('should not report webhooks validated by direct children', async () => { }, }; - return Db.collections.Workflow.save(details); + return Container.get(WorkflowRepository).save(details); }); await Promise.all(promises); diff --git a/packages/cli/test/integration/audit/nodes.risk.test.ts b/packages/cli/test/integration/audit/nodes.risk.test.ts index 7a4940dfc1..a486ac7780 100644 --- a/packages/cli/test/integration/audit/nodes.risk.test.ts +++ b/packages/cli/test/integration/audit/nodes.risk.test.ts @@ -1,15 +1,16 @@ import { v4 as uuid } from 'uuid'; import { Container } from 'typedi'; -import * as Db from '@/Db'; import { audit } from '@/audit'; import { OFFICIAL_RISKY_NODE_TYPES, NODES_REPORT } from '@/audit/constants'; -import { getRiskSection, MOCK_PACKAGE, saveManualTriggerWorkflow } from './utils'; -import * as testDb from '../shared/testDb'; import { toReportTitle } from '@/audit/utils'; -import { mockInstance } from '../shared/utils/'; import { LoadNodesAndCredentials } from '@/LoadNodesAndCredentials'; import { NodeTypes } from '@/NodeTypes'; import { CommunityPackagesService } from '@/services/communityPackages.service'; +import { WorkflowRepository } from '@db/repositories/workflow.repository'; + +import { mockInstance } from '../../shared/mocking'; +import { getRiskSection, MOCK_PACKAGE, saveManualTriggerWorkflow } from './utils'; +import * as testDb from '../shared/testDb'; const nodesAndCredentials = mockInstance(LoadNodesAndCredentials); nodesAndCredentials.getCustomDirectories.mockReturnValue([]); @@ -37,7 +38,7 @@ test('should report risky official nodes', async () => { }, {}); const promises = Object.entries(map).map(async ([nodeType, nodeId]) => { - const details = Db.collections.Workflow.create({ + const details = Container.get(WorkflowRepository).create({ name: 'My Test Workflow', active: false, connections: {}, @@ -53,7 +54,7 @@ test('should report risky official nodes', async () => { ], }); - return Db.collections.Workflow.save(details); + return Container.get(WorkflowRepository).save(details); }); await Promise.all(promises); diff --git a/packages/cli/test/integration/audit/utils.ts b/packages/cli/test/integration/audit/utils.ts index 9a023fa5dd..f9d8d71106 100644 --- a/packages/cli/test/integration/audit/utils.ts +++ b/packages/cli/test/integration/audit/utils.ts @@ -1,12 +1,13 @@ import nock from 'nock'; import config from '@/config'; import { v4 as uuid } from 'uuid'; -import * as Db from '@/Db'; import { toReportTitle } from '@/audit/utils'; import * as constants from '@/constants'; import type { Risk } from '@/audit/types'; import type { InstalledNodes } from '@db/entities/InstalledNodes'; import type { InstalledPackages } from '@db/entities/InstalledPackages'; +import { WorkflowRepository } from '@db/repositories/workflow.repository'; +import Container from 'typedi'; type GetSectionKind = C extends 'instance' ? Risk.InstanceSection @@ -52,7 +53,7 @@ export async function saveManualTriggerWorkflow() { ], }; - return Db.collections.Workflow.save(details); + return Container.get(WorkflowRepository).save(details); } export const MOCK_09990_N8N_VERSION = { diff --git a/packages/cli/test/integration/auth.api.test.ts b/packages/cli/test/integration/auth.api.test.ts index 590263e6ec..8f54e4ca6b 100644 --- a/packages/cli/test/integration/auth.api.test.ts +++ b/packages/cli/test/integration/auth.api.test.ts @@ -3,7 +3,6 @@ import { Container } from 'typedi'; import { License } from '@/License'; import validator from 'validator'; import config from '@/config'; -import * as Db from '@/Db'; import { AUTH_COOKIE_NAME } from '@/constants'; import type { Role } from '@db/entities/Role'; import type { User } from '@db/entities/User'; @@ -13,6 +12,7 @@ import * as testDb from './shared/testDb'; import * as utils from './shared/utils/'; import { getGlobalMemberRole, getGlobalOwnerRole } from './shared/db/roles'; import { createUser, createUserShell } from './shared/db/users'; +import { UserRepository } from '@db/repositories/user.repository'; let globalOwnerRole: Role; let globalMemberRole: Role; @@ -292,7 +292,7 @@ describe('GET /resolve-signup-token', () => { .query({ inviteeId }); // cause inconsistent DB state - await Db.collections.User.update(owner.id, { email: '' }); + await Container.get(UserRepository).update(owner.id, { email: '' }); const fifth = await authOwnerAgent .get('/resolve-signup-token') .query({ inviterId: owner.id }) diff --git a/packages/cli/test/integration/binaryData.api.test.ts b/packages/cli/test/integration/binaryData.api.test.ts index 6eddb97137..f8b5b8a4d0 100644 --- a/packages/cli/test/integration/binaryData.api.test.ts +++ b/packages/cli/test/integration/binaryData.api.test.ts @@ -1,8 +1,10 @@ import fsp from 'node:fs/promises'; import { Readable } from 'node:stream'; import { BinaryDataService, FileNotFoundError } from 'n8n-core'; -import { mockInstance, setupTestServer } from './shared/utils'; import type { SuperAgentTest } from 'supertest'; + +import { mockInstance } from '../shared/mocking'; +import { setupTestServer } from './shared/utils'; import { createOwner } from './shared/db/users'; jest.mock('fs/promises'); diff --git a/packages/cli/test/integration/commands/credentials.cmd.test.ts b/packages/cli/test/integration/commands/credentials.cmd.test.ts index afb6698621..1104e3c6b9 100644 --- a/packages/cli/test/integration/commands/credentials.cmd.test.ts +++ b/packages/cli/test/integration/commands/credentials.cmd.test.ts @@ -3,8 +3,9 @@ import * as Config from '@oclif/config'; import { InternalHooks } from '@/InternalHooks'; import { ImportCredentialsCommand } from '@/commands/import/credentials'; import { LoadNodesAndCredentials } from '@/LoadNodesAndCredentials'; + +import { mockInstance } from '../../shared/mocking'; import * as testDb from '../shared/testDb'; -import { mockInstance } from '../shared/utils'; import { getAllCredentials } from '../shared/db/credentials'; beforeAll(async () => { diff --git a/packages/cli/test/integration/commands/import.cmd.test.ts b/packages/cli/test/integration/commands/import.cmd.test.ts index ff16690e3b..44e92261f6 100644 --- a/packages/cli/test/integration/commands/import.cmd.test.ts +++ b/packages/cli/test/integration/commands/import.cmd.test.ts @@ -3,8 +3,9 @@ import * as Config from '@oclif/config'; import { InternalHooks } from '@/InternalHooks'; import { ImportWorkflowsCommand } from '@/commands/import/workflow'; import { LoadNodesAndCredentials } from '@/LoadNodesAndCredentials'; + +import { mockInstance } from '../../shared/mocking'; import * as testDb from '../shared/testDb'; -import { mockInstance } from '../shared/utils/'; import { getAllWorkflows } from '../shared/db/workflows'; beforeAll(async () => { diff --git a/packages/cli/test/integration/commands/reset.cmd.test.ts b/packages/cli/test/integration/commands/reset.cmd.test.ts index 47a973b05c..6ffc229bb7 100644 --- a/packages/cli/test/integration/commands/reset.cmd.test.ts +++ b/packages/cli/test/integration/commands/reset.cmd.test.ts @@ -1,11 +1,13 @@ -import * as Db from '@/Db'; import { Reset } from '@/commands/user-management/reset'; import type { Role } from '@db/entities/Role'; -import * as testDb from '../shared/testDb'; -import { mockInstance } from '../shared/utils/'; import { InternalHooks } from '@/InternalHooks'; import { LoadNodesAndCredentials } from '@/LoadNodesAndCredentials'; import { NodeTypes } from '@/NodeTypes'; +import Container from 'typedi'; +import { UserRepository } from '@db/repositories/user.repository'; + +import { mockInstance } from '../../shared/mocking'; +import * as testDb from '../shared/testDb'; import { getGlobalOwnerRole } from '../shared/db/roles'; import { createUser } from '../shared/db/users'; @@ -34,7 +36,7 @@ test.skip('user-management:reset should reset DB to default user state', async ( await Reset.run(); - const user = await Db.collections.User.findOneBy({ globalRoleId: globalOwnerRole.id }); + const user = await Container.get(UserRepository).findOneBy({ globalRoleId: globalOwnerRole.id }); if (!user) { fail('No owner found after DB reset to default user state'); diff --git a/packages/cli/test/integration/commands/start.cmd.test.ts b/packages/cli/test/integration/commands/start.cmd.test.ts index 7fb6bb8533..1bf80c3254 100644 --- a/packages/cli/test/integration/commands/start.cmd.test.ts +++ b/packages/cli/test/integration/commands/start.cmd.test.ts @@ -1,12 +1,10 @@ import * as Config from '@oclif/config'; - -import { mockInstance } from '../shared/utils'; +import { DataSource } from 'typeorm'; import { Start } from '@/commands/start'; import { BaseCommand } from '@/commands/BaseCommand'; import config from '@/config'; import { License } from '@/License'; - import { ExternalSecretsManager } from '@/ExternalSecrets/ExternalSecretsManager.ee'; import { MultiMainInstancePublisher } from '@/services/orchestration/main/MultiMainInstance.publisher.ee'; import { ActiveWorkflowRunner } from '@/ActiveWorkflowRunner'; @@ -16,9 +14,12 @@ import { RedisServicePubSubPublisher } from '@/services/redis/RedisServicePubSub import { RedisServicePubSubSubscriber } from '@/services/redis/RedisServicePubSubSubscriber'; import { OrchestrationHandlerMainService } from '@/services/orchestration/main/orchestration.handler.main.service'; +import { mockInstance } from '../../shared/mocking'; + const oclifConfig: Config.IConfig = new Config.Config({ root: __dirname }); beforeAll(() => { + mockInstance(DataSource); mockInstance(ExternalSecretsManager); mockInstance(ActiveWorkflowRunner); mockInstance(WorkflowHistoryManager); diff --git a/packages/cli/test/integration/commands/worker.cmd.test.ts b/packages/cli/test/integration/commands/worker.cmd.test.ts index 939fd6db0e..3b7567faae 100644 --- a/packages/cli/test/integration/commands/worker.cmd.test.ts +++ b/packages/cli/test/integration/commands/worker.cmd.test.ts @@ -1,4 +1,3 @@ -import { mockInstance } from '../shared/utils/'; import { Worker } from '@/commands/worker'; import * as Config from '@oclif/config'; import config from '@/config'; @@ -18,6 +17,8 @@ import { RedisService } from '@/services/redis.service'; import { OrchestrationHandlerWorkerService } from '@/services/orchestration/worker/orchestration.handler.worker.service'; import { OrchestrationWorkerService } from '@/services/orchestration/worker/orchestration.worker.service'; +import { mockInstance } from '../../shared/mocking'; + const oclifConfig: Config.IConfig = new Config.Config({ root: __dirname }); beforeAll(async () => { diff --git a/packages/cli/test/integration/community-packages.api.test.ts b/packages/cli/test/integration/community-packages.api.test.ts index 40aa879fdd..1eb184a88c 100644 --- a/packages/cli/test/integration/community-packages.api.test.ts +++ b/packages/cli/test/integration/community-packages.api.test.ts @@ -7,14 +7,9 @@ import { LoadNodesAndCredentials } from '@/LoadNodesAndCredentials'; import { Push } from '@/push'; import { CommunityPackagesService } from '@/services/communityPackages.service'; +import { mockInstance } from '../shared/mocking'; import { COMMUNITY_PACKAGE_VERSION } from './shared/constants'; -import { - mockInstance, - setupTestServer, - mockPackage, - mockNode, - mockPackageName, -} from './shared/utils'; +import { setupTestServer, mockPackage, mockNode, mockPackageName } from './shared/utils'; import { createOwner } from './shared/db/users'; const communityPackagesService = mockInstance(CommunityPackagesService, { diff --git a/packages/cli/test/integration/credentials.ee.test.ts b/packages/cli/test/integration/credentials.ee.test.ts index dcef22c17e..d980338772 100644 --- a/packages/cli/test/integration/credentials.ee.test.ts +++ b/packages/cli/test/integration/credentials.ee.test.ts @@ -2,7 +2,6 @@ import type { SuperAgentTest } from 'supertest'; import { In } from 'typeorm'; import type { IUser } from 'n8n-workflow'; -import * as Db from '@/Db'; import type { Credentials } from '@/requests'; import * as UserManagementHelpers from '@/UserManagement/UserManagementHelper'; import type { Role } from '@db/entities/Role'; @@ -15,6 +14,8 @@ import * as utils from './shared/utils/'; import { affixRoleToSaveCredential, shareCredentialWithUsers } from './shared/db/credentials'; import { getCredentialOwnerRole, getGlobalMemberRole, getGlobalOwnerRole } from './shared/db/roles'; import { createManyUsers, createUser, createUserShell } from './shared/db/users'; +import { SharedCredentialsRepository } from '@db/repositories/sharedCredentials.repository'; +import Container from 'typedi'; const sharingSpy = jest.spyOn(UserManagementHelpers, 'isSharingEnabled').mockReturnValue(true); const testServer = utils.setupTestServer({ endpointGroups: ['credentials'] }); @@ -340,7 +341,7 @@ describe('PUT /credentials/:id/share', () => { expect(response.statusCode).toBe(200); expect(response.body.data).toBeUndefined(); - const sharedCredentials = await Db.collections.SharedCredentials.find({ + const sharedCredentials = await Container.get(SharedCredentialsRepository).find({ relations: ['role'], where: { credentialsId: savedCredential.id }, }); @@ -375,7 +376,7 @@ describe('PUT /credentials/:id/share', () => { expect(response.body.data).toBeUndefined(); // check that sharings got correctly set in DB - const sharedCredentials = await Db.collections.SharedCredentials.find({ + const sharedCredentials = await Container.get(SharedCredentialsRepository).find({ relations: ['role'], where: { credentialsId: savedCredential.id, userId: In([...memberIds]) }, }); @@ -388,7 +389,7 @@ describe('PUT /credentials/:id/share', () => { }); // check that owner still exists - const ownerSharedCredential = await Db.collections.SharedCredentials.findOneOrFail({ + const ownerSharedCredential = await Container.get(SharedCredentialsRepository).findOneOrFail({ relations: ['role'], where: { credentialsId: savedCredential.id, userId: owner.id }, }); @@ -425,7 +426,7 @@ describe('PUT /credentials/:id/share', () => { expect(response.statusCode).toBe(200); - const sharedCredentials = await Db.collections.SharedCredentials.find({ + const sharedCredentials = await Container.get(SharedCredentialsRepository).find({ where: { credentialsId: savedCredential.id }, }); @@ -442,7 +443,7 @@ describe('PUT /credentials/:id/share', () => { expect(response.statusCode).toBe(200); - const sharedCredentials = await Db.collections.SharedCredentials.find({ + const sharedCredentials = await Container.get(SharedCredentialsRepository).find({ where: { credentialsId: savedCredential.id }, }); @@ -475,7 +476,7 @@ describe('PUT /credentials/:id/share', () => { expect(response.statusCode).toBe(200); - const sharedCredentials = await Db.collections.SharedCredentials.find({ + const sharedCredentials = await Container.get(SharedCredentialsRepository).find({ where: { credentialsId: savedCredential.id }, }); diff --git a/packages/cli/test/integration/credentials.test.ts b/packages/cli/test/integration/credentials.test.ts index e8c8b7af0d..90d8deaf45 100644 --- a/packages/cli/test/integration/credentials.test.ts +++ b/packages/cli/test/integration/credentials.test.ts @@ -1,6 +1,5 @@ import type { SuperAgentTest } from 'supertest'; -import * as Db from '@/Db'; import config from '@/config'; import * as UserManagementHelpers from '@/UserManagement/UserManagementHelper'; import type { Credentials } from '@/requests'; @@ -14,6 +13,9 @@ import * as utils from './shared/utils/'; import { affixRoleToSaveCredential } from './shared/db/credentials'; import { getCredentialOwnerRole, getGlobalMemberRole, getGlobalOwnerRole } from './shared/db/roles'; import { createManyUsers, createUser } from './shared/db/users'; +import { CredentialsRepository } from '@db/repositories/credentials.repository'; +import Container from 'typedi'; +import { SharedCredentialsRepository } from '@db/repositories/sharedCredentials.repository'; // mock that credentialsSharing is not enabled jest.spyOn(UserManagementHelpers, 'isSharingEnabled').mockReturnValue(false); @@ -109,14 +111,14 @@ describe('POST /credentials', () => { expect(nodesAccess[0].nodeType).toBe(payload.nodesAccess[0].nodeType); expect(encryptedData).not.toBe(payload.data); - const credential = await Db.collections.Credentials.findOneByOrFail({ id }); + const credential = await Container.get(CredentialsRepository).findOneByOrFail({ id }); expect(credential.name).toBe(payload.name); expect(credential.type).toBe(payload.type); expect(credential.nodesAccess[0].nodeType).toBe(payload.nodesAccess[0].nodeType); expect(credential.data).not.toBe(payload.data); - const sharedCredential = await Db.collections.SharedCredentials.findOneOrFail({ + const sharedCredential = await Container.get(SharedCredentialsRepository).findOneOrFail({ relations: ['user', 'credentials'], where: { credentialsId: credential.id }, }); @@ -156,13 +158,13 @@ describe('DELETE /credentials/:id', () => { expect(response.statusCode).toBe(200); expect(response.body).toEqual({ data: true }); - const deletedCredential = await Db.collections.Credentials.findOneBy({ + const deletedCredential = await Container.get(CredentialsRepository).findOneBy({ id: savedCredential.id, }); expect(deletedCredential).toBeNull(); // deleted - const deletedSharedCredential = await Db.collections.SharedCredentials.findOneBy({}); + const deletedSharedCredential = await Container.get(SharedCredentialsRepository).findOneBy({}); expect(deletedSharedCredential).toBeNull(); // deleted }); @@ -175,13 +177,13 @@ describe('DELETE /credentials/:id', () => { expect(response.statusCode).toBe(200); expect(response.body).toEqual({ data: true }); - const deletedCredential = await Db.collections.Credentials.findOneBy({ + const deletedCredential = await Container.get(CredentialsRepository).findOneBy({ id: savedCredential.id, }); expect(deletedCredential).toBeNull(); // deleted - const deletedSharedCredential = await Db.collections.SharedCredentials.findOneBy({}); + const deletedSharedCredential = await Container.get(SharedCredentialsRepository).findOneBy({}); expect(deletedSharedCredential).toBeNull(); // deleted }); @@ -194,13 +196,13 @@ describe('DELETE /credentials/:id', () => { expect(response.statusCode).toBe(200); expect(response.body).toEqual({ data: true }); - const deletedCredential = await Db.collections.Credentials.findOneBy({ + const deletedCredential = await Container.get(CredentialsRepository).findOneBy({ id: savedCredential.id, }); expect(deletedCredential).toBeNull(); // deleted - const deletedSharedCredential = await Db.collections.SharedCredentials.findOneBy({}); + const deletedSharedCredential = await Container.get(SharedCredentialsRepository).findOneBy({}); expect(deletedSharedCredential).toBeNull(); // deleted }); @@ -212,11 +214,13 @@ describe('DELETE /credentials/:id', () => { expect(response.statusCode).toBe(404); - const shellCredential = await Db.collections.Credentials.findOneBy({ id: savedCredential.id }); + const shellCredential = await Container.get(CredentialsRepository).findOneBy({ + id: savedCredential.id, + }); expect(shellCredential).toBeDefined(); // not deleted - const deletedSharedCredential = await Db.collections.SharedCredentials.findOneBy({}); + const deletedSharedCredential = await Container.get(SharedCredentialsRepository).findOneBy({}); expect(deletedSharedCredential).toBeDefined(); // not deleted }); @@ -250,14 +254,14 @@ describe('PATCH /credentials/:id', () => { expect(encryptedData).not.toBe(patchPayload.data); - const credential = await Db.collections.Credentials.findOneByOrFail({ id }); + const credential = await Container.get(CredentialsRepository).findOneByOrFail({ id }); expect(credential.name).toBe(patchPayload.name); expect(credential.type).toBe(patchPayload.type); expect(credential.nodesAccess[0].nodeType).toBe(patchPayload.nodesAccess[0].nodeType); expect(credential.data).not.toBe(patchPayload.data); - const sharedCredential = await Db.collections.SharedCredentials.findOneOrFail({ + const sharedCredential = await Container.get(SharedCredentialsRepository).findOneOrFail({ relations: ['credentials'], where: { credentialsId: credential.id }, }); @@ -287,14 +291,14 @@ describe('PATCH /credentials/:id', () => { expect(encryptedData).not.toBe(patchPayload.data); - const credential = await Db.collections.Credentials.findOneByOrFail({ id }); + const credential = await Container.get(CredentialsRepository).findOneByOrFail({ id }); expect(credential.name).toBe(patchPayload.name); expect(credential.type).toBe(patchPayload.type); expect(credential.nodesAccess[0].nodeType).toBe(patchPayload.nodesAccess[0].nodeType); expect(credential.data).not.toBe(patchPayload.data); - const sharedCredential = await Db.collections.SharedCredentials.findOneOrFail({ + const sharedCredential = await Container.get(SharedCredentialsRepository).findOneOrFail({ relations: ['credentials'], where: { credentialsId: credential.id }, }); @@ -324,14 +328,14 @@ describe('PATCH /credentials/:id', () => { expect(encryptedData).not.toBe(patchPayload.data); - const credential = await Db.collections.Credentials.findOneByOrFail({ id }); + const credential = await Container.get(CredentialsRepository).findOneByOrFail({ id }); expect(credential.name).toBe(patchPayload.name); expect(credential.type).toBe(patchPayload.type); expect(credential.nodesAccess[0].nodeType).toBe(patchPayload.nodesAccess[0].nodeType); expect(credential.data).not.toBe(patchPayload.data); - const sharedCredential = await Db.collections.SharedCredentials.findOneOrFail({ + const sharedCredential = await Container.get(SharedCredentialsRepository).findOneOrFail({ relations: ['credentials'], where: { credentialsId: credential.id }, }); @@ -349,7 +353,7 @@ describe('PATCH /credentials/:id', () => { expect(response.statusCode).toBe(404); - const shellCredential = await Db.collections.Credentials.findOneByOrFail({ + const shellCredential = await Container.get(CredentialsRepository).findOneByOrFail({ id: savedCredential.id, }); diff --git a/packages/cli/test/integration/executions.controller.test.ts b/packages/cli/test/integration/executions.controller.test.ts index c302ea5660..16f7e8d780 100644 --- a/packages/cli/test/integration/executions.controller.test.ts +++ b/packages/cli/test/integration/executions.controller.test.ts @@ -1,4 +1,4 @@ -import type { User } from '@/databases/entities/User'; +import type { User } from '@db/entities/User'; import { createSuccessfulExecution, getAllExecutions } from './shared/db/executions'; import { createOwner } from './shared/db/users'; import { createWorkflow } from './shared/db/workflows'; diff --git a/packages/cli/test/integration/ldap/ldap.api.test.ts b/packages/cli/test/integration/ldap/ldap.api.test.ts index cc166716cb..d4b32f0080 100644 --- a/packages/cli/test/integration/ldap/ldap.api.test.ts +++ b/packages/cli/test/integration/ldap/ldap.api.test.ts @@ -4,7 +4,6 @@ import { Not } from 'typeorm'; import { jsonParse } from 'n8n-workflow'; import config from '@/config'; -import * as Db from '@/Db'; import type { Role } from '@db/entities/Role'; import type { User } from '@db/entities/User'; import { LDAP_DEFAULT_CONFIGURATION, LDAP_FEATURE_NAME } from '@/Ldap/constants'; @@ -21,6 +20,9 @@ import Container from 'typedi'; import { Cipher } from 'n8n-core'; import { getGlobalMemberRole, getGlobalOwnerRole } from '../shared/db/roles'; import { createLdapUser, createUser, getAllUsers, getLdapIdentities } from '../shared/db/users'; +import { UserRepository } from '@db/repositories/user.repository'; +import { SettingsRepository } from '@db/repositories/settings.repository'; +import { AuthProviderSyncHistoryRepository } from '@db/repositories/authProviderSyncHistory.repository'; jest.mock('@/telemetry'); @@ -73,7 +75,7 @@ beforeEach(async () => { 'Workflow', ]); - await Db.collections.User.delete({ id: Not(owner.id) }); + await Container.get(UserRepository).delete({ id: Not(owner.id) }); jest.mock('@/telemetry'); @@ -83,7 +85,7 @@ beforeEach(async () => { }); const createLdapConfig = async (attributes: Partial = {}): Promise => { - const { value: ldapConfig } = await Db.collections.Settings.save({ + const { value: ldapConfig } = await Container.get(SettingsRepository).save({ key: LDAP_FEATURE_NAME, value: JSON.stringify({ ...defaultLdapConfig, @@ -174,7 +176,7 @@ describe('PUT /ldap/config', () => { // disable the login, so the strategy is applied await authOwnerAgent.put('/ldap/config').send({ ...configuration, loginEnabled: false }); - const emailUser = await Db.collections.User.findOneByOrFail({ id: member.id }); + const emailUser = await Container.get(UserRepository).findOneByOrFail({ id: member.id }); const localLdapIdentities = await getLdapIdentities(); expect(getCurrentAuthenticationMethod()).toBe('email'); @@ -237,7 +239,9 @@ describe('POST /ldap/sync', () => { await authOwnerAgent.post('/ldap/sync').send({ type: 'dry' }).expect(200); - const synchronization = await Db.collections.AuthProviderSyncHistory.findOneByOrFail({}); + const synchronization = await Container.get( + AuthProviderSyncHistoryRepository, + ).findOneByOrFail({}); expect(synchronization.id).toBeDefined(); expect(synchronization.startedAt).toBeDefined(); @@ -268,7 +272,7 @@ describe('POST /ldap/sync', () => { expect(synchronization.created).toBe(1); // Make sure only the instance owner is on the DB - const localDbUsers = await Db.collections.User.find(); + const localDbUsers = await Container.get(UserRepository).find(); expect(localDbUsers.length).toBe(1); expect(localDbUsers[0].id).toBe(owner.id); }); @@ -330,7 +334,9 @@ describe('POST /ldap/sync', () => { await authOwnerAgent.post('/ldap/sync').send({ type: 'live' }).expect(200); - const synchronization = await Db.collections.AuthProviderSyncHistory.findOneByOrFail({}); + const synchronization = await Container.get( + AuthProviderSyncHistoryRepository, + ).findOneByOrFail({}); expect(synchronization.id).toBeDefined(); expect(synchronization.startedAt).toBeDefined(); diff --git a/packages/cli/test/integration/me.api.test.ts b/packages/cli/test/integration/me.api.test.ts index 330345a12d..552e0d649c 100644 --- a/packages/cli/test/integration/me.api.test.ts +++ b/packages/cli/test/integration/me.api.test.ts @@ -1,7 +1,6 @@ import type { SuperAgentTest } from 'supertest'; import { IsNull } from 'typeorm'; import validator from 'validator'; -import * as Db from '@/Db'; import type { Role } from '@db/entities/Role'; import type { User } from '@db/entities/User'; import { SUCCESS_RESPONSE_BODY } from './shared/constants'; @@ -16,6 +15,8 @@ import * as testDb from './shared/testDb'; import * as utils from './shared/utils/'; import { getGlobalMemberRole, getGlobalOwnerRole } from './shared/db/roles'; import { addApiKey, createUser, createUserShell } from './shared/db/users'; +import Container from 'typedi'; +import { UserRepository } from '@db/repositories/user.repository'; const testServer = utils.setupTestServer({ endpointGroups: ['me'] }); @@ -70,7 +71,7 @@ describe('Owner shell', () => { expect(globalRole.scope).toBe('global'); expect(apiKey).toBeUndefined(); - const storedOwnerShell = await Db.collections.User.findOneByOrFail({ id }); + const storedOwnerShell = await Container.get(UserRepository).findOneByOrFail({ id }); expect(storedOwnerShell.email).toBe(validPayload.email.toLowerCase()); expect(storedOwnerShell.firstName).toBe(validPayload.firstName); @@ -83,7 +84,7 @@ describe('Owner shell', () => { const response = await authOwnerShellAgent.patch('/me').send(invalidPayload); expect(response.statusCode).toBe(400); - const storedOwnerShell = await Db.collections.User.findOneByOrFail({}); + const storedOwnerShell = await Container.get(UserRepository).findOneByOrFail({}); expect(storedOwnerShell.email).toBeNull(); expect(storedOwnerShell.firstName).toBeNull(); expect(storedOwnerShell.lastName).toBeNull(); @@ -102,7 +103,7 @@ describe('Owner shell', () => { const response = await authOwnerShellAgent.patch('/me/password').send(payload); expect([400, 500].includes(response.statusCode)).toBe(true); - const storedMember = await Db.collections.User.findOneByOrFail({}); + const storedMember = await Container.get(UserRepository).findOneByOrFail({}); if (payload.newPassword) { expect(storedMember.password).not.toBe(payload.newPassword); @@ -113,7 +114,7 @@ describe('Owner shell', () => { } } - const storedOwnerShell = await Db.collections.User.findOneByOrFail({}); + const storedOwnerShell = await Container.get(UserRepository).findOneByOrFail({}); expect(storedOwnerShell.password).toBeNull(); }); @@ -126,7 +127,7 @@ describe('Owner shell', () => { expect(response.statusCode).toBe(200); expect(response.body).toEqual(SUCCESS_RESPONSE_BODY); - const storedShellOwner = await Db.collections.User.findOneOrFail({ + const storedShellOwner = await Container.get(UserRepository).findOneOrFail({ where: { email: IsNull() }, }); @@ -141,7 +142,7 @@ describe('Owner shell', () => { expect(response.body.data.apiKey).toBeDefined(); expect(response.body.data.apiKey).not.toBeNull(); - const storedShellOwner = await Db.collections.User.findOneOrFail({ + const storedShellOwner = await Container.get(UserRepository).findOneOrFail({ where: { email: IsNull() }, }); @@ -160,7 +161,7 @@ describe('Owner shell', () => { expect(response.statusCode).toBe(200); - const storedShellOwner = await Db.collections.User.findOneOrFail({ + const storedShellOwner = await Container.get(UserRepository).findOneOrFail({ where: { email: IsNull() }, }); @@ -213,7 +214,7 @@ describe('Member', () => { expect(globalRole.scope).toBe('global'); expect(apiKey).toBeUndefined(); - const storedMember = await Db.collections.User.findOneByOrFail({ id }); + const storedMember = await Container.get(UserRepository).findOneByOrFail({ id }); expect(storedMember.email).toBe(validPayload.email.toLowerCase()); expect(storedMember.firstName).toBe(validPayload.firstName); @@ -226,7 +227,7 @@ describe('Member', () => { const response = await authMemberAgent.patch('/me').send(invalidPayload); expect(response.statusCode).toBe(400); - const storedMember = await Db.collections.User.findOneByOrFail({}); + const storedMember = await Container.get(UserRepository).findOneByOrFail({}); expect(storedMember.email).toBe(member.email); expect(storedMember.firstName).toBe(member.firstName); expect(storedMember.lastName).toBe(member.lastName); @@ -243,7 +244,7 @@ describe('Member', () => { expect(response.statusCode).toBe(200); expect(response.body).toEqual(SUCCESS_RESPONSE_BODY); - const storedMember = await Db.collections.User.findOneByOrFail({}); + const storedMember = await Container.get(UserRepository).findOneByOrFail({}); expect(storedMember.password).not.toBe(member.password); expect(storedMember.password).not.toBe(validPayload.newPassword); }); @@ -253,7 +254,7 @@ describe('Member', () => { const response = await authMemberAgent.patch('/me/password').send(payload); expect([400, 500].includes(response.statusCode)).toBe(true); - const storedMember = await Db.collections.User.findOneByOrFail({}); + const storedMember = await Container.get(UserRepository).findOneByOrFail({}); if (payload.newPassword) { expect(storedMember.password).not.toBe(payload.newPassword); @@ -272,9 +273,9 @@ describe('Member', () => { expect(response.statusCode).toBe(200); expect(response.body).toEqual(SUCCESS_RESPONSE_BODY); - const { personalizationAnswers: storedAnswers } = await Db.collections.User.findOneByOrFail( - {}, - ); + const { personalizationAnswers: storedAnswers } = await Container.get( + UserRepository, + ).findOneByOrFail({}); expect(storedAnswers).toEqual(validPayload); } @@ -287,7 +288,7 @@ describe('Member', () => { expect(response.body.data.apiKey).toBeDefined(); expect(response.body.data.apiKey).not.toBeNull(); - const storedMember = await Db.collections.User.findOneByOrFail({ id: member.id }); + const storedMember = await Container.get(UserRepository).findOneByOrFail({ id: member.id }); expect(storedMember.apiKey).toEqual(response.body.data.apiKey); }); @@ -304,7 +305,7 @@ describe('Member', () => { expect(response.statusCode).toBe(200); - const storedMember = await Db.collections.User.findOneByOrFail({ id: member.id }); + const storedMember = await Container.get(UserRepository).findOneByOrFail({ id: member.id }); expect(storedMember.apiKey).toBeNull(); }); @@ -347,7 +348,7 @@ describe('Owner', () => { expect(globalRole.scope).toBe('global'); expect(apiKey).toBeUndefined(); - const storedOwner = await Db.collections.User.findOneByOrFail({ id }); + const storedOwner = await Container.get(UserRepository).findOneByOrFail({ id }); expect(storedOwner.email).toBe(validPayload.email.toLowerCase()); expect(storedOwner.firstName).toBe(validPayload.firstName); diff --git a/packages/cli/test/integration/mfa/mfa.api.test.ts b/packages/cli/test/integration/mfa/mfa.api.test.ts index de94a3333f..1f9a5318ea 100644 --- a/packages/cli/test/integration/mfa/mfa.api.test.ts +++ b/packages/cli/test/integration/mfa/mfa.api.test.ts @@ -1,6 +1,5 @@ import Container from 'typedi'; import config from '@/config'; -import * as Db from '@/Db'; import type { Role } from '@db/entities/Role'; import type { User } from '@db/entities/User'; import { randomPassword } from '@/Ldap/helpers'; @@ -10,6 +9,7 @@ import { randomDigit, randomString, randomValidPassword, uniqueId } from '../sha import * as testDb from '../shared/testDb'; import * as utils from '../shared/utils'; import { createUser, createUserWithMfaEnabled } from '../shared/db/users'; +import { UserRepository } from '@db/repositories/user.repository'; jest.mock('@/telemetry'); @@ -161,7 +161,7 @@ describe('Enable MFA setup', () => { expect(statusCode).toBe(200); - const user = await Db.collections.User.findOneOrFail({ + const user = await Container.get(UserRepository).findOneOrFail({ where: {}, select: ['mfaEnabled', 'mfaRecoveryCodes', 'mfaSecret'], }); @@ -181,7 +181,7 @@ describe('Disable MFA setup', () => { expect(response.statusCode).toBe(200); - const dbUser = await Db.collections.User.findOneOrFail({ + const dbUser = await Container.get(UserRepository).findOneOrFail({ where: { id: user.id }, select: ['mfaEnabled', 'mfaRecoveryCodes', 'mfaSecret'], }); @@ -375,7 +375,7 @@ describe('Login', () => { expect(data.mfaEnabled).toBe(true); expect(data.hasRecoveryCodesLeft).toBe(true); - const dbUser = await Db.collections.User.findOneOrFail({ + const dbUser = await Container.get(UserRepository).findOneOrFail({ where: { id: user.id }, select: ['mfaEnabled', 'mfaRecoveryCodes', 'mfaSecret'], }); diff --git a/packages/cli/test/integration/owner.api.test.ts b/packages/cli/test/integration/owner.api.test.ts index 0819dffc70..93ee3e5b97 100644 --- a/packages/cli/test/integration/owner.api.test.ts +++ b/packages/cli/test/integration/owner.api.test.ts @@ -2,7 +2,6 @@ import validator from 'validator'; import type { SuperAgentTest } from 'supertest'; import config from '@/config'; -import * as Db from '@/Db'; import type { Role } from '@db/entities/Role'; import type { User } from '@db/entities/User'; import { @@ -15,6 +14,8 @@ import * as testDb from './shared/testDb'; import * as utils from './shared/utils/'; import { getGlobalOwnerRole } from './shared/db/roles'; import { createUserShell } from './shared/db/users'; +import { UserRepository } from '@db/repositories/user.repository'; +import Container from 'typedi'; const testServer = utils.setupTestServer({ endpointGroups: ['owner'] }); @@ -72,7 +73,7 @@ describe('POST /owner/setup', () => { expect(globalRole.scope).toBe('global'); expect(apiKey).toBeUndefined(); - const storedOwner = await Db.collections.User.findOneByOrFail({ id }); + const storedOwner = await Container.get(UserRepository).findOneByOrFail({ id }); expect(storedOwner.password).not.toBe(newOwnerData.password); expect(storedOwner.email).toBe(newOwnerData.email); expect(storedOwner.firstName).toBe(newOwnerData.firstName); @@ -102,7 +103,7 @@ describe('POST /owner/setup', () => { expect(id).toBe(ownerShell.id); expect(email).toBe(newOwnerData.email.toLowerCase()); - const storedOwner = await Db.collections.User.findOneByOrFail({ id }); + const storedOwner = await Container.get(UserRepository).findOneByOrFail({ id }); expect(storedOwner.email).toBe(newOwnerData.email.toLowerCase()); }); diff --git a/packages/cli/test/integration/passwordReset.api.test.ts b/packages/cli/test/integration/passwordReset.api.test.ts index cd6660deb2..1cdd8017c8 100644 --- a/packages/cli/test/integration/passwordReset.api.test.ts +++ b/packages/cli/test/integration/passwordReset.api.test.ts @@ -4,7 +4,6 @@ import { Container } from 'typedi'; import { mock } from 'jest-mock-extended'; import { License } from '@/License'; -import * as Db from '@/Db'; import config from '@/config'; import type { Role } from '@db/entities/Role'; import type { User } from '@db/entities/User'; @@ -13,8 +12,10 @@ import { ExternalHooks } from '@/ExternalHooks'; import { JwtService } from '@/services/jwt.service'; import { UserService } from '@/services/user.service'; import { UserManagementMailer } from '@/UserManagement/email'; +import { UserRepository } from '@db/repositories/user.repository'; -import * as utils from './shared/utils/'; +import { mockInstance } from '../shared/mocking'; +import { getAuthToken, setupTestServer } from './shared/utils/'; import { randomEmail, randomInvalidPassword, @@ -33,9 +34,9 @@ let globalMemberRole: Role; let owner: User; let member: User; -const externalHooks = utils.mockInstance(ExternalHooks); -const mailer = utils.mockInstance(UserManagementMailer, { isEmailSetUp: true }); -const testServer = utils.setupTestServer({ endpointGroups: ['passwordReset'] }); +const externalHooks = mockInstance(ExternalHooks); +const mailer = mockInstance(UserManagementMailer, { isEmailSetUp: true }); +const testServer = setupTestServer({ endpointGroups: ['passwordReset'] }); const jwtService = Container.get(JwtService); let userService: UserService; @@ -199,10 +200,10 @@ describe('POST /change-password', () => { expect(response.statusCode).toBe(200); - const authToken = utils.getAuthToken(response); + const authToken = getAuthToken(response); expect(authToken).toBeDefined(); - const { password: storedPassword } = await Db.collections.User.findOneByOrFail({ + const { password: storedPassword } = await Container.get(UserRepository).findOneByOrFail({ id: owner.id, }); @@ -243,7 +244,7 @@ describe('POST /change-password', () => { .post('/change-password') .query(invalidPayload); expect(response.statusCode).toBe(400); - const { password: storedPassword } = await Db.collections.User.findOneByOrFail({ + const { password: storedPassword } = await Container.get(UserRepository).findOneByOrFail({ id: owner.id, }); expect(owner.password).toBe(storedPassword); @@ -276,10 +277,10 @@ describe('POST /change-password', () => { expect(response.statusCode).toBe(200); - const authToken = utils.getAuthToken(response); + const authToken = getAuthToken(response); expect(authToken).toBeDefined(); - const { password: storedPassword } = await Db.collections.User.findOneByOrFail({ + const { password: storedPassword } = await Container.get(UserRepository).findOneByOrFail({ id: owner.id, }); diff --git a/packages/cli/test/integration/pruning.service.test.ts b/packages/cli/test/integration/pruning.service.test.ts index 65fa9833dc..14ed6b4874 100644 --- a/packages/cli/test/integration/pruning.service.test.ts +++ b/packages/cli/test/integration/pruning.service.test.ts @@ -1,15 +1,17 @@ import config from '@/config'; -import * as Db from '@/Db'; import { BinaryDataService } from 'n8n-core'; import type { ExecutionStatus } from 'n8n-workflow'; +import Container from 'typedi'; import * as testDb from './shared/testDb'; import type { ExecutionEntity } from '@db/entities/ExecutionEntity'; import type { WorkflowEntity } from '@db/entities/WorkflowEntity'; +import { ExecutionRepository } from '@db/repositories/execution.repository'; import { TIME } from '@/constants'; import { PruningService } from '@/services/pruning.service'; import { Logger } from '@/Logger'; -import { mockInstance } from './shared/utils'; + +import { mockInstance } from '../shared/mocking'; import { createWorkflow } from './shared/db/workflows'; import { createExecution, createSuccessfulExecution } from './shared/db/executions'; @@ -25,7 +27,7 @@ describe('softDeleteOnPruningCycle()', () => { pruningService = new PruningService( mockInstance(Logger), - Db.collections.Execution, + Container.get(ExecutionRepository), mockInstance(BinaryDataService), ); @@ -45,7 +47,7 @@ describe('softDeleteOnPruningCycle()', () => { }); async function findAllExecutions() { - return Db.collections.Execution.find({ + return Container.get(ExecutionRepository).find({ order: { id: 'asc' }, withDeleted: true, }); diff --git a/packages/cli/test/integration/publicApi/credentials.test.ts b/packages/cli/test/integration/publicApi/credentials.test.ts index e1a03df536..b754208dec 100644 --- a/packages/cli/test/integration/publicApi/credentials.test.ts +++ b/packages/cli/test/integration/publicApi/credentials.test.ts @@ -1,5 +1,4 @@ import type { SuperAgentTest } from 'supertest'; -import * as Db from '@/Db'; import type { Role } from '@db/entities/Role'; import type { User } from '@db/entities/User'; @@ -10,6 +9,9 @@ import * as testDb from '../shared/testDb'; import { affixRoleToSaveCredential } from '../shared/db/credentials'; import { getAllRoles } from '../shared/db/roles'; import { addApiKey, createUser, createUserShell } from '../shared/db/users'; +import { CredentialsRepository } from '@db/repositories/credentials.repository'; +import Container from 'typedi'; +import { SharedCredentialsRepository } from '@db/repositories/sharedCredentials.repository'; let globalMemberRole: Role; let credentialOwnerRole: Role; @@ -64,13 +66,13 @@ describe('POST /credentials', () => { expect(name).toBe(payload.name); expect(type).toBe(payload.type); - const credential = await Db.collections.Credentials.findOneByOrFail({ id }); + const credential = await Container.get(CredentialsRepository).findOneByOrFail({ id }); expect(credential.name).toBe(payload.name); expect(credential.type).toBe(payload.type); expect(credential.data).not.toBe(payload.data); - const sharedCredential = await Db.collections.SharedCredentials.findOneOrFail({ + const sharedCredential = await Container.get(SharedCredentialsRepository).findOneOrFail({ relations: ['user', 'credentials', 'role'], where: { credentialsId: credential.id, userId: owner.id }, }); @@ -100,13 +102,13 @@ describe('DELETE /credentials/:id', () => { expect(name).toBe(savedCredential.name); expect(type).toBe(savedCredential.type); - const deletedCredential = await Db.collections.Credentials.findOneBy({ + const deletedCredential = await Container.get(CredentialsRepository).findOneBy({ id: savedCredential.id, }); expect(deletedCredential).toBeNull(); // deleted - const deletedSharedCredential = await Db.collections.SharedCredentials.findOneBy({}); + const deletedSharedCredential = await Container.get(SharedCredentialsRepository).findOneBy({}); expect(deletedSharedCredential).toBeNull(); // deleted }); @@ -118,13 +120,13 @@ describe('DELETE /credentials/:id', () => { expect(response.statusCode).toBe(200); - const deletedCredential = await Db.collections.Credentials.findOneBy({ + const deletedCredential = await Container.get(CredentialsRepository).findOneBy({ id: savedCredential.id, }); expect(deletedCredential).toBeNull(); // deleted - const deletedSharedCredential = await Db.collections.SharedCredentials.findOneBy({}); + const deletedSharedCredential = await Container.get(SharedCredentialsRepository).findOneBy({}); expect(deletedSharedCredential).toBeNull(); // deleted }); @@ -141,13 +143,13 @@ describe('DELETE /credentials/:id', () => { expect(name).toBe(savedCredential.name); expect(type).toBe(savedCredential.type); - const deletedCredential = await Db.collections.Credentials.findOneBy({ + const deletedCredential = await Container.get(CredentialsRepository).findOneBy({ id: savedCredential.id, }); expect(deletedCredential).toBeNull(); // deleted - const deletedSharedCredential = await Db.collections.SharedCredentials.findOneBy({}); + const deletedSharedCredential = await Container.get(SharedCredentialsRepository).findOneBy({}); expect(deletedSharedCredential).toBeNull(); // deleted }); @@ -173,13 +175,13 @@ describe('DELETE /credentials/:id', () => { expect(name).toBe(savedCredential.name); expect(type).toBe(savedCredential.type); - const deletedCredential = await Db.collections.Credentials.findOneBy({ + const deletedCredential = await Container.get(CredentialsRepository).findOneBy({ id: savedCredential.id, }); expect(deletedCredential).toBeNull(); // deleted - const deletedSharedCredential = await Db.collections.SharedCredentials.findOne({ + const deletedSharedCredential = await Container.get(SharedCredentialsRepository).findOne({ where: { credentialsId: savedCredential.id, }, @@ -189,13 +191,13 @@ describe('DELETE /credentials/:id', () => { await Promise.all( [notToBeChangedCredential, notToBeChangedCredential2].map(async (credential) => { - const untouchedCredential = await Db.collections.Credentials.findOneBy({ + const untouchedCredential = await Container.get(CredentialsRepository).findOneBy({ id: credential.id, }); expect(untouchedCredential).toEqual(credential); // not deleted - const untouchedSharedCredential = await Db.collections.SharedCredentials.findOne({ + const untouchedSharedCredential = await Container.get(SharedCredentialsRepository).findOne({ where: { credentialsId: credential.id, }, @@ -213,13 +215,13 @@ describe('DELETE /credentials/:id', () => { expect(response.statusCode).toBe(404); - const shellCredential = await Db.collections.Credentials.findOneBy({ + const shellCredential = await Container.get(CredentialsRepository).findOneBy({ id: savedCredential.id, }); expect(shellCredential).toBeDefined(); // not deleted - const deletedSharedCredential = await Db.collections.SharedCredentials.findOneBy({}); + const deletedSharedCredential = await Container.get(SharedCredentialsRepository).findOneBy({}); expect(deletedSharedCredential).toBeDefined(); // not deleted }); diff --git a/packages/cli/test/integration/publicApi/users.ee.test.ts b/packages/cli/test/integration/publicApi/users.ee.test.ts index 1426486a8a..40709e8926 100644 --- a/packages/cli/test/integration/publicApi/users.ee.test.ts +++ b/packages/cli/test/integration/publicApi/users.ee.test.ts @@ -5,13 +5,14 @@ import { v4 as uuid } from 'uuid'; import type { Role } from '@db/entities/Role'; import { License } from '@/License'; +import { mockInstance } from '../../shared/mocking'; import { randomApiKey } from '../shared/random'; import * as utils from '../shared/utils/'; import * as testDb from '../shared/testDb'; import { getGlobalMemberRole, getGlobalOwnerRole } from '../shared/db/roles'; import { createUser, createUserShell } from '../shared/db/users'; -utils.mockInstance(License, { +mockInstance(License, { getUsersLimit: jest.fn().mockReturnValue(-1), }); @@ -216,7 +217,7 @@ describe('With license without quota:users', () => { let authOwnerAgent: SuperAgentTest; beforeEach(async () => { - utils.mockInstance(License, { getUsersLimit: jest.fn().mockReturnValue(null) }); + mockInstance(License, { getUsersLimit: jest.fn().mockReturnValue(null) }); const owner = await createUser({ globalRole: globalOwnerRole, diff --git a/packages/cli/test/integration/publicApi/workflows.test.ts b/packages/cli/test/integration/publicApi/workflows.test.ts index b6e18f5994..e1d471ffe5 100644 --- a/packages/cli/test/integration/publicApi/workflows.test.ts +++ b/packages/cli/test/integration/publicApi/workflows.test.ts @@ -1,18 +1,19 @@ import type { SuperAgentTest } from 'supertest'; -import * as Db from '@/Db'; -import type { Role } from '@db/entities/Role'; -import type { TagEntity } from '@db/entities/TagEntity'; -import type { User } from '@db/entities/User'; -import type { ActiveWorkflowRunner } from '@/ActiveWorkflowRunner'; - -import { randomApiKey } from '../shared/random'; -import * as utils from '../shared/utils/'; -import * as testDb from '../shared/testDb'; +import Container from 'typedi'; import type { INode } from 'n8n-workflow'; import { STARTING_NODES } from '@/constants'; import { License } from '@/License'; -import { WorkflowHistoryRepository } from '@/databases/repositories'; -import Container from 'typedi'; +import type { Role } from '@db/entities/Role'; +import type { TagEntity } from '@db/entities/TagEntity'; +import type { User } from '@db/entities/User'; +import { SharedWorkflowRepository } from '@db/repositories/sharedWorkflow.repository'; +import { WorkflowHistoryRepository } from '@db/repositories/workflowHistory.repository'; +import type { ActiveWorkflowRunner } from '@/ActiveWorkflowRunner'; + +import { mockInstance } from '../../shared/mocking'; +import { randomApiKey } from '../shared/random'; +import * as utils from '../shared/utils/'; +import * as testDb from '../shared/testDb'; import { getAllRoles } from '../shared/db/roles'; import { createUser } from '../shared/db/users'; import { createWorkflow, createWorkflowWithTrigger } from '../shared/db/workflows'; @@ -27,7 +28,7 @@ let workflowRunner: ActiveWorkflowRunner; const testServer = utils.setupTestServer({ endpointGroups: ['publicApi'] }); -const licenseLike = utils.mockInstance(License, { +const licenseLike = mockInstance(License, { isWorkflowHistoryLicensed: jest.fn().mockReturnValue(false), isWithinUsersLimit: jest.fn().mockReturnValue(true), }); @@ -58,7 +59,7 @@ beforeEach(async () => { 'Tag', 'Workflow', 'Credentials', - WorkflowHistoryRepository, + 'WorkflowHistory', ]); authOwnerAgent = testServer.publicApiAgentFor(owner); @@ -397,7 +398,7 @@ describe('DELETE /workflows/:id', () => { expect(updatedAt).toEqual(workflow.updatedAt.toISOString()); // make sure the workflow actually deleted from the db - const sharedWorkflow = await Db.collections.SharedWorkflow.findOneBy({ + const sharedWorkflow = await Container.get(SharedWorkflowRepository).findOneBy({ workflowId: workflow.id, }); @@ -426,7 +427,7 @@ describe('DELETE /workflows/:id', () => { expect(updatedAt).toEqual(workflow.updatedAt.toISOString()); // make sure the workflow actually deleted from the db - const sharedWorkflow = await Db.collections.SharedWorkflow.findOneBy({ + const sharedWorkflow = await Container.get(SharedWorkflowRepository).findOneBy({ workflowId: workflow.id, }); @@ -474,7 +475,7 @@ describe('POST /workflows/:id/activate', () => { expect(updatedAt).toEqual(workflow.updatedAt.toISOString()); // check whether the workflow is on the database - const sharedWorkflow = await Db.collections.SharedWorkflow.findOne({ + const sharedWorkflow = await Container.get(SharedWorkflowRepository).findOne({ where: { userId: member.id, workflowId: workflow.id, @@ -509,7 +510,7 @@ describe('POST /workflows/:id/activate', () => { expect(updatedAt).toEqual(workflow.updatedAt.toISOString()); // check whether the workflow is on the database - const sharedOwnerWorkflow = await Db.collections.SharedWorkflow.findOne({ + const sharedOwnerWorkflow = await Container.get(SharedWorkflowRepository).findOne({ where: { userId: owner.id, workflowId: workflow.id, @@ -518,7 +519,7 @@ describe('POST /workflows/:id/activate', () => { expect(sharedOwnerWorkflow).toBeNull(); - const sharedWorkflow = await Db.collections.SharedWorkflow.findOne({ + const sharedWorkflow = await Container.get(SharedWorkflowRepository).findOne({ where: { userId: member.id, workflowId: workflow.id, @@ -572,7 +573,7 @@ describe('POST /workflows/:id/deactivate', () => { expect(updatedAt).toBeDefined(); // get the workflow after it was deactivated - const sharedWorkflow = await Db.collections.SharedWorkflow.findOne({ + const sharedWorkflow = await Container.get(SharedWorkflowRepository).findOne({ where: { userId: member.id, workflowId: workflow.id, @@ -609,7 +610,7 @@ describe('POST /workflows/:id/deactivate', () => { expect(updatedAt).toBeDefined(); // check whether the workflow is deactivated in the database - const sharedOwnerWorkflow = await Db.collections.SharedWorkflow.findOne({ + const sharedOwnerWorkflow = await Container.get(SharedWorkflowRepository).findOne({ where: { userId: owner.id, workflowId: workflow.id, @@ -618,7 +619,7 @@ describe('POST /workflows/:id/deactivate', () => { expect(sharedOwnerWorkflow).toBeNull(); - const sharedWorkflow = await Db.collections.SharedWorkflow.findOne({ + const sharedWorkflow = await Container.get(SharedWorkflowRepository).findOne({ where: { userId: member.id, workflowId: workflow.id, @@ -685,7 +686,7 @@ describe('POST /workflows', () => { expect(updatedAt).toEqual(createdAt); // check if created workflow in DB - const sharedWorkflow = await Db.collections.SharedWorkflow.findOne({ + const sharedWorkflow = await Container.get(SharedWorkflowRepository).findOne({ where: { userId: member.id, workflowId: response.body.id, @@ -924,7 +925,7 @@ describe('PUT /workflows/:id', () => { expect(updatedAt).not.toBe(workflow.updatedAt.toISOString()); // check updated workflow in DB - const sharedWorkflow = await Db.collections.SharedWorkflow.findOne({ + const sharedWorkflow = await Container.get(SharedWorkflowRepository).findOne({ where: { userId: member.id, workflowId: response.body.id, @@ -1093,7 +1094,7 @@ describe('PUT /workflows/:id', () => { expect(updatedAt).not.toBe(workflow.updatedAt.toISOString()); // check updated workflow in DB - const sharedOwnerWorkflow = await Db.collections.SharedWorkflow.findOne({ + const sharedOwnerWorkflow = await Container.get(SharedWorkflowRepository).findOne({ where: { userId: owner.id, workflowId: response.body.id, @@ -1102,7 +1103,7 @@ describe('PUT /workflows/:id', () => { expect(sharedOwnerWorkflow).toBeNull(); - const sharedWorkflow = await Db.collections.SharedWorkflow.findOne({ + const sharedWorkflow = await Container.get(SharedWorkflowRepository).findOne({ where: { userId: member.id, workflowId: response.body.id, diff --git a/packages/cli/test/integration/shared/db/credentials.ts b/packages/cli/test/integration/shared/db/credentials.ts index 0ad6edf3af..780bfbe7dd 100644 --- a/packages/cli/test/integration/shared/db/credentials.ts +++ b/packages/cli/test/integration/shared/db/credentials.ts @@ -5,7 +5,8 @@ import type { ICredentialsDb } from '@/Interfaces'; import { RoleService } from '@/services/role.service'; import type { CredentialPayload } from '../types'; import Container from 'typedi'; -import { CredentialsRepository, SharedCredentialsRepository } from '@/databases/repositories'; +import { CredentialsRepository } from '@db/repositories/credentials.repository'; +import { SharedCredentialsRepository } from '@db/repositories/sharedCredentials.repository'; async function encryptCredentialData(credential: CredentialsEntity) { const { createCredentialsFromCredentialsEntity } = await import('@/CredentialsHelper'); diff --git a/packages/cli/test/integration/shared/db/executions.ts b/packages/cli/test/integration/shared/db/executions.ts index a0f06071ca..f68e5edf36 100644 --- a/packages/cli/test/integration/shared/db/executions.ts +++ b/packages/cli/test/integration/shared/db/executions.ts @@ -2,7 +2,8 @@ import Container from 'typedi'; import type { ExecutionData } from '@db/entities/ExecutionData'; import type { ExecutionEntity } from '@db/entities/ExecutionEntity'; import type { WorkflowEntity } from '@db/entities/WorkflowEntity'; -import { ExecutionDataRepository, ExecutionRepository } from '@db/repositories'; +import { ExecutionRepository } from '@db/repositories/execution.repository'; +import { ExecutionDataRepository } from '@db/repositories/executionData.repository'; export async function createManyExecutions( amount: number, diff --git a/packages/cli/test/integration/shared/db/tags.ts b/packages/cli/test/integration/shared/db/tags.ts index 7543153cb8..53bfb2ef5c 100644 --- a/packages/cli/test/integration/shared/db/tags.ts +++ b/packages/cli/test/integration/shared/db/tags.ts @@ -1,7 +1,8 @@ import Container from 'typedi'; import type { TagEntity } from '@db/entities/TagEntity'; import type { WorkflowEntity } from '@db/entities/WorkflowEntity'; -import { TagRepository, WorkflowTagMappingRepository } from '@db/repositories'; +import { TagRepository } from '@db/repositories/tag.repository'; +import { WorkflowTagMappingRepository } from '@db/repositories/workflowTagMapping.repository'; import { generateNanoId } from '@db/utils/generators'; import { randomName } from '../random'; diff --git a/packages/cli/test/integration/shared/db/users.ts b/packages/cli/test/integration/shared/db/users.ts index 34e637b34f..27140b526d 100644 --- a/packages/cli/test/integration/shared/db/users.ts +++ b/packages/cli/test/integration/shared/db/users.ts @@ -3,7 +3,8 @@ import { hash } from 'bcryptjs'; import { AuthIdentity } from '@db/entities/AuthIdentity'; import type { Role } from '@db/entities/Role'; import type { User } from '@db/entities/User'; -import { AuthIdentityRepository, UserRepository } from '@db/repositories'; +import { AuthIdentityRepository } from '@db/repositories/authIdentity.repository'; +import { UserRepository } from '@db/repositories/user.repository'; import { TOTPService } from '@/Mfa/totp.service'; import { MfaService } from '@/Mfa/mfa.service'; diff --git a/packages/cli/test/integration/shared/db/workflowHistory.ts b/packages/cli/test/integration/shared/db/workflowHistory.ts index f9589c6469..8233d80077 100644 --- a/packages/cli/test/integration/shared/db/workflowHistory.ts +++ b/packages/cli/test/integration/shared/db/workflowHistory.ts @@ -1,7 +1,7 @@ import Container from 'typedi'; import { v4 as uuid } from 'uuid'; import type { WorkflowHistory } from '@db/entities/WorkflowHistory'; -import { WorkflowHistoryRepository } from '@db/repositories'; +import { WorkflowHistoryRepository } from '@db/repositories/workflowHistory.repository'; export async function createWorkflowHistoryItem( workflowId: string, diff --git a/packages/cli/test/integration/shared/db/workflows.ts b/packages/cli/test/integration/shared/db/workflows.ts index 285c5e94f7..c60f5350cd 100644 --- a/packages/cli/test/integration/shared/db/workflows.ts +++ b/packages/cli/test/integration/shared/db/workflows.ts @@ -2,7 +2,8 @@ import Container from 'typedi'; import { v4 as uuid } from 'uuid'; import type { User } from '@db/entities/User'; import type { WorkflowEntity } from '@db/entities/WorkflowEntity'; -import { SharedWorkflowRepository, WorkflowRepository } from '@db/repositories'; +import { SharedWorkflowRepository } from '@db/repositories/sharedWorkflow.repository'; +import { WorkflowRepository } from '@db/repositories/workflow.repository'; import { getWorkflowEditorRole, getWorkflowOwnerRole } from './roles'; export async function createManyWorkflows( diff --git a/packages/cli/test/integration/shared/testDb.ts b/packages/cli/test/integration/shared/testDb.ts index 3704108695..065652cc4d 100644 --- a/packages/cli/test/integration/shared/testDb.ts +++ b/packages/cli/test/integration/shared/testDb.ts @@ -8,12 +8,10 @@ import { entities } from '@db/entities'; import { mysqlMigrations } from '@db/migrations/mysqldb'; import { postgresMigrations } from '@db/migrations/postgresdb'; import { sqliteMigrations } from '@db/migrations/sqlite'; -import { TagRepository, WorkflowTagMappingRepository } from '@/databases/repositories'; import { DB_INITIALIZATION_TIMEOUT } from './constants'; import { randomString } from './random'; -import type { CollectionName, PostgresSchemaSection } from './types'; -import { separate } from '@/utils'; +import type { PostgresSchemaSection } from './types'; export type TestDBType = 'postgres' | 'mysql'; @@ -88,23 +86,40 @@ export async function terminate() { await Db.close(); } +// Can't use `Object.keys(entities)` here because some entities have a `Entity` suffix, while the repositories don't +const repositories = [ + 'AuthIdentity', + 'AuthProviderSyncHistory', + 'Credentials', + 'EventDestinations', + 'ExecutionData', + 'ExecutionMetadata', + 'Execution', + 'InstalledNodes', + 'InstalledPackages', + 'Role', + 'Settings', + 'SharedCredentials', + 'SharedWorkflow', + 'Tag', + 'User', + 'Variables', + 'Webhook', + 'Workflow', + 'WorkflowHistory', + 'WorkflowStatistics', + 'WorkflowTagMapping', +] as const; + /** * Truncate specific DB tables in a test DB. */ -export async function truncate(collections: CollectionName[]) { - const [tag, rest] = separate(collections, (c) => c === 'Tag'); - - if (tag.length) { - await Container.get(TagRepository).delete({}); - await Container.get(WorkflowTagMappingRepository).delete({}); - } - - for (const collection of rest) { - if (typeof collection === 'string') { - await Db.collections[collection].delete({}); - } else { - await Container.get(collection as { new (): Repository }).delete({}); - } +export async function truncate(names: Array<(typeof repositories)[number]>) { + for (const name of names) { + const RepositoryClass: { new (): Repository } = ( + await import(`@db/repositories/${name.charAt(0).toLowerCase() + name.slice(1)}.repository`) + )[`${name}Repository`]; + await Container.get(RepositoryClass).delete({}); } } diff --git a/packages/cli/test/integration/shared/types.ts b/packages/cli/test/integration/shared/types.ts index 54c23b5dee..0021cfc99c 100644 --- a/packages/cli/test/integration/shared/types.ts +++ b/packages/cli/test/integration/shared/types.ts @@ -5,12 +5,7 @@ import type { Server } from 'http'; import type { CredentialsEntity } from '@db/entities/CredentialsEntity'; import type { User } from '@db/entities/User'; -import type { BooleanLicenseFeature, ICredentialsDb, IDatabaseCollections } from '@/Interfaces'; -import type { DataSource, Repository } from 'typeorm'; - -export type CollectionName = - | keyof IDatabaseCollections - | { new (dataSource: DataSource): Repository }; +import type { BooleanLicenseFeature, ICredentialsDb } from '@/Interfaces'; type EndpointGroup = | 'me' diff --git a/packages/cli/test/integration/shared/utils/communityNodes.ts b/packages/cli/test/integration/shared/utils/communityNodes.ts index c5cf10591f..1587313c51 100644 --- a/packages/cli/test/integration/shared/utils/communityNodes.ts +++ b/packages/cli/test/integration/shared/utils/communityNodes.ts @@ -3,7 +3,8 @@ import { InstalledPackages } from '@db/entities/InstalledPackages'; import { randomName } from '../random'; import { COMMUNITY_NODE_VERSION, COMMUNITY_PACKAGE_VERSION } from '../constants'; -import { InstalledNodesRepository, InstalledPackagesRepository } from '@/databases/repositories'; +import { InstalledNodesRepository } from '@db/repositories/installedNodes.repository'; +import { InstalledPackagesRepository } from '@db/repositories/installedPackages.repository'; import Container from 'typedi'; export const mockPackageName = () => NODE_PACKAGE_PREFIX + randomName(); diff --git a/packages/cli/test/integration/shared/utils/index.ts b/packages/cli/test/integration/shared/utils/index.ts index 280a8bc02b..47a10fabc2 100644 --- a/packages/cli/test/integration/shared/utils/index.ts +++ b/packages/cli/test/integration/shared/utils/index.ts @@ -10,15 +10,14 @@ import type request from 'supertest'; import { v4 as uuid } from 'uuid'; import config from '@/config'; -import * as Db from '@/Db'; import { WorkflowEntity } from '@db/entities/WorkflowEntity'; import { AUTH_COOKIE_NAME } from '@/constants'; import { LoadNodesAndCredentials } from '@/LoadNodesAndCredentials'; -import { mockInstance } from './mocking'; +import { SettingsRepository } from '@db/repositories/settings.repository'; import { mockNodeTypesData } from '../../../unit/Helpers'; +import { mockInstance } from '../../../shared/mocking'; -export { mockInstance } from './mocking'; export { setupTestServer } from './testServer'; // ---------------------------------- @@ -108,7 +107,7 @@ export function getAuthToken(response: request.Response, authCookieName = AUTH_C // ---------------------------------- export async function isInstanceOwnerSetUp() { - const { value } = await Db.collections.Settings.findOneByOrFail({ + const { value } = await Container.get(SettingsRepository).findOneByOrFail({ key: 'userManagement.isInstanceOwnerSetUp', }); @@ -118,7 +117,7 @@ export async function isInstanceOwnerSetUp() { export const setInstanceOwnerSetUp = async (value: boolean) => { config.set('userManagement.isInstanceOwnerSetUp', value); - await Db.collections.Settings.update( + await Container.get(SettingsRepository).update( { key: 'userManagement.isInstanceOwnerSetUp' }, { value: JSON.stringify(value) }, ); diff --git a/packages/cli/test/integration/shared/utils/testServer.ts b/packages/cli/test/integration/shared/utils/testServer.ts index 11c32c2512..15dba72c0e 100644 --- a/packages/cli/test/integration/shared/utils/testServer.ts +++ b/packages/cli/test/integration/shared/utils/testServer.ts @@ -14,18 +14,12 @@ import { rawBodyReader, bodyParser, setupAuthMiddlewares } from '@/middlewares'; import { InternalHooks } from '@/InternalHooks'; import { PostHogClient } from '@/posthog'; import { License } from '@/License'; - -import { - SettingsRepository, - SharedCredentialsRepository, - SharedWorkflowRepository, -} from '@/databases/repositories'; import { Logger } from '@/Logger'; +import { mockInstance } from '../../../shared/mocking'; import * as testDb from '../../shared/testDb'; import { AUTHLESS_ENDPOINTS, PUBLIC_API_REST_PATH_SEGMENT, REST_PATH_SEGMENT } from '../constants'; import type { SetupProps, TestServer } from '../types'; -import { mockInstance } from './mocking'; /** * Plugin to prefix a path segment into a request URL pathname. @@ -217,6 +211,7 @@ export const setupTestServer = ({ case 'owner': const { UserService } = await import('@/services/user.service'); + const { SettingsRepository } = await import('@db/repositories/settings.repository'); const { OwnerController } = await import('@/controllers/owner.controller'); registerController( app, @@ -232,6 +227,12 @@ export const setupTestServer = ({ break; case 'users': + const { SharedCredentialsRepository } = await import( + '@db/repositories/sharedCredentials.repository' + ); + const { SharedWorkflowRepository } = await import( + '@db/repositories/sharedWorkflow.repository' + ); const { ActiveWorkflowRunner } = await import('@/ActiveWorkflowRunner'); const { ExternalHooks } = await import('@/ExternalHooks'); const { JwtService } = await import('@/services/jwt.service'); diff --git a/packages/cli/test/integration/tags.api.test.ts b/packages/cli/test/integration/tags.api.test.ts index b929c55f45..bc44fdf00d 100644 --- a/packages/cli/test/integration/tags.api.test.ts +++ b/packages/cli/test/integration/tags.api.test.ts @@ -1,7 +1,7 @@ import * as utils from './shared/utils/'; import * as testDb from './shared/testDb'; import type { SuperAgentTest } from 'supertest'; -import { TagRepository } from '@/databases/repositories'; +import { TagRepository } from '@db/repositories/tag.repository'; import Container from 'typedi'; import { getGlobalOwnerRole } from './shared/db/roles'; import { createUserShell } from './shared/db/users'; diff --git a/packages/cli/test/integration/users.api.test.ts b/packages/cli/test/integration/users.api.test.ts index 0ce7d5a8e2..6c31b58db9 100644 --- a/packages/cli/test/integration/users.api.test.ts +++ b/packages/cli/test/integration/users.api.test.ts @@ -2,7 +2,6 @@ import validator from 'validator'; import { Not } from 'typeorm'; import type { SuperAgentTest } from 'supertest'; -import * as Db from '@/Db'; import { CredentialsEntity } from '@db/entities/CredentialsEntity'; import type { Role } from '@db/entities/Role'; import type { User } from '@db/entities/User'; @@ -10,6 +9,14 @@ import { WorkflowEntity } from '@db/entities/WorkflowEntity'; import { compareHash } from '@/UserManagement/UserManagementHelper'; import { UserManagementMailer } from '@/UserManagement/email/UserManagementMailer'; +import Container from 'typedi'; +import { UserRepository } from '@db/repositories/user.repository'; +import { WorkflowRepository } from '@db/repositories/workflow.repository'; +import { CredentialsRepository } from '@db/repositories/credentials.repository'; +import { SharedCredentialsRepository } from '@db/repositories/sharedCredentials.repository'; +import { SharedWorkflowRepository } from '@db/repositories/sharedWorkflow.repository'; + +import { mockInstance } from '../shared/mocking'; import { SUCCESS_RESPONSE_BODY } from './shared/constants'; import { randomCredentialPayload, @@ -31,7 +38,7 @@ let credentialOwnerRole: Role; let owner: User; let authOwnerAgent: SuperAgentTest; -const mailer = utils.mockInstance(UserManagementMailer, { isEmailSetUp: true }); +const mailer = mockInstance(UserManagementMailer, { isEmailSetUp: true }); const testServer = utils.setupTestServer({ endpointGroups: ['users'] }); @@ -54,7 +61,7 @@ beforeAll(async () => { beforeEach(async () => { await testDb.truncate(['SharedCredentials', 'SharedWorkflow', 'Workflow', 'Credentials']); - await Db.collections.User.delete({ id: Not(owner.id) }); + await Container.get(UserRepository).delete({ id: Not(owner.id) }); mailer.invite.mockResolvedValue({ emailSent: true }); }); @@ -72,9 +79,9 @@ describe('DELETE /users/:id', () => { nodes: [], }); - const savedWorkflow = await Db.collections.Workflow.save(newWorkflow); + const savedWorkflow = await Container.get(WorkflowRepository).save(newWorkflow); - await Db.collections.SharedWorkflow.save({ + await Container.get(SharedWorkflowRepository).save({ role: workflowOwnerRole, user: userToDelete, workflow: savedWorkflow, @@ -89,9 +96,9 @@ describe('DELETE /users/:id', () => { nodesAccess: [], }); - const savedCredential = await Db.collections.Credentials.save(newCredential); + const savedCredential = await Container.get(CredentialsRepository).save(newCredential); - await Db.collections.SharedCredentials.save({ + await Container.get(SharedCredentialsRepository).save({ role: credentialOwnerRole, user: userToDelete, credentials: savedCredential, @@ -102,27 +109,29 @@ describe('DELETE /users/:id', () => { expect(response.statusCode).toBe(200); expect(response.body).toEqual(SUCCESS_RESPONSE_BODY); - const user = await Db.collections.User.findOneBy({ id: userToDelete.id }); + const user = await Container.get(UserRepository).findOneBy({ id: userToDelete.id }); expect(user).toBeNull(); // deleted - const sharedWorkflow = await Db.collections.SharedWorkflow.findOne({ + const sharedWorkflow = await Container.get(SharedWorkflowRepository).findOne({ relations: ['user'], where: { userId: userToDelete.id, roleId: workflowOwnerRole.id }, }); expect(sharedWorkflow).toBeNull(); // deleted - const sharedCredential = await Db.collections.SharedCredentials.findOne({ + const sharedCredential = await Container.get(SharedCredentialsRepository).findOne({ relations: ['user'], where: { userId: userToDelete.id, roleId: credentialOwnerRole.id }, }); expect(sharedCredential).toBeNull(); // deleted - const workflow = await Db.collections.Workflow.findOneBy({ id: savedWorkflow.id }); + const workflow = await Container.get(WorkflowRepository).findOneBy({ id: savedWorkflow.id }); expect(workflow).toBeNull(); // deleted // TODO: Include active workflow and check whether webhook has been removed - const credential = await Db.collections.Credentials.findOneBy({ id: savedCredential.id }); + const credential = await Container.get(CredentialsRepository).findOneBy({ + id: savedCredential.id, + }); expect(credential).toBeNull(); // deleted }); @@ -131,7 +140,7 @@ describe('DELETE /users/:id', () => { expect(response.statusCode).toBe(400); - const user = await Db.collections.User.findOneBy({ id: owner.id }); + const user = await Container.get(UserRepository).findOneBy({ id: owner.id }); expect(user).toBeDefined(); }); @@ -144,7 +153,7 @@ describe('DELETE /users/:id', () => { expect(response.statusCode).toBe(400); - const user = await Db.collections.User.findOneBy({ id: idToDelete }); + const user = await Container.get(UserRepository).findOneBy({ id: idToDelete }); expect(user).toBeDefined(); }); @@ -164,7 +173,7 @@ describe('DELETE /users/:id', () => { expect(response.statusCode).toBe(200); - const sharedWorkflow = await Db.collections.SharedWorkflow.findOneOrFail({ + const sharedWorkflow = await Container.get(SharedWorkflowRepository).findOneOrFail({ relations: ['workflow'], where: { userId: owner.id }, }); @@ -172,7 +181,7 @@ describe('DELETE /users/:id', () => { expect(sharedWorkflow.workflow).toBeDefined(); expect(sharedWorkflow.workflow.id).toBe(savedWorkflow.id); - const sharedCredential = await Db.collections.SharedCredentials.findOneOrFail({ + const sharedCredential = await Container.get(SharedCredentialsRepository).findOneOrFail({ relations: ['credentials'], where: { userId: owner.id }, }); @@ -180,7 +189,7 @@ describe('DELETE /users/:id', () => { expect(sharedCredential.credentials).toBeDefined(); expect(sharedCredential.credentials.id).toBe(savedCredential.id); - const deletedUser = await Db.collections.User.findOneBy({ id: userToDelete.id }); + const deletedUser = await Container.get(UserRepository).findOneBy({ id: userToDelete.id }); expect(deletedUser).toBeNull(); }); @@ -226,7 +235,7 @@ describe('POST /users/:id', () => { const authToken = utils.getAuthToken(response); expect(authToken).toBeDefined(); - const member = await Db.collections.User.findOneByOrFail({ id: memberShell.id }); + const member = await Container.get(UserRepository).findOneByOrFail({ id: memberShell.id }); expect(member.firstName).toBe(memberData.firstName); expect(member.lastName).toBe(memberData.lastName); expect(member.password).not.toBe(memberData.password); @@ -235,7 +244,7 @@ describe('POST /users/:id', () => { test('should fail with invalid inputs', async () => { const memberShellEmail = randomEmail(); - const memberShell = await Db.collections.User.save({ + const memberShell = await Container.get(UserRepository).save({ email: memberShellEmail, globalRole: globalMemberRole, }); @@ -275,7 +284,7 @@ describe('POST /users/:id', () => { .send(invalidPayload); expect(response.statusCode).toBe(400); - const storedUser = await Db.collections.User.findOneOrFail({ + const storedUser = await Container.get(UserRepository).findOneOrFail({ where: { email: memberShellEmail }, }); @@ -299,7 +308,7 @@ describe('POST /users/:id', () => { expect(response.statusCode).toBe(400); - const storedMember = await Db.collections.User.findOneOrFail({ + const storedMember = await Container.get(UserRepository).findOneOrFail({ where: { email: member.email }, }); expect(storedMember.firstName).not.toBe(newMemberData.firstName); @@ -353,7 +362,7 @@ describe('POST /users', () => { expect(error).toBe('Email could not be sent'); } - const storedUser = await Db.collections.User.findOneByOrFail({ id }); + const storedUser = await Container.get(UserRepository).findOneByOrFail({ id }); const { firstName, lastName, personalizationAnswers, password } = storedUser; expect(firstName).toBeNull(); @@ -377,7 +386,7 @@ describe('POST /users', () => { const response = await authOwnerAgent.post('/users').send(invalidPayload); expect(response.statusCode).toBe(400); - const users = await Db.collections.User.find(); + const users = await Container.get(UserRepository).find(); expect(users.length).toBe(1); // DB unaffected }), ); @@ -392,7 +401,7 @@ describe('POST /users', () => { expect(Array.isArray(data)).toBe(true); expect(data.length).toBe(0); - const users = await Db.collections.User.find(); + const users = await Container.get(UserRepository).find(); expect(users.length).toBe(1); }); }); diff --git a/packages/cli/test/integration/users.controller.test.ts b/packages/cli/test/integration/users.controller.test.ts index 8af36533a6..191e398064 100644 --- a/packages/cli/test/integration/users.controller.test.ts +++ b/packages/cli/test/integration/users.controller.test.ts @@ -1,7 +1,7 @@ import { createMember, createOwner } from './shared/db/users'; import * as testDb from './shared/testDb'; import { setupTestServer } from './shared/utils/'; -import type { User } from '@/databases/entities/User'; +import type { User } from '@db/entities/User'; import type { PublicUser } from '@/Interfaces'; const { any } = expect; diff --git a/packages/cli/test/integration/variables.test.ts b/packages/cli/test/integration/variables.test.ts index da1611c275..373e451654 100644 --- a/packages/cli/test/integration/variables.test.ts +++ b/packages/cli/test/integration/variables.test.ts @@ -1,10 +1,12 @@ import Container from 'typedi'; import type { SuperAgentTest } from 'supertest'; import type { Variables } from '@db/entities/Variables'; -import { VariablesRepository } from '@db/repositories'; +import { VariablesRepository } from '@db/repositories/variables.repository'; import { generateNanoId } from '@db/utils/generators'; import { License } from '@/License'; import { VariablesService } from '@/environments/variables/variables.service'; + +import { mockInstance } from '../shared/mocking'; import * as testDb from './shared/testDb'; import * as utils from './shared/utils/'; import { createOwner, createUser } from './shared/db/users'; @@ -47,7 +49,7 @@ async function getVariableById(id: string) { } beforeAll(async () => { - utils.mockInstance(License, licenseLike); + mockInstance(License, licenseLike); const owner = await createOwner(); authOwnerAgent = testServer.authAgentFor(owner); diff --git a/packages/cli/test/integration/webhooks.api.test.ts b/packages/cli/test/integration/webhooks.api.test.ts index b352bf395b..37862be6aa 100644 --- a/packages/cli/test/integration/webhooks.api.test.ts +++ b/packages/cli/test/integration/webhooks.api.test.ts @@ -10,7 +10,8 @@ import { NodeTypes } from '@/NodeTypes'; import { Push } from '@/push'; import type { WorkflowEntity } from '@db/entities/WorkflowEntity'; -import { mockInstance, initActiveWorkflowRunner } from './shared/utils'; +import { mockInstance } from '../shared/mocking'; +import { initActiveWorkflowRunner } from './shared/utils'; import * as testDb from './shared/testDb'; import { createUser } from './shared/db/users'; import { createWorkflow } from './shared/db/workflows'; diff --git a/packages/cli/test/integration/workflowHistory.api.test.ts b/packages/cli/test/integration/workflowHistory.api.test.ts index dab1076854..dbff04c2ea 100644 --- a/packages/cli/test/integration/workflowHistory.api.test.ts +++ b/packages/cli/test/integration/workflowHistory.api.test.ts @@ -1,9 +1,10 @@ import type { SuperAgentTest } from 'supertest'; import { License } from '@/License'; +import type { User } from '@db/entities/User'; + +import { mockInstance } from '../shared/mocking'; import * as testDb from './shared/testDb'; import * as utils from './shared/utils/'; -import type { User } from '@/databases/entities/User'; -import { WorkflowHistoryRepository } from '@/databases/repositories'; import { createOwner, createUser } from './shared/db/users'; import { createWorkflow } from './shared/db/workflows'; import { createWorkflowHistoryItem } from './shared/db/workflowHistory'; @@ -13,7 +14,7 @@ let authOwnerAgent: SuperAgentTest; let member: User; let authMemberAgent: SuperAgentTest; -const licenseLike = utils.mockInstance(License, { +const licenseLike = mockInstance(License, { isWorkflowHistoryLicensed: jest.fn().mockReturnValue(true), isWithinUsersLimit: jest.fn().mockReturnValue(true), }); @@ -32,7 +33,7 @@ beforeEach(() => { }); afterEach(async () => { - await testDb.truncate(['Workflow', 'SharedWorkflow', WorkflowHistoryRepository]); + await testDb.truncate(['Workflow', 'SharedWorkflow', 'WorkflowHistory']); }); describe('GET /workflow-history/:workflowId', () => { diff --git a/packages/cli/test/integration/workflowHistoryManager.test.ts b/packages/cli/test/integration/workflowHistoryManager.test.ts index 497e5919fe..fe8690efce 100644 --- a/packages/cli/test/integration/workflowHistoryManager.test.ts +++ b/packages/cli/test/integration/workflowHistoryManager.test.ts @@ -3,12 +3,12 @@ import { In } from 'typeorm'; import { DateTime } from 'luxon'; import config from '@/config'; -import { WorkflowHistoryRepository } from '@/databases/repositories'; +import { WorkflowHistoryRepository } from '@db/repositories/workflowHistory.repository'; import { License } from '@/License'; import { WorkflowHistoryManager } from '@/workflows/workflowHistory/workflowHistoryManager.ee'; +import { mockInstance } from '../shared/mocking'; import * as testDb from './shared/testDb'; -import { mockInstance } from './shared/utils'; import { createWorkflow } from './shared/db/workflows'; import { createManyWorkflowHistoryItems } from './shared/db/workflowHistory'; diff --git a/packages/cli/test/integration/workflows.controller.ee.test.ts b/packages/cli/test/integration/workflows.controller.ee.test.ts index 21e13885f2..0687f4b865 100644 --- a/packages/cli/test/integration/workflows.controller.ee.test.ts +++ b/packages/cli/test/integration/workflows.controller.ee.test.ts @@ -7,9 +7,10 @@ import * as UserManagementHelpers from '@/UserManagement/UserManagementHelper'; import type { User } from '@db/entities/User'; import { getSharedWorkflowIds } from '@/WorkflowHelpers'; import { License } from '@/License'; -import { WorkflowHistoryRepository } from '@/databases/repositories'; +import { WorkflowHistoryRepository } from '@db/repositories/workflowHistory.repository'; import { ActiveWorkflowRunner } from '@/ActiveWorkflowRunner'; +import { mockInstance } from '../shared/mocking'; import * as utils from './shared/utils/'; import * as testDb from './shared/testDb'; import type { SaveCredentialFunction } from './shared/types'; @@ -28,11 +29,11 @@ let authMemberAgent: SuperAgentTest; let authAnotherMemberAgent: SuperAgentTest; let saveCredential: SaveCredentialFunction; -const licenseLike = utils.mockInstance(License, { +const licenseLike = mockInstance(License, { isWorkflowHistoryLicensed: jest.fn().mockReturnValue(false), isWithinUsersLimit: jest.fn().mockReturnValue(true), }); -const activeWorkflowRunnerLike = utils.mockInstance(ActiveWorkflowRunner); +const activeWorkflowRunnerLike = mockInstance(ActiveWorkflowRunner); const sharingSpy = jest.spyOn(UserManagementHelpers, 'isSharingEnabled').mockReturnValue(true); const testServer = utils.setupTestServer({ @@ -62,7 +63,7 @@ beforeEach(async () => { activeWorkflowRunnerLike.add.mockReset(); activeWorkflowRunnerLike.remove.mockReset(); - await testDb.truncate(['Workflow', 'SharedWorkflow', WorkflowHistoryRepository]); + await testDb.truncate(['Workflow', 'SharedWorkflow', 'WorkflowHistory']); licenseLike.isWorkflowHistoryLicensed.mockReturnValue(false); }); diff --git a/packages/cli/test/integration/workflows.controller.test.ts b/packages/cli/test/integration/workflows.controller.test.ts index f8126a4480..0e6a39786e 100644 --- a/packages/cli/test/integration/workflows.controller.test.ts +++ b/packages/cli/test/integration/workflows.controller.test.ts @@ -1,15 +1,16 @@ import type { SuperAgentTest } from 'supertest'; import type { INode, IPinData } from 'n8n-workflow'; import * as UserManagementHelpers from '@/UserManagement/UserManagementHelper'; -import type { User } from '@/databases/entities/User'; +import type { User } from '@db/entities/User'; import { v4 as uuid } from 'uuid'; import { RoleService } from '@/services/role.service'; import Container from 'typedi'; import type { ListQuery } from '@/requests'; import { License } from '@/License'; -import { WorkflowHistoryRepository } from '@/databases/repositories'; +import { WorkflowHistoryRepository } from '@db/repositories/workflowHistory.repository'; import { ActiveWorkflowRunner } from '@/ActiveWorkflowRunner'; +import { mockInstance } from '../shared/mocking'; import * as utils from './shared/utils/'; import * as testDb from './shared/testDb'; import { makeWorkflow, MOCK_PINDATA } from './shared/utils/'; @@ -27,12 +28,12 @@ const testServer = utils.setupTestServer({ endpointGroups: ['workflows'] }); const { objectContaining, arrayContaining, any } = expect; -const licenseLike = utils.mockInstance(License, { +const licenseLike = mockInstance(License, { isWorkflowHistoryLicensed: jest.fn().mockReturnValue(false), isWithinUsersLimit: jest.fn().mockReturnValue(true), }); -const activeWorkflowRunnerLike = utils.mockInstance(ActiveWorkflowRunner); +const activeWorkflowRunnerLike = mockInstance(ActiveWorkflowRunner); beforeAll(async () => { owner = await createOwner(); @@ -41,7 +42,7 @@ beforeAll(async () => { beforeEach(async () => { jest.resetAllMocks(); - await testDb.truncate(['Workflow', 'SharedWorkflow', 'Tag', WorkflowHistoryRepository]); + await testDb.truncate(['Workflow', 'SharedWorkflow', 'Tag', 'WorkflowHistory']); licenseLike.isWorkflowHistoryLicensed.mockReturnValue(false); }); diff --git a/packages/cli/test/integration/shared/utils/mocking.ts b/packages/cli/test/shared/mocking.ts similarity index 100% rename from packages/cli/test/integration/shared/utils/mocking.ts rename to packages/cli/test/shared/mocking.ts diff --git a/packages/cli/test/unit/ActiveExecutions.test.ts b/packages/cli/test/unit/ActiveExecutions.test.ts index 485d1cd13e..689bbbefab 100644 --- a/packages/cli/test/unit/ActiveExecutions.test.ts +++ b/packages/cli/test/unit/ActiveExecutions.test.ts @@ -5,7 +5,7 @@ import { Container } from 'typedi'; import type { IExecuteResponsePromiseData, IRun } from 'n8n-workflow'; import { createDeferredPromise } from 'n8n-workflow'; import type { IWorkflowExecutionDataProcess } from '@/Interfaces'; -import { ExecutionRepository } from '@db/repositories'; +import { ExecutionRepository } from '@db/repositories/execution.repository'; import { mock } from 'jest-mock-extended'; const FAKE_EXECUTION_ID = '15'; diff --git a/packages/cli/test/unit/CredentialTypes.test.ts b/packages/cli/test/unit/CredentialTypes.test.ts index 731e1b2bac..0ee99c9f8a 100644 --- a/packages/cli/test/unit/CredentialTypes.test.ts +++ b/packages/cli/test/unit/CredentialTypes.test.ts @@ -1,7 +1,7 @@ import { CredentialTypes } from '@/CredentialTypes'; import { Container } from 'typedi'; import { LoadNodesAndCredentials } from '@/LoadNodesAndCredentials'; -import { mockInstance } from '../integration/shared/utils'; +import { mockInstance } from '../shared/mocking'; describe('CredentialTypes', () => { const mockNodesAndCredentials = mockInstance(LoadNodesAndCredentials, { diff --git a/packages/cli/test/unit/CredentialsHelper.test.ts b/packages/cli/test/unit/CredentialsHelper.test.ts index 5556fb67b7..648fa28918 100644 --- a/packages/cli/test/unit/CredentialsHelper.test.ts +++ b/packages/cli/test/unit/CredentialsHelper.test.ts @@ -1,3 +1,4 @@ +import Container from 'typedi'; import type { IAuthenticateGeneric, ICredentialDataDecryptedObject, @@ -11,10 +12,13 @@ import { Workflow } from 'n8n-workflow'; import { CredentialsHelper } from '@/CredentialsHelper'; import { NodeTypes } from '@/NodeTypes'; import { LoadNodesAndCredentials } from '@/LoadNodesAndCredentials'; -import { mockInstance } from '../integration/shared/utils'; -import Container from 'typedi'; +import { CredentialsRepository } from '@db/repositories/credentials.repository'; +import { SharedCredentialsRepository } from '@db/repositories/sharedCredentials.repository'; +import { mockInstance } from '../shared/mocking'; describe('CredentialsHelper', () => { + mockInstance(CredentialsRepository); + mockInstance(SharedCredentialsRepository); const mockNodesAndCredentials = mockInstance(LoadNodesAndCredentials, { loadedNodes: { 'test.set': { diff --git a/packages/cli/test/unit/ExternalSecrets/ExternalSecretsManager.test.ts b/packages/cli/test/unit/ExternalSecrets/ExternalSecretsManager.test.ts index acb6e7a4cb..b8a728d5f5 100644 --- a/packages/cli/test/unit/ExternalSecrets/ExternalSecretsManager.test.ts +++ b/packages/cli/test/unit/ExternalSecrets/ExternalSecretsManager.test.ts @@ -1,12 +1,12 @@ import { Container } from 'typedi'; import { Cipher } from 'n8n-core'; -import { SettingsRepository } from '@/databases/repositories'; +import { SettingsRepository } from '@db/repositories/settings.repository'; import type { ExternalSecretsSettings } from '@/Interfaces'; import { License } from '@/License'; import { ExternalSecretsManager } from '@/ExternalSecrets/ExternalSecretsManager.ee'; import { ExternalSecretsProviders } from '@/ExternalSecrets/ExternalSecretsProviders.ee'; import { InternalHooks } from '@/InternalHooks'; -import { mockInstance } from '../../integration/shared/utils'; +import { mockInstance } from '../../shared/mocking'; import { DummyProvider, ErrorProvider, diff --git a/packages/cli/test/unit/InternalHooks.test.ts b/packages/cli/test/unit/InternalHooks.test.ts index dea011723b..8d33fd4672 100644 --- a/packages/cli/test/unit/InternalHooks.test.ts +++ b/packages/cli/test/unit/InternalHooks.test.ts @@ -1,6 +1,6 @@ import { Telemetry } from '@/telemetry'; import { InternalHooks } from '@/InternalHooks'; -import { mockInstance } from '../integration/shared/utils'; +import { mockInstance } from '../shared/mocking'; import type { IDiagnosticInfo } from '@/Interfaces'; import { mock } from 'jest-mock-extended'; diff --git a/packages/cli/test/unit/License.test.ts b/packages/cli/test/unit/License.test.ts index 356fb07685..e2b5551ff5 100644 --- a/packages/cli/test/unit/License.test.ts +++ b/packages/cli/test/unit/License.test.ts @@ -1,10 +1,11 @@ import { LicenseManager } from '@n8n_io/license-sdk'; import { InstanceSettings } from 'n8n-core'; +import { mock } from 'jest-mock-extended'; import config from '@/config'; import { License } from '@/License'; import { Logger } from '@/Logger'; import { N8N_VERSION } from '@/constants'; -import { mockInstance } from '../integration/shared/utils'; +import { mockInstance } from '../shared/mocking'; jest.mock('@n8n_io/license-sdk'); @@ -28,7 +29,7 @@ describe('License', () => { const instanceSettings = mockInstance(InstanceSettings, { instanceId: MOCK_INSTANCE_ID }); beforeEach(async () => { - license = new License(logger, instanceSettings); + license = new License(logger, instanceSettings, mock(), mock()); await license.init(); }); @@ -51,7 +52,7 @@ describe('License', () => { }); test('initializes license manager for worker', async () => { - license = new License(logger, instanceSettings); + license = new License(logger, instanceSettings, mock(), mock()); await license.init('worker'); expect(LicenseManager).toHaveBeenCalledWith({ autoRenewEnabled: false, diff --git a/packages/cli/test/unit/PermissionChecker.test.ts b/packages/cli/test/unit/PermissionChecker.test.ts index 8784c1a517..df596a3058 100644 --- a/packages/cli/test/unit/PermissionChecker.test.ts +++ b/packages/cli/test/unit/PermissionChecker.test.ts @@ -4,7 +4,6 @@ import type { INodeTypes } from 'n8n-workflow'; import { SubworkflowOperationError, Workflow } from 'n8n-workflow'; import config from '@/config'; -import * as Db from '@/Db'; import { Role } from '@db/entities/Role'; import { User } from '@db/entities/User'; import { SharedWorkflow } from '@db/entities/SharedWorkflow'; @@ -14,7 +13,7 @@ import { PermissionChecker } from '@/UserManagement/PermissionChecker'; import * as UserManagementHelper from '@/UserManagement/UserManagementHelper'; import { OwnershipService } from '@/services/ownership.service'; -import { mockInstance } from '../integration/shared/utils/'; +import { mockInstance } from '../shared/mocking'; import { randomCredentialPayload as randomCred, randomPositiveDigit, @@ -25,6 +24,8 @@ import { mockNodeTypesData } from './Helpers'; import { affixRoleToSaveCredential } from '../integration/shared/db/credentials'; import { getCredentialOwnerRole, getWorkflowOwnerRole } from '../integration/shared/db/roles'; import { createOwner, createUser } from '../integration/shared/db/users'; +import { WorkflowRepository } from '@db/repositories/workflow.repository'; +import { SharedWorkflowRepository } from '@db/repositories/sharedWorkflow.repository'; let mockNodeTypes: INodeTypes; let credentialOwnerRole: Role; @@ -199,9 +200,9 @@ describe('PermissionChecker.check()', () => { ], }; - const workflowEntity = await Db.collections.Workflow.save(workflowDetails); + const workflowEntity = await Container.get(WorkflowRepository).save(workflowDetails); - await Db.collections.SharedWorkflow.save({ + await Container.get(SharedWorkflowRepository).save({ workflow: workflowEntity, user: member, role: workflowOwnerRole, diff --git a/packages/cli/test/unit/PostHog.test.ts b/packages/cli/test/unit/PostHog.test.ts index 6c53b44891..5798c0cce2 100644 --- a/packages/cli/test/unit/PostHog.test.ts +++ b/packages/cli/test/unit/PostHog.test.ts @@ -2,7 +2,7 @@ import { PostHog } from 'posthog-node'; import { InstanceSettings } from 'n8n-core'; import { PostHogClient } from '@/posthog'; import config from '@/config'; -import { mockInstance } from '../integration/shared/utils'; +import { mockInstance } from '../shared/mocking'; jest.mock('posthog-node'); diff --git a/packages/cli/test/unit/SourceControl.test.ts b/packages/cli/test/unit/SourceControl.test.ts index 48f055ed21..4d0d786532 100644 --- a/packages/cli/test/unit/SourceControl.test.ts +++ b/packages/cli/test/unit/SourceControl.test.ts @@ -18,6 +18,7 @@ import { import { constants as fsConstants, accessSync } from 'fs'; import type { SourceControlledFile } from '@/environments/sourceControl/types/sourceControlledFile'; import type { SourceControlPreferences } from '@/environments/sourceControl/types/sourceControlPreferences'; +import { mockInstance } from '../shared/mocking'; const pushResult: SourceControlledFile[] = [ { @@ -149,8 +150,11 @@ const pullResult: SourceControlledFile[] = [ }, ]; +const license = mockInstance(License); + beforeAll(async () => { - Container.get(License).isSourceControlLicensed = () => true; + jest.resetAllMocks(); + license.isSourceControlLicensed.mockReturnValue(true); Container.get(SourceControlPreferencesService).getPreferences = () => ({ branchName: 'main', connected: true, @@ -205,10 +209,6 @@ describe('Source Control', () => { expect(accessSync(gitFolder, fsConstants.F_OK)).toBeUndefined(); }); - it('should check if source control is licensed', async () => { - expect(Container.get(License).isSourceControlLicensed()).toBe(true); - }); - it('should get repo type from url', async () => { expect(getRepoType('git@github.com:n8ntest/n8n_testrepo.git')).toBe('github'); expect(getRepoType('git@gitlab.com:n8ntest/n8n_testrepo.git')).toBe('gitlab'); diff --git a/packages/cli/test/unit/Telemetry.test.ts b/packages/cli/test/unit/Telemetry.test.ts index 6899604279..129df8daeb 100644 --- a/packages/cli/test/unit/Telemetry.test.ts +++ b/packages/cli/test/unit/Telemetry.test.ts @@ -4,8 +4,8 @@ import config from '@/config'; import { flushPromises } from './Helpers'; import { PostHogClient } from '@/posthog'; import { mock } from 'jest-mock-extended'; -import { mockInstance } from '../integration/shared/utils'; import { InstanceSettings } from 'n8n-core'; +import { mockInstance } from '../shared/mocking'; jest.unmock('@/telemetry'); jest.mock('@/license/License.service', () => { diff --git a/packages/cli/test/unit/WorkflowCredentials.test.ts b/packages/cli/test/unit/WorkflowCredentials.test.ts index 5f922adfd6..6fc47cbbe0 100644 --- a/packages/cli/test/unit/WorkflowCredentials.test.ts +++ b/packages/cli/test/unit/WorkflowCredentials.test.ts @@ -1,43 +1,36 @@ -import { mocked } from 'jest-mock'; -import type { INode, IWorkflowCredentials } from 'n8n-workflow'; -import * as Db from '@/Db'; +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'; -// Define a function used to mock the findOneBy function -async function mockFind({ - id, - type, -}: { - id: string; - type: string; -}): Promise { - // 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: '', - }, - }, - }; -} +const credentialsRepository = mockInstance(CredentialsRepository); +credentialsRepository.findOneBy.mockImplementation( + async (where: FindOptionsWhere) => { + 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; + } -jest.mock('@/Db', () => { - return { - collections: { - Credentials: { - findOneBy: jest.fn(mockFind), + // 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 @@ -54,7 +47,7 @@ describe('WorkflowCredentials', () => { `Credentials with name "${credentials.name}" for type "test" miss an ID.`, ); await expect(WorkflowCredentials([noIdNode])).rejects.toEqual(expectedError); - expect(mocked(Db.collections.Credentials.findOneBy)).toHaveBeenCalledTimes(0); + expect(credentialsRepository.findOneBy).toHaveBeenCalledTimes(0); }); test('Should return an error if credentials cannot be found in the DB', async () => { @@ -63,7 +56,7 @@ describe('WorkflowCredentials', () => { `Could not find credentials for type "test" with ID "${credentials.id}".`, ); await expect(WorkflowCredentials([notFoundNode])).rejects.toEqual(expectedError); - expect(mocked(Db.collections.Credentials.findOneBy)).toHaveBeenCalledTimes(1); + expect(credentialsRepository.findOneBy).toHaveBeenCalledTimes(1); }); test('Should ignore duplicates', async () => { diff --git a/packages/cli/test/unit/WorkflowExecuteAdditionalData.test.ts b/packages/cli/test/unit/WorkflowExecuteAdditionalData.test.ts index 5d72a01f2e..c36c43455e 100644 --- a/packages/cli/test/unit/WorkflowExecuteAdditionalData.test.ts +++ b/packages/cli/test/unit/WorkflowExecuteAdditionalData.test.ts @@ -1,7 +1,7 @@ import { Container } from 'typedi'; -import { ExecutionMetadataRepository } from '@db/repositories'; +import { ExecutionMetadataRepository } from '@db/repositories/executionMetadata.repository'; import { ExecutionMetadataService } from '@/services/executionMetadata.service'; -import { mockInstance } from '../integration/shared/utils'; +import { mockInstance } from '../shared/mocking'; describe('WorkflowExecuteAdditionalData', () => { const repository = mockInstance(ExecutionMetadataRepository); diff --git a/packages/cli/test/unit/WorkflowRunner.test.ts b/packages/cli/test/unit/WorkflowRunner.test.ts index 91f8c7362f..876ae1ac1c 100644 --- a/packages/cli/test/unit/WorkflowRunner.test.ts +++ b/packages/cli/test/unit/WorkflowRunner.test.ts @@ -1,12 +1,13 @@ import type { User } from '@db/entities/User'; -import * as testDb from '../integration/shared/testDb'; -import * as utils from '../integration/shared/utils/'; import { WorkflowRunner } from '@/WorkflowRunner'; import { WorkflowHooks, type ExecutionError, type IWorkflowExecuteHooks } from 'n8n-workflow'; import { Push } from '@/push'; -import { mockInstance } from '../integration/shared/utils'; import Container from 'typedi'; import config from '@/config'; + +import { mockInstance } from '../shared/mocking'; +import * as testDb from '../integration/shared/testDb'; +import { setupTestServer } from '../integration/shared/utils'; import { getGlobalOwnerRole } from '../integration/shared/db/roles'; import { createUser } from '../integration/shared/db/users'; import { createWorkflow } from '../integration/shared/db/workflows'; @@ -15,7 +16,7 @@ import { createExecution } from '../integration/shared/db/executions'; let owner: User; let runner: WorkflowRunner; let hookFunctions: IWorkflowExecuteHooks; -utils.setupTestServer({ endpointGroups: [] }); +setupTestServer({ endpointGroups: [] }); class Watchers { workflowExecuteAfter = jest.fn(); diff --git a/packages/cli/test/unit/collaboration/collaboration.service.test.ts b/packages/cli/test/unit/collaboration/collaboration.service.test.ts index d4a4c5f335..3478d628b9 100644 --- a/packages/cli/test/unit/collaboration/collaboration.service.test.ts +++ b/packages/cli/test/unit/collaboration/collaboration.service.test.ts @@ -1,6 +1,6 @@ import { CollaborationService } from '@/collaboration/collaboration.service'; import type { Logger } from '@/Logger'; -import type { User } from '@/databases/entities/User'; +import type { User } from '@db/entities/User'; import type { UserService } from '@/services/user.service'; import { CollaborationState } from '@/collaboration/collaboration.state'; import type { Push } from '@/push'; diff --git a/packages/cli/test/unit/controllers/me.controller.test.ts b/packages/cli/test/unit/controllers/me.controller.test.ts index 5f4e8fdbba..1ea28820ff 100644 --- a/packages/cli/test/unit/controllers/me.controller.test.ts +++ b/packages/cli/test/unit/controllers/me.controller.test.ts @@ -11,13 +11,15 @@ import type { AuthenticatedRequest, MeRequest } from '@/requests'; import { UserService } from '@/services/user.service'; import { ExternalHooks } from '@/ExternalHooks'; import { InternalHooks } from '@/InternalHooks'; +import { License } from '@/License'; import { badPasswords } from '../shared/testData'; -import { mockInstance } from '../../integration/shared/utils'; +import { mockInstance } from '../../shared/mocking'; describe('MeController', () => { const externalHooks = mockInstance(ExternalHooks); const internalHooks = mockInstance(InternalHooks); const userService = mockInstance(UserService); + mockInstance(License).isWithinUsersLimit.mockReturnValue(true); const controller = Container.get(MeController); describe('updateCurrentUser', () => { diff --git a/packages/cli/test/unit/controllers/oAuth1Credential.controller.test.ts b/packages/cli/test/unit/controllers/oAuth1Credential.controller.test.ts index 92d06080a9..1fb036fe23 100644 --- a/packages/cli/test/unit/controllers/oAuth1Credential.controller.test.ts +++ b/packages/cli/test/unit/controllers/oAuth1Credential.controller.test.ts @@ -8,14 +8,15 @@ import type { CredentialsEntity } from '@db/entities/CredentialsEntity'; import type { User } from '@db/entities/User'; import type { OAuthRequest } from '@/requests'; import { BadRequestError, NotFoundError } from '@/ResponseHelper'; -import { CredentialsRepository, SharedCredentialsRepository } from '@/databases/repositories'; +import { CredentialsRepository } from '@db/repositories/credentials.repository'; +import { SharedCredentialsRepository } from '@db/repositories/sharedCredentials.repository'; import { ExternalHooks } from '@/ExternalHooks'; import { Logger } from '@/Logger'; import { VariablesService } from '@/environments/variables/variables.service'; import { SecretsHelper } from '@/SecretsHelpers'; import { CredentialsHelper } from '@/CredentialsHelper'; -import { mockInstance } from '../../integration/shared/utils'; +import { mockInstance } from '../../shared/mocking'; describe('OAuth1CredentialController', () => { mockInstance(Logger); diff --git a/packages/cli/test/unit/controllers/oAuth2Credential.controller.test.ts b/packages/cli/test/unit/controllers/oAuth2Credential.controller.test.ts index 46c7bd6d05..2824f7fd88 100644 --- a/packages/cli/test/unit/controllers/oAuth2Credential.controller.test.ts +++ b/packages/cli/test/unit/controllers/oAuth2Credential.controller.test.ts @@ -10,14 +10,15 @@ import type { CredentialsEntity } from '@db/entities/CredentialsEntity'; import type { User } from '@db/entities/User'; import type { OAuthRequest } from '@/requests'; import { BadRequestError, NotFoundError } from '@/ResponseHelper'; -import { CredentialsRepository, SharedCredentialsRepository } from '@/databases/repositories'; +import { CredentialsRepository } from '@db/repositories/credentials.repository'; +import { SharedCredentialsRepository } from '@db/repositories/sharedCredentials.repository'; import { ExternalHooks } from '@/ExternalHooks'; import { Logger } from '@/Logger'; import { VariablesService } from '@/environments/variables/variables.service'; import { SecretsHelper } from '@/SecretsHelpers'; import { CredentialsHelper } from '@/CredentialsHelper'; -import { mockInstance } from '../../integration/shared/utils'; +import { mockInstance } from '../../shared/mocking'; describe('OAuth2CredentialController', () => { mockInstance(Logger); diff --git a/packages/cli/test/unit/controllers/owner.controller.test.ts b/packages/cli/test/unit/controllers/owner.controller.test.ts index 58f37ec5ac..099f3bf47a 100644 --- a/packages/cli/test/unit/controllers/owner.controller.test.ts +++ b/packages/cli/test/unit/controllers/owner.controller.test.ts @@ -3,21 +3,24 @@ import { anyObject, captor, mock } from 'jest-mock-extended'; import jwt from 'jsonwebtoken'; import type { IInternalHooksClass } from '@/Interfaces'; import type { User } from '@db/entities/User'; -import type { SettingsRepository } from '@db/repositories'; +import type { SettingsRepository } from '@db/repositories/settings.repository'; import type { Config } from '@/config'; import { BadRequestError } from '@/ResponseHelper'; import type { OwnerRequest } from '@/requests'; import { OwnerController } from '@/controllers/owner.controller'; -import { badPasswords } from '../shared/testData'; import { AUTH_COOKIE_NAME } from '@/constants'; import { UserService } from '@/services/user.service'; -import { mockInstance } from '../../integration/shared/utils'; +import { License } from '@/License'; + +import { mockInstance } from '../../shared/mocking'; +import { badPasswords } from '../shared/testData'; describe('OwnerController', () => { const config = mock(); const internalHooks = mock(); const userService = mockInstance(UserService); const settingsRepository = mock(); + mockInstance(License).isWithinUsersLimit.mockReturnValue(true); const controller = new OwnerController( config, mock(), diff --git a/packages/cli/test/unit/execution.lifecycle.test.ts b/packages/cli/test/unit/execution.lifecycle.test.ts index 02c41aafc0..59929708f8 100644 --- a/packages/cli/test/unit/execution.lifecycle.test.ts +++ b/packages/cli/test/unit/execution.lifecycle.test.ts @@ -1,6 +1,6 @@ import { restoreBinaryDataId } from '@/executionLifecycleHooks/restoreBinaryDataId'; import { BinaryDataService } from 'n8n-core'; -import { mockInstance } from '../integration/shared/utils/mocking'; +import { mockInstance } from '../shared/mocking'; import { toSaveSettings } from '@/executionLifecycleHooks/toSaveSettings'; import type { IRun } from 'n8n-workflow'; import config from '@/config'; diff --git a/packages/cli/test/unit/push/websocket.push.test.ts b/packages/cli/test/unit/push/websocket.push.test.ts index d4f72a5c9b..2e072c3857 100644 --- a/packages/cli/test/unit/push/websocket.push.test.ts +++ b/packages/cli/test/unit/push/websocket.push.test.ts @@ -3,9 +3,9 @@ import { EventEmitter } from 'events'; import type WebSocket from 'ws'; import { WebSocketPush } from '@/push/websocket.push'; import { Logger } from '@/Logger'; -import type { User } from '@/databases/entities/User'; +import type { User } from '@db/entities/User'; import type { PushDataExecutionRecovered } from '@/Interfaces'; -import { mockInstance } from '../../integration/shared/utils'; +import { mockInstance } from '../../shared/mocking'; jest.useFakeTimers(); diff --git a/packages/cli/test/unit/repositories/role.repository.test.ts b/packages/cli/test/unit/repositories/role.repository.test.ts index c7669967cf..40d95207ac 100644 --- a/packages/cli/test/unit/repositories/role.repository.test.ts +++ b/packages/cli/test/unit/repositories/role.repository.test.ts @@ -4,7 +4,7 @@ import { mock } from 'jest-mock-extended'; import type { RoleNames, RoleScopes } from '@db/entities/Role'; import { Role } from '@db/entities/Role'; import { RoleRepository } from '@db/repositories/role.repository'; -import { mockInstance } from '../../integration/shared/utils/'; +import { mockInstance } from '../../shared/mocking'; import { randomInteger } from '../../integration/shared/random'; describe('RoleRepository', () => { diff --git a/packages/cli/test/unit/repositories/sharedCredentials.repository.test.ts b/packages/cli/test/unit/repositories/sharedCredentials.repository.test.ts index d04b6974a6..1a4803a35c 100644 --- a/packages/cli/test/unit/repositories/sharedCredentials.repository.test.ts +++ b/packages/cli/test/unit/repositories/sharedCredentials.repository.test.ts @@ -5,7 +5,7 @@ import type { User } from '@db/entities/User'; import type { CredentialsEntity } from '@db/entities/CredentialsEntity'; import { SharedCredentials } from '@db/entities/SharedCredentials'; import { SharedCredentialsRepository } from '@db/repositories/sharedCredentials.repository'; -import { mockInstance } from '../../integration/shared/utils/'; +import { mockInstance } from '../../shared/mocking'; describe('SharedCredentialsRepository', () => { const entityManager = mockInstance(EntityManager); diff --git a/packages/cli/test/unit/services/communityPackages.service.test.ts b/packages/cli/test/unit/services/communityPackages.service.test.ts index 6bbee36d53..1d2a74e369 100644 --- a/packages/cli/test/unit/services/communityPackages.service.test.ts +++ b/packages/cli/test/unit/services/communityPackages.service.test.ts @@ -15,16 +15,18 @@ import config from '@/config'; import { InstalledPackages } from '@db/entities/InstalledPackages'; import type { CommunityPackages } from '@/Interfaces'; import { CommunityPackagesService } from '@/services/communityPackages.service'; -import { InstalledNodesRepository, InstalledPackagesRepository } from '@/databases/repositories'; -import { InstalledNodes } from '@/databases/entities/InstalledNodes'; +import { InstalledNodesRepository } from '@db/repositories/installedNodes.repository'; +import { InstalledPackagesRepository } from '@db/repositories/installedPackages.repository'; +import { InstalledNodes } from '@db/entities/InstalledNodes'; import { LoadNodesAndCredentials } from '@/LoadNodesAndCredentials'; +import { mockInstance } from '../../shared/mocking'; import { COMMUNITY_NODE_VERSION, COMMUNITY_PACKAGE_VERSION, } from '../../integration/shared/constants'; import { randomName } from '../../integration/shared/random'; -import { mockInstance, mockPackageName, mockPackagePair } from '../../integration/shared/utils'; +import { mockPackageName, mockPackagePair } from '../../integration/shared/utils'; jest.mock('fs/promises'); jest.mock('child_process'); diff --git a/packages/cli/test/unit/services/events.service.test.ts b/packages/cli/test/unit/services/events.service.test.ts index b8703054a8..bc1aeb6387 100644 --- a/packages/cli/test/unit/services/events.service.test.ts +++ b/packages/cli/test/unit/services/events.service.test.ts @@ -11,11 +11,11 @@ import { mock } from 'jest-mock-extended'; import config from '@/config'; import type { User } from '@db/entities/User'; import type { WorkflowStatistics } from '@db/entities/WorkflowStatistics'; -import { WorkflowStatisticsRepository } from '@db/repositories'; +import { WorkflowStatisticsRepository } from '@db/repositories/workflowStatistics.repository'; import { EventsService } from '@/services/events.service'; import { UserService } from '@/services/user.service'; import { OwnershipService } from '@/services/ownership.service'; -import { mockInstance } from '../../integration/shared/utils'; +import { mockInstance } from '../../shared/mocking'; jest.mock('@/UserManagement/UserManagementHelper', () => ({ getWorkflowOwner: jest.fn() })); diff --git a/packages/cli/test/unit/services/orchestration.service.test.ts b/packages/cli/test/unit/services/orchestration.service.test.ts index 96cc5e420e..6cf073f28a 100644 --- a/packages/cli/test/unit/services/orchestration.service.test.ts +++ b/packages/cli/test/unit/services/orchestration.service.test.ts @@ -4,13 +4,13 @@ import { SingleMainInstancePublisher } from '@/services/orchestration/main/Singl import type { RedisServiceWorkerResponseObject } from '@/services/redis/RedisServiceCommands'; import { eventBus } from '@/eventbus'; import { RedisService } from '@/services/redis.service'; -import { mockInstance } from '../../integration/shared/utils'; import { handleWorkerResponseMessageMain } from '@/services/orchestration/main/handleWorkerResponseMessageMain'; import { handleCommandMessageMain } from '@/services/orchestration/main/handleCommandMessageMain'; import { OrchestrationHandlerMainService } from '@/services/orchestration/main/orchestration.handler.main.service'; import * as helpers from '@/services/orchestration/helpers'; import { ExternalSecretsManager } from '@/ExternalSecrets/ExternalSecretsManager.ee'; import { Logger } from '@/Logger'; +import { mockInstance } from '../../shared/mocking'; const os = Container.get(SingleMainInstancePublisher); const handler = Container.get(OrchestrationHandlerMainService); diff --git a/packages/cli/test/unit/services/ownership.service.test.ts b/packages/cli/test/unit/services/ownership.service.test.ts index 32b50bb417..f197c1ee15 100644 --- a/packages/cli/test/unit/services/ownership.service.test.ts +++ b/packages/cli/test/unit/services/ownership.service.test.ts @@ -1,20 +1,20 @@ import { OwnershipService } from '@/services/ownership.service'; -import { SharedWorkflowRepository } from '@/databases/repositories'; -import { mockInstance } from '../../integration/shared/utils'; -import { Role } from '@/databases/entities/Role'; +import { SharedWorkflowRepository } from '@db/repositories/sharedWorkflow.repository'; +import { Role } from '@db/entities/Role'; +import { SharedWorkflow } from '@db/entities/SharedWorkflow'; +import { CacheService } from '@/services/cache.service'; +import { User } from '@db/entities/User'; +import { RoleService } from '@/services/role.service'; +import { UserService } from '@/services/user.service'; +import { CredentialsEntity } from '@db/entities/CredentialsEntity'; +import type { SharedCredentials } from '@db/entities/SharedCredentials'; +import { mockInstance } from '../../shared/mocking'; import { randomCredentialPayload, randomEmail, randomInteger, randomName, } from '../../integration/shared/random'; -import { SharedWorkflow } from '@/databases/entities/SharedWorkflow'; -import { CacheService } from '@/services/cache.service'; -import { User } from '@/databases/entities/User'; -import { RoleService } from '@/services/role.service'; -import { UserService } from '@/services/user.service'; -import { CredentialsEntity } from '@/databases/entities/CredentialsEntity'; -import type { SharedCredentials } from '@/databases/entities/SharedCredentials'; const wfOwnerRole = () => Object.assign(new Role(), { diff --git a/packages/cli/test/unit/services/redis.service.test.ts b/packages/cli/test/unit/services/redis.service.test.ts index 9066f16852..309593ce24 100644 --- a/packages/cli/test/unit/services/redis.service.test.ts +++ b/packages/cli/test/unit/services/redis.service.test.ts @@ -2,7 +2,7 @@ import Container from 'typedi'; import { Logger } from '@/Logger'; import config from '@/config'; import { RedisService } from '@/services/redis.service'; -import { mockInstance } from '../../integration/shared/utils'; +import { mockInstance } from '../../shared/mocking'; mockInstance(Logger); const redisService = Container.get(RedisService); diff --git a/packages/cli/test/unit/services/role.service.test.ts b/packages/cli/test/unit/services/role.service.test.ts index 9b0f524a10..b74036a45c 100644 --- a/packages/cli/test/unit/services/role.service.test.ts +++ b/packages/cli/test/unit/services/role.service.test.ts @@ -1,11 +1,11 @@ import { SharedWorkflowRepository } from '@db/repositories/sharedWorkflow.repository'; import type { RoleNames, RoleScopes } from '@db/entities/Role'; import { Role } from '@db/entities/Role'; -import { mockInstance } from '../../integration/shared/utils/'; import { RoleService } from '@/services/role.service'; -import { RoleRepository } from '@/databases/repositories'; +import { RoleRepository } from '@db/repositories/role.repository'; import { CacheService } from '@/services/cache.service'; -import { SharedWorkflow } from '@/databases/entities/SharedWorkflow'; +import { SharedWorkflow } from '@db/entities/SharedWorkflow'; +import { mockInstance } from '../../shared/mocking'; import { chooseRandomly } from '../../integration/shared/random'; import config from '@/config'; diff --git a/packages/cli/test/unit/services/user.service.test.ts b/packages/cli/test/unit/services/user.service.test.ts index 0eeaf8b617..02148a3a13 100644 --- a/packages/cli/test/unit/services/user.service.test.ts +++ b/packages/cli/test/unit/services/user.service.test.ts @@ -3,9 +3,9 @@ import jwt from 'jsonwebtoken'; import { Logger } from '@/Logger'; import config from '@/config'; import { User } from '@db/entities/User'; -import { UserRepository } from '@db/repositories'; +import { UserRepository } from '@db/repositories/user.repository'; import { UserService } from '@/services/user.service'; -import { mockInstance } from '../../integration/shared/utils'; +import { mockInstance } from '../../shared/mocking'; describe('UserService', () => { config.set('userManagement.jwtSecret', 'random-secret'); diff --git a/packages/cli/test/unit/services/webhook.service.test.ts b/packages/cli/test/unit/services/webhook.service.test.ts index e9df60d9df..34a510eb56 100644 --- a/packages/cli/test/unit/services/webhook.service.test.ts +++ b/packages/cli/test/unit/services/webhook.service.test.ts @@ -1,10 +1,10 @@ import { v4 as uuid } from 'uuid'; import config from '@/config'; -import { mockInstance } from '../../integration/shared/utils/'; -import { WebhookRepository } from '@/databases/repositories'; +import { WebhookRepository } from '@db/repositories/webhook.repository'; import { CacheService } from '@/services/cache.service'; import { WebhookService } from '@/services/webhook.service'; -import { WebhookEntity } from '@/databases/entities/WebhookEntity'; +import { WebhookEntity } from '@db/entities/WebhookEntity'; +import { mockInstance } from '../../shared/mocking'; const createWebhook = (method: string, path: string, webhookId?: string, pathSegments?: number) => Object.assign(new WebhookEntity(), { diff --git a/packages/cli/test/unit/webhooks.test.ts b/packages/cli/test/unit/webhooks.test.ts index f4b1b02d5b..f6478806b4 100644 --- a/packages/cli/test/unit/webhooks.test.ts +++ b/packages/cli/test/unit/webhooks.test.ts @@ -11,7 +11,7 @@ import { TestWebhooks } from '@/TestWebhooks'; import { WaitingWebhooks } from '@/WaitingWebhooks'; import type { IResponseCallbackData } from '@/Interfaces'; -import { mockInstance } from '../integration/shared/utils'; +import { mockInstance } from '../shared/mocking'; let agent: SuperAgentTest; diff --git a/packages/cli/test/unit/workflowHistoryHelper.test.ts b/packages/cli/test/unit/workflowHistoryHelper.test.ts index a6a701452d..09849b1437 100644 --- a/packages/cli/test/unit/workflowHistoryHelper.test.ts +++ b/packages/cli/test/unit/workflowHistoryHelper.test.ts @@ -1,7 +1,7 @@ import { License } from '@/License'; -import { mockInstance } from '../integration/shared/utils'; import config from '@/config'; import { getWorkflowHistoryPruneTime } from '@/workflows/workflowHistory/workflowHistoryHelper.ee'; +import { mockInstance } from '../shared/mocking'; let licenseMock: License; let licensePruneTime = -1;