mirror of
https://github.com/n8n-io/n8n.git
synced 2025-02-02 07:01:30 -08:00
refactor(core): Port workflows config (no-changelog) (#10173)
This commit is contained in:
parent
9056242b3a
commit
b81f0bf9ea
20
packages/@n8n/config/src/configs/workflows.ts
Normal file
20
packages/@n8n/config/src/configs/workflows.ts
Normal file
|
@ -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';
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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', () => {
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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<Project>();
|
|||
|
||||
describe('SubworkflowPolicyChecker', () => {
|
||||
const license = mock<License>();
|
||||
const checker = new SubworkflowPolicyChecker(mock(), license, ownershipService);
|
||||
const globalConfig = mock<GlobalConfig>({
|
||||
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<GlobalConfig>({ workflows: { callerPolicyDefaultOption: 'none' } }),
|
||||
);
|
||||
|
||||
const parentWorkflow = mock<WorkflowEntity>();
|
||||
const subworkflow = mock<Workflow>(); // no caller policy
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
Loading…
Reference in a new issue