mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-16 17:46:45 +00:00
refactor(core): Continue porting legacy schema (#16318)
This commit is contained in:
7
packages/@n8n/config/src/configs/deployment.config.ts
Normal file
7
packages/@n8n/config/src/configs/deployment.config.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { Config, Env } from '../decorators';
|
||||
|
||||
@Config
|
||||
export class DeploymentConfig {
|
||||
@Env('N8N_DEPLOYMENT_TYPE')
|
||||
type: string = 'default';
|
||||
}
|
||||
8
packages/@n8n/config/src/configs/hiring-banner.config.ts
Normal file
8
packages/@n8n/config/src/configs/hiring-banner.config.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { Config, Env } from '../decorators';
|
||||
|
||||
@Config
|
||||
export class HiringBannerConfig {
|
||||
/** Whether hiring banner in browser console is enabled. */
|
||||
@Env('N8N_HIRING_BANNER_ENABLED')
|
||||
enabled: boolean = true;
|
||||
}
|
||||
8
packages/@n8n/config/src/configs/mfa.config.ts
Normal file
8
packages/@n8n/config/src/configs/mfa.config.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { Config, Env } from '../decorators';
|
||||
|
||||
@Config
|
||||
export class MfaConfig {
|
||||
/** Whether to enable multi-factor authentication. */
|
||||
@Env('N8N_MFA_ENABLED')
|
||||
enabled: boolean = true;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import { Config, Env } from '../decorators';
|
||||
|
||||
@Config
|
||||
export class PersonalizationConfig {
|
||||
@Env('N8N_PERSONALIZATION_ENABLED')
|
||||
enabled: boolean = true;
|
||||
}
|
||||
@@ -5,17 +5,21 @@ import { AuthConfig } from './configs/auth.config';
|
||||
import { CacheConfig } from './configs/cache.config';
|
||||
import { CredentialsConfig } from './configs/credentials.config';
|
||||
import { DatabaseConfig } from './configs/database.config';
|
||||
import { DeploymentConfig } from './configs/deployment.config';
|
||||
import { DiagnosticsConfig } from './configs/diagnostics.config';
|
||||
import { EndpointsConfig } from './configs/endpoints.config';
|
||||
import { EventBusConfig } from './configs/event-bus.config';
|
||||
import { ExecutionsConfig } from './configs/executions.config';
|
||||
import { ExternalHooksConfig } from './configs/external-hooks.config';
|
||||
import { GenericConfig } from './configs/generic.config';
|
||||
import { HiringBannerConfig } from './configs/hiring-banner.config';
|
||||
import { LicenseConfig } from './configs/license.config';
|
||||
import { LoggingConfig } from './configs/logging.config';
|
||||
import { MfaConfig } from './configs/mfa.config';
|
||||
import { MultiMainSetupConfig } from './configs/multi-main-setup.config';
|
||||
import { NodesConfig } from './configs/nodes.config';
|
||||
import { PartialExecutionsConfig } from './configs/partial-executions.config';
|
||||
import { PersonalizationConfig } from './configs/personalization.config';
|
||||
import { PublicApiConfig } from './configs/public-api.config';
|
||||
import { TaskRunnersConfig } from './configs/runners.config';
|
||||
import { ScalingModeConfig } from './configs/scaling-mode.config';
|
||||
@@ -39,6 +43,10 @@ export { LOG_SCOPES } from './configs/logging.config';
|
||||
export type { LogScope } from './configs/logging.config';
|
||||
export { WorkflowsConfig } from './configs/workflows.config';
|
||||
export * from './custom-types';
|
||||
export { DeploymentConfig } from './configs/deployment.config';
|
||||
export { MfaConfig } from './configs/mfa.config';
|
||||
export { HiringBannerConfig } from './configs/hiring-banner.config';
|
||||
export { PersonalizationConfig } from './configs/personalization.config';
|
||||
|
||||
const protocolSchema = z.enum(['http', 'https']);
|
||||
|
||||
@@ -146,4 +154,28 @@ export class GlobalConfig {
|
||||
|
||||
@Nested
|
||||
workflowHistory: WorkflowHistoryConfig;
|
||||
|
||||
@Nested
|
||||
deployment: DeploymentConfig;
|
||||
|
||||
@Nested
|
||||
mfa: MfaConfig;
|
||||
|
||||
@Nested
|
||||
hiringBanner: HiringBannerConfig;
|
||||
|
||||
@Nested
|
||||
personalization: PersonalizationConfig;
|
||||
|
||||
/** Default locale for the UI. */
|
||||
@Env('N8N_DEFAULT_LOCALE')
|
||||
defaultLocale: string = 'en';
|
||||
|
||||
/** Whether to hide the page that shows active workflows and executions count. */
|
||||
@Env('N8N_HIDE_USAGE_PAGE')
|
||||
hideUsagePage: boolean = false;
|
||||
|
||||
/** Number of reverse proxies n8n is running behind. */
|
||||
@Env('N8N_PROXY_HOPS')
|
||||
proxy_hops: number = 0;
|
||||
}
|
||||
|
||||
@@ -33,6 +33,21 @@ describe('GlobalConfig', () => {
|
||||
secure: true,
|
||||
},
|
||||
},
|
||||
defaultLocale: 'en',
|
||||
hideUsagePage: false,
|
||||
deployment: {
|
||||
type: 'default',
|
||||
},
|
||||
mfa: {
|
||||
enabled: true,
|
||||
},
|
||||
hiringBanner: {
|
||||
enabled: true,
|
||||
},
|
||||
personalization: {
|
||||
enabled: true,
|
||||
},
|
||||
proxy_hops: 0,
|
||||
database: {
|
||||
logging: {
|
||||
enabled: false,
|
||||
|
||||
@@ -72,7 +72,7 @@ export abstract class AbstractServer {
|
||||
this.app.set('view engine', 'handlebars');
|
||||
this.app.set('views', TEMPLATES_DIR);
|
||||
|
||||
const proxyHops = config.getEnv('proxy_hops');
|
||||
const proxyHops = this.globalConfig.proxy_hops;
|
||||
if (proxyHops > 0) this.app.set('trust proxy', proxyHops);
|
||||
|
||||
this.sslKey = config.getEnv('ssl_key');
|
||||
@@ -260,7 +260,7 @@ export abstract class AbstractServer {
|
||||
if (!inTest) {
|
||||
this.logger.info(`Version: ${N8N_VERSION}`);
|
||||
|
||||
const defaultLocale = config.getEnv('defaultLocale');
|
||||
const { defaultLocale } = this.globalConfig;
|
||||
if (defaultLocale !== 'en') {
|
||||
this.logger.info(`Locale: ${defaultLocale}`);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { GlobalConfig } from '@n8n/config';
|
||||
import type { ExecutionRepository } from '@n8n/db';
|
||||
import { mock } from 'jest-mock-extended';
|
||||
import type { WorkflowExecuteMode as ExecutionMode } from 'n8n-workflow';
|
||||
@@ -21,6 +22,7 @@ describe('ConcurrencyControlService', () => {
|
||||
const executionRepository = mock<ExecutionRepository>();
|
||||
const telemetry = mock<Telemetry>();
|
||||
const eventService = mock<EventService>();
|
||||
const globalConfig = mock<GlobalConfig>();
|
||||
|
||||
afterEach(() => {
|
||||
config.set('executions.concurrency.productionLimit', -1);
|
||||
@@ -47,6 +49,7 @@ describe('ConcurrencyControlService', () => {
|
||||
executionRepository,
|
||||
telemetry,
|
||||
eventService,
|
||||
globalConfig,
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -73,7 +76,13 @@ describe('ConcurrencyControlService', () => {
|
||||
/**
|
||||
* Act
|
||||
*/
|
||||
new ConcurrencyControlService(logger, executionRepository, telemetry, eventService);
|
||||
new ConcurrencyControlService(
|
||||
logger,
|
||||
executionRepository,
|
||||
telemetry,
|
||||
eventService,
|
||||
globalConfig,
|
||||
);
|
||||
} catch (error) {
|
||||
/**
|
||||
* Assert
|
||||
@@ -98,6 +107,7 @@ describe('ConcurrencyControlService', () => {
|
||||
executionRepository,
|
||||
telemetry,
|
||||
eventService,
|
||||
globalConfig,
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -123,6 +133,7 @@ describe('ConcurrencyControlService', () => {
|
||||
executionRepository,
|
||||
telemetry,
|
||||
eventService,
|
||||
globalConfig,
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -148,6 +159,7 @@ describe('ConcurrencyControlService', () => {
|
||||
executionRepository,
|
||||
telemetry,
|
||||
eventService,
|
||||
globalConfig,
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -177,6 +189,7 @@ describe('ConcurrencyControlService', () => {
|
||||
executionRepository,
|
||||
telemetry,
|
||||
eventService,
|
||||
globalConfig,
|
||||
);
|
||||
const enqueueSpy = jest.spyOn(ConcurrencyQueue.prototype, 'enqueue');
|
||||
|
||||
@@ -203,6 +216,7 @@ describe('ConcurrencyControlService', () => {
|
||||
executionRepository,
|
||||
telemetry,
|
||||
eventService,
|
||||
globalConfig,
|
||||
);
|
||||
const enqueueSpy = jest.spyOn(ConcurrencyQueue.prototype, 'enqueue');
|
||||
|
||||
@@ -228,6 +242,7 @@ describe('ConcurrencyControlService', () => {
|
||||
executionRepository,
|
||||
telemetry,
|
||||
eventService,
|
||||
globalConfig,
|
||||
);
|
||||
const enqueueSpy = jest.spyOn(ConcurrencyQueue.prototype, 'enqueue');
|
||||
|
||||
@@ -257,6 +272,7 @@ describe('ConcurrencyControlService', () => {
|
||||
executionRepository,
|
||||
telemetry,
|
||||
eventService,
|
||||
globalConfig,
|
||||
);
|
||||
const dequeueSpy = jest.spyOn(ConcurrencyQueue.prototype, 'dequeue');
|
||||
|
||||
@@ -283,6 +299,7 @@ describe('ConcurrencyControlService', () => {
|
||||
executionRepository,
|
||||
telemetry,
|
||||
eventService,
|
||||
globalConfig,
|
||||
);
|
||||
const dequeueSpy = jest.spyOn(ConcurrencyQueue.prototype, 'dequeue');
|
||||
|
||||
@@ -308,6 +325,7 @@ describe('ConcurrencyControlService', () => {
|
||||
executionRepository,
|
||||
telemetry,
|
||||
eventService,
|
||||
globalConfig,
|
||||
);
|
||||
const dequeueSpy = jest.spyOn(ConcurrencyQueue.prototype, 'dequeue');
|
||||
|
||||
@@ -337,6 +355,7 @@ describe('ConcurrencyControlService', () => {
|
||||
executionRepository,
|
||||
telemetry,
|
||||
eventService,
|
||||
globalConfig,
|
||||
);
|
||||
const removeSpy = jest.spyOn(ConcurrencyQueue.prototype, 'remove');
|
||||
|
||||
@@ -365,6 +384,7 @@ describe('ConcurrencyControlService', () => {
|
||||
executionRepository,
|
||||
telemetry,
|
||||
eventService,
|
||||
globalConfig,
|
||||
);
|
||||
const removeSpy = jest.spyOn(ConcurrencyQueue.prototype, 'remove');
|
||||
|
||||
@@ -391,6 +411,7 @@ describe('ConcurrencyControlService', () => {
|
||||
executionRepository,
|
||||
telemetry,
|
||||
eventService,
|
||||
globalConfig,
|
||||
);
|
||||
const removeSpy = jest.spyOn(ConcurrencyQueue.prototype, 'remove');
|
||||
|
||||
@@ -420,6 +441,7 @@ describe('ConcurrencyControlService', () => {
|
||||
executionRepository,
|
||||
telemetry,
|
||||
eventService,
|
||||
globalConfig,
|
||||
);
|
||||
|
||||
jest
|
||||
@@ -459,6 +481,7 @@ describe('ConcurrencyControlService', () => {
|
||||
executionRepository,
|
||||
telemetry,
|
||||
eventService,
|
||||
globalConfig,
|
||||
);
|
||||
// @ts-expect-error Private property
|
||||
const queue = service.getQueue('webhook');
|
||||
@@ -485,6 +508,7 @@ describe('ConcurrencyControlService', () => {
|
||||
executionRepository,
|
||||
telemetry,
|
||||
eventService,
|
||||
globalConfig,
|
||||
);
|
||||
// @ts-expect-error Private property
|
||||
const queue = service.getQueue('evaluation');
|
||||
@@ -515,6 +539,7 @@ describe('ConcurrencyControlService', () => {
|
||||
executionRepository,
|
||||
telemetry,
|
||||
eventService,
|
||||
globalConfig,
|
||||
);
|
||||
const enqueueSpy = jest.spyOn(ConcurrencyQueue.prototype, 'enqueue');
|
||||
|
||||
@@ -541,6 +566,7 @@ describe('ConcurrencyControlService', () => {
|
||||
executionRepository,
|
||||
telemetry,
|
||||
eventService,
|
||||
globalConfig,
|
||||
);
|
||||
const enqueueSpy = jest.spyOn(ConcurrencyQueue.prototype, 'enqueue');
|
||||
|
||||
@@ -569,6 +595,7 @@ describe('ConcurrencyControlService', () => {
|
||||
executionRepository,
|
||||
telemetry,
|
||||
eventService,
|
||||
globalConfig,
|
||||
);
|
||||
const dequeueSpy = jest.spyOn(ConcurrencyQueue.prototype, 'dequeue');
|
||||
|
||||
@@ -594,6 +621,7 @@ describe('ConcurrencyControlService', () => {
|
||||
executionRepository,
|
||||
telemetry,
|
||||
eventService,
|
||||
globalConfig,
|
||||
);
|
||||
const dequeueSpy = jest.spyOn(ConcurrencyQueue.prototype, 'dequeue');
|
||||
|
||||
@@ -621,6 +649,7 @@ describe('ConcurrencyControlService', () => {
|
||||
executionRepository,
|
||||
telemetry,
|
||||
eventService,
|
||||
globalConfig,
|
||||
);
|
||||
const removeSpy = jest.spyOn(ConcurrencyQueue.prototype, 'remove');
|
||||
|
||||
@@ -646,6 +675,7 @@ describe('ConcurrencyControlService', () => {
|
||||
executionRepository,
|
||||
telemetry,
|
||||
eventService,
|
||||
globalConfig,
|
||||
);
|
||||
const removeSpy = jest.spyOn(ConcurrencyQueue.prototype, 'remove');
|
||||
|
||||
@@ -675,12 +705,13 @@ describe('ConcurrencyControlService', () => {
|
||||
* Arrange
|
||||
*/
|
||||
config.set('executions.concurrency.productionLimit', CLOUD_TEMP_PRODUCTION_LIMIT);
|
||||
config.set('deployment.type', 'cloud');
|
||||
globalConfig.deployment.type = 'cloud';
|
||||
const service = new ConcurrencyControlService(
|
||||
logger,
|
||||
executionRepository,
|
||||
telemetry,
|
||||
eventService,
|
||||
globalConfig,
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -708,12 +739,13 @@ describe('ConcurrencyControlService', () => {
|
||||
* Arrange
|
||||
*/
|
||||
config.set('executions.concurrency.productionLimit', CLOUD_TEMP_PRODUCTION_LIMIT);
|
||||
config.set('deployment.type', 'cloud');
|
||||
globalConfig.deployment.type = 'cloud';
|
||||
const service = new ConcurrencyControlService(
|
||||
logger,
|
||||
executionRepository,
|
||||
telemetry,
|
||||
eventService,
|
||||
globalConfig,
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -740,12 +772,13 @@ describe('ConcurrencyControlService', () => {
|
||||
* Arrange
|
||||
*/
|
||||
config.set('executions.concurrency.productionLimit', CLOUD_TEMP_PRODUCTION_LIMIT);
|
||||
config.set('deployment.type', 'cloud');
|
||||
globalConfig.deployment.type = 'cloud';
|
||||
const service = new ConcurrencyControlService(
|
||||
logger,
|
||||
executionRepository,
|
||||
telemetry,
|
||||
eventService,
|
||||
globalConfig,
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Logger } from '@n8n/backend-common';
|
||||
import { GlobalConfig } from '@n8n/config';
|
||||
import { ExecutionRepository } from '@n8n/db';
|
||||
import { Service } from '@n8n/di';
|
||||
import capitalize from 'lodash/capitalize';
|
||||
@@ -34,6 +35,7 @@ export class ConcurrencyControlService {
|
||||
private readonly executionRepository: ExecutionRepository,
|
||||
private readonly telemetry: Telemetry,
|
||||
private readonly eventService: EventService,
|
||||
private readonly globalConfig: GlobalConfig,
|
||||
) {
|
||||
this.logger = this.logger.scoped('concurrency');
|
||||
|
||||
@@ -185,7 +187,7 @@ export class ConcurrencyControlService {
|
||||
}
|
||||
|
||||
private shouldReport(capacity: number) {
|
||||
return config.getEnv('deployment.type') === 'cloud' && this.limitsToReport.includes(capacity);
|
||||
return this.globalConfig.deployment.type === 'cloud' && this.limitsToReport.includes(capacity);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -165,23 +165,6 @@ export const schema = {
|
||||
env: 'EXTERNAL_FRONTEND_HOOKS_URLS',
|
||||
},
|
||||
|
||||
deployment: {
|
||||
type: {
|
||||
format: String,
|
||||
default: 'default',
|
||||
env: 'N8N_DEPLOYMENT_TYPE',
|
||||
},
|
||||
},
|
||||
|
||||
mfa: {
|
||||
enabled: {
|
||||
format: Boolean,
|
||||
default: true,
|
||||
doc: 'Whether to enable MFA feature in instance.',
|
||||
env: 'N8N_MFA_ENABLED',
|
||||
},
|
||||
},
|
||||
|
||||
sso: {
|
||||
justInTimeProvisioning: {
|
||||
format: Boolean,
|
||||
@@ -223,38 +206,6 @@ export const schema = {
|
||||
},
|
||||
},
|
||||
|
||||
hiringBanner: {
|
||||
enabled: {
|
||||
doc: 'Whether hiring banner in browser console is enabled.',
|
||||
format: Boolean,
|
||||
default: true,
|
||||
env: 'N8N_HIRING_BANNER_ENABLED',
|
||||
},
|
||||
},
|
||||
|
||||
personalization: {
|
||||
enabled: {
|
||||
doc: 'Whether personalization is enabled.',
|
||||
format: Boolean,
|
||||
default: true,
|
||||
env: 'N8N_PERSONALIZATION_ENABLED',
|
||||
},
|
||||
},
|
||||
|
||||
defaultLocale: {
|
||||
doc: 'Default locale for the UI',
|
||||
format: String,
|
||||
default: 'en',
|
||||
env: 'N8N_DEFAULT_LOCALE',
|
||||
},
|
||||
|
||||
hideUsagePage: {
|
||||
format: Boolean,
|
||||
default: false,
|
||||
env: 'N8N_HIDE_USAGE_PAGE',
|
||||
doc: 'Hide or show the usage page',
|
||||
},
|
||||
|
||||
redis: {
|
||||
prefix: {
|
||||
doc: 'Prefix for all n8n related keys',
|
||||
@@ -285,11 +236,4 @@ export const schema = {
|
||||
env: 'N8N_AI_ENABLED',
|
||||
},
|
||||
},
|
||||
|
||||
proxy_hops: {
|
||||
format: Number,
|
||||
default: 0,
|
||||
env: 'N8N_PROXY_HOPS',
|
||||
doc: 'Number of reverse-proxies n8n is running behind',
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { GlobalConfig } from '@n8n/config';
|
||||
import { mock } from 'jest-mock-extended';
|
||||
|
||||
import config from '@/config';
|
||||
import type { TranslationRequest } from '@/controllers/translation.controller';
|
||||
import {
|
||||
TranslationController,
|
||||
@@ -10,9 +10,11 @@ import type { CredentialTypes } from '@/credential-types';
|
||||
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
||||
|
||||
describe('TranslationController', () => {
|
||||
const configGetSpy = jest.spyOn(config, 'getEnv');
|
||||
const credentialTypes = mock<CredentialTypes>();
|
||||
const controller = new TranslationController(credentialTypes);
|
||||
const controller = new TranslationController(
|
||||
credentialTypes,
|
||||
mock<GlobalConfig>({ defaultLocale: 'de' }),
|
||||
);
|
||||
|
||||
describe('getCredentialTranslation', () => {
|
||||
it('should throw 400 on invalid credential types', async () => {
|
||||
@@ -28,7 +30,6 @@ describe('TranslationController', () => {
|
||||
it('should return translation json on valid credential types', async () => {
|
||||
const credentialType = 'credential-type';
|
||||
const req = mock<TranslationRequest.Credential>({ query: { credentialType } });
|
||||
configGetSpy.mockReturnValue('de');
|
||||
credentialTypes.recognizes.calledWith(credentialType).mockReturnValue(true);
|
||||
const response = { translation: 'string' };
|
||||
jest.mock(`${CREDENTIAL_TRANSLATIONS_DIR}/de/credential-type.json`, () => response, {
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
import { GlobalConfig } from '@n8n/config';
|
||||
import { Post, RestController } from '@n8n/decorators';
|
||||
import { Request } from 'express';
|
||||
import { readFile } from 'fs/promises';
|
||||
import get from 'lodash/get';
|
||||
import type { INodeTypeDescription, INodeTypeNameVersion } from 'n8n-workflow';
|
||||
|
||||
import config from '@/config';
|
||||
import { NodeTypes } from '@/node-types';
|
||||
|
||||
@RestController('/node-types')
|
||||
export class NodeTypesController {
|
||||
constructor(private readonly nodeTypes: NodeTypes) {}
|
||||
constructor(
|
||||
private readonly nodeTypes: NodeTypes,
|
||||
private readonly globalConfig: GlobalConfig,
|
||||
) {}
|
||||
|
||||
@Post('/')
|
||||
async getNodeInfo(req: Request) {
|
||||
const nodeInfos = get(req, 'body.nodeInfos', []) as INodeTypeNameVersion[];
|
||||
|
||||
const defaultLocale = config.getEnv('defaultLocale');
|
||||
const defaultLocale = this.globalConfig.defaultLocale;
|
||||
|
||||
if (defaultLocale === 'en') {
|
||||
return nodeInfos.reduce<INodeTypeDescription[]>((acc, { name, version }) => {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { GlobalConfig } from '@n8n/config';
|
||||
import { Get, RestController } from '@n8n/decorators';
|
||||
import type { Request } from 'express';
|
||||
import { access } from 'fs/promises';
|
||||
import { join } from 'path';
|
||||
|
||||
import config from '@/config';
|
||||
import { NODES_BASE_DIR } from '@/constants';
|
||||
import { CredentialTypes } from '@/credential-types';
|
||||
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
||||
@@ -18,7 +18,10 @@ export declare namespace TranslationRequest {
|
||||
|
||||
@RestController('/')
|
||||
export class TranslationController {
|
||||
constructor(private readonly credentialTypes: CredentialTypes) {}
|
||||
constructor(
|
||||
private readonly credentialTypes: CredentialTypes,
|
||||
private readonly globalConfig: GlobalConfig,
|
||||
) {}
|
||||
|
||||
@Get('/credential-translation')
|
||||
async getCredentialTranslation(req: TranslationRequest.Credential) {
|
||||
@@ -27,7 +30,7 @@ export class TranslationController {
|
||||
if (!this.credentialTypes.recognizes(credentialType))
|
||||
throw new BadRequestError(`Invalid Credential type: "${credentialType}"`);
|
||||
|
||||
const defaultLocale = config.getEnv('defaultLocale');
|
||||
const { defaultLocale } = this.globalConfig;
|
||||
const translationPath = join(
|
||||
CREDENTIAL_TRANSLATIONS_DIR,
|
||||
defaultLocale,
|
||||
|
||||
@@ -26,6 +26,9 @@ describe('TelemetryEventRelay', () => {
|
||||
const telemetry = mock<Telemetry>();
|
||||
const license = mock<License>();
|
||||
const globalConfig = mock<GlobalConfig>({
|
||||
deployment: {
|
||||
type: 'default',
|
||||
},
|
||||
userManagement: {
|
||||
emails: {
|
||||
mode: 'smtp',
|
||||
|
||||
@@ -578,7 +578,7 @@ export class TelemetryEventRelay extends EventRelay {
|
||||
}
|
||||
|
||||
private async workflowSaved({ user, workflow, publicApi }: RelayEventMap['workflow-saved']) {
|
||||
const isCloudDeployment = config.getEnv('deployment.type') === 'cloud';
|
||||
const isCloudDeployment = this.globalConfig.deployment.type === 'cloud';
|
||||
|
||||
const { nodeGraph } = TelemetryHelpers.generateNodesGraph(workflow, this.nodeTypes, {
|
||||
isCloudDeployment,
|
||||
@@ -835,7 +835,7 @@ export class TelemetryEventRelay extends EventRelay {
|
||||
executions_data_prune: this.globalConfig.executions.pruneData,
|
||||
executions_data_max_age: this.globalConfig.executions.pruneDataMaxAge,
|
||||
},
|
||||
n8n_deployment_type: config.getEnv('deployment.type'),
|
||||
n8n_deployment_type: this.globalConfig.deployment.type,
|
||||
n8n_binary_data_mode: this.binaryDataConfig.mode,
|
||||
smtp_set_up: this.globalConfig.userManagement.emails.mode === 'smtp',
|
||||
ldap_allowed: authenticationMethod === 'ldap',
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export const MFA_FEATURE_ENABLED = 'mfa.enabled';
|
||||
@@ -1,11 +1,8 @@
|
||||
import { GlobalConfig } from '@n8n/config';
|
||||
import { UserRepository } from '@n8n/db';
|
||||
import { Container } from '@n8n/di';
|
||||
|
||||
import config from '@/config';
|
||||
|
||||
import { MFA_FEATURE_ENABLED } from './constants';
|
||||
|
||||
export const isMfaFeatureEnabled = () => config.get(MFA_FEATURE_ENABLED);
|
||||
export const isMfaFeatureEnabled = () => Container.get(GlobalConfig).mfa.enabled;
|
||||
|
||||
const isMfaFeatureDisabled = () => !isMfaFeatureEnabled();
|
||||
|
||||
@@ -18,7 +15,7 @@ export const handleMfaDisable = async () => {
|
||||
// users, then keep the feature enabled
|
||||
const users = await getUsersWithMfaEnabled();
|
||||
if (users) {
|
||||
config.set(MFA_FEATURE_ENABLED, true);
|
||||
Container.get(GlobalConfig).mfa.enabled = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -6,7 +6,6 @@ import axios from 'axios';
|
||||
import { InstanceSettings } from 'n8n-core';
|
||||
import type { IWorkflowBase } from 'n8n-workflow';
|
||||
|
||||
import config from '@/config';
|
||||
import { N8N_VERSION } from '@/constants';
|
||||
import { isApiEnabled } from '@/public-api';
|
||||
import {
|
||||
@@ -84,7 +83,7 @@ export class InstanceRiskReporter implements RiskReporter {
|
||||
}
|
||||
|
||||
private getSecuritySettings() {
|
||||
if (config.getEnv('deployment.type') === 'cloud') return null;
|
||||
if (this.globalConfig.deployment.type === 'cloud') return null;
|
||||
|
||||
const settings: Record<string, unknown> = {};
|
||||
|
||||
|
||||
@@ -133,12 +133,12 @@ export class FrontendService {
|
||||
apiHost: this.globalConfig.diagnostics.posthogConfig.apiHost,
|
||||
apiKey: this.globalConfig.diagnostics.posthogConfig.apiKey,
|
||||
autocapture: false,
|
||||
disableSessionRecording: config.getEnv('deployment.type') !== 'cloud',
|
||||
disableSessionRecording: this.globalConfig.deployment.type !== 'cloud',
|
||||
debug: this.globalConfig.logging.level === 'debug',
|
||||
},
|
||||
personalizationSurveyEnabled:
|
||||
config.getEnv('personalization.enabled') && this.globalConfig.diagnostics.enabled,
|
||||
defaultLocale: config.getEnv('defaultLocale'),
|
||||
this.globalConfig.personalization.enabled && this.globalConfig.diagnostics.enabled,
|
||||
defaultLocale: this.globalConfig.defaultLocale,
|
||||
userManagement: {
|
||||
quota: this.license.getUsersLimit(),
|
||||
showSetupOnFirstLoad: !config.getEnv('userManagement.isInstanceOwnerSetUp'),
|
||||
@@ -170,7 +170,7 @@ export class FrontendService {
|
||||
},
|
||||
workflowTagsDisabled: this.globalConfig.tags.disabled,
|
||||
logLevel: this.globalConfig.logging.level,
|
||||
hiringBannerEnabled: config.getEnv('hiringBanner.enabled'),
|
||||
hiringBannerEnabled: this.globalConfig.hiringBanner.enabled,
|
||||
aiAssistant: {
|
||||
enabled: false,
|
||||
},
|
||||
@@ -184,7 +184,7 @@ export class FrontendService {
|
||||
communityNodesEnabled: this.globalConfig.nodes.communityPackages.enabled,
|
||||
unverifiedCommunityNodesEnabled: this.globalConfig.nodes.communityPackages.unverifiedEnabled,
|
||||
deployment: {
|
||||
type: config.getEnv('deployment.type'),
|
||||
type: this.globalConfig.deployment.type,
|
||||
},
|
||||
allowedModules: {
|
||||
builtIn: process.env.NODE_FUNCTION_ALLOW_BUILTIN?.split(',') ?? undefined,
|
||||
@@ -217,7 +217,7 @@ export class FrontendService {
|
||||
mfa: {
|
||||
enabled: false,
|
||||
},
|
||||
hideUsagePage: config.getEnv('hideUsagePage'),
|
||||
hideUsagePage: this.globalConfig.hideUsagePage,
|
||||
license: {
|
||||
consumerId: 'unknown',
|
||||
environment: this.globalConfig.license.tenantId === 1 ? 'production' : 'staging',
|
||||
@@ -395,7 +395,7 @@ export class FrontendService {
|
||||
dateRanges: getInsightsAvailableDateRanges(this.licenseState),
|
||||
});
|
||||
|
||||
this.settings.mfa.enabled = config.get('mfa.enabled');
|
||||
this.settings.mfa.enabled = this.globalConfig.mfa.enabled;
|
||||
|
||||
this.settings.executionMode = config.getEnv('executions.mode');
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Service } from '@n8n/di';
|
||||
import { GlobalConfig } from '@n8n/config';
|
||||
import { Container, Service } from '@n8n/di';
|
||||
|
||||
import config from '@/config';
|
||||
import type {
|
||||
DisconnectAnalyzer,
|
||||
DisconnectErrorOptions,
|
||||
@@ -16,7 +16,7 @@ import { TaskRunnerFailedHeartbeatError } from './errors/task-runner-failed-hear
|
||||
@Service()
|
||||
export class DefaultTaskRunnerDisconnectAnalyzer implements DisconnectAnalyzer {
|
||||
get isCloudDeployment() {
|
||||
return config.get('deployment.type') === 'cloud';
|
||||
return Container.get(GlobalConfig).deployment.type === 'cloud';
|
||||
}
|
||||
|
||||
async toDisconnectError(opts: DisconnectErrorOptions): Promise<Error> {
|
||||
@@ -25,7 +25,7 @@ export class DefaultTaskRunnerDisconnectAnalyzer implements DisconnectAnalyzer {
|
||||
if (reason === 'failed-heartbeat-check' && heartbeatInterval) {
|
||||
return new TaskRunnerFailedHeartbeatError(
|
||||
heartbeatInterval,
|
||||
config.get('deployment.type') !== 'cloud',
|
||||
Container.get(GlobalConfig).deployment.type !== 'cloud',
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ describe('TaskBroker', () => {
|
||||
let taskBroker: TaskBroker;
|
||||
|
||||
beforeEach(() => {
|
||||
taskBroker = new TaskBroker(mock(), mock(), mock());
|
||||
taskBroker = new TaskBroker(mock(), mock(), mock(), mock());
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
@@ -724,7 +724,7 @@ describe('TaskBroker', () => {
|
||||
beforeAll(() => {
|
||||
jest.useFakeTimers();
|
||||
config = mock<TaskRunnersConfig>({ taskTimeout: 30, mode: 'internal' });
|
||||
taskBroker = new TaskBroker(mock(), config, runnerLifecycleEvents);
|
||||
taskBroker = new TaskBroker(mock(), config, runnerLifecycleEvents, mock());
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
@@ -844,7 +844,7 @@ describe('TaskBroker', () => {
|
||||
|
||||
it('[external mode] on timeout, we should instruct the runner to cancel and send error to requester', async () => {
|
||||
const config = mock<TaskRunnersConfig>({ taskTimeout: 30, mode: 'external' });
|
||||
taskBroker = new TaskBroker(mock(), config, runnerLifecycleEvents);
|
||||
taskBroker = new TaskBroker(mock(), config, runnerLifecycleEvents, mock());
|
||||
|
||||
jest.spyOn(global, 'clearTimeout');
|
||||
|
||||
@@ -895,7 +895,7 @@ describe('TaskBroker', () => {
|
||||
const messageCallback = jest.fn();
|
||||
const loggerMock = mock<Logger>();
|
||||
|
||||
taskBroker = new TaskBroker(loggerMock, mock(), mock());
|
||||
taskBroker = new TaskBroker(loggerMock, mock(), mock(), mock());
|
||||
taskBroker.registerRunner(runner, messageCallback);
|
||||
|
||||
const offer: TaskOffer = {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Logger } from '@n8n/backend-common';
|
||||
import { TaskRunnersConfig } from '@n8n/config';
|
||||
import { GlobalConfig, TaskRunnersConfig } from '@n8n/config';
|
||||
import { Service } from '@n8n/di';
|
||||
import type {
|
||||
BrokerMessage,
|
||||
@@ -10,7 +10,6 @@ import type {
|
||||
import { UnexpectedError, UserError } from 'n8n-workflow';
|
||||
import { nanoid } from 'nanoid';
|
||||
|
||||
import config from '@/config';
|
||||
import { Time } from '@/constants';
|
||||
import { TaskDeferredError } from '@/task-runners/task-broker/errors/task-deferred.error';
|
||||
import { TaskRejectError } from '@/task-runners/task-broker/errors/task-reject.error';
|
||||
@@ -91,6 +90,7 @@ export class TaskBroker {
|
||||
private readonly logger: Logger,
|
||||
private readonly taskRunnersConfig: TaskRunnersConfig,
|
||||
private readonly taskRunnerLifecycleEvents: TaskRunnerLifecycleEvents,
|
||||
private readonly globalConfig: GlobalConfig,
|
||||
) {
|
||||
if (this.taskRunnersConfig.taskTimeout <= 0) {
|
||||
throw new UserError('Task timeout must be greater than 0');
|
||||
@@ -471,7 +471,7 @@ export class TaskBroker {
|
||||
taskId,
|
||||
new TaskRunnerExecutionTimeoutError({
|
||||
taskTimeout,
|
||||
isSelfHosted: config.getEnv('deployment.type') !== 'cloud',
|
||||
isSelfHosted: this.globalConfig.deployment.type !== 'cloud',
|
||||
mode,
|
||||
}),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user