Skip to content

Commit

Permalink
feat(core): Add license:info command (#6047)
Browse files Browse the repository at this point in the history
* feat(core): Add license:info command

* revert changes to start.ts

* revert changes to start.ts

* fix typo
  • Loading branch information
csuermann authored Apr 21, 2023
1 parent 54f99a7 commit ab12d3e
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 39 deletions.
2 changes: 1 addition & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
68 changes: 38 additions & 30 deletions packages/cli/src/License.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
});

Expand All @@ -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;
Expand Down Expand Up @@ -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 changes: 22 additions & 0 deletions packages/cli/src/commands/license/info.ts
Original file line number Diff line number Diff line change
@@ -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);
}
}
2 changes: 1 addition & 1 deletion packages/cli/src/config/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
9 changes: 6 additions & 3 deletions packages/cli/src/license/license.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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
Expand All @@ -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);
}
}

Expand Down
8 changes: 4 additions & 4 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit ab12d3e

Please sign in to comment.