mirror of
https://github.com/n8n-io/n8n.git
synced 2024-11-10 12:35:46 +03:00
refactor(core): Move frontend settings to service (no-changelog) (#7396)
Quick follow-up to https://github.com/n8n-io/n8n/pull/7283
This commit is contained in:
parent
1e0753516c
commit
54e900955a
@ -40,7 +40,6 @@ import type {
|
||||
INodeParameters,
|
||||
INodePropertyOptions,
|
||||
INodeTypeNameVersion,
|
||||
ITelemetrySettings,
|
||||
WorkflowExecuteMode,
|
||||
ICredentialTypes,
|
||||
ExecutionStatus,
|
||||
@ -64,7 +63,6 @@ import {
|
||||
GENERATED_STATIC_DIR,
|
||||
inDevelopment,
|
||||
inE2ETests,
|
||||
LICENSE_FEATURES,
|
||||
N8N_VERSION,
|
||||
RESPONSE_ERROR_MESSAGES,
|
||||
TEMPLATES_DIR,
|
||||
@ -99,12 +97,7 @@ import { BinaryDataController } from './controllers/binaryData.controller';
|
||||
import { ExternalSecretsController } from '@/ExternalSecrets/ExternalSecrets.controller.ee';
|
||||
import { executionsController } from '@/executions/executions.controller';
|
||||
import { isApiEnabled, loadPublicApiVersions } from '@/PublicApi';
|
||||
import {
|
||||
getInstanceBaseUrl,
|
||||
isEmailSetUp,
|
||||
isSharingEnabled,
|
||||
whereClause,
|
||||
} from '@/UserManagement/UserManagementHelper';
|
||||
import { whereClause } from '@/UserManagement/UserManagementHelper';
|
||||
import { UserManagementMailer } from '@/UserManagement/email';
|
||||
import * as Db from '@/Db';
|
||||
import type {
|
||||
@ -130,40 +123,25 @@ import * as WorkflowExecuteAdditionalData from '@/WorkflowExecuteAdditionalData'
|
||||
import { toHttpNodeParameters } from '@/CurlConverterHelper';
|
||||
import { EventBusController } from '@/eventbus/eventBus.controller';
|
||||
import { EventBusControllerEE } from '@/eventbus/eventBus.controller.ee';
|
||||
import { isLogStreamingEnabled } from '@/eventbus/MessageEventBus/MessageEventBusHelper';
|
||||
import { licenseController } from './license/license.controller';
|
||||
import { Push, setupPushServer, setupPushHandler } from '@/push';
|
||||
import { setupAuthMiddlewares } from './middlewares';
|
||||
import {
|
||||
getLdapLoginLabel,
|
||||
handleLdapInit,
|
||||
isLdapEnabled,
|
||||
isLdapLoginEnabled,
|
||||
} from './Ldap/helpers';
|
||||
import { handleLdapInit, isLdapEnabled } from './Ldap/helpers';
|
||||
import { AbstractServer } from './AbstractServer';
|
||||
import { PostHogClient } from './posthog';
|
||||
import { eventBus } from './eventbus';
|
||||
import { Container } from 'typedi';
|
||||
import { InternalHooks } from './InternalHooks';
|
||||
import { License } from './License';
|
||||
import {
|
||||
getStatusUsingPreviousExecutionStatusMethod,
|
||||
isAdvancedExecutionFiltersEnabled,
|
||||
isDebugInEditorLicensed,
|
||||
} from './executions/executionHelpers';
|
||||
import { getSamlLoginLabel, isSamlLoginEnabled, isSamlLicensed } from './sso/saml/samlHelpers';
|
||||
import { getStatusUsingPreviousExecutionStatusMethod } from './executions/executionHelpers';
|
||||
import { SamlController } from './sso/saml/routes/saml.controller.ee';
|
||||
import { SamlService } from './sso/saml/saml.service.ee';
|
||||
import { variablesController } from './environments/variables/variables.controller';
|
||||
import { LdapManager } from './Ldap/LdapManager.ee';
|
||||
import { getVariablesLimit, isVariablesEnabled } from '@/environments/variables/enviromentHelpers';
|
||||
import {
|
||||
getCurrentAuthenticationMethod,
|
||||
isLdapCurrentAuthenticationMethod,
|
||||
isSamlCurrentAuthenticationMethod,
|
||||
} from './sso/ssoHelpers';
|
||||
import { isExternalSecretsEnabled } from './ExternalSecrets/externalSecretsHelper.ee';
|
||||
import { isSourceControlLicensed } from '@/environments/sourceControl/sourceControlHelper.ee';
|
||||
import { SourceControlService } from '@/environments/sourceControl/sourceControl.service.ee';
|
||||
import { SourceControlController } from '@/environments/sourceControl/sourceControl.controller.ee';
|
||||
import { ExecutionRepository, SettingsRepository } from '@db/repositories';
|
||||
@ -176,11 +154,6 @@ import { JwtService } from './services/jwt.service';
|
||||
import { RoleService } from './services/role.service';
|
||||
import { UserService } from './services/user.service';
|
||||
import { OrchestrationController } from './controllers/orchestration.controller';
|
||||
import {
|
||||
getWorkflowHistoryLicensePruneTime,
|
||||
getWorkflowHistoryPruneTime,
|
||||
isWorkflowHistoryEnabled,
|
||||
} from './workflows/workflowHistory/workflowHistoryHelper.ee';
|
||||
import { WorkflowHistoryController } from './workflows/workflowHistory/workflowHistory.controller.ee';
|
||||
|
||||
const exec = promisify(callbackExec);
|
||||
@ -192,8 +165,6 @@ export class Server extends AbstractServer {
|
||||
|
||||
activeExecutionsInstance: ActiveExecutions;
|
||||
|
||||
frontendSettings: IN8nUISettings;
|
||||
|
||||
presetCredentialsLoaded: boolean;
|
||||
|
||||
loadNodesAndCredentials: LoadNodesAndCredentials;
|
||||
@ -217,146 +188,6 @@ export class Server extends AbstractServer {
|
||||
|
||||
this.testWebhooksEnabled = true;
|
||||
this.webhooksEnabled = !config.getEnv('endpoints.disableProductionWebhooksOnMainProcess');
|
||||
|
||||
const urlBaseWebhook = WebhookHelpers.getWebhookBaseUrl();
|
||||
const telemetrySettings: ITelemetrySettings = {
|
||||
enabled: config.getEnv('diagnostics.enabled'),
|
||||
};
|
||||
|
||||
if (telemetrySettings.enabled) {
|
||||
const conf = config.getEnv('diagnostics.config.frontend');
|
||||
const [key, url] = conf.split(';');
|
||||
|
||||
if (!key || !url) {
|
||||
LoggerProxy.warn('Diagnostics frontend config is invalid');
|
||||
telemetrySettings.enabled = false;
|
||||
}
|
||||
|
||||
telemetrySettings.config = { key, url };
|
||||
}
|
||||
|
||||
// Define it here to avoid calling the function multiple times
|
||||
const instanceBaseUrl = getInstanceBaseUrl();
|
||||
|
||||
this.frontendSettings = {
|
||||
endpointWebhook: this.endpointWebhook,
|
||||
endpointWebhookTest: this.endpointWebhookTest,
|
||||
saveDataErrorExecution: config.getEnv('executions.saveDataOnError'),
|
||||
saveDataSuccessExecution: config.getEnv('executions.saveDataOnSuccess'),
|
||||
saveManualExecutions: config.getEnv('executions.saveDataManualExecutions'),
|
||||
executionTimeout: config.getEnv('executions.timeout'),
|
||||
maxExecutionTimeout: config.getEnv('executions.maxTimeout'),
|
||||
workflowCallerPolicyDefaultOption: config.getEnv('workflows.callerPolicyDefaultOption'),
|
||||
timezone: this.timezone,
|
||||
urlBaseWebhook,
|
||||
urlBaseEditor: instanceBaseUrl,
|
||||
versionCli: '',
|
||||
releaseChannel: config.getEnv('generic.releaseChannel'),
|
||||
oauthCallbackUrls: {
|
||||
oauth1: `${instanceBaseUrl}/${this.restEndpoint}/oauth1-credential/callback`,
|
||||
oauth2: `${instanceBaseUrl}/${this.restEndpoint}/oauth2-credential/callback`,
|
||||
},
|
||||
versionNotifications: {
|
||||
enabled: config.getEnv('versionNotifications.enabled'),
|
||||
endpoint: config.getEnv('versionNotifications.endpoint'),
|
||||
infoUrl: config.getEnv('versionNotifications.infoUrl'),
|
||||
},
|
||||
instanceId: '',
|
||||
telemetry: telemetrySettings,
|
||||
posthog: {
|
||||
enabled: config.getEnv('diagnostics.enabled'),
|
||||
apiHost: config.getEnv('diagnostics.config.posthog.apiHost'),
|
||||
apiKey: config.getEnv('diagnostics.config.posthog.apiKey'),
|
||||
autocapture: false,
|
||||
disableSessionRecording: config.getEnv(
|
||||
'diagnostics.config.posthog.disableSessionRecording',
|
||||
),
|
||||
debug: config.getEnv('logs.level') === 'debug',
|
||||
},
|
||||
personalizationSurveyEnabled:
|
||||
config.getEnv('personalization.enabled') && config.getEnv('diagnostics.enabled'),
|
||||
defaultLocale: config.getEnv('defaultLocale'),
|
||||
userManagement: {
|
||||
quota: Container.get(License).getUsersLimit(),
|
||||
showSetupOnFirstLoad: config.getEnv('userManagement.isInstanceOwnerSetUp') === false,
|
||||
smtpSetup: isEmailSetUp(),
|
||||
authenticationMethod: getCurrentAuthenticationMethod(),
|
||||
},
|
||||
sso: {
|
||||
saml: {
|
||||
loginEnabled: false,
|
||||
loginLabel: '',
|
||||
},
|
||||
ldap: {
|
||||
loginEnabled: false,
|
||||
loginLabel: '',
|
||||
},
|
||||
},
|
||||
publicApi: {
|
||||
enabled: isApiEnabled(),
|
||||
latestVersion: 1,
|
||||
path: config.getEnv('publicApi.path'),
|
||||
swaggerUi: {
|
||||
enabled: !config.getEnv('publicApi.swaggerUi.disabled'),
|
||||
},
|
||||
},
|
||||
workflowTagsDisabled: config.getEnv('workflowTagsDisabled'),
|
||||
logLevel: config.getEnv('logs.level'),
|
||||
hiringBannerEnabled: config.getEnv('hiringBanner.enabled'),
|
||||
templates: {
|
||||
enabled: config.getEnv('templates.enabled'),
|
||||
host: config.getEnv('templates.host'),
|
||||
},
|
||||
onboardingCallPromptEnabled: config.getEnv('onboardingCallPrompt.enabled'),
|
||||
executionMode: config.getEnv('executions.mode'),
|
||||
pushBackend: config.getEnv('push.backend'),
|
||||
communityNodesEnabled: config.getEnv('nodes.communityPackages.enabled'),
|
||||
deployment: {
|
||||
type: config.getEnv('deployment.type'),
|
||||
},
|
||||
isNpmAvailable: false,
|
||||
allowedModules: {
|
||||
builtIn: process.env.NODE_FUNCTION_ALLOW_BUILTIN?.split(',') ?? undefined,
|
||||
external: process.env.NODE_FUNCTION_ALLOW_EXTERNAL?.split(',') ?? undefined,
|
||||
},
|
||||
enterprise: {
|
||||
sharing: false,
|
||||
ldap: false,
|
||||
saml: false,
|
||||
logStreaming: false,
|
||||
advancedExecutionFilters: false,
|
||||
variables: false,
|
||||
sourceControl: false,
|
||||
auditLogs: false,
|
||||
externalSecrets: false,
|
||||
showNonProdBanner: false,
|
||||
debugInEditor: false,
|
||||
workflowHistory: false,
|
||||
},
|
||||
mfa: {
|
||||
enabled: false,
|
||||
},
|
||||
hideUsagePage: config.getEnv('hideUsagePage'),
|
||||
license: {
|
||||
environment: config.getEnv('license.tenantId') === 1 ? 'production' : 'staging',
|
||||
},
|
||||
variables: {
|
||||
limit: 0,
|
||||
},
|
||||
expressions: {
|
||||
evaluator: config.getEnv('expression.evaluator'),
|
||||
},
|
||||
banners: {
|
||||
dismissed: [],
|
||||
},
|
||||
ai: {
|
||||
enabled: config.getEnv('ai.enabled'),
|
||||
},
|
||||
workflowHistory: {
|
||||
pruneTime: -1,
|
||||
licensePruneTime: -1,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async start() {
|
||||
@ -443,92 +274,6 @@ export class Server extends AbstractServer {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current settings for the frontend
|
||||
*/
|
||||
private async getSettingsForFrontend(): Promise<IN8nUISettings> {
|
||||
// Update all urls, in case `WEBHOOK_URL` was updated by `--tunnel`
|
||||
const instanceBaseUrl = getInstanceBaseUrl();
|
||||
this.frontendSettings.urlBaseWebhook = WebhookHelpers.getWebhookBaseUrl();
|
||||
this.frontendSettings.urlBaseEditor = instanceBaseUrl;
|
||||
this.frontendSettings.oauthCallbackUrls = {
|
||||
oauth1: `${instanceBaseUrl}/${this.restEndpoint}/oauth1-credential/callback`,
|
||||
oauth2: `${instanceBaseUrl}/${this.restEndpoint}/oauth2-credential/callback`,
|
||||
};
|
||||
|
||||
// refresh user management status
|
||||
Object.assign(this.frontendSettings.userManagement, {
|
||||
quota: Container.get(License).getUsersLimit(),
|
||||
authenticationMethod: getCurrentAuthenticationMethod(),
|
||||
showSetupOnFirstLoad:
|
||||
config.getEnv('userManagement.isInstanceOwnerSetUp') === false &&
|
||||
config.getEnv('deployment.type').startsWith('desktop_') === false,
|
||||
});
|
||||
|
||||
let dismissedBanners: string[] = [];
|
||||
|
||||
try {
|
||||
dismissedBanners = config.getEnv('ui.banners.dismissed') ?? [];
|
||||
} catch {
|
||||
// not yet in DB
|
||||
}
|
||||
|
||||
this.frontendSettings.banners.dismissed = dismissedBanners;
|
||||
|
||||
// refresh enterprise status
|
||||
Object.assign(this.frontendSettings.enterprise, {
|
||||
sharing: isSharingEnabled(),
|
||||
logStreaming: isLogStreamingEnabled(),
|
||||
ldap: isLdapEnabled(),
|
||||
saml: isSamlLicensed(),
|
||||
advancedExecutionFilters: isAdvancedExecutionFiltersEnabled(),
|
||||
variables: isVariablesEnabled(),
|
||||
sourceControl: isSourceControlLicensed(),
|
||||
externalSecrets: isExternalSecretsEnabled(),
|
||||
showNonProdBanner: Container.get(License).isFeatureEnabled(
|
||||
LICENSE_FEATURES.SHOW_NON_PROD_BANNER,
|
||||
),
|
||||
debugInEditor: isDebugInEditorLicensed(),
|
||||
workflowHistory: isWorkflowHistoryEnabled(),
|
||||
});
|
||||
|
||||
if (isLdapEnabled()) {
|
||||
Object.assign(this.frontendSettings.sso.ldap, {
|
||||
loginLabel: getLdapLoginLabel(),
|
||||
loginEnabled: isLdapLoginEnabled(),
|
||||
});
|
||||
}
|
||||
|
||||
if (isSamlLicensed()) {
|
||||
Object.assign(this.frontendSettings.sso.saml, {
|
||||
loginLabel: getSamlLoginLabel(),
|
||||
loginEnabled: isSamlLoginEnabled(),
|
||||
});
|
||||
}
|
||||
|
||||
if (isVariablesEnabled()) {
|
||||
this.frontendSettings.variables.limit = getVariablesLimit();
|
||||
}
|
||||
|
||||
if (isWorkflowHistoryEnabled()) {
|
||||
Object.assign(this.frontendSettings.workflowHistory, {
|
||||
pruneTime: getWorkflowHistoryPruneTime(),
|
||||
licensePruneTime: getWorkflowHistoryLicensePruneTime(),
|
||||
});
|
||||
}
|
||||
|
||||
if (config.getEnv('nodes.communityPackages.enabled')) {
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
const { CommunityPackagesService } = await import('@/services/communityPackages.service');
|
||||
this.frontendSettings.missingPackages =
|
||||
Container.get(CommunityPackagesService).hasMissingPackages;
|
||||
}
|
||||
|
||||
this.frontendSettings.mfa.enabled = isMfaFeatureEnabled();
|
||||
|
||||
return this.frontendSettings;
|
||||
}
|
||||
|
||||
private async registerControllers(ignoredEndpoints: Readonly<string[]>) {
|
||||
const { app, externalHooks, activeWorkflowRunner, nodeTypes } = this;
|
||||
const repositories = Db.collections;
|
||||
@ -628,17 +373,17 @@ export class Server extends AbstractServer {
|
||||
|
||||
this.instanceId = await UserSettings.getInstanceId();
|
||||
|
||||
this.frontendSettings.isNpmAvailable = await exec('npm --version')
|
||||
.then(() => true)
|
||||
.catch(() => false);
|
||||
this.frontendService.addToSettings({
|
||||
isNpmAvailable: await exec('npm --version')
|
||||
.then(() => true)
|
||||
.catch(() => false),
|
||||
versionCli: N8N_VERSION,
|
||||
instanceId: this.instanceId,
|
||||
});
|
||||
|
||||
this.frontendSettings.versionCli = N8N_VERSION;
|
||||
await this.externalHooks.run('frontend.settings', [this.frontendService.getSettings()]);
|
||||
|
||||
this.frontendSettings.instanceId = this.instanceId;
|
||||
|
||||
await this.externalHooks.run('frontend.settings', [this.frontendSettings]);
|
||||
|
||||
await this.postHog.init(this.frontendSettings.instanceId);
|
||||
await this.postHog.init(this.instanceId);
|
||||
|
||||
const publicApiEndpoint = config.getEnv('publicApi.path');
|
||||
const excludeEndpoints = config.getEnv('security.excludeEndpoints');
|
||||
@ -665,7 +410,7 @@ export class Server extends AbstractServer {
|
||||
if (isApiEnabled()) {
|
||||
const { apiRouters, apiLatestVersion } = await loadPublicApiVersions(publicApiEndpoint);
|
||||
this.app.use(...apiRouters);
|
||||
this.frontendSettings.publicApi.latestVersion = apiLatestVersion;
|
||||
this.frontendService.settings.publicApi.latestVersion = apiLatestVersion;
|
||||
}
|
||||
// Parse cookies for easier access
|
||||
this.app.use(cookieParser());
|
||||
@ -1465,7 +1210,7 @@ export class Server extends AbstractServer {
|
||||
async (req: express.Request, res: express.Response): Promise<IN8nUISettings> => {
|
||||
void Container.get(InternalHooks).onFrontendSettingsAPI(req.headers.sessionid as string);
|
||||
|
||||
return this.getSettingsForFrontend();
|
||||
return this.frontendService.getSettings();
|
||||
},
|
||||
),
|
||||
);
|
||||
|
@ -1,23 +1,187 @@
|
||||
import { Service } from 'typedi';
|
||||
import { Container, Service } from 'typedi';
|
||||
import uniq from 'lodash/uniq';
|
||||
import { createWriteStream } from 'fs';
|
||||
import { mkdir } from 'fs/promises';
|
||||
import path from 'path';
|
||||
|
||||
import type { ICredentialType, INodeTypeBaseDescription } from 'n8n-workflow';
|
||||
import type {
|
||||
ICredentialType,
|
||||
IN8nUISettings,
|
||||
INodeTypeBaseDescription,
|
||||
ITelemetrySettings,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
import { GENERATED_STATIC_DIR } from '@/constants';
|
||||
import { GENERATED_STATIC_DIR, LICENSE_FEATURES } from '@/constants';
|
||||
import { CredentialsOverwrites } from '@/CredentialsOverwrites';
|
||||
import { CredentialTypes } from '@/CredentialTypes';
|
||||
import { LoadNodesAndCredentials } from '@/LoadNodesAndCredentials';
|
||||
import { License } from '@/License';
|
||||
import { getInstanceBaseUrl, isEmailSetUp } from '@/UserManagement/UserManagementHelper';
|
||||
import * as WebhookHelpers from '@/WebhookHelpers';
|
||||
import { LoggerProxy } from 'n8n-workflow';
|
||||
import config from '@/config';
|
||||
import { getCurrentAuthenticationMethod } from '@/sso/ssoHelpers';
|
||||
import { getLdapLoginLabel } from '@/Ldap/helpers';
|
||||
import { getSamlLoginLabel } from '@/sso/saml/samlHelpers';
|
||||
import { getVariablesLimit } from '@/environments/variables/enviromentHelpers';
|
||||
import {
|
||||
getWorkflowHistoryLicensePruneTime,
|
||||
getWorkflowHistoryPruneTime,
|
||||
} from '@/workflows/workflowHistory/workflowHistoryHelper.ee';
|
||||
|
||||
@Service()
|
||||
export class FrontendService {
|
||||
settings: IN8nUISettings;
|
||||
|
||||
constructor(
|
||||
private readonly loadNodesAndCredentials: LoadNodesAndCredentials,
|
||||
private readonly credentialTypes: CredentialTypes,
|
||||
private readonly credentialsOverwrites: CredentialsOverwrites,
|
||||
) {}
|
||||
private readonly license: License,
|
||||
) {
|
||||
this.initSettings();
|
||||
}
|
||||
|
||||
private initSettings() {
|
||||
const instanceBaseUrl = getInstanceBaseUrl();
|
||||
const restEndpoint = config.getEnv('endpoints.rest');
|
||||
|
||||
const telemetrySettings: ITelemetrySettings = {
|
||||
enabled: config.getEnv('diagnostics.enabled'),
|
||||
};
|
||||
|
||||
if (telemetrySettings.enabled) {
|
||||
const conf = config.getEnv('diagnostics.config.frontend');
|
||||
const [key, url] = conf.split(';');
|
||||
|
||||
if (!key || !url) {
|
||||
LoggerProxy.warn('Diagnostics frontend config is invalid');
|
||||
telemetrySettings.enabled = false;
|
||||
}
|
||||
|
||||
telemetrySettings.config = { key, url };
|
||||
}
|
||||
|
||||
this.settings = {
|
||||
endpointWebhook: config.getEnv('endpoints.webhook'),
|
||||
endpointWebhookTest: config.getEnv('endpoints.webhookTest'),
|
||||
saveDataErrorExecution: config.getEnv('executions.saveDataOnError'),
|
||||
saveDataSuccessExecution: config.getEnv('executions.saveDataOnSuccess'),
|
||||
saveManualExecutions: config.getEnv('executions.saveDataManualExecutions'),
|
||||
executionTimeout: config.getEnv('executions.timeout'),
|
||||
maxExecutionTimeout: config.getEnv('executions.maxTimeout'),
|
||||
workflowCallerPolicyDefaultOption: config.getEnv('workflows.callerPolicyDefaultOption'),
|
||||
timezone: config.getEnv('generic.timezone'),
|
||||
urlBaseWebhook: WebhookHelpers.getWebhookBaseUrl(),
|
||||
urlBaseEditor: instanceBaseUrl,
|
||||
versionCli: '',
|
||||
releaseChannel: config.getEnv('generic.releaseChannel'),
|
||||
oauthCallbackUrls: {
|
||||
oauth1: `${instanceBaseUrl}/${restEndpoint}/oauth1-credential/callback`,
|
||||
oauth2: `${instanceBaseUrl}/${restEndpoint}/oauth2-credential/callback`,
|
||||
},
|
||||
versionNotifications: {
|
||||
enabled: config.getEnv('versionNotifications.enabled'),
|
||||
endpoint: config.getEnv('versionNotifications.endpoint'),
|
||||
infoUrl: config.getEnv('versionNotifications.infoUrl'),
|
||||
},
|
||||
instanceId: '',
|
||||
telemetry: telemetrySettings,
|
||||
posthog: {
|
||||
enabled: config.getEnv('diagnostics.enabled'),
|
||||
apiHost: config.getEnv('diagnostics.config.posthog.apiHost'),
|
||||
apiKey: config.getEnv('diagnostics.config.posthog.apiKey'),
|
||||
autocapture: false,
|
||||
disableSessionRecording: config.getEnv(
|
||||
'diagnostics.config.posthog.disableSessionRecording',
|
||||
),
|
||||
debug: config.getEnv('logs.level') === 'debug',
|
||||
},
|
||||
personalizationSurveyEnabled:
|
||||
config.getEnv('personalization.enabled') && config.getEnv('diagnostics.enabled'),
|
||||
defaultLocale: config.getEnv('defaultLocale'),
|
||||
userManagement: {
|
||||
quota: this.license.getUsersLimit(),
|
||||
showSetupOnFirstLoad: !config.getEnv('userManagement.isInstanceOwnerSetUp'),
|
||||
smtpSetup: isEmailSetUp(),
|
||||
authenticationMethod: getCurrentAuthenticationMethod(),
|
||||
},
|
||||
sso: {
|
||||
saml: {
|
||||
loginEnabled: false,
|
||||
loginLabel: '',
|
||||
},
|
||||
ldap: {
|
||||
loginEnabled: false,
|
||||
loginLabel: '',
|
||||
},
|
||||
},
|
||||
publicApi: {
|
||||
enabled: !config.get('publicApi.disabled') && !this.license.isAPIDisabled(),
|
||||
latestVersion: 1,
|
||||
path: config.getEnv('publicApi.path'),
|
||||
swaggerUi: {
|
||||
enabled: !config.getEnv('publicApi.swaggerUi.disabled'),
|
||||
},
|
||||
},
|
||||
workflowTagsDisabled: config.getEnv('workflowTagsDisabled'),
|
||||
logLevel: config.getEnv('logs.level'),
|
||||
hiringBannerEnabled: config.getEnv('hiringBanner.enabled'),
|
||||
templates: {
|
||||
enabled: config.getEnv('templates.enabled'),
|
||||
host: config.getEnv('templates.host'),
|
||||
},
|
||||
onboardingCallPromptEnabled: config.getEnv('onboardingCallPrompt.enabled'),
|
||||
executionMode: config.getEnv('executions.mode'),
|
||||
pushBackend: config.getEnv('push.backend'),
|
||||
communityNodesEnabled: config.getEnv('nodes.communityPackages.enabled'),
|
||||
deployment: {
|
||||
type: config.getEnv('deployment.type'),
|
||||
},
|
||||
isNpmAvailable: false,
|
||||
allowedModules: {
|
||||
builtIn: process.env.NODE_FUNCTION_ALLOW_BUILTIN?.split(',') ?? undefined,
|
||||
external: process.env.NODE_FUNCTION_ALLOW_EXTERNAL?.split(',') ?? undefined,
|
||||
},
|
||||
enterprise: {
|
||||
sharing: false,
|
||||
ldap: false,
|
||||
saml: false,
|
||||
logStreaming: false,
|
||||
advancedExecutionFilters: false,
|
||||
variables: false,
|
||||
sourceControl: false,
|
||||
auditLogs: false,
|
||||
externalSecrets: false,
|
||||
showNonProdBanner: false,
|
||||
debugInEditor: false,
|
||||
workflowHistory: false,
|
||||
},
|
||||
mfa: {
|
||||
enabled: false,
|
||||
},
|
||||
hideUsagePage: config.getEnv('hideUsagePage'),
|
||||
license: {
|
||||
environment: config.getEnv('license.tenantId') === 1 ? 'production' : 'staging',
|
||||
},
|
||||
variables: {
|
||||
limit: 0,
|
||||
},
|
||||
expressions: {
|
||||
evaluator: config.getEnv('expression.evaluator'),
|
||||
},
|
||||
banners: {
|
||||
dismissed: [],
|
||||
},
|
||||
ai: {
|
||||
enabled: config.getEnv('ai.enabled'),
|
||||
},
|
||||
workflowHistory: {
|
||||
pruneTime: -1,
|
||||
licensePruneTime: -1,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async generateTypes() {
|
||||
this.overwriteCredentialsProperties();
|
||||
@ -29,6 +193,93 @@ export class FrontendService {
|
||||
this.writeStaticJSON('credentials', credentials);
|
||||
}
|
||||
|
||||
async getSettings(): Promise<IN8nUISettings> {
|
||||
const restEndpoint = config.getEnv('endpoints.rest');
|
||||
|
||||
// Update all urls, in case `WEBHOOK_URL` was updated by `--tunnel`
|
||||
const instanceBaseUrl = getInstanceBaseUrl();
|
||||
this.settings.urlBaseWebhook = WebhookHelpers.getWebhookBaseUrl();
|
||||
this.settings.urlBaseEditor = instanceBaseUrl;
|
||||
this.settings.oauthCallbackUrls = {
|
||||
oauth1: `${instanceBaseUrl}/${restEndpoint}/oauth1-credential/callback`,
|
||||
oauth2: `${instanceBaseUrl}/${restEndpoint}/oauth2-credential/callback`,
|
||||
};
|
||||
|
||||
// refresh user management status
|
||||
Object.assign(this.settings.userManagement, {
|
||||
quota: this.license.getUsersLimit(),
|
||||
authenticationMethod: getCurrentAuthenticationMethod(),
|
||||
showSetupOnFirstLoad:
|
||||
!config.getEnv('userManagement.isInstanceOwnerSetUp') &&
|
||||
!config.getEnv('deployment.type').startsWith('desktop_'),
|
||||
});
|
||||
|
||||
let dismissedBanners: string[] = [];
|
||||
|
||||
try {
|
||||
dismissedBanners = config.getEnv('ui.banners.dismissed') ?? [];
|
||||
} catch {
|
||||
// not yet in DB
|
||||
}
|
||||
|
||||
this.settings.banners.dismissed = dismissedBanners;
|
||||
|
||||
// refresh enterprise status
|
||||
Object.assign(this.settings.enterprise, {
|
||||
sharing: this.license.isSharingEnabled(),
|
||||
logStreaming: this.license.isLogStreamingEnabled(),
|
||||
ldap: this.license.isLdapEnabled(),
|
||||
saml: this.license.isSamlEnabled(),
|
||||
advancedExecutionFilters: this.license.isAdvancedExecutionFiltersEnabled(),
|
||||
variables: this.license.isVariablesEnabled(),
|
||||
sourceControl: this.license.isSourceControlLicensed(),
|
||||
externalSecrets: this.license.isExternalSecretsEnabled(),
|
||||
showNonProdBanner: this.license.isFeatureEnabled(LICENSE_FEATURES.SHOW_NON_PROD_BANNER),
|
||||
debugInEditor: this.license.isDebugInEditorLicensed(),
|
||||
workflowHistory:
|
||||
this.license.isWorkflowHistoryLicensed() && config.getEnv('workflowHistory.enabled'),
|
||||
});
|
||||
|
||||
if (this.license.isLdapEnabled()) {
|
||||
Object.assign(this.settings.sso.ldap, {
|
||||
loginLabel: getLdapLoginLabel(),
|
||||
loginEnabled: config.getEnv('sso.ldap.loginEnabled'),
|
||||
});
|
||||
}
|
||||
|
||||
if (this.license.isSamlEnabled()) {
|
||||
Object.assign(this.settings.sso.saml, {
|
||||
loginLabel: getSamlLoginLabel(),
|
||||
loginEnabled: config.getEnv('sso.saml.loginEnabled'),
|
||||
});
|
||||
}
|
||||
|
||||
if (this.license.isVariablesEnabled()) {
|
||||
this.settings.variables.limit = getVariablesLimit();
|
||||
}
|
||||
|
||||
if (this.license.isWorkflowHistoryLicensed() && config.getEnv('workflowHistory.enabled')) {
|
||||
Object.assign(this.settings.workflowHistory, {
|
||||
pruneTime: getWorkflowHistoryPruneTime(),
|
||||
licensePruneTime: getWorkflowHistoryLicensePruneTime(),
|
||||
});
|
||||
}
|
||||
|
||||
if (config.getEnv('nodes.communityPackages.enabled')) {
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
const { CommunityPackagesService } = await import('@/services/communityPackages.service');
|
||||
this.settings.missingPackages = Container.get(CommunityPackagesService).hasMissingPackages;
|
||||
}
|
||||
|
||||
this.settings.mfa.enabled = config.get('mfa.enabled');
|
||||
|
||||
return this.settings;
|
||||
}
|
||||
|
||||
addToSettings(newSettings: Record<string, unknown>) {
|
||||
this.settings = { ...this.settings, ...newSettings };
|
||||
}
|
||||
|
||||
private writeStaticJSON(name: string, data: INodeTypeBaseDescription[] | ICredentialType[]) {
|
||||
const filePath = path.join(GENERATED_STATIC_DIR, `types/${name}.json`);
|
||||
const stream = createWriteStream(filePath, 'utf-8');
|
||||
|
Loading…
Reference in New Issue
Block a user