From 70ce6be0bf3df5bc09b06b3f78c7b40c7682b3af Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Fri, 2 Aug 2024 22:58:29 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/core/pipeline/.gitignore | 1 + packages/core/pipeline/.mocharc.json | 5 +- packages/core/pipeline/.npmignore | 3 +- packages/core/pipeline/package.json | 5 +- packages/core/pipeline/src/core/index.ts | 1 + .../core/pipeline/src/core/license.spec.ts | 16 ++++ packages/core/pipeline/src/core/license.ts | 90 +++++++++++++++++++ .../core/pipeline/src/utils/util.sleep.ts | 1 - packages/core/pipeline/test/index.test.ts | 2 +- .../core/pipeline/test/pipeline/.gitignore | 1 + packages/core/pipeline/tsconfig.json | 1 + .../src/modules/auto/auto-init-site.ts | 7 +- .../src/modules/system/service/models.ts | 7 ++ 13 files changed, 131 insertions(+), 9 deletions(-) create mode 100644 packages/core/pipeline/src/core/license.spec.ts create mode 100644 packages/core/pipeline/src/core/license.ts create mode 100644 packages/core/pipeline/test/pipeline/.gitignore diff --git a/packages/core/pipeline/.gitignore b/packages/core/pipeline/.gitignore index 0e868052..92686f43 100644 --- a/packages/core/pipeline/.gitignore +++ b/packages/core/pipeline/.gitignore @@ -24,3 +24,4 @@ dist-ssr *.sw? test/user.secret.* +test/**/*.js \ No newline at end of file diff --git a/packages/core/pipeline/.mocharc.json b/packages/core/pipeline/.mocharc.json index 24b75f3e..b0018e9d 100644 --- a/packages/core/pipeline/.mocharc.json +++ b/packages/core/pipeline/.mocharc.json @@ -1,5 +1,4 @@ { "extension": ["ts"], - "spec": "test/**/*.test.ts", - "require": "ts-node/register" -} \ No newline at end of file + "spec": "src/**/*.spec.ts" +} diff --git a/packages/core/pipeline/.npmignore b/packages/core/pipeline/.npmignore index bf40d278..739a0043 100644 --- a/packages/core/pipeline/.npmignore +++ b/packages/core/pipeline/.npmignore @@ -1,2 +1,3 @@ node_modules -src \ No newline at end of file +src +dist/**/*.spec.* \ No newline at end of file diff --git a/packages/core/pipeline/package.json b/packages/core/pipeline/package.json index e7d1807a..d9492454 100644 --- a/packages/core/pipeline/package.json +++ b/packages/core/pipeline/package.json @@ -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", diff --git a/packages/core/pipeline/src/core/index.ts b/packages/core/pipeline/src/core/index.ts index 25ff426d..ea038be6 100644 --- a/packages/core/pipeline/src/core/index.ts +++ b/packages/core/pipeline/src/core/index.ts @@ -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"; diff --git a/packages/core/pipeline/src/core/license.spec.ts b/packages/core/pipeline/src/core/license.spec.ts new file mode 100644 index 00000000..81b50b92 --- /dev/null +++ b/packages/core/pipeline/src/core/license.spec.ts @@ -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); + }); +}); diff --git a/packages/core/pipeline/src/core/license.ts b/packages/core/pipeline/src/core/license.ts new file mode 100644 index 00000000..ac4ce632 --- /dev/null +++ b/packages/core/pipeline/src/core/license.ts @@ -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); +} diff --git a/packages/core/pipeline/src/utils/util.sleep.ts b/packages/core/pipeline/src/utils/util.sleep.ts index 496e2d2e..5dcca1d8 100644 --- a/packages/core/pipeline/src/utils/util.sleep.ts +++ b/packages/core/pipeline/src/utils/util.sleep.ts @@ -5,4 +5,3 @@ export default function (timeout: number) { }, timeout); }); } - diff --git a/packages/core/pipeline/test/index.test.ts b/packages/core/pipeline/test/index.test.ts index 42e26dc3..b90d0d42 100644 --- a/packages/core/pipeline/test/index.test.ts +++ b/packages/core/pipeline/test/index.test.ts @@ -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"); diff --git a/packages/core/pipeline/test/pipeline/.gitignore b/packages/core/pipeline/test/pipeline/.gitignore new file mode 100644 index 00000000..705b4c1a --- /dev/null +++ b/packages/core/pipeline/test/pipeline/.gitignore @@ -0,0 +1 @@ +license.* \ No newline at end of file diff --git a/packages/core/pipeline/tsconfig.json b/packages/core/pipeline/tsconfig.json index 3944e11f..42bad159 100644 --- a/packages/core/pipeline/tsconfig.json +++ b/packages/core/pipeline/tsconfig.json @@ -34,6 +34,7 @@ "exclude": [ "*.js", "*.ts", + "*.spec.ts", "dist", "node_modules", "test" diff --git a/packages/ui/certd-server/src/modules/auto/auto-init-site.ts b/packages/ui/certd-server/src/modules/auto/auto-init-site.ts index cbd6707b..8f986996 100644 --- a/packages/ui/certd-server/src/modules/auto/auto-init-site.ts +++ b/packages/ui/certd-server/src/modules/auto/auto-init-site.ts @@ -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('初始化站点完成'); } } diff --git a/packages/ui/certd-server/src/modules/system/service/models.ts b/packages/ui/certd-server/src/modules/system/service/models.ts index b7cdde07..ee6b16e5 100644 --- a/packages/ui/certd-server/src/modules/system/service/models.ts +++ b/packages/ui/certd-server/src/modules/system/service/models.ts @@ -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; +}