From 83aef1712070c29fea5d0522c95b1208af4cd2e4 Mon Sep 17 00:00:00 2001 From: Michael Auerswald Date: Fri, 31 Mar 2023 13:51:38 +0200 Subject: [PATCH] feat(core): Read ephemeral license from environment and clean up ee flags (#5808) Co-authored-by: Cornelius Suermann --- packages/cli/package.json | 2 +- packages/cli/src/Ldap/constants.ts | 2 -- packages/cli/src/Ldap/helpers.ts | 3 +- packages/cli/src/License.ts | 13 ++++++-- packages/cli/src/Server.ts | 4 +-- .../UserManagement/UserManagementHelper.ts | 5 +-- packages/cli/src/api/e2e.api.ts | 22 +++++++++++-- packages/cli/src/config/index.ts | 4 --- packages/cli/src/config/schema.ts | 31 ++++--------------- .../MessageEventBus/MessageEventBusHelper.ts | 3 +- .../cli/src/executions/executionHelpers.ts | 6 +--- packages/cli/src/sso/saml/constants.ts | 2 -- packages/cli/src/sso/saml/samlHelpers.ts | 7 ++--- .../cli/test/integration/eventbus.test.ts | 10 +++--- .../test/integration/ldap/ldap.api.test.ts | 7 +++-- .../test/integration/saml/saml.api.test.ts | 6 ++-- packages/cli/test/integration/shared/utils.ts | 4 +-- .../workflows.controller.ee.test.ts | 7 +++-- pnpm-lock.yaml | 29 +++++++---------- 19 files changed, 75 insertions(+), 92 deletions(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index dd8720b73b9dc..086977d013369 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -115,7 +115,7 @@ "tsconfig-paths": "^4.1.2" }, "dependencies": { - "@n8n_io/license-sdk": "~1.8.0", + "@n8n_io/license-sdk": "~2.0.0", "@oclif/command": "^1.8.16", "@oclif/core": "^1.16.4", "@oclif/errors": "^1.3.6", diff --git a/packages/cli/src/Ldap/constants.ts b/packages/cli/src/Ldap/constants.ts index 3b7b369b80abf..c70159e4e071f 100644 --- a/packages/cli/src/Ldap/constants.ts +++ b/packages/cli/src/Ldap/constants.ts @@ -2,8 +2,6 @@ import type { LdapConfig } from './types'; export const LDAP_FEATURE_NAME = 'features.ldap'; -export const LDAP_ENABLED = 'enterprise.features.ldap'; - export const LDAP_LOGIN_LABEL = 'sso.ldap.loginLabel'; export const LDAP_LOGIN_ENABLED = 'sso.ldap.loginEnabled'; diff --git a/packages/cli/src/Ldap/helpers.ts b/packages/cli/src/Ldap/helpers.ts index 6ed83242e001a..0785f7fdd1fb5 100644 --- a/packages/cli/src/Ldap/helpers.ts +++ b/packages/cli/src/Ldap/helpers.ts @@ -17,7 +17,6 @@ import { LdapManager } from './LdapManager.ee'; import { BINARY_AD_ATTRIBUTES, LDAP_CONFIG_SCHEMA, - LDAP_ENABLED, LDAP_FEATURE_NAME, LDAP_LOGIN_ENABLED, LDAP_LOGIN_LABEL, @@ -37,7 +36,7 @@ import { */ export const isLdapEnabled = (): boolean => { const license = Container.get(License); - return isUserManagementEnabled() && (config.getEnv(LDAP_ENABLED) || license.isLdapEnabled()); + return isUserManagementEnabled() && license.isLdapEnabled(); }; /** diff --git a/packages/cli/src/License.ts b/packages/cli/src/License.ts index 9dc68d86a5240..19d3e9510fdd7 100644 --- a/packages/cli/src/License.ts +++ b/packages/cli/src/License.ts @@ -1,4 +1,4 @@ -import type { TEntitlement, TLicenseContainerStr } from '@n8n_io/license-sdk'; +import type { TEntitlement, TLicenseBlock } from '@n8n_io/license-sdk'; import { LicenseManager } from '@n8n_io/license-sdk'; import type { ILogger } from 'n8n-workflow'; import { getLogger } from './Logger'; @@ -7,7 +7,12 @@ import * as Db from '@/Db'; import { LICENSE_FEATURES, N8N_VERSION, SETTINGS_LICENSE_CERT_KEY } from './constants'; import { Service } from 'typedi'; -async function loadCertStr(): Promise { +async function loadCertStr(): Promise { + // if we have an ephemeral license, we don't want to load it from the database + const ephemeralLicense = config.get('license.cert'); + if (ephemeralLicense) { + return ephemeralLicense; + } const databaseSettings = await Db.collections.Settings.findOne({ where: { key: SETTINGS_LICENSE_CERT_KEY, @@ -17,7 +22,9 @@ async function loadCertStr(): Promise { return databaseSettings?.value ?? ''; } -async function saveCertStr(value: TLicenseContainerStr): Promise { +async function saveCertStr(value: TLicenseBlock): Promise { + // if we have an ephemeral license, we don't want to save it to the database + if (config.get('license.cert')) return; await Db.collections.Settings.upsert( { key: SETTINGS_LICENSE_CERT_KEY, diff --git a/packages/cli/src/Server.ts b/packages/cli/src/Server.ts index 5bffa178c7e08..1609b3ba286e0 100644 --- a/packages/cli/src/Server.ts +++ b/packages/cli/src/Server.ts @@ -311,8 +311,8 @@ class Server extends AbstractServer { sharing: false, ldap: false, saml: false, - logStreaming: config.getEnv('enterprise.features.logStreaming'), - advancedExecutionFilters: config.getEnv('enterprise.features.advancedExecutionFilters'), + logStreaming: false, + advancedExecutionFilters: false, }, hideUsagePage: config.getEnv('hideUsagePage'), license: { diff --git a/packages/cli/src/UserManagement/UserManagementHelper.ts b/packages/cli/src/UserManagement/UserManagementHelper.ts index 4c34a57b31e26..2e4682db2eef3 100644 --- a/packages/cli/src/UserManagement/UserManagementHelper.ts +++ b/packages/cli/src/UserManagement/UserManagementHelper.ts @@ -57,10 +57,7 @@ export function isUserManagementEnabled(): boolean { export function isSharingEnabled(): boolean { const license = Container.get(License); - return ( - isUserManagementEnabled() && - (config.getEnv('enterprise.features.sharing') || license.isSharingEnabled()) - ); + return isUserManagementEnabled() && license.isSharingEnabled(); } export async function getRoleId(scope: Role['scope'], name: Role['name']): Promise { diff --git a/packages/cli/src/api/e2e.api.ts b/packages/cli/src/api/e2e.api.ts index befd913114449..fb9097da619b6 100644 --- a/packages/cli/src/api/e2e.api.ts +++ b/packages/cli/src/api/e2e.api.ts @@ -5,6 +5,7 @@ /* eslint-disable @typescript-eslint/no-unsafe-assignment */ /* eslint-disable @typescript-eslint/naming-convention */ import { Router } from 'express'; +import type { Request } from 'express'; import bodyParser from 'body-parser'; import { v4 as uuid } from 'uuid'; import config from '@/config'; @@ -12,12 +13,26 @@ import * as Db from '@/Db'; import type { Role } from '@db/entities/Role'; import { hashPassword } from '@/UserManagement/UserManagementHelper'; import { eventBus } from '@/eventbus/MessageEventBus/MessageEventBus'; +import Container from 'typedi'; +import { License } from '../License'; if (process.env.E2E_TESTS !== 'true') { console.error('E2E endpoints only allowed during E2E tests'); process.exit(1); } +const enabledFeatures = { + sharing: true, //default to true here instead of setting it in config/index.ts for e2e + ldap: false, + saml: false, + logStreaming: false, + advancedExecutionFilters: false, +}; + +type Feature = keyof typeof enabledFeatures; + +Container.get(License).isFeatureEnabled = (feature: Feature) => enabledFeatures[feature] ?? false; + const tablesToTruncate = [ 'auth_identity', 'auth_provider_sync_history', @@ -78,7 +93,7 @@ const setupUserManagement = async () => { }; const resetLogStreaming = async () => { - config.set('enterprise.features.logStreaming', false); + enabledFeatures.logStreaming = false; for (const id in eventBus.destinations) { await eventBus.removeDestination(id); } @@ -127,7 +142,8 @@ e2eController.post('/db/setup-owner', bodyParser.json(), async (req, res) => { res.writeHead(204).end(); }); -e2eController.post('/enable-feature/:feature', async (req, res) => { - config.set(`enterprise.features.${req.params.feature}`, true); +e2eController.post('/enable-feature/:feature', async (req: Request<{ feature: Feature }>, res) => { + const { feature } = req.params; + enabledFeatures[feature] = true; res.writeHead(204).end(); }); diff --git a/packages/cli/src/config/index.ts b/packages/cli/src/config/index.ts index f84c73cddb936..4b87524611196 100644 --- a/packages/cli/src/config/index.ts +++ b/packages/cli/src/config/index.ts @@ -26,10 +26,6 @@ if (inE2ETests) { const config = convict(schema, { args: [] }); -if (inE2ETests) { - config.set('enterprise.features.sharing', true); -} - // eslint-disable-next-line @typescript-eslint/unbound-method config.getEnv = config.get; diff --git a/packages/cli/src/config/schema.ts b/packages/cli/src/config/schema.ts index 5d9cb40045740..74f7ab64fc4e0 100644 --- a/packages/cli/src/config/schema.ts +++ b/packages/cli/src/config/schema.ts @@ -990,31 +990,6 @@ export const schema = { }, }, - enterprise: { - features: { - sharing: { - format: Boolean, - default: false, - }, - ldap: { - format: Boolean, - default: false, - }, - saml: { - format: Boolean, - default: false, - }, - logStreaming: { - format: Boolean, - default: false, - }, - advancedExecutionFilters: { - format: Boolean, - default: false, - }, - }, - }, - sso: { justInTimeProvisioning: { format: Boolean, @@ -1166,6 +1141,12 @@ export const schema = { env: 'N8N_LICENSE_TENANT_ID', doc: 'Tenant id used by the license manager', }, + cert: { + format: String, + default: '', + env: 'N8N_LICENSE_CERT', + doc: 'Ephemeral license certificate', + }, }, hideUsagePage: { diff --git a/packages/cli/src/eventbus/MessageEventBus/MessageEventBusHelper.ts b/packages/cli/src/eventbus/MessageEventBus/MessageEventBusHelper.ts index 7dfc68e564d5e..29eab2872aa5e 100644 --- a/packages/cli/src/eventbus/MessageEventBus/MessageEventBusHelper.ts +++ b/packages/cli/src/eventbus/MessageEventBus/MessageEventBusHelper.ts @@ -1,8 +1,7 @@ -import config from '@/config'; import { License } from '@/License'; import { Container } from 'typedi'; export function isLogStreamingEnabled(): boolean { const license = Container.get(License); - return config.getEnv('enterprise.features.logStreaming') || license.isLogStreamingEnabled(); + return license.isLogStreamingEnabled(); } diff --git a/packages/cli/src/executions/executionHelpers.ts b/packages/cli/src/executions/executionHelpers.ts index de27577e22170..148bd9b8b9644 100644 --- a/packages/cli/src/executions/executionHelpers.ts +++ b/packages/cli/src/executions/executionHelpers.ts @@ -2,7 +2,6 @@ import { Container } from 'typedi'; import type { IExecutionFlattedDb } from '@/Interfaces'; import type { ExecutionStatus } from 'n8n-workflow'; import { License } from '@/License'; -import config from '@/config'; export function getStatusUsingPreviousExecutionStatusMethod( execution: IExecutionFlattedDb, @@ -22,8 +21,5 @@ export function getStatusUsingPreviousExecutionStatusMethod( export function isAdvancedExecutionFiltersEnabled(): boolean { const license = Container.get(License); - return ( - config.getEnv('enterprise.features.advancedExecutionFilters') || - license.isAdvancedExecutionFiltersEnabled() - ); + return license.isAdvancedExecutionFiltersEnabled(); } diff --git a/packages/cli/src/sso/saml/constants.ts b/packages/cli/src/sso/saml/constants.ts index 6f92690f5f5d1..3729f3ce51660 100644 --- a/packages/cli/src/sso/saml/constants.ts +++ b/packages/cli/src/sso/saml/constants.ts @@ -28,8 +28,6 @@ export class SamlUrls { export const SAML_PREFERENCES_DB_KEY = 'features.saml'; -export const SAML_ENTERPRISE_FEATURE_ENABLED = 'enterprise.features.saml'; - export const SAML_LOGIN_LABEL = 'sso.saml.loginLabel'; export const SAML_LOGIN_ENABLED = 'sso.saml.loginEnabled'; diff --git a/packages/cli/src/sso/saml/samlHelpers.ts b/packages/cli/src/sso/saml/samlHelpers.ts index 57c710e7071a4..5975c02653c34 100644 --- a/packages/cli/src/sso/saml/samlHelpers.ts +++ b/packages/cli/src/sso/saml/samlHelpers.ts @@ -10,7 +10,7 @@ import type { SamlPreferences } from './types/samlPreferences'; import type { SamlUserAttributes } from './types/samlUserAttributes'; import type { FlowResult } from 'samlify/types/src/flow'; import type { SamlAttributeMapping } from './types/samlAttributeMapping'; -import { SAML_ENTERPRISE_FEATURE_ENABLED, SAML_LOGIN_ENABLED, SAML_LOGIN_LABEL } from './constants'; +import { SAML_LOGIN_ENABLED, SAML_LOGIN_LABEL } from './constants'; import { isEmailCurrentAuthenticationMethod, isSamlCurrentAuthenticationMethod, @@ -52,10 +52,7 @@ export function setSamlLoginLabel(label: string): void { export function isSamlLicensed(): boolean { const license = Container.get(License); - return ( - isUserManagementEnabled() && - (license.isSamlEnabled() || config.getEnv(SAML_ENTERPRISE_FEATURE_ENABLED)) - ); + return isUserManagementEnabled() && license.isSamlEnabled(); } export function isSamlLicensedAndEnabled(): boolean { diff --git a/packages/cli/test/integration/eventbus.test.ts b/packages/cli/test/integration/eventbus.test.ts index d456f86799884..52a5642bf9f11 100644 --- a/packages/cli/test/integration/eventbus.test.ts +++ b/packages/cli/test/integration/eventbus.test.ts @@ -3,6 +3,7 @@ import config from '@/config'; import axios from 'axios'; import syslog from 'syslog-client'; import { v4 as uuid } from 'uuid'; +import Container from 'typedi'; import type { SuperAgentTest } from 'supertest'; import * as utils from './shared/utils'; import * as testDb from './shared/testDb'; @@ -23,6 +24,7 @@ import { MessageEventBusDestinationWebhook } from '@/eventbus/MessageEventBusDes import { MessageEventBusDestinationSentry } from '@/eventbus/MessageEventBusDestination/MessageEventBusDestinationSentry.ee'; import { EventMessageAudit } from '@/eventbus/EventMessageClasses/EventMessageAudit'; import { EventNamesTypes } from '@/eventbus/EventMessageClasses'; +import { License } from '@/License'; jest.unmock('@/eventbus/MessageEventBus/MessageEventBus'); jest.mock('axios'); @@ -77,6 +79,7 @@ async function confirmIdSent(id: string) { } beforeAll(async () => { + Container.get(License).isLogStreamingEnabled = () => true; app = await utils.initTestServer({ endpointGroups: ['eventBus'] }); globalOwnerRole = await testDb.getGlobalOwnerRole(); @@ -101,7 +104,6 @@ beforeAll(async () => { utils.initConfigFile(); config.set('eventBus.logWriter.logBaseName', 'n8n-test-logwriter'); config.set('eventBus.logWriter.keepLogCount', 1); - config.set('enterprise.features.logStreaming', true); config.set('userManagement.disabled', false); config.set('userManagement.isInstanceOwnerSetUp', true); @@ -110,6 +112,7 @@ beforeAll(async () => { afterAll(async () => { jest.mock('@/eventbus/MessageEventBus/MessageEventBus'); + Container.reset(); await testDb.terminate(); await eventBus.close(); }); @@ -178,7 +181,6 @@ test.skip('should send message to syslog', async () => { eventName: 'n8n.test.message' as EventNamesTypes, id: uuid(), }); - config.set('enterprise.features.logStreaming', true); const syslogDestination = eventBus.destinations[ testSyslogDestination.id! @@ -219,7 +221,6 @@ test.skip('should confirm send message if there are no subscribers', async () => eventName: 'n8n.test.unsub' as EventNamesTypes, id: uuid(), }); - config.set('enterprise.features.logStreaming', true); const syslogDestination = eventBus.destinations[ testSyslogDestination.id! @@ -255,7 +256,6 @@ test('should anonymize audit message to syslog ', async () => { }, id: uuid(), }); - config.set('enterprise.features.logStreaming', true); const syslogDestination = eventBus.destinations[ testSyslogDestination.id! @@ -317,7 +317,6 @@ test('should send message to webhook ', async () => { eventName: 'n8n.test.message' as EventNamesTypes, id: uuid(), }); - config.set('enterprise.features.logStreaming', true); const webhookDestination = eventBus.destinations[ testWebhookDestination.id! @@ -352,7 +351,6 @@ test('should send message to sentry ', async () => { eventName: 'n8n.test.message' as EventNamesTypes, id: uuid(), }); - config.set('enterprise.features.logStreaming', true); const sentryDestination = eventBus.destinations[ testSentryDestination.id! diff --git a/packages/cli/test/integration/ldap/ldap.api.test.ts b/packages/cli/test/integration/ldap/ldap.api.test.ts index fcecb25d8fcfb..3814cbe4c1310 100644 --- a/packages/cli/test/integration/ldap/ldap.api.test.ts +++ b/packages/cli/test/integration/ldap/ldap.api.test.ts @@ -1,6 +1,7 @@ import express from 'express'; import type { Entry as LdapUser } from 'ldapts'; import { Not } from 'typeorm'; +import Container from 'typedi'; import { jsonParse } from 'n8n-workflow'; import config from '@/config'; import * as Db from '@/Db'; @@ -12,11 +13,12 @@ import { LdapService } from '@/Ldap/LdapService.ee'; import { encryptPassword, saveLdapSynchronization } from '@/Ldap/helpers'; import type { LdapConfig } from '@/Ldap/types'; import { sanitizeUser } from '@/UserManagement/UserManagementHelper'; +import { getCurrentAuthenticationMethod, setCurrentAuthenticationMethod } from '@/sso/ssoHelpers'; +import { License } from '@/License'; import { randomEmail, randomName, uniqueId } from './../shared/random'; import * as testDb from './../shared/testDb'; import type { AuthAgent } from '../shared/types'; import * as utils from '../shared/utils'; -import { getCurrentAuthenticationMethod, setCurrentAuthenticationMethod } from '@/sso/ssoHelpers'; jest.mock('@/telemetry'); jest.mock('@/UserManagement/email/NodeMailer'); @@ -41,6 +43,7 @@ const defaultLdapConfig = { }; beforeAll(async () => { + Container.get(License).isLdapEnabled = () => true; app = await utils.initTestServer({ endpointGroups: ['auth', 'ldap'] }); const [globalOwnerRole, fetchedGlobalMemberRole] = await testDb.getAllRoles(); @@ -77,10 +80,10 @@ beforeEach(async () => { config.set('userManagement.disabled', false); config.set('userManagement.isInstanceOwnerSetUp', true); config.set('userManagement.emails.mode', ''); - config.set('enterprise.features.ldap', true); }); afterAll(async () => { + Container.reset(); await testDb.terminate(); }); diff --git a/packages/cli/test/integration/saml/saml.api.test.ts b/packages/cli/test/integration/saml/saml.api.test.ts index a3abb177aa2d7..d02bd95c68ac8 100644 --- a/packages/cli/test/integration/saml/saml.api.test.ts +++ b/packages/cli/test/integration/saml/saml.api.test.ts @@ -1,8 +1,9 @@ +import Container from 'typedi'; import type { SuperAgentTest } from 'supertest'; -import config from '@/config'; import type { User } from '@db/entities/User'; import { setSamlLoginEnabled } from '@/sso/saml/samlHelpers'; import { getCurrentAuthenticationMethod, setCurrentAuthenticationMethod } from '@/sso/ssoHelpers'; +import { License } from '@/License'; import { randomEmail, randomName, randomValidPassword } from '../shared/random'; import * as testDb from '../shared/testDb'; import * as utils from '../shared/utils'; @@ -13,16 +14,17 @@ let authOwnerAgent: SuperAgentTest; async function enableSaml(enable: boolean) { await setSamlLoginEnabled(enable); - config.set('enterprise.features.saml', enable); } beforeAll(async () => { + Container.get(License).isSamlEnabled = () => true; const app = await utils.initTestServer({ endpointGroups: ['me', 'saml'] }); owner = await testDb.createOwner(); authOwnerAgent = utils.createAuthAgent(app)(owner); }); afterAll(async () => { + Container.reset(); await testDb.terminate(); }); diff --git a/packages/cli/test/integration/shared/utils.ts b/packages/cli/test/integration/shared/utils.ts index e8bf676ba7125..619d03f9b7697 100644 --- a/packages/cli/test/integration/shared/utils.ts +++ b/packages/cli/test/integration/shared/utils.ts @@ -74,13 +74,13 @@ import { InternalHooks } from '@/InternalHooks'; import { LoadNodesAndCredentials } from '@/LoadNodesAndCredentials'; import { PostHogClient } from '@/posthog'; import { LdapManager } from '@/Ldap/LdapManager.ee'; -import { LDAP_ENABLED } from '@/Ldap/constants'; import { handleLdapInit } from '@/Ldap/helpers'; import { Push } from '@/push'; import { setSamlLoginEnabled } from '@/sso/saml/samlHelpers'; import { SamlService } from '@/sso/saml/saml.service.ee'; import { SamlController } from '@/sso/saml/routes/saml.controller.ee'; import { EventBusController } from '@/eventbus/eventBus.controller'; +import { License } from '@/License'; export const mockInstance = ( ctor: new (...args: any[]) => T, @@ -186,7 +186,7 @@ export async function initTestServer({ ); break; case 'ldap': - config.set(LDAP_ENABLED, true); + Container.get(License).isLdapEnabled = () => true; await handleLdapInit(); const { service, sync } = LdapManager.getInstance(); registerController( diff --git a/packages/cli/test/integration/workflows.controller.ee.test.ts b/packages/cli/test/integration/workflows.controller.ee.test.ts index c544416eee6c2..22e90558e79c0 100644 --- a/packages/cli/test/integration/workflows.controller.ee.test.ts +++ b/packages/cli/test/integration/workflows.controller.ee.test.ts @@ -1,10 +1,10 @@ +import Container from 'typedi'; import type { SuperAgentTest } from 'supertest'; import { v4 as uuid } from 'uuid'; import type { INode } from 'n8n-workflow'; import * as UserManagementHelpers from '@/UserManagement/UserManagementHelper'; import type { User } from '@db/entities/User'; -import config from '@/config'; import * as utils from './shared/utils'; import * as testDb from './shared/testDb'; @@ -12,6 +12,7 @@ import { createWorkflow } from './shared/testDb'; import type { SaveCredentialFunction } from './shared/types'; import { makeWorkflow } from './shared/utils'; import { randomCredentialPayload } from './shared/random'; +import { License } from '@/License'; let owner: User; let member: User; @@ -23,6 +24,7 @@ let saveCredential: SaveCredentialFunction; let sharingSpy: jest.SpyInstance; beforeAll(async () => { + Container.get(License).isSharingEnabled = () => true; const app = await utils.initTestServer({ endpointGroups: ['workflows'] }); const globalOwnerRole = await testDb.getGlobalOwnerRole(); @@ -42,8 +44,6 @@ beforeAll(async () => { sharingSpy = jest.spyOn(UserManagementHelpers, 'isSharingEnabled').mockReturnValue(true); await utils.initNodeTypes(); - - config.set('enterprise.features.sharing', true); }); beforeEach(async () => { @@ -51,6 +51,7 @@ beforeEach(async () => { }); afterAll(async () => { + Container.reset(); await testDb.terminate(); }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c47fb4938efdc..d760b05e2827f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -151,8 +151,8 @@ importers: packages/cli: dependencies: '@n8n_io/license-sdk': - specifier: ~1.8.0 - version: 1.8.0 + specifier: ~2.0.0 + version: 2.0.0 '@oclif/command': specifier: ^1.8.16 version: 1.8.18(@oclif/config@1.18.5)(supports-color@8.1.1) @@ -4284,16 +4284,14 @@ packages: dev: false optional: true - /@n8n_io/license-sdk@1.8.0: - resolution: {integrity: sha512-dSBD6EHTu6kWWz1ILxtCcaQqVZu+p/8J0eQ2ntx7Jk8BYSvn5Hh4Oz5M81ut9Pz+2uak+GnIuI6KeYUe1QBXIQ==} + /@n8n_io/license-sdk@2.0.0: + resolution: {integrity: sha512-JBgVqp2Hp8QkEHwWmDvoU8dLrq0wZlK38FnwaX/yZiCGpEz1+zywFxaggxbDYXxvhX3cwlgxv3o3kfVaYX1Xlw==} engines: {node: '>=14.0.0', npm: '>=7.10.0'} dependencies: - axios: 1.1.3 crypto-js: 4.1.1 node-machine-id: 1.1.12 node-rsa: 1.1.1 - transitivePeerDependencies: - - debug + undici: 5.21.0 dev: false /@n8n_io/riot-tmpl@3.0.0: @@ -8220,16 +8218,6 @@ packages: - debug dev: false - /axios@1.1.3: - resolution: {integrity: sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA==} - dependencies: - follow-redirects: 1.15.2(debug@3.2.7) - form-data: 4.0.0 - proxy-from-env: 1.1.0 - transitivePeerDependencies: - - debug - dev: false - /babel-core@7.0.0-bridge.0(@babel/core@7.20.12): resolution: {integrity: sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==} peerDependencies: @@ -20766,6 +20754,13 @@ packages: undertaker-registry: 1.0.1 dev: true + /undici@5.21.0: + resolution: {integrity: sha512-HOjK8l6a57b2ZGXOcUsI5NLfoTrfmbOl90ixJDl0AEFG4wgHNDQxtZy15/ZQp7HhjkpaGlp/eneMgtsu1dIlUA==} + engines: {node: '>=12.18'} + dependencies: + busboy: 1.6.0 + dev: false + /unescape@1.0.1: resolution: {integrity: sha512-O0+af1Gs50lyH1nUu3ZyYS1cRh01Q/kUKatTOkSs7jukXE6/NebucDVxyiDsA9AQ4JC1V1jUH9EO8JX2nMDgGQ==} engines: {node: '>=0.10.0'}