diff --git a/cypress/package.json b/cypress/package.json index 509abca04b..e64be91c2b 100644 --- a/cypress/package.json +++ b/cypress/package.json @@ -15,6 +15,7 @@ "start": "cd ..; pnpm start" }, "devDependencies": { + "@n8n/api-types": "workspace:*", "@types/lodash": "catalog:", "eslint-plugin-cypress": "^3.3.0", "n8n-workflow": "workspace:*" diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index 7bef3727dc..808c0b6aca 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -1,6 +1,6 @@ import 'cypress-real-events'; import FakeTimers from '@sinonjs/fake-timers'; -import type { IN8nUISettings } from 'n8n-workflow'; +import type { FrontendSettings } from '@n8n/api-types'; import { WorkflowPage } from '../pages'; import { BACKEND_BASE_URL, @@ -86,8 +86,8 @@ Cypress.Commands.add('signout', () => { cy.getCookie(N8N_AUTH_COOKIE).should('not.exist'); }); -export let settings: Partial; -Cypress.Commands.add('overrideSettings', (value: Partial) => { +export let settings: Partial; +Cypress.Commands.add('overrideSettings', (value: Partial) => { settings = value; }); diff --git a/cypress/support/index.ts b/cypress/support/index.ts index 7c1897b11f..a5f1caf5b2 100644 --- a/cypress/support/index.ts +++ b/cypress/support/index.ts @@ -1,7 +1,7 @@ // Load type definitions that come with Cypress module /// -import type { IN8nUISettings } from 'n8n-workflow'; +import type { FrontendSettings } from '@n8n/api-types'; Cypress.Keyboard.defaults({ keystrokeDelay: 0, @@ -45,7 +45,7 @@ declare global { */ signinAsMember(index?: number): void; signout(): void; - overrideSettings(value: Partial): void; + overrideSettings(value: Partial): void; enableFeature(feature: string): void; disableFeature(feature: string): void; enableQueueMode(): void; diff --git a/packages/@n8n/api-types/src/frontend-settings.ts b/packages/@n8n/api-types/src/frontend-settings.ts new file mode 100644 index 0000000000..8815f14f05 --- /dev/null +++ b/packages/@n8n/api-types/src/frontend-settings.ts @@ -0,0 +1,172 @@ +import type { ExpressionEvaluatorType, LogLevel, WorkflowSettings } from 'n8n-workflow'; + +export interface IVersionNotificationSettings { + enabled: boolean; + endpoint: string; + infoUrl: string; +} + +export interface ITelemetryClientConfig { + url: string; + key: string; +} + +export interface ITelemetrySettings { + enabled: boolean; + config?: ITelemetryClientConfig; +} + +export type AuthenticationMethod = 'email' | 'ldap' | 'saml'; + +export interface IUserManagementSettings { + quota: number; + showSetupOnFirstLoad?: boolean; + smtpSetup: boolean; + authenticationMethod: AuthenticationMethod; +} + +export interface FrontendSettings { + isDocker?: boolean; + databaseType: 'sqlite' | 'mariadb' | 'mysqldb' | 'postgresdb'; + endpointForm: string; + endpointFormTest: string; + endpointFormWaiting: string; + endpointWebhook: string; + endpointWebhookTest: string; + saveDataErrorExecution: WorkflowSettings.SaveDataExecution; + saveDataSuccessExecution: WorkflowSettings.SaveDataExecution; + saveManualExecutions: boolean; + saveExecutionProgress: boolean; + executionTimeout: number; + maxExecutionTimeout: number; + workflowCallerPolicyDefaultOption: WorkflowSettings.CallerPolicy; + oauthCallbackUrls: { + oauth1: string; + oauth2: string; + }; + timezone: string; + urlBaseWebhook: string; + urlBaseEditor: string; + versionCli: string; + nodeJsVersion: string; + concurrency: number; + authCookie: { + secure: boolean; + }; + binaryDataMode: 'default' | 'filesystem' | 's3'; + releaseChannel: 'stable' | 'beta' | 'nightly' | 'dev'; + n8nMetadata?: { + userId?: string; + [key: string]: string | number | undefined; + }; + versionNotifications: IVersionNotificationSettings; + instanceId: string; + telemetry: ITelemetrySettings; + posthog: { + enabled: boolean; + apiHost: string; + apiKey: string; + autocapture: boolean; + disableSessionRecording: boolean; + debug: boolean; + }; + personalizationSurveyEnabled: boolean; + defaultLocale: string; + userManagement: IUserManagementSettings; + sso: { + saml: { + loginLabel: string; + loginEnabled: boolean; + }; + ldap: { + loginLabel: string; + loginEnabled: boolean; + }; + }; + publicApi: { + enabled: boolean; + latestVersion: number; + path: string; + swaggerUi: { + enabled: boolean; + }; + }; + workflowTagsDisabled: boolean; + logLevel: LogLevel; + hiringBannerEnabled: boolean; + previewMode: boolean; + templates: { + enabled: boolean; + host: string; + }; + missingPackages?: boolean; + executionMode: 'regular' | 'queue'; + pushBackend: 'sse' | 'websocket'; + communityNodesEnabled: boolean; + aiAssistant: { + enabled: boolean; + }; + deployment: { + type: string; + }; + isNpmAvailable: boolean; + allowedModules: { + builtIn?: string[]; + external?: string[]; + }; + enterprise: { + sharing: boolean; + ldap: boolean; + saml: boolean; + logStreaming: boolean; + advancedExecutionFilters: boolean; + variables: boolean; + sourceControl: boolean; + auditLogs: boolean; + externalSecrets: boolean; + showNonProdBanner: boolean; + debugInEditor: boolean; + binaryDataS3: boolean; + workflowHistory: boolean; + workerView: boolean; + advancedPermissions: boolean; + projects: { + team: { + limit: number; + }; + }; + }; + hideUsagePage: boolean; + license: { + planName?: string; + consumerId: string; + environment: 'development' | 'production' | 'staging'; + }; + variables: { + limit: number; + }; + expressions: { + evaluator: ExpressionEvaluatorType; + }; + mfa: { + enabled: boolean; + }; + banners: { + dismissed: string[]; + }; + ai: { + enabled: boolean; + }; + workflowHistory: { + pruneTime: number; + licensePruneTime: number; + }; + pruning: { + isEnabled: boolean; + maxAge: number; + maxCount: number; + }; + security: { + blockFileAccessToN8nFiles: boolean; + }; +} diff --git a/packages/@n8n/api-types/src/index.ts b/packages/@n8n/api-types/src/index.ts index 5d59a1b768..89b6a3541c 100644 --- a/packages/@n8n/api-types/src/index.ts +++ b/packages/@n8n/api-types/src/index.ts @@ -1,6 +1,7 @@ +export type * from './datetime'; export type * from './push'; export type * from './scaling'; -export type * from './datetime'; +export type * from './frontend-settings'; export type * from './user'; export type { Collaborator } from './push/collaboration'; diff --git a/packages/cli/src/events/relay-event-map.ts b/packages/cli/src/events/relay-event-map.ts index cf2d5f9cfb..a53a36842e 100644 --- a/packages/cli/src/events/relay-event-map.ts +++ b/packages/cli/src/events/relay-event-map.ts @@ -1,5 +1,5 @@ +import type { AuthenticationMethod } from '@n8n/api-types'; import type { - AuthenticationMethod, IPersonalizationSurveyAnswersV4, IRun, IWorkflowBase, diff --git a/packages/cli/src/interfaces.ts b/packages/cli/src/interfaces.ts index aeb2573d55..02da5a7c77 100644 --- a/packages/cli/src/interfaces.ts +++ b/packages/cli/src/interfaces.ts @@ -239,12 +239,6 @@ export interface IExternalHooksFunctions { }; } -export interface IVersionNotificationSettings { - enabled: boolean; - endpoint: string; - infoUrl: string; -} - export interface IPersonalizationSurveyAnswers { email: string | null; codingSkill: string | null; diff --git a/packages/cli/src/server.ts b/packages/cli/src/server.ts index e7d1eaabfb..12bf5e6b40 100644 --- a/packages/cli/src/server.ts +++ b/packages/cli/src/server.ts @@ -1,10 +1,10 @@ +import type { FrontendSettings } from '@n8n/api-types'; import { exec as callbackExec } from 'child_process'; import cookieParser from 'cookie-parser'; import express from 'express'; import { access as fsAccess } from 'fs/promises'; import helmet from 'helmet'; import { InstanceSettings } from 'n8n-core'; -import type { IN8nUISettings } from 'n8n-workflow'; import { resolve } from 'path'; import { Container, Service } from 'typedi'; import { promisify } from 'util'; @@ -252,7 +252,7 @@ export class Server extends AbstractServer { this.app.get( `/${this.restEndpoint}/settings`, ResponseHelper.send( - async (req: express.Request): Promise => + async (req: express.Request): Promise => frontendService.getSettings(req.headers['push-ref'] as string), ), ); diff --git a/packages/cli/src/services/frontend.service.ts b/packages/cli/src/services/frontend.service.ts index 8459642a5b..ee9e0dabf3 100644 --- a/packages/cli/src/services/frontend.service.ts +++ b/packages/cli/src/services/frontend.service.ts @@ -1,14 +1,10 @@ +import type { FrontendSettings, ITelemetrySettings } from '@n8n/api-types'; import { GlobalConfig } from '@n8n/config'; import { createWriteStream } from 'fs'; import { mkdir } from 'fs/promises'; import uniq from 'lodash/uniq'; import { InstanceSettings } from 'n8n-core'; -import type { - ICredentialType, - IN8nUISettings, - INodeTypeBaseDescription, - ITelemetrySettings, -} from 'n8n-workflow'; +import type { ICredentialType, INodeTypeBaseDescription } from 'n8n-workflow'; import fs from 'node:fs'; import path from 'path'; import { Container, Service } from 'typedi'; @@ -37,7 +33,7 @@ import { UrlService } from './url.service'; @Service() export class FrontendService { - settings: IN8nUISettings; + settings: FrontendSettings; private communityPackagesService?: CommunityPackagesService; @@ -247,7 +243,7 @@ export class FrontendService { this.writeStaticJSON('credentials', credentials); } - getSettings(pushRef?: string): IN8nUISettings { + getSettings(pushRef?: string): FrontendSettings { this.eventService.emit('session-started', { pushRef }); const restEndpoint = this.globalConfig.endpoints.rest; diff --git a/packages/editor-ui/src/Interface.ts b/packages/editor-ui/src/Interface.ts index bcbd8a25f6..e8bc05bec9 100644 --- a/packages/editor-ui/src/Interface.ts +++ b/packages/editor-ui/src/Interface.ts @@ -1,7 +1,12 @@ import type { Component } from 'vue'; import type { NotificationOptions as ElementNotificationOptions } from 'element-plus'; import type { Connection } from '@jsplumb/core'; -import type { Iso8601DateTimeString } from '@n8n/api-types'; +import type { + FrontendSettings, + Iso8601DateTimeString, + IUserManagementSettings, + IVersionNotificationSettings, +} from '@n8n/api-types'; import type { Scope } from '@n8n/permissions'; import type { IMenuItem, NodeCreatorTag } from 'n8n-design-system'; import type { @@ -31,10 +36,8 @@ import type { FeatureFlags, ExecutionStatus, ITelemetryTrackProperties, - IUserManagementSettings, WorkflowSettings, IUserSettings, - IN8nUISettings, BannerName, INodeExecutionData, INodeProperties, @@ -496,12 +499,6 @@ export interface IUser extends IUserResponse { mfaEnabled: boolean; } -export interface IVersionNotificationSettings { - enabled: boolean; - endpoint: string; - infoUrl: string; -} - export interface IUserListAction { label: string; value: string; @@ -1090,7 +1087,7 @@ export interface INodeCreatorState { export interface ISettingsState { initialized: boolean; - settings: IN8nUISettings; + settings: FrontendSettings; userManagement: IUserManagementSettings; templatesEndpointHealthy: boolean; api: { @@ -1643,7 +1640,7 @@ export type EnterpriseEditionFeatureKey = | 'WorkerView' | 'AdvancedPermissions'; -export type EnterpriseEditionFeatureValue = keyof Omit; +export type EnterpriseEditionFeatureValue = keyof Omit; export interface IN8nPromptResponse { updated: boolean; diff --git a/packages/editor-ui/src/__tests__/defaults.ts b/packages/editor-ui/src/__tests__/defaults.ts index 3328ac9100..d2134ebf55 100644 --- a/packages/editor-ui/src/__tests__/defaults.ts +++ b/packages/editor-ui/src/__tests__/defaults.ts @@ -1,6 +1,6 @@ -import type { IN8nUISettings } from 'n8n-workflow'; +import type { FrontendSettings } from '@n8n/api-types'; -export const defaultSettings: IN8nUISettings = { +export const defaultSettings: FrontendSettings = { databaseType: 'sqlite', isDocker: false, pruning: { diff --git a/packages/editor-ui/src/api/settings.ts b/packages/editor-ui/src/api/settings.ts index ffac562da9..f26703a1a4 100644 --- a/packages/editor-ui/src/api/settings.ts +++ b/packages/editor-ui/src/api/settings.ts @@ -1,9 +1,9 @@ import type { IRestApiContext, IN8nPrompts, IN8nPromptResponse } from '../Interface'; import { makeRestApiRequest, get, post } from '@/utils/apiUtils'; import { N8N_IO_BASE_URL, NPM_COMMUNITY_NODE_SEARCH_API_URL } from '@/constants'; -import type { IN8nUISettings } from 'n8n-workflow'; +import type { FrontendSettings } from '@n8n/api-types'; -export async function getSettings(context: IRestApiContext): Promise { +export async function getSettings(context: IRestApiContext): Promise { return await makeRestApiRequest(context, 'GET', '/settings'); } diff --git a/packages/editor-ui/src/components/Telemetry.vue b/packages/editor-ui/src/components/Telemetry.vue index df3ed63cc1..b799ad6172 100644 --- a/packages/editor-ui/src/components/Telemetry.vue +++ b/packages/editor-ui/src/components/Telemetry.vue @@ -1,8 +1,8 @@