mirror of
https://github.com/n8n-io/n8n.git
synced 2025-02-21 02:56:40 -08:00
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
This commit is contained in:
parent
54f99a7d0d
commit
ab12d3e327
|
@ -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",
|
||||
|
|
|
@ -12,34 +12,6 @@ import {
|
|||
} from './constants';
|
||||
import { Service } from 'typedi';
|
||||
|
||||
async function loadCertStr(): Promise<TLicenseBlock> {
|
||||
// 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<void> {
|
||||
// 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<TLicenseBlock> {
|
||||
// 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<void> {
|
||||
// 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<void> {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
22
packages/cli/src/commands/license/info.ts
Normal file
22
packages/cli/src/commands/license/info.ts
Normal file
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue