Compare commits

...

149 Commits

Author SHA1 Message Date
xiaojunnuo
f3a90a63b6 v1.36.14 2025-07-28 23:42:30 +08:00
xiaojunnuo
2494173aec build: prepare to build 2025-07-28 23:38:49 +08:00
xiaojunnuo
866eb6241b perf: 授权管理支持模糊查询 2025-07-28 23:36:10 +08:00
xiaojunnuo
86b3df1941 perf: 运行主机脚本插件支持选择运行策略 2025-07-28 23:22:38 +08:00
xiaojunnuo
e87f6d56f5 perf: cdnfly 支持 账号密码登陆授权 2025-07-28 23:20:44 +08:00
xiaojunnuo
acc890730f perf: 1panel支持 currenNode 2025-07-28 22:41:45 +08:00
xiaojunnuo
b0707739fd fix: 修复复制流水线为空的bug 2025-07-28 18:29:28 +08:00
xiaojunnuo
251dd1fe45 fix: 修复商用证书上传第二次运行无法使用pfx格式证书的bug 2025-07-28 16:18:49 +08:00
xiaojunnuo
b9f3dc65e0 chore: 雨云ref 2025-07-25 17:29:37 +08:00
xiaojunnuo
238ad7ce51 perf: 优化start脚本 2025-07-25 16:57:21 +08:00
xiaojunnuo
99fd5fca4d chore: 2025-07-25 12:05:42 +08:00
xiaojunnuo
8eda77b76d Merge branch 'v2' into v2-dev 2025-07-25 10:18:35 +08:00
ahe
81ac240ac8 perf: 新增找回密码功能 @nicheng-he
* feat 找回密码

* 1.发送邮件时修改模版
2.重置成功时清除登陆错误次数

* 增加自助找回密码控制

* 补充接口自助找回判断
2025-07-24 16:56:22 +08:00
xiaojunnuo
6109798fab chore: 2025-07-24 16:23:13 +08:00
xiaojunnuo
95715a007d perf: k8s ack、tke 支持重启ingress 2025-07-24 16:22:07 +08:00
xiaojunnuo
b33ec201ac build: publish 2025-07-23 23:41:46 +08:00
xiaojunnuo
b53fbaf5b3 build: trigger build image 2025-07-23 23:41:31 +08:00
xiaojunnuo
1e03a2e553 v1.36.13 2025-07-23 23:40:09 +08:00
xiaojunnuo
fda7c6f67a build: prepare to build 2025-07-23 23:37:57 +08:00
xiaojunnuo
fabb7982ff chore: 2025-07-23 17:55:08 +08:00
xiaojunnuo
cbf206be60 chore: 2025-07-23 17:41:16 +08:00
xiaojunnuo
aa0c282205 Merge branch 'v2' into v2-dev 2025-07-23 15:59:14 +08:00
xiaojunnuo
9759365329 Merge remote-tracking branch 'origin/v2' into v2 2025-07-23 15:56:09 +08:00
ahe
e3738f6422 perf: 阿里云部分插件优化 @nicheng-he
1.新增RemoteAutoComplete插件
2.阿里云OSS部署插件支持自动获取BucketList
3.阿里云ESA支持选择上传到阿里云CAS产物
4.解决阿里云OSS默认接入点配置错误问题
2025-07-23 15:55:52 +08:00
ahe
9746d169f9 阿里云部分插件优化 @nicheng-he
1.新增RemoteAutoComplete插件
2.阿里云OSS部署插件支持自动获取BucketList
3.阿里云ESA支持选择上传到阿里云CAS产物
4.解决阿里云OSS默认接入点配置错误问题
2025-07-23 15:45:40 +08:00
xiaojunnuo
2e6d03ff00 fix: 修复阿里云发送短信验证码失败的bug 2025-07-23 11:33:02 +08:00
xiaojunnuo
f7b7d3d65e build: publish 2025-07-23 00:18:48 +08:00
xiaojunnuo
4037cf11aa build: trigger build image 2025-07-23 00:18:32 +08:00
xiaojunnuo
02aeb321ce v1.36.12 2025-07-23 00:17:02 +08:00
xiaojunnuo
0012619257 build: prepare to build 2025-07-23 00:14:43 +08:00
xiaojunnuo
6f3ade0d94 Merge branch 'v2' into v2-dev 2025-07-23 00:13:58 +08:00
xiaojunnuo
cf572f328a Merge branch 'v2' into v2-dev 2025-07-23 00:13:29 +08:00
xiaojunnuo
d1ce36038c perf: 增加版本过低提示 2025-07-23 00:10:15 +08:00
xiaojunnuo
b382351c7b fix: 上传到阿里云cas,证书前缀无效的bug 2025-07-22 23:53:33 +08:00
xiaojunnuo
4e5e862f58 fix: 修复自定义插件onlyAdmin报错的bug 2025-07-22 23:31:42 +08:00
xiaojunnuo
ab84835362 perf: 部署到k8s,tke,ack忽悠证书校验 2025-07-22 17:03:52 +08:00
xiaojunnuo
41ce8489dc perf: 首页增加更新日志按钮 2025-07-22 16:42:17 +08:00
xiaojunnuo
ef3faf5832 Merge branch 'v2-dev' into v2 2025-07-22 12:27:51 +08:00
xiaojunnuo
edf089ec9e build: publish 2025-07-22 12:27:21 +08:00
xiaojunnuo
0ae9a3605c build: trigger build image 2025-07-22 12:27:10 +08:00
xiaojunnuo
7f9c4e52ac v1.36.11 2025-07-22 12:25:40 +08:00
xiaojunnuo
35947f96a8 build: prepare to build 2025-07-22 12:23:42 +08:00
xiaojunnuo
b0f91f1eea chore: 2025-07-22 12:22:54 +08:00
xiaojunnuo
13dfca1749 fix: 安全更新,备份数据库插件仅限管理员运行 2025-07-22 11:51:27 +08:00
xiaojunnuo
9d9cd8a362 build: 2025-07-19 12:02:08 +08:00
xiaojunnuo
5e5c41fda5 build: 2025-07-19 12:01:47 +08:00
xiaojunnuo
3ebdc52b3e build: 2025-07-19 08:58:02 +08:00
xiaojunnuo
af54f48cec Merge branch 'v2-dev' into v2 2025-07-18 23:14:52 +08:00
xiaojunnuo
8656059151 build: publish 2025-07-18 23:09:44 +08:00
xiaojunnuo
a6d38f2458 build: trigger build image 2025-07-18 23:09:27 +08:00
xiaojunnuo
085bdf5cfa v1.36.10 2025-07-18 23:08:03 +08:00
xiaojunnuo
6883bcacee build: prepare to build 2025-07-18 23:02:57 +08:00
xiaojunnuo
2ecc6e0368 build: prepare to build 2025-07-18 23:00:39 +08:00
xiaojunnuo
8fb5ca2fe1 chore: ip检查新旧ip变化对比逻辑修复 2025-07-18 18:24:01 +08:00
xiaojunnuo
e40345095f perf: 账号即将过期通知 2025-07-18 18:18:01 +08:00
xiaojunnuo
ffc0c7bb7b perf: 子域名托管重复域名不允许添加 2025-07-18 16:36:56 +08:00
xiaojunnuo
58fadc8928 chore: 2025-07-18 16:32:19 +08:00
xiaojunnuo
d96a607c04 chore: 2025-07-18 16:00:34 +08:00
xiaojunnuo
2ea2c8c05f perf: 部署到阿里云oss插件支持选择上传到阿里云cas中的证书 2025-07-18 15:35:35 +08:00
xiaojunnuo
b15f514018 perf: 优化子域名托管的说明 2025-07-18 14:47:15 +08:00
xiaojunnuo
05a33a0ec9 fix: api接口获取不到证书的bug 2025-07-18 14:46:58 +08:00
xiaojunnuo
747d266742 fix: 企业微信通知改成text类型,因为markdown类型不支持@用户 2025-07-15 17:15:43 +08:00
xiaojunnuo
522d30545b Merge branch 'v2-dev' into v2 2025-07-15 16:56:31 +08:00
xiaojunnuo
6135a44a8d build: publish 2025-07-15 16:54:52 +08:00
xiaojunnuo
7c7d646792 build: trigger build image 2025-07-15 16:54:35 +08:00
xiaojunnuo
4a36fd2ec3 v1.36.9 2025-07-15 16:53:06 +08:00
xiaojunnuo
b1bcc287cb build: prepare to build 2025-07-15 16:46:42 +08:00
xiaojunnuo
6f5868a9d7 build: prepare to build 2025-07-15 16:43:58 +08:00
xiaojunnuo
75863441f4 build: prepare to build 2025-07-15 16:41:37 +08:00
xiaojunnuo
9763cb00e5 fix: 修复ssh无法执行命令的bug 2025-07-15 16:41:15 +08:00
xiaojunnuo
521599ef39 Merge branch 'v2-dev' into v2 2025-07-15 15:47:46 +08:00
xiaojunnuo
1921a64f4b build: publish 2025-07-15 15:36:31 +08:00
xiaojunnuo
6b73f5d555 build: trigger build image 2025-07-15 15:36:14 +08:00
xiaojunnuo
e0408f30ba v1.36.7 2025-07-15 15:33:36 +08:00
xiaojunnuo
dca44fa093 build: prepare to build 2025-07-15 15:21:52 +08:00
xiaojunnuo
bbacb76581 build: prepare to build 2025-07-15 15:19:18 +08:00
xiaojunnuo
1da8617a53 perf: 支持上传证书到各种对象存储,oss、cos、七牛、s3、minio等 2025-07-15 15:18:35 +08:00
xiaojunnuo
e5967f7e9d chore: 2025-07-15 15:17:11 +08:00
xiaojunnuo
65d84f9e9d chore: 2025-07-15 15:06:59 +08:00
xiaojunnuo
93e9498b41 fix: 修复流水线页面状态没有刷新的bug 2025-07-15 15:05:09 +08:00
xiaojunnuo
95332d5db9 perf: 支持邮箱发送证书 2025-07-15 13:58:01 +08:00
xiaojunnuo
9864792bbf fix: 修复流水线列表页报length错误的bug 2025-07-15 10:53:11 +08:00
xiaojunnuo
ca9d1eed7a Merge remote-tracking branch 'origin/v2-dev' into v2-dev 2025-07-15 10:45:34 +08:00
xiaojunnuo
38e867c917 fix: 修复自定义证书检查时间重启之后不生效的bug 2025-07-15 10:42:56 +08:00
xiaojunnuo
1ff6daaa27 Merge branch 'v2-dev' into v2 2025-07-14 23:55:04 +08:00
xiaojunnuo
3ee1dbb8a5 build: publish 2025-07-14 23:54:12 +08:00
xiaojunnuo
b4571d5c98 build: trigger build image 2025-07-14 23:53:51 +08:00
xiaojunnuo
29d49d72f9 v1.36.6 2025-07-14 23:52:25 +08:00
xiaojunnuo
81de0fc7e4 build: prepare to build 2025-07-14 23:48:40 +08:00
xiaojunnuo
9d5d266d2a build: prepare to build 2025-07-14 23:46:40 +08:00
xiaojunnuo
b97935299f chore: auto功能 数据库升级脚本 2025-07-14 23:46:24 +08:00
xiaojunnuo
32a7ea1c16 chore: 2025-07-14 23:29:35 +08:00
xiaojunnuo
9fd95e6a1e chore: 2025-07-14 23:26:54 +08:00
xiaojunnuo
61ba83c775 perf: 通知和定时器的删除按钮显示为红色更显眼 2025-07-14 23:25:56 +08:00
xiaojunnuo
6369fed5fc chore: 2025-07-14 23:15:22 +08:00
xiaojunnuo
42f4d1477d perf: OpenAPI支持autoApply参数 2025-07-14 23:02:47 +08:00
xiaojunnuo
609ac9c9a2 perf: 优化流水线列表页面、详情页面性能,精简返回数据 2025-07-14 01:36:40 +08:00
xiaojunnuo
79f2367472 chore: 2025-07-14 00:34:47 +08:00
xiaojunnuo
dfc9362084 fix: 修复运行流水线后会闪烁一下的bug 2025-07-14 00:33:42 +08:00
xiaojunnuo
487b469603 chore: 增强cname安全性 2025-07-14 00:15:46 +08:00
xiaojunnuo
19e1df1e5d chore: 2025-07-13 23:58:07 +08:00
xiaojunnuo
fc55010888 Merge branch 'v2-dev-auto' into v2-dev 2025-07-13 23:23:47 +08:00
xiaojunnuo
56a36aa595 chore: 修复商业版翻译导致报错的bug 2025-07-13 23:20:04 +08:00
xiaojunnuo
0b3158fdd5 fix: 修复某些页面翻译不全显示错误的bug 2025-07-13 23:14:28 +08:00
xiaojunnuo
896cd950e9 chore: auto 2025-07-13 23:08:00 +08:00
xiaojunnuo
af5e1b805f chore: 2025-07-13 18:30:04 +08:00
xiaojunnuo
3f9943270c perf: 支持自动选择校验方式申请证书 2025-07-13 18:25:09 +08:00
xiaojunnuo
902d246d1a perf: 部署plesk证书,支持删除未使用的证书 2025-07-13 17:10:15 +08:00
xiaojunnuo
785bee2b39 chore: auto 2025-07-12 23:00:04 +08:00
xiaojunnuo
4b335db31c chore: 2025-07-11 18:17:11 +08:00
xiaojunnuo
4bef527ebb Merge branch 'v2-dev' into v2-dev-auto
# Conflicts:
#	packages/ui/certd-client/src/locales/langs/en-US/certd.ts
#	packages/ui/certd-client/src/locales/langs/zh-CN/certd.ts
2025-07-11 17:44:04 +08:00
xiaojunnuo
8273031d7e docs: 自动升级帮助文档 2025-07-11 17:37:33 +08:00
xiaojunnuo
dbf69bcd98 chore: 2025-07-11 11:11:22 +08:00
xiaojunnuo
24d3096752 build: publish 2025-07-11 10:51:21 +08:00
xiaojunnuo
9a3754fbf8 build: trigger build image 2025-07-11 10:51:05 +08:00
xiaojunnuo
c2a95a13fe v1.36.5 2025-07-11 10:49:26 +08:00
xiaojunnuo
b46466ac96 build: prepare to build 2025-07-11 10:46:08 +08:00
xiaojunnuo
06991ddb17 chore: 2025-07-11 10:44:49 +08:00
xiaojunnuo
4b3f4a868a fix: 某些插件找不到的bug 2025-07-11 09:45:33 +08:00
xiaojunnuo
014eff3534 build: publish 2025-07-10 23:42:44 +08:00
xiaojunnuo
c01b7ddb59 build: trigger build image 2025-07-10 23:42:27 +08:00
xiaojunnuo
0ff700849f v1.36.4 2025-07-10 23:41:05 +08:00
xiaojunnuo
5c695dea20 build: prepare to build 2025-07-10 23:36:24 +08:00
xiaojunnuo
c7ee4ca4db build: prepare to build 2025-07-10 23:32:50 +08:00
xiaojunnuo
c3da026b33 perf: 支持部署证书到网宿CDN 2025-07-10 23:30:33 +08:00
xiaojunnuo
98da4e1791 perf: 支持部署到阿里云vod 2025-07-10 21:40:35 +08:00
xiaojunnuo
8626b6d9f2 fix: 修复查看证书对话框翻译错误的bug 2025-07-10 18:27:56 +08:00
xiaojunnuo
80c5331a5d perf: 站点证书即将过期通知标题颜色优化为红色 2025-07-10 17:02:48 +08:00
xiaojunnuo
39dc5c8160 chore: domain manager 2025-07-10 17:00:47 +08:00
xiaojunnuo
f3002e4fb6 chore: domain manager 2025-07-10 16:32:12 +08:00
xiaojunnuo
c451823c2b chore: chore: auto domain entity 2025-07-09 16:00:55 +08:00
xiaojunnuo
b37cffd704 fix: 执行windows nginx命令时,改为return code判断是否执行成功 2025-07-09 15:43:25 +08:00
xiaojunnuo
2af91dbf2a perf: 优化证书进度条颜色 2025-07-09 15:24:23 +08:00
xiaojunnuo
f2551318fc chore: 增加多dns提供商选项支持 2025-07-09 15:10:21 +08:00
xiaojunnuo
22eb84f944 chore: 2025-07-09 15:03:04 +08:00
xiaojunnuo
1ece0915f1 perf: 重置管理员密码同时可以清除管理员的2FA设置 2025-07-09 14:49:11 +08:00
xiaojunnuo
87853a2015 perf: output-selector from参数支持更丰富的过滤规则
规则:  pluginName:valueType:keyName
2025-07-09 14:34:24 +08:00
xiaojunnuo
46a1b74799 fix: 修复translation后分组编辑打不开的bug 2025-07-09 11:14:09 +08:00
xiaojunnuo
0f6e7e5eab build: publish 2025-07-07 22:22:09 +08:00
xiaojunnuo
5dfa9615d2 build: trigger build image 2025-07-07 22:21:52 +08:00
xiaojunnuo
1bde777bee v1.36.3 2025-07-07 22:20:26 +08:00
xiaojunnuo
fa4f5df3e7 build: prepare to build 2025-07-07 22:18:24 +08:00
xiaojunnuo
8a3c3810e0 build: prepare to build 2025-07-07 22:14:35 +08:00
xiaojunnuo
144532530a perf: 优化部署到腾讯TKE插件,支持Opaque类型选择,优化填写说明 2025-07-07 21:30:45 +08:00
xiaojunnuo
0f1129e19b chore: 2025-07-07 18:20:25 +08:00
xiaojunnuo
1f74580f15 chore: cname的key转为小写 2025-07-07 16:27:25 +08:00
xiaojunnuo
f93ba9970c fix: 修复开放接口添加按钮文本显示问题 2025-07-07 14:21:00 +08:00
xiaojunnuo
f87a3d0892 build: publish 2025-07-07 00:47:44 +08:00
xiaojunnuo
c661ad67d0 build: trigger build image 2025-07-07 00:47:26 +08:00
236 changed files with 6003 additions and 1412 deletions

View File

