From 69595f58215142b21d4603084b9acad1f47ae51e Mon Sep 17 00:00:00 2001 From: Charlie Kolb Date: Fri, 2 Oct 2026 11:24:08 +0000 Subject: [PATCH] refactor(core): Move workflow sharing service to backend services (no-changelog) (#40157) --- packages/@n8n/backend-services/src/index.ts | 4 + .../workflow-sharing.service.test.ts | 75 ++++++++++++++- .../src/services}/workflow-sharing.service.ts | 57 ++---------- .../shared-workflow.repository.test.ts | 93 +++++++++++++++++++ .../shared-workflow.repository.ts | 60 ++++++++++++ packages/cli/eslint.config.mjs | 1 - packages/cli/oxlint.config.mts | 1 - .../__tests__/active-workflow-manager.test.ts | 3 +- .../binary-data-access.service.test.ts | 2 +- .../binary-data/binary-data-access.service.ts | 2 +- .../__tests__/execution-list.service.test.ts | 3 +- ...ution-recovery.service.integration.test.ts | 2 +- .../__tests__/executions.controller.test.ts | 2 +- .../src/executions/execution-list.service.ts | 3 +- .../src/executions/executions.controller.ts | 2 +- .../__tests__/insights.controller.test.ts | 2 +- .../insights.service.integration.test.ts | 2 +- .../__tests__/insights.service.test.ts | 2 +- .../src/modules/insights/insights.service.ts | 2 +- .../executions.public.controller.ts | 3 +- .../active-workflows.service.test.ts | 2 +- .../src/services/active-workflows.service.ts | 2 +- .../workflow-push-notifier.service.test.ts | 2 +- .../publication-status-reporter.test.ts | 2 +- .../workflow-push-notifier.service.ts | 2 +- .../repositories/workflow.repository.test.ts | 10 +- .../workflow-sharing.service.test.ts | 2 +- 27 files changed, 261 insertions(+), 82 deletions(-) rename packages/{cli/src/workflows => @n8n/backend-services/src/services}/__tests__/workflow-sharing.service.test.ts (64%) rename packages/{cli/src/workflows => @n8n/backend-services/src/services}/workflow-sharing.service.ts (79%) diff --git a/packages/@n8n/backend-services/src/index.ts b/packages/@n8n/backend-services/src/index.ts index d1651f587ed..64b59e55385 100644 --- a/packages/@n8n/backend-services/src/index.ts +++ b/packages/@n8n/backend-services/src/index.ts @@ -14,6 +14,10 @@ export { type RoleDeletionChecker, } from './services/role-deletion-check-proxy.service'; export { RoleService } from './services/role.service'; +export { + WorkflowSharingService, + type ShareWorkflowOptions, +} from './services/workflow-sharing.service'; export { FolderFinderService } from './services/folder-finder.service'; export { UrlService } from './services/url.service'; export { diff --git a/packages/cli/src/workflows/__tests__/workflow-sharing.service.test.ts b/packages/@n8n/backend-services/src/services/__tests__/workflow-sharing.service.test.ts similarity index 64% rename from packages/cli/src/workflows/__tests__/workflow-sharing.service.test.ts rename to packages/@n8n/backend-services/src/services/__tests__/workflow-sharing.service.test.ts index b93d80f8b90..7a188e01113 100644 --- a/packages/cli/src/workflows/__tests__/workflow-sharing.service.test.ts +++ b/packages/@n8n/backend-services/src/services/__tests__/workflow-sharing.service.test.ts @@ -1,9 +1,13 @@ import type { Logger, LicenseState } from '@n8n/backend-common'; -import type { ProjectRelationRepository, SharedWorkflowRepository, UserRepository } from '@n8n/db'; +import type { + ProjectRelationRepository, + SharedWorkflowRepository, + User, + UserRepository, +} from '@n8n/db'; import { mock } from 'vitest-mock-extended'; -import type { RoleService } from '@n8n/backend-services'; - +import type { RoleService } from '../role.service'; import { WorkflowSharingService } from '../workflow-sharing.service'; describe('WorkflowSharingService', () => { @@ -22,10 +26,73 @@ describe('WorkflowSharingService', () => { userRepository, logger, ); + const globalUser: User = mock({ + id: 'global-user', + role: { scopes: [{ slug: 'workflow:read' }] }, + }); + const member: User = mock({ id: 'member', role: { scopes: [] } }); + + beforeEach(() => { + vi.clearAllMocks(); + }); + + describe('getSharedWorkflowIds', () => { + it('returns project workflows directly for users with global access', async () => { + sharedWorkflowRepository.findWorkflowIdsForGlobalAccess.mockResolvedValue(['workflow-1']); + + const result = await service.getSharedWorkflowIds(globalUser, { + scopes: ['workflow:read'], + projectId: 'project-1', + }); + + expect(sharedWorkflowRepository.findWorkflowIdsForGlobalAccess).toHaveBeenCalledWith( + 'project-1', + ); + expect(roleService.rolesWithScope).not.toHaveBeenCalled(); + expect(result).toEqual(['workflow-1']); + }); + + it('resolves roles before querying workflows for other users', async () => { + roleService.rolesWithScope.mockImplementation(async (namespace) => + namespace === 'project' ? ['project:viewer'] : ['workflow:owner'], + ); + sharedWorkflowRepository.findWorkflowIdsAccessibleToUser.mockResolvedValue(['workflow-1']); + + const result = await service.getSharedWorkflowIds(member, { + scopes: ['workflow:read'], + }); + + expect(sharedWorkflowRepository.findWorkflowIdsAccessibleToUser).toHaveBeenCalledWith( + member.id, + ['workflow:owner'], + ['project:viewer'], + ); + expect(result).toEqual(['workflow-1']); + }); + }); + + it('gets workflow IDs shared with the user from the repository', async () => { + sharedWorkflowRepository.findWorkflowIdsSharedWithUser.mockResolvedValue(['workflow-1']); + + await expect(service.getSharedWithMeIds(member)).resolves.toEqual(['workflow-1']); + expect(sharedWorkflowRepository.findWorkflowIdsSharedWithUser).toHaveBeenCalledWith(member.id); + }); + + it('gets workflow IDs owned in the personal project from the repository', async () => { + sharedWorkflowRepository.findOwnedWorkflowIdsInPersonalProject.mockResolvedValue([ + 'workflow-1', + ]); + + await expect(service.getOwnedWorkflowsInPersonalProject(member.id)).resolves.toEqual([ + 'workflow-1', + ]); + expect(sharedWorkflowRepository.findOwnedWorkflowIdsInPersonalProject).toHaveBeenCalledWith( + member.id, + ); + }); describe('getUserIdsWithAccessToWorkflow', () => { beforeEach(() => { - vi.clearAllMocks(); roleService.rolesWithScope.mockImplementation(async (namespace) => { if (namespace === 'global') return ['global:owner', 'global:admin']; if (namespace === 'project') return ['project:editor']; diff --git a/packages/cli/src/workflows/workflow-sharing.service.ts b/packages/@n8n/backend-services/src/services/workflow-sharing.service.ts similarity index 79% rename from packages/cli/src/workflows/workflow-sharing.service.ts rename to packages/@n8n/backend-services/src/services/workflow-sharing.service.ts index 603b551ea40..f499c4b6a2e 100644 --- a/packages/cli/src/workflows/workflow-sharing.service.ts +++ b/packages/@n8n/backend-services/src/services/workflow-sharing.service.ts @@ -9,9 +9,8 @@ import { type Scope, PROJECT_OWNER_ROLE_SLUG, } from '@n8n/permissions'; -import { In } from '@n8n/typeorm'; -import { RoleService } from '@n8n/backend-services'; +import { RoleService } from './role.service'; export type ShareWorkflowOptions = | { scopes: Scope[]; projectId?: string } @@ -40,11 +39,7 @@ export class WorkflowSharingService { const { projectId } = options; if (hasGlobalScope(user, 'workflow:read')) { - const sharedWorkflows = await this.sharedWorkflowRepository.find({ - select: ['workflowId'], - ...(projectId && { where: { projectId } }), - }); - return sharedWorkflows.map(({ workflowId }) => workflowId); + return await this.sharedWorkflowRepository.findWorkflowIdsForGlobalAccess(projectId); } const projectRoles = @@ -56,20 +51,11 @@ export class WorkflowSharingService { ? await this.roleService.rolesWithScope('workflow', options.scopes) : options.workflowRoles; - const sharedWorkflows = await this.sharedWorkflowRepository.find({ - where: { - role: In(workflowRoles), - project: { - projectRelations: { - userId: user.id, - role: In(projectRoles), - }, - }, - }, - select: ['workflowId'], - }); - - return sharedWorkflows.map(({ workflowId }) => workflowId); + return await this.sharedWorkflowRepository.findWorkflowIdsAccessibleToUser( + user.id, + workflowRoles, + projectRoles, + ); } /** @@ -134,20 +120,7 @@ export class WorkflowSharingService { } async getSharedWithMeIds(user: User) { - const sharedWithMeWorkflows = await this.sharedWorkflowRepository.find({ - select: ['workflowId'], - where: { - role: 'workflow:editor', - project: { - projectRelations: { - userId: user.id, - role: { slug: PROJECT_OWNER_ROLE_SLUG }, - }, - }, - }, - }); - - return sharedWithMeWorkflows.map(({ workflowId }) => workflowId); + return await this.sharedWorkflowRepository.findWorkflowIdsSharedWithUser(user.id); } async getSharedWorkflowScopes( @@ -175,19 +148,7 @@ export class WorkflowSharingService { } async getOwnedWorkflowsInPersonalProject(userId: string): Promise { - const sharedWorkflows = await this.sharedWorkflowRepository.find({ - select: ['workflowId'], - where: { - role: 'workflow:owner', - project: { - projectRelations: { - userId, - role: { slug: PROJECT_OWNER_ROLE_SLUG }, - }, - }, - }, - }); - return sharedWorkflows.map(({ workflowId }) => workflowId); + return await this.sharedWorkflowRepository.findOwnedWorkflowIdsInPersonalProject(userId); } /** diff --git a/packages/@n8n/db/src/repositories/__tests__/shared-workflow.repository.test.ts b/packages/@n8n/db/src/repositories/__tests__/shared-workflow.repository.test.ts index ced665cfcf0..812d4507347 100644 --- a/packages/@n8n/db/src/repositories/__tests__/shared-workflow.repository.test.ts +++ b/packages/@n8n/db/src/repositories/__tests__/shared-workflow.repository.test.ts @@ -26,6 +26,99 @@ describe('SharedWorkflowRepository', () => { vi.spyOn(sharedWorkflowRepository, 'createQueryBuilder').mockReturnValue(queryBuilder); }); + describe('workflow access IDs', () => { + const rows = [ + mock({ workflowId: 'workflow-1' }), + mock({ workflowId: 'workflow-2' }), + ]; + + it('finds all workflow IDs for global access', async () => { + entityManager.find.mockResolvedValue(rows); + + const result = await sharedWorkflowRepository.findWorkflowIdsForGlobalAccess(); + + expect(entityManager.find).toHaveBeenCalledWith(SharedWorkflow, { + select: ['workflowId'], + }); + expect(result).toEqual(['workflow-1', 'workflow-2']); + }); + + it('limits global access workflow IDs to a project', async () => { + entityManager.find.mockResolvedValue(rows); + + await sharedWorkflowRepository.findWorkflowIdsForGlobalAccess('project-1'); + + expect(entityManager.find).toHaveBeenCalledWith(SharedWorkflow, { + select: ['workflowId'], + where: { projectId: 'project-1' }, + }); + }); + + it('finds workflow IDs accessible through project and workflow roles', async () => { + entityManager.find.mockResolvedValue(rows); + + const result = await sharedWorkflowRepository.findWorkflowIdsAccessibleToUser( + 'user-1', + ['workflow:owner'], + ['project:viewer'], + ); + + expect(entityManager.find).toHaveBeenCalledWith(SharedWorkflow, { + select: ['workflowId'], + where: { + role: In(['workflow:owner']), + project: { + projectRelations: { + userId: 'user-1', + role: { slug: In(['project:viewer']) }, + }, + }, + }, + }); + expect(result).toEqual(['workflow-1', 'workflow-2']); + }); + + it('finds workflow IDs shared with a user', async () => { + entityManager.find.mockResolvedValue(rows); + + const result = await sharedWorkflowRepository.findWorkflowIdsSharedWithUser('user-1'); + + expect(entityManager.find).toHaveBeenCalledWith(SharedWorkflow, { + select: ['workflowId'], + where: { + role: 'workflow:editor', + project: { + projectRelations: { + userId: 'user-1', + role: { slug: 'project:personalOwner' }, + }, + }, + }, + }); + expect(result).toEqual(['workflow-1', 'workflow-2']); + }); + + it('finds workflow IDs owned in a personal project', async () => { + entityManager.find.mockResolvedValue(rows); + + const result = await sharedWorkflowRepository.findOwnedWorkflowIdsInPersonalProject('user-1'); + + expect(entityManager.find).toHaveBeenCalledWith(SharedWorkflow, { + select: ['workflowId'], + where: { + role: 'workflow:owner', + project: { + projectRelations: { + userId: 'user-1', + role: { slug: 'project:personalOwner' }, + }, + }, + }, + }); + expect(result).toEqual(['workflow-1', 'workflow-2']); + }); + }); + describe('findOwnedWorkflowRemovalCandidates', () => { const rootWorkflow = mock({ id: 'root', diff --git a/packages/@n8n/db/src/repositories/shared-workflow.repository.ts b/packages/@n8n/db/src/repositories/shared-workflow.repository.ts index bdd486d38d9..cf0df0a234f 100644 --- a/packages/@n8n/db/src/repositories/shared-workflow.repository.ts +++ b/packages/@n8n/db/src/repositories/shared-workflow.repository.ts @@ -25,6 +25,66 @@ export class SharedWorkflowRepository extends BaseRepository { super(SharedWorkflow, dataSource.manager, transactionRunner); } + async findWorkflowIdsForGlobalAccess(projectId?: string): Promise { + const rows = await this.find({ + select: ['workflowId'], + ...(projectId ? { where: { projectId } } : {}), + }); + return rows.map(({ workflowId }) => workflowId); + } + + async findWorkflowIdsAccessibleToUser( + userId: string, + workflowRoleSlugs: string[], + projectRoleSlugs: string[], + ): Promise { + const rows = await this.find({ + where: { + role: In(workflowRoleSlugs), + project: { + projectRelations: { + userId, + role: { slug: In(projectRoleSlugs) }, + }, + }, + }, + select: ['workflowId'], + }); + return rows.map(({ workflowId }) => workflowId); + } + + async findWorkflowIdsSharedWithUser(userId: string): Promise { + const rows = await this.find({ + select: ['workflowId'], + where: { + role: 'workflow:editor', + project: { + projectRelations: { + userId, + role: { slug: PROJECT_OWNER_ROLE_SLUG }, + }, + }, + }, + }); + return rows.map(({ workflowId }) => workflowId); + } + + async findOwnedWorkflowIdsInPersonalProject(userId: string): Promise { + const rows = await this.find({ + select: ['workflowId'], + where: { + role: 'workflow:owner', + project: { + projectRelations: { + userId, + role: { slug: PROJECT_OWNER_ROLE_SLUG }, + }, + }, + }, + }); + return rows.map(({ workflowId }) => workflowId); + } + async findOwnedWorkflowRemovalCandidates( projectId: string, workflowIds: string[], diff --git a/packages/cli/eslint.config.mjs b/packages/cli/eslint.config.mjs index 38eb5ce025e..4dbb7aef590 100644 --- a/packages/cli/eslint.config.mjs +++ b/packages/cli/eslint.config.mjs @@ -311,7 +311,6 @@ export default defineConfig( // workflows/ './src/workflows/workflow-finder.service.ts', './src/workflows/workflow-history/workflow-history.service.ts', - './src/workflows/workflow-sharing.service.ts', './src/workflows/workflow-validation.service.ts', './src/workflows/workflow.service.ee.ts', './src/workflows/workflow.service.ts', diff --git a/packages/cli/oxlint.config.mts b/packages/cli/oxlint.config.mts index 0906bcd0ca5..6d7bd67575e 100644 --- a/packages/cli/oxlint.config.mts +++ b/packages/cli/oxlint.config.mts @@ -312,7 +312,6 @@ export default defineConfig({ // workflows/ './src/workflows/workflow-finder.service.ts', './src/workflows/workflow-history/workflow-history.service.ts', - './src/workflows/workflow-sharing.service.ts', './src/workflows/workflow-validation.service.ts', './src/workflows/workflow.service.ee.ts', './src/workflows/workflow.service.ts', diff --git a/packages/cli/src/__tests__/active-workflow-manager.test.ts b/packages/cli/src/__tests__/active-workflow-manager.test.ts index 4a8b91b140b..700fef56457 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 } from '@n8n/backend-services'; +import type { EventService, WorkflowSharingService } 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'; @@ -50,7 +50,6 @@ 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'; import { WorkflowPushNotifier } from '@/workflows/workflow-push-notifier.service'; -import type { WorkflowSharingService } from '@/workflows/workflow-sharing.service'; import type { WorkflowStaticDataService } from '@/workflows/workflow-static-data.service'; describe('ActiveWorkflowManager', () => { diff --git a/packages/cli/src/binary-data/__tests__/binary-data-access.service.test.ts b/packages/cli/src/binary-data/__tests__/binary-data-access.service.test.ts index 1e4003a5974..39fac7008a7 100644 --- a/packages/cli/src/binary-data/__tests__/binary-data-access.service.test.ts +++ b/packages/cli/src/binary-data/__tests__/binary-data-access.service.test.ts @@ -1,7 +1,7 @@ import type { BinaryDataRepository, ExecutionRepository, User } from '@n8n/db'; import { mock } from 'vitest-mock-extended'; -import type { WorkflowSharingService } from '@/workflows/workflow-sharing.service'; +import type { WorkflowSharingService } from '@n8n/backend-services'; import { BinaryDataAccessService } from '../binary-data-access.service'; diff --git a/packages/cli/src/binary-data/binary-data-access.service.ts b/packages/cli/src/binary-data/binary-data-access.service.ts index a63ff63d0db..14bde51d6d4 100644 --- a/packages/cli/src/binary-data/binary-data-access.service.ts +++ b/packages/cli/src/binary-data/binary-data-access.service.ts @@ -3,7 +3,7 @@ import { BinaryDataRepository, ExecutionRepository } from '@n8n/db'; import { Service } from '@n8n/di'; import { parseExecutionFileId, TEMP_EXECUTION_ID } from 'n8n-core'; -import { WorkflowSharingService } from '@/workflows/workflow-sharing.service'; +import { WorkflowSharingService } from '@n8n/backend-services'; /** * Workflow that a binary derives its access from. Normally the workflow of the diff --git a/packages/cli/src/executions/__tests__/execution-list.service.test.ts b/packages/cli/src/executions/__tests__/execution-list.service.test.ts index 3f1892aa75b..158c01f1d76 100644 --- a/packages/cli/src/executions/__tests__/execution-list.service.test.ts +++ b/packages/cli/src/executions/__tests__/execution-list.service.test.ts @@ -3,8 +3,7 @@ import { Container } from '@n8n/di'; import { mock } from 'vitest-mock-extended'; import type { EngineDataPlaneProxyService } from '@/services/engine-data-plane-proxy.service'; -import type { RoleService } from '@n8n/backend-services'; -import type { WorkflowSharingService } from '@/workflows/workflow-sharing.service'; +import type { RoleService, WorkflowSharingService } from '@n8n/backend-services'; import type { ExecutionCursor } from '../execution-cursor'; import { COMPLETED_STATUSES, type ExecutionListV1Service } from '../execution-list-v1.service'; 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 021abd34f0a..c5ef0ce0313 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 @@ -36,7 +36,7 @@ import { Push } from '@/push'; import { OwnershipService } from '@/services/ownership.service'; import { WorkflowPublicationNotifier } from '@/workflows/publication/workflow-publication-notifier'; import { WorkflowPushNotifier } from '@/workflows/workflow-push-notifier.service'; -import { WorkflowSharingService } from '@/workflows/workflow-sharing.service'; +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__/executions.controller.test.ts b/packages/cli/src/executions/__tests__/executions.controller.test.ts index cd50287fb7a..4591c2b501d 100644 --- a/packages/cli/src/executions/__tests__/executions.controller.test.ts +++ b/packages/cli/src/executions/__tests__/executions.controller.test.ts @@ -8,7 +8,7 @@ import type { ExecutionListService } from '@/executions/execution-list.service'; import type { ExecutionService } from '@/executions/execution.service'; import type { ExecutionRequest } from '@/executions/execution.types'; import { ExecutionsController } from '@/executions/executions.controller'; -import type { WorkflowSharingService } from '@/workflows/workflow-sharing.service'; +import type { WorkflowSharingService } from '@n8n/backend-services'; const V2_EXECUTION_ID = '01a038ae-c4a8-7799-8a3e-e3c2ca055cfa'; diff --git a/packages/cli/src/executions/execution-list.service.ts b/packages/cli/src/executions/execution-list.service.ts index 74d4100f2a8..839ffb29a79 100644 --- a/packages/cli/src/executions/execution-list.service.ts +++ b/packages/cli/src/executions/execution-list.service.ts @@ -3,8 +3,7 @@ import { Container, Service } from '@n8n/di'; import type { Scope } from '@n8n/permissions'; import { EngineDataPlaneProxyService } from '@/services/engine-data-plane-proxy.service'; -import { RoleService } from '@n8n/backend-services'; -import { WorkflowSharingService } from '@/workflows/workflow-sharing.service'; +import { RoleService, WorkflowSharingService } from '@n8n/backend-services'; import { hasPosition, type ExecutionCursor } from './execution-cursor'; import { diff --git a/packages/cli/src/executions/executions.controller.ts b/packages/cli/src/executions/executions.controller.ts index cc3c1a681e5..1c06233d4bf 100644 --- a/packages/cli/src/executions/executions.controller.ts +++ b/packages/cli/src/executions/executions.controller.ts @@ -7,7 +7,7 @@ import type { Response } from 'express'; import { BadRequestError, NotFoundError, NotImplementedError } from '@n8n/errors'; import { License } from '@/license'; import { isPositiveInteger } from '@/utils'; -import { WorkflowSharingService } from '@/workflows/workflow-sharing.service'; +import { WorkflowSharingService } from '@n8n/backend-services'; import { isExecutionIdV2 } from './execution-id'; import { ExecutionListService } from './execution-list.service'; diff --git a/packages/cli/src/modules/insights/__tests__/insights.controller.test.ts b/packages/cli/src/modules/insights/__tests__/insights.controller.test.ts index 55e4fd8365c..4e6e9645d93 100644 --- a/packages/cli/src/modules/insights/__tests__/insights.controller.test.ts +++ b/packages/cli/src/modules/insights/__tests__/insights.controller.test.ts @@ -6,7 +6,7 @@ import { DateTime } from 'luxon'; import { mock } from 'vitest-mock-extended'; import { BadRequestError, ForbiddenError } from '@n8n/errors'; -import { WorkflowSharingService } from '@/workflows/workflow-sharing.service'; +import { WorkflowSharingService } from '@n8n/backend-services'; import { TypeToNumber, type TypeUnitNumber } from '../database/entities/insights-shared'; import { InsightsByPeriodRepository } from '../database/repositories/insights-by-period.repository'; diff --git a/packages/cli/src/modules/insights/__tests__/insights.service.integration.test.ts b/packages/cli/src/modules/insights/__tests__/insights.service.integration.test.ts index 0d7eb16d860..cf34c7f3b80 100644 --- a/packages/cli/src/modules/insights/__tests__/insights.service.integration.test.ts +++ b/packages/cli/src/modules/insights/__tests__/insights.service.integration.test.ts @@ -19,7 +19,7 @@ import type { MockProxy } from 'vitest-mock-extended'; import { mock } from 'vitest-mock-extended'; import { ForbiddenError } from '@n8n/errors'; -import type { WorkflowSharingService } from '@/workflows/workflow-sharing.service'; +import type { WorkflowSharingService } from '@n8n/backend-services'; import { createMember } from '@test-integration/db/users'; import { createCompactedInsightsEvent } from '../database/entities/__tests__/db-utils'; diff --git a/packages/cli/src/modules/insights/__tests__/insights.service.test.ts b/packages/cli/src/modules/insights/__tests__/insights.service.test.ts index ba13759d75d..0c6a7cc1121 100644 --- a/packages/cli/src/modules/insights/__tests__/insights.service.test.ts +++ b/packages/cli/src/modules/insights/__tests__/insights.service.test.ts @@ -6,7 +6,7 @@ import type { MockProxy } from 'vitest-mock-extended'; import { mock } from 'vitest-mock-extended'; import { userHasScopes } from '@/permissions.ee/check-access'; -import type { WorkflowSharingService } from '@/workflows/workflow-sharing.service'; +import type { WorkflowSharingService } from '@n8n/backend-services'; import { TypeToNumber, type TypeUnitNumber } from '../database/entities/insights-shared'; import type { InsightsByPeriodRepository } from '../database/repositories/insights-by-period.repository'; diff --git a/packages/cli/src/modules/insights/insights.service.ts b/packages/cli/src/modules/insights/insights.service.ts index 14869f389f5..746e1b1d394 100644 --- a/packages/cli/src/modules/insights/insights.service.ts +++ b/packages/cli/src/modules/insights/insights.service.ts @@ -4,6 +4,7 @@ import { type RestrictedInsightsByTime, } from '@n8n/api-types'; import { LicenseState, Logger } from '@n8n/backend-common'; +import { WorkflowSharingService } from '@n8n/backend-services'; import type { User } from '@n8n/db'; import { Container, Service } from '@n8n/di'; import { DateTime } from 'luxon'; @@ -12,7 +13,6 @@ import { UserError } from 'n8n-workflow'; import { ForbiddenError } from '@n8n/errors'; import { userHasScopes } from '@/permissions.ee/check-access'; -import { WorkflowSharingService } from '@/workflows/workflow-sharing.service'; import type { PeriodUnit, TypeUnit, ByTimeInsightType } from './database/entities/insights-shared'; import { NumberToType } from './database/entities/insights-shared'; diff --git a/packages/cli/src/public-api/v1/controllers/executions.public.controller.ts b/packages/cli/src/public-api/v1/controllers/executions.public.controller.ts index 5fd427cf118..b6f157079a0 100644 --- a/packages/cli/src/public-api/v1/controllers/executions.public.controller.ts +++ b/packages/cli/src/public-api/v1/controllers/executions.public.controller.ts @@ -15,7 +15,7 @@ import { StoppedExecutionsPublicDto, TagIdsPublicDto, } from '@n8n/api-types'; -import { EventService } from '@n8n/backend-services'; +import { EventService, WorkflowSharingService } from '@n8n/backend-services'; import { ExecutionsConfig } from '@n8n/config'; import type { AuthenticatedRequest, IExecutionBase, IExecutionResponse } from '@n8n/db'; import { @@ -48,7 +48,6 @@ import { ExecutionService } from '@/executions/execution.service'; import type { StopResult } from '@/executions/execution.types'; import type { TracingContext } from '@/modules/otel/tracing-context'; import { decodeCursor, encodeNextCursor } from '@/public-api/v1/shared/services/pagination.service'; -import { WorkflowSharingService } from '@/workflows/workflow-sharing.service'; type PublicExecution = IExecutionBase & Partial; diff --git a/packages/cli/src/services/__tests__/active-workflows.service.test.ts b/packages/cli/src/services/__tests__/active-workflows.service.test.ts index d4e884f2dbd..13f0d0f040e 100644 --- a/packages/cli/src/services/__tests__/active-workflows.service.test.ts +++ b/packages/cli/src/services/__tests__/active-workflows.service.test.ts @@ -7,7 +7,7 @@ import { BadRequestError } from '@n8n/errors'; import type { ProjectScopeService } from '@/permissions.ee/project-scope.service'; import { ActiveWorkflowsService } from '@/services/active-workflows.service'; import type { WorkflowFinderService } from '@/workflows/workflow-finder.service'; -import type { WorkflowSharingService } from '@/workflows/workflow-sharing.service'; +import type { WorkflowSharingService } from '@n8n/backend-services'; describe('ActiveWorkflowsService', () => { const user = mock(); diff --git a/packages/cli/src/services/active-workflows.service.ts b/packages/cli/src/services/active-workflows.service.ts index b81682ad51b..b00079e5505 100644 --- a/packages/cli/src/services/active-workflows.service.ts +++ b/packages/cli/src/services/active-workflows.service.ts @@ -7,7 +7,7 @@ import { hasGlobalScope } from '@n8n/permissions'; import { ActivationErrorsService } from '@/activation-errors.service'; import { BadRequestError } from '@n8n/errors'; import { WorkflowFinderService } from '@/workflows/workflow-finder.service'; -import { WorkflowSharingService } from '@/workflows/workflow-sharing.service'; +import { WorkflowSharingService } from '@n8n/backend-services'; @Service() export class ActiveWorkflowsService { diff --git a/packages/cli/src/workflows/__tests__/workflow-push-notifier.service.test.ts b/packages/cli/src/workflows/__tests__/workflow-push-notifier.service.test.ts index c1cf516f4ae..751d90ffdf1 100644 --- a/packages/cli/src/workflows/__tests__/workflow-push-notifier.service.test.ts +++ b/packages/cli/src/workflows/__tests__/workflow-push-notifier.service.test.ts @@ -2,7 +2,7 @@ import { mock } from 'vitest-mock-extended'; import type { Push } from '@/push'; import { WorkflowPushNotifier } from '@/workflows/workflow-push-notifier.service'; -import type { WorkflowSharingService } from '@/workflows/workflow-sharing.service'; +import type { WorkflowSharingService } from '@n8n/backend-services'; describe('WorkflowPushNotifier', () => { const push = mock(); diff --git a/packages/cli/src/workflows/publication/__tests__/publication-status-reporter.test.ts b/packages/cli/src/workflows/publication/__tests__/publication-status-reporter.test.ts index 58859bf62a8..a0d28f17cf9 100644 --- a/packages/cli/src/workflows/publication/__tests__/publication-status-reporter.test.ts +++ b/packages/cli/src/workflows/publication/__tests__/publication-status-reporter.test.ts @@ -16,7 +16,7 @@ import type { Push } from '@/push'; import type { Publisher } from '@/scaling/pubsub/publisher.service'; import { PublicationStatusReporter } from '@/workflows/publication/publication-status-reporter'; import { WorkflowPushNotifier } from '@/workflows/workflow-push-notifier.service'; -import type { WorkflowSharingService } from '@/workflows/workflow-sharing.service'; +import type { WorkflowSharingService } from '@n8n/backend-services'; describe('PublicationStatusReporter', () => { const logger = mock(); diff --git a/packages/cli/src/workflows/workflow-push-notifier.service.ts b/packages/cli/src/workflows/workflow-push-notifier.service.ts index c9e5939017f..3668cc3b075 100644 --- a/packages/cli/src/workflows/workflow-push-notifier.service.ts +++ b/packages/cli/src/workflows/workflow-push-notifier.service.ts @@ -2,7 +2,7 @@ import type { PushMessage } from '@n8n/api-types'; import { Service } from '@n8n/di'; import { Push } from '@/push'; -import { WorkflowSharingService } from '@/workflows/workflow-sharing.service'; +import { WorkflowSharingService } from '@n8n/backend-services'; /** Sends a push message only to users who can currently read the workflow it concerns. */ @Service() diff --git a/packages/cli/test/integration/database/repositories/workflow.repository.test.ts b/packages/cli/test/integration/database/repositories/workflow.repository.test.ts index 816a54222a0..bb33c37a0e8 100644 --- a/packages/cli/test/integration/database/repositories/workflow.repository.test.ts +++ b/packages/cli/test/integration/database/repositories/workflow.repository.test.ts @@ -1131,7 +1131,7 @@ describe('WorkflowRepository', () => { // ARRANGE const { createMember } = await import('../../shared/db/users.js'); const { createTeamProject, linkUserToProject } = await import('@n8n/backend-test-utils'); - const { WorkflowSharingService } = await import('@/workflows/workflow-sharing.service.js'); + const { WorkflowSharingService } = await import('@n8n/backend-services'); const { RoleService } = await import('@n8n/backend-services'); const member = await createMember(); @@ -1176,7 +1176,7 @@ describe('WorkflowRepository', () => { // ARRANGE const { createOwner } = await import('../../shared/db/users.js'); const { getPersonalProject } = await import('@n8n/backend-test-utils'); - const { WorkflowSharingService } = await import('@/workflows/workflow-sharing.service.js'); + const { WorkflowSharingService } = await import('@n8n/backend-services'); const owner = await createOwner(); const personalProject = await getPersonalProject(owner); @@ -1217,7 +1217,7 @@ describe('WorkflowRepository', () => { // ARRANGE const { createOwner } = await import('../../shared/db/users.js'); const { getPersonalProject } = await import('@n8n/backend-test-utils'); - const { WorkflowSharingService } = await import('@/workflows/workflow-sharing.service.js'); + const { WorkflowSharingService } = await import('@n8n/backend-services'); const owner = await createOwner(); const personalProject = await getPersonalProject(owner); @@ -1269,7 +1269,7 @@ describe('WorkflowRepository', () => { // ARRANGE const { createMember } = await import('../../shared/db/users.js'); const { createTeamProject, linkUserToProject } = await import('@n8n/backend-test-utils'); - const { WorkflowSharingService } = await import('@/workflows/workflow-sharing.service.js'); + const { WorkflowSharingService } = await import('@n8n/backend-services'); const { RoleService } = await import('@n8n/backend-services'); const member = await createMember(); @@ -1351,7 +1351,7 @@ describe('WorkflowRepository', () => { // ARRANGE const { createMember } = await import('../../shared/db/users.js'); const { createTeamProject, linkUserToProject } = await import('@n8n/backend-test-utils'); - const { WorkflowSharingService } = await import('@/workflows/workflow-sharing.service.js'); + const { WorkflowSharingService } = await import('@n8n/backend-services'); const { RoleService } = await import('@n8n/backend-services'); // Create two separate users diff --git a/packages/cli/test/integration/workflows/workflow-sharing.service.test.ts b/packages/cli/test/integration/workflows/workflow-sharing.service.test.ts index f815ece55dc..aa3ba26e63c 100644 --- a/packages/cli/test/integration/workflows/workflow-sharing.service.test.ts +++ b/packages/cli/test/integration/workflows/workflow-sharing.service.test.ts @@ -5,7 +5,7 @@ import { Container } from '@n8n/di'; import { mock } from 'vitest-mock-extended'; import { ProjectService } from '@/services/project.service.ee'; -import { WorkflowSharingService } from '@/workflows/workflow-sharing.service'; +import { WorkflowSharingService } from '@n8n/backend-services'; import { createUser } from '../shared/db/users';