mirror of
https://github.com/n8n-io/n8n.git
synced 2026-10-17 05:29:44 +02:00
refactor(core): Move workflow sharing service to backend services (no-changelog) (#40157)
This commit is contained in:
parent
aae8016c84
commit
69595f5821
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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<User>({
|
||||
id: 'global-user',
|
||||
role: { scopes: [{ slug: 'workflow:read' }] },
|
||||
});
|
||||
const member: User = mock<User>({ 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'];
|
||||
|
|
@ -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<string[]> {
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -26,6 +26,99 @@ describe('SharedWorkflowRepository', () => {
|
|||
vi.spyOn(sharedWorkflowRepository, 'createQueryBuilder').mockReturnValue(queryBuilder);
|
||||
});
|
||||
|
||||
describe('workflow access IDs', () => {
|
||||
const rows = [
|
||||
mock<SharedWorkflow>({ workflowId: 'workflow-1' }),
|
||||
mock<SharedWorkflow>({ 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<WorkflowEntity>({
|
||||
id: 'root',
|
||||
|
|
|
|||
|
|
@ -25,6 +25,66 @@ export class SharedWorkflowRepository extends BaseRepository<SharedWorkflow> {
|
|||
super(SharedWorkflow, dataSource.manager, transactionRunner);
|
||||
}
|
||||
|
||||
async findWorkflowIdsForGlobalAccess(projectId?: string): Promise<string[]> {
|
||||
const rows = await this.find({
|
||||
select: ['workflowId'],
|
||||
...(projectId ? { where: { projectId } } : {}),
|
||||
});
|
||||
return rows.map(({ workflowId }) => workflowId);
|
||||
}
|
||||
|
||||
async findWorkflowIdsAccessibleToUser(
|
||||
userId: string,
|
||||
workflowRoleSlugs: string[],
|
||||
projectRoleSlugs: string[],
|
||||
): Promise<string[]> {
|
||||
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<string[]> {
|
||||
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<string[]> {
|
||||
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[],
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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', () => {
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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<IExecutionResponse>;
|
||||
|
||||
|
|
|
|||
|
|
@ -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<User>();
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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<Push>();
|
||||
|
|
|
|||
|
|
@ -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<Logger>();
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user