mirror of
https://github.com/certd/certd.git
synced 2026-04-04 06:30:51 +08:00
Compare commits
74 Commits
alert-auto
...
v2-dev-plu
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ca20be197 | ||
|
|
17f23f3751 | ||
|
|
8e3d699856 | ||
|
|
f1a168fa53 | ||
|
|
3575113655 | ||
|
|
9feb9d04b3 | ||
|
|
5419b1439a | ||
|
|
e4489343fe | ||
|
|
d9f4a5793d | ||
|
|
70fcdc9ebb | ||
|
|
78e7a81638 | ||
|
|
58e82d5dbd | ||
|
|
06d15be43a | ||
|
|
e1e7011853 | ||
|
|
eff7645035 | ||
|
|
eb75e52278 | ||
|
|
15e6148272 | ||
|
|
ccd448a675 | ||
|
|
db54c019ad | ||
|
|
b762b4d72c | ||
|
|
2f8faa839d | ||
|
|
831c325c63 | ||
|
|
f4f73078c5 | ||
|
|
f7d43ad5af | ||
|
|
a77c777980 | ||
|
|
a34db7449e | ||
|
|
0283bd2f97 | ||
|
|
a8de2f8ae7 | ||
|
|
d5dee75df3 | ||
|
|
79cb5c0631 | ||
|
|
7d9901540f | ||
|
|
e979e9c9fb | ||
|
|
de719df6fe | ||
|
|
38d7f91ea0 | ||
|
|
a20a429e8c | ||
|
|
9b63fb4ee2 | ||
|
|
099efdbc1d | ||
|
|
af9120fc7a | ||
|
|
798a48aa96 | ||
|
|
462e22a3b0 | ||
|
|
4e432ed03f | ||
|
|
dfa74a69f7 | ||
|
|
9e1e4eeec2 | ||
|
|
221e068bac | ||
|
|
1bdceeecf4 | ||
|
|
a6824d9cd0 | ||
|
|
fe03f9942b | ||
|
|
4c196922fb | ||
|
|
2a9a513d85 | ||
|
|
2bcea27ecd | ||
|
|
fb7341f1f7 | ||
|
|
f327daa12d | ||
|
|
2872b9fbf9 | ||
|
|
cedd5c9c96 | ||
|
|
60e6aa9b54 | ||
|
|
541f482518 | ||
|
|
4019b7939a | ||
|
|
013b9c4c7c | ||
|
|
79addfda42 | ||
|
|
8546bda471 | ||
|
|
0770f174a1 | ||
|
|
5f4a89cecc | ||
|
|
cbe0b1c5a6 | ||
|
|
0af193c505 | ||
|
|
fdcfcc77a0 | ||
|
|
06d166d0d7 | ||
|
|
b1b3e39fcd | ||
|
|
5ec025a3b9 | ||
|
|
58b7fbcf75 | ||
|
|
be053d47e4 | ||
|
|
fae1981161 | ||
|
|
fd95549de9 | ||
|
|
ff10bc05ec | ||
|
|
eb8cd53de2 |
11
.editorconfig
Normal file
11
.editorconfig
Normal file
@@ -0,0 +1,11 @@
|
||||
#
|
||||
# http://editorconfig.org
|
||||
#
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
36
.github/ISSUE_TEMPLATE/1plugin.md
vendored
Normal file
36
.github/ISSUE_TEMPLATE/1plugin.md
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
---
|
||||
name: Plugin Apply
|
||||
about: 部署插件申请支持
|
||||
title: "[Plugin] "
|
||||
labels: feature
|
||||
---
|
||||
|
||||
> > 感谢您支持certd,请按如下规范提交issue
|
||||
> 如果有条件,请尽量在[github上提交](https://github.com/certd/certd/issues)
|
||||
|
||||
# 新部署插件申请支持
|
||||
|
||||
## 1. 需求描述
|
||||
`请在此处简要描述你的需求`
|
||||
|
||||
|
||||
## 2. 要部署证书应用的信息
|
||||
|
||||
1. 应用名称:
|
||||
|
||||
|
||||
2. 应用网址/项目地址/官方网站:
|
||||
|
||||
|
||||
3. 管理证书界面截图(或者手动部署证书方式介绍及截图):
|
||||
|
||||
|
||||
4. 是否有API接口,接口地址:
|
||||
|
||||
|
||||
5. 如果没有API接口,网页登录是否需要验证码:
|
||||
|
||||
|
||||
6. 是否可以提供测试账号?(如果可以请留下联系方式或者加作者好友)
|
||||
|
||||
|
||||
36
.github/ISSUE_TEMPLATE/2dns.md
vendored
Normal file
36
.github/ISSUE_TEMPLATE/2dns.md
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
---
|
||||
name: DNS Provider Apply
|
||||
about: 域名提供商申请支持
|
||||
title: "[DNS] "
|
||||
labels: feature
|
||||
---
|
||||
|
||||
|
||||
> 感谢您支持certd,请按如下规范提交issue
|
||||
> 如果有条件,请尽量在[github上提交](https://github.com/certd/certd/issues)
|
||||
|
||||
# 新域名提供商支持申请
|
||||
|
||||
## 1. 基本信息
|
||||
请填写如下内容:
|
||||
|
||||
1. 域名提供商名称:
|
||||
|
||||
|
||||
2. 管理页面地址:
|
||||
|
||||
|
||||
3. 是否有API接口,接口地址:
|
||||
|
||||
|
||||
4. 如果没有API接口,网页登录是否有验证码:
|
||||
|
||||
|
||||
5. 是否可以提供测试账号?(如果可以请留下联系方式或者加作者好友)
|
||||
|
||||
|
||||
|
||||
## 2. 截图
|
||||
|
||||
`域名管理页面截图`
|
||||
|
||||
@@ -1,21 +1,28 @@
|
||||
> 感谢您支持certd,请按如下规范提交issue
|
||||
---
|
||||
name: Bug Report
|
||||
about: 错误或问题报告
|
||||
title: "[BUG] "
|
||||
labels: bug
|
||||
---
|
||||
|
||||
|
||||
> 感谢您支持certd,请按如下规范提交issue
|
||||
> 如果有条件,请尽量在[github上提交](https://github.com/certd/certd/issues)
|
||||
|
||||
|
||||
## 一、问题描述
|
||||
# bug提交
|
||||
## 1、问题描述
|
||||
`请在此处简要描述你所遇到的问题,必要时请贴出相关截图辅助理解和定位`
|
||||
|
||||
### 复现步骤
|
||||
### 2、复现步骤
|
||||
`请描述复现问题的详细步骤`
|
||||
`如果非示例页面的问题,最好能提供最小复现示例的代码、或者仓库链接`
|
||||
|
||||
|
||||
### 报错截图
|
||||
### 3.报错截图
|
||||
`请贴出报错日志截图`
|
||||
|
||||
### 效果截图
|
||||
### 4、效果截图
|
||||
`请贴出效果截图`
|
||||
#### 1. 期望效果
|
||||
|
||||
#### 2. 实际效果
|
||||
#### 4.1. 期望效果
|
||||
|
||||
#### 4.2. 实际效果
|
||||
24
.github/ISSUE_TEMPLATE/4feature.md
vendored
Normal file
24
.github/ISSUE_TEMPLATE/4feature.md
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
---
|
||||
name: Feature Request
|
||||
about: 新需求、新特性申请支持
|
||||
title: "[Feature] "
|
||||
labels: feature
|
||||
---
|
||||
|
||||
> > 感谢您支持certd,请按如下规范提交issue
|
||||
> 如果有条件,请尽量在[github上提交](https://github.com/certd/certd/issues)
|
||||
|
||||
|
||||
# 新特性申请
|
||||
>注意:这里仅供如果是要申请新的部署插件,请提交插件申请
|
||||
|
||||
## 1. 需求描述,需求背景
|
||||
`请在此处简要描述你所遇到的问题,必要时请贴出相关截图辅助理解`
|
||||
|
||||
|
||||
## 2. 期望效果
|
||||
`必要时可以截图描述你的期望效果`
|
||||
|
||||
|
||||
## 3. 你的解决方案
|
||||
`如果你有解决方案,请描述你的方案`
|
||||
47
CHANGELOG.md
47
CHANGELOG.md
@@ -3,6 +3,53 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.36.17](https://github.com/certd/certd/compare/v1.36.16...v1.36.17) (2025-08-17)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复新部署的无法保存公共eab配置的bug ([d5dee75](https://github.com/certd/certd/commit/d5dee75df3bd635a597436e448b2de1407531f3a))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 阿里云 FC3.0 不在要求证书加密方式为旧版, 修复支持的协议类型可以正常选择 ([a34db74](https://github.com/certd/certd/commit/a34db7449eff6ad1dda01de673bf85579fa3865a))
|
||||
* 部署到腾讯云cdn,每个域名增加3每秒延迟 ([f7d43ad](https://github.com/certd/certd/commit/f7d43ad5af4663d4be369820a80d1fd9817ca4ab))
|
||||
* 腾讯云关闭证书通知增加开关选项,在腾讯云授权里面 ([a77c777](https://github.com/certd/certd/commit/a77c777980dd38d97d983124eeed1596879bba95))
|
||||
* 证书申请任务默认不发送申请成功通知 ([0283bd2](https://github.com/certd/certd/commit/0283bd2f978dbcd13d361129135e439dd9fbc180))
|
||||
|
||||
## [1.36.16](https://github.com/certd/certd/compare/v1.36.15...v1.36.16) (2025-08-16)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复授权配置复制功能,无法复制已加密字段的问题 ([221e068](https://github.com/certd/certd/commit/221e068bac3af6cd5d1794f8cd4c2ec5c0bc3f45))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 百度云支持上传到证书托管,支持部署到负载均衡 ([798a48a](https://github.com/certd/certd/commit/798a48aa9686fd5d11cfffb6cd93eadfc40aacb3))
|
||||
* 部署到百度cdn支持自动获取域名列表选择 ([4e432ed](https://github.com/certd/certd/commit/4e432ed03f4fb564e85a2f284ee26b58400b82f5))
|
||||
* 验证码可重试次数设置为3次 ([1bdceee](https://github.com/certd/certd/commit/1bdceeecf4b5daecdd621a05a2596b6eb45ce8ea))
|
||||
* 增加找回密码的验证码可重试次数 [@nicheng-he](https://github.com/nicheng-he) ([#496](https://github.com/certd/certd/issues/496)) ([fe03f99](https://github.com/certd/certd/commit/fe03f9942b5662fb90cad86da10782f5dc3603f5))
|
||||
* 支持阿里云API网关 ([9e1e4ee](https://github.com/certd/certd/commit/9e1e4eeec2859759ca5b07834c9d24cf88a6ad33))
|
||||
* 支持部署到金山云CDN ([dfa74a6](https://github.com/certd/certd/commit/dfa74a69f7cbb9009d3e20c7eecfa1b905a00cf0))
|
||||
* 支持更新金山云cdn证书 ([462e22a](https://github.com/certd/certd/commit/462e22a3b0a94887462fe6aa68e4671a365e0737))
|
||||
* 支持apisix证书部署 ([9b63fb4](https://github.com/certd/certd/commit/9b63fb4ee2c6b56139160c5bf63482dab0869c2b))
|
||||
|
||||
## [1.36.15](https://github.com/certd/certd/compare/v1.36.14...v1.36.15) (2025-08-07)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复 https://cas.undefined.aliyuncs.com 的bug ([60e6aa9](https://github.com/certd/certd/commit/60e6aa9b54a761a47e39acee4a1ff947a745be27))
|
||||
* 修复阿里云clb api接口没有使用region的问题 ([0770f17](https://github.com/certd/certd/commit/0770f174a14313e28d08113e69829ef6cc02d719))
|
||||
* 修复站点监控使用自定义dns解析域名报错的bug ([eb8cd53](https://github.com/certd/certd/commit/eb8cd53de27991321e36dd14e5ce95f42b51351f))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 部署到阿里云支持选择bucket和域名 ([013b9c4](https://github.com/certd/certd/commit/013b9c4c7c2adf485d086123ccea448719577fd4))
|
||||
* 清理数据库备份的临时目录 ([fd95549](https://github.com/certd/certd/commit/fd95549de9a5d8cec09772ee2630bb7521e15e1f))
|
||||
* 添加免费通知,OneBot V11协议通知支持 ([#491](https://github.com/certd/certd/issues/491)) [@ayakasuki](https://github.com/ayakasuki) ([be053d4](https://github.com/certd/certd/commit/be053d47e41084f817882400882b64143d036d1a))
|
||||
* 支持webhook部署证书 ([cbe0b1c](https://github.com/certd/certd/commit/cbe0b1c5a6538f232e9a63f1693d20d5acf0a306))
|
||||
* 注册时支持填写用户名 ([fdcfcc7](https://github.com/certd/certd/commit/fdcfcc77a0db87954e0b026635d3ccdd9bc6cee8))
|
||||
* add start:server npm script for quick server launch from root directory ([#484](https://github.com/certd/certd/issues/484)) [@orzyyyy](https://github.com/orzyyyy) ([fae1981](https://github.com/certd/certd/commit/fae1981161080f698c3f1263b712306d63baae64))
|
||||
|
||||
## [1.36.14](https://github.com/certd/certd/compare/v1.36.13...v1.36.14) (2025-07-28)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -1 +1 @@
|
||||
23:44
|
||||
23:58
|
||||
|
||||
@@ -11,6 +11,9 @@ services:
|
||||
# ↓↓↓↓↓ -------------------------------------------------------- 数据库以及证书存储路径,默认存在宿主机的/data/certd/目录下,【您需要定时备份此目录,以保障数据容灾】
|
||||
# 只要修改冒号前面的,冒号后面的/app/data不要动
|
||||
- /data/certd:/app/data
|
||||
# ↓↓↓↓↓ -------------------------------------------------------- 如果走时不准,考虑挂载localtime文件
|
||||
#- /etc/localtime:/etc/localtime
|
||||
#- /etc/timezone:/etc/timezone
|
||||
ports: # 端口映射
|
||||
# ↓↓↓↓ ---------------------------------------------------------- 如果端口有冲突,可以修改第一个7001为其他不冲突的端口号,第二个7001不要动
|
||||
- "7001:7001"
|
||||
@@ -38,11 +41,11 @@ services:
|
||||
# - ip6net
|
||||
environment:
|
||||
# ↓↓↓↓ ----------------------------------------------------- 使用上海东八时区
|
||||
# - TZ=Asia/Shanghai
|
||||
- TZ=Asia/Shanghai
|
||||
# 设置环境变量即可自定义certd配置
|
||||
# 配置项见: packages/ui/certd-server/src/config/config.default.ts
|
||||
# 配置规则: certd_ + 配置项, 点号用_代替
|
||||
# #↓↓↓↓ ----------------------------- 如果忘记管理员密码,可以设置为true,重启之后,管理员密码将改成123456,然后请及时修改回false
|
||||
# #↓↓↓↓ ----------------------------- 如果忘记管理员密码,可以设置为true,docker compose up -d 重建容器之后,管理员密码将改成123456,然后请及时修改回false
|
||||
- certd_system_resetAdminPasswd=false
|
||||
|
||||
# 默认使用sqlite文件数据库,如果需要使用其他数据库,请设置以下环境变量
|
||||
|
||||
@@ -3,6 +3,53 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.36.17](https://github.com/certd/certd/compare/v1.36.16...v1.36.17) (2025-08-17)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复新部署的无法保存公共eab配置的bug ([d5dee75](https://github.com/certd/certd/commit/d5dee75df3bd635a597436e448b2de1407531f3a))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 阿里云 FC3.0 不在要求证书加密方式为旧版, 修复支持的协议类型可以正常选择 ([a34db74](https://github.com/certd/certd/commit/a34db7449eff6ad1dda01de673bf85579fa3865a))
|
||||
* 部署到腾讯云cdn,每个域名增加3每秒延迟 ([f7d43ad](https://github.com/certd/certd/commit/f7d43ad5af4663d4be369820a80d1fd9817ca4ab))
|
||||
* 腾讯云关闭证书通知增加开关选项,在腾讯云授权里面 ([a77c777](https://github.com/certd/certd/commit/a77c777980dd38d97d983124eeed1596879bba95))
|
||||
* 证书申请任务默认不发送申请成功通知 ([0283bd2](https://github.com/certd/certd/commit/0283bd2f978dbcd13d361129135e439dd9fbc180))
|
||||
|
||||
## [1.36.16](https://github.com/certd/certd/compare/v1.36.15...v1.36.16) (2025-08-16)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复授权配置复制功能,无法复制已加密字段的问题 ([221e068](https://github.com/certd/certd/commit/221e068bac3af6cd5d1794f8cd4c2ec5c0bc3f45))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 百度云支持上传到证书托管,支持部署到负载均衡 ([798a48a](https://github.com/certd/certd/commit/798a48aa9686fd5d11cfffb6cd93eadfc40aacb3))
|
||||
* 部署到百度cdn支持自动获取域名列表选择 ([4e432ed](https://github.com/certd/certd/commit/4e432ed03f4fb564e85a2f284ee26b58400b82f5))
|
||||
* 验证码可重试次数设置为3次 ([1bdceee](https://github.com/certd/certd/commit/1bdceeecf4b5daecdd621a05a2596b6eb45ce8ea))
|
||||
* 增加找回密码的验证码可重试次数 [@nicheng-he](https://github.com/nicheng-he) ([#496](https://github.com/certd/certd/issues/496)) ([fe03f99](https://github.com/certd/certd/commit/fe03f9942b5662fb90cad86da10782f5dc3603f5))
|
||||
* 支持阿里云API网关 ([9e1e4ee](https://github.com/certd/certd/commit/9e1e4eeec2859759ca5b07834c9d24cf88a6ad33))
|
||||
* 支持部署到金山云CDN ([dfa74a6](https://github.com/certd/certd/commit/dfa74a69f7cbb9009d3e20c7eecfa1b905a00cf0))
|
||||
* 支持更新金山云cdn证书 ([462e22a](https://github.com/certd/certd/commit/462e22a3b0a94887462fe6aa68e4671a365e0737))
|
||||
* 支持apisix证书部署 ([9b63fb4](https://github.com/certd/certd/commit/9b63fb4ee2c6b56139160c5bf63482dab0869c2b))
|
||||
|
||||
## [1.36.15](https://github.com/certd/certd/compare/v1.36.14...v1.36.15) (2025-08-07)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复 https://cas.undefined.aliyuncs.com 的bug ([60e6aa9](https://github.com/certd/certd/commit/60e6aa9b54a761a47e39acee4a1ff947a745be27))
|
||||
* 修复阿里云clb api接口没有使用region的问题 ([0770f17](https://github.com/certd/certd/commit/0770f174a14313e28d08113e69829ef6cc02d719))
|
||||
* 修复站点监控使用自定义dns解析域名报错的bug ([eb8cd53](https://github.com/certd/certd/commit/eb8cd53de27991321e36dd14e5ce95f42b51351f))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 部署到阿里云支持选择bucket和域名 ([013b9c4](https://github.com/certd/certd/commit/013b9c4c7c2adf485d086123ccea448719577fd4))
|
||||
* 清理数据库备份的临时目录 ([fd95549](https://github.com/certd/certd/commit/fd95549de9a5d8cec09772ee2630bb7521e15e1f))
|
||||
* 添加免费通知,OneBot V11协议通知支持 ([#491](https://github.com/certd/certd/issues/491)) [@ayakasuki](https://github.com/ayakasuki) ([be053d4](https://github.com/certd/certd/commit/be053d47e41084f817882400882b64143d036d1a))
|
||||
* 支持webhook部署证书 ([cbe0b1c](https://github.com/certd/certd/commit/cbe0b1c5a6538f232e9a63f1693d20d5acf0a306))
|
||||
* 注册时支持填写用户名 ([fdcfcc7](https://github.com/certd/certd/commit/fdcfcc77a0db87954e0b026635d3ccdd9bc6cee8))
|
||||
* add start:server npm script for quick server launch from root directory ([#484](https://github.com/certd/certd/issues/484)) [@orzyyyy](https://github.com/orzyyyy) ([fae1981](https://github.com/certd/certd/commit/fae1981161080f698c3f1263b712306d63baae64))
|
||||
|
||||
## [1.36.14](https://github.com/certd/certd/compare/v1.36.13...v1.36.14) (2025-07-28)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
* 登录宝塔面板,在菜单栏中点击 Docker,首次进入会提示安装Docker服务,点击立即安装,按提示完成安装
|
||||
|
||||
### 2、部署certd
|
||||
以下两种方式人选一种:
|
||||
以下两种方式任选一种:
|
||||
|
||||
#### 2.1 应用商店方式一键部署【推荐】
|
||||
|
||||
* 在宝塔Docker应用商店中找到`certd`(要先点右上角更新应用)
|
||||
|
||||
@@ -65,8 +65,16 @@ networks:
|
||||
docker logs -f --tail 200 certd
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 6. 容器内走时不准,或者时区不对
|
||||
走时不准确,慢慢偏差越来越大
|
||||
或者整个时区都不对
|
||||
可以尝试挂载localtime文件
|
||||
```yaml
|
||||
volumes:
|
||||
# ↓↓↓↓↓ -------------------- 如果走时不准,请尝试挂载localtime文件
|
||||
- /etc/localtime:/etc/localtime
|
||||
- /etc/timezone:/etc/timezone
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,19 +2,24 @@
|
||||
|
||||
## 配置步骤
|
||||
|
||||
1. 创建应用,获取APPID
|
||||
|
||||
1. 注册支付宝商家账号
|
||||
* 开通电脑网站支付产品(需营业执照): https://b.alipay.com/page/product-workspace/all-product
|
||||
|
||||
|
||||
2. 开放平台,创建应用,获取APPID
|
||||
* 登录支付宝开放平台,进入开发者中心,创建网页应用,获取应用的AppId(左上角复制)
|
||||
* 开发者中心:https://open.alipay.com/develop/manage
|
||||
|
||||
|
||||
2. 进入应用详情,选择开发设置,配置接口加签方式 (选择密钥类型)
|
||||
3. 进入应用详情,选择开发设置,配置接口加签方式 (选择密钥类型)
|
||||
|
||||
* 参考文档:https://opendocs.alipay.com/common/02kdnc?pathHash=fb0c752a
|
||||
* 此步骤完成后,可以获取应用的私钥、支付宝公钥。
|
||||
* 注意:支付宝不会保存应用的私钥,你需要自己保管好私钥。
|
||||
|
||||
|
||||
3. 在Certd后台配置支付宝
|
||||
4. 在Certd后台配置支付宝
|
||||
|
||||
* 进入“系统”->"设置"->“支付设置”
|
||||
* 启用支付宝,选择“支付宝配置”,点击添加
|
||||
|
||||
@@ -9,5 +9,5 @@
|
||||
}
|
||||
},
|
||||
"npmClient": "pnpm",
|
||||
"version": "1.36.14"
|
||||
"version": "1.36.17"
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"start": "lerna bootstrap --hoist",
|
||||
"start:server": "cd ./packages/ui/certd-server && npm start",
|
||||
"devb": "lerna run dev-build",
|
||||
"i-all": "lerna link && lerna exec npm install ",
|
||||
"publish": "npm run prepublishOnly2 && lerna publish --force-publish=pro/plus-core --conventional-commits --create-release github && npm run afterpublishOnly && npm run commitAll",
|
||||
@@ -30,7 +31,7 @@
|
||||
"init": "lerna run build",
|
||||
"init:dev": "lerna run build",
|
||||
"docs:dev": "vitepress dev docs",
|
||||
"docs:build": "vitepress build docs",
|
||||
"docs:build": "npm run copylogs && vitepress build docs",
|
||||
"docs:preview": "vitepress preview docs",
|
||||
"pub": "echo 1"
|
||||
},
|
||||
|
||||
@@ -6,7 +6,7 @@ root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
indent_size = 2
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[{*.yml,*.yaml}]
|
||||
|
||||
@@ -3,6 +3,20 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.36.17](https://github.com/publishlab/node-acme-client/compare/v1.36.16...v1.36.17) (2025-08-17)
|
||||
|
||||
**Note:** Version bump only for package @certd/acme-client
|
||||
|
||||
## [1.36.16](https://github.com/publishlab/node-acme-client/compare/v1.36.15...v1.36.16) (2025-08-16)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 部署到百度cdn支持自动获取域名列表选择 ([4e432ed](https://github.com/publishlab/node-acme-client/commit/4e432ed03f4fb564e85a2f284ee26b58400b82f5))
|
||||
|
||||
## [1.36.15](https://github.com/publishlab/node-acme-client/compare/v1.36.14...v1.36.15) (2025-08-07)
|
||||
|
||||
**Note:** Version bump only for package @certd/acme-client
|
||||
|
||||
## [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
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"description": "Simple and unopinionated ACME client",
|
||||
"private": false,
|
||||
"author": "nmorsman",
|
||||
"version": "1.36.14",
|
||||
"version": "1.36.17",
|
||||
"type": "module",
|
||||
"module": "scr/index.js",
|
||||
"main": "src/index.js",
|
||||
@@ -18,7 +18,7 @@
|
||||
"types"
|
||||
],
|
||||
"dependencies": {
|
||||
"@certd/basic": "^1.36.14",
|
||||
"@certd/basic": "^1.36.17",
|
||||
"@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": "f3a90a63b66646a6beddcead43b4d4df7be704fc"
|
||||
"gitHead": "831c325c6383ba0a6f2dfa7496451ec714784e93"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,18 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.36.17](https://github.com/certd/certd/compare/v1.36.16...v1.36.17) (2025-08-17)
|
||||
|
||||
**Note:** Version bump only for package @certd/basic
|
||||
|
||||
## [1.36.16](https://github.com/certd/certd/compare/v1.36.15...v1.36.16) (2025-08-16)
|
||||
|
||||
**Note:** Version bump only for package @certd/basic
|
||||
|
||||
## [1.36.15](https://github.com/certd/certd/compare/v1.36.14...v1.36.15) (2025-08-07)
|
||||
|
||||
**Note:** Version bump only for package @certd/basic
|
||||
|
||||
## [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 +1 @@
|
||||
23:38
|
||||
23:53
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/basic",
|
||||
"private": false,
|
||||
"version": "1.36.14",
|
||||
"version": "1.36.17",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
@@ -45,5 +45,5 @@
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "f3a90a63b66646a6beddcead43b4d4df7be704fc"
|
||||
"gitHead": "831c325c6383ba0a6f2dfa7496451ec714784e93"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,21 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.36.17](https://github.com/certd/certd/compare/v1.36.16...v1.36.17) (2025-08-17)
|
||||
|
||||
**Note:** Version bump only for package @certd/pipeline
|
||||
|
||||
## [1.36.16](https://github.com/certd/certd/compare/v1.36.15...v1.36.16) (2025-08-16)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 百度云支持上传到证书托管,支持部署到负载均衡 ([798a48a](https://github.com/certd/certd/commit/798a48aa9686fd5d11cfffb6cd93eadfc40aacb3))
|
||||
* 支持部署到金山云CDN ([dfa74a6](https://github.com/certd/certd/commit/dfa74a69f7cbb9009d3e20c7eecfa1b905a00cf0))
|
||||
|
||||
## [1.36.15](https://github.com/certd/certd/compare/v1.36.14...v1.36.15) (2025-08-07)
|
||||
|
||||
**Note:** Version bump only for package @certd/pipeline
|
||||
|
||||
## [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,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/pipeline",
|
||||
"private": false,
|
||||
"version": "1.36.14",
|
||||
"version": "1.36.17",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
@@ -17,8 +17,8 @@
|
||||
"pub": "npm publish"
|
||||
},
|
||||
"dependencies": {
|
||||
"@certd/basic": "^1.36.14",
|
||||
"@certd/plus-core": "^1.36.14",
|
||||
"@certd/basic": "^1.36.17",
|
||||
"@certd/plus-core": "^1.36.17",
|
||||
"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": "f3a90a63b66646a6beddcead43b4d4df7be704fc"
|
||||
"gitHead": "831c325c6383ba0a6f2dfa7496451ec714784e93"
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ export type PageSearch = {
|
||||
// sortOrder?: "asc" | "desc";
|
||||
};
|
||||
|
||||
|
||||
export type PageRes = {
|
||||
pageNo?: number;
|
||||
pageSize?: number;
|
||||
|
||||
@@ -27,6 +27,7 @@ export const pluginGroups = {
|
||||
tencent: new PluginGroup("tencent", "腾讯云", 4, "svg:icon-tencentcloud"),
|
||||
volcengine: new PluginGroup("volcengine", "火山引擎", 4, "svg:icon-volcengine"),
|
||||
jdcloud: new PluginGroup("jdcloud", "京东云", 4, "svg:icon-jdcloud"),
|
||||
baidu: new PluginGroup("baidu", "百度云", 4, "ant-design:baidu-outlined"),
|
||||
qiniu: new PluginGroup("qiniu", "七牛云", 5, "svg:icon-qiniuyun"),
|
||||
aws: new PluginGroup("aws", "亚马逊云", 6, "svg:icon-aws"),
|
||||
other: new PluginGroup("other", "其他", 10, "clarity:plugin-line"),
|
||||
|
||||
@@ -3,6 +3,18 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.36.17](https://github.com/certd/certd/compare/v1.36.16...v1.36.17) (2025-08-17)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-huawei
|
||||
|
||||
## [1.36.16](https://github.com/certd/certd/compare/v1.36.15...v1.36.16) (2025-08-16)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-huawei
|
||||
|
||||
## [1.36.15](https://github.com/certd/certd/compare/v1.36.14...v1.36.15) (2025-08-07)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-huawei
|
||||
|
||||
## [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,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/lib-huawei",
|
||||
"private": false,
|
||||
"version": "1.36.14",
|
||||
"version": "1.36.17",
|
||||
"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": "f3a90a63b66646a6beddcead43b4d4df7be704fc"
|
||||
"gitHead": "831c325c6383ba0a6f2dfa7496451ec714784e93"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,18 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.36.17](https://github.com/certd/certd/compare/v1.36.16...v1.36.17) (2025-08-17)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-iframe
|
||||
|
||||
## [1.36.16](https://github.com/certd/certd/compare/v1.36.15...v1.36.16) (2025-08-16)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-iframe
|
||||
|
||||
## [1.36.15](https://github.com/certd/certd/compare/v1.36.14...v1.36.15) (2025-08-07)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-iframe
|
||||
|
||||
## [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,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/lib-iframe",
|
||||
"private": false,
|
||||
"version": "1.36.14",
|
||||
"version": "1.36.17",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
@@ -31,5 +31,5 @@
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "f3a90a63b66646a6beddcead43b4d4df7be704fc"
|
||||
"gitHead": "831c325c6383ba0a6f2dfa7496451ec714784e93"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,18 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.36.17](https://github.com/certd/certd/compare/v1.36.16...v1.36.17) (2025-08-17)
|
||||
|
||||
**Note:** Version bump only for package @certd/jdcloud
|
||||
|
||||
## [1.36.16](https://github.com/certd/certd/compare/v1.36.15...v1.36.16) (2025-08-16)
|
||||
|
||||
**Note:** Version bump only for package @certd/jdcloud
|
||||
|
||||
## [1.36.15](https://github.com/certd/certd/compare/v1.36.14...v1.36.15) (2025-08-07)
|
||||
|
||||
**Note:** Version bump only for package @certd/jdcloud
|
||||
|
||||
## [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,6 +1,6 @@
|
||||
{
|
||||
"name": "@certd/jdcloud",
|
||||
"version": "1.36.14",
|
||||
"version": "1.36.17",
|
||||
"description": "jdcloud openApi sdk",
|
||||
"main": "./dist/bundle.js",
|
||||
"module": "./dist/bundle.js",
|
||||
@@ -61,5 +61,5 @@
|
||||
"fetch"
|
||||
]
|
||||
},
|
||||
"gitHead": "f3a90a63b66646a6beddcead43b4d4df7be704fc"
|
||||
"gitHead": "831c325c6383ba0a6f2dfa7496451ec714784e93"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,18 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.36.17](https://github.com/certd/certd/compare/v1.36.16...v1.36.17) (2025-08-17)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-k8s
|
||||
|
||||
## [1.36.16](https://github.com/certd/certd/compare/v1.36.15...v1.36.16) (2025-08-16)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-k8s
|
||||
|
||||
## [1.36.15](https://github.com/certd/certd/compare/v1.36.14...v1.36.15) (2025-08-07)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-k8s
|
||||
|
||||
## [1.36.14](https://github.com/certd/certd/compare/v1.36.13...v1.36.14) (2025-07-28)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/lib-k8s",
|
||||
"private": false,
|
||||
"version": "1.36.14",
|
||||
"version": "1.36.17",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
@@ -17,7 +17,7 @@
|
||||
"pub": "npm publish"
|
||||
},
|
||||
"dependencies": {
|
||||
"@certd/basic": "^1.36.14",
|
||||
"@certd/basic": "^1.36.17",
|
||||
"@kubernetes/client-node": "0.21.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -32,5 +32,5 @@
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "f3a90a63b66646a6beddcead43b4d4df7be704fc"
|
||||
"gitHead": "831c325c6383ba0a6f2dfa7496451ec714784e93"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,20 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.36.17](https://github.com/certd/certd/compare/v1.36.16...v1.36.17) (2025-08-17)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-server
|
||||
|
||||
## [1.36.16](https://github.com/certd/certd/compare/v1.36.15...v1.36.16) (2025-08-16)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复授权配置复制功能,无法复制已加密字段的问题 ([221e068](https://github.com/certd/certd/commit/221e068bac3af6cd5d1794f8cd4c2ec5c0bc3f45))
|
||||
|
||||
## [1.36.15](https://github.com/certd/certd/compare/v1.36.14...v1.36.15) (2025-08-07)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-server
|
||||
|
||||
## [1.36.14](https://github.com/certd/certd/compare/v1.36.13...v1.36.14) (2025-07-28)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@certd/lib-server",
|
||||
"version": "1.36.14",
|
||||
"version": "1.36.17",
|
||||
"description": "midway with flyway, sql upgrade way ",
|
||||
"private": false,
|
||||
"type": "module",
|
||||
@@ -27,10 +27,10 @@
|
||||
],
|
||||
"license": "AGPL",
|
||||
"dependencies": {
|
||||
"@certd/acme-client": "^1.36.14",
|
||||
"@certd/basic": "^1.36.14",
|
||||
"@certd/pipeline": "^1.36.14",
|
||||
"@certd/plus-core": "^1.36.14",
|
||||
"@certd/acme-client": "^1.36.17",
|
||||
"@certd/basic": "^1.36.17",
|
||||
"@certd/pipeline": "^1.36.17",
|
||||
"@certd/plus-core": "^1.36.17",
|
||||
"@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": "f3a90a63b66646a6beddcead43b4d4df7be704fc"
|
||||
"gitHead": "831c325c6383ba0a6f2dfa7496451ec714784e93"
|
||||
}
|
||||
|
||||
@@ -34,7 +34,18 @@ export class AccessService extends BaseService<AccessEntity> {
|
||||
}
|
||||
|
||||
async add(param) {
|
||||
this.encryptSetting(param, null);
|
||||
let oldEntity = null;
|
||||
if (param._copyFrom){
|
||||
oldEntity = await this.info(param._copyFrom);
|
||||
if (oldEntity == null) {
|
||||
throw new ValidateException('该授权配置不存在,请确认是否已被删除');
|
||||
}
|
||||
if (oldEntity.userId !== param.userId) {
|
||||
throw new ValidateException('您无权查看该授权配置');
|
||||
}
|
||||
}
|
||||
delete param._copyFrom
|
||||
this.encryptSetting(param, oldEntity);
|
||||
return await super.add(param);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,18 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.36.17](https://github.com/certd/certd/compare/v1.36.16...v1.36.17) (2025-08-17)
|
||||
|
||||
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||
|
||||
## [1.36.16](https://github.com/certd/certd/compare/v1.36.15...v1.36.16) (2025-08-16)
|
||||
|
||||
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||
|
||||
## [1.36.15](https://github.com/certd/certd/compare/v1.36.14...v1.36.15) (2025-08-07)
|
||||
|
||||
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||
|
||||
## [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,6 +1,6 @@
|
||||
{
|
||||
"name": "@certd/midway-flyway-js",
|
||||
"version": "1.36.14",
|
||||
"version": "1.36.17",
|
||||
"description": "midway with flyway, sql upgrade way ",
|
||||
"private": false,
|
||||
"type": "module",
|
||||
@@ -46,5 +46,5 @@
|
||||
"typeorm": "^0.3.11",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "f3a90a63b66646a6beddcead43b4d4df7be704fc"
|
||||
"gitHead": "831c325c6383ba0a6f2dfa7496451ec714784e93"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,22 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.36.17](https://github.com/certd/certd/compare/v1.36.16...v1.36.17) (2025-08-17)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 证书申请任务默认不发送申请成功通知 ([0283bd2](https://github.com/certd/certd/commit/0283bd2f978dbcd13d361129135e439dd9fbc180))
|
||||
|
||||
## [1.36.16](https://github.com/certd/certd/compare/v1.36.15...v1.36.16) (2025-08-16)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 百度云支持上传到证书托管,支持部署到负载均衡 ([798a48a](https://github.com/certd/certd/commit/798a48aa9686fd5d11cfffb6cd93eadfc40aacb3))
|
||||
|
||||
## [1.36.15](https://github.com/certd/certd/compare/v1.36.14...v1.36.15) (2025-08-07)
|
||||
|
||||
**Note:** Version bump only for package @certd/plugin-cert
|
||||
|
||||
## [1.36.14](https://github.com/certd/certd/compare/v1.36.13...v1.36.14) (2025-07-28)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/plugin-cert",
|
||||
"private": false,
|
||||
"version": "1.36.14",
|
||||
"version": "1.36.17",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -16,10 +16,10 @@
|
||||
"pub": "npm publish"
|
||||
},
|
||||
"dependencies": {
|
||||
"@certd/acme-client": "^1.36.14",
|
||||
"@certd/basic": "^1.36.14",
|
||||
"@certd/pipeline": "^1.36.14",
|
||||
"@certd/plugin-lib": "^1.36.14",
|
||||
"@certd/acme-client": "^1.36.17",
|
||||
"@certd/basic": "^1.36.17",
|
||||
"@certd/pipeline": "^1.36.17",
|
||||
"@certd/plugin-lib": "^1.36.17",
|
||||
"@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": "f3a90a63b66646a6beddcead43b4d4df7be704fc"
|
||||
"gitHead": "831c325c6383ba0a6f2dfa7496451ec714784e93"
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ export type CertInfo = {
|
||||
der?: string;
|
||||
jks?: string;
|
||||
one?: string;
|
||||
p7b?: string;
|
||||
};
|
||||
export type SSLProvider = "letsencrypt" | "google" | "zerossl";
|
||||
export type PrivateKeyType = "rsa_1024" | "rsa_2048" | "rsa_3072" | "rsa_4096" | "ec_256" | "ec_384" | "ec_521";
|
||||
|
||||
@@ -125,6 +125,10 @@ export abstract class CertApplyBaseConvertPlugin extends AbstractTaskPlugin {
|
||||
cert.jks = res.jks;
|
||||
}
|
||||
|
||||
if (cert.p7b == null && res.p7b) {
|
||||
cert.p7b = res.p7b;
|
||||
}
|
||||
|
||||
this.logger.info("转换证书格式成功");
|
||||
} catch (e) {
|
||||
this.logger.error("转换证书格式失败", e);
|
||||
@@ -150,6 +154,7 @@ export abstract class CertApplyBaseConvertPlugin extends AbstractTaskPlugin {
|
||||
zip.file("intermediate.crt", cert.ic);
|
||||
zip.file("origin.crt", cert.oc);
|
||||
zip.file("one.pem", cert.one);
|
||||
zip.file("cert.p7b", cert.p7b);
|
||||
if (cert.pfx) {
|
||||
zip.file("cert.pfx", Buffer.from(cert.pfx, "base64"));
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ export abstract class CertApplyBasePlugin extends CertApplyBaseConvertPlugin {
|
||||
|
||||
@TaskInput({
|
||||
title: "证书申请成功通知",
|
||||
value: true,
|
||||
value: false,
|
||||
component: {
|
||||
name: "a-switch",
|
||||
vModel: "checked",
|
||||
@@ -41,7 +41,7 @@ export abstract class CertApplyBasePlugin extends CertApplyBaseConvertPlugin {
|
||||
order: 100,
|
||||
helper: "证书申请成功后是否发送通知,优先使用默认通知渠道",
|
||||
})
|
||||
successNotify = true;
|
||||
successNotify = false;
|
||||
|
||||
// @TaskInput({
|
||||
// title: "CsrInfo",
|
||||
|
||||
@@ -17,6 +17,7 @@ export type CertReaderHandleContext = {
|
||||
tmpIcPath?: string;
|
||||
tmpJksPath?: string;
|
||||
tmpOnePath?: string;
|
||||
tmpP7bPath?: string;
|
||||
};
|
||||
export type CertReaderHandle = (ctx: CertReaderHandleContext) => Promise<void>;
|
||||
export type HandleOpts = { logger: ILogger; handle: CertReaderHandle };
|
||||
@@ -124,7 +125,7 @@ export class CertReader {
|
||||
return domain;
|
||||
}
|
||||
|
||||
saveToFile(type: "crt" | "key" | "pfx" | "der" | "oc" | "one" | "ic" | "jks", filepath?: string) {
|
||||
saveToFile(type: "crt" | "key" | "pfx" | "der" | "oc" | "one" | "ic" | "jks" | "p7b", filepath?: string) {
|
||||
if (!this.cert[type]) {
|
||||
return;
|
||||
}
|
||||
@@ -138,7 +139,7 @@ export class CertReader {
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
}
|
||||
if (type === "crt" || type === "key" || type === "ic" || type === "oc" || type === "one") {
|
||||
if (type === "crt" || type === "key" || type === "ic" || type === "oc" || type === "one" || type === "p7b") {
|
||||
fs.writeFileSync(filepath, this.cert[type]);
|
||||
} else {
|
||||
fs.writeFileSync(filepath, Buffer.from(this.cert[type], "base64"));
|
||||
@@ -157,17 +158,19 @@ export class CertReader {
|
||||
const tmpDerPath = this.saveToFile("der");
|
||||
const tmpJksPath = this.saveToFile("jks");
|
||||
const tmpOnePath = this.saveToFile("one");
|
||||
const tmpP7bPath = this.saveToFile("p7b");
|
||||
logger.info("本地文件写入成功");
|
||||
try {
|
||||
return await opts.handle({
|
||||
reader: this,
|
||||
tmpCrtPath: tmpCrtPath,
|
||||
tmpKeyPath: tmpKeyPath,
|
||||
tmpPfxPath: tmpPfxPath,
|
||||
tmpDerPath: tmpDerPath,
|
||||
tmpIcPath: tmpIcPath,
|
||||
tmpJksPath: tmpJksPath,
|
||||
tmpOcPath: tmpOcPath,
|
||||
tmpCrtPath,
|
||||
tmpKeyPath,
|
||||
tmpPfxPath,
|
||||
tmpDerPath,
|
||||
tmpIcPath,
|
||||
tmpJksPath,
|
||||
tmpOcPath,
|
||||
tmpP7bPath,
|
||||
tmpOnePath,
|
||||
});
|
||||
} catch (err) {
|
||||
@@ -189,6 +192,7 @@ export class CertReader {
|
||||
removeFile(tmpIcPath);
|
||||
removeFile(tmpJksPath);
|
||||
removeFile(tmpOnePath);
|
||||
removeFile(tmpP7bPath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,4 +215,8 @@ export class CertReader {
|
||||
}
|
||||
return name + "_" + dayjs().format("YYYYMMDDHHmmssSSS");
|
||||
}
|
||||
|
||||
static buildCertName(cert: any) {
|
||||
return new CertReader(cert).buildCertName();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,11 +18,13 @@ export class CertConverter {
|
||||
pfx: string;
|
||||
der: string;
|
||||
jks: string;
|
||||
p7b: string;
|
||||
}> {
|
||||
const certReader = new CertReader(opts.cert);
|
||||
let pfx: string;
|
||||
let der: string;
|
||||
let jks: string;
|
||||
let p7b: string;
|
||||
const handle = async (ctx: CertReaderHandleContext) => {
|
||||
// 调用openssl 转pfx
|
||||
pfx = await this.convertPfx(ctx, opts.pfxPassword, opts.pfxArgs);
|
||||
@@ -31,6 +33,8 @@ export class CertConverter {
|
||||
der = await this.convertDer(ctx);
|
||||
|
||||
jks = await this.convertJks(ctx, opts.pfxPassword);
|
||||
|
||||
p7b = await this.convertP7b(ctx);
|
||||
};
|
||||
|
||||
await certReader.readCertFile({ logger: this.logger, handle });
|
||||
@@ -39,6 +43,7 @@ export class CertConverter {
|
||||
pfx,
|
||||
der,
|
||||
jks,
|
||||
p7b,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -95,6 +100,23 @@ export class CertConverter {
|
||||
return derCert;
|
||||
}
|
||||
|
||||
async convertP7b(opts: CertReaderHandleContext) {
|
||||
const { tmpCrtPath } = opts;
|
||||
const p7bPath = path.join(os.tmpdir(), "/certd/tmp/", Math.floor(Math.random() * 1000000) + `_cert.p7b`);
|
||||
const dir = path.dirname(p7bPath);
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
}
|
||||
//openssl crl2pkcs7 -nocrl \
|
||||
// -certfile your_domain.crt \
|
||||
// -certfile intermediate.crt \
|
||||
// -out chain.p7b
|
||||
await this.exec(`openssl crl2pkcs7 -nocrl -certfile ${tmpCrtPath} -out ${p7bPath}`);
|
||||
const fileBuffer = fs.readFileSync(p7bPath);
|
||||
const p7bCert = fileBuffer.toString();
|
||||
fs.unlinkSync(p7bPath);
|
||||
return p7bCert;
|
||||
}
|
||||
async convertJks(opts: CertReaderHandleContext, pfxPassword = "") {
|
||||
const jksPassword = pfxPassword || "123456";
|
||||
try {
|
||||
@@ -113,9 +135,7 @@ export class CertConverter {
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
}
|
||||
await this.exec(
|
||||
`keytool -importkeystore -srckeystore ${p12Path} -srcstoretype PKCS12 -srcstorepass "${jksPassword}" -destkeystore ${jksPath} -deststoretype PKCS12 -deststorepass "${jksPassword}" `
|
||||
);
|
||||
await this.exec(`keytool -importkeystore -srckeystore ${p12Path} -srcstoretype PKCS12 -srcstorepass "${jksPassword}" -destkeystore ${jksPath} -deststoretype PKCS12 -deststorepass "${jksPassword}" `);
|
||||
fs.unlinkSync(p12Path);
|
||||
|
||||
const fileBuffer = fs.readFileSync(jksPath);
|
||||
|
||||
@@ -3,6 +3,22 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.36.17](https://github.com/certd/certd/compare/v1.36.16...v1.36.17) (2025-08-17)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 腾讯云关闭证书通知增加开关选项,在腾讯云授权里面 ([a77c777](https://github.com/certd/certd/commit/a77c777980dd38d97d983124eeed1596879bba95))
|
||||
|
||||
## [1.36.16](https://github.com/certd/certd/compare/v1.36.15...v1.36.16) (2025-08-16)
|
||||
|
||||
**Note:** Version bump only for package @certd/plugin-lib
|
||||
|
||||
## [1.36.15](https://github.com/certd/certd/compare/v1.36.14...v1.36.15) (2025-08-07)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 支持webhook部署证书 ([cbe0b1c](https://github.com/certd/certd/commit/cbe0b1c5a6538f232e9a63f1693d20d5acf0a306))
|
||||
|
||||
## [1.36.14](https://github.com/certd/certd/compare/v1.36.13...v1.36.14) (2025-07-28)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/plugin-lib",
|
||||
"private": false,
|
||||
"version": "1.36.14",
|
||||
"version": "1.36.17",
|
||||
"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.14",
|
||||
"@certd/pipeline": "^1.36.14",
|
||||
"@certd/basic": "^1.36.17",
|
||||
"@certd/pipeline": "^1.36.17",
|
||||
"@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": "f3a90a63b66646a6beddcead43b4d4df7be704fc"
|
||||
"gitHead": "831c325c6383ba0a6f2dfa7496451ec714784e93"
|
||||
}
|
||||
|
||||
@@ -7,9 +7,9 @@ export type AliyunClientV2Req = {
|
||||
// 接口 HTTP 方法
|
||||
method?: "GET" | "POST";
|
||||
authType?: "AK";
|
||||
style?: "RPC";
|
||||
style?: "RPC" | "ROA";
|
||||
// 接口 PATH
|
||||
pathname?: `/`;
|
||||
pathname?: string;
|
||||
|
||||
data?: any;
|
||||
};
|
||||
@@ -63,10 +63,10 @@ export class AliyunClientV2 {
|
||||
protocol: "HTTPS",
|
||||
// 接口 HTTP 方法
|
||||
method: req.method ?? "POST",
|
||||
authType: "AK",
|
||||
style: "RPC",
|
||||
authType: req.authType ?? "AK",
|
||||
style: req.style ?? "RPC",
|
||||
// 接口 PATH
|
||||
pathname: `/`,
|
||||
pathname: req.pathname ?? `/`,
|
||||
// 接口请求体内容格式
|
||||
reqBodyType: "json",
|
||||
// 接口响应体内容格式
|
||||
|
||||
@@ -9,7 +9,8 @@ export type AliyunCertInfo = {
|
||||
export type AliyunSslClientOpts = {
|
||||
access: AliyunAccess;
|
||||
logger: ILogger;
|
||||
endpoint: string;
|
||||
endpoint?: string;
|
||||
region?: string;
|
||||
};
|
||||
|
||||
export type AliyunSslGetResourceListReq = {
|
||||
@@ -48,10 +49,19 @@ export class AliyunSslClient {
|
||||
async getClient() {
|
||||
const access = this.opts.access;
|
||||
const client = new AliyunClient({ logger: this.opts.logger });
|
||||
|
||||
let endpoint = this.opts.endpoint || "cas.aliyuncs.com";
|
||||
if (this.opts.endpoint == null && this.opts.region) {
|
||||
if (this.opts.region === "cn-hangzhou") {
|
||||
endpoint = "cas.aliyuncs.com";
|
||||
} else {
|
||||
endpoint = `cas.${this.opts.region}.aliyuncs.com`;
|
||||
}
|
||||
}
|
||||
await client.init({
|
||||
accessKeyId: access.accessKeyId,
|
||||
accessKeySecret: access.accessKeySecret,
|
||||
endpoint: `https://${this.opts.endpoint || "cas.aliyuncs.com"}`,
|
||||
endpoint: `https://${endpoint}`,
|
||||
apiVersion: "2020-04-07",
|
||||
});
|
||||
return client;
|
||||
|
||||
@@ -5,6 +5,7 @@ import { IsAccess, AccessInput, BaseAccess } from "@certd/pipeline";
|
||||
title: "天翼云授权",
|
||||
desc: "",
|
||||
icon: "ant-design:aliyun-outlined",
|
||||
order: 2,
|
||||
})
|
||||
export class CtyunAccess extends BaseAccess {
|
||||
@AccessInput({
|
||||
|
||||
@@ -6,6 +6,7 @@ import { AccessInput, BaseAccess, IsAccess } from "@certd/pipeline";
|
||||
desc: "",
|
||||
icon: "svg:icon-qiniuyun",
|
||||
input: {},
|
||||
order: 2,
|
||||
})
|
||||
export class QiniuAccess extends BaseAccess {
|
||||
@AccessInput({
|
||||
|
||||
@@ -5,6 +5,7 @@ import { AccessInput, BaseAccess, IsAccess } from "@certd/pipeline";
|
||||
desc: "",
|
||||
icon: "clarity:host-line",
|
||||
input: {},
|
||||
order: 0,
|
||||
})
|
||||
export class SshAccess extends BaseAccess {
|
||||
@AccessInput({
|
||||
@@ -45,8 +46,8 @@ export class SshAccess extends BaseAccess {
|
||||
title: "私钥登录",
|
||||
helper: "私钥或密码必填一项",
|
||||
component: {
|
||||
name: "a-textarea",
|
||||
vModel: "value",
|
||||
name: "pem-input",
|
||||
vModel: "modelValue",
|
||||
},
|
||||
encrypt: true,
|
||||
})
|
||||
|
||||
@@ -247,6 +247,9 @@ export class AsyncSsh2Client {
|
||||
const err = this.convert(iconv, ret);
|
||||
stdErr += err;
|
||||
hasErrorLog = true;
|
||||
if (err.includes("sudo: a password is required")) {
|
||||
this.logger.warn("请配置sudo免密,否则命令无法执行");
|
||||
}
|
||||
this.logger.error(`[${this.connConf.host}][error]: ` + err.trimEnd());
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,6 +4,7 @@ import { IsAccess, AccessInput, BaseAccess } from "@certd/pipeline";
|
||||
name: "tencent",
|
||||
title: "腾讯云",
|
||||
icon: "svg:icon-tencentcloud",
|
||||
order: 0,
|
||||
})
|
||||
export class TencentAccess extends BaseAccess {
|
||||
@AccessInput({
|
||||
@@ -46,7 +47,21 @@ export class TencentAccess extends BaseAccess {
|
||||
})
|
||||
accountType: string;
|
||||
|
||||
@AccessInput({
|
||||
title: "关闭证书过期通知",
|
||||
value: true,
|
||||
component: {
|
||||
name: "a-switch",
|
||||
vModel: "checked",
|
||||
},
|
||||
})
|
||||
closeExpiresNotify: boolean = true;
|
||||
|
||||
isIntl() {
|
||||
return this.accountType === "intl";
|
||||
}
|
||||
|
||||
intlDomain() {
|
||||
return this.isIntl() ? "intl." : "";
|
||||
}
|
||||
}
|
||||
|
||||
183
packages/plugins/plugin-lib/src/tencent/lib/cos-client.js
Normal file
183
packages/plugins/plugin-lib/src/tencent/lib/cos-client.js
Normal file
@@ -0,0 +1,183 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
||||
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.TencentCosClient = void 0;
|
||||
var basic_1 = require("@certd/basic");
|
||||
var fs_1 = require("fs");
|
||||
var TencentCosClient = /** @class */ (function () {
|
||||
function TencentCosClient(opts) {
|
||||
this.access = opts.access;
|
||||
this.logger = opts.logger;
|
||||
this.bucket = opts.bucket;
|
||||
this.region = opts.region;
|
||||
}
|
||||
TencentCosClient.prototype.getCosClient = function () {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var sdk, clientConfig;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0: return [4 /*yield*/, Promise.resolve().then(function () { return require("cos-nodejs-sdk-v5"); })];
|
||||
case 1:
|
||||
sdk = _a.sent();
|
||||
clientConfig = {
|
||||
SecretId: this.access.secretId,
|
||||
SecretKey: this.access.secretKey,
|
||||
};
|
||||
return [2 /*return*/, new sdk.default(clientConfig)];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
TencentCosClient.prototype.uploadFile = function (key, file) {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var cos;
|
||||
var _this = this;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0: return [4 /*yield*/, this.getCosClient()];
|
||||
case 1:
|
||||
cos = _a.sent();
|
||||
return [2 /*return*/, (0, basic_1.safePromise)(function (resolve, reject) {
|
||||
var readableStream = file;
|
||||
if (typeof file === "string") {
|
||||
readableStream = fs_1.default.createReadStream(file);
|
||||
}
|
||||
cos.putObject({
|
||||
Bucket: _this.bucket /* 必须 */,
|
||||
Region: _this.region /* 必须 */,
|
||||
Key: key /* 必须 */,
|
||||
Body: readableStream, // 上传文件对象
|
||||
onProgress: function (progressData) {
|
||||
console.log(JSON.stringify(progressData));
|
||||
},
|
||||
}, function (err, data) {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
resolve(data);
|
||||
});
|
||||
})];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
TencentCosClient.prototype.removeFile = function (key) {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var cos;
|
||||
var _this = this;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0: return [4 /*yield*/, this.getCosClient()];
|
||||
case 1:
|
||||
cos = _a.sent();
|
||||
return [2 /*return*/, (0, basic_1.safePromise)(function (resolve, reject) {
|
||||
cos.deleteObject({
|
||||
Bucket: _this.bucket,
|
||||
Region: _this.region,
|
||||
Key: key,
|
||||
}, function (err, data) {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
resolve(data);
|
||||
});
|
||||
})];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
TencentCosClient.prototype.downloadFile = function (key, savePath) {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var cos, writeStream;
|
||||
var _this = this;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0: return [4 /*yield*/, this.getCosClient()];
|
||||
case 1:
|
||||
cos = _a.sent();
|
||||
writeStream = fs_1.default.createWriteStream(savePath);
|
||||
return [2 /*return*/, (0, basic_1.safePromise)(function (resolve, reject) {
|
||||
cos.getObject({
|
||||
Bucket: _this.bucket,
|
||||
Region: _this.region,
|
||||
Key: key,
|
||||
Output: writeStream,
|
||||
}, function (err, data) {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
resolve(data);
|
||||
});
|
||||
})];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
TencentCosClient.prototype.listDir = function (dirKey) {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var cos;
|
||||
var _this = this;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0: return [4 /*yield*/, this.getCosClient()];
|
||||
case 1:
|
||||
cos = _a.sent();
|
||||
return [2 /*return*/, (0, basic_1.safePromise)(function (resolve, reject) {
|
||||
cos.getBucket({
|
||||
Bucket: _this.bucket,
|
||||
Region: _this.region,
|
||||
Prefix: dirKey,
|
||||
MaxKeys: 1000,
|
||||
}, function (err, data) {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
resolve(data.Contents);
|
||||
});
|
||||
})];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
return TencentCosClient;
|
||||
}());
|
||||
exports.TencentCosClient = TencentCosClient;
|
||||
@@ -26,7 +26,7 @@ export class TencentSslClient {
|
||||
region: this.region,
|
||||
profile: {
|
||||
httpProfile: {
|
||||
endpoint: "ssl.tencentcloudapi.com",
|
||||
endpoint: this.access.isIntl() ? "ssl.intl.tencentcloudapi.com" : "ssl.tencentcloudapi.com",
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -50,7 +50,10 @@ export class TencentSslClient {
|
||||
const ret = await client.UploadCertificate(params);
|
||||
this.checkRet(ret);
|
||||
this.logger.info(`证书[${opts.certName}]上传成功:tencentCertId=`, ret.CertificateId);
|
||||
await this.switchCertNotify([ret.CertificateId], true);
|
||||
if (this.access.closeExpiresNotify) {
|
||||
await this.switchCertNotify([ret.CertificateId], true);
|
||||
}
|
||||
|
||||
return ret.CertificateId;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,4 +9,5 @@ VITE_APP_COPYRIGHT_URL=https://certd.handsfree.work
|
||||
VITE_APP_LOGO=static/images/logo/logo.svg
|
||||
VITE_APP_LOGIN_LOGO=static/images/logo/rect-black.svg
|
||||
VITE_APP_PROJECT_PATH=https://github.com/certd/certd
|
||||
VITE_APP_NAMESPACE=fs
|
||||
VITE_APP_NAMESPACE=fs
|
||||
VITE_APP_VIP_PRODUCT_URL=http://localhost:1017/subject#/product/list
|
||||
@@ -3,6 +3,30 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.36.17](https://github.com/certd/certd/compare/v1.36.16...v1.36.17) (2025-08-17)
|
||||
|
||||
**Note:** Version bump only for package @certd/ui-client
|
||||
|
||||
## [1.36.16](https://github.com/certd/certd/compare/v1.36.15...v1.36.16) (2025-08-16)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复授权配置复制功能,无法复制已加密字段的问题 ([221e068](https://github.com/certd/certd/commit/221e068bac3af6cd5d1794f8cd4c2ec5c0bc3f45))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 增加找回密码的验证码可重试次数 [@nicheng-he](https://github.com/nicheng-he) ([#496](https://github.com/certd/certd/issues/496)) ([fe03f99](https://github.com/certd/certd/commit/fe03f9942b5662fb90cad86da10782f5dc3603f5))
|
||||
* 支持阿里云API网关 ([9e1e4ee](https://github.com/certd/certd/commit/9e1e4eeec2859759ca5b07834c9d24cf88a6ad33))
|
||||
* 支持部署到金山云CDN ([dfa74a6](https://github.com/certd/certd/commit/dfa74a69f7cbb9009d3e20c7eecfa1b905a00cf0))
|
||||
|
||||
## [1.36.15](https://github.com/certd/certd/compare/v1.36.14...v1.36.15) (2025-08-07)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 部署到阿里云支持选择bucket和域名 ([013b9c4](https://github.com/certd/certd/commit/013b9c4c7c2adf485d086123ccea448719577fd4))
|
||||
* 支持webhook部署证书 ([cbe0b1c](https://github.com/certd/certd/commit/cbe0b1c5a6538f232e9a63f1693d20d5acf0a306))
|
||||
* 注册时支持填写用户名 ([fdcfcc7](https://github.com/certd/certd/commit/fdcfcc77a0db87954e0b026635d3ccdd9bc6cee8))
|
||||
|
||||
## [1.36.14](https://github.com/certd/certd/compare/v1.36.13...v1.36.14) (2025-07-28)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@certd/ui-client",
|
||||
"version": "1.36.14",
|
||||
"version": "1.36.17",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite --open",
|
||||
@@ -43,7 +43,7 @@
|
||||
"@tailwindcss/typography": "^0.5.16",
|
||||
"@tanstack/vue-store": "^0.7.0",
|
||||
"@vee-validate/zod": "^4.15.0",
|
||||
"@vue-js-cron/light": "^4.0.5",
|
||||
"@certd/vue-js-cron-light": "^4.0.14",
|
||||
"@vue/shared": "^3.5.13",
|
||||
"@vueuse/core": "^10.11.0",
|
||||
"ant-design-vue": "^4.2.6",
|
||||
@@ -103,8 +103,8 @@
|
||||
"zod-defaults": "^0.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@certd/lib-iframe": "^1.36.14",
|
||||
"@certd/pipeline": "^1.36.14",
|
||||
"@certd/lib-iframe": "^1.36.17",
|
||||
"@certd/pipeline": "^1.36.17",
|
||||
"@rollup/plugin-commonjs": "^25.0.7",
|
||||
"@rollup/plugin-node-resolve": "^15.2.3",
|
||||
"@types/chai": "^4.3.12",
|
||||
@@ -120,7 +120,7 @@
|
||||
"@vue/compiler-sfc": "^3.4.21",
|
||||
"@vue/eslint-config-typescript": "^13.0.0",
|
||||
"@vue/test-utils": "^2.4.6",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"autoprefixer": "^10.4.21",
|
||||
"caller-path": "^4.0.0",
|
||||
"chai": "^5.1.0",
|
||||
"dependency-cruiser": "^16.2.3",
|
||||
|
||||
@@ -54,6 +54,36 @@
|
||||
<div class="content unicode" style="display: block;">
|
||||
<ul class="icon_lists dib-box">
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">social-foursquare</div>
|
||||
<div class="code-name">&#xe8fb;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">ksyun-logo</div>
|
||||
<div class="code-name">&#xe65a;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">雨-copy</div>
|
||||
<div class="code-name">&#xe608;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">网宿</div>
|
||||
<div class="code-name">&#xe655;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">ai客服</div>
|
||||
<div class="code-name">&#xe727;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">cdn</div>
|
||||
@@ -198,7 +228,7 @@
|
||||
<pre><code class="language-css"
|
||||
>@font-face {
|
||||
font-family: 'iconfont';
|
||||
src: url('iconfont.svg?t=1743267254898#iconfont') format('svg');
|
||||
src: url('iconfont.svg?t=1754884110189#iconfont') format('svg');
|
||||
}
|
||||
</code></pre>
|
||||
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
|
||||
@@ -224,6 +254,51 @@
|
||||
<div class="content font-class">
|
||||
<ul class="icon_lists dib-box">
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-four"></span>
|
||||
<div class="name">
|
||||
social-foursquare
|
||||
</div>
|
||||
<div class="code-name">.icon-four
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-ksyun"></span>
|
||||
<div class="name">
|
||||
ksyun-logo
|
||||
</div>
|
||||
<div class="code-name">.icon-ksyun
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-rainyun"></span>
|
||||
<div class="name">
|
||||
雨-copy
|
||||
</div>
|
||||
<div class="code-name">.icon-rainyun
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-wangsu"></span>
|
||||
<div class="name">
|
||||
网宿
|
||||
</div>
|
||||
<div class="code-name">.icon-wangsu
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-aikefu"></span>
|
||||
<div class="name">
|
||||
ai客服
|
||||
</div>
|
||||
<div class="code-name">.icon-aikefu
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-cdn"></span>
|
||||
<div class="name">
|
||||
@@ -440,6 +515,46 @@
|
||||
<div class="content symbol">
|
||||
<ul class="icon_lists dib-box">
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-four"></use>
|
||||
</svg>
|
||||
<div class="name">social-foursquare</div>
|
||||
<div class="code-name">#icon-four</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-ksyun"></use>
|
||||
</svg>
|
||||
<div class="name">ksyun-logo</div>
|
||||
<div class="code-name">#icon-ksyun</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-rainyun"></use>
|
||||
</svg>
|
||||
<div class="name">雨-copy</div>
|
||||
<div class="code-name">#icon-rainyun</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-wangsu"></use>
|
||||
</svg>
|
||||
<div class="name">网宿</div>
|
||||
<div class="code-name">#icon-wangsu</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-aikefu"></use>
|
||||
</svg>
|
||||
<div class="name">ai客服</div>
|
||||
<div class="code-name">#icon-aikefu</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-cdn"></use>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
@font-face {
|
||||
font-family: "iconfont"; /* Project id 4688792 */
|
||||
src: url('iconfont.svg?t=1743267254898#iconfont') format('svg');
|
||||
src: url('iconfont.svg?t=1754884110189#iconfont') format('svg');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
@@ -11,6 +11,26 @@
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.icon-four:before {
|
||||
content: "\e8fb";
|
||||
}
|
||||
|
||||
.icon-ksyun:before {
|
||||
content: "\e65a";
|
||||
}
|
||||
|
||||
.icon-rainyun:before {
|
||||
content: "\e608";
|
||||
}
|
||||
|
||||
.icon-wangsu:before {
|
||||
content: "\e655";
|
||||
}
|
||||
|
||||
.icon-aikefu:before {
|
||||
content: "\e727";
|
||||
}
|
||||
|
||||
.icon-cdn:before {
|
||||
content: "\e6e4";
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -5,6 +5,41 @@
|
||||
"css_prefix_text": "icon-",
|
||||
"description": "",
|
||||
"glyphs": [
|
||||
{
|
||||
"icon_id": "544964",
|
||||
"name": "social-foursquare",
|
||||
"font_class": "four",
|
||||
"unicode": "e8fb",
|
||||
"unicode_decimal": 59643
|
||||
},
|
||||
{
|
||||
"icon_id": "8567079",
|
||||
"name": "ksyun-logo",
|
||||
"font_class": "ksyun",
|
||||
"unicode": "e65a",
|
||||
"unicode_decimal": 58970
|
||||
},
|
||||
{
|
||||
"icon_id": "42174864",
|
||||
"name": "雨-copy",
|
||||
"font_class": "rainyun",
|
||||
"unicode": "e608",
|
||||
"unicode_decimal": 58888
|
||||
},
|
||||
{
|
||||
"icon_id": "14065547",
|
||||
"name": "网宿",
|
||||
"font_class": "wangsu",
|
||||
"unicode": "e655",
|
||||
"unicode_decimal": 58965
|
||||
},
|
||||
{
|
||||
"icon_id": "41324539",
|
||||
"name": "ai客服",
|
||||
"font_class": "aikefu",
|
||||
"unicode": "e727",
|
||||
"unicode_decimal": 59175
|
||||
},
|
||||
{
|
||||
"icon_id": "13592652",
|
||||
"name": "cdn",
|
||||
|
||||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 77 KiB |
@@ -4,8 +4,8 @@ import vip from "./vip-button/install.js";
|
||||
import { CheckCircleOutlined, InfoCircleOutlined, UndoOutlined } from "@ant-design/icons-vue";
|
||||
import CronEditor from "./cron-editor/index.vue";
|
||||
import FoldBox from "./fold-box.vue";
|
||||
import { CronLight } from "@vue-js-cron/light";
|
||||
import "@vue-js-cron/light/dist/light.css";
|
||||
import { CronLight } from "@certd/vue-js-cron-light";
|
||||
import "@certd/vue-js-cron-light/dist/light.css";
|
||||
import Plugins from "./plugins/index";
|
||||
import LoadingButton from "./loading-button.vue";
|
||||
import IconSelect from "./icon-select.vue";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="pem-input">
|
||||
<FileInput v-bind="fileInput" class="mb-5" type="primary" text="选择文件" @change="onChange" />
|
||||
<a-textarea v-bind="textarea" :value="modelValue" @update:value="emitValue"></a-textarea>
|
||||
<a-textarea placeholder="或直接粘贴" v-bind="textarea" :value="modelValue" @update:value="emitValue"></a-textarea>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -27,7 +27,7 @@ function onChange(e: any) {
|
||||
const size = file.size;
|
||||
if (size > 100 * 1024) {
|
||||
notification.error({
|
||||
message: "文件超过100k,请选择正确的证书文件",
|
||||
message: "文件超过100k,请选择正确的文件",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -100,6 +100,8 @@ const getOptions = async () => {
|
||||
const list = res?.list || res || [];
|
||||
if (list.length > 0) {
|
||||
message.value = "获取数据成功,请从下拉框中选择";
|
||||
} else {
|
||||
message.value = "获取数据成功,没有数据";
|
||||
}
|
||||
optionsRef.value = list;
|
||||
|
||||
|
||||
@@ -145,6 +145,8 @@ const getOptions = async () => {
|
||||
const list = res?.list || res || [];
|
||||
if (list.length > 0) {
|
||||
message.value = "获取数据成功,请从下拉框中选择";
|
||||
} else {
|
||||
message.value = "获取数据成功,没有数据";
|
||||
}
|
||||
optionsRef.value = list;
|
||||
pagerRef.value.total = list.length;
|
||||
|
||||
@@ -564,7 +564,7 @@ export default {
|
||||
ipv6Priority: "IPv6 Priority",
|
||||
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.",
|
||||
commonCnameHelper: "Allow use of public CNAME service. If disabled and no <a href='#/sys/cname/provider'>custom CNAME service</a> is set, CNAME proxy certificate application will not work.",
|
||||
enableCommonSelfServicePasswordRetrieval: "Enable self-service password recovery",
|
||||
saveButton: "Save",
|
||||
stopSuccess: "Stopped successfully",
|
||||
|
||||
@@ -570,7 +570,7 @@ export default {
|
||||
ipv6Priority: "IPV6优先",
|
||||
dualStackNetworkHelper: "如果选择IPv6优先,需要在docker-compose.yaml中启用ipv6",
|
||||
enableCommonCnameService: "启用公共CNAME服务",
|
||||
commonCnameHelper: "是否可以使用公共CNAME服务,如果禁用,且没有设置<router-link to='/sys/cname/provider'>自定义CNAME服务</router-link>,则无法使用CNAME代理方式申请证书",
|
||||
commonCnameHelper: "是否可以使用公共CNAME服务,如果禁用,且没有设置<a href='#/sys/cname/provider'>自定义CNAME服务</a>,则无法使用CNAME代理方式申请证书",
|
||||
enableCommonSelfServicePasswordRetrieval: "启用自助找回密码",
|
||||
saveButton: "保存",
|
||||
stopSuccess: "停止成功",
|
||||
|
||||
@@ -95,7 +95,7 @@ function install(app: App, options: any = {}) {
|
||||
|
||||
//不能用 !scope.value , 否则switch组件设置为关之后就消失了
|
||||
const { value, key, props } = scope;
|
||||
return !value && key != "_index" && value != false;
|
||||
return !value && key != "_index" && value != false && value != 0;
|
||||
},
|
||||
render() {
|
||||
return "-";
|
||||
|
||||
@@ -133,7 +133,7 @@ export const sysResources = [
|
||||
title: "certd.sysResources.sysPluginConfig",
|
||||
name: "SysPluginConfig",
|
||||
path: "/sys/plugin/config",
|
||||
component: "/sys/plugin/config.vue",
|
||||
component: "/sys/plugin/config-common.vue",
|
||||
meta: {
|
||||
show: () => {
|
||||
const settingStore = useSettingStore();
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { defineStore } from "pinia";
|
||||
import * as api from "./api.plugin";
|
||||
import { DynamicType, FormItemProps } from "@fast-crud/fast-crud";
|
||||
import { DynamicType, FormItemProps, useMerge } from "@fast-crud/fast-crud";
|
||||
import { i18n } from "/src/locales/i18n";
|
||||
import { cloneDeep } from "lodash-es";
|
||||
interface PluginState {
|
||||
group?: PluginGroups;
|
||||
}
|
||||
@@ -32,14 +33,17 @@ export class PluginGroups {
|
||||
groups!: { [key: string]: PluginGroup };
|
||||
map!: { [key: string]: PluginDefine };
|
||||
t: any;
|
||||
constructor(groups: { [key: string]: PluginGroup }) {
|
||||
mergeSetting?: boolean;
|
||||
constructor(groups: { [key: string]: PluginGroup }, opts?: { mergeSetting?: boolean }) {
|
||||
this.groups = groups;
|
||||
this.t = i18n.global.t;
|
||||
this.mergeSetting = opts?.mergeSetting ?? false;
|
||||
this.initGroup(groups);
|
||||
this.initMap();
|
||||
}
|
||||
|
||||
private initGroup(groups: { [p: string]: PluginGroup }) {
|
||||
const { merge } = useMerge();
|
||||
const all: PluginGroup = {
|
||||
key: "all",
|
||||
title: this.t("certd.all"),
|
||||
@@ -48,6 +52,14 @@ export class PluginGroups {
|
||||
icon: "material-symbols:border-all-rounded",
|
||||
};
|
||||
for (const key in groups) {
|
||||
if (this.mergeSetting) {
|
||||
for (const plugin of groups[key].plugins) {
|
||||
if (plugin.sysSetting) {
|
||||
merge(plugin.input, plugin.sysSetting.metadata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
all.plugins.push(...groups[key].plugins);
|
||||
}
|
||||
this.groups = {
|
||||
@@ -132,11 +144,15 @@ export const usePluginStore = defineStore({
|
||||
id: "app.plugin",
|
||||
state: (): PluginState => ({
|
||||
group: null,
|
||||
originGroup: null,
|
||||
}),
|
||||
actions: {
|
||||
async reload() {
|
||||
const groups = await api.GetGroups({});
|
||||
this.group = new PluginGroups(groups);
|
||||
this.group = new PluginGroups(groups, { mergeSetting: true });
|
||||
this.originGroup = new PluginGroups(cloneDeep(groups));
|
||||
console.log("group", this.group);
|
||||
console.log("originGroup", this.originGroup);
|
||||
},
|
||||
async init() {
|
||||
if (!this.group) {
|
||||
@@ -159,6 +175,10 @@ export const usePluginStore = defineStore({
|
||||
await this.init();
|
||||
return this.group.get(name);
|
||||
},
|
||||
async getPluginDefineFromOrigin(name: string): Promise<PluginDefine> {
|
||||
await this.init();
|
||||
return this.originGroup.get(name);
|
||||
},
|
||||
async getPluginConfig(query: any) {
|
||||
return await api.GetPluginConfig(query);
|
||||
},
|
||||
|
||||
@@ -304,3 +304,11 @@ h6 {
|
||||
padding: 10px;
|
||||
color: #6e6e6e;
|
||||
}
|
||||
|
||||
.ant-modal-body{
|
||||
.fs-form-body{
|
||||
max-height: 66vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -84,6 +84,7 @@ export function getCommonColumnDefine(crudExpose: any, typeRef: any, api: any) {
|
||||
component: {
|
||||
color: "auto",
|
||||
},
|
||||
order: -1,
|
||||
},
|
||||
form: {
|
||||
component: {
|
||||
|
||||
@@ -44,6 +44,20 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
},
|
||||
rowHandle: {
|
||||
width: 200,
|
||||
buttons: {
|
||||
copy: {
|
||||
async click(ctx: any) {
|
||||
const { row, index } = ctx;
|
||||
await crudExpose.openCopy({
|
||||
row: {
|
||||
...row,
|
||||
_copyFrom: row.id,
|
||||
},
|
||||
index: index,
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
columns: {
|
||||
id: {
|
||||
@@ -68,6 +82,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
},
|
||||
column: {
|
||||
width: 300,
|
||||
order: -11,
|
||||
},
|
||||
},
|
||||
from: {
|
||||
|
||||
@@ -138,6 +138,7 @@ export function useCertPipelineCreator() {
|
||||
form: {
|
||||
doSubmit,
|
||||
wrapper: {
|
||||
wrapClassName: "cert_pipeline_create_form",
|
||||
width: 1350,
|
||||
saveRemind: false,
|
||||
title: t("certd.pipelineForm.createTitle"),
|
||||
|
||||
@@ -115,4 +115,13 @@ function batchRerun() {
|
||||
padding-left: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.cert_pipeline_create_form {
|
||||
.ant-collapse {
|
||||
margin: 10px;
|
||||
}
|
||||
.ant-collapse-header {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -41,7 +41,7 @@ const option = ref({
|
||||
center: ["60%", "50%"],
|
||||
name: "状态",
|
||||
type: "pie",
|
||||
radius: "80%",
|
||||
radius: ["30%", "70%"],
|
||||
avoidLabelOverlap: false,
|
||||
itemStyle: {
|
||||
borderRadius: 0,
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
<a-form-item>
|
||||
<a-button type="primary" size="large" html-type="submit" :loading="loading" class="login-button">
|
||||
<a-button type="primary" size="large" html-type="button" :loading="loading" class="login-button" @click="handleFinish">
|
||||
{{ t("authentication.loginButton") }}
|
||||
</a-button>
|
||||
|
||||
@@ -217,7 +217,6 @@ export default defineComponent({
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
|
||||
.login-page.main {
|
||||
//margin: 20px !important;
|
||||
margin-bottom: 100px;
|
||||
|
||||
@@ -32,6 +32,13 @@
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="email" tab="邮箱注册" :disabled="!settingsStore.sysPublic.emailRegisterEnabled">
|
||||
<template v-if="registerType === 'email'">
|
||||
<a-form-item required has-feedback name="username" label="用户名" :rules="rules.username">
|
||||
<a-input v-model:value="formState.username" placeholder="用户名" size="large" autocomplete="off">
|
||||
<template #prefix>
|
||||
<fs-icon icon="ion:person-outline"></fs-icon>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
<a-form-item required has-feedback name="email" label="邮箱">
|
||||
<a-input v-model:value="formState.email" placeholder="邮箱" size="large" autocomplete="off">
|
||||
<template #prefix>
|
||||
|
||||
@@ -97,6 +97,7 @@ export type CertApplyPluginSysInput = {
|
||||
export type PluginSysSetting<T> = {
|
||||
sysSetting: {
|
||||
input?: T;
|
||||
metadata?: Record<string, any>;
|
||||
};
|
||||
};
|
||||
export type CommPluginConfig = {
|
||||
@@ -118,6 +119,14 @@ export async function SaveCommPluginConfigs(data: CommPluginConfig): Promise<voi
|
||||
});
|
||||
}
|
||||
|
||||
export async function savePluginSetting(req: { id: number; metadata: any }): Promise<void> {
|
||||
return await request({
|
||||
url: apiPrefix + "/saveSetting",
|
||||
method: "post",
|
||||
data: req,
|
||||
});
|
||||
}
|
||||
|
||||
export async function DoTest(req: { id: number; input: any }): Promise<void> {
|
||||
return await request({
|
||||
url: apiPrefix + "/doTest",
|
||||
|
||||
177
packages/ui/certd-client/src/views/sys/plugin/config-editor.vue
Normal file
177
packages/ui/certd-client/src/views/sys/plugin/config-editor.vue
Normal file
@@ -0,0 +1,177 @@
|
||||
<template>
|
||||
<div class="plugin-config">
|
||||
<div class="origin-metadata w-100%">
|
||||
<div class="block-title">
|
||||
自定义插件参数配置
|
||||
<div class="helper">1111</div>
|
||||
</div>
|
||||
<div class="p-10">
|
||||
<div ref="formRef" class="config-form w-full" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<table class="table-fixed w-full">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-left p-5" width="200px">插件参数</th>
|
||||
<th class="text-left p-5" width="100px">参数配置</th>
|
||||
<th class="text-left flex-1 p-5">自定义</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<template v-for="(item, key) in originInputs" :key="key">
|
||||
<template v-for="prop in editableKeys" :key="prop.key">
|
||||
<tr>
|
||||
<td v-if="prop.key === 'value'" class="border-t-2 p-5" rowspan="3" :class="{ 'border-t-2': prop.key === 'value' }">{{ item.title }}</td>
|
||||
<td class="border-t p-5" :class="{ 'border-t-2': prop.key === 'value' }">{{ prop.label }}</td>
|
||||
<td class="border-t p-5" :class="{ 'border-t-2': prop.key === 'value' }">
|
||||
<rollbackable :value="configForm[key][prop.key]" @set="configForm[key][prop.key] = item[prop.key] ?? null" @clear="delete configForm[key][prop.key]">
|
||||
<template #default>
|
||||
<fs-render :render-func="prop.defaultRender(key, item)"></fs-render>
|
||||
</template>
|
||||
<template #edit>
|
||||
<fs-render :render-func="prop.editRender(key, item)"></fs-render>
|
||||
</template>
|
||||
</rollbackable>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
</template>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="tsx">
|
||||
import { computed, nextTick, onMounted, reactive, ref, Ref, unref } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import * as api from "./api";
|
||||
import { usePluginStore } from "/@/store/plugin";
|
||||
import { cloneDeep, get, merge, set, unset } from "lodash-es";
|
||||
import Rollbackable from "./rollbackable.vue";
|
||||
import { FsRender } from "@fast-crud/fast-crud";
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const pluginStore = usePluginStore();
|
||||
const props = defineProps<{
|
||||
plugin: any;
|
||||
}>();
|
||||
|
||||
const pluginMetadata = ref<any>("");
|
||||
const currentPlugin = ref();
|
||||
const labelCol = ref({
|
||||
span: null,
|
||||
style: {
|
||||
width: "145px",
|
||||
},
|
||||
});
|
||||
const wrapperCol = ref({ span: 16 });
|
||||
const configForm: any = reactive({});
|
||||
|
||||
function getScope() {
|
||||
return {
|
||||
form: configForm,
|
||||
};
|
||||
}
|
||||
function getScopeFunc() {
|
||||
return getScope;
|
||||
}
|
||||
function getForm() {
|
||||
return configForm;
|
||||
}
|
||||
|
||||
const editableKeys = ref([
|
||||
{
|
||||
key: "value",
|
||||
label: "默认值",
|
||||
defaultRender(key: string, item: any) {
|
||||
return () => {
|
||||
return item["value"] ?? "";
|
||||
};
|
||||
},
|
||||
editRender(key: string, item: any) {
|
||||
return () => {
|
||||
return <fs-component-render {...item.component} vModel:modelValue={configForm[key]["value"]} scope={getScope()} />;
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "show",
|
||||
label: "是否显示",
|
||||
defaultRender(key: string, item: any) {
|
||||
return () => {
|
||||
const value = item["show"];
|
||||
return value === false ? "不显示" : "显示";
|
||||
};
|
||||
},
|
||||
editRender(key: string, item: any) {
|
||||
return () => {
|
||||
return <a-switch vModel:checked={configForm[key]["show"]} />;
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "helper",
|
||||
label: "帮助说明",
|
||||
defaultRender(key: string, item: any) {
|
||||
return () => {
|
||||
return <pre class={"helper"}>{item["helper"]}</pre>;
|
||||
};
|
||||
},
|
||||
editRender(key: string, item: any) {
|
||||
return () => {
|
||||
return <a-textarea rows={5} vModel:value={configForm[key]["helper"]} />;
|
||||
};
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
const originInputs = computed(() => {
|
||||
if (!currentPlugin.value) {
|
||||
return;
|
||||
}
|
||||
const input = cloneDeep(currentPlugin.value.input);
|
||||
const newInputs: any = {};
|
||||
|
||||
for (const key in input) {
|
||||
const value = input[key];
|
||||
value.key = key;
|
||||
const newInput: any = cloneDeep(value);
|
||||
newInputs[key] = newInput;
|
||||
}
|
||||
return newInputs;
|
||||
});
|
||||
|
||||
function clearFormValue(key: string) {
|
||||
unset(configForm, key);
|
||||
console.log(key, configForm);
|
||||
}
|
||||
|
||||
async function loadPluginSetting() {
|
||||
currentPlugin.value = await pluginStore.getPluginDefineFromOrigin(props.plugin.name);
|
||||
for (const key in currentPlugin.value.input) {
|
||||
configForm[key] = {};
|
||||
}
|
||||
const setting = props.plugin.sysSetting;
|
||||
if (setting) {
|
||||
const settingJson = JSON.parse(setting);
|
||||
merge(configForm, settingJson.metadata);
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await loadPluginSetting();
|
||||
});
|
||||
|
||||
defineExpose({
|
||||
getForm,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
.plugin-config {
|
||||
pre {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,11 +1,14 @@
|
||||
import * as api from "./api";
|
||||
import { useI18n } from "/src/locales";
|
||||
import { Ref, ref } from "vue";
|
||||
import { Ref, ref, computed } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { AddReq, compute, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, useFormWrapper, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
|
||||
import { Modal, notification } from "ant-design-vue";
|
||||
import { AddReq, compute, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
|
||||
import { Modal } from "ant-design-vue";
|
||||
//@ts-ignore
|
||||
import yaml from "js-yaml";
|
||||
import { usePluginImport } from "./use-import";
|
||||
import { usePluginConfig } from "./use-config";
|
||||
import { useSettingStore } from "/src/store/settings/index";
|
||||
|
||||
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||
const router = useRouter();
|
||||
@@ -35,75 +38,11 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
|
||||
const selectedRowKeys: Ref<any[]> = ref([]);
|
||||
context.selectedRowKeys = selectedRowKeys;
|
||||
const { openCrudFormDialog } = useFormWrapper();
|
||||
|
||||
async function openImportDialog() {
|
||||
function createCrudOptions() {
|
||||
return {
|
||||
crudOptions: {
|
||||
columns: {
|
||||
content: {
|
||||
title: t("certd.pluginFile"),
|
||||
type: "text",
|
||||
form: {
|
||||
component: {
|
||||
name: "pem-input",
|
||||
vModel: "modelValue",
|
||||
textarea: {
|
||||
rows: 8,
|
||||
},
|
||||
},
|
||||
col: {
|
||||
span: 24,
|
||||
},
|
||||
helper: t("certd.selectPluginFile"),
|
||||
},
|
||||
},
|
||||
override: {
|
||||
title: t("certd.overrideSameName"),
|
||||
type: "dict-switch",
|
||||
dict: dict({
|
||||
data: [
|
||||
{
|
||||
value: true,
|
||||
label: t("certd.override"),
|
||||
},
|
||||
{
|
||||
value: false,
|
||||
label: t("certd.noOverride"),
|
||||
},
|
||||
],
|
||||
}),
|
||||
form: {
|
||||
value: false,
|
||||
col: {
|
||||
span: 24,
|
||||
},
|
||||
helper: t("certd.overrideHelper"),
|
||||
},
|
||||
},
|
||||
},
|
||||
form: {
|
||||
wrapper: {
|
||||
title: t("certd.importPlugin"),
|
||||
saveRemind: false,
|
||||
},
|
||||
afterSubmit() {
|
||||
notification.success({ message: t("certd.operationSuccess") });
|
||||
crudExpose.doRefresh();
|
||||
},
|
||||
async doSubmit({ form }: any) {
|
||||
return await api.ImportPlugin({
|
||||
...form,
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
const { crudOptions } = createCrudOptions();
|
||||
await openCrudFormDialog({ crudOptions });
|
||||
}
|
||||
const { openImportDialog } = usePluginImport();
|
||||
const { openConfigDialog } = usePluginConfig();
|
||||
|
||||
const settingStore = useSettingStore();
|
||||
return {
|
||||
crudOptions: {
|
||||
settings: {
|
||||
@@ -139,7 +78,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
text: t("certd.import"),
|
||||
type: "primary",
|
||||
async click() {
|
||||
await openImportDialog();
|
||||
await openImportDialog({ crudExpose });
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -186,6 +125,21 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
}
|
||||
},
|
||||
},
|
||||
config: {
|
||||
show: computed(() => {
|
||||
return settingStore.isComm;
|
||||
}),
|
||||
text: null,
|
||||
icon: "ion:settings-outline",
|
||||
title: t("certd.config"),
|
||||
type: "link",
|
||||
async click({ row }) {
|
||||
await openConfigDialog({
|
||||
row,
|
||||
crudExpose,
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
table: {
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
<script setup lang="ts">
|
||||
import { defineProps } from "vue";
|
||||
|
||||
const props = defineProps<{ value: any }>();
|
||||
|
||||
const emits = defineEmits(["set", "clear"]);
|
||||
function setValue() {
|
||||
emits("set");
|
||||
}
|
||||
function clearValue() {
|
||||
emits("clear");
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="rollbackable">
|
||||
<div class="flex">
|
||||
<div style="width: 100px">
|
||||
<a-tag v-if="value === undefined" color="green" size="small" class="pointer flex-inline items-center" @click.stop="setValue">
|
||||
<fs-icon icon="material-symbols:edit" class="mr-5"></fs-icon>
|
||||
自定义
|
||||
</a-tag>
|
||||
<a-tag v-else color="red" size="small" class="pointer flex-inline items-center" @click.stop="clearValue">
|
||||
<fs-icon icon="material-symbols:undo" class="mr-5"></fs-icon>
|
||||
还原
|
||||
</a-tag>
|
||||
</div>
|
||||
<div class="flex-1 overflow-hidden value-render">
|
||||
<slot v-if="value === undefined" name="default"></slot>
|
||||
<slot v-else name="edit"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="less">
|
||||
.rollbackable {
|
||||
.value-render {
|
||||
.ant-select,
|
||||
.ant-input {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
73
packages/ui/certd-client/src/views/sys/plugin/use-config.tsx
Normal file
73
packages/ui/certd-client/src/views/sys/plugin/use-config.tsx
Normal file
@@ -0,0 +1,73 @@
|
||||
import * as api from "/@/views/sys/plugin/api";
|
||||
import { useFormWrapper } from "@fast-crud/fast-crud";
|
||||
import { useI18n } from "/@/locales";
|
||||
import { Modal, notification } from "ant-design-vue";
|
||||
import ConfigEditor from "./config-editor.vue";
|
||||
import { useModal } from "/@/use/use-modal";
|
||||
import { ref } from "vue";
|
||||
export function usePluginConfig() {
|
||||
const { openCrudFormDialog } = useFormWrapper();
|
||||
const { t } = useI18n();
|
||||
|
||||
const modal = useModal();
|
||||
async function openConfigDialog({ row, crudExpose }) {
|
||||
const configEditorRef = ref();
|
||||
function createCrudOptions() {
|
||||
return {
|
||||
crudOptions: {
|
||||
columns: {},
|
||||
form: {
|
||||
wrapper: {
|
||||
width: "80%",
|
||||
title: "插件元数据配置",
|
||||
saveRemind: false,
|
||||
slots: {
|
||||
"form-body-top": () => {
|
||||
return (
|
||||
<div>
|
||||
<ConfigEditor ref={configEditorRef} plugin={row}></ConfigEditor>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
},
|
||||
afterSubmit() {
|
||||
notification.success({ message: t("certd.operationSuccess") });
|
||||
crudExpose.doRefresh();
|
||||
},
|
||||
async doSubmit({}: any) {
|
||||
const form = configEditorRef.value.getForm();
|
||||
const newForm: any = {};
|
||||
for (const key in form) {
|
||||
const value = form[key];
|
||||
if (value && Object.keys(value).length > 0) {
|
||||
newForm[key] = value;
|
||||
}
|
||||
}
|
||||
return await api.savePluginSetting({
|
||||
name: row.name,
|
||||
sysSetting: {
|
||||
metadata: newForm,
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
const { crudOptions } = createCrudOptions();
|
||||
await openCrudFormDialog({ crudOptions });
|
||||
|
||||
// modal.confirm({
|
||||
// title: "插件元数据配置",
|
||||
// width: "80%",
|
||||
// content: () => {
|
||||
// return <ConfigEditor plugin={row}></ConfigEditor>;
|
||||
// },
|
||||
// });
|
||||
}
|
||||
|
||||
return {
|
||||
openConfigDialog,
|
||||
};
|
||||
}
|
||||
80
packages/ui/certd-client/src/views/sys/plugin/use-import.ts
Normal file
80
packages/ui/certd-client/src/views/sys/plugin/use-import.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
import * as api from "/@/views/sys/plugin/api";
|
||||
import { useFormWrapper } from "@fast-crud/fast-crud";
|
||||
import { useI18n } from "/@/locales";
|
||||
import { Modal, notification } from "ant-design-vue";
|
||||
export function usePluginImport() {
|
||||
const { openCrudFormDialog } = useFormWrapper();
|
||||
const { t } = useI18n();
|
||||
|
||||
async function openImportDialog({ crudExpose }) {
|
||||
function createCrudOptions() {
|
||||
return {
|
||||
crudOptions: {
|
||||
columns: {
|
||||
content: {
|
||||
title: t("certd.pluginFile"),
|
||||
type: "text",
|
||||
form: {
|
||||
component: {
|
||||
name: "pem-input",
|
||||
vModel: "modelValue",
|
||||
textarea: {
|
||||
rows: 8,
|
||||
},
|
||||
},
|
||||
col: {
|
||||
span: 24,
|
||||
},
|
||||
helper: t("certd.selectPluginFile"),
|
||||
},
|
||||
},
|
||||
override: {
|
||||
title: t("certd.overrideSameName"),
|
||||
type: "dict-switch",
|
||||
dict: dict({
|
||||
data: [
|
||||
{
|
||||
value: true,
|
||||
label: t("certd.override"),
|
||||
},
|
||||
{
|
||||
value: false,
|
||||
label: t("certd.noOverride"),
|
||||
},
|
||||
],
|
||||
}),
|
||||
form: {
|
||||
value: false,
|
||||
col: {
|
||||
span: 24,
|
||||
},
|
||||
helper: t("certd.overrideHelper"),
|
||||
},
|
||||
},
|
||||
},
|
||||
form: {
|
||||
wrapper: {
|
||||
title: t("certd.importPlugin"),
|
||||
saveRemind: false,
|
||||
},
|
||||
afterSubmit() {
|
||||
notification.success({ message: t("certd.operationSuccess") });
|
||||
crudExpose.doRefresh();
|
||||
},
|
||||
async doSubmit({ form }: any) {
|
||||
return await api.ImportPlugin({
|
||||
...form,
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
const { crudOptions } = createCrudOptions();
|
||||
await openCrudFormDialog({ crudOptions });
|
||||
}
|
||||
|
||||
return {
|
||||
openImportDialog,
|
||||
};
|
||||
}
|
||||
@@ -47,10 +47,6 @@
|
||||
<div class="helper" v-html="t('certd.commonCnameHelper')"></div>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item :label="t('certd.enableCommonSelfServicePasswordRetrieval')" :name="['public', 'selfServicePasswordRetrievalEnabled']">
|
||||
<a-switch v-model:checked="formState.public.selfServicePasswordRetrievalEnabled" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label=" " :colon="false" :wrapper-col="{ span: 8 }">
|
||||
<a-button :loading="saveLoading" type="primary" html-type="submit">{{ t("certd.saveButton") }}</a-button>
|
||||
</a-form-item>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<a-form-item v-if="formState.yizhifu.enabled" label="易支付配置" :name="['yizhifu', 'accessId']" :required="true">
|
||||
<access-selector v-model="formState.yizhifu.accessId" type="yizhifu" from="sys" />
|
||||
<div class="helper">
|
||||
<a href="https://certd.docmirror.cn/comm/payments/yizhifu.html">彩虹易支付配置帮助文档</a>
|
||||
<a href="https://certd.docmirror.cn/guide/use/comm/payments/yizhifu.html">彩虹易支付配置帮助文档</a>
|
||||
</div>
|
||||
</a-form-item>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
</a-form-item>
|
||||
<a-form-item v-if="formState.alipay.enabled" label="支付宝配置" :name="['alipay', 'accessId']" :required="true">
|
||||
<access-selector v-model="formState.alipay.accessId" type="alipay" from="sys" />
|
||||
<div class="helper">需要开通电脑网站支付, <a href="https://certd.docmirror.cn/comm/payments/alipay.html">支付宝配置帮助文档</a></div>
|
||||
<div class="helper">需要开通电脑网站支付, <a href="https://certd.docmirror.cn/guide/use/comm/payments/alipay.html">支付宝配置帮助文档</a></div>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="微信支付" :name="['wxpay', 'enabled']" :required="true">
|
||||
@@ -25,7 +25,7 @@
|
||||
</a-form-item>
|
||||
<a-form-item v-if="formState.wxpay.enabled" label="微信支付配置" :name="['wxpay', 'accessId']" :required="true">
|
||||
<access-selector v-model="formState.wxpay.accessId" type="wxpay" from="sys" />
|
||||
<div class="helper">需要开通Native支付, <a href="https://certd.docmirror.cn/comm/payments/wxpay.html">微信配置帮助文档</a></div>
|
||||
<div class="helper">需要开通Native支付, <a href="https://certd.docmirror.cn/guide/use/comm/payments/wxpay.html">微信配置帮助文档</a></div>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label=" " :colon="false" :wrapper-col="{ span: 16 }">
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
<a-form-item :label="t('certd.enableSelfRegistration')" :name="['public', 'registerEnabled']">
|
||||
<a-switch v-model:checked="formState.public.registerEnabled" />
|
||||
</a-form-item>
|
||||
<a-form-item :label="t('certd.enableCommonSelfServicePasswordRetrieval')" :name="['public', 'selfServicePasswordRetrievalEnabled']">
|
||||
<a-switch v-model:checked="formState.public.selfServicePasswordRetrievalEnabled" />
|
||||
</a-form-item>
|
||||
<a-form-item :label="t('certd.enableUserValidityPeriod')" :name="['public', 'userValidTimeEnabled']">
|
||||
<div class="flex-o">
|
||||
<a-switch v-model:checked="formState.public.userValidTimeEnabled" :disabled="!settingsStore.isPlus" />
|
||||
|
||||
@@ -3,6 +3,45 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.36.17](https://github.com/certd/certd/compare/v1.36.16...v1.36.17) (2025-08-17)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复新部署的无法保存公共eab配置的bug ([d5dee75](https://github.com/certd/certd/commit/d5dee75df3bd635a597436e448b2de1407531f3a))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 阿里云 FC3.0 不在要求证书加密方式为旧版, 修复支持的协议类型可以正常选择 ([a34db74](https://github.com/certd/certd/commit/a34db7449eff6ad1dda01de673bf85579fa3865a))
|
||||
* 部署到腾讯云cdn,每个域名增加3每秒延迟 ([f7d43ad](https://github.com/certd/certd/commit/f7d43ad5af4663d4be369820a80d1fd9817ca4ab))
|
||||
|
||||
## [1.36.16](https://github.com/certd/certd/compare/v1.36.15...v1.36.16) (2025-08-16)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 百度云支持上传到证书托管,支持部署到负载均衡 ([798a48a](https://github.com/certd/certd/commit/798a48aa9686fd5d11cfffb6cd93eadfc40aacb3))
|
||||
* 验证码可重试次数设置为3次 ([1bdceee](https://github.com/certd/certd/commit/1bdceeecf4b5daecdd621a05a2596b6eb45ce8ea))
|
||||
* 增加找回密码的验证码可重试次数 [@nicheng-he](https://github.com/nicheng-he) ([#496](https://github.com/certd/certd/issues/496)) ([fe03f99](https://github.com/certd/certd/commit/fe03f9942b5662fb90cad86da10782f5dc3603f5))
|
||||
* 支持阿里云API网关 ([9e1e4ee](https://github.com/certd/certd/commit/9e1e4eeec2859759ca5b07834c9d24cf88a6ad33))
|
||||
* 支持部署到金山云CDN ([dfa74a6](https://github.com/certd/certd/commit/dfa74a69f7cbb9009d3e20c7eecfa1b905a00cf0))
|
||||
* 支持更新金山云cdn证书 ([462e22a](https://github.com/certd/certd/commit/462e22a3b0a94887462fe6aa68e4671a365e0737))
|
||||
* 支持apisix证书部署 ([9b63fb4](https://github.com/certd/certd/commit/9b63fb4ee2c6b56139160c5bf63482dab0869c2b))
|
||||
|
||||
## [1.36.15](https://github.com/certd/certd/compare/v1.36.14...v1.36.15) (2025-08-07)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复 https://cas.undefined.aliyuncs.com 的bug ([60e6aa9](https://github.com/certd/certd/commit/60e6aa9b54a761a47e39acee4a1ff947a745be27))
|
||||
* 修复阿里云clb api接口没有使用region的问题 ([0770f17](https://github.com/certd/certd/commit/0770f174a14313e28d08113e69829ef6cc02d719))
|
||||
* 修复站点监控使用自定义dns解析域名报错的bug ([eb8cd53](https://github.com/certd/certd/commit/eb8cd53de27991321e36dd14e5ce95f42b51351f))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 部署到阿里云支持选择bucket和域名 ([013b9c4](https://github.com/certd/certd/commit/013b9c4c7c2adf485d086123ccea448719577fd4))
|
||||
* 清理数据库备份的临时目录 ([fd95549](https://github.com/certd/certd/commit/fd95549de9a5d8cec09772ee2630bb7521e15e1f))
|
||||
* 添加免费通知,OneBot V11协议通知支持 ([#491](https://github.com/certd/certd/issues/491)) [@ayakasuki](https://github.com/ayakasuki) ([be053d4](https://github.com/certd/certd/commit/be053d47e41084f817882400882b64143d036d1a))
|
||||
* 支持webhook部署证书 ([cbe0b1c](https://github.com/certd/certd/commit/cbe0b1c5a6538f232e9a63f1693d20d5acf0a306))
|
||||
* 注册时支持填写用户名 ([fdcfcc7](https://github.com/certd/certd/commit/fdcfcc77a0db87954e0b026635d3ccdd9bc6cee8))
|
||||
|
||||
## [1.36.14](https://github.com/certd/certd/compare/v1.36.13...v1.36.14) (2025-07-28)
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
|
||||
```
|
||||
|
||||
|
||||
```shell
|
||||
npm run heap
|
||||
```
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@certd/ui-server",
|
||||
"version": "1.36.14",
|
||||
"version": "1.36.17",
|
||||
"description": "fast-server base midway",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
@@ -42,20 +42,20 @@
|
||||
"@aws-sdk/client-cloudfront": "^3.699.0",
|
||||
"@aws-sdk/client-iam": "^3.699.0",
|
||||
"@aws-sdk/client-s3": "^3.705.0",
|
||||
"@certd/acme-client": "^1.36.14",
|
||||
"@certd/basic": "^1.36.14",
|
||||
"@certd/commercial-core": "^1.36.14",
|
||||
"@certd/acme-client": "^1.36.17",
|
||||
"@certd/basic": "^1.36.17",
|
||||
"@certd/commercial-core": "^1.36.17",
|
||||
"@certd/cv4pve-api-javascript": "^8.4.1",
|
||||
"@certd/jdcloud": "^1.36.14",
|
||||
"@certd/lib-huawei": "^1.36.14",
|
||||
"@certd/lib-k8s": "^1.36.14",
|
||||
"@certd/lib-server": "^1.36.14",
|
||||
"@certd/midway-flyway-js": "^1.36.14",
|
||||
"@certd/pipeline": "^1.36.14",
|
||||
"@certd/plugin-cert": "^1.36.14",
|
||||
"@certd/plugin-lib": "^1.36.14",
|
||||
"@certd/plugin-plus": "^1.36.14",
|
||||
"@certd/plus-core": "^1.36.14",
|
||||
"@certd/jdcloud": "^1.36.17",
|
||||
"@certd/lib-huawei": "^1.36.17",
|
||||
"@certd/lib-k8s": "^1.36.17",
|
||||
"@certd/lib-server": "^1.36.17",
|
||||
"@certd/midway-flyway-js": "^1.36.17",
|
||||
"@certd/pipeline": "^1.36.17",
|
||||
"@certd/plugin-cert": "^1.36.17",
|
||||
"@certd/plugin-lib": "^1.36.17",
|
||||
"@certd/plugin-plus": "^1.36.17",
|
||||
"@certd/plus-core": "^1.36.17",
|
||||
"@huaweicloud/huaweicloud-sdk-cdn": "^3.1.120",
|
||||
"@huaweicloud/huaweicloud-sdk-core": "^3.1.120",
|
||||
"@koa/cors": "^5.0.0",
|
||||
@@ -82,6 +82,7 @@
|
||||
"cross-env": "^7.0.3",
|
||||
"crypto-js": "^4.2.0",
|
||||
"dayjs": "^1.11.7",
|
||||
"esdk-obs-nodejs": "^3.25.6",
|
||||
"form-data": "^4.0.0",
|
||||
"glob": "^11.0.0",
|
||||
"https-proxy-agent": "^7.0.5",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Controller, Get, Inject, Provide } from '@midwayjs/core';
|
||||
import {Body, Controller, Get, Inject, Post, Provide} from '@midwayjs/core';
|
||||
import { BaseController, Constants, FileService, SysSettingsService, SysSiteInfo } from '@certd/lib-server';
|
||||
import { http, logger } from '@certd/basic';
|
||||
import { isComm } from '@certd/plus-core';
|
||||
@@ -46,4 +46,10 @@ export class AppController extends BaseController {
|
||||
this.ctx.response.redirect(redirect);
|
||||
this.ctx.response.set('Cache-Control', 'public,max-age=25920');
|
||||
}
|
||||
|
||||
@Post('/webhook', { summary: Constants.per.guest })
|
||||
public async webhook( @Body() body: any) {
|
||||
logger.info('webhook', JSON.stringify(body))
|
||||
return this.ok("success")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,9 @@ export class SmsCodeReq {
|
||||
|
||||
@Rule(RuleType.string().required().max(4))
|
||||
imgCode: string;
|
||||
|
||||
@Rule(RuleType.string())
|
||||
verificationType: string;
|
||||
}
|
||||
|
||||
export class EmailCodeReq {
|
||||
@@ -32,6 +35,9 @@ export class EmailCodeReq {
|
||||
verificationType: string;
|
||||
}
|
||||
|
||||
// 找回密码的验证码有效期
|
||||
const FORGOT_PASSWORD_CODE_DURATION = 3
|
||||
|
||||
/**
|
||||
*/
|
||||
@Provide()
|
||||
@@ -48,8 +54,18 @@ export class BasicController extends BaseController {
|
||||
@Body(ALL)
|
||||
body: SmsCodeReq
|
||||
) {
|
||||
const opts = {
|
||||
verificationType: body.verificationType,
|
||||
verificationCodeLength: undefined,
|
||||
duration: undefined,
|
||||
};
|
||||
if(body?.verificationType === 'forgotPassword') {
|
||||
opts.duration = FORGOT_PASSWORD_CODE_DURATION;
|
||||
// opts.verificationCodeLength = 6; //部分厂商这里会设置参数长度这里就不改了
|
||||
}
|
||||
|
||||
await this.codeService.checkCaptcha(body.randomStr, body.imgCode);
|
||||
await this.codeService.sendSmsCode(body.phoneCode, body.mobile, body.randomStr);
|
||||
await this.codeService.sendSmsCode(body.phoneCode, body.mobile, body.randomStr, opts);
|
||||
return this.ok(null);
|
||||
}
|
||||
|
||||
@@ -60,6 +76,7 @@ export class BasicController extends BaseController {
|
||||
) {
|
||||
const opts = {
|
||||
verificationType: body.verificationType,
|
||||
verificationCodeLength: undefined,
|
||||
title: undefined,
|
||||
content: undefined,
|
||||
duration: undefined,
|
||||
@@ -67,7 +84,8 @@ export class BasicController extends BaseController {
|
||||
if(body?.verificationType === 'forgotPassword') {
|
||||
opts.title = '找回密码';
|
||||
opts.content = '验证码:${code}。您正在找回密码,请输入验证码并完成操作。如非本人操作请忽略';
|
||||
opts.duration = 3;
|
||||
opts.duration = FORGOT_PASSWORD_CODE_DURATION;
|
||||
opts.verificationCodeLength = 6;
|
||||
}
|
||||
|
||||
await this.codeService.checkCaptcha(body.randomStr, body.imgCode);
|
||||
|
||||
@@ -2,7 +2,11 @@ import { ALL, Body, Controller, Inject, Post, Provide, Query } from '@midwayjs/c
|
||||
import { merge } from 'lodash-es';
|
||||
import { CrudController } from '@certd/lib-server';
|
||||
import { PluginImportReq, PluginService } from "../../../modules/plugin/service/plugin-service.js";
|
||||
import { CommPluginConfig, PluginConfigService } from '../../../modules/plugin/service/plugin-config-service.js';
|
||||
import {
|
||||
CommPluginConfig,
|
||||
PluginConfig,
|
||||
PluginConfigService
|
||||
} from '../../../modules/plugin/service/plugin-config-service.js';
|
||||
/**
|
||||
* 插件
|
||||
*/
|
||||
@@ -79,7 +83,11 @@ export class PluginController extends CrudController<PluginService> {
|
||||
const res = await this.pluginConfigService.saveCommPluginConfig(body);
|
||||
return this.ok(res);
|
||||
}
|
||||
|
||||
@Post('/saveSetting', { summary: 'sys:settings:edit' })
|
||||
async saveSetting(@Body(ALL) body: PluginConfig) {
|
||||
const res = await this.pluginConfigService.savePluginConfig(body);
|
||||
return this.ok(res);
|
||||
}
|
||||
|
||||
@Post('/import', { summary: 'sys:settings:edit' })
|
||||
async import(@Body(ALL) body: PluginImportReq) {
|
||||
|
||||
@@ -28,6 +28,8 @@ export class LoginController extends BaseController {
|
||||
if(!sysSettings.selfServicePasswordRetrievalEnabled) {
|
||||
throw new CommonException('暂未开启自助找回');
|
||||
}
|
||||
// 找回密码的验证码允许错误次数
|
||||
const errorNum = 5;
|
||||
|
||||
if(body.type === 'email') {
|
||||
this.codeService.checkEmailCode({
|
||||
@@ -35,6 +37,7 @@ export class LoginController extends BaseController {
|
||||
email: body.input,
|
||||
randomStr: body.randomStr,
|
||||
validateCode: body.validateCode,
|
||||
errorNum,
|
||||
throwError: true,
|
||||
});
|
||||
} else if(body.type === 'mobile') {
|
||||
@@ -44,6 +47,7 @@ export class LoginController extends BaseController {
|
||||
randomStr: body.randomStr,
|
||||
phoneCode: body.phoneCode,
|
||||
smsCode: body.validateCode,
|
||||
errorNum,
|
||||
throwError: true,
|
||||
});
|
||||
} else {
|
||||
|
||||
@@ -40,10 +40,18 @@ export class RegisterController extends BaseController {
|
||||
throw new Error('当前站点已禁止自助注册功能');
|
||||
}
|
||||
|
||||
if (body.username && ["admin","certd"].includes(body.username) ) {
|
||||
throw new Error('用户名不能为保留字');
|
||||
}
|
||||
|
||||
if (body.type === 'username') {
|
||||
if (sysPublicSettings.usernameRegisterEnabled === false) {
|
||||
throw new Error('当前站点已禁止用户名注册功能');
|
||||
}
|
||||
if (!body.username) {
|
||||
throw new Error('用户名不能为空');
|
||||
}
|
||||
|
||||
await this.codeService.checkCaptcha(body.randomStr, body.imgCode);
|
||||
const newUser = await this.userService.register(body.type, {
|
||||
username: body.username,
|
||||
@@ -64,6 +72,7 @@ export class RegisterController extends BaseController {
|
||||
throwError: true,
|
||||
});
|
||||
const newUser = await this.userService.register(body.type, {
|
||||
username: body.username,
|
||||
phoneCode: body.phoneCode,
|
||||
mobile: body.mobile,
|
||||
password: body.password,
|
||||
@@ -81,6 +90,7 @@ export class RegisterController extends BaseController {
|
||||
throwError: true,
|
||||
});
|
||||
const newUser = await this.userService.register(body.type, {
|
||||
username: body.username,
|
||||
email: body.email,
|
||||
password: body.password,
|
||||
} as any);
|
||||
|
||||
@@ -63,7 +63,8 @@ export class CodeService {
|
||||
randomStr: string,
|
||||
opts?: {
|
||||
duration?: number,
|
||||
verificationType?: string
|
||||
verificationType?: string,
|
||||
verificationCodeLength?: number,
|
||||
},
|
||||
) {
|
||||
if (!mobile) {
|
||||
@@ -73,7 +74,8 @@ export class CodeService {
|
||||
throw new Error('randomStr不能为空');
|
||||
}
|
||||
|
||||
const duration = Math.max(Math.floor(Math.min(opts?.duration || 5, 15)), 1);
|
||||
const verificationCodeLength = Math.floor(Math.max(Math.min(opts?.verificationCodeLength || 4, 8), 4));
|
||||
const duration = Math.floor(Math.max(Math.min(opts?.duration || 5, 15), 1));
|
||||
|
||||
const sysSettings = await this.sysSettingsService.getPrivateSettings();
|
||||
if (!sysSettings.sms?.config?.accessId) {
|
||||
@@ -87,7 +89,7 @@ export class CodeService {
|
||||
accessService: accessGetter,
|
||||
config: smsConfig,
|
||||
});
|
||||
const smsCode = randomNumber(4);
|
||||
const smsCode = randomNumber(verificationCodeLength);
|
||||
await sender.sendSmsCode({
|
||||
mobile,
|
||||
code: smsCode,
|
||||
@@ -114,7 +116,8 @@ export class CodeService {
|
||||
title?: string,
|
||||
content?: string,
|
||||
duration?: number,
|
||||
verificationType?: string
|
||||
verificationType?: string,
|
||||
verificationCodeLength?: number,
|
||||
},
|
||||
) {
|
||||
if (!email) {
|
||||
@@ -132,8 +135,10 @@ export class CodeService {
|
||||
}
|
||||
}
|
||||
|
||||
const code = randomNumber(4);
|
||||
const duration = Math.max(Math.floor(Math.min(opts?.duration || 5, 15)), 1);
|
||||
const verificationCodeLength = Math.floor(Math.max(Math.min(opts?.verificationCodeLength || 4, 8), 4));
|
||||
const duration = Math.floor(Math.max(Math.min(opts?.duration || 5, 15), 1));
|
||||
|
||||
const code = randomNumber(verificationCodeLength);
|
||||
|
||||
const title = `【${siteTitle}】${!!opts?.title ? opts.title : '验证码'}`;
|
||||
const content = !!opts.content ? this.compile(opts.content)({code, duration}) : `您的验证码是${code},请勿泄露`;
|
||||
@@ -154,12 +159,12 @@ export class CodeService {
|
||||
/**
|
||||
* checkSms
|
||||
*/
|
||||
async checkSmsCode(opts: { mobile: string; phoneCode: string; smsCode: string; randomStr: string; verificationType?: string; throwError: boolean }) {
|
||||
async checkSmsCode(opts: { mobile: string; phoneCode: string; smsCode: string; randomStr: string; verificationType?: string; throwError: boolean; errorNum?: number }) {
|
||||
const key = this.buildSmsCodeKey(opts.phoneCode, opts.mobile, opts.randomStr, opts.verificationType);
|
||||
if (isDev()) {
|
||||
return true;
|
||||
}
|
||||
return this.checkValidateCode(key, opts.smsCode, opts.throwError);
|
||||
return this.checkValidateCode(key, opts.smsCode, opts.throwError, opts.errorNum);
|
||||
}
|
||||
|
||||
buildSmsCodeKey(phoneCode: string, mobile: string, randomStr: string, verificationType?: string) {
|
||||
@@ -169,22 +174,38 @@ export class CodeService {
|
||||
buildEmailCodeKey(email: string, randomStr: string, verificationType?: string) {
|
||||
return ['email', verificationType, email, randomStr].filter(item => !!item).join(':');
|
||||
}
|
||||
checkValidateCode(key: string, userCode: string, throwError = true) {
|
||||
checkValidateCode(key: string, userCode: string, throwError = true, errorNum = 3) {
|
||||
// 记录异常次数key
|
||||
const err_num_key = key + ':err_num';
|
||||
//验证图片验证码
|
||||
const code = cache.get(key);
|
||||
if (code == null || code !== userCode) {
|
||||
let maxRetryCount = false;
|
||||
if (!!code && errorNum > 0) {
|
||||
const err_num = cache.get(err_num_key) || 0
|
||||
if(err_num >= errorNum - 1) {
|
||||
maxRetryCount = true;
|
||||
cache.delete(key);
|
||||
cache.delete(err_num_key);
|
||||
} else {
|
||||
cache.set(err_num_key, err_num + 1, {
|
||||
ttl: 30 * 60 * 1000
|
||||
});
|
||||
}
|
||||
}
|
||||
if (throwError) {
|
||||
throw new CodeErrorException('验证码错误');
|
||||
throw new CodeErrorException(!maxRetryCount ? '验证码错误': '验证码错误请获取新的验证码');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
cache.delete(key);
|
||||
cache.delete(err_num_key);
|
||||
return true;
|
||||
}
|
||||
|
||||
checkEmailCode(opts: { randomStr: string; validateCode: string; email: string; verificationType?: string; throwError: boolean }) {
|
||||
checkEmailCode(opts: { randomStr: string; validateCode: string; email: string; verificationType?: string; throwError: boolean; errorNum?: number }) {
|
||||
const key = this.buildEmailCodeKey(opts.email, opts.randomStr, opts.verificationType);
|
||||
return this.checkValidateCode(key, opts.validateCode, opts.throwError);
|
||||
return this.checkValidateCode(key, opts.validateCode, opts.throwError, opts.errorNum);
|
||||
}
|
||||
|
||||
compile(templateString: string) {
|
||||
|
||||
@@ -1,60 +1,110 @@
|
||||
import { LocalCache } from '@certd/basic';
|
||||
import dnsSdk from 'dns'
|
||||
import {LocalCache, logger} from '@certd/basic';
|
||||
import dnsSdk, {AnyRecord} from 'dns'
|
||||
import {LookupAddress} from "node:dns";
|
||||
|
||||
const dns = dnsSdk.promises
|
||||
|
||||
export class DnsCustom{
|
||||
resolver: any;
|
||||
private resolver: dnsSdk.promises.Resolver;
|
||||
// private cache = new LRUCache<string, any>({
|
||||
// max: 1000,
|
||||
// ttl: 1000 * 60 * 5,
|
||||
// });
|
||||
|
||||
constructor(dnsServers:string[]) {
|
||||
const resolver = new dns.Resolver();
|
||||
resolver.setServers(dnsServers);
|
||||
this.resolver = resolver;
|
||||
}
|
||||
async resolve(hostname:string,options:any):Promise<string[]>{
|
||||
// { family: undefined, hints: 0, all: true }
|
||||
|
||||
const cnames = await this.resolver.resolveCname(hostname)
|
||||
let cnameIps = []
|
||||
// deep
|
||||
if (cnames && cnames.length > 0) {
|
||||
for (let cname of cnames) {
|
||||
const cnameIp = await this.resolve(cname,options)
|
||||
if (cnameIp && cnameIp.length > 0) {
|
||||
cnameIps.push(...cnameIp)
|
||||
// async lookup(hostname:string,options?:{ family: any, hints: number, all: boolean }):Promise<LookupAddress[]>{
|
||||
// const cacheKey = hostname + JSON.stringify(options)
|
||||
// let res = this.cache.get(cacheKey)
|
||||
// if (res){
|
||||
// return res
|
||||
// }
|
||||
// res = await this.doLookup(hostname,options)
|
||||
// this.cache.set(cacheKey,res)
|
||||
// return res
|
||||
// }
|
||||
async lookup(hostname:string,options?:{ family: any, hints: number, all: boolean }):Promise<LookupAddress[]>{
|
||||
// { family: undefined, hints: 0, all: true }
|
||||
let v4:LookupAddress[] = []
|
||||
let v6:LookupAddress[] = []
|
||||
let errors = []
|
||||
const queryV6 = async ()=>{
|
||||
try{
|
||||
const list = await this.resolver.resolve6(hostname)
|
||||
if (list && list.length > 0) {
|
||||
v6 = list.map(item=>{
|
||||
return {
|
||||
address: item,
|
||||
family: 6
|
||||
}
|
||||
})
|
||||
}
|
||||
}catch (e) {
|
||||
logger.warn("query v6 error",e)
|
||||
errors.push(e)
|
||||
}
|
||||
}
|
||||
let v4 = []
|
||||
let v6 = []
|
||||
const queryV4 = async ()=>{
|
||||
try{
|
||||
const list =await this.resolver.resolve4(hostname)
|
||||
if (list && list.length > 0) {
|
||||
v4 = list.map(item=>{
|
||||
return {
|
||||
address: item,
|
||||
family: 4
|
||||
}
|
||||
})
|
||||
}
|
||||
}catch (e) {
|
||||
logger.warn("query v4 error",e)
|
||||
errors.push(e)
|
||||
}
|
||||
}
|
||||
|
||||
const queries:Promise<any>[] = []
|
||||
|
||||
|
||||
const {family, all} = options
|
||||
if(family === 6 && !all){
|
||||
v6= await this.resolver.resolve6(hostname)
|
||||
if (all){
|
||||
queries.push(queryV6())
|
||||
queries.push(queryV4())
|
||||
}else{
|
||||
if(family === 6 ){
|
||||
queries.push(queryV6())
|
||||
}
|
||||
if(family === 4 ){
|
||||
queries.push(queryV4())
|
||||
}
|
||||
}
|
||||
if(family === 4 && !all){
|
||||
v4 = await this.resolver.resolve4(hostname)
|
||||
await Promise.all(queries)
|
||||
const res = [...v4,...v6]
|
||||
if(res.length === 0){
|
||||
if (errors.length > 0){
|
||||
const e = new Error(errors[0])
|
||||
// @ts-ignore
|
||||
e.errors = errors
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
if(all){
|
||||
v4 = await this.resolver.resolve4(hostname)
|
||||
v6 = await this.resolver.resolve6(hostname)
|
||||
}
|
||||
|
||||
return [...v4,...v6,...cnameIps]
|
||||
return res
|
||||
}
|
||||
|
||||
async resolve4(hostname:string,options:any):Promise<string[]>{
|
||||
return await this.resolver.resolve4(hostname,options)
|
||||
async resolve4(hostname:string):Promise<string[]>{
|
||||
return await this.resolver.resolve4(hostname)
|
||||
}
|
||||
async resolve6(hostname:string,options:any):Promise<string[]>{
|
||||
return await this.resolver.resolve6(hostname,options)
|
||||
async resolve6(hostname:string):Promise<string[]>{
|
||||
return await this.resolver.resolve6(hostname)
|
||||
}
|
||||
async resolveAny(hostname:string,options:any):Promise<string[]>{
|
||||
return await this.resolver.resolveAny(hostname,options)
|
||||
async resolveAny(hostname:string):Promise<AnyRecord[]>{
|
||||
return await this.resolver.resolveAny(hostname)
|
||||
}
|
||||
|
||||
async resolveCname(hostname:string,options:any):Promise<string[]>{
|
||||
return await this.resolver.resolveCname(hostname,options)
|
||||
async resolveCname(hostname:string):Promise<string[]>{
|
||||
return await this.resolver.resolveCname(hostname)
|
||||
}
|
||||
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user