diff --git a/packages/cli/src/UserManagement/PermissionChecker.ts b/packages/cli/src/UserManagement/PermissionChecker.ts index e2e42a4481..c1bfcae759 100644 --- a/packages/cli/src/UserManagement/PermissionChecker.ts +++ b/packages/cli/src/UserManagement/PermissionChecker.ts @@ -3,7 +3,7 @@ import type { INode, Workflow } from 'n8n-workflow'; import { NodeOperationError, WorkflowOperationError } from 'n8n-workflow'; import config from '@/config'; -import { isSharingEnabled } from './UserManagementHelper'; +import { License } from '@/License'; import { OwnershipService } from '@/services/ownership.service'; import { RoleService } from '@/services/role.service'; import { UserRepository } from '@db/repositories/user.repository'; @@ -18,6 +18,7 @@ export class PermissionChecker { private readonly sharedWorkflowRepository: SharedWorkflowRepository, private readonly roleService: RoleService, private readonly ownershipService: OwnershipService, + private readonly license: License, ) {} /** @@ -46,7 +47,7 @@ export class PermissionChecker { let workflowUserIds = [userId]; - if (workflow.id && isSharingEnabled()) { + if (workflow.id && this.license.isSharingEnabled()) { const workflowSharings = await this.sharedWorkflowRepository.find({ relations: ['workflow'], where: { workflowId: workflow.id }, @@ -98,7 +99,7 @@ export class PermissionChecker { let policy = subworkflow.settings?.callerPolicy ?? config.getEnv('workflows.callerPolicyDefaultOption'); - if (!isSharingEnabled()) { + if (!this.license.isSharingEnabled()) { // Community version allows only same owner workflows policy = 'workflowsFromSameOwner'; } diff --git a/packages/cli/src/UserManagement/UserManagementHelper.ts b/packages/cli/src/UserManagement/UserManagementHelper.ts deleted file mode 100644 index 97557c45f9..0000000000 --- a/packages/cli/src/UserManagement/UserManagementHelper.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { Container } from 'typedi'; -import { License } from '@/License'; - -export function isSharingEnabled(): boolean { - return Container.get(License).isSharingEnabled(); -} diff --git a/packages/cli/src/credentials/credentials.controller.ee.ts b/packages/cli/src/credentials/credentials.controller.ee.ts index fadf0df227..0df219c297 100644 --- a/packages/cli/src/credentials/credentials.controller.ee.ts +++ b/packages/cli/src/credentials/credentials.controller.ee.ts @@ -5,7 +5,7 @@ import * as Db from '@/Db'; import * as ResponseHelper from '@/ResponseHelper'; import type { CredentialRequest } from '@/requests'; -import { isSharingEnabled } from '@/UserManagement/UserManagementHelper'; +import { License } from '@/License'; import { EECredentialsService as EECredentials } from './credentials.service.ee'; import { OwnershipService } from '@/services/ownership.service'; import { Container } from 'typedi'; @@ -24,7 +24,7 @@ import { InternalServerError } from '@/errors/response-errors/internal-server.er export const EECredentialsController = express.Router(); EECredentialsController.use((req, res, next) => { - if (!isSharingEnabled()) { + if (!Container.get(License).isSharingEnabled()) { // skip ee router and use free one next('router'); return; diff --git a/packages/cli/src/executions/executions.controller.ts b/packages/cli/src/executions/executions.controller.ts index 699ce509d2..5808b92d01 100644 --- a/packages/cli/src/executions/executions.controller.ts +++ b/packages/cli/src/executions/executions.controller.ts @@ -3,7 +3,7 @@ import { ExecutionRequest } from './execution.types'; import { ExecutionService } from './execution.service'; import { Authorized, Get, Post, RestController } from '@/decorators'; import { EnterpriseExecutionsService } from './execution.service.ee'; -import { isSharingEnabled } from '@/UserManagement/UserManagementHelper'; +import { License } from '@/License'; import { WorkflowSharingService } from '@/workflows/workflowSharing.service'; import type { User } from '@/databases/entities/User'; import config from '@/config'; @@ -21,10 +21,11 @@ export class ExecutionsController { private readonly enterpriseExecutionService: EnterpriseExecutionsService, private readonly workflowSharingService: WorkflowSharingService, private readonly activeExecutionService: ActiveExecutionService, + private readonly license: License, ) {} private async getAccessibleWorkflowIds(user: User) { - return isSharingEnabled() + return this.license.isSharingEnabled() ? await this.workflowSharingService.getSharedWorkflowIds(user) : await this.workflowSharingService.getSharedWorkflowIds(user, ['owner']); } @@ -68,7 +69,7 @@ export class ExecutionsController { if (workflowIds.length === 0) throw new NotFoundError('Execution not found'); - return isSharingEnabled() + return this.license.isSharingEnabled() ? await this.enterpriseExecutionService.findOne(req, workflowIds) : await this.executionService.findOne(req, workflowIds); } diff --git a/packages/cli/src/services/role.service.ts b/packages/cli/src/services/role.service.ts index b7c432632f..3deaeebfc2 100644 --- a/packages/cli/src/services/role.service.ts +++ b/packages/cli/src/services/role.service.ts @@ -4,7 +4,7 @@ import { SharedWorkflowRepository } from '@db/repositories/sharedWorkflow.reposi import { CacheService } from '@/services/cache/cache.service'; import type { RoleNames, RoleScopes } from '@db/entities/Role'; import { InvalidRoleError } from '@/errors/invalid-role.error'; -import { isSharingEnabled } from '@/UserManagement/UserManagementHelper'; +import { License } from '@/License'; @Service() export class RoleService { @@ -12,6 +12,7 @@ export class RoleService { private roleRepository: RoleRepository, private sharedWorkflowRepository: SharedWorkflowRepository, private cacheService: CacheService, + private readonly license: License, ) { void this.populateCache(); } @@ -103,6 +104,6 @@ export class RoleService { } async findCredentialOwnerRoleId() { - return isSharingEnabled() ? undefined : (await this.findCredentialOwnerRole()).id; + return this.license.isSharingEnabled() ? undefined : (await this.findCredentialOwnerRole()).id; } } diff --git a/packages/cli/src/workflows/workflows.controller.ts b/packages/cli/src/workflows/workflows.controller.ts index 71a2a054c4..a21df79ca5 100644 --- a/packages/cli/src/workflows/workflows.controller.ts +++ b/packages/cli/src/workflows/workflows.controller.ts @@ -21,7 +21,7 @@ import { validateEntity } from '@/GenericHelpers'; import { ExternalHooks } from '@/ExternalHooks'; import { ListQuery } from '@/requests'; import { WorkflowService } from './workflow.service'; -import { isSharingEnabled } from '@/UserManagement/UserManagementHelper'; +import { License } from '@/License'; import { InternalHooks } from '@/InternalHooks'; import { RoleService } from '@/services/role.service'; import * as utils from '@/utils'; @@ -64,6 +64,7 @@ export class WorkflowsController { private readonly workflowSharingService: WorkflowSharingService, private readonly sharedWorkflowRepository: SharedWorkflowRepository, private readonly userRepository: UserRepository, + private readonly license: License, private readonly mailer: UserManagementMailer, private readonly urlService: UrlService, ) {} @@ -92,7 +93,7 @@ export class WorkflowsController { WorkflowHelpers.addNodeIds(newWorkflow); - if (isSharingEnabled()) { + if (this.license.isSharingEnabled()) { // This is a new workflow, so we simply check if the user has access to // all used workflows @@ -150,7 +151,7 @@ export class WorkflowsController { @Get('/', { middlewares: listQueryMiddleware }) async getAll(req: ListQuery.Request, res: express.Response) { try { - const roles: RoleNames[] = isSharingEnabled() ? [] : ['owner']; + const roles: RoleNames[] = this.license.isSharingEnabled() ? [] : ['owner']; const sharedWorkflowIds = await this.workflowSharingService.getSharedWorkflowIds( req.user, roles, @@ -221,7 +222,7 @@ export class WorkflowsController { async getWorkflow(req: WorkflowRequest.Get) { const { id: workflowId } = req.params; - if (isSharingEnabled()) { + if (this.license.isSharingEnabled()) { const relations = ['shared', 'shared.user', 'shared.role']; if (!config.getEnv('workflowTagsDisabled')) { relations.push('tags'); @@ -280,7 +281,7 @@ export class WorkflowsController { const { tags, ...rest } = req.body; Object.assign(updateData, rest); - if (isSharingEnabled()) { + if (this.license.isSharingEnabled()) { updateData = await this.enterpriseWorkflowService.preventTampering( updateData, workflowId, @@ -293,8 +294,8 @@ export class WorkflowsController { updateData, workflowId, tags, - isSharingEnabled() ? forceSave : true, - isSharingEnabled() ? undefined : ['owner'], + this.license.isSharingEnabled() ? forceSave : true, + this.license.isSharingEnabled() ? undefined : ['owner'], ); return updatedWorkflow; @@ -320,7 +321,7 @@ export class WorkflowsController { @Post('/run') async runManually(req: WorkflowRequest.ManualRun) { - if (isSharingEnabled()) { + if (this.license.isSharingEnabled()) { const workflow = this.workflowRepository.create(req.body.workflowData); if (req.body.workflowData.id !== undefined) { @@ -342,7 +343,7 @@ export class WorkflowsController { @Put('/:workflowId/share') async share(req: WorkflowRequest.Share) { - if (!isSharingEnabled()) throw new NotFoundError('Route not found'); + if (!this.license.isSharingEnabled()) throw new NotFoundError('Route not found'); const { workflowId } = req.params; const { shareWithIds } = req.body; diff --git a/packages/cli/test/integration/credentials.ee.test.ts b/packages/cli/test/integration/credentials.ee.test.ts index e6a7413925..146fe2f4a5 100644 --- a/packages/cli/test/integration/credentials.ee.test.ts +++ b/packages/cli/test/integration/credentials.ee.test.ts @@ -3,7 +3,6 @@ import { In } from 'typeorm'; import type { IUser } from 'n8n-workflow'; import type { ListQuery } from '@/requests'; -import * as UserManagementHelpers from '@/UserManagement/UserManagementHelper'; import type { Role } from '@db/entities/Role'; import type { User } from '@db/entities/User'; @@ -16,10 +15,11 @@ import { getCredentialOwnerRole, getGlobalMemberRole, getGlobalOwnerRole } from import { createManyUsers, createUser, createUserShell } from './shared/db/users'; import { SharedCredentialsRepository } from '@db/repositories/sharedCredentials.repository'; import Container from 'typedi'; +import { License } from '@/License'; import { mockInstance } from '../shared/mocking'; import { UserManagementMailer } from '@/UserManagement/email'; -const sharingSpy = jest.spyOn(UserManagementHelpers, 'isSharingEnabled').mockReturnValue(true); +const sharingSpy = jest.spyOn(License.prototype, 'isSharingEnabled').mockReturnValue(true); const testServer = utils.setupTestServer({ endpointGroups: ['credentials'] }); let globalMemberRole: Role; diff --git a/packages/cli/test/integration/credentials.test.ts b/packages/cli/test/integration/credentials.test.ts index 09a8c2973f..992ea6fb71 100644 --- a/packages/cli/test/integration/credentials.test.ts +++ b/packages/cli/test/integration/credentials.test.ts @@ -1,7 +1,6 @@ import type { SuperAgentTest } from 'supertest'; import config from '@/config'; -import * as UserManagementHelpers from '@/UserManagement/UserManagementHelper'; import type { ListQuery } from '@/requests'; import type { Role } from '@db/entities/Role'; import type { User } from '@db/entities/User'; @@ -16,9 +15,10 @@ import { createManyUsers, createUser } from './shared/db/users'; import { CredentialsRepository } from '@db/repositories/credentials.repository'; import Container from 'typedi'; import { SharedCredentialsRepository } from '@db/repositories/sharedCredentials.repository'; +import { License } from '@/License'; // mock that credentialsSharing is not enabled -jest.spyOn(UserManagementHelpers, 'isSharingEnabled').mockReturnValue(false); +jest.spyOn(License.prototype, 'isSharingEnabled').mockReturnValue(false); const testServer = utils.setupTestServer({ endpointGroups: ['credentials'] }); let globalOwnerRole: Role; diff --git a/packages/cli/test/integration/workflows/workflows.controller.ee.test.ts b/packages/cli/test/integration/workflows/workflows.controller.ee.test.ts index e33bbadde7..bf7472c69a 100644 --- a/packages/cli/test/integration/workflows/workflows.controller.ee.test.ts +++ b/packages/cli/test/integration/workflows/workflows.controller.ee.test.ts @@ -7,7 +7,6 @@ import type { Role } from '@db/entities/Role'; import type { User } from '@db/entities/User'; import { WorkflowHistoryRepository } from '@db/repositories/workflowHistory.repository'; import { ActiveWorkflowRunner } from '@/ActiveWorkflowRunner'; -import * as UserManagementHelpers from '@/UserManagement/UserManagementHelper'; import { Push } from '@/push'; import { WorkflowSharingService } from '@/workflows/workflowSharing.service'; @@ -25,6 +24,7 @@ import { } from '../shared/db/roles'; import { createUser } from '../shared/db/users'; import { createWorkflow, getWorkflowSharing, shareWorkflowWithUsers } from '../shared/db/workflows'; +import { License } from '@/License'; import { UserManagementMailer } from '@/UserManagement/email'; let globalMemberRole: Role; @@ -39,7 +39,7 @@ let saveCredential: SaveCredentialFunction; const activeWorkflowRunner = mockInstance(ActiveWorkflowRunner); mockInstance(Push); -const sharingSpy = jest.spyOn(UserManagementHelpers, 'isSharingEnabled').mockReturnValue(true); +const sharingSpy = jest.spyOn(License.prototype, 'isSharingEnabled').mockReturnValue(true); const testServer = utils.setupTestServer({ endpointGroups: ['workflows'], enabledFeatures: ['feat:sharing'], diff --git a/packages/cli/test/integration/workflows/workflows.controller.test.ts b/packages/cli/test/integration/workflows/workflows.controller.test.ts index 47c8788889..345a466084 100644 --- a/packages/cli/test/integration/workflows/workflows.controller.test.ts +++ b/packages/cli/test/integration/workflows/workflows.controller.test.ts @@ -3,7 +3,6 @@ import type { SuperAgentTest } from 'supertest'; import { v4 as uuid } from 'uuid'; import type { INode, IPinData } from 'n8n-workflow'; -import * as UserManagementHelpers from '@/UserManagement/UserManagementHelper'; import type { User } from '@db/entities/User'; import { WorkflowRepository } from '@db/repositories/workflow.repository'; import type { WorkflowEntity } from '@db/entities/WorkflowEntity'; @@ -23,11 +22,12 @@ import { saveCredential } from '../shared/db/credentials'; import { createOwner } from '../shared/db/users'; import { createWorkflow } from '../shared/db/workflows'; import { createTag } from '../shared/db/tags'; +import { License } from '@/License'; let owner: User; let authOwnerAgent: SuperAgentTest; -jest.spyOn(UserManagementHelpers, 'isSharingEnabled').mockReturnValue(false); +jest.spyOn(License.prototype, 'isSharingEnabled').mockReturnValue(false); const testServer = utils.setupTestServer({ endpointGroups: ['workflows'] }); const license = testServer.license; @@ -640,7 +640,7 @@ describe('POST /workflows/run', () => { const enterpriseWorkflowService = Container.get(EnterpriseWorkflowService); const workflowRepository = Container.get(WorkflowRepository); - sharingSpy = jest.spyOn(UserManagementHelpers, 'isSharingEnabled'); + sharingSpy = jest.spyOn(License.prototype, 'isSharingEnabled'); tamperingSpy = jest.spyOn(enterpriseWorkflowService, 'preventTampering'); workflow = workflowRepository.create({ id: uuid() }); }); diff --git a/packages/cli/test/unit/controllers/executions.controller.test.ts b/packages/cli/test/unit/controllers/executions.controller.test.ts index ccae675cb9..04263ea2c8 100644 --- a/packages/cli/test/unit/controllers/executions.controller.test.ts +++ b/packages/cli/test/unit/controllers/executions.controller.test.ts @@ -34,6 +34,7 @@ describe('ExecutionsController', () => { mock(), workflowSharingService, activeExecutionService, + mock(), ).getActive(req); expect(activeExecutionService.findManyInQueueMode).toHaveBeenCalled(); @@ -48,6 +49,7 @@ describe('ExecutionsController', () => { mock(), workflowSharingService, activeExecutionService, + mock(), ).getActive(req); expect(activeExecutionService.findManyInQueueMode).not.toHaveBeenCalled(); @@ -67,6 +69,7 @@ describe('ExecutionsController', () => { mock(), workflowSharingService, activeExecutionService, + mock(), ).stop(req); await expect(promise).rejects.toThrow(NotFoundError); @@ -82,6 +85,7 @@ describe('ExecutionsController', () => { mock(), workflowSharingService, activeExecutionService, + mock(), ).stop(req); expect(activeExecutionService.stop).toHaveBeenCalled(); diff --git a/packages/cli/test/unit/services/events.service.test.ts b/packages/cli/test/unit/services/events.service.test.ts index bc1aeb6387..6504b691e8 100644 --- a/packages/cli/test/unit/services/events.service.test.ts +++ b/packages/cli/test/unit/services/events.service.test.ts @@ -17,8 +17,6 @@ import { UserService } from '@/services/user.service'; import { OwnershipService } from '@/services/ownership.service'; import { mockInstance } from '../../shared/mocking'; -jest.mock('@/UserManagement/UserManagementHelper', () => ({ getWorkflowOwner: jest.fn() })); - describe('EventsService', () => { const dbType = config.getEnv('database.type'); const fakeUser = mock({ id: 'abcde-fghij' });