mirror of
https://github.com/certd/certd.git
synced 2026-04-03 22:20:51 +08:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6ea5f04bae | ||
|
|
d3a1626776 | ||
|
|
4264d38843 | ||
|
|
8851870400 | ||
|
|
94fca0b554 | ||
|
|
43b8a0ac94 | ||
|
|
e96a83a528 | ||
|
|
fbddd7ead8 | ||
|
|
762a2058d3 | ||
|
|
2bc0a4bd14 | ||
|
|
e052e304bd | ||
|
|
50c56d134e | ||
|
|
4caa2fad9d | ||
|
|
07043aff0c | ||
|
|
e8b617b80c | ||
|
|
417971d15d | ||
|
|
ccfe72a0d9 | ||
|
|
6f8fe62087 | ||
|
|
5601bc4ab2 | ||
|
|
67ba17286c | ||
|
|
a10b8aa042 | ||
|
|
273ab6139f | ||
|
|
9b68009eb3 | ||
|
|
aec2448406 |
14
CHANGELOG.md
14
CHANGELOG.md
@@ -3,6 +3,20 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.26.5](https://github.com/certd/certd/compare/v1.26.4...v1.26.5) (2024-10-14)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复版本号获取错误的bug ([8851870](https://github.com/certd/certd/commit/8851870400df86e496198ad509061b8989fcc44f))
|
||||
|
||||
## [1.26.4](https://github.com/certd/certd/compare/v1.26.3...v1.26.4) (2024-10-14)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* [comm] 支持插件管理 ([e8b617b](https://github.com/certd/certd/commit/e8b617b80ce882dd63006f0cfc719a80a1cc6acc))
|
||||
* 新增代理设置功能 ([273ab61](https://github.com/certd/certd/commit/273ab6139f5807f4d7fe865cc353b97f51b9a668))
|
||||
* EAB授权支持绑定邮箱,支持公共EAB设置 ([07043af](https://github.com/certd/certd/commit/07043aff0ca7fd29c56dd3c363002cb15d78b464))
|
||||
|
||||
## [1.26.3](https://github.com/certd/certd/compare/v1.26.2...v1.26.3) (2024-10-12)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
@@ -9,11 +9,11 @@ Certd 是一个免费全自动申请和自动部署更新SSL证书的工具。
|
||||
## 一、特性
|
||||
本项目不仅支持证书申请过程自动化,还可以自动化部署更新证书,让你的证书永不过期。
|
||||
|
||||
* 全自动申请证书(支持阿里云、腾讯云、华为云、Cloudflare等各种途径注册的域名)
|
||||
* 全自动部署更新证书(目前支持部署到主机、部署到阿里云、腾讯云等)
|
||||
* 全自动申请证书(支持所有注册商注册的域名)
|
||||
* 全自动部署更新证书(目前支持部署到主机、部署到阿里云、腾讯云等,目前已支持30+部署插件)
|
||||
* 支持通配符域名/泛域名,支持多个域名打到一个证书上
|
||||
* 邮件通知
|
||||
* 私有化部署,保障安全
|
||||
* 私有化部署,保障数据安全
|
||||
* 免费、免费、免费([阿里云单个通配符域名证书最便宜也要1800/年](https://yundun.console.aliyun.com/?p=cas#/certExtend/buy/cn-hangzhou))
|
||||
|
||||
|
||||
@@ -124,6 +124,7 @@ git clone https://github.com/certd/certd
|
||||
cd certd
|
||||
# 启动服务
|
||||
./start.sh
|
||||
# 数据默认保存在 ./packages/ui/certd-server/data 目录下,注意数据备份
|
||||
```
|
||||
如果是windows,请先安装`git for windows` ,然后右键,选择`open git bash here`打开终端,再执行`./start.sh`命令
|
||||
|
||||
@@ -169,6 +170,7 @@ docker compose up -d
|
||||
* [google证书](./doc/google/google.md)
|
||||
* [群晖部署certd及证书更新教程](./doc/synology/index.md)
|
||||
|
||||
* [CNAME证书校验方式说明](./doc/cname/index.md)
|
||||
|
||||
## 八、问题处理
|
||||
### 7.1 忘记管理员密码
|
||||
|
||||
@@ -1 +1 @@
|
||||
13:39
|
||||
1
|
||||
|
||||
BIN
doc/cname/images/cname1.png
Normal file
BIN
doc/cname/images/cname1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 172 KiB |
BIN
doc/cname/images/cname2.png
Normal file
BIN
doc/cname/images/cname2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 71 KiB |
BIN
doc/cname/images/cname3.png
Normal file
BIN
doc/cname/images/cname3.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 200 KiB |
BIN
doc/cname/images/cname4.png
Normal file
BIN
doc/cname/images/cname4.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
27
doc/cname/index.md
Normal file
27
doc/cname/index.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# CNAME代理校验方式说明
|
||||
|
||||
## 1. 前言
|
||||
申请域名证书是需要校验域名所有权的。
|
||||
目前有两种校验方式:
|
||||
1. http-01: 在网站根目录下放置一份txt文件(Certd不支持)
|
||||
2. dns-01: 需要给域名添加txt解析记录,通配符域名只能用这种方式(Certd采用这种方式)
|
||||
|
||||
DNS-01方式需要开发适配DNS服务商的接口,目前已实现主流域名注册商的接口(阿里云、腾讯云、华为云、Cloudflare、西数)
|
||||
|
||||
如果域名不在这几家,那么就只能通过CNAME代理校验方式来实现
|
||||
|
||||
|
||||
## 2. 使用步骤
|
||||
|
||||
1. 假设你要申请证书的域名叫:need.cert.com ,它是在其他服务商注册的
|
||||
2. 现在你需要另外一个域名:cname.foo.com,这个域名属于是在阿里云、腾讯云、华为云、Cloudflare、西数,或者你把这个域名的DNS服务器转到这几家。
|
||||
3. 到Certd的 CNAME服务管理界面,用`cname.foo.com`创建一条默认的CNAME服务,需要提供DNS提供商授权。
|
||||

|
||||
4. 申请证书时,Certd会生成一个随机的CNAME记录,例如:`_acme-challenge.need`->`xxxxxx.cname.foo.com`
|
||||

|
||||
5. 您需要手动添加这条CNAME记录到你要申请证书的域名解析中,点击校验,校验成功后就可以开始申请证书了 (此操作每个域名只需要做一次,后续可以重复使用,注意不要删除添加的CNAME记录)
|
||||

|
||||
6. 
|
||||
6. 申请过程中,Certd会在`xxxxxx.cname.foo.com`下自动添加验证TXT记录。
|
||||
7. 由于您配置了`_acme-challenge.need`的CNAME,所以这个TXT记录会被解析到`_acme-challenge.need.cert.com`下,从而完成域名校验。
|
||||
|
||||
@@ -9,5 +9,5 @@
|
||||
}
|
||||
},
|
||||
"npmClient": "pnpm",
|
||||
"version": "1.26.3"
|
||||
"version": "1.26.5"
|
||||
}
|
||||
|
||||
@@ -14,11 +14,12 @@
|
||||
"i-all": "lerna link && lerna exec npm install ",
|
||||
"publish": "npm run prepublishOnly2 && lerna publish --force-publish=pro/plus-core --conventional-commits --create-release github && npm run afterpublishOnly && npm run commitAll",
|
||||
"afterpublishOnly": "time /t >build.trigger && git add ./build.trigger && git commit -m \"build: trigger build image\" && TIMEOUT /T 10 && git push",
|
||||
"transform-sql":"cd ./packages/ui/certd-server/db/ && node --experimental-json-modules transform.js",
|
||||
"commitAll": "git add . && git commit -m \"build: publish\" && git push && npm run commitPro",
|
||||
"commitPro": "cd ./packages/core/ && git add . && git commit -m \"build: publish\" && git push",
|
||||
"prepublishOnly1": "npm run check && lerna run build ",
|
||||
"prepublishOnly2": "npm run check && npm run before-build && lerna run build ",
|
||||
"before-build": "cd ./packages/core/basic && time /t >build.md && git add ./build.md && git commit -m \"build: prepare to build\"",
|
||||
"before-build": "npm run transform-sql && cd ./packages/core/basic && time /t >build.md && git add ./build.md && git commit -m \"build: prepare to build\"",
|
||||
"deploy1": "node --experimental-json-modules deploy.js ",
|
||||
"check": "node --experimental-json-modules publish-check.js",
|
||||
"init": "lerna run build"
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.26.5](https://github.com/publishlab/node-acme-client/compare/v1.26.4...v1.26.5) (2024-10-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/acme-client
|
||||
|
||||
## [1.26.4](https://github.com/publishlab/node-acme-client/compare/v1.26.3...v1.26.4) (2024-10-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/acme-client
|
||||
|
||||
## [1.26.3](https://github.com/publishlab/node-acme-client/compare/v1.26.2...v1.26.3) (2024-10-12)
|
||||
|
||||
**Note:** Version bump only for package @certd/acme-client
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"description": "Simple and unopinionated ACME client",
|
||||
"private": false,
|
||||
"author": "nmorsman",
|
||||
"version": "1.26.3",
|
||||
"version": "1.26.5",
|
||||
"main": "src/index.js",
|
||||
"types": "types/index.d.ts",
|
||||
"license": "MIT",
|
||||
@@ -59,5 +59,5 @@
|
||||
"bugs": {
|
||||
"url": "https://github.com/publishlab/node-acme-client/issues"
|
||||
},
|
||||
"gitHead": "66f9b08fcf5035577eafc609fd634d6490bc9cae"
|
||||
"gitHead": "e96a83a528d6b850bca12d1636690d2ec654ed57"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,16 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.26.5](https://github.com/certd/certd/compare/v1.26.4...v1.26.5) (2024-10-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/basic
|
||||
|
||||
## [1.26.4](https://github.com/certd/certd/compare/v1.26.3...v1.26.4) (2024-10-14)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 新增代理设置功能 ([273ab61](https://github.com/certd/certd/commit/273ab6139f5807f4d7fe865cc353b97f51b9a668))
|
||||
|
||||
## [1.26.3](https://github.com/certd/certd/compare/v1.26.2...v1.26.3) (2024-10-12)
|
||||
|
||||
**Note:** Version bump only for package @certd/basic
|
||||
|
||||
@@ -1 +1 @@
|
||||
15:04
|
||||
13:48
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/basic",
|
||||
"private": false,
|
||||
"version": "1.26.3",
|
||||
"version": "1.26.5",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
@@ -64,5 +64,5 @@
|
||||
"vite": "^4.3.8",
|
||||
"vue-tsc": "^1.6.5"
|
||||
},
|
||||
"gitHead": "66f9b08fcf5035577eafc609fd634d6490bc9cae"
|
||||
"gitHead": "e96a83a528d6b850bca12d1636690d2ec654ed57"
|
||||
}
|
||||
|
||||
@@ -47,6 +47,21 @@ export class HttpError extends Error {
|
||||
}
|
||||
|
||||
export const HttpCommonError = HttpError;
|
||||
|
||||
let defaultAgents = createAgent();
|
||||
|
||||
export function setGlobalProxy(opts: { httpProxy?: string; httpsProxy?: string }) {
|
||||
logger.info('setGlobalProxy:', opts);
|
||||
if (opts.httpProxy) {
|
||||
process.env.HTTP_PROXY = opts.httpProxy;
|
||||
}
|
||||
if (opts.httpsProxy) {
|
||||
process.env.HTTPS_PROXY = opts.httpsProxy;
|
||||
}
|
||||
|
||||
defaultAgents = createAgent();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 创建请求实例
|
||||
*/
|
||||
@@ -54,7 +69,6 @@ export function createAxiosService({ logger }: { logger: Logger }) {
|
||||
// 创建一个 axios 实例
|
||||
const service = axios.create();
|
||||
|
||||
const defaultAgents = createAgent();
|
||||
// 请求拦截
|
||||
service.interceptors.request.use(
|
||||
(config: any) => {
|
||||
|
||||
@@ -3,6 +3,17 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.26.5](https://github.com/certd/certd/compare/v1.26.4...v1.26.5) (2024-10-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/pipeline
|
||||
|
||||
## [1.26.4](https://github.com/certd/certd/compare/v1.26.3...v1.26.4) (2024-10-14)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* [comm] 支持插件管理 ([e8b617b](https://github.com/certd/certd/commit/e8b617b80ce882dd63006f0cfc719a80a1cc6acc))
|
||||
* EAB授权支持绑定邮箱,支持公共EAB设置 ([07043af](https://github.com/certd/certd/commit/07043aff0ca7fd29c56dd3c363002cb15d78b464))
|
||||
|
||||
## [1.26.3](https://github.com/certd/certd/compare/v1.26.2...v1.26.3) (2024-10-12)
|
||||
|
||||
**Note:** Version bump only for package @certd/pipeline
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/pipeline",
|
||||
"private": false,
|
||||
"version": "1.26.3",
|
||||
"version": "1.26.5",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -15,8 +15,8 @@
|
||||
"test": "mocha --loader=ts-node/esm"
|
||||
},
|
||||
"dependencies": {
|
||||
"@certd/basic": "^1.26.3",
|
||||
"@certd/plus-core": "^1.26.3",
|
||||
"@certd/basic": "^1.26.5",
|
||||
"@certd/plus-core": "^1.26.5",
|
||||
"axios": "^1.7.2",
|
||||
"dayjs": "^1.11.7",
|
||||
"fix-path": "^4.0.0",
|
||||
@@ -66,5 +66,5 @@
|
||||
"vite": "^4.3.8",
|
||||
"vue-tsc": "^1.6.5"
|
||||
},
|
||||
"gitHead": "66f9b08fcf5035577eafc609fd634d6490bc9cae"
|
||||
"gitHead": "e96a83a528d6b850bca12d1636690d2ec654ed57"
|
||||
}
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
import { ConcurrencyStrategy, NotificationWhen, Pipeline, ResultType, Runnable, RunStrategy, Stage, Step, Task } from "../dt/index.js";
|
||||
import _ from "lodash-es";
|
||||
import { RunHistory, RunnableCollection } from "./run-history.js";
|
||||
import { AbstractTaskPlugin, PluginDefine, pluginRegistry, TaskInstanceContext, UserInfo } from "../plugin/index.js";
|
||||
import { ContextFactory, IContext } from "./context.js";
|
||||
import { IStorage } from "./storage.js";
|
||||
import { logger } from "../utils/index.js";
|
||||
import { createAxiosService, hashUtils, logger, utils } from "../utils/index.js";
|
||||
import { Logger } from "log4js";
|
||||
import { createAxiosService } from "../utils/index.js";
|
||||
import { IAccessService } from "../access/index.js";
|
||||
import { RegistryItem } from "../registry/index.js";
|
||||
import { Decorator } from "../decorator/index.js";
|
||||
import { ICnameProxyService, IEmailService } from "../service/index.js";
|
||||
import { ICnameProxyService, IEmailService, IPluginConfigService } from "../service/index.js";
|
||||
import { FileStore } from "./file-store.js";
|
||||
import { hashUtils, utils } from "../utils/index.js";
|
||||
import { cloneDeep, forEach, merge } from "lodash-es";
|
||||
|
||||
export type ExecutorOptions = {
|
||||
pipeline: Pipeline;
|
||||
@@ -21,6 +19,7 @@ export type ExecutorOptions = {
|
||||
accessService: IAccessService;
|
||||
emailService: IEmailService;
|
||||
cnameProxyService: ICnameProxyService;
|
||||
pluginConfigService: IPluginConfigService;
|
||||
fileRootDir?: string;
|
||||
user: UserInfo;
|
||||
};
|
||||
@@ -42,7 +41,7 @@ export class Executor {
|
||||
onChanged: (history: RunHistory) => Promise<void>;
|
||||
constructor(options: ExecutorOptions) {
|
||||
this.options = options;
|
||||
this.pipeline = _.cloneDeep(options.pipeline);
|
||||
this.pipeline = cloneDeep(options.pipeline);
|
||||
this.onChanged = async (history: RunHistory) => {
|
||||
await options.onChanged(history);
|
||||
};
|
||||
@@ -218,8 +217,10 @@ export class Executor {
|
||||
const instance: ITaskPlugin = new plugin.target();
|
||||
// @ts-ignore
|
||||
const define: PluginDefine = plugin.define;
|
||||
const pluginName = define.name;
|
||||
const pluginConfig = await this.options.pluginConfigService.getPluginConfig(pluginName);
|
||||
//从outputContext读取输入参数
|
||||
const input = _.cloneDeep(step.input);
|
||||
const input = cloneDeep(step.input);
|
||||
Decorator.inject(define.input, instance, input, (item, key) => {
|
||||
if (item.component?.name === "output-selector") {
|
||||
const contextKey = input[key];
|
||||
@@ -239,6 +240,12 @@ export class Executor {
|
||||
}
|
||||
});
|
||||
|
||||
const sysInput = pluginConfig.sysSetting?.input || {};
|
||||
//注入系统设置参数
|
||||
for (const sysInputKey in sysInput) {
|
||||
input[sysInputKey] = sysInput[sysInputKey];
|
||||
}
|
||||
|
||||
const newInputHash = hashUtils.md5(JSON.stringify(input));
|
||||
step.status!.inputHash = newInputHash;
|
||||
//判断是否需要跳过
|
||||
@@ -269,6 +276,7 @@ export class Executor {
|
||||
accessService: this.options.accessService,
|
||||
emailService: this.options.emailService,
|
||||
cnameProxyService: this.options.cnameProxyService,
|
||||
pluginConfigService: this.options.pluginConfigService,
|
||||
pipelineContext: this.pipelineContext,
|
||||
userContext: this.contextFactory.getContext("user", this.options.user.id),
|
||||
fileStore: new FileStore({
|
||||
@@ -290,7 +298,7 @@ export class Executor {
|
||||
this.lastStatusMap.clear();
|
||||
}
|
||||
//输出上下文变量到output context
|
||||
_.forEach(define.output, (item: any, key: any) => {
|
||||
forEach(define.output, (item: any, key: any) => {
|
||||
step.status!.output[key] = instance[key];
|
||||
// const stepOutputKey = `step.${step.id}.${key}`;
|
||||
// this.runtime.context[stepOutputKey] = instance[key];
|
||||
@@ -300,7 +308,7 @@ export class Executor {
|
||||
if (Object.keys(instance._result.pipelineVars).length > 0) {
|
||||
// 判断 pipelineVars 有值时更新
|
||||
const vars = this.pipelineContext.getObj("vars");
|
||||
_.merge(vars, instance._result.pipelineVars);
|
||||
merge(vars, instance._result.pipelineVars);
|
||||
await this.pipelineContext.setObj("vars", vars);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,8 @@ import { IContext, PluginRequestHandleReq, RunnableCollection } from "../core/in
|
||||
import { ILogger, logger, utils } from "../utils/index.js";
|
||||
import { HttpClient } from "../utils/index.js";
|
||||
import dayjs from "dayjs";
|
||||
import _ from "lodash-es";
|
||||
import { IPluginConfigService } from "../service/config";
|
||||
import { upperFirst } from "lodash-es";
|
||||
export type UserInfo = {
|
||||
role: "admin" | "user";
|
||||
id: any;
|
||||
@@ -25,7 +26,10 @@ export type TaskOutputDefine = {
|
||||
type?: string;
|
||||
};
|
||||
|
||||
export type TaskInputDefine = FormItemProps;
|
||||
export type TaskInputDefine = {
|
||||
required?: boolean;
|
||||
isSys?: boolean;
|
||||
} & FormItemProps;
|
||||
|
||||
export type PluginDefine = Registrable & {
|
||||
default?: any;
|
||||
@@ -72,6 +76,8 @@ export type TaskInstanceContext = {
|
||||
emailService: IEmailService;
|
||||
//cname记录服务
|
||||
cnameProxyService: ICnameProxyService;
|
||||
//插件配置服务
|
||||
pluginConfigService: IPluginConfigService;
|
||||
//流水线上下文
|
||||
pipelineContext: IContext;
|
||||
//用户上下文
|
||||
@@ -169,7 +175,7 @@ export abstract class AbstractTaskPlugin implements ITaskPlugin {
|
||||
|
||||
let methodName = req.action;
|
||||
if (!req.action.startsWith("on")) {
|
||||
methodName = `on${_.upperFirst(req.action)}`;
|
||||
methodName = `on${upperFirst(req.action)}`;
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import _ from "lodash-es";
|
||||
import { pluginRegistry } from "./registry.js";
|
||||
import { PluginDefine, TaskInputDefine, TaskOutputDefine } from "./api.js";
|
||||
import { Decorator } from "../decorator/index.js";
|
||||
import { AUTOWIRE_KEY } from "../decorator/index.js";
|
||||
import "reflect-metadata";
|
||||
import { merge, sortBy } from "lodash-es";
|
||||
// 提供一个唯一 key
|
||||
export const PLUGIN_CLASS_KEY = "pipeline:plugin";
|
||||
|
||||
@@ -42,13 +42,13 @@ export function IsTaskPlugin(define: PluginDefine): ClassDecorator {
|
||||
}
|
||||
inputArray.push([key, _input]);
|
||||
}
|
||||
inputArray = _.sortBy(inputArray, (item: any) => item[1].order);
|
||||
inputArray = sortBy(inputArray, (item: any) => item[1].order);
|
||||
const inputMap: any = {};
|
||||
inputArray.forEach((item: any) => {
|
||||
inputMap[item[0]] = item[1];
|
||||
});
|
||||
|
||||
_.merge(define, { input: inputMap, autowire: autowires, output: outputs });
|
||||
merge(define, { input: inputMap, autowire: autowires, output: outputs });
|
||||
|
||||
Reflect.defineMetadata(PLUGIN_CLASS_KEY, define, target);
|
||||
|
||||
|
||||
12
packages/core/pipeline/src/service/config.ts
Normal file
12
packages/core/pipeline/src/service/config.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
export type PluginConfig = {
|
||||
name: string;
|
||||
disabled: boolean;
|
||||
sysSetting: {
|
||||
input: Record<string, any>;
|
||||
};
|
||||
};
|
||||
|
||||
//插件配置服务
|
||||
export type IPluginConfigService = {
|
||||
getPluginConfig: (pluginName: string) => Promise<PluginConfig>;
|
||||
};
|
||||
@@ -1,2 +1,3 @@
|
||||
export * from "./email.js";
|
||||
export * from "./cname.js";
|
||||
export * from "./config.js";
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.26.5](https://github.com/certd/certd/compare/v1.26.4...v1.26.5) (2024-10-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-huawei
|
||||
|
||||
## [1.26.4](https://github.com/certd/certd/compare/v1.26.3...v1.26.4) (2024-10-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-huawei
|
||||
|
||||
## [1.26.3](https://github.com/certd/certd/compare/v1.26.2...v1.26.3) (2024-10-12)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-huawei
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/lib-huawei",
|
||||
"private": false,
|
||||
"version": "1.26.3",
|
||||
"version": "1.26.5",
|
||||
"main": "./dist/bundle.js",
|
||||
"module": "./dist/bundle.js",
|
||||
"types": "./dist/d/index.d.ts",
|
||||
@@ -17,5 +17,5 @@
|
||||
"rimraf": "^5.0.5",
|
||||
"rollup": "^3.7.4"
|
||||
},
|
||||
"gitHead": "66f9b08fcf5035577eafc609fd634d6490bc9cae"
|
||||
"gitHead": "e96a83a528d6b850bca12d1636690d2ec654ed57"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.26.5](https://github.com/certd/certd/compare/v1.26.4...v1.26.5) (2024-10-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-iframe
|
||||
|
||||
## [1.26.4](https://github.com/certd/certd/compare/v1.26.3...v1.26.4) (2024-10-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-iframe
|
||||
|
||||
## [1.26.3](https://github.com/certd/certd/compare/v1.26.2...v1.26.3) (2024-10-12)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-iframe
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/lib-iframe",
|
||||
"private": false,
|
||||
"version": "1.26.3",
|
||||
"version": "1.26.5",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -39,5 +39,5 @@
|
||||
"tslib": "^2.5.2",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "66f9b08fcf5035577eafc609fd634d6490bc9cae"
|
||||
"gitHead": "e96a83a528d6b850bca12d1636690d2ec654ed57"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.26.5](https://github.com/certd/certd/compare/v1.26.4...v1.26.5) (2024-10-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-jdcloud
|
||||
|
||||
## [1.26.4](https://github.com/certd/certd/compare/v1.26.3...v1.26.4) (2024-10-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-jdcloud
|
||||
|
||||
## [1.26.3](https://github.com/certd/certd/compare/v1.26.2...v1.26.3) (2024-10-12)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-jdcloud
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/lib-jdcloud",
|
||||
"private": false,
|
||||
"version": "1.26.3",
|
||||
"version": "1.26.5",
|
||||
"main": "./dist/bundle.mjs",
|
||||
"module": "./dist/bundle.mjs",
|
||||
"types": "./dist/d/index.d.ts",
|
||||
@@ -27,5 +27,5 @@
|
||||
"rimraf": "^5.0.5",
|
||||
"rollup": "^3.7.4"
|
||||
},
|
||||
"gitHead": "66f9b08fcf5035577eafc609fd634d6490bc9cae"
|
||||
"gitHead": "e96a83a528d6b850bca12d1636690d2ec654ed57"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.26.5](https://github.com/certd/certd/compare/v1.26.4...v1.26.5) (2024-10-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-k8s
|
||||
|
||||
## [1.26.4](https://github.com/certd/certd/compare/v1.26.3...v1.26.4) (2024-10-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-k8s
|
||||
|
||||
## [1.26.3](https://github.com/certd/certd/compare/v1.26.2...v1.26.3) (2024-10-12)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-k8s
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/lib-k8s",
|
||||
"private": false,
|
||||
"version": "1.26.3",
|
||||
"version": "1.26.5",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -18,7 +18,7 @@
|
||||
"@kubernetes/client-node": "0.21.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@certd/pipeline": "^1.26.3",
|
||||
"@certd/pipeline": "^1.26.5",
|
||||
"@rollup/plugin-commonjs": "^23.0.4",
|
||||
"@rollup/plugin-json": "^6.0.0",
|
||||
"@rollup/plugin-node-resolve": "^15.0.1",
|
||||
@@ -40,5 +40,5 @@
|
||||
"tslib": "^2.5.2",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "66f9b08fcf5035577eafc609fd634d6490bc9cae"
|
||||
"gitHead": "e96a83a528d6b850bca12d1636690d2ec654ed57"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,18 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.26.5](https://github.com/certd/certd/compare/v1.26.4...v1.26.5) (2024-10-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-server
|
||||
|
||||
## [1.26.4](https://github.com/certd/certd/compare/v1.26.3...v1.26.4) (2024-10-14)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* [comm] 支持插件管理 ([e8b617b](https://github.com/certd/certd/commit/e8b617b80ce882dd63006f0cfc719a80a1cc6acc))
|
||||
* 新增代理设置功能 ([273ab61](https://github.com/certd/certd/commit/273ab6139f5807f4d7fe865cc353b97f51b9a668))
|
||||
* EAB授权支持绑定邮箱,支持公共EAB设置 ([07043af](https://github.com/certd/certd/commit/07043aff0ca7fd29c56dd3c363002cb15d78b464))
|
||||
|
||||
## [1.26.3](https://github.com/certd/certd/compare/v1.26.2...v1.26.3) (2024-10-12)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@certd/lib-server",
|
||||
"version": "1.26.3",
|
||||
"version": "1.26.5",
|
||||
"description": "midway with flyway, sql upgrade way ",
|
||||
"private": false,
|
||||
"type": "module",
|
||||
@@ -26,8 +26,8 @@
|
||||
],
|
||||
"license": "AGPL",
|
||||
"dependencies": {
|
||||
"@certd/basic": "^1.26.3",
|
||||
"@certd/pipeline": "^1.26.3",
|
||||
"@certd/basic": "^1.26.5",
|
||||
"@certd/pipeline": "^1.26.5",
|
||||
"@midwayjs/cache": "~3.14.0",
|
||||
"@midwayjs/core": "~3.17.1",
|
||||
"@midwayjs/i18n": "~3.17.3",
|
||||
@@ -68,5 +68,5 @@
|
||||
"typeorm": "^0.3.11",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "66f9b08fcf5035577eafc609fd634d6490bc9cae"
|
||||
"gitHead": "e96a83a528d6b850bca12d1636690d2ec654ed57"
|
||||
}
|
||||
|
||||
@@ -1,11 +1,24 @@
|
||||
import { ValidateException } from './exception/index.js';
|
||||
import * as _ from 'lodash-es';
|
||||
import { PermissionException } from './exception/index.js';
|
||||
import { In, Repository } from 'typeorm';
|
||||
import { In, Repository, SelectQueryBuilder } from 'typeorm';
|
||||
import { Inject } from '@midwayjs/core';
|
||||
import { TypeORMDataSourceManager } from '@midwayjs/typeorm';
|
||||
import { EntityManager } from 'typeorm/entity-manager/EntityManager.js';
|
||||
|
||||
export type PageReq<T = any> = {
|
||||
page?: { offset: number; limit: number };
|
||||
} & ListReq<T>;
|
||||
|
||||
export type ListReq<T = any> = {
|
||||
query?: Partial<T>;
|
||||
order?: {
|
||||
prop: string;
|
||||
asc: boolean;
|
||||
};
|
||||
buildQuery?: (bq: SelectQueryBuilder<any>) => void;
|
||||
};
|
||||
|
||||
/**
|
||||
* 服务基类
|
||||
*/
|
||||
@@ -106,50 +119,22 @@ export abstract class BaseService<T> {
|
||||
* 新增|修改|删除 之后的操作
|
||||
* @param data 对应数据
|
||||
*/
|
||||
async modifyAfter(data) {}
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
async modifyAfter(data: any) {}
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
* @param query 查询条件 bean
|
||||
* @param page
|
||||
* @param order
|
||||
* @param buildQuery
|
||||
*/
|
||||
async page(query, page = { offset: 0, limit: 20 }, order, buildQuery) {
|
||||
async page(pageReq: PageReq<T>) {
|
||||
const { page } = pageReq;
|
||||
if (page.offset == null) {
|
||||
page.offset = 0;
|
||||
}
|
||||
if (page.limit == null) {
|
||||
page.limit = 20;
|
||||
}
|
||||
const qb = this.getRepository().createQueryBuilder('main');
|
||||
if (order && order.prop) {
|
||||
qb.addOrderBy('main.' + order.prop, order.asc ? 'ASC' : 'DESC');
|
||||
}
|
||||
qb.addOrderBy('id', 'DESC');
|
||||
const qb = this.buildListQuery(pageReq);
|
||||
qb.offset(page.offset).limit(page.limit);
|
||||
//根据bean query
|
||||
if (query) {
|
||||
let whereSql = '';
|
||||
let index = 0;
|
||||
_.forEach(query, (value, key) => {
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
if (index !== 0) {
|
||||
whereSql += ' and ';
|
||||
}
|
||||
whereSql += ` main.${key} = :${key} `;
|
||||
index++;
|
||||
});
|
||||
if (index > 0) {
|
||||
qb.where(whereSql, query);
|
||||
}
|
||||
}
|
||||
//自定义query
|
||||
if (buildQuery) {
|
||||
buildQuery(qb);
|
||||
}
|
||||
const list = await qb.getMany();
|
||||
const total = await qb.getCount();
|
||||
return {
|
||||
@@ -160,19 +145,13 @@ export abstract class BaseService<T> {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
* @param query 查询条件 bean
|
||||
* @param order
|
||||
* @param buildQuery
|
||||
*/
|
||||
async list(query, order, buildQuery) {
|
||||
private buildListQuery(listReq: ListReq<T>) {
|
||||
const { query, order, buildQuery } = listReq;
|
||||
const qb = this.getRepository().createQueryBuilder('main');
|
||||
if (order && order.prop) {
|
||||
qb.orderBy('main.' + order.prop, order.asc ? 'ASC' : 'DESC');
|
||||
} else {
|
||||
qb.orderBy('id', 'DESC');
|
||||
qb.addOrderBy('main.' + order.prop, order.asc ? 'ASC' : 'DESC');
|
||||
}
|
||||
qb.addOrderBy('id', 'DESC');
|
||||
//根据bean query
|
||||
if (query) {
|
||||
let whereSql = '';
|
||||
@@ -188,13 +167,21 @@ export abstract class BaseService<T> {
|
||||
index++;
|
||||
});
|
||||
if (index > 0) {
|
||||
qb.where(whereSql, query);
|
||||
qb.andWhere(whereSql, query);
|
||||
}
|
||||
}
|
||||
//自定义query
|
||||
if (buildQuery) {
|
||||
buildQuery(qb);
|
||||
}
|
||||
return qb;
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*/
|
||||
async list(listReq: ListReq<T>) {
|
||||
const qb = this.buildListQuery(listReq);
|
||||
return await qb.getMany();
|
||||
}
|
||||
|
||||
|
||||
@@ -2,59 +2,50 @@ import { ALL, Body, Post, Query } from '@midwayjs/core';
|
||||
import { BaseController } from './base-controller.js';
|
||||
|
||||
export abstract class CrudController<T> extends BaseController {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
abstract getService<T>();
|
||||
|
||||
@Post('/page')
|
||||
async page(
|
||||
@Body(ALL)
|
||||
body
|
||||
) {
|
||||
const pageRet = await this.getService().page(body?.query, body?.page, body?.sort, null);
|
||||
async page(@Body(ALL) body: any) {
|
||||
const pageRet = await this.getService().page({
|
||||
query: body.query ?? {},
|
||||
page: body.page,
|
||||
sort: body.sort,
|
||||
bq: body.bq,
|
||||
});
|
||||
return this.ok(pageRet);
|
||||
}
|
||||
|
||||
@Post('/list')
|
||||
async list(
|
||||
@Body(ALL)
|
||||
body
|
||||
) {
|
||||
const listRet = await this.getService().list(body, null, null);
|
||||
async list(@Body(ALL) body: any) {
|
||||
const listRet = await this.getService().list({
|
||||
query: body.query ?? {},
|
||||
order: body.order,
|
||||
});
|
||||
return this.ok(listRet);
|
||||
}
|
||||
|
||||
@Post('/add')
|
||||
async add(
|
||||
@Body(ALL)
|
||||
bean
|
||||
) {
|
||||
async add(@Body(ALL) bean: any) {
|
||||
delete bean.id;
|
||||
const id = await this.getService().add(bean);
|
||||
return this.ok(id);
|
||||
}
|
||||
|
||||
@Post('/info')
|
||||
async info(
|
||||
@Query('id')
|
||||
id
|
||||
) {
|
||||
async info(@Query('id') id: number) {
|
||||
const bean = await this.getService().info(id);
|
||||
return this.ok(bean);
|
||||
}
|
||||
|
||||
@Post('/update')
|
||||
async update(
|
||||
@Body(ALL)
|
||||
bean
|
||||
) {
|
||||
async update(@Body(ALL) bean: any) {
|
||||
await this.getService().update(bean);
|
||||
return this.ok(null);
|
||||
}
|
||||
|
||||
@Post('/delete')
|
||||
async delete(
|
||||
@Query('id')
|
||||
id
|
||||
) {
|
||||
async delete(@Query('id') id: number) {
|
||||
await this.getService().delete([id]);
|
||||
return this.ok(null);
|
||||
}
|
||||
|
||||
@@ -24,13 +24,21 @@ export class SysPrivateSettings extends BaseSettings {
|
||||
static __key__ = 'sys.private';
|
||||
jwtKey?: string;
|
||||
encryptSecret?: string;
|
||||
|
||||
httpsProxy? = '';
|
||||
httpProxy? = '';
|
||||
|
||||
removeSecret() {
|
||||
delete this.jwtKey;
|
||||
delete this.encryptSecret;
|
||||
}
|
||||
}
|
||||
|
||||
export class SysInstallInfo extends BaseSettings {
|
||||
static __title__ = '系统安装信息';
|
||||
static __key__ = 'sys.install';
|
||||
static __access__ = 'private';
|
||||
installTime: number;
|
||||
installTime?: number;
|
||||
siteId?: string;
|
||||
bindUserId?: number;
|
||||
bindUrl?: string;
|
||||
|
||||
@@ -7,6 +7,7 @@ import { BaseSettings, SysPrivateSettings, SysPublicSettings } from './models.js
|
||||
import * as _ from 'lodash-es';
|
||||
import { BaseService } from '../../../basic/index.js';
|
||||
import { isComm } from '@certd/pipeline';
|
||||
import { setGlobalProxy } from '@certd/basic';
|
||||
|
||||
/**
|
||||
* 设置
|
||||
@@ -118,8 +119,25 @@ export class SysSettingsService extends BaseService<SysSettingsEntity> {
|
||||
await this.saveSetting(bean);
|
||||
}
|
||||
|
||||
async getPrivateSettings(): Promise<SysPrivateSettings> {
|
||||
return await this.getSetting(SysPrivateSettings);
|
||||
}
|
||||
|
||||
async savePrivateSettings(bean: SysPrivateSettings) {
|
||||
this.saveSetting(bean);
|
||||
await this.saveSetting(bean);
|
||||
|
||||
//让设置生效
|
||||
await this.reloadPrivateSettings();
|
||||
}
|
||||
|
||||
async reloadPrivateSettings() {
|
||||
const bean = await this.getPrivateSettings();
|
||||
if (bean.httpProxy || bean.httpsProxy) {
|
||||
setGlobalProxy({
|
||||
httpProxy: bean.httpProxy,
|
||||
httpsProxy: bean.httpsProxy,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async updateByKey(key: string, setting: any) {
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.26.5](https://github.com/certd/certd/compare/v1.26.4...v1.26.5) (2024-10-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||
|
||||
## [1.26.4](https://github.com/certd/certd/compare/v1.26.3...v1.26.4) (2024-10-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||
|
||||
## [1.26.3](https://github.com/certd/certd/compare/v1.26.2...v1.26.3) (2024-10-12)
|
||||
|
||||
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@certd/midway-flyway-js",
|
||||
"version": "1.26.3",
|
||||
"version": "1.26.5",
|
||||
"description": "midway with flyway, sql upgrade way ",
|
||||
"private": false,
|
||||
"type": "module",
|
||||
@@ -56,5 +56,5 @@
|
||||
"typeorm": "^0.3.11",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "66f9b08fcf5035577eafc609fd634d6490bc9cae"
|
||||
"gitHead": "e96a83a528d6b850bca12d1636690d2ec654ed57"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,18 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.26.5](https://github.com/certd/certd/compare/v1.26.4...v1.26.5) (2024-10-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/plugin-cert
|
||||
|
||||
## [1.26.4](https://github.com/certd/certd/compare/v1.26.3...v1.26.4) (2024-10-14)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* [comm] 支持插件管理 ([e8b617b](https://github.com/certd/certd/commit/e8b617b80ce882dd63006f0cfc719a80a1cc6acc))
|
||||
* 新增代理设置功能 ([273ab61](https://github.com/certd/certd/commit/273ab6139f5807f4d7fe865cc353b97f51b9a668))
|
||||
* EAB授权支持绑定邮箱,支持公共EAB设置 ([07043af](https://github.com/certd/certd/commit/07043aff0ca7fd29c56dd3c363002cb15d78b464))
|
||||
|
||||
## [1.26.3](https://github.com/certd/certd/compare/v1.26.2...v1.26.3) (2024-10-12)
|
||||
|
||||
**Note:** Version bump only for package @certd/plugin-cert
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/plugin-cert",
|
||||
"private": false,
|
||||
"version": "1.26.3",
|
||||
"version": "1.26.5",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -15,9 +15,9 @@
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@certd/acme-client": "^1.26.3",
|
||||
"@certd/basic": "^1.26.3",
|
||||
"@certd/pipeline": "^1.26.3",
|
||||
"@certd/acme-client": "^1.26.5",
|
||||
"@certd/basic": "^1.26.5",
|
||||
"@certd/pipeline": "^1.26.5",
|
||||
"@google-cloud/publicca": "^1.3.0",
|
||||
"dayjs": "^1.11.7",
|
||||
"jszip": "^3.10.1",
|
||||
@@ -57,5 +57,5 @@
|
||||
"vite": "^3.1.0",
|
||||
"vue-tsc": "^0.38.9"
|
||||
},
|
||||
"gitHead": "66f9b08fcf5035577eafc609fd634d6490bc9cae"
|
||||
"gitHead": "e96a83a528d6b850bca12d1636690d2ec654ed57"
|
||||
}
|
||||
|
||||
@@ -26,6 +26,16 @@ export class EabAccess extends BaseAccess {
|
||||
encrypt: true,
|
||||
})
|
||||
hmacKey = "";
|
||||
|
||||
@AccessInput({
|
||||
title: "email",
|
||||
component: {
|
||||
placeholder: "绑定一个邮箱",
|
||||
},
|
||||
helper: "Google EAB 申请证书绑定邮箱后,不能更换,否则会导致EAB失效",
|
||||
required: false,
|
||||
})
|
||||
email = "";
|
||||
}
|
||||
|
||||
new EabAccess();
|
||||
|
||||
@@ -195,6 +195,7 @@ export abstract class CertApplyBasePlugin extends AbstractTaskPlugin {
|
||||
async condition() {
|
||||
if (this.forceUpdate) {
|
||||
this.logger.info("强制更新证书选项已勾选,准备申请新证书");
|
||||
this.logger.warn("申请完之后,切记取消强制更新,避免申请过多证书。");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import { createDnsProvider, DnsProviderContext, IDnsProvider } from "../../dns-p
|
||||
import { CertReader } from "./cert-reader.js";
|
||||
import { CertApplyBasePlugin } from "./base.js";
|
||||
import { GoogleClient } from "../../libs/google.js";
|
||||
import { EabAccess } from "../../access";
|
||||
|
||||
export type { CertInfo };
|
||||
export * from "./cert-reader.js";
|
||||
@@ -103,7 +104,7 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
|
||||
},
|
||||
rules: [{ type: "checkCnameVerifyPlan" }],
|
||||
required: true,
|
||||
helper: "如果选择CNAME方式,请按照上面的显示,给域名添加CNAME记录,添加后,点击验证,验证成功后不要删除记录,申请和续期证书会一直用它",
|
||||
helper: "如果选择CNAME方式,请按照上面的显示,给要申请证书的域名添加CNAME记录,添加后,点击验证,验证成功后不要删除记录,申请和续期证书会一直用它",
|
||||
col: {
|
||||
span: 24,
|
||||
},
|
||||
@@ -122,7 +123,7 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
|
||||
domainsVerifyPlan!: DomainsVerifyPlanInput;
|
||||
|
||||
@TaskInput({
|
||||
title: "证书提供商",
|
||||
title: "证书颁发机构",
|
||||
value: "letsencrypt",
|
||||
component: {
|
||||
name: "a-select",
|
||||
@@ -138,6 +139,13 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
|
||||
})
|
||||
sslProvider!: SSLProvider;
|
||||
|
||||
@TaskInput({
|
||||
title: "Google公共EAB授权",
|
||||
isSys: true,
|
||||
show: false,
|
||||
})
|
||||
googleCommonEabAccessId!: number;
|
||||
|
||||
@TaskInput({
|
||||
title: "EAB授权",
|
||||
component: {
|
||||
@@ -151,7 +159,7 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
|
||||
mergeScript: `
|
||||
return {
|
||||
show: ctx.compute(({form})=>{
|
||||
return form.sslProvider === 'zerossl' || form.sslProvider === 'google'
|
||||
return form.sslProvider === 'zerossl' || (form.sslProvider === 'google' && !form.googleCommonEabAccessId)
|
||||
})
|
||||
}
|
||||
`,
|
||||
@@ -171,7 +179,7 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
|
||||
mergeScript: `
|
||||
return {
|
||||
show: ctx.compute(({form})=>{
|
||||
return form.sslProvider === 'google'
|
||||
return form.sslProvider === 'google' && !form.googleCommonEabAccessId
|
||||
})
|
||||
}
|
||||
`,
|
||||
@@ -233,12 +241,13 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
|
||||
|
||||
acme!: AcmeService;
|
||||
|
||||
eab!: EabAccess;
|
||||
async onInit() {
|
||||
let eab: any = null;
|
||||
let eab: EabAccess = null;
|
||||
|
||||
if (this.sslProvider === "google") {
|
||||
if (this.googleAccessId) {
|
||||
this.logger.info("您正在使用google服务账号授权");
|
||||
this.logger.info("当前正在使用 google服务账号授权获取EAB");
|
||||
const googleAccess = await this.ctx.accessService.getById(this.googleAccessId);
|
||||
const googleClient = new GoogleClient({
|
||||
access: googleAccess,
|
||||
@@ -246,8 +255,11 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
|
||||
});
|
||||
eab = await googleClient.getEab();
|
||||
} else if (this.eabAccessId) {
|
||||
this.logger.info("您正在使用google EAB授权");
|
||||
this.logger.info("当前正在使用 google EAB授权");
|
||||
eab = await this.ctx.accessService.getById(this.eabAccessId);
|
||||
} else if (this.googleCommonEabAccessId) {
|
||||
this.logger.info("当前正在使用 google公共EAB授权");
|
||||
eab = await this.ctx.accessService.getById(this.googleCommonEabAccessId);
|
||||
} else {
|
||||
this.logger.error("google需要配置EAB授权或服务账号授权");
|
||||
return;
|
||||
@@ -260,7 +272,7 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.eab = eab;
|
||||
this.acme = new AcmeService({
|
||||
userContext: this.userContext,
|
||||
logger: this.logger,
|
||||
@@ -276,7 +288,10 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
|
||||
}
|
||||
|
||||
async doCertApply() {
|
||||
const email = this["email"];
|
||||
let email = this.email;
|
||||
if (this.eab && this.eab.email) {
|
||||
email = this.eab.email;
|
||||
}
|
||||
const domains = this["domains"];
|
||||
|
||||
const csrInfo = _.merge(
|
||||
|
||||
@@ -3,6 +3,18 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.26.5](https://github.com/certd/certd/compare/v1.26.4...v1.26.5) (2024-10-14)
|
||||
|
||||
**Note:** Version bump only for package @certd/ui-client
|
||||
|
||||
## [1.26.4](https://github.com/certd/certd/compare/v1.26.3...v1.26.4) (2024-10-14)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* [comm] 支持插件管理 ([e8b617b](https://github.com/certd/certd/commit/e8b617b80ce882dd63006f0cfc719a80a1cc6acc))
|
||||
* 新增代理设置功能 ([273ab61](https://github.com/certd/certd/commit/273ab6139f5807f4d7fe865cc353b97f51b9a668))
|
||||
* EAB授权支持绑定邮箱,支持公共EAB设置 ([07043af](https://github.com/certd/certd/commit/07043aff0ca7fd29c56dd3c363002cb15d78b464))
|
||||
|
||||
## [1.26.3](https://github.com/certd/certd/compare/v1.26.2...v1.26.3) (2024-10-12)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@certd/ui-client",
|
||||
"version": "1.26.3",
|
||||
"version": "1.26.5",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite --open",
|
||||
@@ -61,8 +61,8 @@
|
||||
"vuedraggable": "^4.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@certd/lib-iframe": "^1.26.3",
|
||||
"@certd/pipeline": "^1.26.3",
|
||||
"@certd/lib-iframe": "^1.26.5",
|
||||
"@certd/pipeline": "^1.26.5",
|
||||
"@rollup/plugin-commonjs": "^25.0.7",
|
||||
"@rollup/plugin-node-resolve": "^15.2.3",
|
||||
"@types/chai": "^4.3.12",
|
||||
|
||||
@@ -8,11 +8,11 @@ export type SiteEnv = {
|
||||
};
|
||||
};
|
||||
export type SiteInfo = {
|
||||
title: string;
|
||||
slogan: string;
|
||||
logo: string;
|
||||
loginLogo: string;
|
||||
icpNo: string;
|
||||
title?: string;
|
||||
slogan?: string;
|
||||
logo?: string;
|
||||
loginLogo?: string;
|
||||
icpNo?: string;
|
||||
licenseTo?: string;
|
||||
licenseToUrl?: string;
|
||||
};
|
||||
|
||||
@@ -117,7 +117,7 @@ async function doActive() {
|
||||
}
|
||||
const res = await api.doActive(formState);
|
||||
if (res) {
|
||||
await userStore.reInit();
|
||||
await settingStore.init();
|
||||
const vipLabel = settingStore.vipLabel;
|
||||
Modal.success({
|
||||
title: "激活成功",
|
||||
|
||||
@@ -77,10 +77,10 @@
|
||||
<a :href="siteInfo.licenseToUrl || ''">{{ siteInfo.licenseTo }}</a>
|
||||
</template>
|
||||
|
||||
<template v-if="siteInfo.icpNo">
|
||||
<template v-if="sysPublic.icpNo">
|
||||
<a-divider type="vertical" />
|
||||
<span>
|
||||
<a href="https://beian.miit.gov.cn/" target="_blank">{{ siteInfo.icpNo }}</a>
|
||||
<a href="https://beian.miit.gov.cn/" target="_blank">{{ sysPublic.icpNo }}</a>
|
||||
</span>
|
||||
</template>
|
||||
</div>
|
||||
@@ -93,7 +93,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, onErrorCaptured, ref } from "vue";
|
||||
import { computed, onErrorCaptured, onMounted, ref } from "vue";
|
||||
import FsMenu from "./components/menu/index.jsx";
|
||||
import FsLocale from "./components/locale/index.vue";
|
||||
import FsUserInfo from "./components/user-info/index.vue";
|
||||
@@ -140,9 +140,16 @@ const userStore = useUserStore();
|
||||
|
||||
const settingStore = useSettingStore();
|
||||
|
||||
const sysPublic = computed(() => {
|
||||
return settingStore.sysPublic;
|
||||
});
|
||||
const siteInfo = computed(() => {
|
||||
return settingStore.siteInfo;
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
await settingStore.checkUrlBound();
|
||||
});
|
||||
</script>
|
||||
<style lang="less">
|
||||
@import "../style/theme/index.less";
|
||||
|
||||
@@ -27,9 +27,9 @@
|
||||
<a-divider type="vertical" />
|
||||
<a :href="siteInfo.licenseToUrl" target="_blank">{{ siteInfo.licenseTo }}</a>
|
||||
</span>
|
||||
<span v-if="siteInfo.icpNo">
|
||||
<span v-if="sysPublic.icpNo">
|
||||
<a-divider type="vertical" />
|
||||
<a href="https://beian.miit.gov.cn/" target="_blank">{{ siteInfo.icpNo }}</a>
|
||||
<a href="https://beian.miit.gov.cn/" target="_blank">{{ sysPublic.icpNo }}</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -40,13 +40,17 @@
|
||||
<script lang="ts" setup>
|
||||
import { env } from "/@/utils/util.env";
|
||||
import { computed, ref, Ref } from "vue";
|
||||
import { SiteInfo, useSettingStore } from "/@/store/modules/settings";
|
||||
import { useSettingStore } from "/@/store/modules/settings";
|
||||
import { SiteInfo, SysPublicSetting } from "/@/api/modules/api.basic";
|
||||
|
||||
const envRef = ref(env);
|
||||
const settingStore = useSettingStore();
|
||||
const siteInfo: Ref<SiteInfo> = computed(() => {
|
||||
return settingStore.siteInfo;
|
||||
});
|
||||
const sysPublic: Ref<SysPublicSetting> = computed(() => {
|
||||
return settingStore.sysPublic;
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
|
||||
@@ -134,7 +134,7 @@ function install(app: App, options: any = {}) {
|
||||
//固定label宽度
|
||||
span: null,
|
||||
style: {
|
||||
width: "120px"
|
||||
width: "145px"
|
||||
}
|
||||
},
|
||||
async afterSubmit({ mode }) {
|
||||
@@ -182,86 +182,7 @@ function install(app: App, options: any = {}) {
|
||||
// @ts-ignore
|
||||
app.use(FsExtendsUploader, {
|
||||
// @ts-ignore
|
||||
defaultType: "cos",
|
||||
cos: {
|
||||
keepName: true,
|
||||
domain: "https://d2p-demo-1251260344.cos.ap-guangzhou.myqcloud.com",
|
||||
bucket: "d2p-plugins-1251260344",
|
||||
region: "ap-guangzhou",
|
||||
secretId: "", //
|
||||
secretKey: "", // 传了secretKey 和secretId 代表使用本地签名模式(不安全,生产环境不推荐)
|
||||
async getAuthorization(custom: any) {
|
||||
// 不传secretKey代表使用临时签名模式,此时此参数必传(安全,生产环境推荐)
|
||||
const ret = request({
|
||||
url: "http://www.docmirror.cn:7070/api/upload/cos/getAuthorization",
|
||||
method: "get"
|
||||
});
|
||||
// 返回结构要求如下
|
||||
// ret.data:{
|
||||
// TmpSecretId,
|
||||
// TmpSecretKey,
|
||||
// XCosSecurityToken,
|
||||
// ExpiredTime, // SDK 在 ExpiredTime 时间前,不会再次调用 getAuthorization
|
||||
// }
|
||||
return ret;
|
||||
},
|
||||
successHandle(ret: any) {
|
||||
// 上传完成后可以在此处处理结果,修改url什么的
|
||||
console.log("success handle:", ret);
|
||||
return ret;
|
||||
}
|
||||
},
|
||||
alioss: {
|
||||
keepName: true,
|
||||
domain: "https://d2p-demo.oss-cn-shenzhen.aliyuncs.com",
|
||||
bucket: "d2p-plugins",
|
||||
region: "oss-cn-shenzhen",
|
||||
accessKeyId: "",
|
||||
accessKeySecret: "",
|
||||
async getAuthorization(context: FsUploaderGetAuthContext): Promise<FsUploaderAliossSTS> {
|
||||
// 不传accessKeySecret代表使用临时签名模式,此时此参数必传(安全,生产环境推荐)
|
||||
const ret = await request({
|
||||
url: "http://www.docmirror.cn:7070/api/upload/alioss/getAuthorization",
|
||||
method: "get"
|
||||
});
|
||||
console.log("ret", ret);
|
||||
// 返回结构要求如下
|
||||
// ret.data:{
|
||||
// TmpSecretId,
|
||||
// TmpSecretKey,
|
||||
// XCosSecurityToken,
|
||||
// ExpiredTime, // SDK 在 ExpiredTime 时间前,不会再次调用 getAuthorization
|
||||
// key //【可选】后台生成的文件key,如果不传则用前端自己生成的key
|
||||
// }
|
||||
return ret;
|
||||
},
|
||||
sdkOpts: {
|
||||
// sdk配置
|
||||
secure: true // 默认为非https上传,为了安全,设置为true
|
||||
},
|
||||
successHandle(ret: any) {
|
||||
// 上传完成后可以在此处处理结果,修改url什么的
|
||||
console.log("success handle:", ret);
|
||||
return ret;
|
||||
}
|
||||
},
|
||||
qiniu: {
|
||||
keepName: true,
|
||||
bucket: "d2p-plugins",
|
||||
async getToken(options: any) {
|
||||
const ret = await request({
|
||||
url: "http://www.docmirror.cn:7070/api/upload/qiniu/getToken",
|
||||
method: "get"
|
||||
});
|
||||
return ret; // {token:xxx,expires:xxx}
|
||||
},
|
||||
successHandle(ret: any) {
|
||||
// 上传完成后可以在此处处理结果,修改url什么的
|
||||
console.log("success handle:", ret);
|
||||
return ret;
|
||||
},
|
||||
domain: "http://d2p.file.handsfree.work/"
|
||||
},
|
||||
defaultType: "form",
|
||||
form: {
|
||||
keepName: true,
|
||||
action: "http://www.docmirror.cn:7070/api/upload/form/upload",
|
||||
@@ -313,6 +234,11 @@ function install(app: App, options: any = {}) {
|
||||
//此处演示修改官方字段类型
|
||||
const textType = getType("text");
|
||||
textType.search.autoSearchTrigger = "change"; //修改官方的字段类型,变化就触发 , "enter"=回车键触发
|
||||
if (!textType.column) {
|
||||
textType.column = {};
|
||||
}
|
||||
textType.column.ellipsis = true;
|
||||
textType.column.showTitle = true;
|
||||
|
||||
// 此处演示自定义字段类型
|
||||
addTypes({
|
||||
|
||||
@@ -68,6 +68,48 @@ export const sysResources = [
|
||||
permission: "sys:settings:view"
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "系统级授权",
|
||||
name: "SysAccess",
|
||||
path: "/sys/access",
|
||||
component: "/sys/access/index.vue",
|
||||
meta: {
|
||||
show: () => {
|
||||
const settingStore = useSettingStore();
|
||||
return settingStore.isComm;
|
||||
},
|
||||
icon: "ion:disc-outline",
|
||||
permission: "sys:settings:view"
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "插件管理",
|
||||
name: "SysPlugin",
|
||||
path: "/sys/plugin",
|
||||
component: "/sys/plugin/index.vue",
|
||||
meta: {
|
||||
show: () => {
|
||||
const settingStore = useSettingStore();
|
||||
return settingStore.isComm;
|
||||
},
|
||||
icon: "ion:extension-puzzle-outline",
|
||||
permission: "sys:settings:view"
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "证书插件配置",
|
||||
name: "SysPluginConfig",
|
||||
path: "/sys/plugin/config",
|
||||
component: "/sys/plugin/config.vue",
|
||||
meta: {
|
||||
show: () => {
|
||||
const settingStore = useSettingStore();
|
||||
return settingStore.isComm;
|
||||
},
|
||||
icon: "ion:extension-puzzle",
|
||||
permission: "sys:settings:view"
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "账号绑定",
|
||||
name: "AccountBind",
|
||||
|
||||
@@ -44,12 +44,11 @@ const defaultThemeConfig = {
|
||||
mode: "light"
|
||||
};
|
||||
const SETTING_THEME_KEY = "SETTING_THEME";
|
||||
const defaultSiteInfo = {
|
||||
const defaultSiteInfo: SiteInfo = {
|
||||
title: env.TITLE || "Certd",
|
||||
slogan: env.SLOGAN || "让你的证书永不过期",
|
||||
logo: env.LOGO || "/static/images/logo/logo.svg",
|
||||
loginLogo: env.LOGIN_LOGO || "/static/images/logo/rect-block.svg",
|
||||
icpNo: env.ICP_NO,
|
||||
licenseTo: "",
|
||||
licenseToUrl: ""
|
||||
};
|
||||
@@ -69,7 +68,7 @@ export const useSettingStore = defineStore({
|
||||
sysPublic: {
|
||||
registerEnabled: false,
|
||||
managerOtherUserPipeline: false,
|
||||
icpNo: ""
|
||||
icpNo: env.ICP_NO || ""
|
||||
},
|
||||
installInfo: {
|
||||
siteId: "",
|
||||
@@ -136,7 +135,6 @@ export const useSettingStore = defineStore({
|
||||
_.merge(this.plusInfo, allSettings.plusInfo || {});
|
||||
//@ts-ignore
|
||||
this.initSiteInfo(allSettings.siteInfo || {});
|
||||
await this.checkUrlBound();
|
||||
},
|
||||
initSiteInfo(siteInfo: SiteInfo) {
|
||||
//@ts-ignore
|
||||
@@ -148,11 +146,6 @@ export const useSettingStore = defineStore({
|
||||
siteInfo.loginLogo = `/api/basic/file/download?key=${siteInfo.loginLogo}`;
|
||||
}
|
||||
}
|
||||
|
||||
const sysPublic = this.getSysPublic;
|
||||
if (sysPublic.icpNo) {
|
||||
siteInfo.icpNo = sysPublic.icpNo;
|
||||
}
|
||||
this.siteInfo = _.merge({}, defaultSiteInfo, siteInfo);
|
||||
},
|
||||
async checkUrlBound() {
|
||||
|
||||
@@ -222,3 +222,8 @@ h1, h2, h3, h4, h5, h6 {
|
||||
/* right: 0; */
|
||||
}
|
||||
}
|
||||
|
||||
.settings-form {
|
||||
width: 800px;
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
@@ -1,33 +1,32 @@
|
||||
// @ts-ignore
|
||||
import * as api from "/@/views/certd/access/api";
|
||||
import { ref } from "vue";
|
||||
import { getCommonColumnDefine } from "/@/views/certd/access/common";
|
||||
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
|
||||
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
|
||||
|
||||
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||
const { crudBinding } = crudExpose;
|
||||
const { props, ctx } = context;
|
||||
const { props, ctx, api } = context;
|
||||
const lastResRef = ref();
|
||||
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
|
||||
return await api.GetList(query);
|
||||
return await context.api.GetList(query);
|
||||
};
|
||||
const editRequest = async (req: EditReq) => {
|
||||
const { form, row } = req;
|
||||
form.id = row.id;
|
||||
form.type = props.type;
|
||||
const res = await api.UpdateObj(form);
|
||||
const res = await context.api.UpdateObj(form);
|
||||
lastResRef.value = res;
|
||||
return res;
|
||||
};
|
||||
const delRequest = async (req: DelReq) => {
|
||||
const { row } = req;
|
||||
return await api.DelObj(row.id);
|
||||
return await context.api.DelObj(row.id);
|
||||
};
|
||||
|
||||
const addRequest = async (req: AddReq) => {
|
||||
const { form } = req;
|
||||
form.type = props.type;
|
||||
const res = await api.AddObj(form);
|
||||
const res = await context.api.AddObj(form);
|
||||
lastResRef.value = res;
|
||||
return res;
|
||||
};
|
||||
@@ -41,7 +40,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
|
||||
const typeRef = ref("aliyun");
|
||||
context.typeRef = typeRef;
|
||||
const commonColumnsDefine = getCommonColumnDefine(crudExpose, typeRef);
|
||||
const commonColumnsDefine = getCommonColumnDefine(crudExpose, typeRef, api);
|
||||
commonColumnsDefine.type.form.component.disabled = true;
|
||||
return {
|
||||
typeRef,
|
||||
@@ -109,6 +108,33 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
width: 200
|
||||
}
|
||||
},
|
||||
from: {
|
||||
title: "级别",
|
||||
type: "dict-select",
|
||||
dict: dict({
|
||||
data: [
|
||||
{ label: "系统", value: "sys" },
|
||||
{ label: "用户", value: "user" }
|
||||
]
|
||||
}),
|
||||
search: {
|
||||
show: false
|
||||
},
|
||||
form: {
|
||||
show: false
|
||||
},
|
||||
column: {
|
||||
width: 100,
|
||||
align: "center",
|
||||
component: {
|
||||
color: "auto"
|
||||
},
|
||||
order: 10
|
||||
},
|
||||
valueBuilder: ({ row, key, value }) => {
|
||||
row[key] = row.userId > 0 ? "user" : "sys";
|
||||
}
|
||||
},
|
||||
...commonColumnsDefine
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
import { defineComponent, onMounted, watch } from "vue";
|
||||
import { useFs } from "@fast-crud/fast-crud";
|
||||
import createCrudOptions from "./crud";
|
||||
import { createAccessApi } from "/@/views/certd/access/api";
|
||||
|
||||
export default defineComponent({
|
||||
name: "CertAccessModal",
|
||||
@@ -16,11 +17,16 @@ export default defineComponent({
|
||||
type: String,
|
||||
default: "aliyun"
|
||||
},
|
||||
from: {
|
||||
type: String, //user | sys
|
||||
default: "user"
|
||||
},
|
||||
modelValue: {}
|
||||
},
|
||||
emits: ["update:modelValue"],
|
||||
setup(props, ctx) {
|
||||
const context: any = { props, ctx };
|
||||
const api = createAccessApi(props.from);
|
||||
const context: any = { props, ctx, api };
|
||||
const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context });
|
||||
|
||||
// 你可以调用此方法,重新初始化crud配置
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="access-selector">
|
||||
<span v-if="target.name" class="mr-5 cd-flex-inline">
|
||||
<span class="mr-5">{{ target.name }}</span>
|
||||
<a-tag class="mr-5" color="green">{{ target.name }}</a-tag>
|
||||
<fs-icon class="cd-icon-button" icon="ion:close-circle-outline" @click="clear"></fs-icon>
|
||||
</span>
|
||||
<span v-else class="mlr-5 text-gray">{{ placeholder }}</span>
|
||||
@@ -9,7 +9,7 @@
|
||||
<a-form-item-rest v-if="chooseForm.show">
|
||||
<a-modal v-model:open="chooseForm.show" title="选择授权提供者" width="900px" @ok="chooseForm.ok">
|
||||
<div style="height: 400px; position: relative">
|
||||
<cert-access-modal v-model="selectedId" :type="type"></cert-access-modal>
|
||||
<cert-access-modal v-model="selectedId" :type="type" :from="from"></cert-access-modal>
|
||||
</div>
|
||||
</a-modal>
|
||||
</a-form-item-rest>
|
||||
@@ -18,9 +18,8 @@
|
||||
|
||||
<script>
|
||||
import { defineComponent, reactive, ref, watch } from "vue";
|
||||
import * as api from "../api";
|
||||
import CertAccessModal from "./access/index.vue";
|
||||
import { GetProviderDefineByAccessType } from "../api";
|
||||
import { createAccessApi } from "../api";
|
||||
|
||||
export default defineComponent({
|
||||
name: "AccessSelector",
|
||||
@@ -41,10 +40,16 @@ export default defineComponent({
|
||||
size: {
|
||||
type: String,
|
||||
default: "middle"
|
||||
},
|
||||
from: {
|
||||
type: String, //user | sys
|
||||
default: "user"
|
||||
}
|
||||
},
|
||||
emits: ["update:modelValue"],
|
||||
setup(props, ctx) {
|
||||
const api = createAccessApi(props.from);
|
||||
|
||||
const target = ref({});
|
||||
const selectedId = ref();
|
||||
async function refreshTarget(value) {
|
||||
|
||||
@@ -1,57 +1,62 @@
|
||||
import { request } from "/src/api/service";
|
||||
const apiPrefix = "/pi/access";
|
||||
export async function GetList(query: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/page",
|
||||
method: "post",
|
||||
data: query
|
||||
});
|
||||
}
|
||||
|
||||
export async function AddObj(obj: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/add",
|
||||
method: "post",
|
||||
data: obj
|
||||
});
|
||||
}
|
||||
export function createAccessApi(from = "user") {
|
||||
const apiPrefix = from === "sys" ? "/sys/access" : "/pi/access";
|
||||
return {
|
||||
async GetList(query: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/page",
|
||||
method: "post",
|
||||
data: query
|
||||
});
|
||||
},
|
||||
|
||||
export async function UpdateObj(obj: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/update",
|
||||
method: "post",
|
||||
data: obj
|
||||
});
|
||||
}
|
||||
async AddObj(obj: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/add",
|
||||
method: "post",
|
||||
data: obj
|
||||
});
|
||||
},
|
||||
|
||||
export async function DelObj(id: number) {
|
||||
return await request({
|
||||
url: apiPrefix + "/delete",
|
||||
method: "post",
|
||||
params: { id }
|
||||
});
|
||||
}
|
||||
async UpdateObj(obj: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/update",
|
||||
method: "post",
|
||||
data: obj
|
||||
});
|
||||
},
|
||||
|
||||
export async function GetObj(id: number) {
|
||||
return await request({
|
||||
url: apiPrefix + "/info",
|
||||
method: "post",
|
||||
params: { id }
|
||||
});
|
||||
}
|
||||
async DelObj(id: number) {
|
||||
return await request({
|
||||
url: apiPrefix + "/delete",
|
||||
method: "post",
|
||||
params: { id }
|
||||
});
|
||||
},
|
||||
|
||||
export async function GetProviderDefine(type: string) {
|
||||
return await request({
|
||||
url: apiPrefix + "/define",
|
||||
method: "post",
|
||||
params: { type }
|
||||
});
|
||||
}
|
||||
async GetObj(id: number) {
|
||||
return await request({
|
||||
url: apiPrefix + "/info",
|
||||
method: "post",
|
||||
params: { id }
|
||||
});
|
||||
},
|
||||
|
||||
export async function GetProviderDefineByAccessType(type: string) {
|
||||
return await request({
|
||||
url: apiPrefix + "/defineByAccessType",
|
||||
method: "post",
|
||||
params: { type }
|
||||
});
|
||||
async GetProviderDefine(type: string) {
|
||||
return await request({
|
||||
url: apiPrefix + "/define",
|
||||
method: "post",
|
||||
params: { type }
|
||||
});
|
||||
},
|
||||
|
||||
async GetProviderDefineByAccessType(type: string) {
|
||||
return await request({
|
||||
url: apiPrefix + "/defineByAccessType",
|
||||
method: "post",
|
||||
params: { type }
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
import { ColumnCompositionProps, dict, compute } from "@fast-crud/fast-crud";
|
||||
// @ts-ignore
|
||||
import * as api from "./api";
|
||||
// @ts-ignore
|
||||
import _ from "lodash-es";
|
||||
import { ColumnCompositionProps, dict } from "@fast-crud/fast-crud";
|
||||
import { computed, ref, toRef } from "vue";
|
||||
import { useReference } from "/@/use/use-refrence";
|
||||
import { forEach, get, merge, set } from "lodash-es";
|
||||
|
||||
export function getCommonColumnDefine(crudExpose: any, typeRef: any) {
|
||||
export function getCommonColumnDefine(crudExpose: any, typeRef: any, api: any) {
|
||||
const AccessTypeDictRef = dict({
|
||||
url: "/pi/access/accessTypeDict"
|
||||
});
|
||||
@@ -27,20 +24,20 @@ export function getCommonColumnDefine(crudExpose: any, typeRef: any) {
|
||||
}
|
||||
}
|
||||
console.log('crudBinding.value[mode + "Form"].columns', columnsRef.value);
|
||||
_.forEach(define.input, (value: any, mapKey: any) => {
|
||||
forEach(define.input, (value: any, mapKey: any) => {
|
||||
const key = "access." + mapKey;
|
||||
const field = {
|
||||
...value,
|
||||
key
|
||||
};
|
||||
const column = _.merge({ title: key }, defaultPluginConfig, field);
|
||||
const column = merge({ title: key }, defaultPluginConfig, field);
|
||||
|
||||
//eval
|
||||
useReference(column);
|
||||
|
||||
//设置默认值
|
||||
if (column.value != null && _.get(form, key) == null) {
|
||||
_.set(form, key, column.value);
|
||||
if (column.value != null && get(form, key) == null) {
|
||||
set(form, key, column.value);
|
||||
}
|
||||
//字段配置赋值
|
||||
columnsRef.value[key] = column;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
// @ts-ignore
|
||||
import * as api from "./api";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { ref } from "vue";
|
||||
import { getCommonColumnDefine } from "/@/views/certd/access/common";
|
||||
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
|
||||
|
||||
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||
const { t } = useI18n();
|
||||
const api = context.api;
|
||||
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
|
||||
return await api.GetList(query);
|
||||
};
|
||||
@@ -28,7 +28,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
|
||||
};
|
||||
|
||||
const typeRef = ref();
|
||||
const commonColumnsDefine = getCommonColumnDefine(crudExpose, typeRef);
|
||||
const commonColumnsDefine = getCommonColumnDefine(crudExpose, typeRef, api);
|
||||
return {
|
||||
crudOptions: {
|
||||
request: {
|
||||
|
||||
@@ -14,11 +14,13 @@
|
||||
import { defineComponent, onMounted } from "vue";
|
||||
import { useFs } from "@fast-crud/fast-crud";
|
||||
import createCrudOptions from "./crud";
|
||||
import { createAccessApi } from "/@/views/certd/access/api";
|
||||
|
||||
export default defineComponent({
|
||||
name: "AccessManager",
|
||||
setup() {
|
||||
const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context: {} });
|
||||
const api = createAccessApi("user");
|
||||
const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context: { api } });
|
||||
|
||||
// 页面打开后获取列表数据
|
||||
onMounted(() => {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { request } from "/src/api/service";
|
||||
import _ from "lodash-es";
|
||||
import { PluginConfigBean, PluginSysSetting } from "/@/views/sys/plugin/api";
|
||||
const apiPrefix = "/pi/plugin";
|
||||
|
||||
const defaultInputDefine = {
|
||||
@@ -54,3 +55,11 @@ export async function GetGroups(query: any) {
|
||||
initPlugins(plugins);
|
||||
return groups;
|
||||
}
|
||||
|
||||
export async function GetPluginConfig(req: { id?: number; name: string; type: string }): Promise<PluginConfigBean> {
|
||||
return await request({
|
||||
url: apiPrefix + "/config",
|
||||
method: "post",
|
||||
data: req
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { compute, CreateCrudOptionsRet, dict } from "@fast-crud/fast-crud";
|
||||
import { PluginGroup } from "@certd/pipeline";
|
||||
import { useReference } from "/@/use/use-refrence";
|
||||
import _ from "lodash-es";
|
||||
import _, { merge } from "lodash-es";
|
||||
import { useUserStore } from "/@/store/modules/user";
|
||||
import { useSettingStore } from "/@/store/modules/settings";
|
||||
|
||||
import * as api from "../api.plugin";
|
||||
export default function (certPluginGroup: PluginGroup, formWrapperRef: any): CreateCrudOptionsRet {
|
||||
const inputs: any = {};
|
||||
const userStore = useUserStore();
|
||||
@@ -46,7 +46,7 @@ export default function (certPluginGroup: PluginGroup, formWrapperRef: any): Cre
|
||||
crudOptions: {
|
||||
form: {
|
||||
wrapper: {
|
||||
width: "1150px",
|
||||
width: 1350,
|
||||
saveRemind: false,
|
||||
title: "创建证书申请流水线"
|
||||
}
|
||||
@@ -73,6 +73,19 @@ export default function (certPluginGroup: PluginGroup, formWrapperRef: any): Cre
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
},
|
||||
valueChange: {
|
||||
handle: async ({ form, value }) => {
|
||||
debugger;
|
||||
const config = await api.GetPluginConfig({
|
||||
name: value,
|
||||
type: "builtIn"
|
||||
});
|
||||
if (config.sysSetting?.input) {
|
||||
merge(form, config.sysSetting.input);
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -116,7 +116,7 @@ import { useUserStore } from "/@/store/modules/user";
|
||||
import { compute, useCompute } from "@fast-crud/fast-crud";
|
||||
import { useReference } from "/@/use/use-refrence";
|
||||
import { useSettingStore } from "/@/store/modules/settings";
|
||||
|
||||
import * as pluginApi from "../../../api.plugin";
|
||||
export default {
|
||||
name: "PiStepForm",
|
||||
// eslint-disable-next-line vue/no-unused-components
|
||||
@@ -163,7 +163,7 @@ export default {
|
||||
console.log("currentStepTypeChanged:", currentStep.value);
|
||||
};
|
||||
|
||||
const stepTypeSave = () => {
|
||||
const stepTypeSave = async () => {
|
||||
currentStep.value._isAdd = false;
|
||||
if (currentStep.value.type == null) {
|
||||
message.warn("请先选择类型");
|
||||
@@ -171,7 +171,7 @@ export default {
|
||||
}
|
||||
|
||||
// 给step的input设置默认值
|
||||
changeCurrentPlugin(currentStep.value);
|
||||
await changeCurrentPlugin(currentStep.value);
|
||||
|
||||
//合并默认值
|
||||
_.merge(currentStep.value, { input: {}, strategy: { runStrategy: 0 } }, currentPlugin.value.default, currentStep.value);
|
||||
@@ -229,7 +229,7 @@ export default {
|
||||
const currentPlugin = doComputed(() => {
|
||||
return currentPluginDefine.value;
|
||||
}, getContext);
|
||||
const changeCurrentPlugin = (step: any) => {
|
||||
const changeCurrentPlugin = async (step: any) => {
|
||||
const stepType = step.type;
|
||||
step.type = stepType;
|
||||
step._isAdd = false;
|
||||
@@ -255,6 +255,14 @@ export default {
|
||||
currentStep.value.input[key] = column.default ?? column.value;
|
||||
}
|
||||
}
|
||||
//设置系统初始值
|
||||
debugger;
|
||||
const pluginSysConfig = await pluginApi.GetPluginConfig({ name: pluginDefine.name, type: "builtIn" });
|
||||
if (pluginSysConfig.sysSetting?.input) {
|
||||
for (const key in pluginSysConfig.sysSetting?.input) {
|
||||
currentStep.value.input[key] = pluginSysConfig.sysSetting?.input[key];
|
||||
}
|
||||
}
|
||||
|
||||
console.log("currentStepTypeChanged:", currentStep.value);
|
||||
console.log("currentStepPlugin:", currentPlugin.value);
|
||||
|
||||
@@ -20,7 +20,7 @@ export type PluginGroup = {
|
||||
};
|
||||
|
||||
export type PluginDefine = {
|
||||
key: string;
|
||||
name: string;
|
||||
title: string;
|
||||
desc?: string;
|
||||
input: {
|
||||
|
||||
36
packages/ui/certd-client/src/views/sys/access/index.vue
Normal file
36
packages/ui/certd-client/src/views/sys/access/index.vue
Normal file
@@ -0,0 +1,36 @@
|
||||
<template>
|
||||
<fs-page>
|
||||
<template #header>
|
||||
<div class="title">
|
||||
系统级授权管理
|
||||
<span class="sub">管理第三方系统的授权信息(系统级)</span>
|
||||
</div>
|
||||
</template>
|
||||
<fs-crud ref="crudRef" v-bind="crudBinding"> </fs-crud>
|
||||
</fs-page>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, onMounted } from "vue";
|
||||
import { useFs } from "@fast-crud/fast-crud";
|
||||
import createCrudOptions from "../../certd/access/crud";
|
||||
import { createAccessApi } from "/@/views/certd/access/api";
|
||||
|
||||
export default defineComponent({
|
||||
name: "SysAccessManager",
|
||||
setup() {
|
||||
const api = createAccessApi("/sys/access");
|
||||
const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context: { api } });
|
||||
|
||||
// 页面打开后获取列表数据
|
||||
onMounted(() => {
|
||||
crudExpose.doRefresh();
|
||||
});
|
||||
|
||||
return {
|
||||
crudBinding,
|
||||
crudRef
|
||||
};
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -76,18 +76,21 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
}
|
||||
},
|
||||
domain: {
|
||||
title: "域名",
|
||||
title: "CNAME域名",
|
||||
type: "text",
|
||||
editForm: {
|
||||
component: {
|
||||
disabled: true
|
||||
}
|
||||
},
|
||||
search: {
|
||||
show: true
|
||||
},
|
||||
form: {
|
||||
component: {
|
||||
placeholder: "cname.handsfree.work"
|
||||
},
|
||||
helper: "CNAME域名一旦确定不可修改,建议使用一级子域名",
|
||||
helper: "需要一个右边DNS提供商注册的域名(也可以将其他域名的dns服务器转移到这几家来)。\nCNAME域名一旦确定不可修改,建议使用一级子域名",
|
||||
rules: [{ required: true, message: "此项必填" }]
|
||||
},
|
||||
column: {
|
||||
@@ -97,6 +100,9 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
dnsProviderType: {
|
||||
title: "DNS提供商",
|
||||
type: "dict-select",
|
||||
search: {
|
||||
show: true
|
||||
},
|
||||
dict: dict({
|
||||
url: "pi/dnsProvider/list",
|
||||
value: "key",
|
||||
|
||||
102
packages/ui/certd-client/src/views/sys/plugin/api.ts
Normal file
102
packages/ui/certd-client/src/views/sys/plugin/api.ts
Normal file
@@ -0,0 +1,102 @@
|
||||
import { request } from "/src/api/service";
|
||||
|
||||
const apiPrefix = "/sys/plugin";
|
||||
|
||||
export async function GetList(query: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/page",
|
||||
method: "post",
|
||||
data: query
|
||||
});
|
||||
}
|
||||
|
||||
export async function AddObj(obj: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/add",
|
||||
method: "post",
|
||||
data: obj
|
||||
});
|
||||
}
|
||||
|
||||
export async function UpdateObj(obj: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/update",
|
||||
method: "post",
|
||||
data: obj
|
||||
});
|
||||
}
|
||||
|
||||
export async function DelObj(id: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/delete",
|
||||
method: "post",
|
||||
params: { id }
|
||||
});
|
||||
}
|
||||
|
||||
export async function GetObj(id: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/info",
|
||||
method: "post",
|
||||
params: { id }
|
||||
});
|
||||
}
|
||||
|
||||
export async function GetDetail(id: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/detail",
|
||||
method: "post",
|
||||
params: { id }
|
||||
});
|
||||
}
|
||||
|
||||
export async function DeleteBatch(ids: any[]) {
|
||||
return await request({
|
||||
url: apiPrefix + "/deleteByIds",
|
||||
method: "post",
|
||||
data: { ids }
|
||||
});
|
||||
}
|
||||
|
||||
export async function SetDisabled(data: { id?: number; name?: string; type?: string; disabled: boolean }) {
|
||||
return await request({
|
||||
url: apiPrefix + "/setDisabled",
|
||||
method: "post",
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
export type PluginConfigBean = {
|
||||
name: string;
|
||||
disabled: boolean;
|
||||
sysSetting: {
|
||||
input?: Record<string, any>;
|
||||
};
|
||||
};
|
||||
|
||||
export type CertApplyPluginSysInput = {
|
||||
googleCommonEabAccessId: number;
|
||||
};
|
||||
export type PluginSysSetting<T> = {
|
||||
sysSetting: {
|
||||
input?: T;
|
||||
};
|
||||
};
|
||||
export type CommPluginConfig = {
|
||||
CertApply?: PluginSysSetting<CertApplyPluginSysInput>;
|
||||
};
|
||||
|
||||
export async function GetCommPluginConfigs(): Promise<CommPluginConfig> {
|
||||
return await request({
|
||||
url: apiPrefix + "/getCommPluginConfigs",
|
||||
method: "post"
|
||||
});
|
||||
}
|
||||
|
||||
export async function SaveCommPluginConfigs(data: CommPluginConfig): Promise<void> {
|
||||
return await request({
|
||||
url: apiPrefix + "/saveCommPluginConfigs",
|
||||
method: "post",
|
||||
data
|
||||
});
|
||||
}
|
||||
73
packages/ui/certd-client/src/views/sys/plugin/config.vue
Normal file
73
packages/ui/certd-client/src/views/sys/plugin/config.vue
Normal file
@@ -0,0 +1,73 @@
|
||||
<template>
|
||||
<fs-page class="page-plugin-config">
|
||||
<template #header>
|
||||
<div class="title">证书插件配置</div>
|
||||
</template>
|
||||
|
||||
<div class="sys-plugin-config settings-form">
|
||||
<a-form :model="formState" :label-col="{ span: 8 }" :wrapper-col="{ span: 16 }" autocomplete="off" @finish="onFinish" @finish-failed="onFinishFailed">
|
||||
<a-form-item label="公共Google EAB授权" :name="['CertApply', 'sysSetting', 'input', 'googleCommonEabAccessId']">
|
||||
<access-selector v-model:model-value="formState.CertApply.sysSetting.input.googleCommonEabAccessId" type="eab" from="sys"></access-selector>
|
||||
<div class="helper">
|
||||
<div>设置公共Google EAB授权给用户使用,避免用户自己去翻墙获取Google EAB授权</div>
|
||||
<div>
|
||||
<a href="https://gitee.com/certd/certd/blob/v2/doc/google/google.md#21-%E7%9B%B4%E6%8E%A5%E8%8E%B7%E5%8F%96eab-%E6%8E%A8%E8%8D%90">
|
||||
获取Google EAB授权方法
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item :wrapper-col="{ offset: 8, span: 16 }">
|
||||
<a-button :loading="saveLoading" type="primary" html-type="submit">保存</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
</fs-page>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import AccessSelector from "/@/views/certd/access/access-selector/index.vue";
|
||||
import { reactive, ref } from "vue";
|
||||
import { CommPluginConfig, GetCommPluginConfigs, SaveCommPluginConfigs } from "/@/views/sys/plugin/api";
|
||||
import { merge } from "lodash-es";
|
||||
import { notification } from "ant-design-vue";
|
||||
|
||||
defineOptions({
|
||||
name: "SysPluginConfig"
|
||||
});
|
||||
const formState = reactive<Partial<CommPluginConfig>>({
|
||||
CertApply: {
|
||||
sysSetting: {
|
||||
input: {
|
||||
googleCommonEabAccessId: null
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
async function loadForm() {
|
||||
const res = await GetCommPluginConfigs();
|
||||
merge(formState, res);
|
||||
}
|
||||
|
||||
loadForm();
|
||||
|
||||
const saveLoading = ref(false);
|
||||
const onFinish = async (form: any) => {
|
||||
try {
|
||||
saveLoading.value = true;
|
||||
await SaveCommPluginConfigs(form);
|
||||
notification.success({
|
||||
message: "保存成功"
|
||||
});
|
||||
} finally {
|
||||
saveLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const onFinishFailed = (errorInfo: any) => {
|
||||
console.log("Failed:", errorInfo);
|
||||
};
|
||||
</script>
|
||||
<style lang="less"></style>
|
||||
211
packages/ui/certd-client/src/views/sys/plugin/crud.tsx
Normal file
211
packages/ui/certd-client/src/views/sys/plugin/crud.tsx
Normal file
@@ -0,0 +1,211 @@
|
||||
import * as api from "./api";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { computed, Ref, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes, utils } from "@fast-crud/fast-crud";
|
||||
import { useUserStore } from "/src/store/modules/user";
|
||||
import { useSettingStore } from "/src/store/modules/settings";
|
||||
import { Modal } from "ant-design-vue";
|
||||
|
||||
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||
const router = useRouter();
|
||||
const { t } = useI18n();
|
||||
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
|
||||
return await api.GetList(query);
|
||||
};
|
||||
const editRequest = async ({ form, row }: EditReq) => {
|
||||
form.id = row.id;
|
||||
const res = await api.UpdateObj(form);
|
||||
return res;
|
||||
};
|
||||
const delRequest = async ({ row }: DelReq) => {
|
||||
return await api.DelObj(row.id);
|
||||
};
|
||||
|
||||
const addRequest = async ({ form }: AddReq) => {
|
||||
form.content = JSON.stringify({
|
||||
title: form.title
|
||||
});
|
||||
const res = await api.AddObj(form);
|
||||
return res;
|
||||
};
|
||||
|
||||
const userStore = useUserStore();
|
||||
const settingStore = useSettingStore();
|
||||
const selectedRowKeys: Ref<any[]> = ref([]);
|
||||
context.selectedRowKeys = selectedRowKeys;
|
||||
|
||||
return {
|
||||
crudOptions: {
|
||||
settings: {
|
||||
plugins: {
|
||||
//这里使用行选择插件,生成行选择crudOptions配置,最终会与crudOptions合并
|
||||
rowSelection: {
|
||||
enabled: true,
|
||||
order: -2,
|
||||
before: true,
|
||||
// handle: (pluginProps,useCrudProps)=>CrudOptions,
|
||||
props: {
|
||||
multiple: true,
|
||||
crossPage: true,
|
||||
selectedRowKeys
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
request: {
|
||||
pageRequest,
|
||||
addRequest,
|
||||
editRequest,
|
||||
delRequest
|
||||
},
|
||||
actionbar: {
|
||||
buttons: {
|
||||
add: {
|
||||
show: false
|
||||
}
|
||||
}
|
||||
},
|
||||
rowHandle: {
|
||||
minWidth: 200,
|
||||
fixed: "right",
|
||||
buttons: {
|
||||
edit: {
|
||||
show: false
|
||||
},
|
||||
copy: {
|
||||
show: false
|
||||
},
|
||||
remove: {
|
||||
show: false
|
||||
}
|
||||
}
|
||||
},
|
||||
columns: {
|
||||
id: {
|
||||
title: "ID",
|
||||
key: "id",
|
||||
type: "number",
|
||||
column: {
|
||||
width: 100
|
||||
},
|
||||
form: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
name: {
|
||||
title: "插件名称",
|
||||
type: "text",
|
||||
search: {
|
||||
show: true
|
||||
},
|
||||
form: {
|
||||
show: false
|
||||
},
|
||||
column: {
|
||||
width: 200
|
||||
}
|
||||
},
|
||||
icon: {
|
||||
title: "图标",
|
||||
type: "text",
|
||||
form: {
|
||||
show: false
|
||||
},
|
||||
column: {
|
||||
width: 100,
|
||||
align: "center",
|
||||
component: {
|
||||
name: "fs-icon",
|
||||
vModel: "icon",
|
||||
style: {
|
||||
fontSize: "22px"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
title: {
|
||||
title: "标题",
|
||||
type: "text",
|
||||
column: {
|
||||
width: 300
|
||||
}
|
||||
},
|
||||
desc: {
|
||||
title: "描述",
|
||||
type: "text",
|
||||
column: {
|
||||
width: 300
|
||||
}
|
||||
},
|
||||
group: {
|
||||
title: "分组",
|
||||
type: "text",
|
||||
column: {
|
||||
width: 100,
|
||||
align: "center"
|
||||
}
|
||||
},
|
||||
disabled: {
|
||||
title: "禁用/启用",
|
||||
type: "dict-switch",
|
||||
dict: dict({
|
||||
data: [
|
||||
{ label: "启用", value: false, color: "success" },
|
||||
{ label: "禁用", value: true, color: "error" }
|
||||
]
|
||||
}),
|
||||
form: {
|
||||
value: false
|
||||
},
|
||||
column: {
|
||||
width: 100,
|
||||
align: "center",
|
||||
component: {
|
||||
title: "点击可禁用/启用",
|
||||
on: {
|
||||
async click({ value, row }) {
|
||||
Modal.confirm({
|
||||
title: "提示",
|
||||
content: `确定要${!value ? "禁用" : "启用"}吗?`,
|
||||
onOk: async () => {
|
||||
await api.SetDisabled({
|
||||
id: row.id,
|
||||
name: row.name,
|
||||
type: row.type,
|
||||
disabled: !value
|
||||
});
|
||||
await crudExpose.doRefresh();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
createTime: {
|
||||
title: "创建时间",
|
||||
type: "datetime",
|
||||
form: {
|
||||
show: false
|
||||
},
|
||||
column: {
|
||||
sorter: true,
|
||||
width: 160,
|
||||
align: "center"
|
||||
}
|
||||
},
|
||||
updateTime: {
|
||||
title: "更新时间",
|
||||
type: "datetime",
|
||||
form: {
|
||||
show: false
|
||||
},
|
||||
column: {
|
||||
show: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
51
packages/ui/certd-client/src/views/sys/plugin/index.vue
Normal file
51
packages/ui/certd-client/src/views/sys/plugin/index.vue
Normal file
@@ -0,0 +1,51 @@
|
||||
<template>
|
||||
<fs-page class="page-cert">
|
||||
<template #header>
|
||||
<div class="title">插件管理</div>
|
||||
</template>
|
||||
<fs-crud ref="crudRef" v-bind="crudBinding">
|
||||
<!-- <template #pagination-left>-->
|
||||
<!-- <a-tooltip title="批量删除">-->
|
||||
<!-- <fs-button icon="DeleteOutlined" @click="handleBatchDelete"></fs-button>-->
|
||||
<!-- </a-tooltip>-->
|
||||
<!-- </template>-->
|
||||
</fs-crud>
|
||||
</fs-page>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted } from "vue";
|
||||
import { useFs } from "@fast-crud/fast-crud";
|
||||
import createCrudOptions from "./crud";
|
||||
import { message, Modal } from "ant-design-vue";
|
||||
import { DeleteBatch } from "./api";
|
||||
|
||||
defineOptions({
|
||||
name: "SysPlugin"
|
||||
});
|
||||
const { crudBinding, crudRef, crudExpose, context } = useFs({ createCrudOptions });
|
||||
|
||||
const selectedRowKeys = context.selectedRowKeys;
|
||||
const handleBatchDelete = () => {
|
||||
if (selectedRowKeys.value?.length > 0) {
|
||||
Modal.confirm({
|
||||
title: "确认",
|
||||
content: `确定要批量删除这${selectedRowKeys.value.length}条记录吗`,
|
||||
async onOk() {
|
||||
await DeleteBatch(selectedRowKeys.value);
|
||||
message.info("删除成功");
|
||||
crudExpose.doRefresh();
|
||||
selectedRowKeys.value = [];
|
||||
}
|
||||
});
|
||||
} else {
|
||||
message.error("请先勾选记录");
|
||||
}
|
||||
};
|
||||
|
||||
// 页面打开后获取列表数据
|
||||
onMounted(() => {
|
||||
crudExpose.doRefresh();
|
||||
});
|
||||
</script>
|
||||
<style lang="less"></style>
|
||||
@@ -1,6 +1,18 @@
|
||||
// @ts-ignore
|
||||
import { request } from "/@/api/service";
|
||||
const apiPrefix = "/sys/settings";
|
||||
export type SysSettings = { public: SysPublicSetting; private: SysPrivateSetting };
|
||||
|
||||
export type SysPublicSetting = {
|
||||
registerEnabled?: boolean;
|
||||
managerOtherUserPipeline?: boolean;
|
||||
icpNo?: string;
|
||||
};
|
||||
|
||||
export type SysPrivateSetting = {
|
||||
httpProxy?: string;
|
||||
httpsProxy?: string;
|
||||
};
|
||||
|
||||
export const SettingKeys = {
|
||||
SysPublic: "sys.public",
|
||||
@@ -8,13 +20,17 @@ export const SettingKeys = {
|
||||
SysEmail: "sys.email"
|
||||
};
|
||||
export async function SettingsGet(key: string) {
|
||||
return await request({
|
||||
const res = await request({
|
||||
url: apiPrefix + "/get",
|
||||
method: "post",
|
||||
params: {
|
||||
key
|
||||
}
|
||||
});
|
||||
if (!res) {
|
||||
return {};
|
||||
}
|
||||
return JSON.parse(res.setting);
|
||||
}
|
||||
|
||||
export async function SettingsSave(key: string, setting: any) {
|
||||
@@ -35,17 +51,31 @@ export async function EmailSettingsGet() {
|
||||
});
|
||||
}
|
||||
|
||||
export async function PublicSettingsSave(setting: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/savePublicSettings",
|
||||
method: "post",
|
||||
data: setting
|
||||
});
|
||||
}
|
||||
|
||||
export async function stopOtherUserTimer() {
|
||||
return await request({
|
||||
url: apiPrefix + "/stopOtherUserTimer",
|
||||
method: "post"
|
||||
});
|
||||
}
|
||||
|
||||
export async function SysSettingsGet(): Promise<SysSettings> {
|
||||
return await request({
|
||||
url: apiPrefix + "/getSysSettings",
|
||||
method: "post"
|
||||
});
|
||||
}
|
||||
|
||||
export async function SysSettingsSave(data: SysSettings) {
|
||||
return await request({
|
||||
url: apiPrefix + "/saveSysSettings",
|
||||
method: "post",
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
export async function TestProxy() {
|
||||
return await request({
|
||||
url: apiPrefix + "/testProxy",
|
||||
method: "post"
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<template #header>
|
||||
<div class="title">系统设置</div>
|
||||
</template>
|
||||
<div class="sys-settings-form">
|
||||
<div class="sys-settings-form settings-form">
|
||||
<a-form
|
||||
:model="formState"
|
||||
name="basic"
|
||||
@@ -13,29 +13,31 @@
|
||||
@finish="onFinish"
|
||||
@finish-failed="onFinishFailed"
|
||||
>
|
||||
<a-form-item label="开启自助注册" name="registerEnabled">
|
||||
<a-switch v-model:checked="formState.registerEnabled" />
|
||||
<a-form-item label="开启自助注册" :name="['public', 'registerEnabled']">
|
||||
<a-switch v-model:checked="formState.public.registerEnabled" />
|
||||
</a-form-item>
|
||||
<a-form-item label="管理其他用户流水线" name="managerOtherUserPipeline">
|
||||
<a-switch v-model:checked="formState.managerOtherUserPipeline" />
|
||||
<a-form-item label="管理其他用户流水线" :name="['public', 'managerOtherUserPipeline']">
|
||||
<a-switch v-model:checked="formState.public.managerOtherUserPipeline" />
|
||||
</a-form-item>
|
||||
<a-form-item label="ICP备案号" name="icpNo">
|
||||
<a-input v-model:value="formState.icpNo" />
|
||||
<a-form-item label="ICP备案号" :name="['public', 'icpNo']">
|
||||
<a-input v-model:value="formState.public.icpNo" placeholder="粤ICP备xxxxxxx号" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="HTTP代理" :name="['private', 'httpProxy']" :rules="urlRules">
|
||||
<a-input v-model:value="formState.private.httpProxy" placeholder="http://192.168.1.2:18010/" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="HTTPS代理" :name="['private', 'httpsProxy']" :rules="urlRules">
|
||||
<div class="flex">
|
||||
<a-input v-model:value="formState.private.httpsProxy" placeholder="http://192.168.1.2:18010/" />
|
||||
<a-button class="ml-5" type="primary" title="保存后,再点击测试" @click="testProxy">测试</a-button>
|
||||
</div>
|
||||
<div class="helper">一般这两个代理填一样的</div>
|
||||
</a-form-item>
|
||||
<!-- <a-form-item label="启动后触发流水线" name="triggerOnStartup">-->
|
||||
<!-- <a-switch v-model:checked="formState.triggerOnStartup" />-->
|
||||
<!-- <div class="helper">启动后自动触发一次所有已启用的流水线</div>-->
|
||||
<!-- </a-form-item>-->
|
||||
<a-form-item :wrapper-col="{ offset: 8, span: 16 }">
|
||||
<a-button :loading="saveLoading" type="primary" html-type="submit">保存</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
|
||||
<!-- <a-descriptions label="系统维护操作">-->
|
||||
<!-- <a-descriptions-item label="自动化任务">-->
|
||||
<!-- <a-button @click="stopOtherUserTimer">停止所有其他用户的定时任务</a-button>-->
|
||||
<!-- </a-descriptions-item>-->
|
||||
<!-- </a-descriptions>-->
|
||||
</div>
|
||||
</fs-page>
|
||||
</template>
|
||||
@@ -43,42 +45,41 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from "vue";
|
||||
import * as api from "./api";
|
||||
import { PublicSettingsSave, SettingKeys } from "./api";
|
||||
import { SysSettings } from "./api";
|
||||
import { notification } from "ant-design-vue";
|
||||
import { useSettingStore } from "/@/store/modules/settings";
|
||||
import { merge } from "lodash-es";
|
||||
|
||||
defineOptions({
|
||||
name: "SysSettings"
|
||||
});
|
||||
|
||||
interface FormState {
|
||||
registerEnabled: boolean;
|
||||
managerOtherUserPipeline: boolean;
|
||||
icpNo: string;
|
||||
}
|
||||
|
||||
const formState = reactive<Partial<FormState>>({
|
||||
registerEnabled: false,
|
||||
managerOtherUserPipeline: false,
|
||||
icpNo: ""
|
||||
const formState = reactive<Partial<SysSettings>>({
|
||||
public: {
|
||||
registerEnabled: false,
|
||||
managerOtherUserPipeline: false,
|
||||
icpNo: ""
|
||||
},
|
||||
private: {}
|
||||
});
|
||||
|
||||
async function loadSysPublicSettings() {
|
||||
const data: any = await api.SettingsGet(SettingKeys.SysPublic);
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
const setting = JSON.parse(data.setting);
|
||||
Object.assign(formState, setting);
|
||||
const urlRules = ref({
|
||||
type: "url",
|
||||
message: "请输入正确的URL"
|
||||
});
|
||||
|
||||
async function loadSysSettings() {
|
||||
const data: any = await api.SysSettingsGet();
|
||||
merge(formState, data);
|
||||
}
|
||||
|
||||
const saveLoading = ref(false);
|
||||
loadSysPublicSettings();
|
||||
loadSysSettings();
|
||||
const settingsStore = useSettingStore();
|
||||
const onFinish = async (form: any) => {
|
||||
try {
|
||||
saveLoading.value = true;
|
||||
await api.PublicSettingsSave(form);
|
||||
await api.SysSettingsSave(form);
|
||||
await settingsStore.loadSysSettings();
|
||||
notification.success({
|
||||
message: "保存成功"
|
||||
@@ -98,6 +99,15 @@ async function stopOtherUserTimer() {
|
||||
message: "停止成功"
|
||||
});
|
||||
}
|
||||
|
||||
async function testProxy() {
|
||||
const res = await api.TestProxy();
|
||||
const content = `测试google:${res.google === true ? "成功" : "失败" + res.google},测试百度:${res.baidu === true ? "成功" : "失败:" + res.baidu}`;
|
||||
notification.success({
|
||||
message: "测试完成",
|
||||
description: content
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
|
||||
@@ -4,23 +4,11 @@
|
||||
# server:
|
||||
# baseUrl: 'http://127.0.0.1:11007'
|
||||
|
||||
#flyway:
|
||||
# scriptDir: './db/migration-pg'
|
||||
|
||||
#typeorm:
|
||||
# dataSource:
|
||||
# default:
|
||||
# type: postgres
|
||||
# host: localhost
|
||||
# port: 5433
|
||||
# username: postgres
|
||||
# password: root
|
||||
# database: postgres
|
||||
|
||||
typeorm:
|
||||
dataSource:
|
||||
default:
|
||||
database: './data/db.sqlite'
|
||||
# database: './data/db.sqlite'
|
||||
plus:
|
||||
server:
|
||||
baseUrls: ['https://api.ai.handsfree.work', 'https://api.ai.docmirror.cn']
|
||||
|
||||
21
packages/ui/certd-server/.env.pgpl.yaml
Normal file
21
packages/ui/certd-server/.env.pgpl.yaml
Normal file
@@ -0,0 +1,21 @@
|
||||
flyway:
|
||||
scriptDir: './db/migration-pg'
|
||||
|
||||
|
||||
typeorm:
|
||||
dataSource:
|
||||
default:
|
||||
type: postgres
|
||||
host: 192.168.42.245
|
||||
port: 5432
|
||||
username: root
|
||||
password: Baode@1234567
|
||||
database: certd
|
||||
|
||||
#plus:
|
||||
# server:
|
||||
# baseUrl: 'https://api.ai.handsfree.work'
|
||||
|
||||
plus:
|
||||
server:
|
||||
baseUrl: 'http://127.0.0.1:11007'
|
||||
2
packages/ui/certd-server/.gitignore
vendored
2
packages/ui/certd-server/.gitignore
vendored
@@ -17,3 +17,5 @@ run/
|
||||
/test/setup.ts
|
||||
/data/
|
||||
.clinic
|
||||
|
||||
.env.pgpl.yaml
|
||||
|
||||
@@ -3,6 +3,20 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.26.5](https://github.com/certd/certd/compare/v1.26.4...v1.26.5) (2024-10-14)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复版本号获取错误的bug ([8851870](https://github.com/certd/certd/commit/8851870400df86e496198ad509061b8989fcc44f))
|
||||
|
||||
## [1.26.4](https://github.com/certd/certd/compare/v1.26.3...v1.26.4) (2024-10-14)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* [comm] 支持插件管理 ([e8b617b](https://github.com/certd/certd/commit/e8b617b80ce882dd63006f0cfc719a80a1cc6acc))
|
||||
* 新增代理设置功能 ([273ab61](https://github.com/certd/certd/commit/273ab6139f5807f4d7fe865cc353b97f51b9a668))
|
||||
* EAB授权支持绑定邮箱,支持公共EAB设置 ([07043af](https://github.com/certd/certd/commit/07043aff0ca7fd29c56dd3c363002cb15d78b464))
|
||||
|
||||
## [1.26.3](https://github.com/certd/certd/compare/v1.26.2...v1.26.3) (2024-10-12)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
18
packages/ui/certd-server/db/migration-pg/v10010__plugin.sql
Normal file
18
packages/ui/certd-server/db/migration-pg/v10010__plugin.sql
Normal file
@@ -0,0 +1,18 @@
|
||||
CREATE TABLE "pi_plugin"
|
||||
(
|
||||
"id" bigint NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
|
||||
"name" varchar(100) NOT NULL,
|
||||
"icon" varchar(100),
|
||||
"title" varchar(200),
|
||||
"desc" varchar(500),
|
||||
"group" varchar(100),
|
||||
"version" varchar(100),
|
||||
"setting" text,
|
||||
"sys_setting" text,
|
||||
"content" text,
|
||||
"type" varchar(100) NOT NULL,
|
||||
"disabled" boolean NOT NULL,
|
||||
"create_time" timestamp NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
"update_time" timestamp NOT NULL DEFAULT (CURRENT_TIMESTAMP)
|
||||
);
|
||||
|
||||
18
packages/ui/certd-server/db/migration/v10010__plugin.sql
Normal file
18
packages/ui/certd-server/db/migration/v10010__plugin.sql
Normal file
@@ -0,0 +1,18 @@
|
||||
CREATE TABLE "pi_plugin"
|
||||
(
|
||||
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
"name" varchar(100) NOT NULL,
|
||||
"icon" varchar(100),
|
||||
"title" varchar(200),
|
||||
"desc" varchar(500),
|
||||
"group" varchar(100),
|
||||
"version" varchar(100),
|
||||
"setting" text,
|
||||
"sys_setting" text,
|
||||
"content" text,
|
||||
"type" varchar(100) NOT NULL,
|
||||
"disabled" boolean NOT NULL,
|
||||
"create_time" datetime NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
"update_time" datetime NOT NULL DEFAULT (CURRENT_TIMESTAMP)
|
||||
);
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
## sqlite与postgres不同点
|
||||
1.
|
||||
sl: AUTOINCREAMENT
|
||||
pg: GENERATED BY DEFAULT AS IDENTITY
|
||||
sqlite: AUTOINCREAMENT
|
||||
postgresql: GENERATED BY DEFAULT AS IDENTITY
|
||||
|
||||
2.
|
||||
datetime
|
||||
timestamp
|
||||
sqlite: datetime
|
||||
postgresql: timestamp
|
||||
|
||||
3.
|
||||
update sqlite_sequence set seq = 1000 where name = 'sys_role' ;
|
||||
select setval('sys_role_id_seq', 1000);
|
||||
sqlite: update sqlite_sequence set seq = 1000 where name = 'sys_role' ;
|
||||
postgresql: select setval('sys_role_id_seq', 1000);
|
||||
|
||||
4.
|
||||
"disabled" boolean DEFAULT (0)
|
||||
"disabled" boolean DEFAULT (false)
|
||||
sqlite: "disabled" boolean DEFAULT (0)
|
||||
postgresql: "disabled" boolean DEFAULT (false)
|
||||
|
||||
5.
|
||||
last_insert_rowid()
|
||||
LASTVAL()
|
||||
sqlite: last_insert_rowid()
|
||||
postgresql: LASTVAL()
|
||||
|
||||
6.
|
||||
sl: integer
|
||||
pg: bigint
|
||||
sqlite: integer
|
||||
postgresql: bigint
|
||||
|
||||
53
packages/ui/certd-server/db/transform.js
Normal file
53
packages/ui/certd-server/db/transform.js
Normal file
@@ -0,0 +1,53 @@
|
||||
import fs from 'fs';
|
||||
/**
|
||||
* ## sqlite与postgres不同点
|
||||
* 1.
|
||||
* sqlite: AUTOINCREAMENT
|
||||
* postgresql: GENERATED BY DEFAULT AS IDENTITY
|
||||
*
|
||||
* 2.
|
||||
* sqlite: datetime
|
||||
* postgresql: timestamp
|
||||
*
|
||||
* 3.
|
||||
* sqlite: update sqlite_sequence set seq = 1000 where name = 'sys_role' ;
|
||||
* postgresql: select setval('sys_role_id_seq', 1000);
|
||||
*
|
||||
* 4.
|
||||
* sqlite: "disabled" boolean DEFAULT (0)
|
||||
* postgresql: "disabled" boolean DEFAULT (false)
|
||||
*
|
||||
* 5.
|
||||
* sqlite: last_insert_rowid()
|
||||
* postgresql: LASTVAL()
|
||||
*
|
||||
* 6.
|
||||
* sqlite: integer
|
||||
* postgresql: bigint
|
||||
*/
|
||||
function transform() {
|
||||
// 读取文件列表
|
||||
const sqliteFiles = fs.readdirSync('./migration/');
|
||||
const pgFiles = fs.readdirSync('./migration-pg');
|
||||
//找出pg里面没有的文件
|
||||
const notFiles = sqliteFiles.filter(file => !pgFiles.includes(file));
|
||||
for (const notFile of notFiles) {
|
||||
//开始转换
|
||||
const sqliteSql = fs.readFileSync(`./migration/${notFile}`, 'utf-8');
|
||||
let pgSql = sqliteSql.replace(/AUTOINCREMENT/g, 'GENERATED BY DEFAULT AS IDENTITY');
|
||||
pgSql = pgSql.replace(/datetime/g, 'timestamp');
|
||||
pgSql = pgSql.replace(/boolean DEFAULT \(0\)/g, 'boolean DEFAULT (false)');
|
||||
pgSql = pgSql.replace(/integer/g, 'bigint');
|
||||
pgSql = pgSql.replace(/last_insert_rowid\(\)/g, 'LASTVAL()');
|
||||
fs.writeFileSync(`./migration-pg/${notFile}`, pgSql);
|
||||
}
|
||||
|
||||
if (notFiles.length > 0) {
|
||||
console.log('sqlite->pg 转换完成');
|
||||
|
||||
throw new Error('sqlite->pg 转换完成,有更新,需要测试pg');
|
||||
} else {
|
||||
console.log('sql无需更新');
|
||||
}
|
||||
}
|
||||
transform();
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@certd/ui-server",
|
||||
"version": "1.26.3",
|
||||
"version": "1.26.5",
|
||||
"description": "fast-server base midway",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
@@ -10,6 +10,9 @@
|
||||
"commdev": "cross-env NODE_ENV=commdev mwtsc --watch --run @midwayjs/mock/app",
|
||||
"commpro": "cross-env NODE_ENV=commpro mwtsc --watch --run @midwayjs/mock/app",
|
||||
"pgdev": "cross-env NODE_ENV=pgdev mwtsc --watch --run @midwayjs/mock/app",
|
||||
"pgpl": "cross-env NODE_ENV=pgpl mwtsc --watch --run @midwayjs/mock/app",
|
||||
"dev-new": "npm run rm-db-new && cross-env NODE_ENV=local mwtsc --watch --run @midwayjs/mock/app",
|
||||
"rm-db-new": "rimraf ./data/db-new.sqlite",
|
||||
"test": "cross-env NODE_ENV=unittest mocha",
|
||||
"cov": "cross-env c8 --all --reporter=text --reporter=lcovonly npm run test",
|
||||
"lint": "mwts check",
|
||||
@@ -19,22 +22,22 @@
|
||||
"dev-build": "echo 1",
|
||||
"build-on-docker": "node ./before-build.js && npm run build",
|
||||
"up-mw-deps": "npx midway-version -u -w",
|
||||
"heap": "clinic heapprofiler -- node ./bootstrap.js",
|
||||
"heap": "cross-env NODE_ENV=pgpl clinic heapprofiler -- node ./bootstrap.js",
|
||||
"flame": "clinic flame -- node ./bootstrap.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@alicloud/pop-core": "^1.7.10",
|
||||
"@certd/acme-client": "^1.26.3",
|
||||
"@certd/commercial-core": "^1.26.3",
|
||||
"@certd/lib-huawei": "^1.26.3",
|
||||
"@certd/lib-jdcloud": "^1.26.3",
|
||||
"@certd/lib-k8s": "^1.26.3",
|
||||
"@certd/lib-server": "^1.26.3",
|
||||
"@certd/midway-flyway-js": "^1.26.3",
|
||||
"@certd/pipeline": "^1.26.3",
|
||||
"@certd/plugin-cert": "^1.26.3",
|
||||
"@certd/plugin-plus": "^1.26.3",
|
||||
"@certd/plus-core": "^1.26.3",
|
||||
"@certd/acme-client": "^1.26.5",
|
||||
"@certd/commercial-core": "^1.26.5",
|
||||
"@certd/lib-huawei": "^1.26.5",
|
||||
"@certd/lib-jdcloud": "^1.26.5",
|
||||
"@certd/lib-k8s": "^1.26.5",
|
||||
"@certd/lib-server": "^1.26.5",
|
||||
"@certd/midway-flyway-js": "^1.26.5",
|
||||
"@certd/pipeline": "^1.26.5",
|
||||
"@certd/plugin-cert": "^1.26.5",
|
||||
"@certd/plugin-plus": "^1.26.5",
|
||||
"@certd/plus-core": "^1.26.5",
|
||||
"@koa/cors": "^5.0.0",
|
||||
"@midwayjs/bootstrap": "~3.17.1",
|
||||
"@midwayjs/cache": "~3.14.0",
|
||||
@@ -102,6 +105,7 @@
|
||||
"mocha": "^10.2.0",
|
||||
"mwts": "^1.3.0",
|
||||
"prettier": "^3.3.3",
|
||||
"rimraf": "^5.0.5",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
|
||||
@@ -66,7 +66,7 @@ const development = {
|
||||
type: 'better-sqlite3',
|
||||
database: './data/db.sqlite',
|
||||
synchronize: false, // 如果第一次使用,不存在表,有同步的需求可以写 true
|
||||
logging: false,
|
||||
logging: true,
|
||||
|
||||
// 配置实体模型 或者 entities: '/entity',
|
||||
entities: ['**/modules/**/entity/*.js', ...libServerEntities, ...commercialEntities, PipelineEntity, FlywayHistory, UserEntity],
|
||||
|
||||
@@ -5,7 +5,7 @@ import * as cache from '@midwayjs/cache';
|
||||
import * as validate from '@midwayjs/validate';
|
||||
import * as info from '@midwayjs/info';
|
||||
import * as staticFile from '@midwayjs/static-file';
|
||||
import * as cron from './modules/plugin/cron/index.js';
|
||||
import * as cron from './modules/cron/index.js';
|
||||
import * as flyway from '@certd/midway-flyway-js';
|
||||
import cors from '@koa/cors';
|
||||
import { GlobalExceptionMiddleware } from './middleware/global-exception.js';
|
||||
|
||||
@@ -3,8 +3,8 @@ import { ALL, Inject } from '@midwayjs/core';
|
||||
import { Body } from '@midwayjs/core';
|
||||
import { Controller, Post, Provide } from '@midwayjs/core';
|
||||
import { BaseController } from '@certd/lib-server';
|
||||
import { CodeService } from '../service/code-service.js';
|
||||
import { EmailService } from '../service/email-service.js';
|
||||
import { CodeService } from '../../modules/basic/service/code-service.js';
|
||||
import { EmailService } from '../../modules/basic/service/email-service.js';
|
||||
import { Constants } from '@certd/lib-server';
|
||||
export class SmsCodeReq {
|
||||
@Rule(RuleType.number().required())
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Body, Controller, Inject, Post, Provide } from '@midwayjs/core';
|
||||
import { BaseController } from '@certd/lib-server';
|
||||
import { EmailService } from '../service/email-service.js';
|
||||
import { EmailService } from '../../modules/basic/service/email-service.js';
|
||||
import { Constants } from '@certd/lib-server';
|
||||
|
||||
/**
|
||||
@@ -1,7 +1,7 @@
|
||||
import { ALL, Body, Controller, Inject, Post, Provide } from '@midwayjs/core';
|
||||
import { BaseController, Constants } from '@certd/lib-server';
|
||||
import { CnameRecordService } from '../service/cname-record-service.js';
|
||||
import { CnameProviderService } from '../../sys/cname/service/cname-provider-service.js';
|
||||
import { CnameRecordService } from '../../modules/cname/service/cname-record-service.js';
|
||||
import { CnameProviderService } from '../../modules/cname/service/cname-provider-service.js';
|
||||
|
||||
/**
|
||||
* 授权
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ALL, Body, Controller, Inject, Post, Provide, Query } from '@midwayjs/core';
|
||||
import { Constants, CrudController } from '@certd/lib-server';
|
||||
import { CnameRecordService } from '../service/cname-record-service.js';
|
||||
import { CnameRecordService } from '../../modules/cname/service/cname-record-service.js';
|
||||
|
||||
/**
|
||||
* 授权
|
||||
@@ -24,11 +24,16 @@ export class CnameRecordController extends CrudController<CnameRecordService> {
|
||||
|
||||
const bq = qb => {
|
||||
if (domain) {
|
||||
qb.where('domain like :domain', { domain: `%${domain}%` });
|
||||
qb.andWhere('domain like :domain', { domain: `%${domain}%` });
|
||||
}
|
||||
};
|
||||
|
||||
const pageRet = await this.getService().page(body?.query, body?.page, body?.sort, bq);
|
||||
const pageRet = await this.getService().page({
|
||||
query: body.query,
|
||||
page: body.page,
|
||||
order: body.order,
|
||||
buildQuery: bq,
|
||||
});
|
||||
return this.ok(pageRet);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Body, Controller, Inject, Post, Provide, ALL } from '@midwayjs/core';
|
||||
import { LoginService } from '../service/login-service.js';
|
||||
import { LoginService } from '../../modules/login/service/login-service.js';
|
||||
import { BaseController } from '@certd/lib-server';
|
||||
import { Constants } from '@certd/lib-server';
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { ALL, Body, Controller, Inject, Post, Provide } from '@midwayjs/core';
|
||||
import { BaseController } from '@certd/lib-server';
|
||||
import { Constants } from '@certd/lib-server';
|
||||
import { UserService } from '../../sys/authority/service/user-service.js';
|
||||
import { UserEntity } from '../../sys/authority/entity/user.js';
|
||||
import { UserService } from '../../modules/sys/authority/service/user-service.js';
|
||||
import { UserEntity } from '../../modules/sys/authority/entity/user.js';
|
||||
import { SysSettingsService } from '@certd/lib-server';
|
||||
|
||||
/**
|
||||
@@ -1,7 +1,7 @@
|
||||
import { ALL, Body, Controller, Inject, Post, Provide } from '@midwayjs/core';
|
||||
import { BaseController, Constants } from '@certd/lib-server';
|
||||
import { UserService } from '../../sys/authority/service/user-service.js';
|
||||
import { RoleService } from '../../sys/authority/service/role-service.js';
|
||||
import { UserService } from '../../modules/sys/authority/service/user-service.js';
|
||||
import { RoleService } from '../../modules/sys/authority/service/role-service.js';
|
||||
|
||||
/**
|
||||
*/
|
||||
@@ -1,8 +1,8 @@
|
||||
import { ALL, Body, Controller, Inject, Post, Provide, Query } from '@midwayjs/core';
|
||||
import { CrudController } from '@certd/lib-server';
|
||||
import { Constants } from '@certd/lib-server';
|
||||
import { UserSettingsService } from '../service/user-settings-service.js';
|
||||
import { UserSettingsEntity } from '../entity/user-settings.js';
|
||||
import { UserSettingsService } from '../../modules/mine/service/user-settings-service.js';
|
||||
import { UserSettingsEntity } from '../../modules/mine/entity/user-settings.js';
|
||||
|
||||
/**
|
||||
*/
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ALL, Body, Controller, Inject, Post, Provide, Query } from '@midwayjs/core';
|
||||
import { CrudController } from '@certd/lib-server';
|
||||
import { AccessService } from '../service/access-service.js';
|
||||
import { AccessService } from '../../modules/pipeline/service/access-service.js';
|
||||
import { Constants } from '@certd/lib-server';
|
||||
|
||||
/**
|
||||
@@ -19,8 +19,17 @@ export class AccessController extends CrudController<AccessService> {
|
||||
@Post('/page', { summary: Constants.per.authOnly })
|
||||
async page(@Body(ALL) body) {
|
||||
body.query = body.query ?? {};
|
||||
body.query.userId = this.getUserId();
|
||||
return await super.page(body);
|
||||
delete body.query.userId;
|
||||
const buildQuery = qb => {
|
||||
qb.andWhere('user_id = :userId', { userId: this.getUserId() });
|
||||
};
|
||||
const res = await this.service.page({
|
||||
query: body.query,
|
||||
page: body.page,
|
||||
order: body.order,
|
||||
buildQuery,
|
||||
});
|
||||
return this.ok(res);
|
||||
}
|
||||
|
||||
@Post('/list', { summary: Constants.per.authOnly })
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ALL, Controller, Inject, Post, Provide, Query } from '@midwayjs/core';
|
||||
import { DnsProviderService } from '../service/dns-provider-service.js';
|
||||
import { DnsProviderService } from '../../modules/pipeline/service/dns-provider-service.js';
|
||||
import { BaseController } from '@certd/lib-server';
|
||||
import { Constants } from '@certd/lib-server';
|
||||
|
||||
@@ -13,9 +13,9 @@ import {
|
||||
utils,
|
||||
} from '@certd/pipeline';
|
||||
import { BaseController } from '@certd/lib-server';
|
||||
import { AccessService } from '../service/access-service.js';
|
||||
import { EmailService } from '../../basic/service/email-service.js';
|
||||
import { AccessGetter } from '../service/access-getter.js';
|
||||
import { AccessService } from '../../modules/pipeline/service/access-service.js';
|
||||
import { EmailService } from '../../modules/basic/service/email-service.js';
|
||||
import { AccessGetter } from '../../modules/pipeline/service/access-getter.js';
|
||||
|
||||
@Provide()
|
||||
@Controller('/api/pi/handle')
|
||||
@@ -1,14 +1,14 @@
|
||||
import { ALL, Body, Controller, Get, Inject, Post, Provide, Query } from '@midwayjs/core';
|
||||
import { CommonException, Constants, CrudController, PermissionException } from '@certd/lib-server';
|
||||
import { PipelineEntity } from '../entity/pipeline.js';
|
||||
import { HistoryService } from '../service/history-service.js';
|
||||
import { HistoryLogService } from '../service/history-log-service.js';
|
||||
import { HistoryEntity } from '../entity/history.js';
|
||||
import { HistoryLogEntity } from '../entity/history-log.js';
|
||||
import { PipelineService } from '../service/pipeline-service.js';
|
||||
import { PipelineEntity } from '../../modules/pipeline/entity/pipeline.js';
|
||||
import { HistoryService } from '../../modules/pipeline/service/history-service.js';
|
||||
import { HistoryLogService } from '../../modules/pipeline/service/history-log-service.js';
|
||||
import { HistoryEntity } from '../../modules/pipeline/entity/history.js';
|
||||
import { HistoryLogEntity } from '../../modules/pipeline/entity/history-log.js';
|
||||
import { PipelineService } from '../../modules/pipeline/service/pipeline-service.js';
|
||||
import * as fs from 'fs';
|
||||
import { logger } from '@certd/pipeline';
|
||||
import { AuthService } from '../../sys/authority/service/auth-service.js';
|
||||
import { AuthService } from '../../modules/sys/authority/service/auth-service.js';
|
||||
import { SysSettingsService } from '@certd/lib-server';
|
||||
import { In } from 'typeorm';
|
||||
|
||||
@@ -48,21 +48,29 @@ export class HistoryController extends CrudController<HistoryService> {
|
||||
let pipelineIds: any = null;
|
||||
const pipelineTitle = body.query?.pipelineTitle;
|
||||
if (pipelineTitle) {
|
||||
const pipelines = await this.pipelineService.list(pipelineQuery, null, qb => {
|
||||
qb.where('title like :title', { title: `%${pipelineTitle}%` });
|
||||
const pipelines = await this.pipelineService.list({
|
||||
query: pipelineQuery,
|
||||
buildQuery: qb => {
|
||||
qb.andWhere('title like :title', { title: `%${pipelineTitle}%` });
|
||||
},
|
||||
});
|
||||
pipelineIds = pipelines.map(p => p.id);
|
||||
}
|
||||
|
||||
const buildQuery = qb => {
|
||||
if (pipelineIds) {
|
||||
qb.where({
|
||||
qb.andWhere({
|
||||
pipelineId: In(pipelineIds),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const res = await this.service.page(body?.query, body?.page, body?.sort, buildQuery);
|
||||
const res = await this.service.page({
|
||||
query: body.query,
|
||||
page: body.page,
|
||||
order: body.order,
|
||||
buildQuery,
|
||||
});
|
||||
return this.ok(res);
|
||||
}
|
||||
|
||||
@@ -78,7 +86,11 @@ export class HistoryController extends CrudController<HistoryService> {
|
||||
const buildQuery = qb => {
|
||||
qb.limit(10);
|
||||
};
|
||||
const listRet = await this.getService().list(body, { prop: 'id', asc: false }, buildQuery);
|
||||
const listRet = await this.getService().list({
|
||||
query: body,
|
||||
order: { prop: 'id', asc: false },
|
||||
buildQuery,
|
||||
});
|
||||
return this.ok(listRet);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { ALL, Body, Controller, Inject, Post, Provide, Query } from '@midwayjs/core';
|
||||
import { Constants, CrudController, SysSettingsService } from '@certd/lib-server';
|
||||
import { PipelineService } from '../service/pipeline-service.js';
|
||||
import { PipelineEntity } from '../entity/pipeline.js';
|
||||
import { HistoryService } from '../service/history-service.js';
|
||||
import { AuthService } from '../../sys/authority/service/auth-service.js';
|
||||
import { PipelineService } from '../../modules/pipeline/service/pipeline-service.js';
|
||||
import { PipelineEntity } from '../../modules/pipeline/entity/pipeline.js';
|
||||
import { HistoryService } from '../../modules/pipeline/service/history-service.js';
|
||||
import { AuthService } from '../../modules/sys/authority/service/auth-service.js';
|
||||
|
||||
/**
|
||||
* 证书
|
||||
@@ -37,14 +37,19 @@ export class PipelineController extends CrudController<PipelineService> {
|
||||
|
||||
const buildQuery = qb => {
|
||||
if (title) {
|
||||
qb.where('title like :title', { title: `%${title}%` });
|
||||
qb.andWhere('title like :title', { title: `%${title}%` });
|
||||
}
|
||||
};
|
||||
if (!body.sort || !body.sort?.prop) {
|
||||
body.sort = { prop: 'order', asc: false };
|
||||
}
|
||||
|
||||
const pageRet = await this.getService().page(body?.query, body?.page, body?.sort, buildQuery);
|
||||
const pageRet = await this.getService().page({
|
||||
query: body.query,
|
||||
page: body.page,
|
||||
order: body.order,
|
||||
buildQuery,
|
||||
});
|
||||
return this.ok(pageRet);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user