From b81f0bf9ea8266e3c8606c4ef4dd31d9c3a32c29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Wed, 24 Jul 2024 14:38:29 +0200 Subject: [PATCH] refactor(core): Port workflows config (no-changelog) (#10173) --- packages/@n8n/config/src/configs/workflows.ts | 20 ++++++++++++++++++ packages/@n8n/config/src/index.ts | 4 ++++ packages/@n8n/config/test/config.test.ts | 5 +++++ packages/cli/src/config/schema.ts | 21 ------------------- packages/cli/src/services/frontend.service.ts | 2 +- .../subworkflow-policy-checker.test.ts | 13 ++++++++++-- .../subworkflow-policy-checker.service.ts | 5 +++-- .../cli/src/workflows/workflows.controller.ts | 6 ++++-- 8 files changed, 48 insertions(+), 28 deletions(-) create mode 100644 packages/@n8n/config/src/configs/workflows.ts diff --git a/packages/@n8n/config/src/configs/workflows.ts b/packages/@n8n/config/src/configs/workflows.ts new file mode 100644 index 0000000000..b19f4bc95d --- /dev/null +++ b/packages/@n8n/config/src/configs/workflows.ts @@ -0,0 +1,20 @@ +import { Config, Env } from '../decorators'; + +@Config +export class WorkflowsConfig { + /** Default name for workflow */ + @Env('WORKFLOWS_DEFAULT_NAME') + readonly defaultName: string = 'My workflow'; + + /** Show onboarding flow in new workflow */ + @Env('N8N_ONBOARDING_FLOW_DISABLED') + readonly onboardingFlowDisabled: boolean = false; + + /** Default option for which workflows may call the current workflow */ + @Env('N8N_WORKFLOW_CALLER_POLICY_DEFAULT_OPTION') + readonly callerPolicyDefaultOption: + | 'any' + | 'none' + | 'workflowsFromAList' + | 'workflowsFromSameOwner' = 'workflowsFromSameOwner'; +} diff --git a/packages/@n8n/config/src/index.ts b/packages/@n8n/config/src/index.ts index 33856fffc4..b32c7c7dc3 100644 --- a/packages/@n8n/config/src/index.ts +++ b/packages/@n8n/config/src/index.ts @@ -9,6 +9,7 @@ import { TemplatesConfig } from './configs/templates'; import { EventBusConfig } from './configs/event-bus'; import { NodesConfig } from './configs/nodes'; import { ExternalStorageConfig } from './configs/external-storage'; +import { WorkflowsConfig } from './configs/workflows'; @Config class UserManagementConfig { @@ -47,4 +48,7 @@ export class GlobalConfig { @Nested readonly externalStorage: ExternalStorageConfig; + + @Nested + readonly workflows: WorkflowsConfig; } diff --git a/packages/@n8n/config/test/config.test.ts b/packages/@n8n/config/test/config.test.ts index 68f49dfb09..90c9ee3240 100644 --- a/packages/@n8n/config/test/config.test.ts +++ b/packages/@n8n/config/test/config.test.ts @@ -135,6 +135,11 @@ describe('GlobalConfig', () => { }, }, }, + workflows: { + defaultName: 'My workflow', + onboardingFlowDisabled: false, + callerPolicyDefaultOption: 'workflowsFromSameOwner', + }, }; it('should use all default values when no env variables are defined', () => { diff --git a/packages/cli/src/config/schema.ts b/packages/cli/src/config/schema.ts index ebf32fe4d1..061ab08b36 100644 --- a/packages/cli/src/config/schema.ts +++ b/packages/cli/src/config/schema.ts @@ -12,27 +12,6 @@ convict.addFormat({ }); export const schema = { - workflows: { - defaultName: { - doc: 'Default name for workflow', - format: String, - default: 'My workflow', - env: 'WORKFLOWS_DEFAULT_NAME', - }, - onboardingFlowDisabled: { - doc: 'Show onboarding flow in new workflow', - format: Boolean, - default: false, - env: 'N8N_ONBOARDING_FLOW_DISABLED', - }, - callerPolicyDefaultOption: { - doc: 'Default option for which workflows may call the current workflow', - format: ['any', 'none', 'workflowsFromAList', 'workflowsFromSameOwner'] as const, - default: 'workflowsFromSameOwner', - env: 'N8N_WORKFLOW_CALLER_POLICY_DEFAULT_OPTION', - }, - }, - executions: { // TODO: remove this and all usage of `executions.process` when we're sure that nobody has this in their config file anymore. process: { diff --git a/packages/cli/src/services/frontend.service.ts b/packages/cli/src/services/frontend.service.ts index 97fb422ff3..918de17935 100644 --- a/packages/cli/src/services/frontend.service.ts +++ b/packages/cli/src/services/frontend.service.ts @@ -99,7 +99,7 @@ export class FrontendService { saveExecutionProgress: config.getEnv('executions.saveExecutionProgress'), executionTimeout: config.getEnv('executions.timeout'), maxExecutionTimeout: config.getEnv('executions.maxTimeout'), - workflowCallerPolicyDefaultOption: config.getEnv('workflows.callerPolicyDefaultOption'), + workflowCallerPolicyDefaultOption: this.globalConfig.workflows.callerPolicyDefaultOption, timezone: config.getEnv('generic.timezone'), urlBaseWebhook: this.urlService.getWebhookBaseUrl(), urlBaseEditor: instanceBaseUrl, diff --git a/packages/cli/src/subworkflows/__tests__/subworkflow-policy-checker.test.ts b/packages/cli/src/subworkflows/__tests__/subworkflow-policy-checker.test.ts index bb66220120..c20d8fdb2c 100644 --- a/packages/cli/src/subworkflows/__tests__/subworkflow-policy-checker.test.ts +++ b/packages/cli/src/subworkflows/__tests__/subworkflow-policy-checker.test.ts @@ -10,6 +10,7 @@ import { SubworkflowPolicyChecker } from '../subworkflow-policy-checker.service' import type { WorkflowEntity } from '@/databases/entities/WorkflowEntity'; import type { License } from '@/License'; +import type { GlobalConfig } from '@n8n/config'; const toTargetCallErrorMsg = (subworkflowId: string) => `Target workflow ID ${subworkflowId} may not be called`; @@ -19,7 +20,10 @@ const memberPersonalProject = mock(); describe('SubworkflowPolicyChecker', () => { const license = mock(); - const checker = new SubworkflowPolicyChecker(mock(), license, ownershipService); + const globalConfig = mock({ + workflows: { callerPolicyDefaultOption: 'workflowsFromSameOwner' }, + }); + const checker = new SubworkflowPolicyChecker(mock(), license, ownershipService, globalConfig); beforeEach(() => { license.isSharingEnabled.mockReturnValue(true); @@ -31,7 +35,12 @@ describe('SubworkflowPolicyChecker', () => { describe('no caller policy', () => { test('should fall back to N8N_WORKFLOW_CALLER_POLICY_DEFAULT_OPTION', async () => { - config.set('workflows.callerPolicyDefaultOption', 'none'); + const checker = new SubworkflowPolicyChecker( + mock(), + license, + ownershipService, + mock({ workflows: { callerPolicyDefaultOption: 'none' } }), + ); const parentWorkflow = mock(); const subworkflow = mock(); // no caller policy diff --git a/packages/cli/src/subworkflows/subworkflow-policy-checker.service.ts b/packages/cli/src/subworkflows/subworkflow-policy-checker.service.ts index ee7bdcd899..d2448cabaf 100644 --- a/packages/cli/src/subworkflows/subworkflow-policy-checker.service.ts +++ b/packages/cli/src/subworkflows/subworkflow-policy-checker.service.ts @@ -1,6 +1,6 @@ import { Service } from 'typedi'; import { WorkflowOperationError } from 'n8n-workflow'; -import config from '@/config'; +import { GlobalConfig } from '@n8n/config'; import { Logger } from '@/Logger'; import { License } from '@/License'; import { OwnershipService } from '@/services/ownership.service'; @@ -12,6 +12,7 @@ export class SubworkflowPolicyChecker { private readonly logger: Logger, private readonly license: License, private readonly ownershipService: OwnershipService, + private readonly globalConfig: GlobalConfig, ) {} async check(subworkflow: Workflow, parentWorkflowId: string, node?: INode) { @@ -28,7 +29,7 @@ export class SubworkflowPolicyChecker { } let policy = - subworkflow.settings?.callerPolicy ?? config.getEnv('workflows.callerPolicyDefaultOption'); + subworkflow.settings?.callerPolicy ?? this.globalConfig.workflows.callerPolicyDefaultOption; const isSharingEnabled = this.license.isSharingEnabled(); diff --git a/packages/cli/src/workflows/workflows.controller.ts b/packages/cli/src/workflows/workflows.controller.ts index f236f6dbaa..d0ec019586 100644 --- a/packages/cli/src/workflows/workflows.controller.ts +++ b/packages/cli/src/workflows/workflows.controller.ts @@ -43,6 +43,7 @@ import type { Project } from '@/databases/entities/Project'; import { ProjectRelationRepository } from '@/databases/repositories/projectRelation.repository'; import { z } from 'zod'; import { EventService } from '@/eventbus/event.service'; +import { GlobalConfig } from '@n8n/config'; @RestController('/workflows') export class WorkflowsController { @@ -67,6 +68,7 @@ export class WorkflowsController { private readonly projectService: ProjectService, private readonly projectRelationRepository: ProjectRelationRepository, private readonly eventService: EventService, + private readonly globalConfig: GlobalConfig, ) {} @Post('/') @@ -204,12 +206,12 @@ export class WorkflowsController { @Get('/new') async getNewName(req: WorkflowRequest.NewName) { - const requestedName = req.query.name ?? config.getEnv('workflows.defaultName'); + const requestedName = req.query.name ?? this.globalConfig.workflows.defaultName; const name = await this.namingService.getUniqueWorkflowName(requestedName); const onboardingFlowEnabled = - !config.getEnv('workflows.onboardingFlowDisabled') && + !this.globalConfig.workflows.onboardingFlowDisabled && !req.user.settings?.isOnboarded && (await this.userOnboardingService.isBelowThreshold(req.user));