@@ -3,6 +3,133 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.36.14](https://github.com/certd/certd/compare/v1.36.13...v1.36.14) (2025-07-28)
### Bug Fixes
* 修复复制流水线为空的bug ([b070773](https://github.com/certd/certd/commit/b0707739fdfbae3d78db4efd3f180db05c4e4164))
* 修复商用证书上传第二次运行无法使用pfx格式证书的bug ([251dd1f](https://github.com/certd/certd/commit/251dd1fe457a7b152f43eb6de18f7beb9f0b194e))
### Performance Improvements
* 1panel支持 currenNode ([acc8907](https://github.com/certd/certd/commit/acc890730f43d492c9b1bd3668814cf10efdf7b8))
* 授权管理支持模糊查询 ([866eb62](https://github.com/certd/certd/commit/866eb6241baa7b21f6eddc649966324c188236c6))
* 新增找回密码功能 [@nicheng-he](https://github.com/nicheng-he) ([81ac240](https://github.com/certd/certd/commit/81ac240ac84db0af2f56b6352e227ecb49f38377))
* 优化start脚本 ([238ad7c](https://github.com/certd/certd/commit/238ad7ce51f17e1098c624e7f61ee2d98de1e02d))
* 运行主机脚本插件支持选择运行策略 ([86b3df1](https://github.com/certd/certd/commit/86b3df194126476e1f58e0952a77e986f62eecce))
* cdnfly 支持 账号密码登陆授权 ([e87f6d5](https://github.com/certd/certd/commit/e87f6d56f524dbbb9e3243e382b348b6e49f0d2c))
* k8s ack、tke 支持重启ingress ([95715a0](https://github.com/certd/certd/commit/95715a007d931c64fa7dd953d94957398e00a443))
## [1.36.13](https://github.com/certd/certd/compare/v1.36.12...v1.36.13) (2025-07-23)
### Bug Fixes
* 修复阿里云发送短信验证码失败的bug ([2e6d03f](https://github.com/certd/certd/commit/2e6d03ff001f521f57368e7a62b97ed7b122e8d0))
### Performance Improvements
* 阿里云部分插件优化 [@nicheng-he](https://github.com/nicheng-he) ([e3738f6](https://github.com/certd/certd/commit/e3738f6422270d75ec414c15a343248cc4cad6e1))
## [1.36.12](https://github.com/certd/certd/compare/v1.36.11...v1.36.12) (2025-07-22)
### Bug Fixes
* 上传到阿里云cas证书前缀无效的bug ([b382351](https://github.com/certd/certd/commit/b382351c7b91ec10e1f61d94bec5aad075207ec8))
* 修复自定义插件onlyAdmin报错的bug ([4e5e862](https://github.com/certd/certd/commit/4e5e862f5834ad180e4428959c272d444a6f78ab))
### Performance Improvements
* 部署到k8stkeack忽悠证书校验 ([ab84835](https://github.com/certd/certd/commit/ab848353621869464a2c9a45fdb5e28d998b8a58))
* 首页增加更新日志按钮 ([41ce848](https://github.com/certd/certd/commit/41ce8489dc2f03a705dfa3fbb357769defb56c60))
* 增加版本过低提示 ([d1ce360](https://github.com/certd/certd/commit/d1ce36038cab72b5dc1b320d0a708c261ffbdacb))
## [1.36.11](https://github.com/certd/certd/compare/v1.36.10...v1.36.11) (2025-07-22)
### Bug Fixes
* 安全更新,备份数据库插件仅限管理员运行 ([13dfca1](https://github.com/certd/certd/commit/13dfca1749275526c82465a17c482b607c820fdd))
## [1.36.10](https://github.com/certd/certd/compare/v1.36.9...v1.36.10) (2025-07-18)
### Bug Fixes
* 企业微信通知改成text类型因为markdown类型不支持@用户 ([747d266](https://github.com/certd/certd/commit/747d26674248082e678a3fd5ecc94712641a2716))
* api接口获取不到证书的bug ([05a33a0](https://github.com/certd/certd/commit/05a33a0ec9999e2802f6c7b23cc1c61a2b9e963d))
### Performance Improvements
* 部署到阿里云oss插件支持选择上传到阿里云cas中的证书 ([2ea2c8c](https://github.com/certd/certd/commit/2ea2c8c05fc40f79595f1bbde67c1413558bf684))
* 优化子域名托管的说明 ([b15f514](https://github.com/certd/certd/commit/b15f514018b728acb0922ee3f93c1f302eb5d471))
* 账号即将过期通知 ([e403450](https://github.com/certd/certd/commit/e40345095f31e2fb8e2333a6647466659133fa0c))
* 子域名托管重复域名不允许添加 ([ffc0c7b](https://github.com/certd/certd/commit/ffc0c7bb7b16d9904fd2d905d1c4e1d4854e92a9))
## [1.36.9](https://github.com/certd/certd/compare/v1.36.7...v1.36.9) (2025-07-15)
### Bug Fixes
* 修复ssh无法执行命令的bug ([9763cb0](https://github.com/certd/certd/commit/9763cb00e5d95b2fa5d1c2d3d4a8eecac71600e6))
## [1.36.7](https://github.com/certd/certd/compare/v1.36.6...v1.36.7) (2025-07-15)
### Bug Fixes
* 修复流水线列表页报length错误的bug ([9864792](https://github.com/certd/certd/commit/9864792bbfd149e770d6e1ffa809573694f99dd3))
* 修复流水线页面状态没有刷新的bug ([93e9498](https://github.com/certd/certd/commit/93e9498b410353f504e11e264db62468895d7290))
* 修复自定义证书检查时间重启之后不生效的bug ([38e867c](https://github.com/certd/certd/commit/38e867c917bbc68bd228bdd8064f3e7358d6413d))
### Performance Improvements
* 支持上传证书到各种对象存储oss、cos、七牛、s3、minio等 ([1da8617](https://github.com/certd/certd/commit/1da8617a53a675776635bbc3bcb3c6d7dff83e27))
* 支持邮箱发送证书 ([95332d5](https://github.com/certd/certd/commit/95332d5db96cd54ddab6ab737332417a09169b39))
## [1.36.6](https://github.com/certd/certd/compare/v1.36.5...v1.36.6) (2025-07-14)
### Bug Fixes
* 修复某些页面翻译不全显示错误的bug ([0b3158f](https://github.com/certd/certd/commit/0b3158fdd5fe5bb0a98c4e65715dbc3de2c38047))
* 修复运行流水线后会闪烁一下的bug ([dfc9362](https://github.com/certd/certd/commit/dfc9362084082ee535b898f23b2609c1d946a6fd))
### Performance Improvements
* 部署plesk证书支持删除未使用的证书 ([902d246](https://github.com/certd/certd/commit/902d246d1a7473ad90f604028c4eb09c8c67d99c))
* 通知和定时器的删除按钮显示为红色更显眼 ([61ba83c](https://github.com/certd/certd/commit/61ba83c77546c3d505d081e19a3d68c127662bf1))
* 优化流水线列表页面、详情页面性能,精简返回数据 ([609ac9c](https://github.com/certd/certd/commit/609ac9c9a2dde605eb09834ae59693c1cb238765))
* 支持自动选择校验方式申请证书 ([3f99432](https://github.com/certd/certd/commit/3f9943270cfb12946e38e6272bc5e8d95ad6ab9e))
* OpenAPI支持autoApply参数 ([42f4d14](https://github.com/certd/certd/commit/42f4d1477dc791520a874aed56035abcbc8c433b))
## [1.36.5](https://github.com/certd/certd/compare/v1.36.4...v1.36.5) (2025-07-11)
### Bug Fixes
* 某些插件找不到的bug ([4b3f4a8](https://github.com/certd/certd/commit/4b3f4a868a8b0800c5c59de9d0f47bddc079e7b3))
## [1.36.4](https://github.com/certd/certd/compare/v1.36.3...v1.36.4) (2025-07-10)
### Bug Fixes
* 修复查看证书对话框翻译错误的bug ([8626b6d](https://github.com/certd/certd/commit/8626b6d9f235c511766f2ae98e0a37f6cebb621c))
* 修复translation后分组编辑打不开的bug ([46a1b74](https://github.com/certd/certd/commit/46a1b7479923d2feb2dece202a5932b99981b2cd))
* 执行windows nginx命令时改为return code判断是否执行成功 ([b37cffd](https://github.com/certd/certd/commit/b37cffd704cd08b8bdd68a6e284706eabe59e78d))
### Performance Improvements
* 优化证书进度条颜色 ([2af91db](https://github.com/certd/certd/commit/2af91dbf2ae36a4ed17c6788bc2a2a79a3bb29f8))
* 站点证书即将过期通知标题颜色优化为红色 ([80c5331](https://github.com/certd/certd/commit/80c5331a5d4c320323d9b9b800e4ea3b72577b33))
* 支持部署到阿里云vod ([98da4e1](https://github.com/certd/certd/commit/98da4e1791ed8bb21daf2a9914fda875d14633c9))
* 支持部署证书到网宿CDN ([c3da026](https://github.com/certd/certd/commit/c3da026b33106f5195959825a68cadbe49efef00))
* 重置管理员密码同时可以清除管理员的2FA设置 ([1ece091](https://github.com/certd/certd/commit/1ece0915f172d5f8b8adb866434e7efcc5c8c46d))
* output-selector from参数支持更丰富的过滤规则 ([87853a2](https://github.com/certd/certd/commit/87853a201535f3bfe8505c40f8f5229d82ffcc73))
## [1.36.3](https://github.com/certd/certd/compare/v1.36.2...v1.36.3) (2025-07-07)
### Bug Fixes
* 修复开放接口添加按钮文本显示问题 ([f93ba99](https://github.com/certd/certd/commit/f93ba9970c12680f38eba2a7abd4b72cf3f5b6a6))
### Performance Improvements
* 优化部署到腾讯TKE插件支持Opaque类型选择优化填写说明 ([1445325](https://github.com/certd/certd/commit/144532530a865b634e68539e4888e26f52f73492))
## [1.36.2](https://github.com/certd/certd/compare/v1.36.1...v1.36.2) (2025-07-06)
### Bug Fixes

View File

@@ -16,7 +16,6 @@ Certd® 是一个免费的全自动证书管理系统,让你的网站证书永
> 流水线数量现已调整为无限制,欢迎大家使用
## 一、特性
本项目不仅支持证书申请过程自动化,还可以自动化部署更新证书,让你的证书永不过期。
@@ -87,8 +86,8 @@ https://certd.handfree.work/
1. 【推荐】[Docker方式部署 ](https://certd.docmirror.cn/guide/install/docker/)
2. 【推荐】[宝塔面板方式部署 ](https://certd.docmirror.cn/guide/install/docker/)
3. 【推荐】[1Panel面板方式部署](https://certd.docmirror.cn/guide/install/1panel/)
4. 【推荐】[雨云一键部署](https://app.rainyun.com/apps/rca/store/6646/?ref=NzExMDQ2_) 首充翻倍每月仅需2.2元
[<img src="https://rainyun-apps.cn-nb1.rains3.com/materials/deploy-on-rainyun-cn.svg">](https://app.rainyun.com/apps/rca/store/6646/?ref=NzExMDQ2_)
4. 【推荐】[雨云一键部署](https://app.rainyun.com/apps/rca/store/6646/?ref=NzExMDQ2) 首充翻倍每月仅需2.2元
[<img src="https://rainyun-apps.cn-nb1.rains3.com/materials/deploy-on-rainyun-cn.svg">](https://app.rainyun.com/apps/rca/store/6646/?ref=NzExMDQ2)
5. 【不推荐】[源码方式部署 ](https://certd.docmirror.cn/guide/install/source/)
#### Docker镜像说明

View File

@@ -1 +1 @@
23:01
23:41

View File

@@ -3,6 +3,127 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.36.13](https://github.com/certd/certd/compare/v1.36.12...v1.36.13) (2025-07-23)
### Bug Fixes
* 修复阿里云发送短信验证码失败的bug ([2e6d03f](https://github.com/certd/certd/commit/2e6d03ff001f521f57368e7a62b97ed7b122e8d0))
### Performance Improvements
* 阿里云部分插件优化 [@nicheng-he](https://github.com/nicheng-he) ([e3738f6](https://github.com/certd/certd/commit/e3738f6422270d75ec414c15a343248cc4cad6e1))
## [1.36.12](https://github.com/certd/certd/compare/v1.36.11...v1.36.12) (2025-07-22)
### Bug Fixes
* 上传到阿里云cas证书前缀无效的bug ([b382351](https://github.com/certd/certd/commit/b382351c7b91ec10e1f61d94bec5aad075207ec8))
* 修复自定义插件onlyAdmin报错的bug ([4e5e862](https://github.com/certd/certd/commit/4e5e862f5834ad180e4428959c272d444a6f78ab))
### Performance Improvements
* 部署到k8stkeack忽悠证书校验 ([ab84835](https://github.com/certd/certd/commit/ab848353621869464a2c9a45fdb5e28d998b8a58))
* 首页增加更新日志按钮 ([41ce848](https://github.com/certd/certd/commit/41ce8489dc2f03a705dfa3fbb357769defb56c60))
* 增加版本过低提示 ([d1ce360](https://github.com/certd/certd/commit/d1ce36038cab72b5dc1b320d0a708c261ffbdacb))
## [1.36.11](https://github.com/certd/certd/compare/v1.36.10...v1.36.11) (2025-07-22)
### Bug Fixes
* 安全更新,备份数据库插件仅限管理员运行 ([13dfca1](https://github.com/certd/certd/commit/13dfca1749275526c82465a17c482b607c820fdd))
## [1.36.10](https://github.com/certd/certd/compare/v1.36.9...v1.36.10) (2025-07-18)
### Bug Fixes
* 企业微信通知改成text类型因为markdown类型不支持@用户 ([747d266](https://github.com/certd/certd/commit/747d26674248082e678a3fd5ecc94712641a2716))
* api接口获取不到证书的bug ([05a33a0](https://github.com/certd/certd/commit/05a33a0ec9999e2802f6c7b23cc1c61a2b9e963d))
### Performance Improvements
* 部署到阿里云oss插件支持选择上传到阿里云cas中的证书 ([2ea2c8c](https://github.com/certd/certd/commit/2ea2c8c05fc40f79595f1bbde67c1413558bf684))
* 优化子域名托管的说明 ([b15f514](https://github.com/certd/certd/commit/b15f514018b728acb0922ee3f93c1f302eb5d471))
* 账号即将过期通知 ([e403450](https://github.com/certd/certd/commit/e40345095f31e2fb8e2333a6647466659133fa0c))
* 子域名托管重复域名不允许添加 ([ffc0c7b](https://github.com/certd/certd/commit/ffc0c7bb7b16d9904fd2d905d1c4e1d4854e92a9))
## [1.36.9](https://github.com/certd/certd/compare/v1.36.7...v1.36.9) (2025-07-15)
### Bug Fixes
* 修复ssh无法执行命令的bug ([9763cb0](https://github.com/certd/certd/commit/9763cb00e5d95b2fa5d1c2d3d4a8eecac71600e6))
## [1.36.7](https://github.com/certd/certd/compare/v1.36.6...v1.36.7) (2025-07-15)
### Bug Fixes
* 修复流水线列表页报length错误的bug ([9864792](https://github.com/certd/certd/commit/9864792bbfd149e770d6e1ffa809573694f99dd3))
* 修复流水线页面状态没有刷新的bug ([93e9498](https://github.com/certd/certd/commit/93e9498b410353f504e11e264db62468895d7290))
* 修复自定义证书检查时间重启之后不生效的bug ([38e867c](https://github.com/certd/certd/commit/38e867c917bbc68bd228bdd8064f3e7358d6413d))
### Performance Improvements
* 支持上传证书到各种对象存储oss、cos、七牛、s3、minio等 ([1da8617](https://github.com/certd/certd/commit/1da8617a53a675776635bbc3bcb3c6d7dff83e27))
* 支持邮箱发送证书 ([95332d5](https://github.com/certd/certd/commit/95332d5db96cd54ddab6ab737332417a09169b39))
## [1.36.6](https://github.com/certd/certd/compare/v1.36.5...v1.36.6) (2025-07-14)
### Bug Fixes
* 修复某些页面翻译不全显示错误的bug ([0b3158f](https://github.com/certd/certd/commit/0b3158fdd5fe5bb0a98c4e65715dbc3de2c38047))
* 修复运行流水线后会闪烁一下的bug ([dfc9362](https://github.com/certd/certd/commit/dfc9362084082ee535b898f23b2609c1d946a6fd))
### Performance Improvements
* 部署plesk证书支持删除未使用的证书 ([902d246](https://github.com/certd/certd/commit/902d246d1a7473ad90f604028c4eb09c8c67d99c))
* 通知和定时器的删除按钮显示为红色更显眼 ([61ba83c](https://github.com/certd/certd/commit/61ba83c77546c3d505d081e19a3d68c127662bf1))
* 优化流水线列表页面、详情页面性能,精简返回数据 ([609ac9c](https://github.com/certd/certd/commit/609ac9c9a2dde605eb09834ae59693c1cb238765))
* 支持自动选择校验方式申请证书 ([3f99432](https://github.com/certd/certd/commit/3f9943270cfb12946e38e6272bc5e8d95ad6ab9e))
* OpenAPI支持autoApply参数 ([42f4d14](https://github.com/certd/certd/commit/42f4d1477dc791520a874aed56035abcbc8c433b))
## [1.36.5](https://github.com/certd/certd/compare/v1.36.4...v1.36.5) (2025-07-11)
### Bug Fixes
* 某些插件找不到的bug ([4b3f4a8](https://github.com/certd/certd/commit/4b3f4a868a8b0800c5c59de9d0f47bddc079e7b3))
## [1.36.4](https://github.com/certd/certd/compare/v1.36.3...v1.36.4) (2025-07-10)
### Bug Fixes
* 修复查看证书对话框翻译错误的bug ([8626b6d](https://github.com/certd/certd/commit/8626b6d9f235c511766f2ae98e0a37f6cebb621c))
* 修复translation后分组编辑打不开的bug ([46a1b74](https://github.com/certd/certd/commit/46a1b7479923d2feb2dece202a5932b99981b2cd))
* 执行windows nginx命令时改为return code判断是否执行成功 ([b37cffd](https://github.com/certd/certd/commit/b37cffd704cd08b8bdd68a6e284706eabe59e78d))
### Performance Improvements
* 优化证书进度条颜色 ([2af91db](https://github.com/certd/certd/commit/2af91dbf2ae36a4ed17c6788bc2a2a79a3bb29f8))
* 站点证书即将过期通知标题颜色优化为红色 ([80c5331](https://github.com/certd/certd/commit/80c5331a5d4c320323d9b9b800e4ea3b72577b33))
* 支持部署到阿里云vod ([98da4e1](https://github.com/certd/certd/commit/98da4e1791ed8bb21daf2a9914fda875d14633c9))
* 支持部署证书到网宿CDN ([c3da026](https://github.com/certd/certd/commit/c3da026b33106f5195959825a68cadbe49efef00))
* 重置管理员密码同时可以清除管理员的2FA设置 ([1ece091](https://github.com/certd/certd/commit/1ece0915f172d5f8b8adb866434e7efcc5c8c46d))
* output-selector from参数支持更丰富的过滤规则 ([87853a2](https://github.com/certd/certd/commit/87853a201535f3bfe8505c40f8f5229d82ffcc73))
## [1.36.3](https://github.com/certd/certd/compare/v1.36.2...v1.36.3) (2025-07-07)
### Bug Fixes
* 修复开放接口添加按钮文本显示问题 ([f93ba99](https://github.com/certd/certd/commit/f93ba9970c12680f38eba2a7abd4b72cf3f5b6a6))
### Performance Improvements
* 优化部署到腾讯TKE插件支持Opaque类型选择优化填写说明 ([1445325](https://github.com/certd/certd/commit/144532530a865b634e68539e4888e26f52f73492))
## [1.36.2](https://github.com/certd/certd/compare/v1.36.1...v1.36.2) (2025-07-06)
### Bug Fixes
* 修复notification编辑按钮无法打开对话框的bug ([0cea26c](https://github.com/certd/certd/commit/0cea26c6287f52adf273b4a525c37bea8555c68c))
* 优化更新飞牛os证书有效期修复某些情况下部署证书后飞牛无法访问https的bug ([610c919](https://github.com/certd/certd/commit/610c919c72037becc0ed326f5d5b18c963dfcb3a))
### Performance Improvements
* 证书检查支持自定义dns服务器 ([c53bb7c](https://github.com/certd/certd/commit/c53bb7cf677faa32729709ae0c10359db5194d7a))
## [1.36.1](https://github.com/certd/certd/compare/v1.36.0...v1.36.1) (2025-07-02)
### Bug Fixes

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -4,7 +4,7 @@
## 一、源码安装
### 环境要求
- nodejs 20 及以上
- nodejs 22 及以上
### 源码启动
```shell
# 克隆代码

View File

@@ -13,4 +13,54 @@
:::
## 升级日志
可以查看最新版本号,以及所有版本的更新日志
[CHANGELOG](../changelogs/CHANGELOG.md)
## 自动升级配置
### 1. 方法一使用watchtower监控
修改docker-compose.yaml文件增加如下配置 使用watchtower监控自动升级
```yaml
services:
certd:
...
labels:
com.centurylinklabs.watchtower.enable: "true"
# ↓↓↓↓ --------------------------------------------------------- 自动升级上面certd的版本号要保持为latest
certd-updater: # 添加 Watchtower 服务
image: containrrr/watchtower:latest
container_name: certd-updater
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock
# 配置 自动更新
environment:
- WATCHTOWER_CLEANUP=true # 自动清理旧版本容器
- WATCHTOWER_INCLUDE_STOPPED=false # 不更新已停止的容器
- WATCHTOWER_LABEL_ENABLE=true # 根据容器标签进行更新
- WATCHTOWER_POLL_INTERVAL=600 # 每 10 分钟检查一次更新
```
### 2. 方法二使用Certd版本监控功能
选择Github-检查Release版本插件
![](./images/github-release.png)
按如下图填写配置
![](./images/github-release-2.png)
检测到新版本后执行宿主机升级命令:
```shell
# 拉取最新镜像
docker pull registry.cn-shenzhen.aliyuncs.com/handsfree/certd:latest
# 升级容器命令, 替换成你自己的certd更新命令
export RESTART_CERT='sleep 10; cd ~/deploy/certd/ ; docker compose down; docker compose up -d'
# 构造一个脚本10s后在后台执行避免容器销毁时执行太快导致流水线任务无法结束
nohup sh -c '$RESTART_CERT' >/dev/null 2>&1 & echo '10秒后重启' && exit
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

View File

@@ -8,8 +8,11 @@
![](./tencent-access.png)
## 如何避免收到腾讯云证书过期邮件
> 新版本已经自动将证书设置为免提醒certd上传的证书后续都不会再提醒了。
腾讯云在证书有效期还剩28天时会发送过期通知邮件
您可以通过配置“腾讯云过期证书删除”任务来避免收到此类邮件。
@@ -18,4 +21,17 @@
注意点:
> 1. 选择腾讯云授权,需授权`服务角色SSL_QCSLinkedRoleInReplaceLoadCertificate`权限
> 2. `1.26.14`版本之前Certd创建的证书流水线默认是到期前20天才更新证书需要将之前创建的证书申请任务的更新天数修改为35天保证删除之前就已经替换掉即将过期证书
![](./images/delete2.png)
![](./images/delete2.png)
## TKE service 的 TCP_SSL Opaque类型证书授权
部署证书到腾讯云TKE如果报以下错误
`is forbidden: User "xxxxxx-xxxxx" cannot get resource "secrets" in API group "" in the namespace "default"'`
则需要单独从授权管理侧再授权子用户的权限
![](./images/tcpssl.png)
![](./images/opaque.png)

View File

@@ -9,5 +9,5 @@
}
},
"npmClient": "pnpm",
"version": "1.36.2"
"version": "1.36.14"
}

View File

@@ -28,6 +28,7 @@
"deploy1": "node --experimental-json-modules deploy.js ",
"check": "node --experimental-json-modules publish-check.js",
"init": "lerna run build",
"init:dev": "lerna run build",
"docs:dev": "vitepress dev docs",
"docs:build": "vitepress build docs",
"docs:preview": "vitepress preview docs",
@@ -35,6 +36,7 @@
},
"license": "AGPL-3.0",
"dependencies": {
"@certd/ui-server": "link:packages/ui/certd-server",
"axios": "^1.7.7",
"copyfiles": "^2.4.1",
"lodash-es": "^4.17.21",

View File

@@ -3,6 +3,50 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.36.14](https://github.com/publishlab/node-acme-client/compare/v1.36.13...v1.36.14) (2025-07-28)
**Note:** Version bump only for package @certd/acme-client
## [1.36.13](https://github.com/publishlab/node-acme-client/compare/v1.36.12...v1.36.13) (2025-07-23)
**Note:** Version bump only for package @certd/acme-client
## [1.36.12](https://github.com/publishlab/node-acme-client/compare/v1.36.11...v1.36.12) (2025-07-22)
**Note:** Version bump only for package @certd/acme-client
## [1.36.11](https://github.com/publishlab/node-acme-client/compare/v1.36.10...v1.36.11) (2025-07-22)
**Note:** Version bump only for package @certd/acme-client
## [1.36.10](https://github.com/publishlab/node-acme-client/compare/v1.36.9...v1.36.10) (2025-07-18)
**Note:** Version bump only for package @certd/acme-client
## [1.36.9](https://github.com/publishlab/node-acme-client/compare/v1.36.7...v1.36.9) (2025-07-15)
**Note:** Version bump only for package @certd/acme-client
## [1.36.7](https://github.com/publishlab/node-acme-client/compare/v1.36.6...v1.36.7) (2025-07-15)
**Note:** Version bump only for package @certd/acme-client
## [1.36.6](https://github.com/publishlab/node-acme-client/compare/v1.36.5...v1.36.6) (2025-07-14)
**Note:** Version bump only for package @certd/acme-client
## [1.36.5](https://github.com/publishlab/node-acme-client/compare/v1.36.4...v1.36.5) (2025-07-11)
**Note:** Version bump only for package @certd/acme-client
## [1.36.4](https://github.com/publishlab/node-acme-client/compare/v1.36.3...v1.36.4) (2025-07-10)
**Note:** Version bump only for package @certd/acme-client
## [1.36.3](https://github.com/publishlab/node-acme-client/compare/v1.36.2...v1.36.3) (2025-07-07)
**Note:** Version bump only for package @certd/acme-client
## [1.36.2](https://github.com/publishlab/node-acme-client/compare/v1.36.1...v1.36.2) (2025-07-06)
**Note:** Version bump only for package @certd/acme-client

View File

@@ -3,7 +3,7 @@
"description": "Simple and unopinionated ACME client",
"private": false,
"author": "nmorsman",
"version": "1.36.2",
"version": "1.36.14",
"type": "module",
"module": "scr/index.js",
"main": "src/index.js",
@@ -18,7 +18,7 @@
"types"
],
"dependencies": {
"@certd/basic": "^1.36.2",
"@certd/basic": "^1.36.14",
"@peculiar/x509": "^1.11.0",
"asn1js": "^3.0.5",
"axios": "^1.7.2",
@@ -69,5 +69,5 @@
"bugs": {
"url": "https://github.com/publishlab/node-acme-client/issues"
},
"gitHead": "8671887abcdfb93a7ecb709f223bd6add6f03c67"
"gitHead": "1e03a2e553aa94982453a477d2a0d35a565b6270"
}

View File

@@ -3,6 +3,50 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.36.14](https://github.com/certd/certd/compare/v1.36.13...v1.36.14) (2025-07-28)
**Note:** Version bump only for package @certd/basic
## [1.36.13](https://github.com/certd/certd/compare/v1.36.12...v1.36.13) (2025-07-23)
**Note:** Version bump only for package @certd/basic
## [1.36.12](https://github.com/certd/certd/compare/v1.36.11...v1.36.12) (2025-07-22)
**Note:** Version bump only for package @certd/basic
## [1.36.11](https://github.com/certd/certd/compare/v1.36.10...v1.36.11) (2025-07-22)
**Note:** Version bump only for package @certd/basic
## [1.36.10](https://github.com/certd/certd/compare/v1.36.9...v1.36.10) (2025-07-18)
**Note:** Version bump only for package @certd/basic
## [1.36.9](https://github.com/certd/certd/compare/v1.36.7...v1.36.9) (2025-07-15)
**Note:** Version bump only for package @certd/basic
## [1.36.7](https://github.com/certd/certd/compare/v1.36.6...v1.36.7) (2025-07-15)
**Note:** Version bump only for package @certd/basic
## [1.36.6](https://github.com/certd/certd/compare/v1.36.5...v1.36.6) (2025-07-14)
**Note:** Version bump only for package @certd/basic
## [1.36.5](https://github.com/certd/certd/compare/v1.36.4...v1.36.5) (2025-07-11)
**Note:** Version bump only for package @certd/basic
## [1.36.4](https://github.com/certd/certd/compare/v1.36.3...v1.36.4) (2025-07-10)
**Note:** Version bump only for package @certd/basic
## [1.36.3](https://github.com/certd/certd/compare/v1.36.2...v1.36.3) (2025-07-07)
**Note:** Version bump only for package @certd/basic
## [1.36.2](https://github.com/certd/certd/compare/v1.36.1...v1.36.2) (2025-07-06)
### Performance Improvements

View File

@@ -1 +1 @@
00:43
23:38

View File

@@ -1,7 +1,7 @@
{
"name": "@certd/basic",
"private": false,
"version": "1.36.2",
"version": "1.36.14",
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
@@ -45,5 +45,5 @@
"tslib": "^2.8.1",
"typescript": "^5.4.2"
},
"gitHead": "8671887abcdfb93a7ecb709f223bd6add6f03c67"
"gitHead": "1e03a2e553aa94982453a477d2a0d35a565b6270"
}

View File

@@ -3,6 +3,56 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.36.14](https://github.com/certd/certd/compare/v1.36.13...v1.36.14) (2025-07-28)
**Note:** Version bump only for package @certd/pipeline
## [1.36.13](https://github.com/certd/certd/compare/v1.36.12...v1.36.13) (2025-07-23)
**Note:** Version bump only for package @certd/pipeline
## [1.36.12](https://github.com/certd/certd/compare/v1.36.11...v1.36.12) (2025-07-22)
### Bug Fixes
* 修复自定义插件onlyAdmin报错的bug ([4e5e862](https://github.com/certd/certd/commit/4e5e862f5834ad180e4428959c272d444a6f78ab))
## [1.36.11](https://github.com/certd/certd/compare/v1.36.10...v1.36.11) (2025-07-22)
### Bug Fixes
* 安全更新,备份数据库插件仅限管理员运行 ([13dfca1](https://github.com/certd/certd/commit/13dfca1749275526c82465a17c482b607c820fdd))
## [1.36.10](https://github.com/certd/certd/compare/v1.36.9...v1.36.10) (2025-07-18)
**Note:** Version bump only for package @certd/pipeline
## [1.36.9](https://github.com/certd/certd/compare/v1.36.7...v1.36.9) (2025-07-15)
**Note:** Version bump only for package @certd/pipeline
## [1.36.7](https://github.com/certd/certd/compare/v1.36.6...v1.36.7) (2025-07-15)
### Performance Improvements
* 支持邮箱发送证书 ([95332d5](https://github.com/certd/certd/commit/95332d5db96cd54ddab6ab737332417a09169b39))
## [1.36.6](https://github.com/certd/certd/compare/v1.36.5...v1.36.6) (2025-07-14)
**Note:** Version bump only for package @certd/pipeline
## [1.36.5](https://github.com/certd/certd/compare/v1.36.4...v1.36.5) (2025-07-11)
**Note:** Version bump only for package @certd/pipeline
## [1.36.4](https://github.com/certd/certd/compare/v1.36.3...v1.36.4) (2025-07-10)
**Note:** Version bump only for package @certd/pipeline
## [1.36.3](https://github.com/certd/certd/compare/v1.36.2...v1.36.3) (2025-07-07)
**Note:** Version bump only for package @certd/pipeline
## [1.36.2](https://github.com/certd/certd/compare/v1.36.1...v1.36.2) (2025-07-06)
**Note:** Version bump only for package @certd/pipeline

View File

@@ -1,7 +1,7 @@
{
"name": "@certd/pipeline",
"private": false,
"version": "1.36.2",
"version": "1.36.14",
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
@@ -17,8 +17,8 @@
"pub": "npm publish"
},
"dependencies": {
"@certd/basic": "^1.36.2",
"@certd/plus-core": "^1.36.1",
"@certd/basic": "^1.36.14",
"@certd/plus-core": "^1.36.14",
"dayjs": "^1.11.7",
"lodash-es": "^4.17.21",
"reflect-metadata": "^0.1.13"
@@ -44,5 +44,5 @@
"tslib": "^2.8.1",
"typescript": "^5.4.2"
},
"gitHead": "8671887abcdfb93a7ecb709f223bd6add6f03c67"
"gitHead": "1e03a2e553aa94982453a477d2a0d35a565b6270"
}

View File

@@ -352,6 +352,7 @@ export class Executor {
pipeline: this.pipeline,
runtime: this.runtime,
step,
define: cloneDeep(define),
lastStatus,
http,
download,

View File

@@ -59,6 +59,7 @@ export type PluginDefine = Registrable & {
form: any;
};
};
onlyAdmin?: boolean;
needPlus?: boolean;
showRunStrategy?: boolean;
pluginType?: string; //类型
@@ -85,6 +86,7 @@ export type TaskInstanceContext = {
runtime: RunHistory;
//步骤定义
step: Step;
define: PluginDefine;
//日志
logger: ILogger;
//当前步骤输入参数跟上一次执行比较是否有变化
@@ -162,6 +164,12 @@ export abstract class AbstractTaskPlugin implements ITaskPlugin {
this.registerSecret(cert.key);
this.registerSecret(cert.one);
}
if (this.ctx?.define?.onlyAdmin) {
if (!this.isAdmin()) {
throw new Error("只有管理员才能运行此任务");
}
}
}
async getAccess<T = any>(accessId: string | number, isCommon = false) {

View File

@@ -30,4 +30,5 @@ export const pluginGroups = {
qiniu: new PluginGroup("qiniu", "七牛云", 5, "svg:icon-qiniuyun"),
aws: new PluginGroup("aws", "亚马逊云", 6, "svg:icon-aws"),
other: new PluginGroup("other", "其他", 10, "clarity:plugin-line"),
admin: new PluginGroup("admin", "管理", 11, "ion:settings-outline"),
};

View File

@@ -1,7 +1,9 @@
export type EmailSend = {
subject: string;
content: string;
receivers: string[];
content?: string;
attachments?: any[];
html?: string;
};
export interface IEmailService {

View File

@@ -3,6 +3,50 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.36.14](https://github.com/certd/certd/compare/v1.36.13...v1.36.14) (2025-07-28)
**Note:** Version bump only for package @certd/lib-huawei
## [1.36.13](https://github.com/certd/certd/compare/v1.36.12...v1.36.13) (2025-07-23)
**Note:** Version bump only for package @certd/lib-huawei
## [1.36.12](https://github.com/certd/certd/compare/v1.36.11...v1.36.12) (2025-07-22)
**Note:** Version bump only for package @certd/lib-huawei
## [1.36.11](https://github.com/certd/certd/compare/v1.36.10...v1.36.11) (2025-07-22)
**Note:** Version bump only for package @certd/lib-huawei
## [1.36.10](https://github.com/certd/certd/compare/v1.36.9...v1.36.10) (2025-07-18)
**Note:** Version bump only for package @certd/lib-huawei
## [1.36.9](https://github.com/certd/certd/compare/v1.36.7...v1.36.9) (2025-07-15)
**Note:** Version bump only for package @certd/lib-huawei
## [1.36.7](https://github.com/certd/certd/compare/v1.36.6...v1.36.7) (2025-07-15)
**Note:** Version bump only for package @certd/lib-huawei
## [1.36.6](https://github.com/certd/certd/compare/v1.36.5...v1.36.6) (2025-07-14)
**Note:** Version bump only for package @certd/lib-huawei
## [1.36.5](https://github.com/certd/certd/compare/v1.36.4...v1.36.5) (2025-07-11)
**Note:** Version bump only for package @certd/lib-huawei
## [1.36.4](https://github.com/certd/certd/compare/v1.36.3...v1.36.4) (2025-07-10)
**Note:** Version bump only for package @certd/lib-huawei
## [1.36.3](https://github.com/certd/certd/compare/v1.36.2...v1.36.3) (2025-07-07)
**Note:** Version bump only for package @certd/lib-huawei
## [1.36.2](https://github.com/certd/certd/compare/v1.36.1...v1.36.2) (2025-07-06)
**Note:** Version bump only for package @certd/lib-huawei

View File

@@ -1,7 +1,7 @@
{
"name": "@certd/lib-huawei",
"private": false,
"version": "1.36.2",
"version": "1.36.14",
"main": "./dist/bundle.js",
"module": "./dist/bundle.js",
"types": "./dist/d/index.d.ts",
@@ -24,5 +24,5 @@
"prettier": "^2.8.8",
"tslib": "^2.8.1"
},
"gitHead": "8671887abcdfb93a7ecb709f223bd6add6f03c67"
"gitHead": "1e03a2e553aa94982453a477d2a0d35a565b6270"
}

View File

@@ -3,6 +3,50 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.36.14](https://github.com/certd/certd/compare/v1.36.13...v1.36.14) (2025-07-28)
**Note:** Version bump only for package @certd/lib-iframe
## [1.36.13](https://github.com/certd/certd/compare/v1.36.12...v1.36.13) (2025-07-23)
**Note:** Version bump only for package @certd/lib-iframe
## [1.36.12](https://github.com/certd/certd/compare/v1.36.11...v1.36.12) (2025-07-22)
**Note:** Version bump only for package @certd/lib-iframe
## [1.36.11](https://github.com/certd/certd/compare/v1.36.10...v1.36.11) (2025-07-22)
**Note:** Version bump only for package @certd/lib-iframe
## [1.36.10](https://github.com/certd/certd/compare/v1.36.9...v1.36.10) (2025-07-18)
**Note:** Version bump only for package @certd/lib-iframe
## [1.36.9](https://github.com/certd/certd/compare/v1.36.7...v1.36.9) (2025-07-15)
**Note:** Version bump only for package @certd/lib-iframe
## [1.36.7](https://github.com/certd/certd/compare/v1.36.6...v1.36.7) (2025-07-15)
**Note:** Version bump only for package @certd/lib-iframe
## [1.36.6](https://github.com/certd/certd/compare/v1.36.5...v1.36.6) (2025-07-14)
**Note:** Version bump only for package @certd/lib-iframe
## [1.36.5](https://github.com/certd/certd/compare/v1.36.4...v1.36.5) (2025-07-11)
**Note:** Version bump only for package @certd/lib-iframe
## [1.36.4](https://github.com/certd/certd/compare/v1.36.3...v1.36.4) (2025-07-10)
**Note:** Version bump only for package @certd/lib-iframe
## [1.36.3](https://github.com/certd/certd/compare/v1.36.2...v1.36.3) (2025-07-07)
**Note:** Version bump only for package @certd/lib-iframe
## [1.36.2](https://github.com/certd/certd/compare/v1.36.1...v1.36.2) (2025-07-06)
**Note:** Version bump only for package @certd/lib-iframe

View File

@@ -1,7 +1,7 @@
{
"name": "@certd/lib-iframe",
"private": false,
"version": "1.36.2",
"version": "1.36.14",
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
@@ -31,5 +31,5 @@
"tslib": "^2.8.1",
"typescript": "^5.4.2"
},
"gitHead": "8671887abcdfb93a7ecb709f223bd6add6f03c67"
"gitHead": "1e03a2e553aa94982453a477d2a0d35a565b6270"
}

View File

@@ -3,6 +3,50 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.36.14](https://github.com/certd/certd/compare/v1.36.13...v1.36.14) (2025-07-28)
**Note:** Version bump only for package @certd/jdcloud
## [1.36.13](https://github.com/certd/certd/compare/v1.36.12...v1.36.13) (2025-07-23)
**Note:** Version bump only for package @certd/jdcloud
## [1.36.12](https://github.com/certd/certd/compare/v1.36.11...v1.36.12) (2025-07-22)
**Note:** Version bump only for package @certd/jdcloud
## [1.36.11](https://github.com/certd/certd/compare/v1.36.10...v1.36.11) (2025-07-22)
**Note:** Version bump only for package @certd/jdcloud
## [1.36.10](https://github.com/certd/certd/compare/v1.36.9...v1.36.10) (2025-07-18)
**Note:** Version bump only for package @certd/jdcloud
## [1.36.9](https://github.com/certd/certd/compare/v1.36.7...v1.36.9) (2025-07-15)
**Note:** Version bump only for package @certd/jdcloud
## [1.36.7](https://github.com/certd/certd/compare/v1.36.6...v1.36.7) (2025-07-15)
**Note:** Version bump only for package @certd/jdcloud
## [1.36.6](https://github.com/certd/certd/compare/v1.36.5...v1.36.6) (2025-07-14)
**Note:** Version bump only for package @certd/jdcloud
## [1.36.5](https://github.com/certd/certd/compare/v1.36.4...v1.36.5) (2025-07-11)
**Note:** Version bump only for package @certd/jdcloud
## [1.36.4](https://github.com/certd/certd/compare/v1.36.3...v1.36.4) (2025-07-10)
**Note:** Version bump only for package @certd/jdcloud
## [1.36.3](https://github.com/certd/certd/compare/v1.36.2...v1.36.3) (2025-07-07)
**Note:** Version bump only for package @certd/jdcloud
## [1.36.2](https://github.com/certd/certd/compare/v1.36.1...v1.36.2) (2025-07-06)
**Note:** Version bump only for package @certd/jdcloud

View File

@@ -1,6 +1,6 @@
{
"name": "@certd/jdcloud",
"version": "1.36.2",
"version": "1.36.14",
"description": "jdcloud openApi sdk",
"main": "./dist/bundle.js",
"module": "./dist/bundle.js",
@@ -61,5 +61,5 @@
"fetch"
]
},
"gitHead": "8671887abcdfb93a7ecb709f223bd6add6f03c67"
"gitHead": "1e03a2e553aa94982453a477d2a0d35a565b6270"
}

View File

@@ -3,6 +3,54 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.36.14](https://github.com/certd/certd/compare/v1.36.13...v1.36.14) (2025-07-28)
### Performance Improvements
* k8s ack、tke 支持重启ingress ([95715a0](https://github.com/certd/certd/commit/95715a007d931c64fa7dd953d94957398e00a443))
## [1.36.13](https://github.com/certd/certd/compare/v1.36.12...v1.36.13) (2025-07-23)
**Note:** Version bump only for package @certd/lib-k8s
## [1.36.12](https://github.com/certd/certd/compare/v1.36.11...v1.36.12) (2025-07-22)
### Performance Improvements
* 部署到k8stkeack忽悠证书校验 ([ab84835](https://github.com/certd/certd/commit/ab848353621869464a2c9a45fdb5e28d998b8a58))
## [1.36.11](https://github.com/certd/certd/compare/v1.36.10...v1.36.11) (2025-07-22)
**Note:** Version bump only for package @certd/lib-k8s
## [1.36.10](https://github.com/certd/certd/compare/v1.36.9...v1.36.10) (2025-07-18)
**Note:** Version bump only for package @certd/lib-k8s
## [1.36.9](https://github.com/certd/certd/compare/v1.36.7...v1.36.9) (2025-07-15)
**Note:** Version bump only for package @certd/lib-k8s
## [1.36.7](https://github.com/certd/certd/compare/v1.36.6...v1.36.7) (2025-07-15)
**Note:** Version bump only for package @certd/lib-k8s
## [1.36.6](https://github.com/certd/certd/compare/v1.36.5...v1.36.6) (2025-07-14)
**Note:** Version bump only for package @certd/lib-k8s
## [1.36.5](https://github.com/certd/certd/compare/v1.36.4...v1.36.5) (2025-07-11)
**Note:** Version bump only for package @certd/lib-k8s
## [1.36.4](https://github.com/certd/certd/compare/v1.36.3...v1.36.4) (2025-07-10)
**Note:** Version bump only for package @certd/lib-k8s
## [1.36.3](https://github.com/certd/certd/compare/v1.36.2...v1.36.3) (2025-07-07)
**Note:** Version bump only for package @certd/lib-k8s
## [1.36.2](https://github.com/certd/certd/compare/v1.36.1...v1.36.2) (2025-07-06)
**Note:** Version bump only for package @certd/lib-k8s

View File

@@ -1,7 +1,7 @@
{
"name": "@certd/lib-k8s",
"private": false,
"version": "1.36.2",
"version": "1.36.14",
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
@@ -17,7 +17,7 @@
"pub": "npm publish"
},
"dependencies": {
"@certd/basic": "^1.36.2",
"@certd/basic": "^1.36.14",
"@kubernetes/client-node": "0.21.0"
},
"devDependencies": {
@@ -32,5 +32,5 @@
"tslib": "^2.8.1",
"typescript": "^5.4.2"
},
"gitHead": "8671887abcdfb93a7ecb709f223bd6add6f03c67"
"gitHead": "1e03a2e553aa94982453a477d2a0d35a565b6270"
}

View File

@@ -1 +1 @@
export * from './lib/k8s.client.js';
export * from "./lib/k8s.client.js";

View File

@@ -1,7 +1,7 @@
import { CoreV1Api, KubeConfig, NetworkingV1Api, V1Ingress, V1Secret } from '@kubernetes/client-node';
import dns from 'dns';
import { ILogger } from '@certd/basic';
import _ from 'lodash-es';
import { CoreV1Api, KubeConfig, NetworkingV1Api, V1Ingress, V1Secret } from "@kubernetes/client-node";
import dns from "dns";
import { ILogger } from "@certd/basic";
import _ from "lodash-es";
export type K8sClientOpts = {
kubeConfigStr: string;
@@ -9,6 +9,7 @@ export type K8sClientOpts = {
//{ [domain]:{ip:'xxx.xx.xxx'} }
//暂时没用
lookup?: any;
skipTLSVerify?: boolean;
};
export class K8sClient {
kubeconfig!: KubeConfig;
@@ -16,10 +17,12 @@ export class K8sClient {
lookup!: (hostnameReq: any, options: any, callback: any) => void;
client!: CoreV1Api;
logger: ILogger;
skipTLSVerify?: boolean;
constructor(opts: K8sClientOpts) {
this.kubeConfigStr = opts.kubeConfigStr;
this.logger = opts.logger;
this.setLookup(opts.lookup);
this.skipTLSVerify = opts.skipTLSVerify;
this.init();
}
@@ -27,6 +30,18 @@ export class K8sClient {
const kubeconfig = new KubeConfig();
kubeconfig.loadFromString(this.kubeConfigStr);
this.kubeconfig = kubeconfig;
try {
if (this.skipTLSVerify == true) {
for (const cluster of kubeconfig.getClusters()) {
// @ts-ignore
cluster["skipTLSVerify"] = this.skipTLSVerify;
}
}
} catch (e) {
this.logger.warn("skipTLSVerify error", e);
}
this.client = kubeconfig.makeApiClient(CoreV1Api);
// const reqOpts = { kubeconfig, request: {} } as any;
@@ -47,9 +62,9 @@ export class K8sClient {
return;
}
this.lookup = (hostnameReq: any, options: any, callback: any) => {
this.logger.info('custom lookup', hostnameReq, localRecords);
this.logger.info("custom lookup", hostnameReq, localRecords);
if (localRecords[hostnameReq]) {
this.logger.info('local record', hostnameReq, localRecords[hostnameReq]);
this.logger.info("local record", hostnameReq, localRecords[hostnameReq]);
callback(null, localRecords[hostnameReq].ip, 4);
} else {
dns.lookup(hostnameReq, options, callback);
@@ -63,7 +78,7 @@ export class K8sClient {
* @returns secretsList
*/
async getSecrets(opts: { namespace: string }) {
const namespace = opts.namespace || 'default';
const namespace = opts.namespace || "default";
return await this.client.listNamespacedSecret(namespace);
}
@@ -73,9 +88,9 @@ export class K8sClient {
* @returns {Promise<*>}
*/
async createSecret(opts: { namespace: string; body: V1Secret }) {
const namespace = opts.namespace || 'default';
const namespace = opts.namespace || "default";
const created = await this.client.createNamespacedSecret(namespace, opts.body);
this.logger.info('new secrets:', opts.body);
this.logger.info("new secrets:", opts.body);
return created.body;
}
@@ -89,24 +104,24 @@ export class K8sClient {
// }
async patchSecret(opts: { namespace: string; secretName: string; body: V1Secret }) {
const namespace = opts.namespace || 'default';
const namespace = opts.namespace || "default";
const secretName = opts.secretName;
if (secretName == null) {
throw new Error('secretName 不能为空');
throw new Error("secretName 不能为空");
}
this.logger.info('patch secret:', secretName, namespace);
this.logger.info("patch secret:", secretName, namespace);
const oldSecret = await this.client.readNamespacedSecret(secretName, namespace);
const newSecret = _.merge(oldSecret.body, opts.body);
const res = await this.client.replaceNamespacedSecret(secretName, namespace, newSecret);
this.logger.info('secret updated');
this.logger.info("secret updated");
return res.body;
}
async getIngressList(opts: { namespace: string }) {
const namespace = opts.namespace || 'default';
const namespace = opts.namespace || "default";
const client = this.kubeconfig.makeApiClient(NetworkingV1Api);
const res = await client.listNamespacedIngress(namespace);
this.logger.info('ingress list get:', res.body);
this.logger.info("ingress list get:", res.body);
return res.body;
}
@@ -122,17 +137,31 @@ export class K8sClient {
// }
async patchIngress(opts: { namespace: string; ingressName: string; body: V1Ingress }) {
const namespace = opts.namespace || 'default';
const namespace = opts.namespace || "default";
const ingressName = opts.ingressName;
if (!ingressName) {
throw new Error('ingressName 不能为空');
throw new Error("ingressName 不能为空");
}
this.logger.info('patch ingress:', ingressName, namespace);
this.logger.info("patch ingress:", ingressName, namespace);
const client = this.kubeconfig.makeApiClient(NetworkingV1Api);
const oldIngress = await client.readNamespacedIngress(ingressName, namespace);
const newIngress = _.merge(oldIngress.body, opts.body);
const res = await client.replaceNamespacedIngress(ingressName, namespace, newIngress);
this.logger.info('ingress patched', opts.body);
this.logger.info("ingress patched", opts.body);
return res;
}
async restartIngress(namespace: string, ingressNames: string[], labels: any) {
const body = {
metadata: {
labels: {
...labels,
},
},
};
for (const ingress of ingressNames) {
await this.patchIngress({ namespace, ingressName: ingress, body });
this.logger.info(`ingress已重启:${ingress}`);
}
}
}

View File

@@ -3,6 +3,55 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.36.14](https://github.com/certd/certd/compare/v1.36.13...v1.36.14) (2025-07-28)
### Performance Improvements
* 新增找回密码功能 [@nicheng-he](https://github.com/nicheng-he) ([81ac240](https://github.com/certd/certd/commit/81ac240ac84db0af2f56b6352e227ecb49f38377))
## [1.36.13](https://github.com/certd/certd/compare/v1.36.12...v1.36.13) (2025-07-23)
**Note:** Version bump only for package @certd/lib-server
## [1.36.12](https://github.com/certd/certd/compare/v1.36.11...v1.36.12) (2025-07-22)
**Note:** Version bump only for package @certd/lib-server
## [1.36.11](https://github.com/certd/certd/compare/v1.36.10...v1.36.11) (2025-07-22)
**Note:** Version bump only for package @certd/lib-server
## [1.36.10](https://github.com/certd/certd/compare/v1.36.9...v1.36.10) (2025-07-18)
**Note:** Version bump only for package @certd/lib-server
## [1.36.9](https://github.com/certd/certd/compare/v1.36.7...v1.36.9) (2025-07-15)
**Note:** Version bump only for package @certd/lib-server
## [1.36.7](https://github.com/certd/certd/compare/v1.36.6...v1.36.7) (2025-07-15)
**Note:** Version bump only for package @certd/lib-server
## [1.36.6](https://github.com/certd/certd/compare/v1.36.5...v1.36.6) (2025-07-14)
### Performance Improvements
* 优化流水线列表页面、详情页面性能,精简返回数据 ([609ac9c](https://github.com/certd/certd/commit/609ac9c9a2dde605eb09834ae59693c1cb238765))
* OpenAPI支持autoApply参数 ([42f4d14](https://github.com/certd/certd/commit/42f4d1477dc791520a874aed56035abcbc8c433b))
## [1.36.5](https://github.com/certd/certd/compare/v1.36.4...v1.36.5) (2025-07-11)
**Note:** Version bump only for package @certd/lib-server
## [1.36.4](https://github.com/certd/certd/compare/v1.36.3...v1.36.4) (2025-07-10)
**Note:** Version bump only for package @certd/lib-server
## [1.36.3](https://github.com/certd/certd/compare/v1.36.2...v1.36.3) (2025-07-07)
**Note:** Version bump only for package @certd/lib-server
## [1.36.2](https://github.com/certd/certd/compare/v1.36.1...v1.36.2) (2025-07-06)
**Note:** Version bump only for package @certd/lib-server

View File

@@ -1,6 +1,6 @@
{
"name": "@certd/lib-server",
"version": "1.36.2",
"version": "1.36.14",
"description": "midway with flyway, sql upgrade way ",
"private": false,
"type": "module",
@@ -27,10 +27,10 @@
],
"license": "AGPL",
"dependencies": {
"@certd/acme-client": "^1.36.2",
"@certd/basic": "^1.36.2",
"@certd/pipeline": "^1.36.2",
"@certd/plus-core": "^1.36.1",
"@certd/acme-client": "^1.36.14",
"@certd/basic": "^1.36.14",
"@certd/pipeline": "^1.36.14",
"@certd/plus-core": "^1.36.14",
"@midwayjs/cache": "~3.14.0",
"@midwayjs/core": "~3.20.3",
"@midwayjs/i18n": "~3.20.3",
@@ -61,5 +61,5 @@
"typeorm": "^0.3.11",
"typescript": "^5.4.2"
},
"gitHead": "8671887abcdfb93a7ecb709f223bd6add6f03c67"
"gitHead": "1e03a2e553aa94982453a477d2a0d35a565b6270"
}

View File

@@ -164,8 +164,11 @@ export abstract class BaseService<T> {
}
private buildListQuery(listReq: ListReq<T>) {
const { query, sort, buildQuery } = listReq;
const { query, sort, buildQuery,select } = listReq;
const qb = this.getRepository().createQueryBuilder('main');
if (select) {
qb.setFindOptions({select});
}
if (query) {
const keys = Object.keys(query);
for (const key of keys) {
@@ -191,6 +194,7 @@ export abstract class BaseService<T> {
if (buildQuery) {
buildQuery(qb);
}
return qb;
}

View File

@@ -107,5 +107,17 @@ export const Constants = {
code: 20012,
message: '证书还未生成',
},
openCertApplying: {
code: 20013,
message: '证书正在申请中,请稍后重新获取',
},
openDomainNoVerifier:{
code: 20014,
message: '域名校验方式未配置',
},
openEmailNotFound: {
code: 20021,
message: '用户邮箱还未配置',
},
},
};

View File

@@ -11,13 +11,13 @@ export class CommonException extends BaseException {
}
export class CodeException extends BaseException {
constructor(res: { code: number; message: string }) {
super("CodeException", res.code, res.message);
constructor(res: { code: number; message: string; data?: any }) {
super("CodeException", res.code, res.message, res.data);
}
}
export class TextException extends BaseException {
constructor(name, code,message, data?) {
constructor(name, code, message, data?) {
super(name, code, message, data);
}
}

View File

@@ -22,6 +22,7 @@ export class SysPublicSettings extends BaseSettings {
mobileRegisterEnabled = false;
smsLoginEnabled = false;
emailRegisterEnabled = false;
selfServicePasswordRetrievalEnabled = false;
limitUserPipelineCount = 0;
managerOtherUserPipeline = false;

View File

@@ -1,6 +1,6 @@
import {Inject, Provide, Scope, ScopeEnum} from '@midwayjs/core';
import {InjectEntityModel} from '@midwayjs/typeorm';
import {Repository} from 'typeorm';
import { In, Repository } from "typeorm";
import {AccessGetter, BaseService, PageReq, PermissionException, ValidateException} from '../../../index.js';
import {AccessEntity} from '../entity/access.js';
import {AccessDefine, accessRegistry, newAccess} from '@certd/pipeline';
@@ -175,4 +175,27 @@ export class AccessService extends BaseService<AccessEntity> {
getDefineByType(type: string) {
return accessRegistry.getDefine(type);
}
async getSimpleByIds(ids: number[], userId: any) {
if (ids.length === 0) {
return [];
}
if (!userId) {
return [];
}
return await this.repository.find({
where: {
id: In(ids),
userId,
},
select: {
id: true,
name: true,
type: true,
userId:true
},
});
}
}

View File

@@ -3,6 +3,50 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.36.14](https://github.com/certd/certd/compare/v1.36.13...v1.36.14) (2025-07-28)
**Note:** Version bump only for package @certd/midway-flyway-js
## [1.36.13](https://github.com/certd/certd/compare/v1.36.12...v1.36.13) (2025-07-23)
**Note:** Version bump only for package @certd/midway-flyway-js
## [1.36.12](https://github.com/certd/certd/compare/v1.36.11...v1.36.12) (2025-07-22)
**Note:** Version bump only for package @certd/midway-flyway-js
## [1.36.11](https://github.com/certd/certd/compare/v1.36.10...v1.36.11) (2025-07-22)
**Note:** Version bump only for package @certd/midway-flyway-js
## [1.36.10](https://github.com/certd/certd/compare/v1.36.9...v1.36.10) (2025-07-18)
**Note:** Version bump only for package @certd/midway-flyway-js
## [1.36.9](https://github.com/certd/certd/compare/v1.36.7...v1.36.9) (2025-07-15)
**Note:** Version bump only for package @certd/midway-flyway-js
## [1.36.7](https://github.com/certd/certd/compare/v1.36.6...v1.36.7) (2025-07-15)
**Note:** Version bump only for package @certd/midway-flyway-js
## [1.36.6](https://github.com/certd/certd/compare/v1.36.5...v1.36.6) (2025-07-14)
**Note:** Version bump only for package @certd/midway-flyway-js
## [1.36.5](https://github.com/certd/certd/compare/v1.36.4...v1.36.5) (2025-07-11)
**Note:** Version bump only for package @certd/midway-flyway-js
## [1.36.4](https://github.com/certd/certd/compare/v1.36.3...v1.36.4) (2025-07-10)
**Note:** Version bump only for package @certd/midway-flyway-js
## [1.36.3](https://github.com/certd/certd/compare/v1.36.2...v1.36.3) (2025-07-07)
**Note:** Version bump only for package @certd/midway-flyway-js
## [1.36.2](https://github.com/certd/certd/compare/v1.36.1...v1.36.2) (2025-07-06)
**Note:** Version bump only for package @certd/midway-flyway-js

View File

@@ -1,6 +1,6 @@
{
"name": "@certd/midway-flyway-js",
"version": "1.36.2",
"version": "1.36.14",
"description": "midway with flyway, sql upgrade way ",
"private": false,
"type": "module",
@@ -46,5 +46,5 @@
"typeorm": "^0.3.11",
"typescript": "^5.4.2"
},
"gitHead": "8671887abcdfb93a7ecb709f223bd6add6f03c67"
"gitHead": "1e03a2e553aa94982453a477d2a0d35a565b6270"
}

View File

@@ -3,6 +3,61 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.36.14](https://github.com/certd/certd/compare/v1.36.13...v1.36.14) (2025-07-28)
### Bug Fixes
* 修复商用证书上传第二次运行无法使用pfx格式证书的bug ([251dd1f](https://github.com/certd/certd/commit/251dd1fe457a7b152f43eb6de18f7beb9f0b194e))
## [1.36.13](https://github.com/certd/certd/compare/v1.36.12...v1.36.13) (2025-07-23)
**Note:** Version bump only for package @certd/plugin-cert
## [1.36.12](https://github.com/certd/certd/compare/v1.36.11...v1.36.12) (2025-07-22)
**Note:** Version bump only for package @certd/plugin-cert
## [1.36.11](https://github.com/certd/certd/compare/v1.36.10...v1.36.11) (2025-07-22)
**Note:** Version bump only for package @certd/plugin-cert
## [1.36.10](https://github.com/certd/certd/compare/v1.36.9...v1.36.10) (2025-07-18)
**Note:** Version bump only for package @certd/plugin-cert
## [1.36.9](https://github.com/certd/certd/compare/v1.36.7...v1.36.9) (2025-07-15)
**Note:** Version bump only for package @certd/plugin-cert
## [1.36.7](https://github.com/certd/certd/compare/v1.36.6...v1.36.7) (2025-07-15)
### Performance Improvements
* 支持邮箱发送证书 ([95332d5](https://github.com/certd/certd/commit/95332d5db96cd54ddab6ab737332417a09169b39))
## [1.36.6](https://github.com/certd/certd/compare/v1.36.5...v1.36.6) (2025-07-14)
### Performance Improvements
* 支持自动选择校验方式申请证书 ([3f99432](https://github.com/certd/certd/commit/3f9943270cfb12946e38e6272bc5e8d95ad6ab9e))
* OpenAPI支持autoApply参数 ([42f4d14](https://github.com/certd/certd/commit/42f4d1477dc791520a874aed56035abcbc8c433b))
## [1.36.5](https://github.com/certd/certd/compare/v1.36.4...v1.36.5) (2025-07-11)
**Note:** Version bump only for package @certd/plugin-cert
## [1.36.4](https://github.com/certd/certd/compare/v1.36.3...v1.36.4) (2025-07-10)
### Performance Improvements
* 优化证书进度条颜色 ([2af91db](https://github.com/certd/certd/commit/2af91dbf2ae36a4ed17c6788bc2a2a79a3bb29f8))
* 支持部署到阿里云vod ([98da4e1](https://github.com/certd/certd/commit/98da4e1791ed8bb21daf2a9914fda875d14633c9))
* output-selector from参数支持更丰富的过滤规则 ([87853a2](https://github.com/certd/certd/commit/87853a201535f3bfe8505c40f8f5229d82ffcc73))
## [1.36.3](https://github.com/certd/certd/compare/v1.36.2...v1.36.3) (2025-07-07)
**Note:** Version bump only for package @certd/plugin-cert
## [1.36.2](https://github.com/certd/certd/compare/v1.36.1...v1.36.2) (2025-07-06)
**Note:** Version bump only for package @certd/plugin-cert

View File

@@ -1,7 +1,7 @@
{
"name": "@certd/plugin-cert",
"private": false,
"version": "1.36.2",
"version": "1.36.14",
"type": "module",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
@@ -16,10 +16,10 @@
"pub": "npm publish"
},
"dependencies": {
"@certd/acme-client": "^1.36.2",
"@certd/basic": "^1.36.2",
"@certd/pipeline": "^1.36.2",
"@certd/plugin-lib": "^1.36.2",
"@certd/acme-client": "^1.36.14",
"@certd/basic": "^1.36.14",
"@certd/pipeline": "^1.36.14",
"@certd/plugin-lib": "^1.36.14",
"@google-cloud/publicca": "^1.3.0",
"dayjs": "^1.11.7",
"jszip": "^3.10.1",
@@ -43,5 +43,5 @@
"tslib": "^2.8.1",
"typescript": "^5.4.2"
},
"gitHead": "8671887abcdfb93a7ecb709f223bd6add6f03c67"
"gitHead": "1e03a2e553aa94982453a477d2a0d35a565b6270"
}

View File

@@ -59,3 +59,38 @@ export interface ISubDomainsGetter {
export interface IDomainParser {
parse(fullDomain: string): Promise<string>;
}
export type DnsVerifier = {
// dns直接校验
dnsProviderType?: string;
dnsProviderAccessId?: number;
};
export type CnameVerifier = {
hostRecord: string;
domain: string;
recordValue: string;
};
export type HttpVerifier = {
// http校验
httpUploaderType: string;
httpUploaderAccess: number;
httpUploadRootDir: string;
};
export type DomainVerifier = {
domain: string;
mainDomain: string;
type: string;
dns?: DnsVerifier;
cname?: CnameVerifier;
http?: HttpVerifier;
};
export type DomainVerifiers = {
[key: string]: DomainVerifier;
};
export interface IDomainVerifierGetter {
getVerifiers(domains: string[]): Promise<DomainVerifiers>;
}

View File

@@ -23,10 +23,11 @@ export type HttpVerifyPlan = {
export type DomainVerifyPlan = {
domain: string;
mainDomain: string;
type: "cname" | "dns" | "http";
dnsProvider?: IDnsProvider;
cnameVerifyPlan?: Record<string, CnameVerifyPlan>;
httpVerifyPlan?: Record<string, HttpVerifyPlan>;
cnameVerifyPlan?: CnameVerifyPlan;
httpVerifyPlan?: HttpVerifyPlan;
};
export type DomainsVerifyPlan = {
[key: string]: DomainVerifyPlan;
@@ -233,23 +234,20 @@ export class AcmeService {
let dnsProvider = providers.dnsProvider;
let fullRecord = `_acme-challenge.${fullDomain}`;
const origDomain = punycode.toUnicode(domain);
// const origDomain = punycode.toUnicode(domain);
const origFullDomain = punycode.toUnicode(fullDomain);
if (providers.domainsVerifyPlan) {
//按照计划执行
const domainVerifyPlan = providers.domainsVerifyPlan[origDomain];
const domainVerifyPlan = providers.domainsVerifyPlan[origFullDomain];
if (domainVerifyPlan) {
if (domainVerifyPlan.type === "dns") {
dnsProvider = domainVerifyPlan.dnsProvider;
} else if (domainVerifyPlan.type === "cname") {
const cnameVerifyPlan = domainVerifyPlan.cnameVerifyPlan;
if (cnameVerifyPlan) {
const cname = cnameVerifyPlan[origFullDomain];
if (cname) {
dnsProvider = cname.dnsProvider;
domain = await this.options.domainParser.parse(cname.domain);
fullRecord = cname.fullRecord;
}
const cname: CnameVerifyPlan = domainVerifyPlan.cnameVerifyPlan;
if (cname) {
dnsProvider = cname.dnsProvider;
domain = await this.options.domainParser.parse(cname.domain);
fullRecord = cname.fullRecord;
} else {
this.logger.error(`未找到域名${fullDomain}的CNAME校验计划请修改证书申请配置`);
}
@@ -257,13 +255,12 @@ export class AcmeService {
throw new Error(`未找到域名${fullDomain}CNAME校验计划的DnsProvider请修改证书申请配置`);
}
} else if (domainVerifyPlan.type === "http") {
const httpVerifyPlan = domainVerifyPlan.httpVerifyPlan;
if (httpVerifyPlan) {
const plan: HttpVerifyPlan = domainVerifyPlan.httpVerifyPlan;
if (plan) {
const httpChallenge = getChallenge("http-01");
if (httpChallenge == null) {
throw new Error("该域名不支持http-01方式校验");
}
const plan = httpVerifyPlan[fullDomain];
return await doHttpVerify(httpChallenge, plan.httpUploader);
} else {
throw new Error("未找到域名【" + fullDomain + "】的http校验配置");
@@ -272,9 +269,12 @@ export class AcmeService {
throw new Error("不支持的校验类型", domainVerifyPlan.type);
}
} else {
this.logger.info("未找到域名校验计划使用默认的dnsProvider");
this.logger.warn(`未找到域名${fullDomain}校验计划使用默认的dnsProvider`);
}
}
if (!dnsProvider) {
throw new Error(`域名${fullDomain}没有匹配到任何校验方式,证书申请失败`);
}
const dnsChallenge = getChallenge("dns-01");
return await doDnsVerify(dnsChallenge, fullRecord, dnsProvider);

View File

@@ -1,4 +1,4 @@
import { AbstractTaskPlugin, IContext, Step, TaskInput, TaskOutput } from "@certd/pipeline";
import { AbstractTaskPlugin, FileItem, IContext, Step, TaskInput, TaskOutput } from "@certd/pipeline";
import dayjs from "dayjs";
import type { CertInfo } from "./acme.js";
import { CertReader } from "./cert-reader.js";
@@ -67,9 +67,16 @@ export abstract class CertApplyBaseConvertPlugin extends AbstractTaskPlugin {
@TaskOutput({
title: "域名证书",
type: "cert",
})
cert?: CertInfo;
@TaskOutput({
title: "域名证书压缩文件",
type: "certZip",
})
certZip?: FileItem;
async onInstance() {
this.userContext = this.ctx.userContext;
this.lastStatus = this.ctx.lastStatus as Step;
@@ -130,6 +137,7 @@ export abstract class CertApplyBaseConvertPlugin extends AbstractTaskPlugin {
} else {
this.extendsFiles();
}
this.certZip = this._result.files[0];
}
async zipCert(cert: CertInfo, filename: string) {
@@ -186,4 +194,13 @@ cert.jksjks格式证书文件java服务器使用
};
return newCert;
}
async readLastCert(): Promise<CertReader | undefined> {
const cert = this.lastStatus?.status?.output?.cert;
if (cert == null) {
this.logger.info("没有找到上次的证书");
return undefined;
}
return new CertReader(cert);
}
}

View File

@@ -130,15 +130,6 @@ export abstract class CertApplyBasePlugin extends CertApplyBaseConvertPlugin {
return null;
}
async readLastCert(): Promise<CertReader | undefined> {
const cert = this.lastStatus?.status?.output?.cert;
if (cert == null) {
this.logger.info("没有找到上次的证书");
return undefined;
}
return new CertReader(cert);
}
/**
* 检查是否过期默认提前35天
* @param expires

View File

@@ -204,4 +204,11 @@ export class CertReader {
domain = domain.replaceAll(".", "_").replaceAll("*", "_");
return `${domain}_${dayjs().format("YYYYMMDDHHmmssSSS")}`;
}
static appendTimeSuffix(name?: string) {
if (name == null) {
name = "certd";
}
return name + "_" + dayjs().format("YYYYMMDDHHmmssSSS");
}
}

View File

@@ -87,6 +87,7 @@ export class CertApplyUploadPlugin extends CertApplyBaseConvertPlugin {
@TaskOutput({
title: "证书MD5",
type: "certMd5",
})
certMd5?: string;
@@ -99,8 +100,17 @@ export class CertApplyUploadPlugin extends CertApplyBaseConvertPlugin {
async onInit(): Promise<void> {}
async getCertFromStore() {
const certReader = new CertReader(this.uploadCert);
if (!certReader.expires && certReader.expires < new Date().getTime()) {
let certReader = null;
try {
this.logger.info("读取上次证书");
certReader = await this.readLastCert();
} catch (e) {
this.logger.warn("读取cert失败", e);
}
if (certReader == null) {
certReader = new CertReader(this.uploadCert);
}
if (!certReader.expires || certReader.expires < new Date().getTime()) {
throw new Error("证书已过期,停止部署,请重新上传证书");
}

View File

@@ -1,16 +1,16 @@
import { CancelError, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline";
import { utils } from "@certd/basic";
import type { CertInfo, CnameVerifyPlan, DomainsVerifyPlan, HttpVerifyPlan, PrivateKeyType, SSLProvider } from "./acme.js";
import { AcmeService } from "./acme.js";
import { AcmeService, CertInfo, DomainsVerifyPlan, DomainVerifyPlan, PrivateKeyType, SSLProvider } from "./acme.js";
import * as _ from "lodash-es";
import { createDnsProvider, DnsProviderContext, IDnsProvider, ISubDomainsGetter } from "../../dns-provider/index.js";
import { createDnsProvider, DnsProviderContext, DnsVerifier, DomainVerifiers, HttpVerifier, IDnsProvider, IDomainVerifierGetter, ISubDomainsGetter } from "../../dns-provider/index.js";
import { CertReader } from "./cert-reader.js";
import { CertApplyBasePlugin } from "./base.js";
import { GoogleClient } from "../../libs/google.js";
import { EabAccess } from "../../access";
import { DomainParser } from "../../dns-provider/domain-parser.js";
import { ossClientFactory } from "@certd/plugin-lib";
export * from "./base.js";
export type { CertInfo };
export * from "./cert-reader.js";
@@ -65,12 +65,17 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
{ value: "dns", label: "DNS直接验证" },
{ value: "cname", label: "CNAME代理验证" },
{ value: "http", label: "HTTP文件验证" },
{ value: "dnses", label: "多DNS提供商" },
{ value: "auto", label: "自动匹配" },
],
},
required: true,
helper: `1. <b>DNS直接验证</b>域名dns解析是在阿里云/腾讯云/华为云/CF/NameSilo/西数/火山/dns.la/京东云/51dns的选它
2. <b>CNAME代理验证</b>支持任何注册商的域名第一次需要手动添加CNAME记录建议将DNS服务器修改为阿里云/腾讯云的然后使用DNS直接验证
3. <b>HTTP文件验证</b>:不支持泛域名,需要配置网站文件上传`,
2. <b>CNAME代理验证</b>:支持任何注册商的域名,第一次需要手动添加[CNAME记录](#/certd/cname/record)建议将DNS服务器修改为阿里云/腾讯云的然后使用DNS直接验证
3. <b>HTTP文件验证</b>:不支持泛域名,需要配置网站文件上传
4. <b>多DNS提供商</b>每个域名可以选择独立的DNS提供商
5. <b>自动匹配</b>:需要在[域名管理](#/certd/cert/domain)中事先配置好校验方式
`,
})
challengeType!: string;
@@ -159,13 +164,15 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
})
},
show: ctx.compute(({form})=>{
return form.challengeType === 'cname' || form.challengeType === 'http'
return form.challengeType === 'cname' || form.challengeType === 'http' || form.challengeType === 'dnses'
}),
helper: ctx.compute(({form})=>{
if(form.challengeType === 'cname' ){
return '请按照上面的提示给要申请证书的域名添加CNAME记录添加后点击验证验证成功后不要删除记录申请和续期证书会一直用它'
}else if (form.challengeType === 'http'){
return '请按照上面的提示,给每个域名设置文件上传配置,证书申请过程中会上传校验文件到网站根目录下'
}else if (form.challengeType === 'http'){
return '给每个域名单独配置dns提供商'
}
})
}
@@ -321,13 +328,14 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
name: "a-input-number",
vModel: "value",
},
helper: "等待解析生效时长(秒)",
helper: "等待解析生效时长(秒)如果使用CNAME方式校验本地验证失败可以尝试延长此时间比如5-10分钟",
})
waitDnsDiffuseTime = 30;
acme!: AcmeService;
eab!: EabAccess;
async onInit() {
let eab: EabAccess = null;
@@ -402,8 +410,10 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
let dnsProvider: IDnsProvider = null;
let domainsVerifyPlan: DomainsVerifyPlan = null;
if (this.challengeType === "cname" || this.challengeType === "http") {
domainsVerifyPlan = await this.createDomainsVerifyPlan();
if (this.challengeType === "cname" || this.challengeType === "http" || this.challengeType === "dnses") {
domainsVerifyPlan = await this.createDomainsVerifyPlan(domains, this.domainsVerifyPlan);
} else if (this.challengeType === "auto") {
domainsVerifyPlan = await this.createDomainsVerifyPlanByAuto(domains);
} else {
const dnsProviderType = this.dnsProviderType;
const access = await this.getAccess(this.dnsProviderAccess);
@@ -439,73 +449,132 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
async createDnsProvider(dnsProviderType: string, dnsProviderAccess: any): Promise<IDnsProvider> {
const domainParser = this.acme.options.domainParser;
const context: DnsProviderContext = { access: dnsProviderAccess, logger: this.logger, http: this.ctx.http, utils, domainParser };
const context: DnsProviderContext = {
access: dnsProviderAccess,
logger: this.logger,
http: this.ctx.http,
utils,
domainParser,
};
return await createDnsProvider({
dnsProviderType,
context,
});
}
async createDomainsVerifyPlan(): Promise<DomainsVerifyPlan> {
async createDomainsVerifyPlan(domains: string[], verifyPlanSetting: DomainsVerifyPlanInput): Promise<DomainsVerifyPlan> {
const plan: DomainsVerifyPlan = {};
for (const domain in this.domainsVerifyPlan) {
const domainVerifyPlan = this.domainsVerifyPlan[domain];
let dnsProvider = null;
const cnameVerifyPlan: Record<string, CnameVerifyPlan> = {};
const httpVerifyPlan: Record<string, HttpVerifyPlan> = {};
if (domainVerifyPlan.type === "dns") {
const access = await this.getAccess(domainVerifyPlan.dnsProviderAccessId);
dnsProvider = await this.createDnsProvider(domainVerifyPlan.dnsProviderType, access);
} else if (domainVerifyPlan.type === "cname") {
for (const key in domainVerifyPlan.cnameVerifyPlan) {
const cnameRecord = await this.ctx.cnameProxyService.getByDomain(key);
let dnsProvider = cnameRecord.commonDnsProvider;
if (cnameRecord.cnameProvider.id > 0) {
dnsProvider = await this.createDnsProvider(cnameRecord.cnameProvider.dnsProviderType, cnameRecord.cnameProvider.access);
}
cnameVerifyPlan[key] = {
type: "cname",
domain: cnameRecord.cnameProvider.domain,
fullRecord: cnameRecord.recordValue,
dnsProvider,
};
}
} else if (domainVerifyPlan.type === "http") {
const httpUploaderContext = {
accessService: this.ctx.accessService,
logger: this.logger,
utils,
};
for (const key in domainVerifyPlan.httpVerifyPlan) {
const httpRecord = domainVerifyPlan.httpVerifyPlan[key];
const access = await this.getAccess(httpRecord.httpUploaderAccess);
let rootDir = httpRecord.httpUploadRootDir;
if (!rootDir.endsWith("/") && !rootDir.endsWith("\\")) {
rootDir = rootDir + "/";
}
this.logger.info("上传方式", httpRecord.httpUploaderType);
const httpUploader = await ossClientFactory.createOssClientByType(httpRecord.httpUploaderType, {
access,
rootDir: rootDir,
ctx: httpUploaderContext,
});
httpVerifyPlan[key] = {
type: "http",
domain: key,
httpUploader,
};
}
const domainParser = this.acme.options.domainParser;
for (const fullDomain of domains) {
const domain = fullDomain.replaceAll("*.", "");
const mainDomain = await domainParser.parse(domain);
const planSetting: DomainVerifyPlanInput = verifyPlanSetting[mainDomain];
if (planSetting == null) {
throw new Error(`没有找到域名(${domain})的校验计划`);
}
if (planSetting.type === "dns") {
plan[domain] = await this.createDnsDomainVerifyPlan(planSetting, domain, mainDomain);
} else if (planSetting.type === "cname") {
plan[domain] = await this.createCnameDomainVerifyPlan(domain, mainDomain);
} else if (planSetting.type === "http") {
plan[domain] = await this.createHttpDomainVerifyPlan(planSetting.httpVerifyPlan[domain], domain, mainDomain);
}
plan[domain] = {
domain,
type: domainVerifyPlan.type,
dnsProvider,
cnameVerifyPlan,
httpVerifyPlan,
};
}
return plan;
}
private async createDomainsVerifyPlanByAuto(domains: string[]) {
//从数据库里面自动选择校验方式
// domain list
const domainList = new Set<string>();
//整理域名
for (let domain of domains) {
domain = domain.replaceAll("*.", "");
domainList.add(domain);
}
const domainVerifierGetter: IDomainVerifierGetter = await this.ctx.serviceGetter.get("domainVerifierGetter");
const verifiers: DomainVerifiers = await domainVerifierGetter.getVerifiers([...domainList]);
const plan: DomainsVerifyPlan = {};
for (const domain in verifiers) {
const verifier = verifiers[domain];
if (verifier == null) {
throw new Error(`没有找到与该域名(${domain})匹配的校验方式,请先到‘域名管理’页面添加校验方式`);
}
if (verifier.type === "dns") {
plan[domain] = await this.createDnsDomainVerifyPlan(verifier.dns, domain, verifier.mainDomain);
} else if (verifier.type === "cname") {
plan[domain] = await this.createCnameDomainVerifyPlan(domain, verifier.mainDomain);
} else if (verifier.type === "http") {
plan[domain] = await this.createHttpDomainVerifyPlan(verifier.http, domain, verifier.mainDomain);
}
}
return plan;
}
private async createDnsDomainVerifyPlan(planSetting: DnsVerifier, domain: string, mainDomain: string): Promise<DomainVerifyPlan> {
const access = await this.getAccess(planSetting.dnsProviderAccessId);
return {
type: "dns",
mainDomain,
domain,
dnsProvider: await this.createDnsProvider(planSetting.dnsProviderType, access),
};
}
private async createHttpDomainVerifyPlan(httpSetting: HttpVerifier, domain: string, mainDomain: string): Promise<DomainVerifyPlan> {
const httpUploaderContext = {
accessService: this.ctx.accessService,
logger: this.logger,
utils,
};
const access = await this.getAccess(httpSetting.httpUploaderAccess);
let rootDir = httpSetting.httpUploadRootDir;
if (!rootDir.endsWith("/") && !rootDir.endsWith("\\")) {
rootDir = rootDir + "/";
}
this.logger.info("上传方式", httpSetting.httpUploaderType);
const httpUploader = await ossClientFactory.createOssClientByType(httpSetting.httpUploaderType, {
access,
rootDir: rootDir,
ctx: httpUploaderContext,
});
return {
type: "http",
domain,
mainDomain,
httpVerifyPlan: {
type: "http",
domain,
httpUploader,
},
};
}
private async createCnameDomainVerifyPlan(domain: string, mainDomain: string): Promise<DomainVerifyPlan> {
const cnameRecord = await this.ctx.cnameProxyService.getByDomain(domain);
if (cnameRecord == null) {
throw new Error(`请先配置${domain}的CNAME记录并通过校验`);
}
let dnsProvider = cnameRecord.commonDnsProvider;
if (cnameRecord.cnameProvider.id > 0) {
dnsProvider = await this.createDnsProvider(cnameRecord.cnameProvider.dnsProviderType, cnameRecord.cnameProvider.access);
}
return {
type: "cname",
domain,
mainDomain,
cnameVerifyPlan: {
domain: cnameRecord.cnameProvider.domain,
fullRecord: cnameRecord.recordValue,
dnsProvider,
},
};
}
}
new CertApplyPlugin();

View File

@@ -3,4 +3,4 @@ export { EVENT_CERT_APPLY_SUCCESS } from "./cert-plugin/base-convert.js";
export * from "./cert-plugin/index.js";
export * from "./cert-plugin/lego/index.js";
export * from "./cert-plugin/custom/index.js";
export const CertApplyPluginNames = ["CertApply", "CertApplyLego", "CertApplyUpload"];
export const CertApplyPluginNames = [":cert:"];

View File

@@ -3,6 +3,64 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.36.14](https://github.com/certd/certd/compare/v1.36.13...v1.36.14) (2025-07-28)
### Performance Improvements
* 1panel支持 currenNode ([acc8907](https://github.com/certd/certd/commit/acc890730f43d492c9b1bd3668814cf10efdf7b8))
## [1.36.13](https://github.com/certd/certd/compare/v1.36.12...v1.36.13) (2025-07-23)
### Bug Fixes
* 修复阿里云发送短信验证码失败的bug ([2e6d03f](https://github.com/certd/certd/commit/2e6d03ff001f521f57368e7a62b97ed7b122e8d0))
## [1.36.12](https://github.com/certd/certd/compare/v1.36.11...v1.36.12) (2025-07-22)
**Note:** Version bump only for package @certd/plugin-lib
## [1.36.11](https://github.com/certd/certd/compare/v1.36.10...v1.36.11) (2025-07-22)
**Note:** Version bump only for package @certd/plugin-lib
## [1.36.10](https://github.com/certd/certd/compare/v1.36.9...v1.36.10) (2025-07-18)
**Note:** Version bump only for package @certd/plugin-lib
## [1.36.9](https://github.com/certd/certd/compare/v1.36.7...v1.36.9) (2025-07-15)
### Bug Fixes
* 修复ssh无法执行命令的bug ([9763cb0](https://github.com/certd/certd/commit/9763cb00e5d95b2fa5d1c2d3d4a8eecac71600e6))
## [1.36.7](https://github.com/certd/certd/compare/v1.36.6...v1.36.7) (2025-07-15)
### Bug Fixes
* 修复流水线页面状态没有刷新的bug ([93e9498](https://github.com/certd/certd/commit/93e9498b410353f504e11e264db62468895d7290))
## [1.36.6](https://github.com/certd/certd/compare/v1.36.5...v1.36.6) (2025-07-14)
**Note:** Version bump only for package @certd/plugin-lib
## [1.36.5](https://github.com/certd/certd/compare/v1.36.4...v1.36.5) (2025-07-11)
**Note:** Version bump only for package @certd/plugin-lib
## [1.36.4](https://github.com/certd/certd/compare/v1.36.3...v1.36.4) (2025-07-10)
### Bug Fixes
* 执行windows nginx命令时改为return code判断是否执行成功 ([b37cffd](https://github.com/certd/certd/commit/b37cffd704cd08b8bdd68a6e284706eabe59e78d))
### Performance Improvements
* 支持部署到阿里云vod ([98da4e1](https://github.com/certd/certd/commit/98da4e1791ed8bb21daf2a9914fda875d14633c9))
## [1.36.3](https://github.com/certd/certd/compare/v1.36.2...v1.36.3) (2025-07-07)
**Note:** Version bump only for package @certd/plugin-lib
## [1.36.2](https://github.com/certd/certd/compare/v1.36.1...v1.36.2) (2025-07-06)
**Note:** Version bump only for package @certd/plugin-lib

View File

@@ -1,7 +1,7 @@
{
"name": "@certd/plugin-lib",
"private": false,
"version": "1.36.2",
"version": "1.36.14",
"type": "module",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
@@ -21,8 +21,8 @@
"@alicloud/pop-core": "^1.7.10",
"@alicloud/tea-util": "^1.4.10",
"@aws-sdk/client-s3": "^3.787.0",
"@certd/basic": "^1.36.2",
"@certd/pipeline": "^1.36.2",
"@certd/basic": "^1.36.14",
"@certd/pipeline": "^1.36.14",
"@kubernetes/client-node": "0.21.0",
"ali-oss": "^6.22.0",
"basic-ftp": "^5.0.5",
@@ -53,5 +53,5 @@
"tslib": "^2.8.1",
"typescript": "^5.4.2"
},
"gitHead": "8671887abcdfb93a7ecb709f223bd6add6f03c67"
"gitHead": "1e03a2e553aa94982453a477d2a0d35a565b6270"
}

View File

@@ -1,6 +1,5 @@
import { IsAccess, AccessInput, BaseAccess } from "@certd/pipeline";
import { AccessInput, BaseAccess, IsAccess } from "@certd/pipeline";
import { ILogger } from "@certd/basic";
export type AliyunClientV2Req = {
action: string;
version: string;

View File

@@ -35,7 +35,7 @@ export class AliyunClient {
}
checkRet(ret: any) {
if (ret.Code != null) {
if (ret.Code != null && ret.Code !== "OK" && ret.Message !== "OK") {
throw new Error("执行失败:" + ret.Message);
}
}

View File

@@ -33,8 +33,10 @@ export type CasCertInfo = { certId: number; certName: string; certIdentifier: st
export class AliyunSslClient {
opts: AliyunSslClientOpts;
logger: ILogger;
constructor(opts: AliyunSslClientOpts) {
this.opts = opts;
this.logger = opts.logger;
}
checkRet(ret: any) {

View File

@@ -17,7 +17,7 @@ export function createCertDomainGetterInputDefine(opts?: { certInputKey?: string
}
}
`,
template:false,
template: false,
required: true,
},
opts?.props
@@ -42,6 +42,7 @@ export function createRemoteSelectInputDefine(opts?: {
search?: boolean;
pager?: boolean;
component?: any;
value?: any;
}) {
const title = opts?.title || "请选择";
const certDomainsInputKey = opts?.certDomainsInputKey || "certDomains";
@@ -74,6 +75,7 @@ export function createRemoteSelectInputDefine(opts?: {
watches: [certDomainsInputKey, accessIdInputKey, ...watches],
...opts.component,
},
value: opts.value,
rules: opts?.rules,
required: opts.required ?? true,
mergeScript:

View File

@@ -16,6 +16,10 @@ export default class SshOssClientImpl extends BaseOssClient<SshAccess> {
throw new Error("Method not implemented.");
}
async upload(filePath: string, fileContent: Buffer) {
if (!filePath) {
filePath = "";
}
filePath = filePath.trim();
const tmpFilePath = path.join(os.tmpdir(), "cert", "http", filePath);
// Write file to temp path

View File

@@ -204,9 +204,18 @@ export class AsyncSsh2Client {
stream
.on("close", (code: any, signal: any) => {
this.logger.info(`[${this.connConf.host}][close]:code:${code}`);
if (opts.throwOnStdErr == null && this.windows) {
opts.throwOnStdErr = true;
}
/**
* ]pipeline 执行命令:[10.123.0.2][exec]:cd /d D:\nginx-1.27.5 && D:\nginx-1.27.5\nginx.exe -t && D:\nginx-1.27.5\nginx.exe -s reload
* [2025-07-09T10:24:11.219] [ERROR]pipeline - [10. 123.0. 2][error]: nginx: the configuration file D: \nginx-1.27. 5/conf/nginx. conf syntax is ok
* [2025-07-09T10:24:11.231] [ERROR][10. 123. 0. 2] [error]: nginx: configuration file D: \nginx-1.27.5/conf/nginx.conf test is successful
* pipeline-
* [2025-07-09T10:24:11.473] [INFO]pipeline -[10.123.0.2][close]:code:0
* [2025-07-09T10:24:11.473][ERRoR] pipeline- [step][主机一执行远程主机脚本命令]<id:53hyarN3yvmbijNuMiNAt>: [Eror: nginx: the configuration fileD:\nginx-1.27.5/conf/nginx.conf syntax is ok
//需要忽略windows的错误
*/
// if (opts.throwOnStdErr == null && this.windows) {
// opts.throwOnStdErr = true;
// }
if (opts.throwOnStdErr && hasErrorLog) {
reject(new Error(data));
}
@@ -482,9 +491,9 @@ export class SshClient {
* Set-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\Windows\System32\cmd.exe"
* @param options
*/
async exec(options: { connectConf: SshAccess; script: string | Array<string>; env?: any }): Promise<string> {
async exec(options: { connectConf: SshAccess; script: string | Array<string>; env?: any; throwOnStdErr?: boolean; stopOnError?: boolean }): Promise<string> {
let { script } = options;
const { connectConf } = options;
const { connectConf, throwOnStdErr } = options;
// this.logger.info('命令:', script);
return await this._call({
@@ -512,10 +521,10 @@ export class SshClient {
}
if (isWinCmd) {
//组合成&&的形式
if (typeof script === "string") {
script = script.split("\n");
}
//组合成&&的形式
script = envScripts.concat(script);
script = script as Array<string>;
script = script.join(" && ");
@@ -529,7 +538,12 @@ export class SshClient {
script = envScripts.join(newLine) + newLine + script;
}
}
return await conn.exec(script as string, {});
if (isLinux && options.stopOnError !== false) {
script = "set -e\n" + script;
}
return await conn.exec(script as string, { throwOnStdErr });
},
});
}

View File

@@ -9,3 +9,4 @@ yarn.lock
/.idea/
yarn-error.log
vite-profile.cpuprofile
!build

View File

@@ -3,6 +3,91 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.36.14](https://github.com/certd/certd/compare/v1.36.13...v1.36.14) (2025-07-28)
### Bug Fixes
* 修复复制流水线为空的bug ([b070773](https://github.com/certd/certd/commit/b0707739fdfbae3d78db4efd3f180db05c4e4164))
### Performance Improvements
* 授权管理支持模糊查询 ([866eb62](https://github.com/certd/certd/commit/866eb6241baa7b21f6eddc649966324c188236c6))
* 新增找回密码功能 [@nicheng-he](https://github.com/nicheng-he) ([81ac240](https://github.com/certd/certd/commit/81ac240ac84db0af2f56b6352e227ecb49f38377))
## [1.36.13](https://github.com/certd/certd/compare/v1.36.12...v1.36.13) (2025-07-23)
### Performance Improvements
* 阿里云部分插件优化 [@nicheng-he](https://github.com/nicheng-he) ([e3738f6](https://github.com/certd/certd/commit/e3738f6422270d75ec414c15a343248cc4cad6e1))
## [1.36.12](https://github.com/certd/certd/compare/v1.36.11...v1.36.12) (2025-07-22)
### Bug Fixes
* 上传到阿里云cas证书前缀无效的bug ([b382351](https://github.com/certd/certd/commit/b382351c7b91ec10e1f61d94bec5aad075207ec8))
### Performance Improvements
* 首页增加更新日志按钮 ([41ce848](https://github.com/certd/certd/commit/41ce8489dc2f03a705dfa3fbb357769defb56c60))
* 增加版本过低提示 ([d1ce360](https://github.com/certd/certd/commit/d1ce36038cab72b5dc1b320d0a708c261ffbdacb))
## [1.36.11](https://github.com/certd/certd/compare/v1.36.10...v1.36.11) (2025-07-22)
**Note:** Version bump only for package @certd/ui-client
## [1.36.10](https://github.com/certd/certd/compare/v1.36.9...v1.36.10) (2025-07-18)
### Performance Improvements
* 优化子域名托管的说明 ([b15f514](https://github.com/certd/certd/commit/b15f514018b728acb0922ee3f93c1f302eb5d471))
* 账号即将过期通知 ([e403450](https://github.com/certd/certd/commit/e40345095f31e2fb8e2333a6647466659133fa0c))
* 子域名托管重复域名不允许添加 ([ffc0c7b](https://github.com/certd/certd/commit/ffc0c7bb7b16d9904fd2d905d1c4e1d4854e92a9))
## [1.36.9](https://github.com/certd/certd/compare/v1.36.7...v1.36.9) (2025-07-15)
**Note:** Version bump only for package @certd/ui-client
## [1.36.7](https://github.com/certd/certd/compare/v1.36.6...v1.36.7) (2025-07-15)
### Bug Fixes
* 修复流水线页面状态没有刷新的bug ([93e9498](https://github.com/certd/certd/commit/93e9498b410353f504e11e264db62468895d7290))
## [1.36.6](https://github.com/certd/certd/compare/v1.36.5...v1.36.6) (2025-07-14)
### Bug Fixes
* 修复某些页面翻译不全显示错误的bug ([0b3158f](https://github.com/certd/certd/commit/0b3158fdd5fe5bb0a98c4e65715dbc3de2c38047))
* 修复运行流水线后会闪烁一下的bug ([dfc9362](https://github.com/certd/certd/commit/dfc9362084082ee535b898f23b2609c1d946a6fd))
### Performance Improvements
* 通知和定时器的删除按钮显示为红色更显眼 ([61ba83c](https://github.com/certd/certd/commit/61ba83c77546c3d505d081e19a3d68c127662bf1))
* 优化流水线列表页面、详情页面性能,精简返回数据 ([609ac9c](https://github.com/certd/certd/commit/609ac9c9a2dde605eb09834ae59693c1cb238765))
* OpenAPI支持autoApply参数 ([42f4d14](https://github.com/certd/certd/commit/42f4d1477dc791520a874aed56035abcbc8c433b))
## [1.36.5](https://github.com/certd/certd/compare/v1.36.4...v1.36.5) (2025-07-11)
**Note:** Version bump only for package @certd/ui-client
## [1.36.4](https://github.com/certd/certd/compare/v1.36.3...v1.36.4) (2025-07-10)
### Bug Fixes
* 修复查看证书对话框翻译错误的bug ([8626b6d](https://github.com/certd/certd/commit/8626b6d9f235c511766f2ae98e0a37f6cebb621c))
* 修复translation后分组编辑打不开的bug ([46a1b74](https://github.com/certd/certd/commit/46a1b7479923d2feb2dece202a5932b99981b2cd))
### Performance Improvements
* 优化证书进度条颜色 ([2af91db](https://github.com/certd/certd/commit/2af91dbf2ae36a4ed17c6788bc2a2a79a3bb29f8))
* output-selector from参数支持更丰富的过滤规则 ([87853a2](https://github.com/certd/certd/commit/87853a201535f3bfe8505c40f8f5229d82ffcc73))
## [1.36.3](https://github.com/certd/certd/compare/v1.36.2...v1.36.3) (2025-07-07)
### Bug Fixes
* 修复开放接口添加按钮文本显示问题 ([f93ba99](https://github.com/certd/certd/commit/f93ba9970c12680f38eba2a7abd4b72cf3f5b6a6))
## [1.36.2](https://github.com/certd/certd/compare/v1.36.1...v1.36.2) (2025-07-06)
### Bug Fixes

View File

@@ -1,6 +1,6 @@
{
"name": "@certd/ui-client",
"version": "1.36.2",
"version": "1.36.14",
"private": true,
"scripts": {
"dev": "vite --open",
@@ -103,8 +103,8 @@
"zod-defaults": "^0.1.3"
},
"devDependencies": {
"@certd/lib-iframe": "^1.36.2",
"@certd/pipeline": "^1.36.2",
"@certd/lib-iframe": "^1.36.14",
"@certd/pipeline": "^1.36.14",
"@rollup/plugin-commonjs": "^25.0.7",
"@rollup/plugin-node-resolve": "^15.2.3",
"@types/chai": "^4.3.12",

View File

@@ -33,6 +33,7 @@
import { Ref, ref, watch, nextTick } from "vue";
import { HttpRecord } from "/@/components/plugins/cert/domains-verify-plan-editor/type";
import { dict } from "@fast-crud/fast-crud";
import { Dicts } from "/@/components/plugins/lib/dicts";
defineOptions({
name: "HttpVerifyPlan",
@@ -68,17 +69,7 @@ async function onRecordChange() {
emit("change", records.value);
}
const uploaderTypeDict = dict({
data: [
{ label: "SFTP", value: "sftp" },
{ label: "FTP", value: "ftp" },
{ label: "阿里云OSS", value: "alioss" },
{ label: "腾讯云COS", value: "tencentcos" },
{ label: "七牛OSS", value: "qiniuoss" },
{ label: "S3/Minio", value: "s3" },
{ label: "SSH(已废弃请选择SFTP方式)", value: "ssh", disabled: true },
],
});
const uploaderTypeDict = Dicts.uploaderTypeDict;
</script>
<style lang="less">

View File

@@ -167,10 +167,14 @@ async function onDomainsChanged(domains: string[]) {
let planItem = planRef.value[domain];
const domainGroupItem = domainGroups[domain];
if (!planItem) {
let type = props.defaultType || "cname";
if (type === "dnses") {
type = "dns";
}
planItem = {
domain,
//@ts-ignore
type: props.defaultType || "cname",
type: type,
//@ts-ignore
cnameVerifyPlan: {},
//@ts-ignore

View File

@@ -9,7 +9,6 @@
<script setup lang="ts">
import { inject, ref, watch } from "vue";
import { CertApplyPluginNames } from "/@/constants";
defineOptions({
name: "CertDomainsGetter",
@@ -54,8 +53,9 @@ function getDomainFromPipeline(inputKey: string) {
return;
}
if (!CertApplyPluginNames.includes(certStep.type)) {
targetStepId = getStepIdFromInputKey(certStep.input?.cert);
const firstLevelValue = certStep.input.cert;
if (firstLevelValue && typeof firstLevelValue === "string" && firstLevelValue.indexOf(".") > 0) {
targetStepId = getStepIdFromInputKey(firstLevelValue);
certStep = findStepFromPipeline(targetStepId);
if (!certStep) {
errorRef.value = "找不到目标步骤,请先选择域名证书";

View File

@@ -4,6 +4,7 @@
<script lang="ts">
import { inject, onMounted, Ref, ref, watch } from "vue";
import { usePluginStore } from "/@/store/plugin";
export default {
name: "OutputSelector",
@@ -27,10 +28,11 @@ export default {
const currentStepIndex = inject("currentStepIndex") as Ref<number>;
const currentTask = inject("currentTask") as Ref<any>;
const getPluginGroups = inject("getPluginGroups") as any;
const pluginGroups = getPluginGroups();
function onCreate() {
options.value = pluginGroups.getPreStepOutputOptions({
const pluginStore = usePluginStore();
async function onCreate() {
await pluginStore.init();
options.value = pluginStore.group.getPreStepOutputOptions({
pipeline: pipeline.value,
currentStageIndex: currentStageIndex.value,
currentTaskIndex: currentTaskIndex.value,
@@ -38,11 +40,38 @@ export default {
currentTask: currentTask.value,
});
if (props.from) {
let froms = [];
if (typeof props.from === "string") {
options.value = options.value.filter((item: any) => item.type === props.from);
froms = [props.from];
} else {
options.value = options.value.filter((item: any) => props.from.includes(item.type));
froms = props.from;
}
function match(from: string, item: any) {
// pluginType:valueType:keyName
if (from.includes(":")) {
const [pluginType, valueType, keyName] = from.split(":");
if (pluginType && item.type !== pluginType) {
return false;
}
if (valueType && item.valueType !== valueType) {
return false;
}
if (keyName && item.key !== keyName) {
return false;
}
return true;
} else {
return item.type === from;
}
}
options.value = options.value.filter((item: any) => {
for (const from of froms) {
if (match(from, item)) {
return true;
}
}
return false;
});
}
if (props.modelValue != null) {
@@ -55,19 +84,10 @@ export default {
ctx.emit("update:modelValue", value);
}
}
onMounted(() => {
onCreate();
onMounted(async () => {
await onCreate();
});
watch(
() => {
return pluginGroups.value?.map;
},
() => {
onCreate();
}
);
function onChanged(value: any) {
ctx.emit("update:modelValue", value);
}

View File

@@ -0,0 +1,162 @@
<template>
<div class="remote-auto-complete">
<div class="flex flex-row">
<a-auto-complete class="remote-auto-complete-input" :filter-option="filterOption" :options="optionsRef" :value="value" v-bind="attrs" @click="onClick" @update:value="emit('update:value', $event)">
</a-auto-complete>
<div class="ml-5">
<fs-button :loading="loading" title="刷新选项" icon="ion:refresh-outline" @click="refreshOptions"></fs-button>
</div>
</div>
<div class="helper" :class="{ error: hasError }">
{{ message }}
</div>
</div>
</template>
<script setup lang="ts">
import { ComponentPropsType, doRequest } from "/@/components/plugins/lib";
import { defineComponent, inject, ref, useAttrs, watch, Ref } from "vue";
import { PluginDefine } from "@certd/pipeline";
defineOptions({
name: "RemoteAutoComplete",
});
const props = defineProps<
{
watches: string[];
} & ComponentPropsType
>();
const emit = defineEmits<{
"update:value": any;
}>();
const attrs = useAttrs();
const getCurrentPluginDefine: any = inject("getCurrentPluginDefine", () => {
return {};
});
const getScope: any = inject("get:scope", () => {
return {};
});
const getPluginType: any = inject("get:plugin:type", () => {
return "plugin";
});
const optionsRef = ref([]);
const message = ref("");
const hasError = ref(false);
const loading = ref(false);
const getOptions = async () => {
if (loading.value) {
return;
}
if (!getCurrentPluginDefine) {
return;
}
const define: PluginDefine = getCurrentPluginDefine()?.value;
if (!define) {
return;
}
const pluginType = getPluginType();
const { form } = getScope();
const input = (pluginType === "plugin" ? form?.input : form) || {};
for (let key in define.input) {
const inWatches = props.watches.includes(key);
const inputDefine = define.input[key];
if (inWatches && inputDefine.required) {
const value = input[key];
if (value == null || value === "") {
console.log("remote-select required", key);
return;
}
}
}
message.value = "";
hasError.value = false;
loading.value = true;
try {
const res = await doRequest(
{
type: pluginType,
typeName: form.type,
action: props.action,
input,
data: {},
},
{
onError(err: any) {
hasError.value = true;
message.value = `获取选项出错:${err.message}`;
},
showErrorNotify: false,
}
);
const list = res?.list || res || [];
if (list.length > 0) {
message.value = "获取数据成功,请从下拉框中选择";
}
optionsRef.value = list;
return res;
} finally {
loading.value = false;
}
};
const filterOption = (input: string, option: any) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0 || String(option.value).toLowerCase().indexOf(input.toLowerCase());
};
async function onClick() {
if (optionsRef.value?.length === 0) {
await refreshOptions();
}
}
async function refreshOptions() {
await getOptions();
}
watch(
() => {
const pluginType = getPluginType();
const { form, key } = getScope();
const input = (pluginType === "plugin" ? form?.input : form) || {};
const watches = {};
for (const key of props.watches) {
//@ts-ignore
watches[key] = input[key];
}
return {
form: watches,
key,
};
},
async (value, oldValue) => {
const { form } = value;
const oldForm: any = oldValue?.form;
let changed = oldForm == null || optionsRef.value.length == 0;
for (const key of props.watches) {
//@ts-ignore
if (oldForm && form[key] != oldForm[key]) {
changed = true;
break;
}
}
if (changed) {
await getOptions();
}
},
{
immediate: true,
}
);
</script>
<style lang="less"></style>

View File

@@ -1,4 +1,5 @@
import SynologyIdDeviceGetter from "./synology/device-id-getter.vue";
import RemoteAutoComplete from "./common/remote-auto-complete.vue";
import RemoteSelect from "./common/remote-select.vue";
import RemoteInput from "./common/remote-input.vue";
import CertDomainsGetter from "./common/cert-domains-getter.vue";
@@ -21,6 +22,7 @@ export default {
app.component("ApiTest", ApiTest);
app.component("SynologyDeviceIdGetter", SynologyIdDeviceGetter);
app.component("RemoteAutoComplete", RemoteAutoComplete);
app.component("RemoteSelect", RemoteSelect);
app.component("RemoteInput", RemoteInput);
app.component("CertDomainsGetter", CertDomainsGetter);

View File

@@ -0,0 +1,31 @@
import { dict } from "@fast-crud/fast-crud";
export const Dicts = {
sslProviderDict: dict({
data: [
{ value: "letsencrypt", label: "Lets Encrypt" },
{ value: "zerossl", label: "ZeroSSL" },
],
}),
challengeTypeDict: dict({
data: [
{ value: "dns", label: "DNS校验", color: "green" },
{ value: "cname", label: "CNAME代理校验", color: "blue" },
{ value: "http", label: "HTTP校验", color: "yellow" },
],
}),
dnsProviderTypeDict: dict({
url: "pi/dnsProvider/dnsProviderTypeDict",
}),
uploaderTypeDict: dict({
data: [
{ label: "SFTP", value: "sftp" },
{ label: "FTP", value: "ftp" },
{ label: "阿里云OSS", value: "alioss" },
{ label: "腾讯云COS", value: "tencentcos" },
{ label: "七牛OSS", value: "qiniuoss" },
{ label: "S3/Minio", value: "s3" },
{ label: "SSH(已废弃请选择SFTP方式)", value: "ssh", disabled: true },
],
}),
};

View File

@@ -1 +1 @@
export const CertApplyPluginNames = ["CertApply", "CertApplyLego", "CertApplyUpload"];
export const CertApplyPluginNames = [":cert:"];

View File

@@ -57,6 +57,7 @@ export default {
passwordPlaceholder: "Please enter your password",
mobilePlaceholder: "Please enter your mobile number",
loginButton: "Log In",
forgotPassword: "Forgot password?",
forgotAdminPassword: "Forgot admin password?",
registerLink: "Register",

View File

@@ -78,6 +78,7 @@ export default {
runCount: "Run Count",
expiringCerts: "Soon-to-Expire Certificates",
supportedTasks: "Overview of Supported Deployment Tasks",
changeLog: "Change Log",
},
steps: {
createPipeline: "Create Certificate Pipeline",
@@ -273,8 +274,7 @@ export default {
monitorCronSetting: "Monitoring Schedule",
cronTrigger: "Scheduled trigger for monitoring",
dnsServer: "DNS Server",
// dnsServerHelper: "使用自定义的域名解析服务器1.1.1.1,8.8.8.8",
dnsServerHelper: "Use a custom domain name resolution server, such as: 1.1.1.1,8.8.8.8",
dnsServerHelper: "Use a custom domain name resolution server, such as: 1.1.1.1 , support multiple",
},
},
checkStatus: {
@@ -450,7 +450,7 @@ export default {
batchDeleteConfirm: "Are you sure to batch delete these {count} records?",
selectRecordFirst: "Please select records first",
subdomainHosted: "Hosted Subdomain",
subdomainHelpText: "If you don't understand what subdomain hosting is, please refer to the documentation ",
subdomainHelpText: "If you don't understand what subdomain hosting is,Do not set it randomly, as it may result in the inability to apply for the certificate. please refer to the documentation ",
subdomainManagement: "Subdomain Management",
isDisabled: "Is Disabled",
enabled: "Enabled",
@@ -565,6 +565,7 @@ export default {
dualStackNetworkHelper: "If IPv6 priority is selected, enable IPv6 in docker-compose.yaml",
enableCommonCnameService: "Enable Public CNAME Service",
commonCnameHelper: "Allow use of public CNAME service. If disabled and no <router-link to='/sys/cname/provider'>custom CNAME service</router-link> is set, CNAME proxy certificate application will not work.",
enableCommonSelfServicePasswordRetrieval: "Enable self-service password recovery",
saveButton: "Save",
stopSuccess: "Stopped successfully",
google: "Google",
@@ -709,4 +710,22 @@ export default {
showRunStrategyHelper: "Allow modify the run strategy of the task",
},
},
modal: {
close: "Close",
viewCertificateTitle: "View Certificate",
},
domain: {
domainManager: "Domain Manager",
domainDescription: "used to auto apply for certificate", //管理域名的校验方式,用于申请证书时自动选择验证方式
domain: "Domain",
challengeType: "Challenge Type",
dnsProviderType: "DNS Provider Type",
dnsProviderAccess: "DNS Provider Access",
httpUploaderType: "HTTP Uploader Type",
httpUploaderAccess: "HTTP Uploader Access",
httpUploadRootDir: "HTTP Upload Root Dir",
disabled: "Disabled",
challengeSetting: "Challenge Setting",
gotoCnameTip: "Please go to CNAME Record Page",
},
};

View File

@@ -14,6 +14,8 @@ export default {
search: "Search",
enabled: "Enabled",
disabled: "Disabled",
enable: "Enable",
disable: "Disable",
edit: "Edit",
delete: "Delete",
create: "Create",

View File

@@ -57,6 +57,7 @@ export default {
passwordPlaceholder: "请输入密码",
mobilePlaceholder: "请输入手机号",
loginButton: "登录",
forgotPassword: "忘记密码?",
forgotAdminPassword: "忘记管理员密码?",
registerLink: "注册",

View File

@@ -84,6 +84,7 @@ export default {
runCount: "运行次数",
expiringCerts: "最快到期证书",
supportedTasks: "已支持的部署任务总览",
changeLog: "更新日志",
},
steps: {
createPipeline: "创建证书流水线",
@@ -278,7 +279,7 @@ export default {
monitorCronSetting: "监控定时设置",
cronTrigger: "定时触发监控",
dnsServer: "DNS服务器",
dnsServerHelper: "使用自定义的域名解析服务器1.1.1.1,8.8.8.8",
dnsServerHelper: "使用自定义的域名解析服务器1.1.1.1 , 支持多个",
},
},
checkStatus: {
@@ -415,7 +416,7 @@ export default {
is_present_no: "否",
basicInfo: "基础信息",
titlea: "名称",
disabled: "是否禁用",
disabled: "禁用",
ordera: "排序",
supportBuy: "支持购买",
intro: "介绍",
@@ -455,7 +456,7 @@ export default {
batchDeleteConfirm: "确定要批量删除这{count}条记录吗",
selectRecordFirst: "请先勾选记录",
subdomainHosted: "托管的子域名",
subdomainHelpText: "如果您不理解什么是子域托管,可以参考文档",
subdomainHelpText: "如果您不理解什么是子域托管,请不要随意设置,可能导致证书无法申请,可以参考文档",
subdomainManagement: "子域管理",
isDisabled: "是否禁用",
enabled: "启用",
@@ -570,6 +571,7 @@ export default {
dualStackNetworkHelper: "如果选择IPv6优先需要在docker-compose.yaml中启用ipv6",
enableCommonCnameService: "启用公共CNAME服务",
commonCnameHelper: "是否可以使用公共CNAME服务如果禁用且没有设置<router-link to='/sys/cname/provider'>自定义CNAME服务</router-link>则无法使用CNAME代理方式申请证书",
enableCommonSelfServicePasswordRetrieval: "启用自助找回密码",
saveButton: "保存",
stopSuccess: "停止成功",
google: "Google",
@@ -711,4 +713,22 @@ export default {
showRunStrategyHelper: "任务设置中是否允许选择运行策略",
},
},
modal: {
close: "关闭",
viewCertificateTitle: "查看证书",
},
domain: {
domainManager: "域名管理",
domainDescription: "管理域名的校验方式,用于申请证书时自动选择验证方式",
domain: "域名",
challengeType: "校验类型",
dnsProviderType: "DNS提供商类型",
dnsProviderAccess: "DNS提供商授权",
httpUploaderType: "上传方式",
httpUploaderAccess: "上传授权信息",
httpUploadRootDir: "网站根路径",
disabled: "禁用/启用",
challengeSetting: "校验配置",
gotoCnameTip: "CNAME域名配置请前往CNAME记录页面添加",
},
};

View File

@@ -14,6 +14,8 @@ export default {
search: "搜索",
enabled: "已启用",
disabled: "已禁用",
enable: "启用",
disable: "禁用",
edit: "修改",
delete: "删除",
create: "新增",

View File

@@ -116,6 +116,17 @@ export const certdResources = [
keepAlive: true,
},
},
{
title: "certd.domain.domainManager",
name: "DomainManager",
path: "/certd/cert/domain",
component: "/certd/cert/domain/index.vue",
meta: {
icon: "ion:globe-outline",
auth: true,
keepAlive: true,
},
},
{
title: "certd.cnameRecord",
name: "CnameRecord",

View File

@@ -24,6 +24,14 @@ export const outsideResource = [
path: "/register",
component: "/framework/register/index.vue",
},
{
meta: {
title: "找回密码",
},
name: "forgotPassword",
path: "/forgotPassword",
component: "/framework/forgot-password/index.vue",
},
],
},
...errorPage,

View File

@@ -87,10 +87,13 @@ export class PluginGroups {
for (const step of steps) {
const stepDefine = this.get(step.type);
for (const key in stepDefine?.output) {
const inputDefine = stepDefine.output[key];
options.push({
value: `step.${step.id}.${key}`,
label: `${stepDefine.output[key].title}【from${step.title}`,
label: `${inputDefine.title}【from${step.title}`,
type: step.type,
valueType: inputDefine.type,
key: key,
});
}
}

View File

@@ -36,6 +36,7 @@ export type SysPublicSetting = {
emailRegisterEnabled?: boolean;
passwordLoginEnabled?: boolean;
smsLoginEnabled?: boolean;
selfServicePasswordRetrievalEnabled?: boolean;
limitUserPipelineCount?: number;
managerOtherUserPipeline?: boolean;

View File

@@ -46,6 +46,10 @@ export interface SettingState {
price3: number;
tooltip?: string;
};
app?: {
minVersion?: string;
minVersionTip?: string;
};
};
}
@@ -107,6 +111,10 @@ export const useSettingStore = defineStore({
price: 399,
price3: 899,
},
app: {
minVersion: "",
minVersionTip: "",
},
},
}),
getters: {

View File

@@ -20,6 +20,17 @@ export interface SmsLoginReq {
randomStr: string;
}
export interface ForgotPasswordReq {
forgotPasswordType: string;
input: string;
randomStr: string;
imgCode: string;
validateCode: string;
password: string;
confirmPassword: string;
}
export interface UserInfoRes {
id: string | number;
username: string;
@@ -43,6 +54,13 @@ export async function register(user: RegisterReq): Promise<UserInfoRes> {
data: user,
});
}
export async function forgotPassword(data: ForgotPasswordReq): Promise<any> {
return await request({
url: "/forgotPassword",
method: "post",
data: data,
});
}
export async function logout() {
return await request({
url: "/logout",

View File

@@ -4,7 +4,7 @@ import router from "../../router";
import { LocalStorage } from "/src/utils/util.storage";
// @ts-ignore
import * as UserApi from "./api.user";
import { RegisterReq, SmsLoginReq } from "./api.user";
import { ForgotPasswordReq, RegisterReq, SmsLoginReq } from "./api.user";
// @ts-ignore
import { LoginReq, UserInfoRes } from "/@/store/user/api.user";
import { message, Modal, notification } from "ant-design-vue";
@@ -67,6 +67,13 @@ export const useUserStore = defineStore({
});
await router.replace("/login");
},
async forgotPassword(params: ForgotPasswordReq): Promise<any> {
await UserApi.forgotPassword(params);
notification.success({
message: "密码已重置,请登录",
});
await router.replace("/login");
},
/**
* @description: login
*/

View File

@@ -488,7 +488,7 @@ const idMainContent = ELEMENT_ID_MAIN_CONTENT;
</template>
</LayoutContent>
<LayoutFooter v-if="footerEnable" class="hidden md:block" :fixed="footerFixed" :height="footerHeight" :show="!isFullContent" :width="footerWidth" :z-index="zIndex + 2">
<LayoutFooter v-if="footerEnable" class="hidden md:block" :fixed="footerFixed" :height="footerHeight" :show="!isFullContent" :width="footerWidth" :z-index="zIndex">
<slot name="footer"></slot>
</LayoutFooter>
</div>

View File

@@ -112,7 +112,8 @@ function menuIcon(menu: MenuRecordRaw) {
.vben-normal-menu__name,
.vben-normal-menu__icon {
@apply text-primary-foreground font-semibold;
//@apply text-primary-foreground font-semibold;
@apply font-semibold;
}
}

View File

@@ -2,7 +2,7 @@
import { ref } from "vue";
import { getCommonColumnDefine } from "/@/views/certd/access/common";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
import { useI18n } from "vue-i18n";
import { useI18n } from "/src/locales";
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const { t } = useI18n();
@@ -57,7 +57,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
show: false,
},
search: {
show: false,
show: true,
},
form: {
wrapper: {

View File

@@ -55,6 +55,14 @@ export function createAccessApi(from = "user") {
});
},
async GetDictByIds(ids: number[]) {
return await request({
url: apiPrefix + "/getDictByIds",
method: "post",
data: { ids },
});
},
async GetSecretPlain(id: number, key: string) {
return await request({
url: apiPrefix + "/getSecretPlain",

View File

@@ -1,5 +1,5 @@
// @ts-ignore
import { useI18n } from "vue-i18n";
import { useI18n } from "/src/locales";
import { ref } from "vue";
import { getCommonColumnDefine } from "/@/views/certd/access/common";
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";

View File

@@ -15,7 +15,7 @@ import { defineComponent, onActivated, onMounted } from "vue";
import { useFs } from "@fast-crud/fast-crud";
import createCrudOptions from "./crud";
import { createAccessApi } from "/@/views/certd/access/api";
import { useI18n } from "vue-i18n";
import { useI18n } from "/src/locales";
export default defineComponent({
name: "AccessManager",

View File

@@ -0,0 +1,60 @@
import { request } from "/src/api/service";
const apiPrefix = "/cert/domain";
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 },
});
}

View File

@@ -0,0 +1,330 @@
import * as api from "./api";
import { useI18n } from "/src/locales";
import { Ref, ref } from "vue";
import { useRouter } from "vue-router";
import { AddReq, compute, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
import { useUserStore } from "/@/store/user";
import { useSettingStore } from "/@/store/settings";
import { Dicts } from "/@/components/plugins/lib/dicts";
import { createAccessApi } from "/@/views/certd/access/api";
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) => {
const res = await api.AddObj(form);
return res;
};
const userStore = useUserStore();
const settingStore = useSettingStore();
const selectedRowKeys: Ref<any[]> = ref([]);
context.selectedRowKeys = selectedRowKeys;
const accessApi = createAccessApi();
const accessDict = dict({
value: "id",
label: "name",
url: "accessDict",
async getNodesByValues(ids: number[]) {
return await accessApi.GetDictByIds(ids);
},
});
const httpUploaderTypeDict = Dicts.uploaderTypeDict;
const dnsProviderTypeDict = dict({
url: "pi/dnsProvider/dnsProviderTypeDict",
});
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,
},
tabs: {
name: "challengeType",
show: true,
},
rowHandle: {
minWidth: 200,
fixed: "right",
},
form: {
beforeSubmit({ form }) {
if (form.challengeType === "cname") {
throw new Error("CNAME方式请前往CNAME记录页面进行管理");
}
},
},
columns: {
id: {
title: "ID",
key: "id",
type: "number",
column: {
width: 80,
},
form: {
show: false,
},
},
domain: {
title: t("certd.domain.domain"),
type: "text",
search: {
show: true,
},
form: {
required: true,
},
editForm: {
component: {
disabled: false,
},
},
column: {
sorter: true,
},
},
challengeType: {
title: t("certd.domain.challengeType"),
type: "dict-select",
dict: Dicts.challengeTypeDict,
search: {
show: true,
},
form: {
required: true,
valueChange({ value }) {
if (value === "cname") {
Modal.confirm({
title: t("certd.domain.gotoCnameTip"),
async onOk() {
router.push({
path: "/certd/cname/record",
});
crudExpose.getFormWrapperRef().close();
},
});
}
},
},
column: {
sorter: true,
show: false,
},
},
/**
* challengeType varchar(50),
* dnsProviderType varchar(50),
* dnsProviderAccess bigint,
* httpUploaderType varchar(50),
* httpUploaderAccess bigint,
* httpUploadRootDir varchar(512),
*/
dnsProviderType: {
title: t("certd.domain.dnsProviderType"),
type: "dict-select",
dict: dnsProviderTypeDict,
form: {
component: {
name: "DnsProviderSelector",
},
show: compute(({ form }) => {
return form.challengeType === "dns";
}),
required: true,
},
column: {
show: false,
component: {
color: "auto",
},
},
},
dnsProviderAccess: {
title: t("certd.domain.dnsProviderAccess"),
type: "dict-select",
dict: accessDict,
form: {
component: {
name: "AccessSelector",
vModel: "modelValue",
type: compute(({ form }) => {
return form.dnsProviderType;
}),
},
show: compute(({ form }) => {
return form.challengeType === "dns";
}),
required: true,
},
column: {
show: false,
component: {
color: "auto",
},
},
},
httpUploaderType: {
title: t("certd.domain.httpUploaderType"),
type: "dict-select",
dict: Dicts.uploaderTypeDict,
form: {
show: compute(({ form }) => {
return form.challengeType === "http";
}),
required: true,
},
column: {
show: false,
component: {
color: "auto",
},
},
},
httpUploaderAccess: {
title: t("certd.domain.httpUploaderAccess"),
type: "text",
form: {
component: {
name: "AccessSelector",
vModel: "modelValue",
type: compute(({ form }) => {
return form.httpUploaderType;
}),
},
show: compute(({ form }) => {
return form.challengeType === "http";
}),
required: true,
},
column: {
show: false,
component: {
color: "auto",
},
},
},
httpUploadRootDir: {
title: t("certd.domain.httpUploadRootDir"),
type: "text",
form: {
show: compute(({ form }) => {
return form.challengeType === "http";
}),
required: true,
},
column: {
show: false,
component: {
color: "auto",
},
},
},
challengeSetting: {
title: t("certd.domain.challengeSetting"),
type: "text",
form: { show: false },
column: {
width: 600,
conditionalRender: false,
cellRender({ row }) {
if (row.challengeType === "dns") {
return (
<div class={"flex"}>
<fs-values-format modelValue={row.challengeType} dict={Dicts.challengeTypeDict} color={"auto"}></fs-values-format>
<fs-values-format modelValue={row.dnsProviderType} dict={dnsProviderTypeDict} color={"auto"}></fs-values-format>
<fs-values-format class={"ml-5"} modelValue={row.dnsProviderAccess} dict={accessDict} color={"auto"}></fs-values-format>
</div>
);
} else if (row.challengeType === "http") {
return (
<div class={"flex"}>
<fs-values-format modelValue={row.challengeType} dict={Dicts.challengeTypeDict} color={"auto"}></fs-values-format>
<fs-values-format modelValue={row.httpUploaderType} dict={httpUploaderTypeDict} color={"auto"}></fs-values-format>
<fs-values-format class={"ml-5"} modelValue={row.httpUploaderAccess} dict={accessDict} color={"auto"}></fs-values-format>
<a-tag class={"ml-5 flex items-center"}>{row.httpUploadRootDir}</a-tag>
</div>
);
}
},
},
},
disabled: {
title: t("certd.domain.disabled"),
type: "dict-switch",
search: { show: true },
dict: dict({
data: [
{ label: t("common.enabled"), value: false, color: "green" },
{ label: t("common.disabled"), value: true, color: "red" },
],
}),
form: {
value: false,
required: true,
},
column: {
width: 100,
sorter: true,
},
},
createTime: {
title: t("certd.createTime"),
type: "datetime",
form: {
show: false,
},
column: {
sorter: true,
width: 160,
align: "center",
},
},
updateTime: {
title: t("certd.updateTime"),
type: "datetime",
form: {
show: false,
},
column: {
show: true,
},
},
},
},
};
}

View File

@@ -0,0 +1,62 @@
<template>
<fs-page class="page-cert">
<template #header>
<div class="title">
{{ t("certd.domain.domainManager") }}
<span class="sub">
{{ t("certd.domain.domainDescription") }}
</span>
</div>
</template>
<fs-crud ref="crudRef" v-bind="crudBinding">
<template #pagination-left>
<a-tooltip :title="t('certd.batch_delete')">
<fs-button icon="DeleteOutlined" @click="handleBatchDelete"></fs-button>
</a-tooltip>
</template>
</fs-crud>
</fs-page>
</template>
<script lang="ts" setup>
import { onActivated, 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";
import { useI18n } from "/src/locales";
const { t } = useI18n();
defineOptions({
name: "DomainManager",
});
const { crudBinding, crudRef, crudExpose, context } = useFs({ createCrudOptions });
const selectedRowKeys = context.selectedRowKeys;
const handleBatchDelete = () => {
if (selectedRowKeys.value?.length > 0) {
Modal.confirm({
title: t("certd.confirm"),
content: t("certd.confirm_delete_count", { count: selectedRowKeys.value.length }),
async onOk() {
await DeleteBatch(selectedRowKeys.value);
message.info(t("certd.delete_successful"));
crudExpose.doRefresh();
selectedRowKeys.value = [];
},
});
} else {
message.error(t("certd.please_select_records"));
}
};
// 页面打开后获取列表数据
onMounted(() => {
crudExpose.doRefresh();
});
onActivated(async () => {
await crudExpose.doRefresh();
});
</script>
<style lang="less"></style>

View File

@@ -1,5 +1,5 @@
import * as api from "./api";
import { useI18n } from "vue-i18n";
import { useI18n } from "/src/locales";
import { Ref, ref } from "vue";
import { useRouter } from "vue-router";
import { AddReq, compute, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";

View File

@@ -26,7 +26,7 @@ import { useFs } from "@fast-crud/fast-crud";
import createCrudOptions from "./crud";
import { message, Modal } from "ant-design-vue";
import { DeleteBatch } from "./api";
import { useI18n } from "vue-i18n";
import { useI18n } from "/src/locales";
const { t } = useI18n();

View File

@@ -1,5 +1,5 @@
import * as api from "./api";
import { useI18n } from "vue-i18n";
import { useI18n } from "/src/locales";
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";

View File

@@ -19,7 +19,7 @@ import { useFs } from "@fast-crud/fast-crud";
import createCrudOptions from "./crud";
import { message, Modal } from "ant-design-vue";
import { DeleteBatch } from "./api";
import { useI18n } from "vue-i18n";
import { useI18n } from "/src/locales";
const { t } = useI18n();

View File

@@ -6,7 +6,7 @@
<script setup lang="ts">
import { ref } from "vue";
import { useI18n } from "vue-i18n";
import { useI18n } from "/src/locales";
const { t } = useI18n();
import { CrudOptions, useColumns, useFormWrapper } from "@fast-crud/fast-crud";

View File

@@ -79,7 +79,7 @@ import { UserTwoFactorSetting } from "./api";
import { Modal, notification } from "ant-design-vue";
import { merge } from "lodash-es";
import { useSettingStore } from "/@/store/settings";
import { useI18n } from "vue-i18n";
import { useI18n } from "/src/locales";
const { t } = useI18n();
const settingsStore = useSettingStore();

Some files were not shown because too many files have changed in this diff Show More