From 0275af78548ecd10cf074f38daefc968c484ee07 Mon Sep 17 00:00:00 2001 From: Charlie Kolb Date: Mon, 12 Oct 2026 08:39:08 +0200 Subject: [PATCH] refactor(core): move ownership service to backend services --- packages/@n8n/backend-services/src/index.ts | 1 + .../__tests__/ownership.service.test.ts | 155 ++---------------- .../src/services/ownership.service.ts | 70 +------- .../__tests__/active-workflow-manager.test.ts | 3 +- .../cli/src/__tests__/wait-tracker.test.ts | 2 +- .../workflow-execute-additional-data.test.ts | 3 +- .../src/__tests__/workflow-helpers.test.ts | 2 +- .../cli/src/__tests__/workflow-runner.test.ts | 2 +- packages/cli/src/active-workflow-manager.ts | 2 +- .../__tests__/chat-execution-manager.test.ts | 2 +- .../cli/src/chat/chat-execution-manager.ts | 2 +- .../commands/__tests__/execute-batch.test.ts | 2 +- .../src/commands/__tests__/execute.test.ts | 2 +- packages/cli/src/commands/execute-batch.ts | 2 +- packages/cli/src/commands/execute.ts | 3 +- .../__tests__/owner.controller.test.ts | 8 +- .../cli/src/controllers/owner.controller.ts | 6 +- .../__tests__/credentials.service.ee.test.ts | 7 +- .../__tests__/credentials.service.test.ts | 10 +- .../src/credentials/credentials.service.ee.ts | 3 +- .../src/credentials/credentials.service.ts | 8 +- .../__tests__/test-runner.service.ee.test.ts | 2 +- .../test-runner/test-runner.service.ee.ts | 3 +- .../__tests__/telemetry-event-relay.test.ts | 3 +- .../events/relays/telemetry.event-relay.ts | 3 +- .../__tests__/execute-error-workflow.test.ts | 3 +- .../execution-lifecycle-hooks.test.ts | 3 +- .../execute-error-workflow.ts | 3 +- ...nqueued-execution-recovery.service.test.ts | 3 +- ...ution-recovery.service.integration.test.ts | 4 +- .../__tests__/execution.service.test.ts | 3 +- .../enqueued-execution-recovery.service.ts | 3 +- .../executions/execution-recovery.service.ts | 2 +- .../cli/src/executions/execution.service.ts | 3 +- .../credentials-permission-checker.test.ts | 3 +- .../subworkflow-policy-checker.test.ts | 3 +- .../credentials-permission-checker.ts | 7 +- .../subworkflow-policy-checker.ts | 3 +- .../owner.instance-settings-loader.test.ts | 20 +-- .../loaders/owner.instance-settings-loader.ts | 6 +- ...ta-table-proxy.service.integration.test.ts | 3 +- .../data-table/data-table-proxy.service.ts | 3 +- .../eval/__tests__/execution.service.test.ts | 2 +- .../instance-ai/eval/execution.service.ts | 2 +- .../__tests__/otel-lifecycle-handler.test.ts | 3 +- .../modules/otel/otel-lifecycle-handler.ts | 3 +- .../policy-lifecycle-handler.test.ts | 2 +- .../policy-lifecycle-handler.ts | 2 +- .../source-control-git.service.ee.ts | 2 +- .../enforce-workflow-publish.test.ts | 2 +- .../src/policy/enforce-workflow-publish.ts | 2 +- .../__tests__/job-processor.service.test.ts | 3 +- .../schedule-trigger-task-handler.test.ts | 3 +- .../schedule-trigger-task-handler.ts | 3 +- .../__tests__/ai-gateway.service.test.ts | 3 +- .../__tests__/frontend.service.test.ts | 3 +- .../__tests__/owner-setup.service.test.ts | 132 +++++++++++++++ .../ownership.service.integration.test.ts | 7 +- .../__tests__/project.service.ee.test.ts | 3 +- .../services/__tests__/user.service.test.ts | 8 +- ...low-statistics.service.integration.test.ts | 3 +- .../cli/src/services/ai-gateway.service.ts | 3 +- packages/cli/src/services/frontend.service.ts | 3 +- .../cli/src/services/owner-setup.service.ts | 73 +++++++++ .../ownership-transfer.service.test.ts | 2 +- .../ownership-transfer.service.ts | 3 +- .../cli/src/services/project.service.ee.ts | 4 +- packages/cli/src/services/user.service.ts | 3 +- .../services/workflow-statistics.service.ts | 3 +- packages/cli/src/wait-tracker.ts | 2 +- .../__tests__/webhook-helpers.test.ts | 3 +- packages/cli/src/webhooks/webhook-helpers.ts | 3 +- .../src/workflow-execute-additional-data.ts | 6 +- packages/cli/src/workflow-helpers.ts | 2 +- .../cli/src/workflows/__tests__/utils.test.ts | 2 +- .../workflow-execution.service.test.ts | 7 +- .../__tests__/workflow.service.ee.test.ts | 3 +- .../__tests__/workflow.service.test.ts | 3 +- .../workflow-publication-applier.test.ts | 2 +- .../workflow-publication-applier.ts | 2 +- .../trigger-execution-context.factory.test.ts | 3 +- .../trigger-execution-context.factory.ts | 3 +- packages/cli/src/workflows/utils.ts | 2 +- .../workflows/workflow-execution.service.ts | 3 +- .../cli/src/workflows/workflow.service.ee.ts | 3 +- .../cli/src/workflows/workflow.service.ts | 3 +- .../cli/src/workflows/workflows.controller.ts | 3 +- .../active-workflow-manager.test.ts | 2 +- .../integration/commands/start.cmd.test.ts | 2 +- .../credentials-permission-checker.test.ts | 2 +- .../folder/folder.controller.test.ts | 2 +- .../cli/test/integration/owner.api.test.ts | 2 +- .../scheduled-job-lifecycle.test.ts | 2 +- .../cli/test/integration/users.api.test.ts | 2 +- ...rkflow-publication-outbox-consumer.test.ts | 2 +- .../workflow-publication-reconciler.test.ts | 3 +- .../workflows/workflow.service.test.ts | 3 +- 97 files changed, 364 insertions(+), 376 deletions(-) rename packages/{cli => @n8n/backend-services}/src/services/__tests__/ownership.service.test.ts (68%) rename packages/{cli => @n8n/backend-services}/src/services/ownership.service.ts (77%) create mode 100644 packages/cli/src/services/__tests__/owner-setup.service.test.ts create mode 100644 packages/cli/src/services/owner-setup.service.ts diff --git a/packages/@n8n/backend-services/src/index.ts b/packages/@n8n/backend-services/src/index.ts index f144eaa0b03..356227c8d44 100644 --- a/packages/@n8n/backend-services/src/index.ts +++ b/packages/@n8n/backend-services/src/index.ts @@ -26,6 +26,7 @@ export { } from './services/workflow-sharing.service'; export { FolderFinderService } from './services/folder-finder.service'; export { InstanceWriteAccessService } from './services/instance-write-access.service'; +export { OwnershipService } from './services/ownership.service'; export { UrlService } from './services/url.service'; export { classifyRestError, diff --git a/packages/cli/src/services/__tests__/ownership.service.test.ts b/packages/@n8n/backend-services/src/services/__tests__/ownership.service.test.ts similarity index 68% rename from packages/cli/src/services/__tests__/ownership.service.test.ts rename to packages/@n8n/backend-services/src/services/__tests__/ownership.service.test.ts index 2ee1539ada3..378e12ff38a 100644 --- a/packages/cli/src/services/__tests__/ownership.service.test.ts +++ b/packages/@n8n/backend-services/src/services/__tests__/ownership.service.test.ts @@ -1,8 +1,7 @@ -import { Logger } from '@n8n/backend-common'; -import type { EventService } from '@n8n/backend-services'; import { mockInstance } from '@n8n/backend-test-utils'; import { Project, + CredentialsEntity, SharedWorkflow, User, WorkflowEntity, @@ -14,17 +13,20 @@ import { GLOBAL_OWNER_ROLE, PROJECT_OWNER_ROLE, } from '@n8n/db'; -import type { SharedCredentials, SettingsRepository } from '@n8n/db'; +import type { SharedCredentials } from '@n8n/db'; import { PROJECT_OWNER_ROLE_SLUG } from '@n8n/permissions'; -import { v4 as uuid } from 'uuid'; -import { mock } from 'vitest-mock-extended'; +import { randomUUID } from 'node:crypto'; -import { BadRequestError } from '@n8n/errors'; -import { OwnershipService } from '@/services/ownership.service'; -import { PasswordUtility } from '@/services/password.utility'; -import { mockCredential, mockProject } from '@test/mock-objects'; +import { CacheService } from '../cache/cache.service'; +import { OwnershipService } from '../ownership.service'; -import { CacheService } from '@n8n/backend-services'; +const mockCredential = () => new CredentialsEntity(); +const mockProject = () => + Object.assign(new Project(), { + id: randomUUID(), + type: 'personal' as const, + name: 'Test project', + }); describe('OwnershipService', () => { const userRepository = mockInstance(UserRepository); @@ -32,21 +34,13 @@ describe('OwnershipService', () => { const projectRelationRepository = mockInstance(ProjectRelationRepository); const projectRepository = mockInstance(ProjectRepository); const cacheService = mockInstance(CacheService); - const passwordUtility = mockInstance(PasswordUtility); - const logger = mockInstance(Logger); - const eventService = mock(); - const settingsRepository = mock(); const ownershipService = new OwnershipService( cacheService, - eventService, - logger, - passwordUtility, projectRelationRepository, projectRepository, sharedWorkflowRepository, userRepository, - settingsRepository, ); beforeEach(() => { @@ -108,9 +102,9 @@ describe('OwnershipService', () => { test('should not use the repository if the owner was found in the cache', async () => { // ARRANGE const project = new Project(); - project.id = uuid(); + project.id = randomUUID(); const owner = new User(); - owner.id = uuid(); + owner.id = randomUUID(); owner.role = GLOBAL_OWNER_ROLE; const projectRelation = new ProjectRelation(); projectRelation.role = PROJECT_OWNER_ROLE; @@ -274,7 +268,7 @@ describe('OwnershipService', () => { describe('invalidateProjectOwnerCacheByUserId()', () => { test('should delete cache entry for personal project', async () => { const project = new Project(); - project.id = uuid(); + project.id = randomUUID(); projectRepository.getPersonalProjectForUser.mockResolvedValueOnce(project); await ownershipService.invalidateProjectOwnerCacheByUserId('some-user-id'); @@ -331,123 +325,4 @@ describe('OwnershipService', () => { }); }); }); - - describe('setupOwner()', () => { - it('should throw a BadRequestError if the instance owner is already setup', async () => { - userRepository.hasClaimedInstanceOwner.mockResolvedValueOnce(true); - - const execution = ownershipService.setupOwner(mock()); - await expect(execution).rejects.toThrow(BadRequestError); - await expect(execution).rejects.toThrow('Instance owner already setup'); - - expect(userRepository.save).not.toHaveBeenCalled(); - expect(eventService.emit).not.toHaveBeenCalled(); - expect(logger.debug).toHaveBeenCalledWith( - 'Request to claim instance ownership failed because instance owner already exists', - ); - }); - - it('should throw a BadRequestError if the shell user is not found', async () => { - userRepository.hasClaimedInstanceOwner.mockResolvedValueOnce(false); - userRepository.findOne.mockResolvedValueOnce(null); - - const execution = ownershipService.setupOwner(mock()); - await expect(execution).rejects.toThrow(BadRequestError); - await expect(execution).rejects.toThrow('Instance owner shell user not found'); - - expect(userRepository.save).not.toHaveBeenCalled(); - }); - - it('should setup the instance owner successfully', async () => { - const user = mock({ - id: 'userId', - role: GLOBAL_OWNER_ROLE, - authIdentities: [], - }); - - const payload = { - email: 'valid@email.com', - password: 'NewPassword123', - firstName: 'Jane', - lastName: 'Doe', - }; - - // not quite perfect as we hash the password. - const expected = { ...user, ...payload, id: 'newUserId' }; - - userRepository.hasClaimedInstanceOwner.mockResolvedValueOnce(false); - userRepository.findOne.mockResolvedValueOnce(user); - userRepository.save.mockResolvedValueOnce(expected); - - const actual = await ownershipService.setupOwner(payload); - - expect(userRepository.save).toHaveBeenCalledWith(user, { transaction: false }); - expect(eventService.emit).toHaveBeenCalledWith('instance-owner-setup', { - userId: 'newUserId', - }); - expect(actual.id).toEqual('newUserId'); - }); - - it('should normalize email to lowercase', async () => { - const user = mock({ - id: 'userId', - role: GLOBAL_OWNER_ROLE, - authIdentities: [], - }); - - const payload = { - email: 'Admin@Example.COM', - password: 'NewPassword123', - firstName: 'Jane', - lastName: 'Doe', - }; - - userRepository.hasClaimedInstanceOwner.mockResolvedValueOnce(false); - userRepository.findOne.mockResolvedValueOnce(user); - userRepository.save.mockResolvedValueOnce(user); - - await ownershipService.setupOwner(payload); - - expect(user.email).toBe('admin@example.com'); - }); - - it('should skip hasInstanceOwner check when override is true', async () => { - const user = mock({ - id: 'userId', - role: GLOBAL_OWNER_ROLE, - authIdentities: [], - }); - - userRepository.findOne.mockResolvedValueOnce(user); - userRepository.save.mockResolvedValueOnce(user); - - await ownershipService.setupOwner( - { email: 'a@b.com', password: 'hash', firstName: 'A', lastName: 'B' }, - { overwriteExisting: true }, - ); - - expect(userRepository.hasClaimedInstanceOwner).not.toHaveBeenCalled(); - }); - - it('should use pre-hashed password when preHashed is true', async () => { - const user = mock({ - id: 'userId', - role: GLOBAL_OWNER_ROLE, - authIdentities: [], - }); - - const preHashedPassword = '$2b$10$abcdefghijklmnopqrstuuABCDEFGHIJKLMNOPQRSTUVWXYZ01234'; - - userRepository.findOne.mockResolvedValueOnce(user); - userRepository.save.mockResolvedValueOnce(user); - - await ownershipService.setupOwner( - { email: 'a@b.com', password: preHashedPassword, firstName: 'A', lastName: 'B' }, - { overwriteExisting: true, passwordIsHashed: true }, - ); - - expect(user.password).toBe(preHashedPassword); - expect(passwordUtility.hash).not.toHaveBeenCalled(); - }); - }); }); diff --git a/packages/cli/src/services/ownership.service.ts b/packages/@n8n/backend-services/src/services/ownership.service.ts similarity index 77% rename from packages/cli/src/services/ownership.service.ts rename to packages/@n8n/backend-services/src/services/ownership.service.ts index 689168e45dd..9f841f8631c 100644 --- a/packages/cli/src/services/ownership.service.ts +++ b/packages/@n8n/backend-services/src/services/ownership.service.ts @@ -1,38 +1,27 @@ -import { OwnerSetupRequestDto } from '@n8n/api-types'; -import { Logger } from '@n8n/backend-common'; -import { CacheService, EventService } from '@n8n/backend-services'; import type { ListQueryDb } from '@n8n/db'; import { GLOBAL_OWNER_ROLE, Project, - User, ProjectRelationRepository, ProjectRepository, - SharedWorkflowRepository, - UserRepository, Role, - SettingsRepository, Scope, + SharedWorkflowRepository, + User, + UserRepository, } from '@n8n/db'; import { Service } from '@n8n/di'; -import config from '@/config'; -import { BadRequestError } from '@n8n/errors'; - -import { PasswordUtility } from './password.utility'; +import { CacheService } from './cache/cache.service'; @Service() export class OwnershipService { constructor( private cacheService: CacheService, - private eventService: EventService, - private logger: Logger, - private passwordUtility: PasswordUtility, private projectRelationRepository: ProjectRelationRepository, private projectRepository: ProjectRepository, private sharedWorkflowRepository: SharedWorkflowRepository, private userRepository: UserRepository, - private settingsRepository: SettingsRepository, ) {} // To make use of the cache service we should store POJOs, these @@ -256,55 +245,4 @@ export class OwnershipService { async hasInstanceOwner() { return await this.userRepository.hasClaimedInstanceOwner(); } - - async setupOwner( - payload: OwnerSetupRequestDto, - options?: { overwriteExisting?: boolean; passwordIsHashed?: boolean }, - ) { - const { email, firstName, lastName, password } = payload; - - if (!options?.overwriteExisting && (await this.hasInstanceOwner())) { - this.logger.debug( - 'Request to claim instance ownership failed because instance owner already exists', - ); - throw new BadRequestError('Instance owner already setup'); - } - - let shellUser = await this.userRepository.findOne({ - where: { role: { slug: GLOBAL_OWNER_ROLE.slug } }, - relations: ['role'], - }); - - if (!shellUser) { - this.logger.error('Could not find shell user with global:owner role'); - throw new BadRequestError('Instance owner shell user not found'); - } - - shellUser.email = email.toLowerCase(); - shellUser.firstName = firstName; - shellUser.lastName = lastName; - shellUser.lastActiveAt = new Date(); - shellUser.password = options?.passwordIsHashed - ? password - : await this.passwordUtility.hash(password); - - shellUser = await this.userRepository.save(shellUser, { transaction: false }); - - this.logger.info('Owner was set up successfully'); - this.eventService.emit('instance-owner-setup', { userId: shellUser.id }); - - // The next block needs to be deleted and is temporary for now - // See packages/cli/src/config/schema.ts for more info - // We update the SettingsRepository so when we "startup" next time - // the config state is restored. - // #region Delete me - await this.settingsRepository.update( - { key: 'userManagement.isInstanceOwnerSetUp' }, - { value: JSON.stringify(true) }, - ); - config.set('userManagement.isInstanceOwnerSetUp', true); - // #endregion - - return shellUser; - } } diff --git a/packages/cli/src/__tests__/active-workflow-manager.test.ts b/packages/cli/src/__tests__/active-workflow-manager.test.ts index 700fef56457..18e94c72f15 100644 --- a/packages/cli/src/__tests__/active-workflow-manager.test.ts +++ b/packages/cli/src/__tests__/active-workflow-manager.test.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/unbound-method */ import type { Logger } from '@n8n/backend-common'; -import type { EventService, WorkflowSharingService } from '@n8n/backend-services'; +import type { EventService, WorkflowSharingService, OwnershipService } from '@n8n/backend-services'; import { mockLogger } from '@n8n/backend-test-utils'; import type { GlobalConfig, WorkflowsConfig } from '@n8n/config'; import type { Project, WorkflowEntity, WorkflowHistory, WorkflowRepository } from '@n8n/db'; @@ -45,7 +45,6 @@ import type { } from '@/scheduling/schedule-trigger-node/schedule-trigger-job-registrar'; import type { PolicyEnforcementService } from '@/policy/policy-enforcement.service'; import { PolicyViolationError } from '@/policy/policy-violation.error'; -import type { OwnershipService } from '@/services/ownership.service'; import type { PollCursorService } from '@/workflows/triggers/poll-cursor.service'; import { TriggerExecutionContextFactory } from '@/workflows/triggers/trigger-execution-context.factory'; import type { WorkflowExecutionService } from '@/workflows/workflow-execution.service'; diff --git a/packages/cli/src/__tests__/wait-tracker.test.ts b/packages/cli/src/__tests__/wait-tracker.test.ts index c686548b903..a56f02e053f 100644 --- a/packages/cli/src/__tests__/wait-tracker.test.ts +++ b/packages/cli/src/__tests__/wait-tracker.test.ts @@ -27,7 +27,7 @@ import { ExecutionAlreadyResumingError } from '@/errors/execution-already-resumi import { ExecutionPersistence } from '@/executions/execution-persistence'; import { NodeTypes } from '@/node-types'; import type { MultiMainSetup } from '@/scaling/multi-main-setup.ee'; -import type { OwnershipService } from '@/services/ownership.service'; +import type { OwnershipService } from '@n8n/backend-services'; import type { WorkflowPublisherService } from '@/workflows/workflow-publisher.service'; import { WaitTracker } from '@/wait-tracker'; import type { WorkflowRunner } from '@/workflow-runner'; diff --git a/packages/cli/src/__tests__/workflow-execute-additional-data.test.ts b/packages/cli/src/__tests__/workflow-execute-additional-data.test.ts index ae1b233e233..27208c17656 100644 --- a/packages/cli/src/__tests__/workflow-execute-additional-data.test.ts +++ b/packages/cli/src/__tests__/workflow-execute-additional-data.test.ts @@ -1,5 +1,5 @@ import { Logger, ModuleRegistry } from '@n8n/backend-common'; -import { EventService, UrlService } from '@n8n/backend-services'; +import { EventService, UrlService, OwnershipService } from '@n8n/backend-services'; import { mockInstance } from '@n8n/backend-test-utils'; import { ExecutionsConfig, GlobalConfig, type NodesConfig, WorkflowsConfig } from '@n8n/config'; import type { WorkflowEntity, Project, WorkflowHistory } from '@n8n/db'; @@ -47,7 +47,6 @@ import { AgentsService } from '@/modules/agents/agents.service'; import { AgentsSettingsService } from '@/modules/agents/agents-settings.service'; import { DataTableProxyService } from '@/modules/data-table/data-table-proxy.service'; import { NodeTypes } from '@/node-types'; -import { OwnershipService } from '@/services/ownership.service'; import { WorkflowStatisticsService } from '@/services/workflow-statistics.service'; import { Telemetry } from '@/telemetry'; import { diff --git a/packages/cli/src/__tests__/workflow-helpers.test.ts b/packages/cli/src/__tests__/workflow-helpers.test.ts index a298889f6b5..b45d98c793d 100644 --- a/packages/cli/src/__tests__/workflow-helpers.test.ts +++ b/packages/cli/src/__tests__/workflow-helpers.test.ts @@ -17,7 +17,7 @@ import type { import { VariablesService } from '@/environments.ee/variables/variables.service.ee'; import { ExecutionPersistence } from '@/executions/execution-persistence'; import { NodeTypes } from '@/node-types'; -import { OwnershipService } from '@/services/ownership.service'; +import { OwnershipService } from '@n8n/backend-services'; import { getLastExecutedNodeData, getLastExecutedNodeRuns, diff --git a/packages/cli/src/__tests__/workflow-runner.test.ts b/packages/cli/src/__tests__/workflow-runner.test.ts index 017027dcf3a..7d255a13bc2 100644 --- a/packages/cli/src/__tests__/workflow-runner.test.ts +++ b/packages/cli/src/__tests__/workflow-runner.test.ts @@ -53,7 +53,7 @@ import { } from '@/executions/pre-execution-checks'; import { ManualExecutionService } from '@/manual-execution.service'; import { EngineV2Dispatcher } from '@/services/engine-v2-dispatcher.service'; -import { OwnershipService } from '@/services/ownership.service'; +import { OwnershipService } from '@n8n/backend-services'; import { Telemetry } from '@/telemetry'; import * as WorkflowExecuteAdditionalData from '@/workflow-execute-additional-data'; import { EXECUTION_ENDED_WITHOUT_RESPONSE } from '@/webhooks/constants'; diff --git a/packages/cli/src/active-workflow-manager.ts b/packages/cli/src/active-workflow-manager.ts index 95cd31b0dc1..59f4dabea10 100644 --- a/packages/cli/src/active-workflow-manager.ts +++ b/packages/cli/src/active-workflow-manager.ts @@ -54,7 +54,7 @@ import { PollTriggerJobRegistrar } from '@/scheduling/poll-trigger-node/poll-tri import type { ScheduleTriggerCollectionSession } from '@/scheduling/schedule-trigger-node/schedule-trigger-job-registrar'; import { ScheduleTriggerJobRegistrar } from '@/scheduling/schedule-trigger-node/schedule-trigger-job-registrar'; import { ActiveWorkflowsService } from '@/services/active-workflows.service'; -import { OwnershipService } from '@/services/ownership.service'; +import { OwnershipService } from '@n8n/backend-services'; import * as WebhookHelpers from '@/webhooks/webhook-helpers'; import { WebhookService } from '@/webhooks/webhook.service'; import * as WorkflowExecuteAdditionalData from '@/workflow-execute-additional-data'; diff --git a/packages/cli/src/chat/__tests__/chat-execution-manager.test.ts b/packages/cli/src/chat/__tests__/chat-execution-manager.test.ts index cc1695c277c..7b54811bccb 100644 --- a/packages/cli/src/chat/__tests__/chat-execution-manager.test.ts +++ b/packages/cli/src/chat/__tests__/chat-execution-manager.test.ts @@ -17,7 +17,7 @@ import * as WorkflowExecuteAdditionalData from '@/workflow-execute-additional-da import { WorkflowRunner } from '@/workflow-runner'; import { NodeTypes } from '../../node-types'; -import { OwnershipService } from '../../services/ownership.service'; +import { OwnershipService } from '@n8n/backend-services'; import { ChatExecutionManager } from '../chat-execution-manager'; import type { ChatMessage } from '../chat-service.types'; diff --git a/packages/cli/src/chat/chat-execution-manager.ts b/packages/cli/src/chat/chat-execution-manager.ts index 86f88a30acd..3eb4d4f80a1 100644 --- a/packages/cli/src/chat/chat-execution-manager.ts +++ b/packages/cli/src/chat/chat-execution-manager.ts @@ -25,7 +25,7 @@ import { WorkflowRunner } from '../workflow-runner'; import type { ChatMessage } from './chat-service.types'; import { findResumeNode, redirectIfToolExecutor } from './utils'; import { NodeTypes } from '../node-types'; -import { OwnershipService } from '../services/ownership.service'; +import { OwnershipService } from '@n8n/backend-services'; import { stripToolSuffix } from '../utils'; @Service() diff --git a/packages/cli/src/commands/__tests__/execute-batch.test.ts b/packages/cli/src/commands/__tests__/execute-batch.test.ts index 22e11bfe4c5..29e4d2dd0b3 100644 --- a/packages/cli/src/commands/__tests__/execute-batch.test.ts +++ b/packages/cli/src/commands/__tests__/execute-batch.test.ts @@ -26,7 +26,7 @@ import { License } from '@/license'; import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials'; import { CommunityPackagesService } from '@/modules/community-packages/community-packages.service'; import { PostHogClient } from '@/posthog'; -import { OwnershipService } from '@/services/ownership.service'; +import { OwnershipService } from '@n8n/backend-services'; import { ShutdownService } from '@/shutdown/shutdown.service'; import { TaskRunnerModule } from '@/task-runners/task-runner-module'; import { WorkflowRunner } from '@/workflow-runner'; diff --git a/packages/cli/src/commands/__tests__/execute.test.ts b/packages/cli/src/commands/__tests__/execute.test.ts index 72d61484526..c7443e73ebc 100644 --- a/packages/cli/src/commands/__tests__/execute.test.ts +++ b/packages/cli/src/commands/__tests__/execute.test.ts @@ -28,7 +28,7 @@ import { License } from '@/license'; import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials'; import { CommunityPackagesService } from '@/modules/community-packages/community-packages.service'; import { PostHogClient } from '@/posthog'; -import { OwnershipService } from '@/services/ownership.service'; +import { OwnershipService } from '@n8n/backend-services'; import { ShutdownService } from '@/shutdown/shutdown.service'; import { TaskRunnerModule } from '@/task-runners/task-runner-module'; import { WorkflowRunner } from '@/workflow-runner'; diff --git a/packages/cli/src/commands/execute-batch.ts b/packages/cli/src/commands/execute-batch.ts index 0eaaf0dda2f..69a796d3f22 100644 --- a/packages/cli/src/commands/execute-batch.ts +++ b/packages/cli/src/commands/execute-batch.ts @@ -12,7 +12,7 @@ import { sep } from 'path'; import { z } from 'zod'; import { ActiveExecutions } from '@/active-executions'; -import { OwnershipService } from '@/services/ownership.service'; +import { OwnershipService } from '@n8n/backend-services'; import { findCliWorkflowStart } from '@/utils'; import { WorkflowRunner } from '@/workflow-runner'; diff --git a/packages/cli/src/commands/execute.ts b/packages/cli/src/commands/execute.ts index db51dddc440..1866d6ca5d5 100644 --- a/packages/cli/src/commands/execute.ts +++ b/packages/cli/src/commands/execute.ts @@ -1,4 +1,4 @@ -import { EventService } from '@n8n/backend-services'; +import { EventService, OwnershipService } from '@n8n/backend-services'; import { WorkflowRepository } from '@n8n/db'; import { Command } from '@n8n/decorators'; import { Container } from '@n8n/di'; @@ -7,7 +7,6 @@ import { ExecutionBaseError, UnexpectedError, UserError } from 'n8n-workflow'; import { z } from 'zod'; import { ActiveExecutions } from '@/active-executions'; -import { OwnershipService } from '@/services/ownership.service'; import { findCliWorkflowStart, isWorkflowIdValid } from '@/utils'; import { WorkflowRunner } from '@/workflow-runner'; import { getWorkflowProjectDetailsSafe } from '@/workflows/utils'; diff --git a/packages/cli/src/controllers/__tests__/owner.controller.test.ts b/packages/cli/src/controllers/__tests__/owner.controller.test.ts index 309499b4e60..6c20b19eb19 100644 --- a/packages/cli/src/controllers/__tests__/owner.controller.test.ts +++ b/packages/cli/src/controllers/__tests__/owner.controller.test.ts @@ -6,14 +6,14 @@ import { OwnerController } from '@/controllers/owner.controller'; import { BadRequestError } from '@n8n/errors'; import type { PostHogClient } from '@/posthog'; import type { BannerService } from '@/services/banner.service'; -import type { OwnershipService } from '@/services/ownership.service'; +import type { OwnerSetupService } from '@/services/owner-setup.service'; import type { UserService } from '@/services/user.service'; describe('OwnerController', () => { const authService = mock(); const bannerService = mock(); const userService = mock(); - const ownershipService = mock(); + const ownerSetupService = mock(); const postHogClient = mock(); const controller = new OwnerController( @@ -21,12 +21,12 @@ describe('OwnerController', () => { bannerService, userService, postHogClient, - ownershipService, + ownerSetupService, ); describe('setupOwner', () => { it('should pass on errors from the service', async () => { - ownershipService.setupOwner.mockRejectedValueOnce( + ownerSetupService.setupOwner.mockRejectedValueOnce( new BadRequestError('Instance owner already setup'), ); diff --git a/packages/cli/src/controllers/owner.controller.ts b/packages/cli/src/controllers/owner.controller.ts index 7bf98ff7d90..0cf305d44e2 100644 --- a/packages/cli/src/controllers/owner.controller.ts +++ b/packages/cli/src/controllers/owner.controller.ts @@ -6,8 +6,8 @@ import { Response } from 'express'; import { AuthService } from '@/auth/auth.service'; import { PostHogClient } from '@/posthog'; import { BannerService } from '@/services/banner.service'; -import { OwnershipService } from '@/services/ownership.service'; import { UserService } from '@/services/user.service'; +import { OwnerSetupService } from '@/services/owner-setup.service'; @RestController('/owner') export class OwnerController { @@ -16,7 +16,7 @@ export class OwnerController { private readonly bannerService: BannerService, private readonly userService: UserService, private readonly postHog: PostHogClient, - private readonly ownershipService: OwnershipService, + private readonly ownerSetupService: OwnerSetupService, ) {} /** @@ -24,7 +24,7 @@ export class OwnerController { */ @Post('/setup', { skipAuth: true }) async setupOwner(req: AuthenticatedRequest, res: Response, @Body payload: OwnerSetupRequestDto) { - const owner = await this.ownershipService.setupOwner(payload); + const owner = await this.ownerSetupService.setupOwner(payload); this.authService.issueCookie(res, owner, req.authInfo?.usedMfa ?? false, req.browserId); return await this.userService.toPublic(owner, { posthog: this.postHog, withScopes: true }); } diff --git a/packages/cli/src/credentials/__tests__/credentials.service.ee.test.ts b/packages/cli/src/credentials/__tests__/credentials.service.ee.test.ts index e48136b906c..8269ba7fc70 100644 --- a/packages/cli/src/credentials/__tests__/credentials.service.ee.test.ts +++ b/packages/cli/src/credentials/__tests__/credentials.service.ee.test.ts @@ -9,13 +9,16 @@ import type { import { mock } from 'vitest-mock-extended'; import type { CredentialConnectionStatusProxy } from '@/credentials/credential-connection-status-proxy'; -import { type CredentialsFinderService, type RoleService } from '@n8n/backend-services'; +import type { + CredentialsFinderService, + RoleService, + OwnershipService, +} from '@n8n/backend-services'; import type { CredentialsService } from '@/credentials/credentials.service'; import { EnterpriseCredentialsService } from '@/credentials/credentials.service.ee'; import type { ExternalSecretsConfig } from '@/modules/external-secrets.ee/external-secrets.config'; import type { SecretsProviderAccessCheckService } from '@/modules/external-secrets.ee/secret-provider-access-check.service.ee'; import type { PolicyEnforcementService } from '@/policy/policy-enforcement.service'; -import type { OwnershipService } from '@/services/ownership.service'; import type { ProjectService } from '@/services/project.service.ee'; describe('EnterpriseCredentialsService', () => { diff --git a/packages/cli/src/credentials/__tests__/credentials.service.test.ts b/packages/cli/src/credentials/__tests__/credentials.service.test.ts index 378b6421f63..e4120a948ea 100644 --- a/packages/cli/src/credentials/__tests__/credentials.service.test.ts +++ b/packages/cli/src/credentials/__tests__/credentials.service.test.ts @@ -2,10 +2,11 @@ import { CredentialDescriptionsService } from '@/credentials/credential-descript import type { PostHogClient } from '@/posthog'; import { CREDENTIAL_DESCRIPTION_MAX_LENGTH } from '@n8n/api-types'; import type { Logger } from '@n8n/backend-common'; -import { - type EventService, - type RoleService, - type CredentialsFinderService, +import type { + EventService, + RoleService, + CredentialsFinderService, + OwnershipService, } from '@n8n/backend-services'; import type { CredentialsRepository, @@ -66,7 +67,6 @@ import { } from '@/oauth/dcr-managed-fields'; import * as checkAccess from '@/permissions.ee/check-access'; import type { CredentialsTester } from '@/services/credentials-tester.service'; -import type { OwnershipService } from '@/services/ownership.service'; import type { ProjectService } from '@/services/project.service.ee'; import { mockExistingCredential } from './credentials.test-data'; diff --git a/packages/cli/src/credentials/credentials.service.ee.ts b/packages/cli/src/credentials/credentials.service.ee.ts index f76d95b9028..f3e8f45675a 100644 --- a/packages/cli/src/credentials/credentials.service.ee.ts +++ b/packages/cli/src/credentials/credentials.service.ee.ts @@ -17,9 +17,8 @@ import { TransferCredentialError } from '@/errors/response-errors/transfer-crede import { ExternalSecretsConfig } from '@/modules/external-secrets.ee/external-secrets.config'; import { SecretsProviderAccessCheckService } from '@/modules/external-secrets.ee/secret-provider-access-check.service.ee'; import { PolicyEnforcementService } from '@/policy/policy-enforcement.service'; -import { OwnershipService } from '@/services/ownership.service'; +import { OwnershipService, RoleService, CredentialsFinderService } from '@n8n/backend-services'; import { ProjectService } from '@/services/project.service.ee'; -import { RoleService, CredentialsFinderService } from '@n8n/backend-services'; import { CredentialConnectionStatusProxy } from './credential-connection-status-proxy'; import { CredentialsService } from './credentials.service'; diff --git a/packages/cli/src/credentials/credentials.service.ts b/packages/cli/src/credentials/credentials.service.ts index fc83809a0ce..b24a10f90f0 100644 --- a/packages/cli/src/credentials/credentials.service.ts +++ b/packages/cli/src/credentials/credentials.service.ts @@ -1,6 +1,11 @@ import type { CreateCredentialDto, CredentialConnectionStatus } from '@n8n/api-types'; import { Logger } from '@n8n/backend-common'; -import { EventService, RoleService, CredentialsFinderService } from '@n8n/backend-services'; +import { + EventService, + RoleService, + CredentialsFinderService, + OwnershipService, +} from '@n8n/backend-services'; import { Time } from '@n8n/constants'; import { Project, @@ -74,7 +79,6 @@ import type { PolicyActor } from '@/policy/policy-enforcement-backend'; import { PolicyEnforcementService } from '@/policy/policy-enforcement.service'; import type { CredentialRequest, ListQuery } from '@/requests'; import { CredentialsTester } from '@/services/credentials-tester.service'; -import { OwnershipService } from '@/services/ownership.service'; import { ProjectService } from '@/services/project.service.ee'; import { CredentialConnectionStatusProxy } from './credential-connection-status-proxy'; diff --git a/packages/cli/src/evaluation.ee/test-runner/__tests__/test-runner.service.ee.test.ts b/packages/cli/src/evaluation.ee/test-runner/__tests__/test-runner.service.ee.test.ts index 7f869f1eea0..f545aafe717 100644 --- a/packages/cli/src/evaluation.ee/test-runner/__tests__/test-runner.service.ee.test.ts +++ b/packages/cli/src/evaluation.ee/test-runner/__tests__/test-runner.service.ee.test.ts @@ -29,7 +29,7 @@ import { TestRunError } from '@/evaluation.ee/test-runner/errors.ee'; import type { License } from '@/license'; import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials'; import type { Publisher } from '@/scaling/pubsub/publisher.service'; -import type { OwnershipService } from '@/services/ownership.service'; +import type { OwnershipService } from '@n8n/backend-services'; import type { Telemetry } from '@/telemetry'; import type { WorkflowRunner } from '@/workflow-runner'; import type { WorkflowHistoryService } from '@/workflows/workflow-history/workflow-history.service'; diff --git a/packages/cli/src/evaluation.ee/test-runner/test-runner.service.ee.ts b/packages/cli/src/evaluation.ee/test-runner/test-runner.service.ee.ts index 281582f819d..0fad3791372 100644 --- a/packages/cli/src/evaluation.ee/test-runner/test-runner.service.ee.ts +++ b/packages/cli/src/evaluation.ee/test-runner/test-runner.service.ee.ts @@ -1,5 +1,5 @@ import { Logger } from '@n8n/backend-common'; -import { EventService } from '@n8n/backend-services'; +import { EventService, OwnershipService } from '@n8n/backend-services'; import { ExecutionsConfig } from '@n8n/config'; import type { EvaluationConfig, User } from '@n8n/db'; import { @@ -52,7 +52,6 @@ import { } from '@/evaluation.ee/test-runner/utils.ee'; import { License } from '@/license'; import { Publisher } from '@/scaling/pubsub/publisher.service'; -import { OwnershipService } from '@/services/ownership.service'; import { Telemetry } from '@/telemetry'; import { WorkflowRunner } from '@/workflow-runner'; import { getWorkflowProjectDetailsSafe } from '@/workflows/utils'; diff --git a/packages/cli/src/events/__tests__/telemetry-event-relay.test.ts b/packages/cli/src/events/__tests__/telemetry-event-relay.test.ts index e5714be9b72..d13d363b732 100644 --- a/packages/cli/src/events/__tests__/telemetry-event-relay.test.ts +++ b/packages/cli/src/events/__tests__/telemetry-event-relay.test.ts @@ -1,5 +1,5 @@ import type { LicenseState } from '@n8n/backend-common'; -import { EventService } from '@n8n/backend-services'; +import { EventService, type OwnershipService } from '@n8n/backend-services'; import { mockInstance } from '@n8n/backend-test-utils'; import { EMPTY_CANVAS_GROUPS_FLAG } from '@n8n/api-types'; import type { GlobalConfig } from '@n8n/config'; @@ -41,7 +41,6 @@ import { OtelConfig } from '@/modules/otel/otel.config'; import type { PolicyRule } from '@/modules/type-availability-policies/policy-rule.types'; import type { NodeTypes } from '@/node-types'; import type { PostHogClient } from '@/posthog'; -import type { OwnershipService } from '@/services/ownership.service'; import type { Telemetry } from '@/telemetry'; const flushPromises = async () => await new Promise((resolve) => setImmediate(resolve)); diff --git a/packages/cli/src/events/relays/telemetry.event-relay.ts b/packages/cli/src/events/relays/telemetry.event-relay.ts index 56d09e16101..7a903066743 100644 --- a/packages/cli/src/events/relays/telemetry.event-relay.ts +++ b/packages/cli/src/events/relays/telemetry.event-relay.ts @@ -1,6 +1,6 @@ import { EMPTY_CANVAS_GROUPS_FLAG } from '@n8n/api-types'; import { LicenseState } from '@n8n/backend-common'; -import { EventService } from '@n8n/backend-services'; +import { EventService, OwnershipService } from '@n8n/backend-services'; import { GlobalConfig } from '@n8n/config'; import { CredentialsRepository, @@ -59,7 +59,6 @@ import type { } from '@/modules/type-availability-policies/policy-rule.types'; import { NodeTypes } from '@/node-types'; import { PostHogClient } from '@/posthog'; -import { OwnershipService } from '@/services/ownership.service'; import { EventRelay } from './event-relay'; import { Telemetry } from '../../telemetry'; diff --git a/packages/cli/src/execution-lifecycle/__tests__/execute-error-workflow.test.ts b/packages/cli/src/execution-lifecycle/__tests__/execute-error-workflow.test.ts index 77b9beaccb6..1192e2b75c0 100644 --- a/packages/cli/src/execution-lifecycle/__tests__/execute-error-workflow.test.ts +++ b/packages/cli/src/execution-lifecycle/__tests__/execute-error-workflow.test.ts @@ -8,8 +8,7 @@ import { createRunExecutionData, NodeOperationError } from 'n8n-workflow'; import { mock } from 'vitest-mock-extended'; import { PolicyViolationError } from '@/policy/policy-violation.error'; -import { OwnershipService } from '@/services/ownership.service'; -import { UrlService } from '@n8n/backend-services'; +import { OwnershipService, UrlService } from '@n8n/backend-services'; import { WorkflowExecutionService } from '@/workflows/workflow-execution.service'; import { executeErrorWorkflow } from '../execute-error-workflow'; diff --git a/packages/cli/src/execution-lifecycle/__tests__/execution-lifecycle-hooks.test.ts b/packages/cli/src/execution-lifecycle/__tests__/execution-lifecycle-hooks.test.ts index 4c69981bdf5..d0d48ed1b95 100644 --- a/packages/cli/src/execution-lifecycle/__tests__/execution-lifecycle-hooks.test.ts +++ b/packages/cli/src/execution-lifecycle/__tests__/execution-lifecycle-hooks.test.ts @@ -1,6 +1,6 @@ import type { PushMessage } from '@n8n/api-types'; import { Logger } from '@n8n/backend-common'; -import { EventService } from '@n8n/backend-services'; +import { EventService, OwnershipService } from '@n8n/backend-services'; import { mockInstance } from '@n8n/backend-test-utils'; import { ExecutionsConfig } from '@n8n/config'; import type { Project, User } from '@n8n/db'; @@ -42,7 +42,6 @@ import { ExecutionRedactionServiceProxy } from '@/executions/execution-redaction import { ExternalHooks } from '@/external-hooks'; import { Push } from '@/push'; import { ExecutionMetadataService } from '@/services/execution-metadata.service'; -import { OwnershipService } from '@/services/ownership.service'; import { WorkflowStatisticsService } from '@/services/workflow-statistics.service'; import { WorkflowHookContextService } from '@/workflow-hook-context.service'; import { WorkflowExecutionService } from '@/workflows/workflow-execution.service'; diff --git a/packages/cli/src/execution-lifecycle/execute-error-workflow.ts b/packages/cli/src/execution-lifecycle/execute-error-workflow.ts index 1f60e08adb2..762a33e9547 100644 --- a/packages/cli/src/execution-lifecycle/execute-error-workflow.ts +++ b/packages/cli/src/execution-lifecycle/execute-error-workflow.ts @@ -7,8 +7,7 @@ import { toErrorWorkflowContext } from 'n8n-workflow'; import type { IWorkflowErrorData } from '@/interfaces'; import { isPolicyRefusal } from '@/policy/policy-violation.error'; -import { OwnershipService } from '@/services/ownership.service'; -import { UrlService } from '@n8n/backend-services'; +import { OwnershipService, UrlService } from '@n8n/backend-services'; /** * Resolved lazily. A static import would close the cycle diff --git a/packages/cli/src/executions/__tests__/enqueued-execution-recovery.service.test.ts b/packages/cli/src/executions/__tests__/enqueued-execution-recovery.service.test.ts index 70b73e2b52f..63d5445b5c7 100644 --- a/packages/cli/src/executions/__tests__/enqueued-execution-recovery.service.test.ts +++ b/packages/cli/src/executions/__tests__/enqueued-execution-recovery.service.test.ts @@ -1,4 +1,4 @@ -import type { EventService } from '@n8n/backend-services'; +import type { EventService, OwnershipService } from '@n8n/backend-services'; import { mockLogger } from '@n8n/backend-test-utils'; import type { ExecutionsConfig } from '@n8n/config'; import type { IExecutionResponse, Project } from '@n8n/db'; @@ -9,7 +9,6 @@ import { ExecutionAlreadyResumingError } from '@/errors/execution-already-resumi import { EnqueuedExecutionRecoveryService } from '@/executions/enqueued-execution-recovery.service'; import type { ExecutionCrashService } from '@/executions/execution-crash.service'; import type { ExecutionService } from '@/executions/execution.service'; -import type { OwnershipService } from '@/services/ownership.service'; import type { WorkflowPublisherService } from '@/workflows/workflow-publisher.service'; import type { WorkflowRunner } from '@/workflow-runner'; diff --git a/packages/cli/src/executions/__tests__/execution-recovery.service.integration.test.ts b/packages/cli/src/executions/__tests__/execution-recovery.service.integration.test.ts index fff6f0d13b3..17e56b96e9f 100644 --- a/packages/cli/src/executions/__tests__/execution-recovery.service.integration.test.ts +++ b/packages/cli/src/executions/__tests__/execution-recovery.service.integration.test.ts @@ -34,11 +34,9 @@ import { ExecutionPersistence } from '@/executions/execution-persistence'; import { ExecutionRecoveryService } from '@/executions/execution-recovery.service'; import { ExternalHooks } from '@/external-hooks'; import { Push } from '@/push'; -import { OwnershipService } from '@/services/ownership.service'; +import { OwnershipService, type EventService, WorkflowSharingService } from '@n8n/backend-services'; import { WorkflowPublicationNotifier } from '@/workflows/publication/workflow-publication-notifier'; import { WorkflowPushNotifier } from '@/workflows/workflow-push-notifier.service'; -import type { EventService } from '@n8n/backend-services'; -import { WorkflowSharingService } from '@n8n/backend-services'; import { createExecution } from '@test-integration/db/executions'; import { IN_PROGRESS_EXECUTION_DATA, OOM_WORKFLOW } from './constants'; diff --git a/packages/cli/src/executions/__tests__/execution.service.test.ts b/packages/cli/src/executions/__tests__/execution.service.test.ts index f5ba9c7acf4..4178a4c9b06 100644 --- a/packages/cli/src/executions/__tests__/execution.service.test.ts +++ b/packages/cli/src/executions/__tests__/execution.service.test.ts @@ -1,5 +1,5 @@ import { DeleteExecutionsDto } from '@n8n/api-types'; -import type { EventService } from '@n8n/backend-services'; +import type { EventService, OwnershipService } from '@n8n/backend-services'; import { mockInstance } from '@n8n/backend-test-utils'; import { GlobalConfig } from '@n8n/config'; import type { @@ -33,7 +33,6 @@ import type { ExecutionRequest } from '@/executions/execution.types'; import type { ExecutionStopService } from '@/scaling/execution-stop.service'; import { ScalingService } from '@/scaling/scaling.service'; import type { Job } from '@/scaling/scaling.types'; -import type { OwnershipService } from '@/services/ownership.service'; import type { EngineDataPlaneProxyService } from '@/services/engine-data-plane-proxy.service'; import type { WaitTracker } from '@/wait-tracker'; import type { WorkflowRunner } from '@/workflow-runner'; diff --git a/packages/cli/src/executions/enqueued-execution-recovery.service.ts b/packages/cli/src/executions/enqueued-execution-recovery.service.ts index 94bc812976b..c2ea22835b6 100644 --- a/packages/cli/src/executions/enqueued-execution-recovery.service.ts +++ b/packages/cli/src/executions/enqueued-execution-recovery.service.ts @@ -1,5 +1,5 @@ import { Logger } from '@n8n/backend-common'; -import { EventService } from '@n8n/backend-services'; +import { EventService, OwnershipService } from '@n8n/backend-services'; import { ExecutionsConfig } from '@n8n/config'; import { Service } from '@n8n/di'; import { ErrorReporter } from 'n8n-core'; @@ -9,7 +9,6 @@ import { strict as assert } from 'node:assert'; import { ExecutionAlreadyResumingError } from '@/errors/execution-already-resuming.error'; import { ExecutionCrashService } from '@/executions/execution-crash.service'; import { ExecutionService } from '@/executions/execution.service'; -import { OwnershipService } from '@/services/ownership.service'; import { WorkflowPublisherService } from '@/workflows/workflow-publisher.service'; import { WorkflowRunner } from '@/workflow-runner'; diff --git a/packages/cli/src/executions/execution-recovery.service.ts b/packages/cli/src/executions/execution-recovery.service.ts index 2c0b80319a2..8af228305fb 100644 --- a/packages/cli/src/executions/execution-recovery.service.ts +++ b/packages/cli/src/executions/execution-recovery.service.ts @@ -24,7 +24,7 @@ import { getLifecycleHooksForRegularMain } from '@/execution-lifecycle/execution import { ExecutionCrashService } from '@/executions/execution-crash.service'; import { ExecutionPersistence } from '@/executions/execution-persistence'; import { Push } from '@/push'; -import { OwnershipService } from '@/services/ownership.service'; +import { OwnershipService } from '@n8n/backend-services'; import { UserManagementMailer } from '@/user-management/email/user-management-mailer'; import { WorkflowPushNotifier } from '@/workflows/workflow-push-notifier.service'; diff --git a/packages/cli/src/executions/execution.service.ts b/packages/cli/src/executions/execution.service.ts index f41715faac1..6f097cf33d5 100644 --- a/packages/cli/src/executions/execution.service.ts +++ b/packages/cli/src/executions/execution.service.ts @@ -1,7 +1,7 @@ import type { DeleteExecutionsDto } from '@n8n/api-types'; import { ExecutionRedactionQueryDtoSchema } from '@n8n/api-types'; import { Logger } from '@n8n/backend-common'; -import { EventService } from '@n8n/backend-services'; +import { EventService, OwnershipService } from '@n8n/backend-services'; import { GlobalConfig } from '@n8n/config'; import type { CreateExecutionPayload, @@ -52,7 +52,6 @@ import { License } from '@/license'; import { NodeTypes } from '@/node-types'; import { ExecutionStopService } from '@/scaling/execution-stop.service'; import { EngineDataPlaneProxyService } from '@/services/engine-data-plane-proxy.service'; -import { OwnershipService } from '@/services/ownership.service'; import { WaitTracker } from '@/wait-tracker'; import { WorkflowRunner } from '@/workflow-runner'; import { getWorkflowProjectDetailsSafe } from '@/workflows/utils'; diff --git a/packages/cli/src/executions/pre-execution-checks/__tests__/credentials-permission-checker.test.ts b/packages/cli/src/executions/pre-execution-checks/__tests__/credentials-permission-checker.test.ts index 8d1e382398f..c3b75251b20 100644 --- a/packages/cli/src/executions/pre-execution-checks/__tests__/credentials-permission-checker.test.ts +++ b/packages/cli/src/executions/pre-execution-checks/__tests__/credentials-permission-checker.test.ts @@ -14,9 +14,8 @@ import { mock } from 'vitest-mock-extended'; import type { Logger } from '@n8n/backend-common'; -import type { CredentialsFinderService } from '@n8n/backend-services'; +import type { CredentialsFinderService, OwnershipService } from '@n8n/backend-services'; import type { NodeTypes } from '@/node-types'; -import type { OwnershipService } from '@/services/ownership.service'; import type { ProjectService } from '@/services/project.service.ee'; import { CredentialsPermissionChecker } from '../credentials-permission-checker'; diff --git a/packages/cli/src/executions/pre-execution-checks/__tests__/subworkflow-policy-checker.test.ts b/packages/cli/src/executions/pre-execution-checks/__tests__/subworkflow-policy-checker.test.ts index ea65b100dec..ab1c0733858 100644 --- a/packages/cli/src/executions/pre-execution-checks/__tests__/subworkflow-policy-checker.test.ts +++ b/packages/cli/src/executions/pre-execution-checks/__tests__/subworkflow-policy-checker.test.ts @@ -11,8 +11,7 @@ import { SubworkflowPolicyDenialError, } from '@/errors/subworkflow-policy-denial.error'; import type { AccessService } from '@/services/access.service'; -import { OwnershipService } from '@/services/ownership.service'; -import type { UrlService } from '@n8n/backend-services'; +import { OwnershipService, type UrlService } from '@n8n/backend-services'; import { SubworkflowPolicyChecker } from '../subworkflow-policy-checker'; diff --git a/packages/cli/src/executions/pre-execution-checks/credentials-permission-checker.ts b/packages/cli/src/executions/pre-execution-checks/credentials-permission-checker.ts index 785f6e7445e..ada8bdb55e9 100644 --- a/packages/cli/src/executions/pre-execution-checks/credentials-permission-checker.ts +++ b/packages/cli/src/executions/pre-execution-checks/credentials-permission-checker.ts @@ -7,9 +7,12 @@ import type { INode, INodeTypeDescription } from 'n8n-workflow'; import { getActiveCredentialTypes, UserError } from 'n8n-workflow'; import { isCredSharingEnabled } from '@/constants/credential-sharing'; -import { CredentialsFinderService, type UnusableCredential } from '@n8n/backend-services'; +import { + CredentialsFinderService, + type UnusableCredential, + OwnershipService, +} from '@n8n/backend-services'; import { NodeTypes } from '@/node-types'; -import { OwnershipService } from '@/services/ownership.service'; import { ProjectService } from '@/services/project.service.ee'; class InvalidCredentialError extends UserError { diff --git a/packages/cli/src/executions/pre-execution-checks/subworkflow-policy-checker.ts b/packages/cli/src/executions/pre-execution-checks/subworkflow-policy-checker.ts index 0a0e9b434bf..f125e74ab43 100644 --- a/packages/cli/src/executions/pre-execution-checks/subworkflow-policy-checker.ts +++ b/packages/cli/src/executions/pre-execution-checks/subworkflow-policy-checker.ts @@ -6,8 +6,7 @@ import { type INode, type IWorkflowBase, type WorkflowSettings } from 'n8n-workf import { SubworkflowPolicyDenialError } from '@/errors/subworkflow-policy-denial.error'; import { AccessService } from '@/services/access.service'; -import { OwnershipService } from '@/services/ownership.service'; -import { UrlService } from '@n8n/backend-services'; +import { OwnershipService, UrlService } from '@n8n/backend-services'; type Policy = WorkflowSettings.CallerPolicy; type DenialPolicy = Exclude; diff --git a/packages/cli/src/instance-settings-loader/__tests__/owner.instance-settings-loader.test.ts b/packages/cli/src/instance-settings-loader/__tests__/owner.instance-settings-loader.test.ts index e2afb452a45..2e3519dc52a 100644 --- a/packages/cli/src/instance-settings-loader/__tests__/owner.instance-settings-loader.test.ts +++ b/packages/cli/src/instance-settings-loader/__tests__/owner.instance-settings-loader.test.ts @@ -2,13 +2,13 @@ import type { Logger } from '@n8n/backend-common'; import type { InstanceSettingsLoaderConfig } from '@n8n/config'; import { mock } from 'vitest-mock-extended'; -import type { OwnershipService } from '@/services/ownership.service'; +import type { OwnerSetupService } from '@/services/owner-setup.service'; import { OwnerInstanceSettingsLoader } from '../loaders/owner.instance-settings-loader'; describe('OwnerInstanceSettingsLoader', () => { const logger = mock({ scoped: vi.fn().mockReturnThis() }); - const ownershipService = mock(); + const ownerSetupService = mock(); const validBcryptHash = '$2b$10$abcdefghijklmnopqrstuuABCDEFGHIJKLMNOPQRSTUVWXYZ01234'; @@ -22,7 +22,7 @@ describe('OwnerInstanceSettingsLoader', () => { ...configOverrides, } as InstanceSettingsLoaderConfig; - return new OwnerInstanceSettingsLoader(config, ownershipService, logger); + return new OwnerInstanceSettingsLoader(config, ownerSetupService, logger); }; beforeEach(() => { @@ -37,7 +37,7 @@ describe('OwnerInstanceSettingsLoader', () => { const result = await loader.run(); expect(result).toBe('skipped'); - expect(ownershipService.setupOwner).not.toHaveBeenCalled(); + expect(ownerSetupService.setupOwner).not.toHaveBeenCalled(); expect(logger.warn).not.toHaveBeenCalled(); }); @@ -47,7 +47,7 @@ describe('OwnerInstanceSettingsLoader', () => { const result = await loader.run(); expect(result).toBe('skipped'); - expect(ownershipService.setupOwner).not.toHaveBeenCalled(); + expect(ownerSetupService.setupOwner).not.toHaveBeenCalled(); }); it('should skip when ownerPasswordHash is set', async () => { @@ -56,7 +56,7 @@ describe('OwnerInstanceSettingsLoader', () => { const result = await loader.run(); expect(result).toBe('skipped'); - expect(ownershipService.setupOwner).not.toHaveBeenCalled(); + expect(ownerSetupService.setupOwner).not.toHaveBeenCalled(); }); it('should skip when both email and password are set', async () => { @@ -68,7 +68,7 @@ describe('OwnerInstanceSettingsLoader', () => { const result = await loader.run(); expect(result).toBe('skipped'); - expect(ownershipService.setupOwner).not.toHaveBeenCalled(); + expect(ownerSetupService.setupOwner).not.toHaveBeenCalled(); }); }); @@ -116,7 +116,7 @@ describe('OwnerInstanceSettingsLoader', () => { expect(logger.info).toHaveBeenCalledWith( expect.stringContaining('N8N_INSTANCE_OWNER_MANAGED_BY_ENV is enabled'), ); - expect(ownershipService.setupOwner).toHaveBeenCalledWith( + expect(ownerSetupService.setupOwner).toHaveBeenCalledWith( { email: 'admin@example.com', firstName: 'Jane', @@ -128,8 +128,6 @@ describe('OwnerInstanceSettingsLoader', () => { }); it('should overwrite existing owner', async () => { - ownershipService.hasInstanceOwner.mockResolvedValue(true); - const loader = createLoader({ ownerManagedByEnv: true, ownerEmail: 'new@example.com', @@ -141,7 +139,7 @@ describe('OwnerInstanceSettingsLoader', () => { const result = await loader.run(); expect(result).toBe('created'); - expect(ownershipService.setupOwner).toHaveBeenCalledWith( + expect(ownerSetupService.setupOwner).toHaveBeenCalledWith( { email: 'new@example.com', firstName: 'New', diff --git a/packages/cli/src/instance-settings-loader/loaders/owner.instance-settings-loader.ts b/packages/cli/src/instance-settings-loader/loaders/owner.instance-settings-loader.ts index a14d5ad1b8e..a63215e0ec2 100644 --- a/packages/cli/src/instance-settings-loader/loaders/owner.instance-settings-loader.ts +++ b/packages/cli/src/instance-settings-loader/loaders/owner.instance-settings-loader.ts @@ -3,7 +3,7 @@ import { InstanceSettingsLoaderConfig } from '@n8n/config'; import { Service } from '@n8n/di'; import { z } from 'zod'; -import { OwnershipService } from '@/services/ownership.service'; +import { OwnerSetupService } from '@/services/owner-setup.service'; import { InstanceBootstrappingError } from '../instance-bootstrapping.error'; @@ -45,7 +45,7 @@ const ownerEnvSchema = z export class OwnerInstanceSettingsLoader { constructor( private readonly instanceSettingsLoaderConfig: InstanceSettingsLoaderConfig, - private readonly ownershipService: OwnershipService, + private readonly ownerSetupService: OwnerSetupService, private logger: Logger, ) { this.logger = this.logger.scoped('instance-settings-loader'); @@ -67,7 +67,7 @@ export class OwnerInstanceSettingsLoader { throw new InstanceBootstrappingError(result.error.issues[0].message); } - await this.ownershipService.setupOwner(result.data.payload, result.data.options); + await this.ownerSetupService.setupOwner(result.data.payload, result.data.options); return 'created'; } diff --git a/packages/cli/src/modules/data-table/__tests__/data-table-proxy.service.integration.test.ts b/packages/cli/src/modules/data-table/__tests__/data-table-proxy.service.integration.test.ts index 107420f6a4b..dfccf5b4c1d 100644 --- a/packages/cli/src/modules/data-table/__tests__/data-table-proxy.service.integration.test.ts +++ b/packages/cli/src/modules/data-table/__tests__/data-table-proxy.service.integration.test.ts @@ -15,9 +15,8 @@ import { NodeOperationError } from 'n8n-workflow'; import type { MockInstance } from 'vitest'; import { mock } from 'vitest-mock-extended'; -import type { InstanceWriteAccessService } from '@n8n/backend-services'; +import type { InstanceWriteAccessService, OwnershipService } from '@n8n/backend-services'; import * as checkAccess from '@/permissions.ee/check-access'; -import type { OwnershipService } from '@/services/ownership.service'; import type { DataTableAggregateService } from '../data-table-aggregate.service'; import { DataTableProxyService } from '../data-table-proxy.service'; diff --git a/packages/cli/src/modules/data-table/data-table-proxy.service.ts b/packages/cli/src/modules/data-table/data-table-proxy.service.ts index ead81265e90..b7259abaf9e 100644 --- a/packages/cli/src/modules/data-table/data-table-proxy.service.ts +++ b/packages/cli/src/modules/data-table/data-table-proxy.service.ts @@ -27,8 +27,7 @@ import { import { ForbiddenError } from '@n8n/errors'; import { userHasScopes } from '@/permissions.ee/check-access'; -import { InstanceWriteAccessService } from '@n8n/backend-services'; -import { OwnershipService } from '@/services/ownership.service'; +import { InstanceWriteAccessService, OwnershipService } from '@n8n/backend-services'; import { DataTableAggregateService } from './data-table-aggregate.service'; import { DataTableService } from './data-table.service'; diff --git a/packages/cli/src/modules/instance-ai/eval/__tests__/execution.service.test.ts b/packages/cli/src/modules/instance-ai/eval/__tests__/execution.service.test.ts index a0ad1d8685d..86927391c3a 100644 --- a/packages/cli/src/modules/instance-ai/eval/__tests__/execution.service.test.ts +++ b/packages/cli/src/modules/instance-ai/eval/__tests__/execution.service.test.ts @@ -20,7 +20,7 @@ import type { NodeTypes } from '@/node-types'; import type { PostHogClient } from '@/posthog'; import type { DataTableService } from '@/modules/data-table/data-table.service'; import type { WorkflowRunner } from '@/workflow-runner'; -import type { OwnershipService } from '@/services/ownership.service'; +import type { OwnershipService } from '@n8n/backend-services'; import type { WorkflowFinderService } from '@/workflows/workflow-finder.service'; import type { WorkflowStaticDataService } from '@/workflows/workflow-static-data.service'; diff --git a/packages/cli/src/modules/instance-ai/eval/execution.service.ts b/packages/cli/src/modules/instance-ai/eval/execution.service.ts index 00009b3b14a..8e463cbf99d 100644 --- a/packages/cli/src/modules/instance-ai/eval/execution.service.ts +++ b/packages/cli/src/modules/instance-ai/eval/execution.service.ts @@ -49,7 +49,7 @@ import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials'; import { DataTableService } from '@/modules/data-table/data-table.service'; import { NodeTypes } from '@/node-types'; import { PostHogClient } from '@/posthog'; -import { OwnershipService } from '@/services/ownership.service'; +import { OwnershipService } from '@n8n/backend-services'; import { WorkflowRunner } from '@/workflow-runner'; import { WorkflowFinderService } from '@/workflows/workflow-finder.service'; import { WorkflowStaticDataService } from '@/workflows/workflow-static-data.service'; diff --git a/packages/cli/src/modules/otel/__tests__/otel-lifecycle-handler.test.ts b/packages/cli/src/modules/otel/__tests__/otel-lifecycle-handler.test.ts index b77a5548d08..8bae668a2a5 100644 --- a/packages/cli/src/modules/otel/__tests__/otel-lifecycle-handler.test.ts +++ b/packages/cli/src/modules/otel/__tests__/otel-lifecycle-handler.test.ts @@ -1,5 +1,5 @@ import type { LicenseState, Logger } from '@n8n/backend-common'; -import { EventService } from '@n8n/backend-services'; +import { EventService, type OwnershipService } from '@n8n/backend-services'; import type { NodeExecuteAfterContext, NodeExecuteBeforeContext, @@ -11,7 +11,6 @@ import { Workflow } from 'n8n-workflow'; import type { INodeTypes, IRun, IRunExecutionData, WorkflowExecuteMode } from 'n8n-workflow'; import type { RelayEventMap } from '@/events/maps/relay.event-map'; -import type { OwnershipService } from '@/services/ownership.service'; import type { ExecutionLevelTracer } from '../execution-level-tracer'; import { OtelLifecycleHandler, countInputItems, countOutputItems } from '../otel-lifecycle-handler'; diff --git a/packages/cli/src/modules/otel/otel-lifecycle-handler.ts b/packages/cli/src/modules/otel/otel-lifecycle-handler.ts index 3ec8f1c4029..d6b886108e8 100644 --- a/packages/cli/src/modules/otel/otel-lifecycle-handler.ts +++ b/packages/cli/src/modules/otel/otel-lifecycle-handler.ts @@ -1,5 +1,5 @@ import { LicenseState, Logger } from '@n8n/backend-common'; -import { EventService } from '@n8n/backend-services'; +import { EventService, OwnershipService } from '@n8n/backend-services'; import { OnLifecycleEvent, OnPubSubEvent } from '@n8n/decorators'; import type { WorkflowExecuteBeforeContext, @@ -18,7 +18,6 @@ import type { CustomAttributes } from './execution-level-tracer.types'; import { OtelSettingsService } from './otel-settings.service'; import { OtelService } from './otel.service'; import { TraceContextService } from './tracing-context'; -import { OwnershipService } from '../../services/ownership.service'; const isCustomTelemetryTag = (value: unknown): value is ICustomTelemetryTag => typeof value === 'object' && diff --git a/packages/cli/src/modules/policy-infrastructure/__tests__/policy-lifecycle-handler.test.ts b/packages/cli/src/modules/policy-infrastructure/__tests__/policy-lifecycle-handler.test.ts index d0be9620307..6780b3742cf 100644 --- a/packages/cli/src/modules/policy-infrastructure/__tests__/policy-lifecycle-handler.test.ts +++ b/packages/cli/src/modules/policy-infrastructure/__tests__/policy-lifecycle-handler.test.ts @@ -10,7 +10,7 @@ import { mock } from 'vitest-mock-extended'; import { PolicyEnforcementService } from '@/policy/policy-enforcement.service'; import { PolicyViolationError } from '@/policy/policy-violation.error'; -import { OwnershipService } from '@/services/ownership.service'; +import { OwnershipService } from '@n8n/backend-services'; import { PolicyCheckFailedError } from '../policy-check-failed.error'; import { PolicyDecisionService } from '../policy-decision.service'; diff --git a/packages/cli/src/modules/policy-infrastructure/policy-lifecycle-handler.ts b/packages/cli/src/modules/policy-infrastructure/policy-lifecycle-handler.ts index f48a2856108..17a068eceed 100644 --- a/packages/cli/src/modules/policy-infrastructure/policy-lifecycle-handler.ts +++ b/packages/cli/src/modules/policy-infrastructure/policy-lifecycle-handler.ts @@ -3,7 +3,7 @@ import type { WorkflowExecuteBeforeContext } from '@n8n/decorators'; import { Service } from '@n8n/di'; import { PolicyEnforcementService } from '@/policy/policy-enforcement.service'; -import { OwnershipService } from '@/services/ownership.service'; +import { OwnershipService } from '@n8n/backend-services'; /** * The execution backstop. Every way an execution starts — main, queue worker, diff --git a/packages/cli/src/modules/source-control.ee/source-control-git.service.ee.ts b/packages/cli/src/modules/source-control.ee/source-control-git.service.ee.ts index 24b6813af88..2c4f581178f 100644 --- a/packages/cli/src/modules/source-control.ee/source-control-git.service.ee.ts +++ b/packages/cli/src/modules/source-control.ee/source-control-git.service.ee.ts @@ -16,7 +16,7 @@ import type { } from 'simple-git'; import { buildHttpsGitConfig, buildSshCommand } from '@/modules/promotions.ee/promotions-git.utils'; -import { OwnershipService } from '@/services/ownership.service'; +import { OwnershipService } from '@n8n/backend-services'; import { SOURCE_CONTROL_DEFAULT_BRANCH, diff --git a/packages/cli/src/policy/__tests__/enforce-workflow-publish.test.ts b/packages/cli/src/policy/__tests__/enforce-workflow-publish.test.ts index 12d46f329b4..493846e32f8 100644 --- a/packages/cli/src/policy/__tests__/enforce-workflow-publish.test.ts +++ b/packages/cli/src/policy/__tests__/enforce-workflow-publish.test.ts @@ -1,7 +1,7 @@ import type { Project } from '@n8n/db'; import { mock } from 'vitest-mock-extended'; -import type { OwnershipService } from '@/services/ownership.service'; +import type { OwnershipService } from '@n8n/backend-services'; import { enforceWorkflowPublishPolicy } from '../enforce-workflow-publish'; import type { PolicyActor } from '../policy-enforcement-backend'; diff --git a/packages/cli/src/policy/enforce-workflow-publish.ts b/packages/cli/src/policy/enforce-workflow-publish.ts index a513a0785a3..f09cad2e5ed 100644 --- a/packages/cli/src/policy/enforce-workflow-publish.ts +++ b/packages/cli/src/policy/enforce-workflow-publish.ts @@ -1,6 +1,6 @@ import type { PolicedWorkflow } from '@n8n/decorators'; -import type { OwnershipService } from '@/services/ownership.service'; +import type { OwnershipService } from '@n8n/backend-services'; import type { PolicyActor } from './policy-enforcement-backend'; import type { PolicyEnforcementService } from './policy-enforcement.service'; diff --git a/packages/cli/src/scaling/__tests__/job-processor.service.test.ts b/packages/cli/src/scaling/__tests__/job-processor.service.test.ts index 5a90eb2f6af..b276f47900e 100644 --- a/packages/cli/src/scaling/__tests__/job-processor.service.test.ts +++ b/packages/cli/src/scaling/__tests__/job-processor.service.test.ts @@ -1,6 +1,6 @@ import { DynamicStructuredTool } from '@langchain/core/tools'; import type { Logger } from '@n8n/backend-common'; -import type { EventService } from '@n8n/backend-services'; +import { type EventService, OwnershipService } from '@n8n/backend-services'; import type { ExecutionsConfig } from '@n8n/config'; import type { IExecutionResponse, ExecutionRepository, Project } from '@n8n/db'; import { WorkflowPublishHistoryRepository } from '@n8n/db'; @@ -49,7 +49,6 @@ import { ExternalHooks } from '@/external-hooks'; import type { ManualExecutionService } from '@/manual-execution.service'; import { DataTableProxyService } from '@/modules/data-table/data-table-proxy.service'; import type { NodeTypes } from '@/node-types'; -import { OwnershipService } from '@/services/ownership.service'; import { WorkflowStatisticsService } from '@/services/workflow-statistics.service'; import * as WorkflowExecuteAdditionalData from '@/workflow-execute-additional-data'; import { WorkflowHookContextService } from '@/workflow-hook-context.service'; diff --git a/packages/cli/src/scheduling/schedule-trigger-node/__tests__/schedule-trigger-task-handler.test.ts b/packages/cli/src/scheduling/schedule-trigger-node/__tests__/schedule-trigger-task-handler.test.ts index 015e84d2229..b1725daf03c 100644 --- a/packages/cli/src/scheduling/schedule-trigger-node/__tests__/schedule-trigger-task-handler.test.ts +++ b/packages/cli/src/scheduling/schedule-trigger-node/__tests__/schedule-trigger-task-handler.test.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/unbound-method */ /* eslint-disable @typescript-eslint/naming-convention -- item keys are pinned to the legacy ScheduleTrigger emit shape */ import type { Logger } from '@n8n/backend-common'; -import type { EventService } from '@n8n/backend-services'; +import type { EventService, OwnershipService } from '@n8n/backend-services'; import type { GlobalConfig } from '@n8n/config'; import type { ExecutionEntity, ExecutionRepository, Project } from '@n8n/db'; import { createDispatchReporter, type ClaimedTask } from '@n8n/scheduler'; @@ -11,7 +11,6 @@ import { CRON_NODE_TYPE, SCHEDULE_TRIGGER_NODE_TYPE, UnexpectedError } from 'n8n import { mock } from 'vitest-mock-extended'; import { DuplicateExecutionError } from '@/errors/duplicate-execution.error'; -import type { OwnershipService } from '@/services/ownership.service'; import * as WorkflowExecuteAdditionalData from '@/workflow-execute-additional-data'; import type { TriggerExecutionContextFactory } from '@/workflows/triggers/trigger-execution-context.factory'; import type { WorkflowExecutionService } from '@/workflows/workflow-execution.service'; diff --git a/packages/cli/src/scheduling/schedule-trigger-node/schedule-trigger-task-handler.ts b/packages/cli/src/scheduling/schedule-trigger-node/schedule-trigger-task-handler.ts index 500ffbf4778..59f7008aa47 100644 --- a/packages/cli/src/scheduling/schedule-trigger-node/schedule-trigger-task-handler.ts +++ b/packages/cli/src/scheduling/schedule-trigger-node/schedule-trigger-task-handler.ts @@ -1,5 +1,5 @@ import { Logger } from '@n8n/backend-common'; -import { EventService } from '@n8n/backend-services'; +import { EventService, OwnershipService } from '@n8n/backend-services'; import { GlobalConfig } from '@n8n/config'; import { ExecutionRepository } from '@n8n/db'; import { Service } from '@n8n/di'; @@ -8,7 +8,6 @@ import { ErrorReporter } from 'n8n-core'; import { CRON_NODE_TYPE, UnexpectedError } from 'n8n-workflow'; import { DuplicateExecutionError } from '@/errors/duplicate-execution.error'; -import { OwnershipService } from '@/services/ownership.service'; import * as WorkflowExecuteAdditionalData from '@/workflow-execute-additional-data'; import { TriggerExecutionContextFactory } from '@/workflows/triggers/trigger-execution-context.factory'; import { getWorkflowProjectDetailsSafe } from '@/workflows/utils'; diff --git a/packages/cli/src/services/__tests__/ai-gateway.service.test.ts b/packages/cli/src/services/__tests__/ai-gateway.service.test.ts index 2ac42799e0b..80376967f68 100644 --- a/packages/cli/src/services/__tests__/ai-gateway.service.test.ts +++ b/packages/cli/src/services/__tests__/ai-gateway.service.test.ts @@ -12,8 +12,7 @@ import { FeatureNotLicensedError } from '@/errors/feature-not-licensed.error'; import { BadRequestError } from '@n8n/errors'; import type { License } from '@/license'; import { AiGatewayService } from '@/services/ai-gateway.service'; -import type { OwnershipService } from '@/services/ownership.service'; -import type { UrlService } from '@n8n/backend-services'; +import type { OwnershipService, UrlService } from '@n8n/backend-services'; const INSTANCE_BASE_URL = 'https://my-n8n.example.com'; diff --git a/packages/cli/src/services/__tests__/frontend.service.test.ts b/packages/cli/src/services/__tests__/frontend.service.test.ts index ee87bc5c1cd..c944cc6896d 100644 --- a/packages/cli/src/services/__tests__/frontend.service.test.ts +++ b/packages/cli/src/services/__tests__/frontend.service.test.ts @@ -3,6 +3,7 @@ import { tmpdir } from 'node:os'; import { join } from 'node:path'; import type { Mock } from 'vitest'; import type { LicenseState, Logger, ModuleRegistry } from '@n8n/backend-common'; +import type { OwnershipService, UrlService } from '@n8n/backend-services'; import type { GlobalConfig, SecurityConfig } from '@n8n/config'; import type { WorkflowRepository } from '@n8n/db'; import { Container } from '@n8n/di'; @@ -19,10 +20,8 @@ import { CommunityPackagesConfig } from '@/modules/community-packages/community- import type { PushConfig } from '@/push/push.config'; import type { AiUsageService } from '@/services/ai-usage.service'; import { FrontendService, type PublicFrontendSettings } from '@/services/frontend.service'; -import type { UrlService } from '@n8n/backend-services'; import type { WorkflowReviewPolicyService } from '@/services/workflow-review-policy.service'; import type { UserManagementMailer } from '@/user-management/email'; -import type { OwnershipService } from '../ownership.service'; // Mock the workflow history helper functions to avoid DI container issues in tests vi.mock('@/workflows/workflow-history/workflow-history-helper', () => ({ diff --git a/packages/cli/src/services/__tests__/owner-setup.service.test.ts b/packages/cli/src/services/__tests__/owner-setup.service.test.ts new file mode 100644 index 00000000000..dd770dc04b4 --- /dev/null +++ b/packages/cli/src/services/__tests__/owner-setup.service.test.ts @@ -0,0 +1,132 @@ +import { Logger } from '@n8n/backend-common'; +import type { EventService, OwnershipService } from '@n8n/backend-services'; +import { mockInstance } from '@n8n/backend-test-utils'; +import { GLOBAL_OWNER_ROLE, type SettingsRepository, User, UserRepository } from '@n8n/db'; +import { BadRequestError } from '@n8n/errors'; +import { mock } from 'vitest-mock-extended'; + +import { OwnerSetupService } from '@/services/owner-setup.service'; +import { PasswordUtility } from '@/services/password.utility'; + +describe('OwnerSetupService', () => { + const ownershipService = mock(); + const eventService = mock(); + const logger = mockInstance(Logger); + const passwordUtility = mockInstance(PasswordUtility); + const userRepository = mockInstance(UserRepository); + const settingsRepository = mock(); + + const ownerSetupService = new OwnerSetupService( + ownershipService, + eventService, + logger, + passwordUtility, + userRepository, + settingsRepository, + ); + + beforeEach(() => { + vi.clearAllMocks(); + }); + + it('should throw a BadRequestError if the instance owner is already setup', async () => { + ownershipService.hasInstanceOwner.mockResolvedValueOnce(true); + + const execution = ownerSetupService.setupOwner(mock()); + await expect(execution).rejects.toThrow(BadRequestError); + await expect(execution).rejects.toThrow('Instance owner already setup'); + + expect(userRepository.save).not.toHaveBeenCalled(); + expect(eventService.emit).not.toHaveBeenCalled(); + expect(logger.debug).toHaveBeenCalledWith( + 'Request to claim instance ownership failed because instance owner already exists', + ); + }); + + it('should throw a BadRequestError if the shell user is not found', async () => { + ownershipService.hasInstanceOwner.mockResolvedValueOnce(false); + userRepository.findOne.mockResolvedValueOnce(null); + + const execution = ownerSetupService.setupOwner(mock()); + await expect(execution).rejects.toThrow(BadRequestError); + await expect(execution).rejects.toThrow('Instance owner shell user not found'); + + expect(userRepository.save).not.toHaveBeenCalled(); + }); + + it('should setup the instance owner successfully', async () => { + const user = mock({ + id: 'userId', + role: GLOBAL_OWNER_ROLE, + authIdentities: [], + }); + const payload = { + email: 'valid@email.com', + password: 'NewPassword123', + firstName: 'Jane', + lastName: 'Doe', + }; + const expected = { ...user, ...payload, id: 'newUserId' }; + + ownershipService.hasInstanceOwner.mockResolvedValueOnce(false); + userRepository.findOne.mockResolvedValueOnce(user); + userRepository.save.mockResolvedValueOnce(expected); + + const actual = await ownerSetupService.setupOwner(payload); + + expect(userRepository.save).toHaveBeenCalledWith(user, { transaction: false }); + expect(eventService.emit).toHaveBeenCalledWith('instance-owner-setup', { + userId: 'newUserId', + }); + expect(settingsRepository.update).toHaveBeenCalledWith( + { key: 'userManagement.isInstanceOwnerSetUp' }, + { value: JSON.stringify(true) }, + ); + expect(actual.id).toEqual('newUserId'); + }); + + it('should normalize email to lowercase', async () => { + const user = mock({ id: 'userId', role: GLOBAL_OWNER_ROLE, authIdentities: [] }); + + ownershipService.hasInstanceOwner.mockResolvedValueOnce(false); + userRepository.findOne.mockResolvedValueOnce(user); + userRepository.save.mockResolvedValueOnce(user); + + await ownerSetupService.setupOwner({ + email: 'Admin@Example.COM', + password: 'NewPassword123', + firstName: 'Jane', + lastName: 'Doe', + }); + + expect(user.email).toBe('admin@example.com'); + }); + + it('should skip the owner check when overwriteExisting is true', async () => { + const user = mock({ id: 'userId', role: GLOBAL_OWNER_ROLE, authIdentities: [] }); + userRepository.findOne.mockResolvedValueOnce(user); + userRepository.save.mockResolvedValueOnce(user); + + await ownerSetupService.setupOwner( + { email: 'a@b.com', password: 'hash', firstName: 'A', lastName: 'B' }, + { overwriteExisting: true }, + ); + + expect(ownershipService.hasInstanceOwner).not.toHaveBeenCalled(); + }); + + it('should use a pre-hashed password when passwordIsHashed is true', async () => { + const user = mock({ id: 'userId', role: GLOBAL_OWNER_ROLE, authIdentities: [] }); + const preHashedPassword = '$2b$10$abcdefghijklmnopqrstuuABCDEFGHIJKLMNOPQRSTUVWXYZ01234'; + userRepository.findOne.mockResolvedValueOnce(user); + userRepository.save.mockResolvedValueOnce(user); + + await ownerSetupService.setupOwner( + { email: 'a@b.com', password: preHashedPassword, firstName: 'A', lastName: 'B' }, + { overwriteExisting: true, passwordIsHashed: true }, + ); + + expect(user.password).toBe(preHashedPassword); + expect(passwordUtility.hash).not.toHaveBeenCalled(); + }); +}); diff --git a/packages/cli/src/services/__tests__/ownership.service.integration.test.ts b/packages/cli/src/services/__tests__/ownership.service.integration.test.ts index b9d13fd3180..d353fcbc8f2 100644 --- a/packages/cli/src/services/__tests__/ownership.service.integration.test.ts +++ b/packages/cli/src/services/__tests__/ownership.service.integration.test.ts @@ -3,11 +3,13 @@ import { GLOBAL_OWNER_ROLE } from '@n8n/db'; import { Container } from '@n8n/di'; import { HooksService } from '@/services/hooks.service'; -import { OwnershipService } from '@/services/ownership.service'; +import { OwnershipService } from '@n8n/backend-services'; +import { OwnerSetupService } from '@/services/owner-setup.service'; import { createUserShell } from '@test-integration/db/users'; let hookService: HooksService; let ownershipService: OwnershipService; +let ownerSetupService: OwnerSetupService; // See PAY-4247 - This test case can be deleted when the ticket is complete describe('Ownership Service integration test', () => { @@ -21,6 +23,7 @@ describe('Ownership Service integration test', () => { await testDb.init(); hookService = Container.get(HooksService); ownershipService = Container.get(OwnershipService); + ownerSetupService = Container.get(OwnerSetupService); }); afterAll(async () => { @@ -49,7 +52,7 @@ describe('Ownership Service integration test', () => { it('should recognise ownership creation from api', async () => { expect(await ownershipService.hasInstanceOwner()).toBeFalsy(); - await ownershipService.setupOwner({ + await ownerSetupService.setupOwner({ firstName: 'TEST', lastName: 'LN', password: 'PW', diff --git a/packages/cli/src/services/__tests__/project.service.ee.test.ts b/packages/cli/src/services/__tests__/project.service.ee.test.ts index c10b82ec748..f3866da1568 100644 --- a/packages/cli/src/services/__tests__/project.service.ee.test.ts +++ b/packages/cli/src/services/__tests__/project.service.ee.test.ts @@ -1,6 +1,6 @@ import type { ProjectRelation } from '@n8n/api-types'; import type { Logger, ModuleRegistry } from '@n8n/backend-common'; -import { type EventService, type RoleService } from '@n8n/backend-services'; +import type { EventService, OwnershipService, RoleService } from '@n8n/backend-services'; import { type FolderRepository, type Project, @@ -21,7 +21,6 @@ import type { EntityManager } from '@n8n/typeorm'; import type { Mocked } from 'vitest'; import { mock } from 'vitest-mock-extended'; -import type { OwnershipService } from '../ownership.service'; import { ProjectService } from '../project.service.ee'; import type { ICredentialConnectionStatusProvider } from '@/credentials/credential-connection-status-provider.interface'; diff --git a/packages/cli/src/services/__tests__/user.service.test.ts b/packages/cli/src/services/__tests__/user.service.test.ts index 959f6ff01cc..6cccc8902ad 100644 --- a/packages/cli/src/services/__tests__/user.service.test.ts +++ b/packages/cli/src/services/__tests__/user.service.test.ts @@ -1,5 +1,10 @@ import { InviteUsersRequestDto } from '@n8n/api-types'; -import { type EventService, UrlService, type RoleService } from '@n8n/backend-services'; +import { + type EventService, + type OwnershipService, + type RoleService, + UrlService, +} from '@n8n/backend-services'; import { mockInstance } from '@n8n/backend-test-utils'; import { GlobalConfig } from '@n8n/config'; import { @@ -32,7 +37,6 @@ import type { UserManagementMailer } from '@/user-management/email'; import { JwtService } from '../jwt.service'; import type { OwnershipTransferService } from '../ownership-transfer/ownership-transfer.service'; -import type { OwnershipService } from '../ownership.service'; import type { ProjectService } from '../project.service.ee'; import type { PublicApiKeyService } from '../public-api-key.service'; diff --git a/packages/cli/src/services/__tests__/workflow-statistics.service.integration.test.ts b/packages/cli/src/services/__tests__/workflow-statistics.service.integration.test.ts index a3d8c78bc84..7c41299accb 100644 --- a/packages/cli/src/services/__tests__/workflow-statistics.service.integration.test.ts +++ b/packages/cli/src/services/__tests__/workflow-statistics.service.integration.test.ts @@ -1,4 +1,4 @@ -import { EventService } from '@n8n/backend-services'; +import { EventService, OwnershipService } from '@n8n/backend-services'; import type { Mock } from 'vitest'; import { getPersonalProject, @@ -30,7 +30,6 @@ import { } from 'n8n-workflow'; import { INSTANCE_ACTIVATED_SETTINGS_KEY } from '@/services/instance-activation.service'; -import { OwnershipService } from '@/services/ownership.service'; import { UserService } from '@/services/user.service'; import { WorkflowStatisticsService } from '@/services/workflow-statistics.service'; import { createUser } from '@test-integration/db/users'; diff --git a/packages/cli/src/services/ai-gateway.service.ts b/packages/cli/src/services/ai-gateway.service.ts index b9f9c9a254a..4d29db9f4ac 100644 --- a/packages/cli/src/services/ai-gateway.service.ts +++ b/packages/cli/src/services/ai-gateway.service.ts @@ -19,8 +19,7 @@ import { FeatureNotLicensedError } from '@/errors/feature-not-licensed.error'; import { BadRequestError } from '@n8n/errors'; import { License } from '@/license'; import { checkAiGatewayEligibility } from '@/services/ai-gateway-eligibility'; -import { OwnershipService } from '@/services/ownership.service'; -import { UrlService } from '@n8n/backend-services'; +import { OwnershipService, UrlService } from '@n8n/backend-services'; interface GatewayTokenResponse { token: string; diff --git a/packages/cli/src/services/frontend.service.ts b/packages/cli/src/services/frontend.service.ts index 9b62b32780d..2b8f04092c0 100644 --- a/packages/cli/src/services/frontend.service.ts +++ b/packages/cli/src/services/frontend.service.ts @@ -11,7 +11,7 @@ import { BinaryDataConfig, InstanceSettings, type Types } from 'n8n-core'; import type { ICredentialType, INodeTypeBaseDescription, INodeTypeDescription } from 'n8n-workflow'; import path from 'path'; -import { UrlService } from '@n8n/backend-services'; +import { UrlService, OwnershipService } from '@n8n/backend-services'; import { AiUsageService } from './ai-usage.service'; import { WorkflowReviewPolicyService } from './workflow-review-policy.service'; @@ -28,7 +28,6 @@ import { MfaService } from '@/mfa/mfa.service'; import { CommunityPackagesConfig } from '@/modules/community-packages/community-packages.config'; import { isApiKeyAuthEnabled } from '@/public-api'; import { PushConfig } from '@/push/push.config'; -import { OwnershipService } from '@/services/ownership.service'; import { getSamlLoginLabel, getCurrentAuthenticationMethod } from '@/sso.ee/sso-helpers'; import { UserManagementMailer } from '@/user-management/email'; import { resolveFrontendHealthEndpointPath } from '@/utils/health-endpoint.util'; diff --git a/packages/cli/src/services/owner-setup.service.ts b/packages/cli/src/services/owner-setup.service.ts new file mode 100644 index 00000000000..d8804f11666 --- /dev/null +++ b/packages/cli/src/services/owner-setup.service.ts @@ -0,0 +1,73 @@ +import { OwnerSetupRequestDto } from '@n8n/api-types'; +import { Logger } from '@n8n/backend-common'; +import { EventService, OwnershipService } from '@n8n/backend-services'; +import { GLOBAL_OWNER_ROLE, SettingsRepository, UserRepository } from '@n8n/db'; +import { Service } from '@n8n/di'; +import { BadRequestError } from '@n8n/errors'; + +import config from '@/config'; + +import { PasswordUtility } from './password.utility'; + +@Service() +export class OwnerSetupService { + constructor( + private readonly ownershipService: OwnershipService, + private readonly eventService: EventService, + private readonly logger: Logger, + private readonly passwordUtility: PasswordUtility, + private readonly userRepository: UserRepository, + private readonly settingsRepository: SettingsRepository, + ) {} + + async setupOwner( + payload: OwnerSetupRequestDto, + options?: { overwriteExisting?: boolean; passwordIsHashed?: boolean }, + ) { + const { email, firstName, lastName, password } = payload; + + if (!options?.overwriteExisting && (await this.ownershipService.hasInstanceOwner())) { + this.logger.debug( + 'Request to claim instance ownership failed because instance owner already exists', + ); + throw new BadRequestError('Instance owner already setup'); + } + + let shellUser = await this.userRepository.findOne({ + where: { role: { slug: GLOBAL_OWNER_ROLE.slug } }, + relations: ['role'], + }); + + if (!shellUser) { + this.logger.error('Could not find shell user with global:owner role'); + throw new BadRequestError('Instance owner shell user not found'); + } + + shellUser.email = email.toLowerCase(); + shellUser.firstName = firstName; + shellUser.lastName = lastName; + shellUser.lastActiveAt = new Date(); + shellUser.password = options?.passwordIsHashed + ? password + : await this.passwordUtility.hash(password); + + shellUser = await this.userRepository.save(shellUser, { transaction: false }); + + this.logger.info('Owner was set up successfully'); + this.eventService.emit('instance-owner-setup', { userId: shellUser.id }); + + // The next block needs to be deleted and is temporary for now + // See packages/cli/src/config/schema.ts for more info + // We update the SettingsRepository so when we "startup" next time + // the config state is restored. + // #region Delete me + await this.settingsRepository.update( + { key: 'userManagement.isInstanceOwnerSetUp' }, + { value: JSON.stringify(true) }, + ); + config.set('userManagement.isInstanceOwnerSetUp', true); + // #endregion + + return shellUser; + } +} diff --git a/packages/cli/src/services/ownership-transfer/__tests__/ownership-transfer.service.test.ts b/packages/cli/src/services/ownership-transfer/__tests__/ownership-transfer.service.test.ts index ba9066b7433..f28fce5d4bb 100644 --- a/packages/cli/src/services/ownership-transfer/__tests__/ownership-transfer.service.test.ts +++ b/packages/cli/src/services/ownership-transfer/__tests__/ownership-transfer.service.test.ts @@ -1,6 +1,7 @@ import { OwnershipTransferHandlerRegistry, type ProjectOwnershipTransferHandler, + type OwnershipService, } from '@n8n/backend-services'; import type { CredentialsEntity, @@ -18,7 +19,6 @@ import type { CredentialsService } from '@/credentials/credentials.service'; import type { PolicyActor } from '@/policy/policy-enforcement-backend'; import type { PolicyEnforcementService } from '@/policy/policy-enforcement.service'; import type { FolderService } from '@/services/folder.service'; -import type { OwnershipService } from '@/services/ownership.service'; import type { WorkflowService } from '@/workflows/workflow.service'; import { OwnershipTransferService } from '../ownership-transfer.service'; diff --git a/packages/cli/src/services/ownership-transfer/ownership-transfer.service.ts b/packages/cli/src/services/ownership-transfer/ownership-transfer.service.ts index e2f5dd932dd..24f317360b9 100644 --- a/packages/cli/src/services/ownership-transfer/ownership-transfer.service.ts +++ b/packages/cli/src/services/ownership-transfer/ownership-transfer.service.ts @@ -1,4 +1,4 @@ -import { OwnershipTransferHandlerRegistry } from '@n8n/backend-services'; +import { OwnershipTransferHandlerRegistry, OwnershipService } from '@n8n/backend-services'; import { SharedCredentialsRepository, SharedWorkflowRepository, @@ -11,7 +11,6 @@ import { CredentialsService } from '@/credentials/credentials.service'; import type { PolicyActor } from '@/policy/policy-enforcement-backend'; import { PolicyEnforcementService } from '@/policy/policy-enforcement.service'; import { FolderService } from '@/services/folder.service'; -import { OwnershipService } from '@/services/ownership.service'; import { WorkflowService } from '@/workflows/workflow.service'; /** diff --git a/packages/cli/src/services/project.service.ee.ts b/packages/cli/src/services/project.service.ee.ts index 813e7148d33..bca6a551d62 100644 --- a/packages/cli/src/services/project.service.ee.ts +++ b/packages/cli/src/services/project.service.ee.ts @@ -1,6 +1,6 @@ import type { CreateProjectDto, ProjectType, UpdateProjectDto } from '@n8n/api-types'; import { LicenseState, Logger, ModuleRegistry } from '@n8n/backend-common'; -import { EventService, RoleService } from '@n8n/backend-services'; +import { EventService, RoleService, OwnershipService } from '@n8n/backend-services'; import { type User, FolderRepository, @@ -37,8 +37,6 @@ import { UserError } from 'n8n-workflow'; import { BadRequestError, ConflictError, ForbiddenError, NotFoundError } from '@n8n/errors'; import { UserManagementMailer } from '@/user-management/email'; -import { OwnershipService } from './ownership.service'; - const INSTANCE_ACCESS_ROLE_ERROR = "This user has access through their instance role. Project roles can't change their access in this project."; const INSTANCE_ACCESS_REMOVE_ERROR = diff --git a/packages/cli/src/services/user.service.ts b/packages/cli/src/services/user.service.ts index 5093bdd90e5..7da478610a6 100644 --- a/packages/cli/src/services/user.service.ts +++ b/packages/cli/src/services/user.service.ts @@ -1,6 +1,6 @@ import type { RoleChangeRequestDto } from '@n8n/api-types'; import { Logger } from '@n8n/backend-common'; -import { EventService, UrlService, RoleService } from '@n8n/backend-services'; +import { EventService, UrlService, RoleService, OwnershipService } from '@n8n/backend-services'; import { GlobalConfig } from '@n8n/config'; import type { PublicUser } from '@n8n/db'; import { @@ -31,7 +31,6 @@ import { UserError } from 'n8n-workflow'; import { validate as uuidValidate } from 'uuid'; import { JwtService } from './jwt.service'; -import { OwnershipService } from './ownership.service'; import { ProjectService } from './project.service.ee'; import { PublicApiKeyService } from './public-api-key.service'; diff --git a/packages/cli/src/services/workflow-statistics.service.ts b/packages/cli/src/services/workflow-statistics.service.ts index a54ce777972..3d8f8bd9fbb 100644 --- a/packages/cli/src/services/workflow-statistics.service.ts +++ b/packages/cli/src/services/workflow-statistics.service.ts @@ -1,5 +1,5 @@ import { Logger, TypedEmitter } from '@n8n/backend-common'; -import { EventService, isBillableExecution } from '@n8n/backend-services'; +import { EventService, isBillableExecution, OwnershipService } from '@n8n/backend-services'; import { DatabaseConfig } from '@n8n/config'; import type { CrashedExecution } from '@n8n/db'; import { @@ -23,7 +23,6 @@ import { import { UserService } from '@/services/user.service'; import { INSTANCE_ACTIVATED_SETTINGS_KEY } from './instance-activation.service'; -import { OwnershipService } from './ownership.service'; type CompletedRunOutcome = { mode: WorkflowExecuteMode; diff --git a/packages/cli/src/wait-tracker.ts b/packages/cli/src/wait-tracker.ts index a62d879522a..c1010226e88 100644 --- a/packages/cli/src/wait-tracker.ts +++ b/packages/cli/src/wait-tracker.ts @@ -18,7 +18,7 @@ import { import { ActiveExecutions } from '@/active-executions'; import { ExecutionAlreadyResumingError } from '@/errors/execution-already-resuming.error'; import { ExecutionPersistence } from '@/executions/execution-persistence'; -import { OwnershipService } from '@/services/ownership.service'; +import { OwnershipService } from '@n8n/backend-services'; import { WorkflowPublisherService } from '@/workflows/workflow-publisher.service'; import { WorkflowRunner } from '@/workflow-runner'; diff --git a/packages/cli/src/webhooks/__tests__/webhook-helpers.test.ts b/packages/cli/src/webhooks/__tests__/webhook-helpers.test.ts index 26bb82fb25e..e723bbabc45 100644 --- a/packages/cli/src/webhooks/__tests__/webhook-helpers.test.ts +++ b/packages/cli/src/webhooks/__tests__/webhook-helpers.test.ts @@ -1,5 +1,5 @@ import { Logger } from '@n8n/backend-common'; -import { EventService } from '@n8n/backend-services'; +import { EventService, OwnershipService } from '@n8n/backend-services'; import { mockInstance } from '@n8n/backend-test-utils'; import { EngineConfig } from '@n8n/config'; import type { Project, User } from '@n8n/db'; @@ -67,7 +67,6 @@ import { WebhookResponseRelay } from '@/scaling/webhook-response-relay'; import { EngineDataPlaneProxyService } from '@/services/engine-data-plane-proxy.service'; import { EngineV2Dispatcher } from '@/services/engine-v2-dispatcher.service'; import { EngineV2WebhookResponseRegistry } from '@/modules/engine-v2/webhook-response/webhook-response-registry.service'; -import { OwnershipService } from '@/services/ownership.service'; import { OAuth2FlowProxy } from '@/services/oauth2-flow-proxy.service'; import type { ProtectedResource } from '@/services/protected-resource.registry'; import { ProtectedResourceRegistry } from '@/services/protected-resource.registry'; diff --git a/packages/cli/src/webhooks/webhook-helpers.ts b/packages/cli/src/webhooks/webhook-helpers.ts index 1bfe929e7dd..0f4c10a930c 100644 --- a/packages/cli/src/webhooks/webhook-helpers.ts +++ b/packages/cli/src/webhooks/webhook-helpers.ts @@ -1,5 +1,5 @@ import { Logger } from '@n8n/backend-common'; -import { EventService } from '@n8n/backend-services'; +import { EventService, OwnershipService } from '@n8n/backend-services'; import { ExecutionsConfig, GlobalConfig } from '@n8n/config'; import type { Project } from '@n8n/db'; import { UserRepository } from '@n8n/db'; @@ -81,7 +81,6 @@ import { OAuthTokenVerifierProxy, } from '@/services/oauth-token-verifier-proxy.service'; import { OAuth2FlowProxy } from '@/services/oauth2-flow-proxy.service'; -import { OwnershipService } from '@/services/ownership.service'; import { ProtectedResourceRegistry } from '@/services/protected-resource.registry'; import type { WebhookRunOutcome } from '@/modules/engine-v2/webhook-response/webhook-outcome'; import type { WebhookResponseWait } from '@/modules/engine-v2/webhook-response/webhook-response-registry.service'; diff --git a/packages/cli/src/workflow-execute-additional-data.ts b/packages/cli/src/workflow-execute-additional-data.ts index 7055378f0ba..89e2e250b74 100644 --- a/packages/cli/src/workflow-execute-additional-data.ts +++ b/packages/cli/src/workflow-execute-additional-data.ts @@ -352,7 +352,7 @@ export async function executeWorkflow( const executionId = await activeExecutions.add(runData); - const { OwnershipService } = await import('@/services/ownership.service.js'); + const { OwnershipService } = await import('@n8n/backend-services'); const { projectId, projectName } = await getWorkflowProjectDetailsSafe( Container.get(OwnershipService), workflowData.id, @@ -423,7 +423,7 @@ export async function executeAgent( // `webhooks/*`, `scaling/job-processor`). Resolve it from the workflow's // owning project so the agent runs under the correct project scope. if (!projectId && additionalData.workflowId) { - const { OwnershipService } = await import('@/services/ownership.service.js'); + const { OwnershipService } = await import('@n8n/backend-services'); const ownershipService = Container.get(OwnershipService); const project = await ownershipService.getWorkflowProjectCached(additionalData.workflowId); projectId = project.id; @@ -883,7 +883,7 @@ export async function getBase({ // matching `getVariables`'s own pre-existing lookup below: an unresolvable owner // project fails execution setup, it isn't silently tolerated. if (!projectId && workflowId) { - const { OwnershipService } = await import('@/services/ownership.service.js'); + const { OwnershipService } = await import('@n8n/backend-services'); const project = await Container.get(OwnershipService).getWorkflowProjectCached(workflowId); projectId = project?.id; } diff --git a/packages/cli/src/workflow-helpers.ts b/packages/cli/src/workflow-helpers.ts index 81028bb0d39..27df6493001 100644 --- a/packages/cli/src/workflow-helpers.ts +++ b/packages/cli/src/workflow-helpers.ts @@ -37,7 +37,7 @@ import { VariablesService } from '@/environments.ee/variables/variables.service. import { ExecutionPersistence } from '@/executions/execution-persistence'; import { NodeTypes } from '@/node-types'; -import { OwnershipService } from './services/ownership.service'; +import { OwnershipService } from '@n8n/backend-services'; export { dropInvalidWorkflowGroups, makeGetNodeTypeForGrouping }; export { getLastExecutedNodeData, getLastExecutedNodeRuns } from 'n8n-workflow'; diff --git a/packages/cli/src/workflows/__tests__/utils.test.ts b/packages/cli/src/workflows/__tests__/utils.test.ts index 1b30312211c..f1559d15675 100644 --- a/packages/cli/src/workflows/__tests__/utils.test.ts +++ b/packages/cli/src/workflows/__tests__/utils.test.ts @@ -4,7 +4,7 @@ import type { Project } from '@n8n/db'; import { WorkflowEntity } from '@n8n/db'; import { mock } from 'vitest-mock-extended'; -import type { OwnershipService } from '@/services/ownership.service'; +import type { OwnershipService } from '@n8n/backend-services'; import { dropRedactionPolicy, getWorkflowProjectDetailsSafe } from '@/workflows/utils'; describe('dropRedactionPolicy', () => { diff --git a/packages/cli/src/workflows/__tests__/workflow-execution.service.test.ts b/packages/cli/src/workflows/__tests__/workflow-execution.service.test.ts index dd9f44e4e19..8d5159d00d4 100644 --- a/packages/cli/src/workflows/__tests__/workflow-execution.service.test.ts +++ b/packages/cli/src/workflows/__tests__/workflow-execution.service.test.ts @@ -1,5 +1,9 @@ import type { Logger } from '@n8n/backend-common'; -import type { EventService, InstanceWriteAccessService } from '@n8n/backend-services'; +import type { + EventService, + InstanceWriteAccessService, + OwnershipService, +} from '@n8n/backend-services'; import type { GlobalConfig, WorkflowsConfig } from '@n8n/config'; import type { CreateExecutionPayload, @@ -36,7 +40,6 @@ import { ForbiddenError } from '@n8n/errors'; import type { ExecutionCrashService } from '@/executions/execution-crash.service'; import type { IWorkflowErrorData } from '@/interfaces'; import type { NodeTypes } from '@/node-types'; -import type { OwnershipService } from '@/services/ownership.service'; import type { TestWebhooks } from '@/webhooks/test-webhooks'; import * as WorkflowExecuteAdditionalData from '@/workflow-execute-additional-data'; import type { WorkflowRunner } from '@/workflow-runner'; diff --git a/packages/cli/src/workflows/__tests__/workflow.service.ee.test.ts b/packages/cli/src/workflows/__tests__/workflow.service.ee.test.ts index aaf4f98edd4..bbe3113b2fb 100644 --- a/packages/cli/src/workflows/__tests__/workflow.service.ee.test.ts +++ b/packages/cli/src/workflows/__tests__/workflow.service.ee.test.ts @@ -15,11 +15,10 @@ import { WorkflowActivationError } from 'n8n-workflow'; import { mock } from 'vitest-mock-extended'; import type { ActiveWorkflowManager } from '@/active-workflow-manager'; -import type { CredentialsFinderService } from '@n8n/backend-services'; +import type { CredentialsFinderService, OwnershipService } from '@n8n/backend-services'; import type { CredentialsService } from '@/credentials/credentials.service'; import type { CredentialsPermissionChecker } from '@/executions/pre-execution-checks/credentials-permission-checker'; import type { PolicyEnforcementService } from '@/policy/policy-enforcement.service'; -import type { OwnershipService } from '@/services/ownership.service'; import type { ProjectService } from '@/services/project.service.ee'; import type { WorkflowFinderService } from '@/workflows/workflow-finder.service'; import type { WorkflowMutationHooksProxy } from '@/workflows/workflow-mutation-hooks-proxy.service'; diff --git a/packages/cli/src/workflows/__tests__/workflow.service.test.ts b/packages/cli/src/workflows/__tests__/workflow.service.test.ts index fc60722f7bf..51b6764e7e6 100644 --- a/packages/cli/src/workflows/__tests__/workflow.service.test.ts +++ b/packages/cli/src/workflows/__tests__/workflow.service.test.ts @@ -1,5 +1,5 @@ import type { LicenseState } from '@n8n/backend-common'; -import { type EventService, type RoleService } from '@n8n/backend-services'; +import type { EventService, RoleService, OwnershipService } from '@n8n/backend-services'; import type { GlobalConfig, WorkflowsConfig } from '@n8n/config'; import type { Transaction, @@ -46,7 +46,6 @@ import type { DurableJobProvisioner } from '@/scheduling/durable-job-provisioner import type { PollTriggerJobRegistrar } from '@/scheduling/poll-trigger-node/poll-trigger-job-registrar'; import type { ScheduleTriggerJobRegistrar } from '@/scheduling/schedule-trigger-node/schedule-trigger-job-registrar'; import type { WorkflowScheduledJobOwner } from '@/scheduling/workflow-scheduled-job-owner'; -import type { OwnershipService } from '@/services/ownership.service'; import type { TagService } from '@/services/tag.service'; import type { WebhookService } from '@/webhooks/webhook.service'; diff --git a/packages/cli/src/workflows/publication/__tests__/workflow-publication-applier.test.ts b/packages/cli/src/workflows/publication/__tests__/workflow-publication-applier.test.ts index 01341cc0995..1eac0f19805 100644 --- a/packages/cli/src/workflows/publication/__tests__/workflow-publication-applier.test.ts +++ b/packages/cli/src/workflows/publication/__tests__/workflow-publication-applier.test.ts @@ -18,7 +18,7 @@ import { TELEMETRY_EVENT } from '@n8n/telemetry'; import type { NodeTypes } from '@/node-types'; import type { PolicyEnforcementService } from '@/policy/policy-enforcement.service'; import { PolicyViolationError } from '@/policy/policy-violation.error'; -import type { OwnershipService } from '@/services/ownership.service'; +import type { OwnershipService } from '@n8n/backend-services'; import type { Telemetry } from '@/telemetry'; import { WorkflowPublicationApplier } from '@/workflows/publication/workflow-publication-applier'; import type { DurableJobProvisioner } from '@/scheduling/durable-job-provisioner'; diff --git a/packages/cli/src/workflows/publication/workflow-publication-applier.ts b/packages/cli/src/workflows/publication/workflow-publication-applier.ts index b3d1000edc6..1c282d908e3 100644 --- a/packages/cli/src/workflows/publication/workflow-publication-applier.ts +++ b/packages/cli/src/workflows/publication/workflow-publication-applier.ts @@ -20,7 +20,7 @@ import { PolicyEnforcementService } from '@/policy/policy-enforcement.service'; import { PolicyViolationError } from '@/policy/policy-violation.error'; import { DurableJobProvisioner } from '@/scheduling/durable-job-provisioner'; import { WorkflowScheduledJobOwner } from '@/scheduling/workflow-scheduled-job-owner'; -import { OwnershipService } from '@/services/ownership.service'; +import { OwnershipService } from '@n8n/backend-services'; import { Telemetry } from '@/telemetry'; import { formatNodeFailures } from '@/workflows/publication/format-node-failures'; import { healNodeIds } from '@/workflows/publication/heal-node-ids'; diff --git a/packages/cli/src/workflows/triggers/__tests__/trigger-execution-context.factory.test.ts b/packages/cli/src/workflows/triggers/__tests__/trigger-execution-context.factory.test.ts index 4df56a09119..38d5e2ae268 100644 --- a/packages/cli/src/workflows/triggers/__tests__/trigger-execution-context.factory.test.ts +++ b/packages/cli/src/workflows/triggers/__tests__/trigger-execution-context.factory.test.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/unbound-method */ import type { Logger } from '@n8n/backend-common'; -import type { EventService } from '@n8n/backend-services'; +import type { EventService, OwnershipService } from '@n8n/backend-services'; import type { GlobalConfig } from '@n8n/config'; import type { Project, WorkflowEntity } from '@n8n/db'; import type { IDeferredPromise } from '@n8n/utils/promise/deferred-promise'; @@ -39,7 +39,6 @@ import type { ScheduleTriggerCollectionSession, ScheduleTriggerJobRegistrar, } from '@/scheduling/schedule-trigger-node/schedule-trigger-job-registrar'; -import type { OwnershipService } from '@/services/ownership.service'; import type { WorkflowPublisherService } from '@/workflows/workflow-publisher.service'; import * as WorkflowExecuteAdditionalData from '@/workflow-execute-additional-data'; import type { WorkflowExecutionService } from '@/workflows/workflow-execution.service'; diff --git a/packages/cli/src/workflows/triggers/trigger-execution-context.factory.ts b/packages/cli/src/workflows/triggers/trigger-execution-context.factory.ts index 823729dd6c3..ad3bed51a06 100644 --- a/packages/cli/src/workflows/triggers/trigger-execution-context.factory.ts +++ b/packages/cli/src/workflows/triggers/trigger-execution-context.factory.ts @@ -1,5 +1,5 @@ import { Logger } from '@n8n/backend-common'; -import { EventService } from '@n8n/backend-services'; +import { EventService, OwnershipService } from '@n8n/backend-services'; import { GlobalConfig } from '@n8n/config'; import { Time } from '@n8n/constants'; import type { IWorkflowDb, PollerCursor, PollLeaseFence } from '@n8n/db'; @@ -39,7 +39,6 @@ import { ExecutionService } from '@/executions/execution.service'; import { NodeTypes } from '@/node-types'; import type { ScheduleTriggerCollectionSession } from '@/scheduling/schedule-trigger-node/schedule-trigger-job-registrar'; import { ScheduleTriggerJobRegistrar } from '@/scheduling/schedule-trigger-node/schedule-trigger-job-registrar'; -import { OwnershipService } from '@/services/ownership.service'; import * as WorkflowExecuteAdditionalData from '@/workflow-execute-additional-data'; import type { EngineV2ActiveTriggerEmit } from '@/workflows/triggers/engine-v2-active-triggers'; import { EngineV2ActiveTriggers } from '@/workflows/triggers/engine-v2-active-triggers'; diff --git a/packages/cli/src/workflows/utils.ts b/packages/cli/src/workflows/utils.ts index 6b8e1f873b9..6b3f91f6aac 100644 --- a/packages/cli/src/workflows/utils.ts +++ b/packages/cli/src/workflows/utils.ts @@ -5,7 +5,7 @@ import type { Scope } from '@n8n/permissions'; import { NodeApiError, NodeError, WorkflowActivationError } from 'n8n-workflow'; import type { WorkflowSettings } from 'n8n-workflow'; -import type { OwnershipService } from '@/services/ownership.service'; +import type { OwnershipService } from '@n8n/backend-services'; type RedactionMode = 'manual' | 'nonManual'; diff --git a/packages/cli/src/workflows/workflow-execution.service.ts b/packages/cli/src/workflows/workflow-execution.service.ts index 41bc0732835..57b7dac7dc4 100644 --- a/packages/cli/src/workflows/workflow-execution.service.ts +++ b/packages/cli/src/workflows/workflow-execution.service.ts @@ -1,5 +1,5 @@ import { Logger } from '@n8n/backend-common'; -import { EventService, InstanceWriteAccessService } from '@n8n/backend-services'; +import { EventService, InstanceWriteAccessService, OwnershipService } from '@n8n/backend-services'; import { GlobalConfig, WorkflowsConfig } from '@n8n/config'; import type { Project, @@ -49,7 +49,6 @@ import { FailedRunFactory } from '@/executions/failed-run-factory'; import { SubworkflowPolicyChecker } from '@/executions/pre-execution-checks'; import type { IWorkflowErrorData } from '@/interfaces'; import { NodeTypes } from '@/node-types'; -import { OwnershipService } from '@/services/ownership.service'; import { TestWebhooks } from '@/webhooks/test-webhooks'; import * as WorkflowExecuteAdditionalData from '@/workflow-execute-additional-data'; import { WorkflowRunner } from '@/workflow-runner'; diff --git a/packages/cli/src/workflows/workflow.service.ee.ts b/packages/cli/src/workflows/workflow.service.ee.ts index 07be74cceb1..6b5ab5e104f 100644 --- a/packages/cli/src/workflows/workflow.service.ee.ts +++ b/packages/cli/src/workflows/workflow.service.ee.ts @@ -32,7 +32,7 @@ import { import { ActiveWorkflowManager } from '@/active-workflow-manager'; import { isCredSharingEnabled } from '@/constants/credential-sharing'; -import { CredentialsFinderService } from '@n8n/backend-services'; +import { CredentialsFinderService, OwnershipService } from '@n8n/backend-services'; import { CredentialsService } from '@/credentials/credentials.service'; import { EnterpriseCredentialsService } from '@/credentials/credentials.service.ee'; import { CredentialsPermissionChecker } from '@/executions/pre-execution-checks/credentials-permission-checker'; @@ -41,7 +41,6 @@ import { BadRequestError, NotFoundError } from '@n8n/errors'; import { TransferWorkflowError } from '@/errors/response-errors/transfer-workflow.error'; import { extractAgentCredentialIds } from '@/modules/agents/utils/extract-agent-credential-ids'; import { PolicyEnforcementService } from '@/policy/policy-enforcement.service'; -import { OwnershipService } from '@/services/ownership.service'; import { ProjectService } from '@/services/project.service.ee'; import { WorkflowFinderService } from './workflow-finder.service'; diff --git a/packages/cli/src/workflows/workflow.service.ts b/packages/cli/src/workflows/workflow.service.ts index 439a695ad01..9905ba97d19 100644 --- a/packages/cli/src/workflows/workflow.service.ts +++ b/packages/cli/src/workflows/workflow.service.ts @@ -1,7 +1,7 @@ import { UpdateWorkflowHistoryVersionDto } from '@n8n/api-types'; import type { WorkflowListPublicationStatus, WorkflowExecutionBlockCause } from '@n8n/api-types'; import { LicenseState, Logger } from '@n8n/backend-common'; -import { EventService, RoleService } from '@n8n/backend-services'; +import { EventService, RoleService, OwnershipService } from '@n8n/backend-services'; import { GlobalConfig } from '@n8n/config'; import type { User, @@ -82,7 +82,6 @@ import { DurableJobProvisioner } from '@/scheduling/durable-job-provisioner'; import { PollTriggerJobRegistrar } from '@/scheduling/poll-trigger-node/poll-trigger-job-registrar'; import { ScheduleTriggerJobRegistrar } from '@/scheduling/schedule-trigger-node/schedule-trigger-job-registrar'; import { WorkflowScheduledJobOwner } from '@/scheduling/workflow-scheduled-job-owner'; -import { OwnershipService } from '@/services/ownership.service'; import { ProjectService } from '@/services/project.service.ee'; import { TagService } from '@/services/tag.service'; diff --git a/packages/cli/src/workflows/workflows.controller.ts b/packages/cli/src/workflows/workflows.controller.ts index 07bfd4af03d..821d8665b36 100644 --- a/packages/cli/src/workflows/workflows.controller.ts +++ b/packages/cli/src/workflows/workflows.controller.ts @@ -12,7 +12,7 @@ import { } from '@n8n/api-types'; import { Logger } from '@n8n/backend-common'; import { OutboundHttp, SsrfBlockedIpError } from '@n8n/backend-network'; -import { EventService } from '@n8n/backend-services'; +import { EventService, OwnershipService } from '@n8n/backend-services'; import { GlobalConfig } from '@n8n/config'; import { AuthenticatedRequest, @@ -50,7 +50,6 @@ import { listQueryMiddleware } from '@/middlewares'; import { userHasScopes } from '@/permissions.ee/check-access'; import * as ResponseHelper from '@/response-helper'; import { NamingService } from '@/services/naming.service'; -import { OwnershipService } from '@/services/ownership.service'; import { ProjectService } from '@/services/project.service.ee'; import { UserManagementMailer } from '@/user-management/email'; import * as utils from '@/utils'; diff --git a/packages/cli/test/integration/active-workflow-manager.test.ts b/packages/cli/test/integration/active-workflow-manager.test.ts index 29b21f85df3..f5275120f57 100644 --- a/packages/cli/test/integration/active-workflow-manager.test.ts +++ b/packages/cli/test/integration/active-workflow-manager.test.ts @@ -27,7 +27,7 @@ import { ExternalHooks } from '@/external-hooks'; import { NodeTypes } from '@/node-types'; import { PolicyEnforcementService } from '@/policy/policy-enforcement.service'; import { Push } from '@/push'; -import { OwnershipService } from '@/services/ownership.service'; +import { OwnershipService } from '@n8n/backend-services'; import * as WebhookHelpers from '@/webhooks/webhook-helpers'; import { WebhookService } from '@/webhooks/webhook.service'; import * as AdditionalData from '@/workflow-execute-additional-data'; diff --git a/packages/cli/test/integration/commands/start.cmd.test.ts b/packages/cli/test/integration/commands/start.cmd.test.ts index 41daad46823..e256062738f 100644 --- a/packages/cli/test/integration/commands/start.cmd.test.ts +++ b/packages/cli/test/integration/commands/start.cmd.test.ts @@ -30,7 +30,7 @@ import { Push } from '@/push'; import { PubSubEventBus } from '@/scaling/pubsub/pubsub.eventbus'; import { DurableScheduler } from '@/scheduling/durable-scheduler'; import { Server } from '@/server'; -import { OwnershipService } from '@/services/ownership.service'; +import { OwnershipService } from '@n8n/backend-services'; import { ExecutionsPruningService } from '@/services/pruning/executions-pruning.service'; import { WorkflowHistoryCompactionService } from '@/services/pruning/workflow-history-compaction.service'; import { WorkflowStatisticsRollupService } from '@/services/workflow-statistics-rollup.service'; diff --git a/packages/cli/test/integration/executions/pre-execution-checks/credentials-permission-checker.test.ts b/packages/cli/test/integration/executions/pre-execution-checks/credentials-permission-checker.test.ts index 101f9c067a4..77574c5ef3a 100644 --- a/packages/cli/test/integration/executions/pre-execution-checks/credentials-permission-checker.test.ts +++ b/packages/cli/test/integration/executions/pre-execution-checks/credentials-permission-checker.test.ts @@ -20,7 +20,7 @@ import { v4 as uuid } from 'uuid'; import { CredentialsPermissionChecker } from '@/executions/pre-execution-checks'; import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials'; import { NodeTypes } from '@/node-types'; -import { OwnershipService } from '@/services/ownership.service'; +import { OwnershipService } from '@n8n/backend-services'; import { WorkflowValidationService } from '@/workflows/workflow-validation.service'; import { affixRoleToSaveCredential } from '@test-integration/db/credentials'; import { createOwner, createUser } from '@test-integration/db/users'; diff --git a/packages/cli/test/integration/folder/folder.controller.test.ts b/packages/cli/test/integration/folder/folder.controller.test.ts index 4d86e7c6580..e917c4d828b 100644 --- a/packages/cli/test/integration/folder/folder.controller.test.ts +++ b/packages/cli/test/integration/folder/folder.controller.test.ts @@ -19,7 +19,7 @@ import { DateTime } from 'luxon'; import { PROJECT_ROOT, UnexpectedError } from 'n8n-workflow'; import { ActiveWorkflowManager } from '@/active-workflow-manager'; -import { OwnershipService } from '@/services/ownership.service'; +import { OwnershipService } from '@n8n/backend-services'; import { createCredentials, getCredentialSharings, diff --git a/packages/cli/test/integration/owner.api.test.ts b/packages/cli/test/integration/owner.api.test.ts index 3f9991e432d..83f4fa0f58c 100644 --- a/packages/cli/test/integration/owner.api.test.ts +++ b/packages/cli/test/integration/owner.api.test.ts @@ -10,7 +10,7 @@ import { GLOBAL_OWNER_ROLE, UserRepository } from '@n8n/db'; import { Container } from '@n8n/di'; import validator from 'validator'; -import { OwnershipService } from '@/services/ownership.service'; +import { OwnershipService } from '@n8n/backend-services'; import { createUserShell } from './shared/db/users'; import * as utils from './shared/utils/'; diff --git a/packages/cli/test/integration/scheduling/scheduled-job-lifecycle.test.ts b/packages/cli/test/integration/scheduling/scheduled-job-lifecycle.test.ts index e05c378e362..1161c532dd4 100644 --- a/packages/cli/test/integration/scheduling/scheduled-job-lifecycle.test.ts +++ b/packages/cli/test/integration/scheduling/scheduled-job-lifecycle.test.ts @@ -25,7 +25,7 @@ import { ExecutionService } from '@/executions/execution.service'; import { ExternalHooks } from '@/external-hooks'; import { Push } from '@/push'; import { WorkflowScheduledJobOwner } from '@/scheduling/workflow-scheduled-job-owner'; -import { OwnershipService } from '@/services/ownership.service'; +import { OwnershipService } from '@n8n/backend-services'; import { Telemetry } from '@/telemetry'; import { WorkflowPublicationOutboxConsumer } from '@/workflows/publication/workflow-publication-outbox-consumer'; import { WorkflowService } from '@/workflows/workflow.service'; diff --git a/packages/cli/test/integration/users.api.test.ts b/packages/cli/test/integration/users.api.test.ts index 4873a98ace6..555ddf2b174 100644 --- a/packages/cli/test/integration/users.api.test.ts +++ b/packages/cli/test/integration/users.api.test.ts @@ -42,7 +42,7 @@ import { validateUser } from './shared/utils/users'; import { RESPONSE_ERROR_MESSAGES } from '@/constants'; import { ExecutionService } from '@/executions/execution.service'; import { ProvisioningService } from '@/modules/provisioning.ee/provisioning.service.ee'; -import { OwnershipService } from '@/services/ownership.service'; +import { OwnershipService } from '@n8n/backend-services'; import { CHANGE_ROLE_ERROR_MESSAGES } from '@/services/user.service'; import { Telemetry } from '@/telemetry'; diff --git a/packages/cli/test/integration/workflows/workflow-publication-outbox-consumer.test.ts b/packages/cli/test/integration/workflows/workflow-publication-outbox-consumer.test.ts index 2a5d56cab52..75bae49d13b 100644 --- a/packages/cli/test/integration/workflows/workflow-publication-outbox-consumer.test.ts +++ b/packages/cli/test/integration/workflows/workflow-publication-outbox-consumer.test.ts @@ -22,7 +22,7 @@ import { ActiveWorkflowManager } from '@/active-workflow-manager'; import { ExecutionService } from '@/executions/execution.service'; import { ExternalHooks } from '@/external-hooks'; import { Push } from '@/push'; -import { OwnershipService } from '@/services/ownership.service'; +import { OwnershipService } from '@n8n/backend-services'; import { Telemetry } from '@/telemetry'; import { PublishedWorkflowTriggerDeactivator } from '@/workflows/publication/published-workflow-trigger-deactivator'; import { WorkflowPublicationLifecycleLock } from '@/workflows/publication/workflow-publication-lifecycle-lock'; diff --git a/packages/cli/test/integration/workflows/workflow-publication-reconciler.test.ts b/packages/cli/test/integration/workflows/workflow-publication-reconciler.test.ts index 6137c9afb55..b1e08f52553 100644 --- a/packages/cli/test/integration/workflows/workflow-publication-reconciler.test.ts +++ b/packages/cli/test/integration/workflows/workflow-publication-reconciler.test.ts @@ -1,4 +1,4 @@ -import { EventService } from '@n8n/backend-services'; +import { EventService, OwnershipService } from '@n8n/backend-services'; import { createWorkflowHistory, createWorkflowWithHistory, @@ -25,7 +25,6 @@ import { ActiveWorkflowManager } from '@/active-workflow-manager'; import { ExecutionService } from '@/executions/execution.service'; import { ExternalHooks } from '@/external-hooks'; import { Push } from '@/push'; -import { OwnershipService } from '@/services/ownership.service'; import { WorkflowPublicationOutboxConsumer } from '@/workflows/publication/workflow-publication-outbox-consumer'; import { WorkflowPublicationApplier } from '@/workflows/publication/workflow-publication-applier'; import { WorkflowPublicationReconciler } from '@/workflows/publication/workflow-publication-reconciler.service'; diff --git a/packages/cli/test/integration/workflows/workflow.service.test.ts b/packages/cli/test/integration/workflows/workflow.service.test.ts index 99b92824676..a0cb0983ff8 100644 --- a/packages/cli/test/integration/workflows/workflow.service.test.ts +++ b/packages/cli/test/integration/workflows/workflow.service.test.ts @@ -33,9 +33,8 @@ import type { ExternalHooks } from '@/external-hooks'; import { MessageEventBus } from '@/eventbus/message-event-bus/message-event-bus'; import { NodeTypes } from '@/node-types'; import { PolicyEnforcementService } from '@/policy/policy-enforcement.service'; -import { OwnershipService } from '@/services/ownership.service'; +import { OwnershipService, RoleService } from '@n8n/backend-services'; import { ProjectService } from '@/services/project.service.ee'; -import { RoleService } from '@n8n/backend-services'; import { Telemetry } from '@/telemetry'; import { WebhookService } from '@/webhooks/webhook.service'; import { WorkflowHookContextService } from '@/workflow-hook-context.service';