From ab12d3e3278745b290de82c16f358841b20850b4 Mon Sep 17 00:00:00 2001 From: Cornelius Suermann Date: Fri, 21 Apr 2023 17:10:10 +0200 Subject: [PATCH] feat(core): Add license:info command (#6047) * feat(core): Add license:info command * revert changes to start.ts * revert changes to start.ts * fix typo --- packages/cli/package.json | 2 +- packages/cli/src/License.ts | 68 +++++++++++-------- packages/cli/src/commands/license/info.ts | 22 ++++++ packages/cli/src/config/schema.ts | 2 +- .../cli/src/license/license.controller.ts | 9 ++- pnpm-lock.yaml | 8 +-- 6 files changed, 72 insertions(+), 39 deletions(-) create mode 100644 packages/cli/src/commands/license/info.ts diff --git a/packages/cli/package.json b/packages/cli/package.json index d9378431a0..25bc5e2217 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -116,7 +116,7 @@ "tsconfig-paths": "^4.1.2" }, "dependencies": { - "@n8n_io/license-sdk": "~2.1.0", + "@n8n_io/license-sdk": "~2.3.0", "@oclif/command": "^1.8.16", "@oclif/core": "^1.16.4", "@oclif/errors": "^1.3.6", diff --git a/packages/cli/src/License.ts b/packages/cli/src/License.ts index d1f2015187..1b820931e1 100644 --- a/packages/cli/src/License.ts +++ b/packages/cli/src/License.ts @@ -12,34 +12,6 @@ import { } from './constants'; import { Service } from 'typedi'; -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, - }, - }); - - return databaseSettings?.value ?? ''; -} - -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, - value, - loadOnStartup: false, - }, - ['key'], - ); -} - @Service() export class License { private logger: ILogger; @@ -67,8 +39,8 @@ export class License { autoRenewEnabled, autoRenewOffset, logger: this.logger, - loadCertStr, - saveCertStr, + loadCertStr: async () => this.loadCertStr(), + saveCertStr: async (value: TLicenseBlock) => this.saveCertStr(value), deviceFingerprint: () => instanceId, }); @@ -80,6 +52,34 @@ export class License { } } + async 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, + }, + }); + + return databaseSettings?.value ?? ''; + } + + async 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, + value, + loadOnStartup: false, + }, + ['key'], + ); + } + async activate(activationKey: string): Promise { if (!this.manager) { return; @@ -185,4 +185,12 @@ export class License { getPlanName(): string { return (this.getFeatureValue('planName') ?? 'Community') as string; } + + getInfo(): string { + if (!this.manager) { + return 'n/a'; + } + + return this.manager.toString(); + } } diff --git a/packages/cli/src/commands/license/info.ts b/packages/cli/src/commands/license/info.ts new file mode 100644 index 0000000000..f4ebd406dc --- /dev/null +++ b/packages/cli/src/commands/license/info.ts @@ -0,0 +1,22 @@ +import { License } from '@/License'; +import { Container } from 'typedi'; +import { BaseCommand } from '../BaseCommand'; + +export class LicenseInfoCommand extends BaseCommand { + static description = 'Print license information'; + + static examples = ['$ n8n license:info']; + + async run() { + const license = Container.get(License); + await license.init(this.instanceId); + + this.logger.info('Printing license information:\n' + license.getInfo()); + } + + async catch(error: Error) { + this.logger.error('\nGOT ERROR'); + this.logger.info('===================================='); + this.logger.error(error.message); + } +} diff --git a/packages/cli/src/config/schema.ts b/packages/cli/src/config/schema.ts index 729df98ed7..e570109f11 100644 --- a/packages/cli/src/config/schema.ts +++ b/packages/cli/src/config/schema.ts @@ -1130,7 +1130,7 @@ export const schema = { format: Boolean, default: true, env: 'N8N_LICENSE_AUTO_RENEW_ENABLED', - doc: 'Whether autorenew for licenses is enabled.', + doc: 'Whether auto renewal for licenses is enabled.', }, autoRenewOffset: { format: Number, diff --git a/packages/cli/src/license/license.controller.ts b/packages/cli/src/license/license.controller.ts index 75d8252411..e5dd13a18b 100644 --- a/packages/cli/src/license/license.controller.ts +++ b/packages/cli/src/license/license.controller.ts @@ -75,6 +75,7 @@ licenseController.post( } catch (e) { const error = e as Error & { errorId?: string }; + //override specific error messages (to map License Server vocabulary to n8n terms) switch (error.errorId ?? 'UNSPECIFIED') { case 'SCHEMA_VALIDATION': error.message = 'Activation key is in the wrong format'; @@ -92,7 +93,7 @@ licenseController.post( break; } - throw new ResponseHelper.BadRequestError((e as Error).message); + throw new ResponseHelper.BadRequestError(error.message); } // Return the read data, plus the management JWT @@ -115,10 +116,12 @@ licenseController.post( try { await license.renew(); } catch (e) { + const error = e as Error & { errorId?: string }; + // not awaiting so as not to make the endpoint hang void Container.get(InternalHooks).onLicenseRenewAttempt({ success: false }); - if (e instanceof Error) { - throw new ResponseHelper.BadRequestError(e.message); + if (error instanceof Error) { + throw new ResponseHelper.BadRequestError(error.message); } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d37180405f..08852f1cf8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -158,8 +158,8 @@ importers: packages/cli: dependencies: '@n8n_io/license-sdk': - specifier: ~2.1.0 - version: 2.1.0 + specifier: ~2.3.0 + version: 2.3.0 '@oclif/command': specifier: ^1.8.16 version: 1.8.18(@oclif/config@1.18.5)(supports-color@8.1.1) @@ -4300,8 +4300,8 @@ packages: dev: false optional: true - /@n8n_io/license-sdk@2.1.0: - resolution: {integrity: sha512-SwIm9b6a30/fAvl1aY0a6cgoSyQBgKHX44M4Ykesn45VSGBKlzO5uuIiIcEPdVjjLEelm7u6wLoDFdIVG37b7Q==} + /@n8n_io/license-sdk@2.3.0: + resolution: {integrity: sha512-1qOg4VEi2mZzhAJ5Uh9IT9Jn/b3xCaxyFbovYLtymzy3ObafUyWieUrSQri3BrCbW1dwQHz99DEVFxYCq1Je0Q==} engines: {node: '>=14.0.0', npm: '>=7.10.0'} dependencies: crypto-js: 4.1.1