chore: 单元测试

pull/148/head
xiaojunnuo 2024-08-02 22:58:29 +08:00
parent 9187e87419
commit 70ce6be0bf
13 changed files with 131 additions and 9 deletions

View File

@ -24,3 +24,4 @@ dist-ssr
*.sw?
test/user.secret.*
test/**/*.js

View File

@ -1,5 +1,4 @@
{
"extension": ["ts"],
"spec": "test/**/*.test.ts",
"require": "ts-node/register"
}
"spec": "src/**/*.spec.ts"
}

View File

@ -1,2 +1,3 @@
node_modules
src
src
dist/**/*.spec.*

View File

@ -10,10 +10,10 @@
"build": "tsc --skipLibCheck",
"build3": "rollup -c",
"build2": "vue-tsc --noEmit && vite build",
"preview": "vite preview"
"preview": "vite preview",
"test": "mocha --loader=ts-node/esm"
},
"dependencies": {
"@types/lodash-es": "^4.17.12",
"axios": "^1.7.2",
"fix-path": "^4.0.0",
"lodash-es": "^4.17.21",
@ -22,6 +22,7 @@
"qs": "^6.11.2"
},
"devDependencies": {
"@types/lodash-es": "^4.17.12",
"@rollup/plugin-commonjs": "^23.0.4",
"@rollup/plugin-json": "^6.0.0",
"@rollup/plugin-node-resolve": "^15.0.1",

View File

@ -3,3 +3,4 @@ export * from "./run-history.js";
export * from "./context.js";
export * from "./storage.js";
export * from "./file-store.js";
export * from "./license.js";

View File

@ -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);
});
});

View File

@ -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);
}

View File

@ -5,4 +5,3 @@ export default function (timeout: number) {
}, timeout);
});
}

View File

@ -1,6 +1,6 @@
import { expect } from "chai";
import "mocha";
import { EchoPlugin } from "./echo-plugin";
import { EchoPlugin } from "./echo-plugin.js";
describe("task_plugin", function () {
it("#taskplugin", function () {
console.log("before new plugin");

View File

@ -0,0 +1 @@
license.*

View File

@ -34,6 +34,7 @@
"exclude": [
"*.js",
"*.ts",
"*.spec.ts",
"dist",
"node_modules",
"test"

View File

@ -3,7 +3,8 @@ import { logger } from '../../utils/logger.js';
import { UserService } from '../authority/service/user-service.js';
import { SysSettingsService } from '../system/service/sys-settings-service.js';
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 = {
installTime: number;
@ -32,6 +33,10 @@ export class AutoInitSite {
await this.sysSettingsService.saveSetting(installInfo);
}
// 授权许可
const licenseInfo: SysLicenseInfo = await this.sysSettingsService.getSetting(SysLicenseInfo);
await verify(licenseInfo.license);
logger.info('初始化站点完成');
}
}

View File

@ -27,3 +27,10 @@ export class SysInstallInfo extends BaseSettings {
installTime: number;
siteId?: string;
}
export class SysLicenseInfo extends BaseSettings {
static __title__ = '授权许可信息';
static __key__ = 'sys.license';
static __access__ = 'private';
license: string;
}