mirror of https://github.com/certd/certd
chore: 单元测试
parent
9187e87419
commit
70ce6be0bf
|
@ -24,3 +24,4 @@ dist-ssr
|
||||||
*.sw?
|
*.sw?
|
||||||
|
|
||||||
test/user.secret.*
|
test/user.secret.*
|
||||||
|
test/**/*.js
|
|
@ -1,5 +1,4 @@
|
||||||
{
|
{
|
||||||
"extension": ["ts"],
|
"extension": ["ts"],
|
||||||
"spec": "test/**/*.test.ts",
|
"spec": "src/**/*.spec.ts"
|
||||||
"require": "ts-node/register"
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
node_modules
|
node_modules
|
||||||
src
|
src
|
||||||
|
dist/**/*.spec.*
|
|
@ -10,10 +10,10 @@
|
||||||
"build": "tsc --skipLibCheck",
|
"build": "tsc --skipLibCheck",
|
||||||
"build3": "rollup -c",
|
"build3": "rollup -c",
|
||||||
"build2": "vue-tsc --noEmit && vite build",
|
"build2": "vue-tsc --noEmit && vite build",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview",
|
||||||
|
"test": "mocha --loader=ts-node/esm"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/lodash-es": "^4.17.12",
|
|
||||||
"axios": "^1.7.2",
|
"axios": "^1.7.2",
|
||||||
"fix-path": "^4.0.0",
|
"fix-path": "^4.0.0",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
|
@ -22,6 +22,7 @@
|
||||||
"qs": "^6.11.2"
|
"qs": "^6.11.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@rollup/plugin-commonjs": "^23.0.4",
|
"@rollup/plugin-commonjs": "^23.0.4",
|
||||||
"@rollup/plugin-json": "^6.0.0",
|
"@rollup/plugin-json": "^6.0.0",
|
||||||
"@rollup/plugin-node-resolve": "^15.0.1",
|
"@rollup/plugin-node-resolve": "^15.0.1",
|
||||||
|
|
|
@ -3,3 +3,4 @@ export * from "./run-history.js";
|
||||||
export * from "./context.js";
|
export * from "./context.js";
|
||||||
export * from "./storage.js";
|
export * from "./storage.js";
|
||||||
export * from "./file-store.js";
|
export * from "./file-store.js";
|
||||||
|
export * from "./license.js";
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { isPlus, verify } from "./license.js";
|
||||||
|
import { equal } from "assert";
|
||||||
|
describe("license", function () {
|
||||||
|
it("#license", async function () {
|
||||||
|
const req = {
|
||||||
|
appKey: "Certd",
|
||||||
|
subjectId: "dev_xiao_001",
|
||||||
|
license:
|
||||||
|
"65794a7a64574a715a574e30535751694f694a6b5a585a6665476c68623138774d4445694c434a686348424c5a586b694f694a485233527953314a58556d7475526d524a53555177636c63694c434a6b64584a6864476c76626949364d7a59314c434a6859335270646d56556157316c496a6f784e7a49794e5459794e7a49334f4455344c434a325a584a7a61573975496a6f784c434a6a6232526c496a6f69516e464d4d335a754e5670564e457830527a6c685557785754544d7764454532636c5a6b563251334e474a664d534973496d563463476c795a565270625755694f6a45334e5451774f5467334d6a63344e546773496e4e6c59334a6c6443493649694973496e4e705a323568644856795a534936496d3535637a564461557475556b74614d31426b5231524c4e6b6f76513342334c7a523052334e7263537443624867784f4552534d556c3256314e5752545534565746365744465a546b706164575a4d5455706863474a356347704c557a4a6b53576f7a546d45344e47645553553434646b5236544568504e5570744f467051576d316d4c335236566d4653595556694f4768494f45706a53307777547a424353573530596d3133616d78595454645352544e344f44497963464d796432646c536d6b34556c64344d6b7832546a68715230394762546c535330644e596c5678556b4e7355305a6f59306c59596b5249615538786156425655305a5053484a7a6333646f4d6e70425a564654576a4276566b74464c316331556d5a745253387a5446517a646b68734f573951656e687161314a79553068794e55466c646d784a4c7a5647526b5a71526b4d76626b356a5a454a705a485a68616e51726556425a5458464e5a33466a616c6c78566a4a6e597939586145744b5a46464d53587035645856614b7a56335554684f64464e6851545272616a464d526d55775a574e4352306c50625751335132464e645774445a3235555644464f5233525a5a6e4650646c706965555636647a3039496e303d",
|
||||||
|
};
|
||||||
|
const plus = isPlus();
|
||||||
|
equal(plus, false);
|
||||||
|
const res = await verify(req);
|
||||||
|
equal(res, true);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,90 @@
|
||||||
|
import { createVerify } from "node:crypto";
|
||||||
|
import { logger } from "../utils/index.js";
|
||||||
|
|
||||||
|
const SecreteKey =
|
||||||
|
"LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQkNnS0NBUUVBMjdoZDM0NjRYbyt3TkpmTTNCWjE5MXlQK2NLaTd3ck9CbXdjTWJPZUdsNlJOMUVtTGhyMgplOFdvOGpmMW9IVXc5RFV6L2I2ZHU3Q3ZXMXZNUDA1Q3dSS3lNd2U3Q1BYRGQ2U01mSkwxRFZyUkw5Ylh0cEYzCjJkQVA5UENrakFJcFMvRE5jVkhLRXk1QW8yMnFFenpTKzlUT0JVY2srREdZcmo4KzI5U3h2aEZDRE5ZbEE2d1EKbEkyRWc5TWNBV2xDU3p1S1JWa2ZWUWdYVlU3SmE5OXp1Um1oWWtYZjFxQzBLcVAwQkpDakdDNEV6ZHorMmwyaAo2T3RxVHVVLzRkemlYYnRMUS8vU0JqNEgxdi9PZ3dUZjJkSVBjUnRHOXlWVTB2ZlQzVzdUTkdlMjU3em5ESDBYCkd6Wm4zdWJxTXJuL084b2ltMHRrS3ZHZXZ1V2ZraWNwVVFJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg==";
|
||||||
|
|
||||||
|
export type LicenseVerifyReq = {
|
||||||
|
appKey: string;
|
||||||
|
subjectId: string;
|
||||||
|
license: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type License = {
|
||||||
|
appKey: string;
|
||||||
|
code: string;
|
||||||
|
subjectId: string;
|
||||||
|
expireTime: number;
|
||||||
|
activeTime: number;
|
||||||
|
duration: number;
|
||||||
|
version: number;
|
||||||
|
secret: string;
|
||||||
|
signature: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LicenseHolder {
|
||||||
|
isPlus = false;
|
||||||
|
}
|
||||||
|
const holder = new LicenseHolder();
|
||||||
|
holder.isPlus = false;
|
||||||
|
|
||||||
|
class LicenseVerifier {
|
||||||
|
checked = false;
|
||||||
|
licenseReq?: LicenseVerifyReq = undefined;
|
||||||
|
async reVerify(req: LicenseVerifyReq) {
|
||||||
|
this.checked = false;
|
||||||
|
//@ts-ignore
|
||||||
|
// globalThis._certd_license_.isPlus = false;
|
||||||
|
return await this.verify(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
setPlus(value: boolean) {
|
||||||
|
//@ts-ignore
|
||||||
|
holder.isPlus = value;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
async verify(req: LicenseVerifyReq) {
|
||||||
|
this.licenseReq = req;
|
||||||
|
if (this.checked) {
|
||||||
|
return this.setPlus(false);
|
||||||
|
}
|
||||||
|
const license = req?.license;
|
||||||
|
if (!license) {
|
||||||
|
this.checked = true;
|
||||||
|
return this.setPlus(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const licenseJson = Buffer.from(Buffer.from(license, "hex").toString(), "base64").toString();
|
||||||
|
const json: License = JSON.parse(licenseJson);
|
||||||
|
if (json.expireTime < Date.now()) {
|
||||||
|
logger.warn("授权已过期");
|
||||||
|
return this.setPlus(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const content = `${this.licenseReq.appKey},${this.licenseReq.subjectId},${json.code},${json.secret}${json.activeTime},${json.duration},${json.expireTime},${json.version}`;
|
||||||
|
const publicKey = Buffer.from(SecreteKey, "base64").toString();
|
||||||
|
const res = this.verifySignature(content, json.signature, publicKey);
|
||||||
|
this.checked = true;
|
||||||
|
if (!res) {
|
||||||
|
logger.warn("授权校验失败");
|
||||||
|
return this.setPlus(false);
|
||||||
|
}
|
||||||
|
return this.setPlus(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
verifySignature(content: string, signature: any, publicKey: string) {
|
||||||
|
const verify = createVerify("RSA-SHA1");
|
||||||
|
verify.update(content);
|
||||||
|
return verify.verify(publicKey, signature, "base64");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const verifier = new LicenseVerifier();
|
||||||
|
|
||||||
|
export function isPlus() {
|
||||||
|
return holder.isPlus;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function verify(req: LicenseVerifyReq) {
|
||||||
|
return await verifier.reVerify(req);
|
||||||
|
}
|
|
@ -5,4 +5,3 @@ export default function (timeout: number) {
|
||||||
}, timeout);
|
}, timeout);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
import "mocha";
|
import "mocha";
|
||||||
import { EchoPlugin } from "./echo-plugin";
|
import { EchoPlugin } from "./echo-plugin.js";
|
||||||
describe("task_plugin", function () {
|
describe("task_plugin", function () {
|
||||||
it("#taskplugin", function () {
|
it("#taskplugin", function () {
|
||||||
console.log("before new plugin");
|
console.log("before new plugin");
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
license.*
|
|
@ -34,6 +34,7 @@
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"*.js",
|
"*.js",
|
||||||
"*.ts",
|
"*.ts",
|
||||||
|
"*.spec.ts",
|
||||||
"dist",
|
"dist",
|
||||||
"node_modules",
|
"node_modules",
|
||||||
"test"
|
"test"
|
||||||
|
|
|
@ -3,7 +3,8 @@ import { logger } from '../../utils/logger.js';
|
||||||
import { UserService } from '../authority/service/user-service.js';
|
import { UserService } from '../authority/service/user-service.js';
|
||||||
import { SysSettingsService } from '../system/service/sys-settings-service.js';
|
import { SysSettingsService } from '../system/service/sys-settings-service.js';
|
||||||
import { nanoid } from 'nanoid';
|
import { nanoid } from 'nanoid';
|
||||||
import { SysInstallInfo } from '../system/service/models.js';
|
import { SysInstallInfo, SysLicenseInfo } from '../system/service/models.js';
|
||||||
|
import { verify } from '@certd/pipeline';
|
||||||
|
|
||||||
export type InstallInfo = {
|
export type InstallInfo = {
|
||||||
installTime: number;
|
installTime: number;
|
||||||
|
@ -32,6 +33,10 @@ export class AutoInitSite {
|
||||||
await this.sysSettingsService.saveSetting(installInfo);
|
await this.sysSettingsService.saveSetting(installInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 授权许可
|
||||||
|
const licenseInfo: SysLicenseInfo = await this.sysSettingsService.getSetting(SysLicenseInfo);
|
||||||
|
await verify(licenseInfo.license);
|
||||||
|
|
||||||
logger.info('初始化站点完成');
|
logger.info('初始化站点完成');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,3 +27,10 @@ export class SysInstallInfo extends BaseSettings {
|
||||||
installTime: number;
|
installTime: number;
|
||||||
siteId?: string;
|
siteId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class SysLicenseInfo extends BaseSettings {
|
||||||
|
static __title__ = '授权许可信息';
|
||||||
|
static __key__ = 'sys.license';
|
||||||
|
static __access__ = 'private';
|
||||||
|
license: string;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue