From 22f5cfcfd8462ca74128329eefb3f48b3ee0b7ea Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Thu, 14 May 2026 23:44:04 +0800 Subject: [PATCH 01/34] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8Dclogin=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E4=B8=A2=E5=A4=B1state=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/controller/basic/login/oauth-controller.ts | 8 ++++++++ .../modules/sys/authority/service/user-service.ts | 12 +++++++----- .../ui/certd-server/src/plugins/plugin-oauth/api.ts | 1 + .../src/plugins/plugin-oauth/oauth2/plugin-clogin.ts | 6 ++---- .../src/plugins/plugin-oauth/oauth2/plugin-gitee.ts | 8 +------- .../src/plugins/plugin-oauth/oauth2/plugin-github.ts | 11 ++--------- .../src/plugins/plugin-oauth/oauth2/plugin-google.ts | 7 +------ .../plugins/plugin-oauth/oauth2/plugin-microsoft.ts | 8 +------- 8 files changed, 23 insertions(+), 38 deletions(-) diff --git a/packages/ui/certd-server/src/controller/basic/login/oauth-controller.ts b/packages/ui/certd-server/src/controller/basic/login/oauth-controller.ts index 86201ac4f..f312a1847 100644 --- a/packages/ui/certd-server/src/controller/basic/login/oauth-controller.ts +++ b/packages/ui/certd-server/src/controller/basic/login/oauth-controller.ts @@ -82,14 +82,22 @@ export class ConnectController extends BaseController { const bindUrl = installInfo?.bindUrl || ""; //构造登录url const redirectUrl = `${bindUrl}api/oauth/callback/${body.type}`; + + let stateObj = { + forType: body.forType || 'login', + } + const state = utils.hash.base64(JSON.stringify(stateObj)) const { loginUrl, ticketValue } = await oauthProvider.addon.buildLoginUrl({ redirectUri: redirectUrl, forType: body.forType, from: body.from || "web", subtype: body.subtype, + state, }); + const ticket = this.codeService.setValidationValue({ ...ticketValue, + state, subtype: body.subtype, }) this.ctx.cookies.set("oauth_ticket", ticket, { diff --git a/packages/ui/certd-server/src/modules/sys/authority/service/user-service.ts b/packages/ui/certd-server/src/modules/sys/authority/service/user-service.ts index 750f2d769..311c4948c 100644 --- a/packages/ui/certd-server/src/modules/sys/authority/service/user-service.ts +++ b/packages/ui/certd-server/src/modules/sys/authority/service/user-service.ts @@ -184,9 +184,9 @@ export class UserService extends BaseService { } async register(type: string, user: UserEntity, withTx?: (tx: EntityManager) => Promise) { - if (!user.password) { - user.password = simpleNanoId(); - } + // if (!user.password) { + // user.password = simpleNanoId(); + // } if (user.username) { const username = user.username; @@ -229,9 +229,11 @@ export class UserService extends BaseService { passwordVersion: 2, }); if (!newUser.password) { - newUser.password = RandomUtil.randomStr(6); + newUser.password = "changeme"; + }else{ + newUser.password = await this.genPassword(newUser.password, newUser.passwordVersion); } - newUser.password = await this.genPassword(newUser.password, newUser.passwordVersion); + await this.transaction(async txManager => { newUser = await txManager.save(newUser); diff --git a/packages/ui/certd-server/src/plugins/plugin-oauth/api.ts b/packages/ui/certd-server/src/plugins/plugin-oauth/api.ts index be97b6a5d..89ee026d7 100644 --- a/packages/ui/certd-server/src/plugins/plugin-oauth/api.ts +++ b/packages/ui/certd-server/src/plugins/plugin-oauth/api.ts @@ -42,6 +42,7 @@ export type BuildLoginUrlReq = { forType?: string; from?:string; subtype?: string; + state?: string; } export type BuildLogoutUrlReq = { diff --git a/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-clogin.ts b/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-clogin.ts index 8499a2e8d..165fd84a3 100644 --- a/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-clogin.ts +++ b/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-clogin.ts @@ -94,16 +94,14 @@ export class CloginOauthProvider extends BaseAddon implements IOauthProvider { // redirectUri = redirectUri.replace("localhost:3008", "certd.handfree.work") // } const res = await this.ctx.http.request({ - url: `${this.endpoint}/connect.php?act=login&appid=${this.appId}&appkey=${this.appKey}&type=${loginType}&redirect_uri=${redirectUri}` + url: `${this.endpoint}/connect.php?act=login&appid=${this.appId}&appkey=${this.appKey}&type=${loginType}&redirect_uri=${redirectUri}&state=${params.state}` }) this.checkRes(res) return { loginUrl: res.url, - ticketValue: { - state: "", - }, + ticketValue: {}, }; } diff --git a/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-gitee.ts b/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-gitee.ts index c93745ae7..0f5a61961 100644 --- a/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-gitee.ts +++ b/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-gitee.ts @@ -79,19 +79,13 @@ gitee.userInfo = https://gitee.com/api/v5/user async buildLoginUrl(params: BuildLoginUrlReq) { let scope = "user_info" // Scope of the access request - let state:any = { - forType: params.forType || 'login', - } - state = this.ctx.utils.hash.base64(JSON.stringify(state)) - const authorizeEndpoint = "https://gitee.com/oauth/authorize" const redirectUrl = encodeURIComponent(params.redirectUri) // https://gitee.com/oauth/authorize?client_id=5bb5f4158af41c50c7a17b5d9068244e97d3ee572def6a57ed32fd8c9d760ad1&redirect_uri=http%3A%2F%2Fcasdoor.docmirror.cn%3A8000%2Fcallback&response_type=code - const loginUrl = `${authorizeEndpoint}?client_id=${this.clientId}&redirect_uri=${redirectUrl}&response_type=code&scope=${scope}&state=${state}` + const loginUrl = `${authorizeEndpoint}?client_id=${this.clientId}&redirect_uri=${redirectUrl}&response_type=code&scope=${scope}&state=${params.state}` return { loginUrl, ticketValue: { - state, }, }; } diff --git a/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-github.ts b/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-github.ts index 0cf9958d3..019b6dc70 100644 --- a/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-github.ts +++ b/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-github.ts @@ -30,19 +30,12 @@ export class GithubOauthProvider extends BaseAddon implements IOauthProvider { async buildLoginUrl(params: BuildLoginUrlReq) { let scope = "user:email" // Scope of the access request - let state:any = { - forType: params.forType || 'login', - } - state = this.ctx.utils.hash.base64(JSON.stringify(state)) - const authorizeEndpoint = "https://github.com/login/oauth/authorize" const redirectUrl = encodeURIComponent(params.redirectUri) - const loginUrl = `${authorizeEndpoint}?client_id=${this.clientId}&redirect_uri=${redirectUrl}&response_type=code&scope=${scope}&state=${state}` + const loginUrl = `${authorizeEndpoint}?client_id=${this.clientId}&redirect_uri=${redirectUrl}&response_type=code&scope=${scope}&state=${params.state}` return { loginUrl, - ticketValue: { - state, - }, + ticketValue: { }, }; } diff --git a/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-google.ts b/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-google.ts index 6d1c12241..59aea2ad6 100644 --- a/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-google.ts +++ b/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-google.ts @@ -30,18 +30,13 @@ export class GoogleOauthProvider extends BaseAddon implements IOauthProvider { async buildLoginUrl(params: BuildLoginUrlReq) { let scope = "email profile" // Scope of the access request - let state:any = { - forType: params.forType || 'login', - } - state = this.ctx.utils.hash.base64(JSON.stringify(state)) const authorizeEndpoint = "https://accounts.google.com/o/oauth2/auth" const redirectUrl = encodeURIComponent(params.redirectUri) - const loginUrl = `${authorizeEndpoint}?client_id=${this.clientId}&redirect_uri=${redirectUrl}&response_type=code&scope=${scope}&state=${state}` + const loginUrl = `${authorizeEndpoint}?client_id=${this.clientId}&redirect_uri=${redirectUrl}&response_type=code&scope=${scope}&state=${params.state}` return { loginUrl, ticketValue: { - state, }, }; } diff --git a/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-microsoft.ts b/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-microsoft.ts index a5773cf95..63a39c877 100644 --- a/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-microsoft.ts +++ b/packages/ui/certd-server/src/plugins/plugin-oauth/oauth2/plugin-microsoft.ts @@ -42,18 +42,12 @@ export class MicrosoftOauthProvider extends BaseAddon implements IOauthProvider async buildLoginUrl(params: BuildLoginUrlReq) { let scope = "openid profile email User.Read" // Scope of the access request - let state:any = { - forType: params.forType || 'login', - } - state = this.ctx.utils.hash.base64(JSON.stringify(state)) - const authorizeEndpoint = `https://login.microsoftonline.com/${this.tenantId}/oauth2/v2.0/authorize` const redirectUrl = encodeURIComponent(params.redirectUri) - const loginUrl = `${authorizeEndpoint}?client_id=${this.clientId}&redirect_uri=${redirectUrl}&response_type=code&scope=${scope}&state=${state}` + const loginUrl = `${authorizeEndpoint}?client_id=${this.clientId}&redirect_uri=${redirectUrl}&response_type=code&scope=${scope}&state=${params.state}` return { loginUrl, ticketValue: { - state, }, }; } From 229f22d5a9087054da8a39696b5ba8163688ab97 Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Fri, 15 May 2026 00:12:44 +0800 Subject: [PATCH 02/34] =?UTF-8?q?docs:=20=E8=87=AA=E5=8A=A8=E5=8D=87?= =?UTF-8?q?=E7=BA=A7docker-compose?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/auto/docker-compose.yaml | 95 +++++++++++++++++++++++++++++++++ docs/guide/install/auto.md | 60 +++++++++++++++++++++ docs/guide/install/upgrade.md | 48 ----------------- 3 files changed, 155 insertions(+), 48 deletions(-) create mode 100644 docker/auto/docker-compose.yaml create mode 100644 docs/guide/install/auto.md diff --git a/docker/auto/docker-compose.yaml b/docker/auto/docker-compose.yaml new file mode 100644 index 000000000..7a5e93ddd --- /dev/null +++ b/docker/auto/docker-compose.yaml @@ -0,0 +1,95 @@ +version: '3.3' # 兼容旧版docker-compose +services: + certd: + # 镜像 # ↓↓↓↓↓ ---- 镜像版本号,建议改成固定版本号,例如:certd:1.29.0 + image: registry.cn-shenzhen.aliyuncs.com/handsfree/certd:latest + # image: ghcr.io/certd/certd:latest # --------- 如果 报镜像not found,可以尝试其他镜像源 + # image: greper/certd:latest + container_name: certd # 容器名 + restart: unless-stopped # 自动重启 + volumes: + # ↓↓↓↓↓ -------------------------------------------------------- 数据库以及证书存储路径,默认存在宿主机的/data/certd/目录下,【您需要定时备份此目录,以保障数据容灾】 + - /data/certd:/app/data # 只要修改冒号前面的,冒号后面的/app/data切记切记不要动 + #- /volume1/docker/certd:/app/data:delegated #群晖使用这个配置 + # ↓↓↓↓↓ -------------------------------------------------------- 如果走时不准,考虑挂载localtime文件 + #- /etc/localtime:/etc/localtime + #- /etc/timezone:/etc/timezone + ports: # 端口映射 + # ↓↓↓↓ ---------------------------------------------------------- 如果端口有冲突,可以修改第一个7001为其他不冲突的端口号,第二个7001不要动 + - "7001:7001" + # ↓↓↓↓ ---------------------------------------------------------- https端口,可以根据实际情况,是否暴露该端口 + - "7002:7002" + #↓↓↓↓ -------------------------------------------------------------- 如果出现getaddrinfo EAI_AGAIN 或 getaddrinfo ENOTFOUND 错误,可以尝试设置dns +# dns: +# - 223.5.5.5 # 阿里云公共dns +# - 223.6.6.6 +# # ↓↓↓↓ --------------------------------------------------------- 如果你服务器在腾讯云,可以用这个替换上面阿里云的公共dns +# - 119.29.29.29 # 腾讯云公共dns +# - 182.254.116.116 +# # ↓↓↓↓ --------------------------------------------------------- 如果你服务器部署在国外,可以用这个替换上面阿里云的公共dns +# - 8.8.8.8 # 谷歌公共dns +# - 8.8.4.4 +# extra_hosts: +# # ↓↓↓↓ -------------------------------------------------------- 这里可以配置自定义hosts,外网域名可以指向本地局域网ip地址 +# - "localdomain.com:192.168.1.3" +# # ↓↓↓↓ ------------------------------------------------ 直接使用主机的网络,如果网络问题实在找不到原因,可以尝试打开此参数 +# network_mode: host + labels: + com.centurylinklabs.watchtower.enable: "true" +# ↓↓↓↓ -------------------------------------------------------------- 启用ipv6网络,还需要把下面networks的注释放开 +# networks: +# - ip6net + environment: +# ↓↓↓↓ ----------------------------------------------------- 使用上海东八时区 + - TZ=Asia/Shanghai +# 设置环境变量即可自定义certd配置 +# 配置项见: packages/ui/certd-server/src/config/config.default.ts +# 配置规则: certd_ + 配置项, 点号用_代替 +# #↓↓↓↓ ----------------------------- 如果忘记管理员密码,可以设置为true,docker compose up -d 重建容器之后,管理员密码将改成123456,然后请及时修改回false + - certd_system_resetAdminPasswd=false + # ↓↓↓ 要使用ipv6,将此配置修改为:: + - certd_koa_hostname=0.0.0.0 + +# 默认使用sqlite文件数据库,如果需要使用其他数据库,请设置以下环境变量 +# 注意: 选定使用一种数据库之后,不支持更换数据库。 +# 数据库迁移方法:1、使用新数据库重新部署一套,然后将旧数据同步过去,注意flyway_history表的数据不要同步 +# #↓↓↓↓ ----------------------------- 使用postgresql数据库,需要提前创建数据库 +# - certd_flyway_scriptDir=./db/migration-pg # 升级脚本目录 +# - certd_typeorm_dataSource_default_type=postgres # 数据库类型 +# - certd_typeorm_dataSource_default_host=localhost # 数据库地址 +# - certd_typeorm_dataSource_default_port=5433 # 数据库端口 +# - certd_typeorm_dataSource_default_username=postgres # 用户名 +# - certd_typeorm_dataSource_default_password=yourpasswd # 密码 +# - certd_typeorm_dataSource_default_database=certd # 数据库名 + +# #↓↓↓↓ ----------------------------- 使用mysql8数据库,需要提前创建数据库 charset=utf8mb4, collation=utf8mb4_bin +# - certd_flyway_scriptDir=./db/migration-mysql # 升级脚本目录 +# - certd_typeorm_dataSource_default_type=mysql # 数据库类型, 或者 mariadb +# - certd_typeorm_dataSource_default_host=localhost # 数据库地址 +# - certd_typeorm_dataSource_default_port=3306 # 数据库端口 +# - certd_typeorm_dataSource_default_username=root # 用户名 +# - certd_typeorm_dataSource_default_password=yourpasswd # 密码 +# - certd_typeorm_dataSource_default_database=certd # 数据库名 + +# ↓↓↓↓ --------------------------------------------------------- 自动升级,上面certd的版本号要保持为latest + certd-updater: # 添加 Watchtower 服务 + image: containrrr/watchtower:latest + container_name: certd-updater + restart: unless-stopped + volumes: + - /var/run/docker.sock:/var/run/docker.sock + # 配置 自动更新 + environment: + - WATCHTOWER_CLEANUP=true # 自动清理旧版本容器 + - WATCHTOWER_INCLUDE_STOPPED=false # 不更新已停止的容器 + - WATCHTOWER_LABEL_ENABLE=true # 根据容器标签进行更新 + - WATCHTOWER_POLL_INTERVAL=600 # 每 10 分钟检查一次更新 + + +# ↓↓↓↓ -------------------------------------------------------------- 启用ipv6网络,还需要把上面networks的注释放开 +#networks: +# ip6net: +# enable_ipv6: true +# ipam: +# config: +# - subnet: 2001:db8::/64 diff --git a/docs/guide/install/auto.md b/docs/guide/install/auto.md new file mode 100644 index 000000000..393d5b34e --- /dev/null +++ b/docs/guide/install/auto.md @@ -0,0 +1,60 @@ + +## 自动升级配置 + +### 1. 方法一:使用watchtower监控自动升级【推荐】 + +1. 修改docker-compose.yaml文件增加如下配置 +或 [下载完整的自动升级docker-compose.yaml配置](https://gitee.com/certd/certd/raw/v2/docker/auto/docker-compose.yaml) +```yaml +services: + certd: + # 镜像 # ↓↓↓↓↓ ---- 镜像版本号 这里要保持为latest + image: registry.cn-shenzhen.aliyuncs.com/handsfree/certd:latest + ... # 这里是你原来的docker-compose.yaml配置 + + # ↓↓↓↓ --------------------------------------------------------- 增加一个标签,表示certd需要自动升级 + labels: + com.centurylinklabs.watchtower.enable: "true" + +# ↓↓↓↓ --------------------------------------------------------- 自动升级watchtower配置,注意:上面certd的版本号要保持为latest + certd-updater: # 添加 Watchtower 服务 + image: containrrr/watchtower:latest + container_name: certd-updater + restart: unless-stopped + volumes: + - /var/run/docker.sock:/var/run/docker.sock + # 配置 自动更新 + environment: + - WATCHTOWER_CLEANUP=true # 自动清理旧版本容器 + - WATCHTOWER_INCLUDE_STOPPED=false # 不更新已停止的容器 + - WATCHTOWER_LABEL_ENABLE=true # 根据容器标签进行更新 + - WATCHTOWER_POLL_INTERVAL=600 # 每 10 分钟检查一次更新 + +``` + +2. 重启certd容器 +```shell +cd certd +docker compose down +docker compose up -d +``` + + +### 2. 方法二:使用Certd版本监控功能【不太稳定】 + +1. 选择Github-检查Release版本插件 +![](./images/github-release.png) +按如下图填写配置 +![](./images/github-release-2.png) + + +2. 检测到新版本后执行宿主机升级命令: + +```shell +# 拉取最新镜像 +docker pull registry.cn-shenzhen.aliyuncs.com/handsfree/certd:latest +# 升级容器命令, 替换成你自己的certd更新命令 +export RESTART_CERT='sleep 10; cd ~/deploy/certd/ ; docker compose down; docker compose up -d' +# 构造一个脚本10s后在后台执行,避免容器销毁时执行太快,导致流水线任务无法结束 +nohup sh -c '$RESTART_CERT' >/dev/null 2>&1 & echo '10秒后重启' && exit +``` \ No newline at end of file diff --git a/docs/guide/install/upgrade.md b/docs/guide/install/upgrade.md index cfa38b245..ef930fd17 100644 --- a/docs/guide/install/upgrade.md +++ b/docs/guide/install/upgrade.md @@ -22,51 +22,3 @@ 可以查看最新版本号,以及所有版本的更新日志 [CHANGELOG](../changelogs/CHANGELOG.md) - -## 自动升级配置 - -### 1. 方法一:使用watchtower监控 - -修改docker-compose.yaml文件增加如下配置, 使用watchtower监控自动升级 -```yaml -services: - certd: - ... - labels: - com.centurylinklabs.watchtower.enable: "true" - -# ↓↓↓↓ --------------------------------------------------------- 自动升级,上面certd的版本号要保持为latest - certd-updater: # 添加 Watchtower 服务 - image: containrrr/watchtower:latest - container_name: certd-updater - restart: unless-stopped - volumes: - - /var/run/docker.sock:/var/run/docker.sock - # 配置 自动更新 - environment: - - WATCHTOWER_CLEANUP=true # 自动清理旧版本容器 - - WATCHTOWER_INCLUDE_STOPPED=false # 不更新已停止的容器 - - WATCHTOWER_LABEL_ENABLE=true # 根据容器标签进行更新 - - WATCHTOWER_POLL_INTERVAL=600 # 每 10 分钟检查一次更新 - -``` - - -### 2. 方法二:使用Certd版本监控功能 - -选择Github-检查Release版本插件 -![](./images/github-release.png) -按如下图填写配置 -![](./images/github-release-2.png) - - -检测到新版本后执行宿主机升级命令: - -```shell -# 拉取最新镜像 -docker pull registry.cn-shenzhen.aliyuncs.com/handsfree/certd:latest -# 升级容器命令, 替换成你自己的certd更新命令 -export RESTART_CERT='sleep 10; cd ~/deploy/certd/ ; docker compose down; docker compose up -d' -# 构造一个脚本10s后在后台执行,避免容器销毁时执行太快,导致流水线任务无法结束 -nohup sh -c '$RESTART_CERT' >/dev/null 2>&1 & echo '10秒后重启' && exit -``` \ No newline at end of file From a815d0245b97efbb948b33d6fc9d49862ce06889 Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Fri, 15 May 2026 00:25:28 +0800 Subject: [PATCH 03/34] =?UTF-8?q?perf:=20=E7=AC=AC=E4=B8=89=E6=96=B9?= =?UTF-8?q?=E7=99=BB=E5=BD=95=E8=87=AA=E5=8A=A8=E6=B3=A8=E5=86=8C=E7=9A=84?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E6=94=AF=E6=8C=81=E8=AE=BE=E7=BD=AE=E5=88=9D?= =?UTF-8?q?=E5=A7=8B=E5=8C=96=E5=AF=86=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/basic/file-controller.test.ts | 20 +++++++++++++++++++ .../src/controller/basic/file-controller.ts | 14 +++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 packages/ui/certd-server/src/controller/basic/file-controller.test.ts diff --git a/packages/ui/certd-server/src/controller/basic/file-controller.test.ts b/packages/ui/certd-server/src/controller/basic/file-controller.test.ts new file mode 100644 index 000000000..a09837292 --- /dev/null +++ b/packages/ui/certd-server/src/controller/basic/file-controller.test.ts @@ -0,0 +1,20 @@ +/// +/// + +import assert from "node:assert/strict"; + +import { isImageFile } from "./file-controller.js"; + +describe("FileController.isImageFile", () => { + it("detects uploaded logo image files", () => { + assert.equal(isImageFile("data/upload/public/user/logo.PNG"), true); + assert.equal(isImageFile("data/upload/public/user/logo.svg"), true); + assert.equal(isImageFile("data/upload/public/user/logo.webp"), true); + }); + + it("does not treat non-image downloads as logo images", () => { + assert.equal(isImageFile("data/upload/public/user/archive.zip"), false); + assert.equal(isImageFile("data/upload/public/user/cert.pem"), false); + assert.equal(isImageFile("data/upload/public/user/logo"), false); + }); +}); diff --git a/packages/ui/certd-server/src/controller/basic/file-controller.ts b/packages/ui/certd-server/src/controller/basic/file-controller.ts index d2dca2acd..e0340fd79 100644 --- a/packages/ui/certd-server/src/controller/basic/file-controller.ts +++ b/packages/ui/certd-server/src/controller/basic/file-controller.ts @@ -5,6 +5,13 @@ import { nanoid } from 'nanoid'; import { cache } from '@certd/basic'; import { UploadFileInfo } from '@midwayjs/upload'; +const imageExtSet = new Set(['.apng', '.avif', '.bmp', '.gif', '.ico', '.jpeg', '.jpg', '.png', '.svg', '.webp']); +const imageCacheSeconds = 3 * 24 * 60 * 60; + +export function isImageFile(filePath: string) { + return imageExtSet.has(filePath.substring(filePath.lastIndexOf('.')).toLowerCase()); +} + /** */ @Provide() @@ -40,8 +47,11 @@ export class FileController extends BaseController { userId = this.getUserId(); } const filePath = this.fileService.getFile(key, userId); - this.ctx.response.attachment(filePath); - this.ctx.response.set('Cache-Control', 'public,max-age=2592000'); + if (isImageFile(filePath)) { + this.ctx.response.set('Cache-Control', `public,max-age=${imageCacheSeconds}`); + } else { + this.ctx.response.attachment(filePath); + } await send(this.ctx, filePath); } } From 3b72ca09c687743ad6e6478df1ea6205864fb9a5 Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Fri, 15 May 2026 00:26:24 +0800 Subject: [PATCH 04/34] =?UTF-8?q?chore:=20=E6=94=AF=E6=8C=81=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE=E5=88=9D=E5=A7=8B=E5=8C=96=E5=AF=86=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 6 +- README.md | 1 + .../src/locales/langs/en-US/authentication.ts | 5 + .../src/locales/langs/zh-CN/authentication.ts | 5 + .../certd-client/src/store/user/api.user.ts | 1 + .../certd-client/src/views/certd/mine/api.ts | 8 + .../certd/mine/change-password-button.vue | 33 +++- .../src/views/certd/mine/user-profile.vue | 18 +- .../controller/user/mine/mine-controller.ts | 54 +++--- .../service/user-password-init.test.ts | 51 ++++++ .../sys/authority/service/user-service.ts | 168 ++++++++++-------- 11 files changed, 243 insertions(+), 107 deletions(-) create mode 100644 packages/ui/certd-server/src/modules/sys/authority/service/user-password-init.test.ts diff --git a/AGENTS.md b/AGENTS.md index e878d1064..3a008f4ec 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -105,7 +105,7 @@ Certd 是一个支持私有化部署的 SSL/TLS 证书自动化管理平台。 - 前端 `pnpm dev`:启动 Vite 开发服务 - 前端 `pnpm build`:生产构建 -- 前端 `pnpm tsc`:类型检查 +- 不要运行前端 `pnpm tsc` / `vue-tsc`:当前依赖组合中 `vue-tsc@1.8.27` 会直接抛内部错误 `Search string not found: "/supportedTSExtensions = .*(?=;)/"`,不是有效的项目类型检查结果。 - 前端暂不跑单元测试;当前 `test:unit` 只是占位脚本 ## 流水线与插件模型 @@ -216,5 +216,5 @@ Get-ChildItem packages\ui\certd-client\src\views\certd - 后端纯单元测试用例放在 `src` 目录内,并尽量与被测文件相邻,例如 `src/utils/random.test.ts`;对应 `test:unit` 只跑 `src/**/*.test.ts`,构建/打包配置应排除这些 `*.test.ts` 文件。 - 单元测试需要 mock ESM 静态 import 时,优先使用 `esmock`,不要为了测试把业务代码改成构造函数注入或把逻辑挪到调用方;各包 `test:unit` 脚本应显式设置 `NODE_ENV=unittest`。 - 单个 monorepo 包运行单元测试时,优先使用 `corepack pnpm --dir <包目录> test:unit`,例如 `corepack pnpm --dir packages\ui\certd-server test:unit`、`corepack pnpm --dir packages\core\basic test:unit`、`corepack pnpm --dir packages\plugins\plugin-lib test:unit`;也可以用包名过滤,例如 `corepack pnpm --filter @certd/ui-server test:unit`。前端 `packages\ui\certd-client` 暂时不跑单元测试。 -- 前端 TS/Vue/locale 等文件改动后,优先只对本次改动文件运行项目现有自动格式化/修复;Windows/PowerShell 下 Prettier 已验证可用命令为 `packages\ui\certd-client\node_modules\.bin\prettier.cmd --write `,ESLint 可用命令为 `packages\ui\certd-client\node_modules\.bin\eslint.cmd --fix `;不要为了格式化无关文件而扩大 diff。项目保留了 `tslint` 依赖,但当前主要使用 ESLint + Prettier。 -- 优先对改动包运行聚焦的测试或类型检查;只有跨包影响明显时再考虑全 monorepo 构建。 +- 前端 TS/Vue/locale 等文件改动后,优先只对本次改动文件运行项目现有自动格式化/修复;Windows/PowerShell 下 Prettier 已验证可用命令为 `packages\ui\certd-client\node_modules\.bin\prettier.cmd --write `,ESLint 可用命令为 `packages\ui\certd-client\node_modules\.bin\eslint.cmd --fix `;不要运行 `vue-tsc` / `pnpm tsc`;不要为了格式化无关文件而扩大 diff。项目保留了 `tslint` 依赖,但当前主要使用 ESLint + Prettier。 +- 优先对改动包运行聚焦的测试;后端可按包运行单元测试,前端优先使用 Prettier/ESLint 做改动文件验证。只有跨包影响明显时再考虑全 monorepo 构建。 diff --git a/README.md b/README.md index 79987d561..f4d96c2a0 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,7 @@ Certd® 是一个免费的全自动证书管理系统,让你的网站证书永 * **开放接口支持**: 提供RESTful API接口,方便集成到其他系统 * **站点证书监控**: 定时监控网站证书的过期时间 * **多用户管理**: 用户可以管理自己的证书流水线 +* **项目管理**: 企业级项目管理模式 * **多语言支持**: 中英双语切换 * **无忧升级**: 版本向下兼容 diff --git a/packages/ui/certd-client/src/locales/langs/en-US/authentication.ts b/packages/ui/certd-client/src/locales/langs/en-US/authentication.ts index aba15f531..77a08fb85 100644 --- a/packages/ui/certd-client/src/locales/langs/en-US/authentication.ts +++ b/packages/ui/certd-client/src/locales/langs/en-US/authentication.ts @@ -78,8 +78,13 @@ export default { passkeyRegisterFailed: "Passkey registration failed", title: "Change Password", weakPasswordWarning: "For your account security, please change your password immediately", + initPasswordWarning: "This account does not have a login password yet. Please set one first", + initPasswordTitle: "Set Password", changeNow: "Change Now", + setNow: "Set Now", + notNow: "Not Now", successMessage: "Changed successfully", + initPasswordSuccessMessage: "Set successfully", oldPassword: "Old Password", oldPasswordRequired: "Please enter the old password", newPassword: "New Password", diff --git a/packages/ui/certd-client/src/locales/langs/zh-CN/authentication.ts b/packages/ui/certd-client/src/locales/langs/zh-CN/authentication.ts index 4ec2f109f..f4e23f5ef 100644 --- a/packages/ui/certd-client/src/locales/langs/zh-CN/authentication.ts +++ b/packages/ui/certd-client/src/locales/langs/zh-CN/authentication.ts @@ -79,8 +79,13 @@ export default { title: "修改密码", weakPasswordWarning: "为了您的账户安全,请立即修改密码", + initPasswordWarning: "当前账号还未设置登录密码,请先设置密码", + initPasswordTitle: "设置密码", changeNow: "立即修改", + setNow: "立即设置", + notNow: "暂不设置", successMessage: "修改成功", + initPasswordSuccessMessage: "设置成功", oldPassword: "旧密码", oldPasswordRequired: "请输入旧密码", newPassword: "新密码", diff --git a/packages/ui/certd-client/src/store/user/api.user.ts b/packages/ui/certd-client/src/store/user/api.user.ts index e358c760c..498c08abe 100644 --- a/packages/ui/certd-client/src/store/user/api.user.ts +++ b/packages/ui/certd-client/src/store/user/api.user.ts @@ -38,6 +38,7 @@ export interface UserInfoRes { avatar?: string; roleIds: number[]; isWeak?: boolean; + needInitPassword?: boolean; validTime?: number; status?: number; } diff --git a/packages/ui/certd-client/src/views/certd/mine/api.ts b/packages/ui/certd-client/src/views/certd/mine/api.ts index 5cabbd16c..04bcd69fd 100644 --- a/packages/ui/certd-client/src/views/certd/mine/api.ts +++ b/packages/ui/certd-client/src/views/certd/mine/api.ts @@ -15,6 +15,14 @@ export async function changePassword(form: any) { }); } +export async function initPassword(form: any) { + return await request({ + url: "/mine/initPassword", + method: "POST", + data: form, + }); +} + export async function UpdateProfile(form: any) { return await request({ url: "/mine/updateProfile", diff --git a/packages/ui/certd-client/src/views/certd/mine/change-password-button.vue b/packages/ui/certd-client/src/views/certd/mine/change-password-button.vue index a1b530de6..ed2f2ec3c 100644 --- a/packages/ui/certd-client/src/views/certd/mine/change-password-button.vue +++ b/packages/ui/certd-client/src/views/certd/mine/change-password-button.vue @@ -9,7 +9,7 @@ import { ref } from "vue"; import { useI18n } from "/src/locales"; const { t } = useI18n(); -import { CrudOptions, useColumns, useFormWrapper } from "@fast-crud/fast-crud"; +import { compute, CrudOptions, useColumns, useFormWrapper } from "@fast-crud/fast-crud"; import * as api from "/@/views/certd/mine/api"; import { notification } from "ant-design-vue"; import { useUserStore } from "/@/store/user"; @@ -20,6 +20,11 @@ defineProps<{ let passwordFormRef = ref(); +type OpenOptions = { + password?: string; + init?: boolean; +}; + const validatePass1 = async (rule: any, value: any) => { if (value === "") { throw new Error(t("authentication.enterPassword")); @@ -53,19 +58,33 @@ const passwordFormOptions: CrudOptions = { width: "500px", }, async doSubmit({ form }) { - await api.changePassword(form); + if (form.init) { + await api.initPassword(form); + } else { + await api.changePassword(form); + } //重新加载用户信息 await userStore.loadUserInfo(); }, async afterSubmit() { - notification.success({ message: t("authentication.successMessage") }); + const formData = passwordFormRef.value?.getFormData?.(); + const message = formData?.init ? t("authentication.initPasswordSuccessMessage") : t("authentication.successMessage"); + notification.success({ message }); }, }, columns: { + init: { + title: "init", + type: "text", + form: { + show: false, + }, + }, password: { title: t("authentication.oldPassword"), type: "password", form: { + show: compute(({ form }) => form.init !== true), rules: [{ required: true, message: t("authentication.oldPasswordRequired") }], }, }, @@ -97,12 +116,16 @@ const passwordFormOptions: CrudOptions = { }, }; -async function open(opts: { password: "" }) { +async function open(opts: OpenOptions = {}) { const formOptions = buildFormOptions(passwordFormOptions); formOptions.newInstance = true; //新实例打开 + if (opts.init) { + formOptions.wrapper.title = t("authentication.initPasswordTitle"); + } passwordFormRef.value = await openDialog(formOptions); passwordFormRef.value.setFormData({ - password: opts.password, + init: opts.init === true, + password: opts.password || "", }); console.log(passwordFormRef.value); } diff --git a/packages/ui/certd-client/src/views/certd/mine/user-profile.vue b/packages/ui/certd-client/src/views/certd/mine/user-profile.vue index 8fb3e8145..11009f97e 100644 --- a/packages/ui/certd-client/src/views/certd/mine/user-profile.vue +++ b/packages/ui/certd-client/src/views/certd/mine/user-profile.vue @@ -48,7 +48,7 @@
- + {{ t("authentication.securitySettingTip") }} @@ -387,6 +387,7 @@ const checkPasskeySupport = () => { } }; const userStore = useUserStore(); +const changePasswordButtonRef = ref(); const userAvatar = computed(() => { if (isEmpty(userInfo.value.avatar)) { return ""; @@ -400,6 +401,21 @@ const userAvatar = computed(() => { onMounted(async () => { await getUserInfo(); + userStore.setUserInfo(userInfo.value); + if (userInfo.value.needInitPassword === true) { + Modal.confirm({ + title: t("authentication.initPasswordTitle"), + content: t("authentication.initPasswordWarning"), + okText: t("authentication.setNow"), + cancelText: t("authentication.notNow"), + closable: true, + onOk: () => { + changePasswordButtonRef.value.open({ + init: true, + }); + }, + }); + } await loadContactCapability(); await loadOauthBounds(); await loadOauthProviders(); diff --git a/packages/ui/certd-server/src/controller/user/mine/mine-controller.ts b/packages/ui/certd-server/src/controller/user/mine/mine-controller.ts index 95f7c96da..fde30a218 100644 --- a/packages/ui/certd-server/src/controller/user/mine/mine-controller.ts +++ b/packages/ui/certd-server/src/controller/user/mine/mine-controller.ts @@ -1,16 +1,16 @@ -import { BaseController, Constants, SysSettingsService } from '@certd/lib-server'; -import { ALL, Body, Controller, Inject, Post, Provide } from '@midwayjs/core'; -import { PasskeyService } from '../../../modules/login/service/passkey-service.js'; -import { RoleService } from '../../../modules/sys/authority/service/role-service.js'; -import { UserService } from '../../../modules/sys/authority/service/user-service.js'; -import { ApiTags } from '@midwayjs/swagger'; -import { CodeService } from '../../../modules/basic/service/code-service.js'; +import { BaseController, Constants, SysSettingsService } from "@certd/lib-server"; +import { ALL, Body, Controller, Inject, Post, Provide } from "@midwayjs/core"; +import { PasskeyService } from "../../../modules/login/service/passkey-service.js"; +import { RoleService } from "../../../modules/sys/authority/service/role-service.js"; +import { UserService } from "../../../modules/sys/authority/service/user-service.js"; +import { ApiTags } from "@midwayjs/swagger"; +import { CodeService } from "../../../modules/basic/service/code-service.js"; /** */ @Provide() -@Controller('/api/mine') -@ApiTags(['mine']) +@Controller("/api/mine") +@ApiTags(["mine"]) export class MineController extends BaseController { @Inject() userService: UserService; @@ -27,28 +27,38 @@ export class MineController extends BaseController { @Inject() sysSettingsService: SysSettingsService; - @Post('/info', { description: Constants.per.authOnly, summary: '查询用户信息' }) + @Post("/info", { description: Constants.per.authOnly, summary: "查询用户信息" }) public async info() { const userId = this.getUserId(); const user = await this.userService.info(userId); - const isWeak = await this.userService.checkPassword('123456', user.password, user.passwordVersion); + const isWeak = await this.userService.checkPassword("123456", user.password, user.passwordVersion); if (isWeak) { //@ts-ignore user.isWeak = true; } + const needInitPassword = user.password === "changeme"; user.roleIds = await this.roleService.getRoleIdsByUserId(userId); delete user.password; + //@ts-ignore + user.needInitPassword = needInitPassword; return this.ok(user); } - @Post('/changePassword', { description: Constants.per.authOnly, summary: '修改密码' }) + @Post("/changePassword", { description: Constants.per.authOnly, summary: "修改密码" }) public async changePassword(@Body(ALL) body: any) { const userId = this.getUserId(); await this.userService.changePassword(userId, body); return this.ok({}); } - @Post('/updateProfile', { description: Constants.per.authOnly, summary: '更新用户资料' }) + @Post("/initPassword", { description: Constants.per.authOnly, summary: "初始化密码" }) + public async initPassword(@Body(ALL) body: any) { + const userId = this.getUserId(); + await this.userService.initPassword(userId, body); + return this.ok({}); + } + + @Post("/updateProfile", { description: Constants.per.authOnly, summary: "更新用户资料" }) public async updateProfile(@Body(ALL) body: any) { const userId = this.getUserId(); @@ -59,7 +69,7 @@ export class MineController extends BaseController { return this.ok({}); } - @Post('/contact/capability', { description: Constants.per.authOnly, summary: '查询联系方式绑定能力' }) + @Post("/contact/capability", { description: Constants.per.authOnly, summary: "查询联系方式绑定能力" }) public async contactCapability() { const settings = await this.sysSettingsService.getPrivateSettings(); return this.ok({ @@ -67,27 +77,27 @@ export class MineController extends BaseController { }); } - @Post('/contact/verifyIdentity', { description: Constants.per.authOnly, summary: '验证本人操作' }) - public async verifyContactIdentity(@Body(ALL) body: { identityType: 'password' | 'email' | 'mobile'; identityPassword?: string; identityValidateCode?: string }) { + @Post("/contact/verifyIdentity", { description: Constants.per.authOnly, summary: "验证本人操作" }) + public async verifyContactIdentity(@Body(ALL) body: { identityType: "password" | "email" | "mobile"; identityPassword?: string; identityValidateCode?: string }) { const userId = this.getUserId(); await this.userService.verifyIdentity(userId, body, this.codeService); const validationCode = this.codeService.setValidationValue({ - type: 'contactIdentity', + type: "contactIdentity", userId, identityType: body.identityType, }); return this.ok({ validationCode }); } - @Post('/contact/mobile', { description: Constants.per.authOnly, summary: '绑定或修改手机号' }) + @Post("/contact/mobile", { description: Constants.per.authOnly, summary: "绑定或修改手机号" }) public async updateMobile(@Body(ALL) body: { phoneCode?: string; mobile: string; validateCode: string; identityValidationCode: string }) { const userId = this.getUserId(); this.userService.checkContactIdentityValidation(userId, body.identityValidationCode, this.codeService); await this.codeService.checkSmsCode({ mobile: body.mobile, - phoneCode: body.phoneCode || '86', + phoneCode: body.phoneCode || "86", smsCode: body.validateCode, - verificationType: 'bindMobile', + verificationType: "bindMobile", throwError: true, }); await this.userService.updateMobile(userId, { @@ -97,14 +107,14 @@ export class MineController extends BaseController { return this.ok({}); } - @Post('/contact/email', { description: Constants.per.authOnly, summary: '绑定或修改邮箱' }) + @Post("/contact/email", { description: Constants.per.authOnly, summary: "绑定或修改邮箱" }) public async updateEmail(@Body(ALL) body: { email: string; validateCode: string; identityValidationCode: string }) { const userId = this.getUserId(); this.userService.checkContactIdentityValidation(userId, body.identityValidationCode, this.codeService); this.codeService.checkEmailCode({ email: body.email, validateCode: body.validateCode, - verificationType: 'bindEmail', + verificationType: "bindEmail", throwError: true, }); await this.userService.updateEmail(userId, { diff --git a/packages/ui/certd-server/src/modules/sys/authority/service/user-password-init.test.ts b/packages/ui/certd-server/src/modules/sys/authority/service/user-password-init.test.ts new file mode 100644 index 000000000..96fa3f77e --- /dev/null +++ b/packages/ui/certd-server/src/modules/sys/authority/service/user-password-init.test.ts @@ -0,0 +1,51 @@ +/// + +import assert from "node:assert/strict"; +import { UserService } from "./user-service.js"; + +describe("UserService.initPassword", () => { + function createService(user: any) { + const service = new UserService(); + service.info = async () => user; + let updatedParam: any; + service.update = async (param: any) => { + updatedParam = param; + }; + return { service, getUpdatedParam: () => updatedParam }; + } + + it("sets a new password when current password is changeme", async () => { + const { service, getUpdatedParam } = createService({ + id: 12, + password: "changeme", + passwordVersion: 2, + }); + + await service.initPassword(12, { + newPassword: "new-password", + confirmNewPassword: "new-password", + }); + + assert.deepEqual(getUpdatedParam(), { + id: 12, + password: "new-password", + }); + }); + + it("rejects initPassword after password has already been set", async () => { + const { service } = createService({ + id: 12, + password: "$2a$10$already-hashed", + passwordVersion: 2, + }); + + await assert.rejects( + () => + service.initPassword(12, { + newPassword: "new-password", + confirmNewPassword: "new-password", + }), + /当前账号已设置密码/ + ); + }); +}); diff --git a/packages/ui/certd-server/src/modules/sys/authority/service/user-service.ts b/packages/ui/certd-server/src/modules/sys/authority/service/user-service.ts index 311c4948c..ac931a48f 100644 --- a/packages/ui/certd-server/src/modules/sys/authority/service/user-service.ts +++ b/packages/ui/certd-server/src/modules/sys/authority/service/user-service.ts @@ -1,22 +1,22 @@ -import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core'; -import { InjectEntityModel } from '@midwayjs/typeorm'; -import { EntityManager, In, MoreThan, Not, Repository } from 'typeorm'; -import { UserEntity } from '../entity/user.js'; -import * as _ from 'lodash-es'; -import { BaseService, CommonException, Constants, FileService, SysInstallInfo, SysSettingsService } from '@certd/lib-server'; -import { RoleService } from './role-service.js'; -import { PermissionService } from './permission-service.js'; -import { UserRoleService } from './user-role-service.js'; -import { UserRoleEntity } from '../entity/user-role.js'; -import bcrypt from 'bcryptjs'; -import { RandomUtil } from '../../../../utils/random.js'; -import dayjs from 'dayjs'; -import { DbAdapter } from '../../../db/index.js'; -import { simpleNanoId, utils } from '@certd/basic'; -import { OauthBoundService } from '../../../login/service/oauth-bound-service.js'; +import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core"; +import { InjectEntityModel } from "@midwayjs/typeorm"; +import { EntityManager, In, MoreThan, Not, Repository } from "typeorm"; +import { UserEntity } from "../entity/user.js"; +import * as _ from "lodash-es"; +import { BaseService, CommonException, Constants, FileService, SysInstallInfo, SysSettingsService } from "@certd/lib-server"; +import { RoleService } from "./role-service.js"; +import { PermissionService } from "./permission-service.js"; +import { UserRoleService } from "./user-role-service.js"; +import { UserRoleEntity } from "../entity/user-role.js"; +import bcrypt from "bcryptjs"; +import { RandomUtil } from "../../../../utils/random.js"; +import dayjs from "dayjs"; +import { DbAdapter } from "../../../db/index.js"; +import { simpleNanoId, utils } from "@certd/basic"; +import { OauthBoundService } from "../../../login/service/oauth-bound-service.js"; -export type RegisterType = 'username' | 'mobile' | 'email'; -export type ForgotPasswordType = 'mobile' | 'email'; +export type RegisterType = "username" | "mobile" | "email"; +export type ForgotPasswordType = "mobile" | "email"; export const AdminRoleId = 1; @@ -83,14 +83,14 @@ export class UserService extends BaseService { }, }); if (!_.isEmpty(exists)) { - throw new CommonException('用户名已经存在'); + throw new CommonException("用户名已经存在"); } const plainPassword = param.password ?? RandomUtil.randomStr(6); param.passwordVersion = 2; param.password = await this.genPassword(plainPassword, param.passwordVersion); // 默认密码 建议未改密码不能登陆 if (param.avatar) { - param.avatar = await this.fileService.saveFile(0, param.avatar, 'public'); + param.avatar = await this.fileService.saveFile(0, param.avatar, "public"); } await super.add(param); @@ -107,13 +107,13 @@ export class UserService extends BaseService { */ async update(param) { if (param.id == null) { - throw new CommonException('id不能为空'); + throw new CommonException("id不能为空"); } const userInfo = await this.repository.findOne({ where: { id: param.id }, }); if (!userInfo) { - throw new CommonException('用户不存在'); + throw new CommonException("用户不存在"); } if (param.username) { @@ -125,7 +125,7 @@ export class UserService extends BaseService { { email: username, id: Not(id) }, ]); if (old != null) { - throw new CommonException('用户名已被占用'); + throw new CommonException("用户名已被占用"); } } if (!_.isEmpty(param.password)) { @@ -136,7 +136,7 @@ export class UserService extends BaseService { } if (param.avatar) { - param.avatar = await this.fileService.saveFile(userInfo.id, param.avatar, 'public'); + param.avatar = await this.fileService.saveFile(userInfo.id, param.avatar, "public"); } await super.update(param); await this.roleService.updateRoles(param.id, param.roles); @@ -168,7 +168,7 @@ export class UserService extends BaseService { async buildPlainPassword(rawPassword: string) { const setting: SysInstallInfo = await this.sysSettingsService.getSetting(SysInstallInfo); if (!setting.siteId) { - throw new CommonException('站点ID还未初始化'); + throw new CommonException("站点ID还未初始化"); } const prefixSiteId = setting.siteId.substring(1, 5); return rawPassword + prefixSiteId; @@ -192,48 +192,47 @@ export class UserService extends BaseService { const username = user.username; const old = await this.findOne([{ username: username }, { mobile: username }, { email: username }]); if (old != null) { - throw new CommonException('用户名已被注册'); + throw new CommonException("用户名已被注册"); } } if (user.mobile) { const mobile = user.mobile; - user.nickName = user.username || mobile.substring(0, 3) + '****' + mobile.substring(7); + user.nickName = user.username || mobile.substring(0, 3) + "****" + mobile.substring(7); const old = await this.findOne([{ username: mobile }, { mobile: mobile }, { email: mobile }]); if (old != null) { - throw new CommonException('手机号已被注册'); + throw new CommonException("手机号已被注册"); } } if (user.email) { const email = user.email; const old = await this.findOne([{ username: email }, { mobile: email }, { email: email }]); if (old != null) { - throw new CommonException('邮箱已被注册'); + throw new CommonException("邮箱已被注册"); } } if (!user.username) { - user.username = 'user_' + simpleNanoId(); + user.username = "user_" + simpleNanoId(); } let newUser: UserEntity = UserEntity.of({ username: user.username, password: user.password, - email: user.email || '', - mobile: user.mobile || '', + email: user.email || "", + mobile: user.mobile || "", nickName: user.nickName || user.username, - avatar: user.avatar || '', - phoneCode: user.phoneCode || '86', + avatar: user.avatar || "", + phoneCode: user.phoneCode || "86", status: 1, passwordVersion: 2, }); if (!newUser.password) { newUser.password = "changeme"; - }else{ + } else { newUser.password = await this.genPassword(newUser.password, newUser.passwordVersion); } - await this.transaction(async txManager => { newUser = await txManager.save(newUser); @@ -248,28 +247,28 @@ export class UserService extends BaseService { delete newUser.password; - utils.mitter.emit('register', { userId: newUser.id }); + utils.mitter.emit("register", { userId: newUser.id }); return newUser; } async forgotPassword(data: { type: ForgotPasswordType; input?: string; phoneCode?: string; validateCode: string; password: string; confirmPassword: string }) { if (!data.type) { - throw new CommonException('找回类型不能为空'); + throw new CommonException("找回类型不能为空"); } if (data.password !== data.confirmPassword) { - throw new CommonException('两次输入的密码不一致'); + throw new CommonException("两次输入的密码不一致"); } const where: any = { [data.type]: data.input, }; - if (data.type === 'mobile') { - where.phoneCode = data.phoneCode ?? '86'; + if (data.type === "mobile") { + where.phoneCode = data.phoneCode ?? "86"; } const user = await this.findOne({ [data.type]: data.input }); - console.log('user', user); + console.log("user", user); if (!user) { - throw new CommonException('用户不存在'); + throw new CommonException("用户不存在"); // return; } await this.resetPassword(user.id, data.password); @@ -284,7 +283,7 @@ export class UserService extends BaseService { const user = await this.info(userId); const passwordChecked = await this.checkPassword(form.password, user.password, user.passwordVersion); if (!passwordChecked) { - throw new CommonException('原密码错误'); + throw new CommonException("原密码错误"); } const param = { id: userId, @@ -294,9 +293,26 @@ export class UserService extends BaseService { await this.update(param); } + async initPassword(userId: any, form: any) { + const user = await this.info(userId); + if (user.password !== "changeme") { + throw new CommonException("当前账号已设置密码"); + } + if (!form.newPassword) { + throw new CommonException("新密码不能为空"); + } + if (form.newPassword !== form.confirmNewPassword) { + throw new CommonException("两次输入的密码不一致"); + } + await this.update({ + id: userId, + password: form.newPassword, + }); + } + async resetPassword(userId: any, newPasswd: string) { if (!userId) { - throw new CommonException('userId不能为空'); + throw new CommonException("userId不能为空"); } const param = { id: userId, @@ -307,15 +323,15 @@ export class UserService extends BaseService { //@ts-ignore async delete(ids: any) { - if (typeof ids === 'string') { - ids = ids.split(','); + if (typeof ids === "string") { + ids = ids.split(","); ids = ids.map(id => parseInt(id)); } if (ids.length === 0) { return; } if (ids.includes(1)) { - throw new CommonException('不能删除管理员'); + throw new CommonException("不能删除管理员"); } await super.delete(ids); await this.oauthBoundService.deleteWhere({ @@ -325,7 +341,7 @@ export class UserService extends BaseService { async isAdmin(userId: any) { if (!userId) { - throw new CommonException('userId不能为空'); + throw new CommonException("userId不能为空"); } const userRoles = await this.userRoleService.find({ where: { @@ -340,7 +356,7 @@ export class UserService extends BaseService { async updateStatus(id: number, status: number) { if (!id) { - throw new CommonException('userId不能为空'); + throw new CommonException("userId不能为空"); } await this.repository.update(id, { status, @@ -357,16 +373,16 @@ export class UserService extends BaseService { } async registerCountPerDay(param: { days: number } = { days: 7 }) { - const todayEnd = dayjs().endOf('day'); + const todayEnd = dayjs().endOf("day"); const result = await this.getRepository() - .createQueryBuilder('main') - .select(`${this.dbAdapter.date('main.createTime')} AS date`) // 将UNIX时间戳转换为日期 - .addSelect('COUNT(1) AS count') + .createQueryBuilder("main") + .select(`${this.dbAdapter.date("main.createTime")} AS date`) // 将UNIX时间戳转换为日期 + .addSelect("COUNT(1) AS count") .where({ // 0点 - createTime: MoreThan(todayEnd.add(-param.days, 'day').toDate()), + createTime: MoreThan(todayEnd.add(-param.days, "day").toDate()), }) - .groupBy('date') + .groupBy("date") .getRawMany(); return result; @@ -386,7 +402,7 @@ export class UserService extends BaseService { status: 1, }, order: { - updateTime: 'DESC', + updateTime: "DESC", }, }); } @@ -398,61 +414,61 @@ export class UserService extends BaseService { }); } - async verifyIdentity(userId: number, body: { identityType: 'password' | 'email' | 'mobile'; identityPassword?: string; identityValidateCode?: string }, codeService: any) { + async verifyIdentity(userId: number, body: { identityType: "password" | "email" | "mobile"; identityPassword?: string; identityValidateCode?: string }, codeService: any) { const user = await this.info(userId); - if (body.identityType === 'password') { + if (body.identityType === "password") { const passwordChecked = await this.checkPassword(body.identityPassword, user.password, user.passwordVersion); if (!passwordChecked) { - throw new CommonException('密码错误'); + throw new CommonException("密码错误"); } return; } - if (body.identityType === 'email') { + if (body.identityType === "email") { if (!user.email) { - throw new CommonException('当前账号未绑定邮箱'); + throw new CommonException("当前账号未绑定邮箱"); } codeService.checkEmailCode({ email: user.email, validateCode: body.identityValidateCode, - verificationType: 'contactIdentity', + verificationType: "contactIdentity", throwError: true, }); return; } - if (body.identityType === 'mobile') { + if (body.identityType === "mobile") { if (!user.mobile) { - throw new CommonException('当前账号未绑定手机号'); + throw new CommonException("当前账号未绑定手机号"); } await codeService.checkSmsCode({ mobile: user.mobile, - phoneCode: user.phoneCode || '86', + phoneCode: user.phoneCode || "86", smsCode: body.identityValidateCode, - verificationType: 'contactIdentity', + verificationType: "contactIdentity", throwError: true, }); return; } - throw new CommonException('不支持的验证方式'); + throw new CommonException("不支持的验证方式"); } checkContactIdentityValidation(userId: number, validationCode: string, codeService: any) { const validationValue = codeService.getValidationValue(validationCode); - if (!validationValue || validationValue.type !== 'contactIdentity' || validationValue.userId !== userId) { - throw new CommonException('请先验证本人操作'); + if (!validationValue || validationValue.type !== "contactIdentity" || validationValue.userId !== userId) { + throw new CommonException("请先验证本人操作"); } } async updateMobile(userId: number, body: { phoneCode?: string; mobile: string }) { const mobile = body.mobile?.trim(); if (!mobile) { - throw new CommonException('手机号不能为空'); + throw new CommonException("手机号不能为空"); } const old = await this.findOne(buildUserContactConflictWhere(mobile, userId)); if (old != null) { - throw new CommonException('手机号已被占用'); + throw new CommonException("手机号已被占用"); } await this.repository.update(userId, { - phoneCode: body.phoneCode || '86', + phoneCode: body.phoneCode || "86", mobile, }); } @@ -460,11 +476,11 @@ export class UserService extends BaseService { async updateEmail(userId: number, body: { email: string }) { const email = body.email?.trim(); if (!email) { - throw new CommonException('邮箱不能为空'); + throw new CommonException("邮箱不能为空"); } const old = await this.findOne(buildUserContactConflictWhere(email, userId)); if (old != null) { - throw new CommonException('邮箱已被占用'); + throw new CommonException("邮箱已被占用"); } await this.repository.update(userId, { email, @@ -473,7 +489,7 @@ export class UserService extends BaseService { async getAllUserIds() { const users = await this.repository.find({ - select: ['id'], + select: ["id"], where: { status: 1, }, From 7015b1b232602e5168a3eb8bee6d7f1776ae1e74 Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Fri, 15 May 2026 00:39:35 +0800 Subject: [PATCH 05/34] =?UTF-8?q?perf:=20=E5=A4=B4=E5=83=8F=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E7=BC=93=E5=AD=98=E6=97=B6=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/views/certd/mine/user-profile.vue | 2 +- .../certd-server/src/configuration-cache.ts | 6 +++++ .../ui/certd-server/src/configuration.test.ts | 22 +++++++++++++++++++ packages/ui/certd-server/src/configuration.ts | 3 ++- .../controller/basic/file-controller.test.ts | 21 +++++++++++++++++- .../src/controller/basic/file-controller.ts | 19 ++++++++++++---- 6 files changed, 66 insertions(+), 7 deletions(-) create mode 100644 packages/ui/certd-server/src/configuration-cache.ts create mode 100644 packages/ui/certd-server/src/configuration.test.ts diff --git a/packages/ui/certd-client/src/views/certd/mine/user-profile.vue b/packages/ui/certd-client/src/views/certd/mine/user-profile.vue index 11009f97e..08f624945 100644 --- a/packages/ui/certd-client/src/views/certd/mine/user-profile.vue +++ b/packages/ui/certd-client/src/views/certd/mine/user-profile.vue @@ -396,7 +396,7 @@ const userAvatar = computed(() => { return userInfo.value.avatar; } - return `api/basic/file/download?token=${userStore.getToken}&key=${userInfo.value.avatar}`; + return `api/basic/file/download?key=${userInfo.value.avatar}`; }); onMounted(async () => { diff --git a/packages/ui/certd-server/src/configuration-cache.ts b/packages/ui/certd-server/src/configuration-cache.ts new file mode 100644 index 000000000..7b1091800 --- /dev/null +++ b/packages/ui/certd-server/src/configuration-cache.ts @@ -0,0 +1,6 @@ +export function shouldSetDefaultNoCache(path: string, cacheControl?: string) { + if (cacheControl) { + return false; + } + return path === '/' || path === '/index.html' || path.startsWith('/api'); +} diff --git a/packages/ui/certd-server/src/configuration.test.ts b/packages/ui/certd-server/src/configuration.test.ts new file mode 100644 index 000000000..9b1266f81 --- /dev/null +++ b/packages/ui/certd-server/src/configuration.test.ts @@ -0,0 +1,22 @@ +/// +/// + +import assert from "node:assert/strict"; + +import { shouldSetDefaultNoCache } from "./configuration-cache.js"; + +describe("shouldSetDefaultNoCache", () => { + it("sets default no-cache for html and api responses without cache headers", () => { + assert.equal(shouldSetDefaultNoCache("/"), true); + assert.equal(shouldSetDefaultNoCache("/index.html"), true); + assert.equal(shouldSetDefaultNoCache("/api/basic/file/download"), true); + }); + + it("keeps explicit cache headers from file responses", () => { + assert.equal(shouldSetDefaultNoCache("/api/basic/file/download", "public,max-age=259200"), false); + }); + + it("ignores non-html and non-api paths", () => { + assert.equal(shouldSetDefaultNoCache("/static/images/logo.svg"), false); + }); +}); diff --git a/packages/ui/certd-server/src/configuration.ts b/packages/ui/certd-server/src/configuration.ts index a3450eaa3..13ee49993 100644 --- a/packages/ui/certd-server/src/configuration.ts +++ b/packages/ui/certd-server/src/configuration.ts @@ -20,6 +20,7 @@ import * as commercial from '@certd/commercial-core'; import * as upload from '@midwayjs/upload'; import { setLogger } from '@certd/acme-client'; import {HiddenMiddleware} from "./middleware/hidden.js"; +import { shouldSetDefaultNoCache } from './configuration-cache.js'; // import * as swagger from '@midwayjs/swagger'; //@ts-ignore // process.env.UV_THREADPOOL_SIZE = 2 @@ -123,7 +124,7 @@ export class MainConfiguration { this.app.getMiddleware().insertFirst(async (ctx: IMidwayKoaContext, next: NextFunction) => { await next(); - if (ctx.path === '/' || ctx.path === '/index.html' || ctx.path.startsWith("/api")) { + if (shouldSetDefaultNoCache(ctx.path, ctx.response.get('Cache-Control'))) { ctx.response.set('Cache-Control', 'public,max-age=0'); } }); diff --git a/packages/ui/certd-server/src/controller/basic/file-controller.test.ts b/packages/ui/certd-server/src/controller/basic/file-controller.test.ts index a09837292..f968d1c15 100644 --- a/packages/ui/certd-server/src/controller/basic/file-controller.test.ts +++ b/packages/ui/certd-server/src/controller/basic/file-controller.test.ts @@ -3,7 +3,7 @@ import assert from "node:assert/strict"; -import { isImageFile } from "./file-controller.js"; +import { getImageDownloadOptions, isImageFile } from "./file-controller.js"; describe("FileController.isImageFile", () => { it("detects uploaded logo image files", () => { @@ -17,4 +17,23 @@ describe("FileController.isImageFile", () => { assert.equal(isImageFile("data/upload/public/user/cert.pem"), false); assert.equal(isImageFile("data/upload/public/user/logo"), false); }); + + it("builds koa-send options that keep image cache headers at 3 days", () => { + const options = getImageDownloadOptions("data/upload/public/user/logo.png"); + + assert.equal(options?.maxage, 259200000); + + const headers: Record = {}; + options?.setHeaders({ + setHeader(key: string, value: string) { + headers[key] = value; + }, + }); + + assert.equal(headers["Cache-Control"], "public,max-age=259200"); + }); + + it("does not build cache options for non-image files", () => { + assert.equal(getImageDownloadOptions("data/upload/private/user/cert.pem"), undefined); + }); }); diff --git a/packages/ui/certd-server/src/controller/basic/file-controller.ts b/packages/ui/certd-server/src/controller/basic/file-controller.ts index e0340fd79..1fb6bd203 100644 --- a/packages/ui/certd-server/src/controller/basic/file-controller.ts +++ b/packages/ui/certd-server/src/controller/basic/file-controller.ts @@ -12,6 +12,18 @@ export function isImageFile(filePath: string) { return imageExtSet.has(filePath.substring(filePath.lastIndexOf('.')).toLowerCase()); } +export function getImageDownloadOptions(filePath: string) { + if (!isImageFile(filePath)) { + return undefined; + } + return { + maxage: imageCacheSeconds * 1000, + setHeaders(res: any) { + res.setHeader('Cache-Control', `public,max-age=${imageCacheSeconds}`); + }, + }; +} + /** */ @Provide() @@ -47,11 +59,10 @@ export class FileController extends BaseController { userId = this.getUserId(); } const filePath = this.fileService.getFile(key, userId); - if (isImageFile(filePath)) { - this.ctx.response.set('Cache-Control', `public,max-age=${imageCacheSeconds}`); - } else { + const sendOptions = getImageDownloadOptions(filePath); + if (!sendOptions) { this.ctx.response.attachment(filePath); } - await send(this.ctx, filePath); + await send(this.ctx, filePath, sendOptions); } } From 17cf16ca921b30b667b7f1e69322b39cb4d6d1c7 Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Fri, 15 May 2026 00:44:39 +0800 Subject: [PATCH 06/34] build: prepare to build --- packages/core/basic/build.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/basic/build.md b/packages/core/basic/build.md index 629b97a7d..b8466c658 100644 --- a/packages/core/basic/build.md +++ b/packages/core/basic/build.md @@ -1 +1 @@ -14:13 +00:44 From 5801f34b3a40cbbd591805e401613b397bec9775 Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Fri, 15 May 2026 00:48:37 +0800 Subject: [PATCH 07/34] v1.40.0 --- CHANGELOG.md | 19 +++++++++++++ lerna.json | 2 +- packages/core/acme-client/CHANGELOG.md | 4 +++ packages/core/acme-client/package.json | 4 +-- packages/core/basic/CHANGELOG.md | 4 +++ packages/core/basic/package.json | 2 +- packages/core/pipeline/CHANGELOG.md | 4 +++ packages/core/pipeline/package.json | 6 ++-- packages/libs/lib-huawei/CHANGELOG.md | 4 +++ packages/libs/lib-huawei/package.json | 2 +- packages/libs/lib-iframe/CHANGELOG.md | 4 +++ packages/libs/lib-iframe/package.json | 2 +- packages/libs/lib-jdcloud/CHANGELOG.md | 4 +++ packages/libs/lib-jdcloud/package.json | 2 +- packages/libs/lib-k8s/CHANGELOG.md | 4 +++ packages/libs/lib-k8s/package.json | 4 +-- packages/libs/lib-server/CHANGELOG.md | 6 ++++ packages/libs/lib-server/package.json | 12 ++++---- packages/libs/midway-flyway-js/CHANGELOG.md | 4 +++ packages/libs/midway-flyway-js/package.json | 2 +- packages/plugins/plugin-cert/CHANGELOG.md | 4 +++ packages/plugins/plugin-cert/package.json | 10 +++---- packages/plugins/plugin-lib/CHANGELOG.md | 4 +++ packages/plugins/plugin-lib/package.json | 10 +++---- packages/ui/certd-client/CHANGELOG.md | 16 +++++++++++ packages/ui/certd-client/package.json | 6 ++-- packages/ui/certd-server/CHANGELOG.md | 17 +++++++++++ .../metadata/access_synology.yaml | 4 +++ .../metadata/addon_oauth_clogin.yaml | 16 +++++------ packages/ui/certd-server/package.json | 28 +++++++++---------- 30 files changed, 156 insertions(+), 54 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f3fe3de4c..701b07825 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,25 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.40.0](https://github.com/certd/certd/compare/v1.39.16...v1.40.0) (2026-05-14) + +### Bug Fixes + +* 修复第三方登录丢失state时无法在用户信息页面绑定第三方账号的bug ([45dedf5](https://github.com/certd/certd/commit/45dedf5bc779fea852e1f33dda4f31db2765633c)) +* 修复群晖授权没有显示设备id输入框的bug ([2f172b5](https://github.com/certd/certd/commit/2f172b56e9411303ca15138d827bdb9bafdae4d1)) +* 修复自动注册后没有跳转到控制台的bug ([4681ec9](https://github.com/certd/certd/commit/4681ec90088a3eb665427b2ac4047ec5ccefd7b3)) +* 修复clogin登录丢失state问题 ([22f5cfc](https://github.com/certd/certd/commit/22f5cfcfd8462ca74128329eefb3f48b3ee0b7ea)) +* 修复clogin多选类型登录失败的bug ([9f878a3](https://github.com/certd/certd/commit/9f878a353cd49b7b10bb0a95610ad236bc920dd2)) + +### Features + +* 彩虹登录支持选择多种登录方式 ([7aa0c7e](https://github.com/certd/certd/commit/7aa0c7e491fe660abb62e68792ff5474f19bd5b8)) + +### Performance Improvements + +* 第三方登录自动注册的用户支持设置初始化密码 ([a815d02](https://github.com/certd/certd/commit/a815d0245b97efbb948b33d6fc9d49862ce06889)) +* 头像增加缓存时间 ([7015b1b](https://github.com/certd/certd/commit/7015b1b232602e5168a3eb8bee6d7f1776ae1e74)) + ## [1.39.16](https://github.com/certd/certd/compare/v1.39.15...v1.39.16) (2026-05-13) **Note:** Version bump only for package root diff --git a/lerna.json b/lerna.json index 2a104497f..9f512693e 100644 --- a/lerna.json +++ b/lerna.json @@ -9,5 +9,5 @@ } }, "npmClient": "pnpm", - "version": "1.39.16" + "version": "1.40.0" } diff --git a/packages/core/acme-client/CHANGELOG.md b/packages/core/acme-client/CHANGELOG.md index ecbfab08c..7e6d2f1c3 100644 --- a/packages/core/acme-client/CHANGELOG.md +++ b/packages/core/acme-client/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.40.0](https://github.com/publishlab/node-acme-client/compare/v1.39.16...v1.40.0) (2026-05-14) + +**Note:** Version bump only for package @certd/acme-client + ## [1.39.16](https://github.com/publishlab/node-acme-client/compare/v1.39.15...v1.39.16) (2026-05-13) **Note:** Version bump only for package @certd/acme-client diff --git a/packages/core/acme-client/package.json b/packages/core/acme-client/package.json index 07f67bb86..3d7dbe351 100644 --- a/packages/core/acme-client/package.json +++ b/packages/core/acme-client/package.json @@ -3,7 +3,7 @@ "description": "Simple and unopinionated ACME client", "private": false, "author": "nmorsman", - "version": "1.39.16", + "version": "1.40.0", "type": "module", "module": "./dist/index.js", "main": "./dist/index.js", @@ -18,7 +18,7 @@ "types" ], "dependencies": { - "@certd/basic": "^1.39.16", + "@certd/basic": "^1.40.0", "@peculiar/x509": "^1.11.0", "asn1js": "^3.0.5", "axios": "^1.9.0", diff --git a/packages/core/basic/CHANGELOG.md b/packages/core/basic/CHANGELOG.md index f856f1839..3fe69e4fa 100644 --- a/packages/core/basic/CHANGELOG.md +++ b/packages/core/basic/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.40.0](https://github.com/certd/certd/compare/v1.39.16...v1.40.0) (2026-05-14) + +**Note:** Version bump only for package @certd/basic + ## [1.39.16](https://github.com/certd/certd/compare/v1.39.15...v1.39.16) (2026-05-13) **Note:** Version bump only for package @certd/basic diff --git a/packages/core/basic/package.json b/packages/core/basic/package.json index 585ee1cf8..a82887597 100644 --- a/packages/core/basic/package.json +++ b/packages/core/basic/package.json @@ -1,7 +1,7 @@ { "name": "@certd/basic", "private": false, - "version": "1.39.16", + "version": "1.40.0", "type": "module", "main": "./dist/index.js", "module": "./dist/index.js", diff --git a/packages/core/pipeline/CHANGELOG.md b/packages/core/pipeline/CHANGELOG.md index d2fbe0a4d..0b3757194 100644 --- a/packages/core/pipeline/CHANGELOG.md +++ b/packages/core/pipeline/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.40.0](https://github.com/certd/certd/compare/v1.39.16...v1.40.0) (2026-05-14) + +**Note:** Version bump only for package @certd/pipeline + ## [1.39.16](https://github.com/certd/certd/compare/v1.39.15...v1.39.16) (2026-05-13) **Note:** Version bump only for package @certd/pipeline diff --git a/packages/core/pipeline/package.json b/packages/core/pipeline/package.json index 910fff5eb..72a88f124 100644 --- a/packages/core/pipeline/package.json +++ b/packages/core/pipeline/package.json @@ -1,7 +1,7 @@ { "name": "@certd/pipeline", "private": false, - "version": "1.39.16", + "version": "1.40.0", "type": "module", "main": "./dist/index.js", "module": "./dist/index.js", @@ -19,8 +19,8 @@ "compile": "tsc --skipLibCheck --watch" }, "dependencies": { - "@certd/basic": "^1.39.16", - "@certd/plus-core": "^1.39.16", + "@certd/basic": "^1.40.0", + "@certd/plus-core": "^1.40.0", "dayjs": "^1.11.7", "lodash-es": "^4.17.21", "reflect-metadata": "^0.1.13" diff --git a/packages/libs/lib-huawei/CHANGELOG.md b/packages/libs/lib-huawei/CHANGELOG.md index 2787e400a..7367110f3 100644 --- a/packages/libs/lib-huawei/CHANGELOG.md +++ b/packages/libs/lib-huawei/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.40.0](https://github.com/certd/certd/compare/v1.39.16...v1.40.0) (2026-05-14) + +**Note:** Version bump only for package @certd/lib-huawei + ## [1.39.15](https://github.com/certd/certd/compare/v1.39.14...v1.39.15) (2026-05-13) **Note:** Version bump only for package @certd/lib-huawei diff --git a/packages/libs/lib-huawei/package.json b/packages/libs/lib-huawei/package.json index 3a17e48f5..4abf191bf 100644 --- a/packages/libs/lib-huawei/package.json +++ b/packages/libs/lib-huawei/package.json @@ -1,7 +1,7 @@ { "name": "@certd/lib-huawei", "private": false, - "version": "1.39.16", + "version": "1.40.0", "main": "./dist/bundle.js", "module": "./dist/bundle.js", "types": "./dist/d/index.d.ts", diff --git a/packages/libs/lib-iframe/CHANGELOG.md b/packages/libs/lib-iframe/CHANGELOG.md index 4ae4cb0a0..42c2b257f 100644 --- a/packages/libs/lib-iframe/CHANGELOG.md +++ b/packages/libs/lib-iframe/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.40.0](https://github.com/certd/certd/compare/v1.39.16...v1.40.0) (2026-05-14) + +**Note:** Version bump only for package @certd/lib-iframe + ## [1.39.15](https://github.com/certd/certd/compare/v1.39.14...v1.39.15) (2026-05-13) **Note:** Version bump only for package @certd/lib-iframe diff --git a/packages/libs/lib-iframe/package.json b/packages/libs/lib-iframe/package.json index 808b94725..d1729cd5d 100644 --- a/packages/libs/lib-iframe/package.json +++ b/packages/libs/lib-iframe/package.json @@ -1,7 +1,7 @@ { "name": "@certd/lib-iframe", "private": false, - "version": "1.39.16", + "version": "1.40.0", "type": "module", "main": "./dist/index.js", "module": "./dist/index.js", diff --git a/packages/libs/lib-jdcloud/CHANGELOG.md b/packages/libs/lib-jdcloud/CHANGELOG.md index 131bd36c8..299b8cd28 100644 --- a/packages/libs/lib-jdcloud/CHANGELOG.md +++ b/packages/libs/lib-jdcloud/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.40.0](https://github.com/certd/certd/compare/v1.39.16...v1.40.0) (2026-05-14) + +**Note:** Version bump only for package @certd/jdcloud + ## [1.39.15](https://github.com/certd/certd/compare/v1.39.14...v1.39.15) (2026-05-13) **Note:** Version bump only for package @certd/jdcloud diff --git a/packages/libs/lib-jdcloud/package.json b/packages/libs/lib-jdcloud/package.json index d047f0979..01d2144a6 100644 --- a/packages/libs/lib-jdcloud/package.json +++ b/packages/libs/lib-jdcloud/package.json @@ -1,6 +1,6 @@ { "name": "@certd/jdcloud", - "version": "1.39.16", + "version": "1.40.0", "description": "jdcloud openApi sdk", "main": "./dist/bundle.js", "module": "./dist/bundle.js", diff --git a/packages/libs/lib-k8s/CHANGELOG.md b/packages/libs/lib-k8s/CHANGELOG.md index 096831196..efba813fd 100644 --- a/packages/libs/lib-k8s/CHANGELOG.md +++ b/packages/libs/lib-k8s/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.40.0](https://github.com/certd/certd/compare/v1.39.16...v1.40.0) (2026-05-14) + +**Note:** Version bump only for package @certd/lib-k8s + ## [1.39.16](https://github.com/certd/certd/compare/v1.39.15...v1.39.16) (2026-05-13) **Note:** Version bump only for package @certd/lib-k8s diff --git a/packages/libs/lib-k8s/package.json b/packages/libs/lib-k8s/package.json index 2b0f5f2d1..091d96cf9 100644 --- a/packages/libs/lib-k8s/package.json +++ b/packages/libs/lib-k8s/package.json @@ -1,7 +1,7 @@ { "name": "@certd/lib-k8s", "private": false, - "version": "1.39.16", + "version": "1.40.0", "type": "module", "main": "./dist/index.js", "module": "./dist/index.js", @@ -19,7 +19,7 @@ "compile": "tsc --skipLibCheck --watch" }, "dependencies": { - "@certd/basic": "^1.39.16", + "@certd/basic": "^1.40.0", "@kubernetes/client-node": "0.21.0" }, "devDependencies": { diff --git a/packages/libs/lib-server/CHANGELOG.md b/packages/libs/lib-server/CHANGELOG.md index 9971d6c17..c455d463b 100644 --- a/packages/libs/lib-server/CHANGELOG.md +++ b/packages/libs/lib-server/CHANGELOG.md @@ -3,6 +3,12 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.40.0](https://github.com/certd/certd/compare/v1.39.16...v1.40.0) (2026-05-14) + +### Features + +* 彩虹登录支持选择多种登录方式 ([7aa0c7e](https://github.com/certd/certd/commit/7aa0c7e491fe660abb62e68792ff5474f19bd5b8)) + ## [1.39.16](https://github.com/certd/certd/compare/v1.39.15...v1.39.16) (2026-05-13) **Note:** Version bump only for package @certd/lib-server diff --git a/packages/libs/lib-server/package.json b/packages/libs/lib-server/package.json index 04fd5d532..c862eaf36 100644 --- a/packages/libs/lib-server/package.json +++ b/packages/libs/lib-server/package.json @@ -1,6 +1,6 @@ { "name": "@certd/lib-server", - "version": "1.39.16", + "version": "1.40.0", "description": "midway with flyway, sql upgrade way ", "private": false, "type": "module", @@ -29,11 +29,11 @@ ], "license": "AGPL", "dependencies": { - "@certd/acme-client": "^1.39.16", - "@certd/basic": "^1.39.16", - "@certd/pipeline": "^1.39.16", - "@certd/plugin-lib": "^1.39.16", - "@certd/plus-core": "^1.39.16", + "@certd/acme-client": "^1.40.0", + "@certd/basic": "^1.40.0", + "@certd/pipeline": "^1.40.0", + "@certd/plugin-lib": "^1.40.0", + "@certd/plus-core": "^1.40.0", "@midwayjs/cache": "3.14.0", "@midwayjs/core": "3.20.11", "@midwayjs/i18n": "3.20.13", diff --git a/packages/libs/midway-flyway-js/CHANGELOG.md b/packages/libs/midway-flyway-js/CHANGELOG.md index d88d7d2ac..d324d9fc6 100644 --- a/packages/libs/midway-flyway-js/CHANGELOG.md +++ b/packages/libs/midway-flyway-js/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.40.0](https://github.com/certd/certd/compare/v1.39.16...v1.40.0) (2026-05-14) + +**Note:** Version bump only for package @certd/midway-flyway-js + ## [1.39.15](https://github.com/certd/certd/compare/v1.39.14...v1.39.15) (2026-05-13) **Note:** Version bump only for package @certd/midway-flyway-js diff --git a/packages/libs/midway-flyway-js/package.json b/packages/libs/midway-flyway-js/package.json index 3a49d67ad..032b781bc 100644 --- a/packages/libs/midway-flyway-js/package.json +++ b/packages/libs/midway-flyway-js/package.json @@ -1,6 +1,6 @@ { "name": "@certd/midway-flyway-js", - "version": "1.39.16", + "version": "1.40.0", "description": "midway with flyway, sql upgrade way ", "private": false, "type": "module", diff --git a/packages/plugins/plugin-cert/CHANGELOG.md b/packages/plugins/plugin-cert/CHANGELOG.md index 3854a8d88..743d50d8e 100644 --- a/packages/plugins/plugin-cert/CHANGELOG.md +++ b/packages/plugins/plugin-cert/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.40.0](https://github.com/certd/certd/compare/v1.39.16...v1.40.0) (2026-05-14) + +**Note:** Version bump only for package @certd/plugin-cert + ## [1.39.16](https://github.com/certd/certd/compare/v1.39.15...v1.39.16) (2026-05-13) **Note:** Version bump only for package @certd/plugin-cert diff --git a/packages/plugins/plugin-cert/package.json b/packages/plugins/plugin-cert/package.json index b36e0ba7d..9123b388e 100644 --- a/packages/plugins/plugin-cert/package.json +++ b/packages/plugins/plugin-cert/package.json @@ -1,7 +1,7 @@ { "name": "@certd/plugin-cert", "private": false, - "version": "1.39.16", + "version": "1.40.0", "type": "module", "main": "./dist/index.js", "types": "./dist/index.d.ts", @@ -18,10 +18,10 @@ "compile": "tsc --skipLibCheck --watch" }, "dependencies": { - "@certd/acme-client": "^1.39.16", - "@certd/basic": "^1.39.16", - "@certd/pipeline": "^1.39.16", - "@certd/plugin-lib": "^1.39.16", + "@certd/acme-client": "^1.40.0", + "@certd/basic": "^1.40.0", + "@certd/pipeline": "^1.40.0", + "@certd/plugin-lib": "^1.40.0", "psl": "^1.9.0", "punycode.js": "^2.3.1" }, diff --git a/packages/plugins/plugin-lib/CHANGELOG.md b/packages/plugins/plugin-lib/CHANGELOG.md index 84dc54f42..da54554d9 100644 --- a/packages/plugins/plugin-lib/CHANGELOG.md +++ b/packages/plugins/plugin-lib/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.40.0](https://github.com/certd/certd/compare/v1.39.16...v1.40.0) (2026-05-14) + +**Note:** Version bump only for package @certd/plugin-lib + ## [1.39.16](https://github.com/certd/certd/compare/v1.39.15...v1.39.16) (2026-05-13) **Note:** Version bump only for package @certd/plugin-lib diff --git a/packages/plugins/plugin-lib/package.json b/packages/plugins/plugin-lib/package.json index 867cf2467..0abc42a70 100644 --- a/packages/plugins/plugin-lib/package.json +++ b/packages/plugins/plugin-lib/package.json @@ -1,7 +1,7 @@ { "name": "@certd/plugin-lib", "private": false, - "version": "1.39.16", + "version": "1.40.0", "type": "module", "main": "./dist/index.js", "types": "./dist/index.d.ts", @@ -23,10 +23,10 @@ "@alicloud/pop-core": "^1.7.10", "@alicloud/tea-util": "^1.4.11", "@aws-sdk/client-s3": "^3.964.0", - "@certd/acme-client": "^1.39.16", - "@certd/basic": "^1.39.16", - "@certd/pipeline": "^1.39.16", - "@certd/plus-core": "^1.39.16", + "@certd/acme-client": "^1.40.0", + "@certd/basic": "^1.40.0", + "@certd/pipeline": "^1.40.0", + "@certd/plus-core": "^1.40.0", "@kubernetes/client-node": "0.21.0", "ali-oss": "^6.22.0", "basic-ftp": "^5.0.5", diff --git a/packages/ui/certd-client/CHANGELOG.md b/packages/ui/certd-client/CHANGELOG.md index 1df7467f1..93da33ce4 100644 --- a/packages/ui/certd-client/CHANGELOG.md +++ b/packages/ui/certd-client/CHANGELOG.md @@ -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.40.0](https://github.com/certd/certd/compare/v1.39.16...v1.40.0) (2026-05-14) + +### Bug Fixes + +* 修复第三方登录丢失state时无法在用户信息页面绑定第三方账号的bug ([45dedf5](https://github.com/certd/certd/commit/45dedf5bc779fea852e1f33dda4f31db2765633c)) +* 修复群晖授权没有显示设备id输入框的bug ([2f172b5](https://github.com/certd/certd/commit/2f172b56e9411303ca15138d827bdb9bafdae4d1)) +* 修复自动注册后没有跳转到控制台的bug ([4681ec9](https://github.com/certd/certd/commit/4681ec90088a3eb665427b2ac4047ec5ccefd7b3)) + +### Features + +* 彩虹登录支持选择多种登录方式 ([7aa0c7e](https://github.com/certd/certd/commit/7aa0c7e491fe660abb62e68792ff5474f19bd5b8)) + +### Performance Improvements + +* 头像增加缓存时间 ([7015b1b](https://github.com/certd/certd/commit/7015b1b232602e5168a3eb8bee6d7f1776ae1e74)) + ## [1.39.16](https://github.com/certd/certd/compare/v1.39.15...v1.39.16) (2026-05-13) **Note:** Version bump only for package @certd/ui-client diff --git a/packages/ui/certd-client/package.json b/packages/ui/certd-client/package.json index 8876e98be..6990cdba6 100644 --- a/packages/ui/certd-client/package.json +++ b/packages/ui/certd-client/package.json @@ -1,6 +1,6 @@ { "name": "@certd/ui-client", - "version": "1.39.16", + "version": "1.40.0", "private": true, "scripts": { "dev": "vite --open", @@ -106,8 +106,8 @@ "zod-defaults": "^0.1.3" }, "devDependencies": { - "@certd/lib-iframe": "^1.39.16", - "@certd/pipeline": "^1.39.16", + "@certd/lib-iframe": "^1.40.0", + "@certd/pipeline": "^1.40.0", "@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-node-resolve": "^15.2.3", "@types/chai": "^4.3.12", diff --git a/packages/ui/certd-server/CHANGELOG.md b/packages/ui/certd-server/CHANGELOG.md index 24a715a50..633a00424 100644 --- a/packages/ui/certd-server/CHANGELOG.md +++ b/packages/ui/certd-server/CHANGELOG.md @@ -3,6 +3,23 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.40.0](https://github.com/certd/certd/compare/v1.39.16...v1.40.0) (2026-05-14) + +### Bug Fixes + +* 修复群晖授权没有显示设备id输入框的bug ([2f172b5](https://github.com/certd/certd/commit/2f172b56e9411303ca15138d827bdb9bafdae4d1)) +* 修复clogin登录丢失state问题 ([22f5cfc](https://github.com/certd/certd/commit/22f5cfcfd8462ca74128329eefb3f48b3ee0b7ea)) +* 修复clogin多选类型登录失败的bug ([9f878a3](https://github.com/certd/certd/commit/9f878a353cd49b7b10bb0a95610ad236bc920dd2)) + +### Features + +* 彩虹登录支持选择多种登录方式 ([7aa0c7e](https://github.com/certd/certd/commit/7aa0c7e491fe660abb62e68792ff5474f19bd5b8)) + +### Performance Improvements + +* 第三方登录自动注册的用户支持设置初始化密码 ([a815d02](https://github.com/certd/certd/commit/a815d0245b97efbb948b33d6fc9d49862ce06889)) +* 头像增加缓存时间 ([7015b1b](https://github.com/certd/certd/commit/7015b1b232602e5168a3eb8bee6d7f1776ae1e74)) + ## [1.39.16](https://github.com/certd/certd/compare/v1.39.15...v1.39.16) (2026-05-13) **Note:** Version bump only for package @certd/ui-server diff --git a/packages/ui/certd-server/metadata/access_synology.yaml b/packages/ui/certd-server/metadata/access_synology.yaml index e6dd4cc99..aebff3861 100644 --- a/packages/ui/certd-server/metadata/access_synology.yaml +++ b/packages/ui/certd-server/metadata/access_synology.yaml @@ -39,6 +39,8 @@ input: component: name: a-switch vModel: checked + col: + span: 24 helper: 是否启用了双重认证 required: true deviceId: @@ -48,6 +50,8 @@ input: name: synology-device-id-getter type: access typeName: synology + col: + span: 24 mergeScript: |2- return { diff --git a/packages/ui/certd-server/metadata/addon_oauth_clogin.yaml b/packages/ui/certd-server/metadata/addon_oauth_clogin.yaml index ed3fc9d6c..c79e9fe2e 100644 --- a/packages/ui/certd-server/metadata/addon_oauth_clogin.yaml +++ b/packages/ui/certd-server/metadata/addon_oauth_clogin.yaml @@ -21,28 +21,28 @@ input: options: - label: QQ value: qq - icon: logos:tencent-qq + icon: cib:tencent-qq:#007AFF - label: 微信 value: wx - icon: logos:wechat-icon + icon: simple-icons:wechat:#34C759 - label: 支付宝 value: alipay - icon: logos:alipay + icon: simple-icons:alipay:#0099ff - label: 微博 value: sina - icon: logos:sina-weibo + icon: uiw:weibo:#FF3B30 - label: 百度 value: baidu - icon: logos:baidu + icon: simple-icons:baidu:#007AFF - label: 华为 value: huawei icon: simple-icons:huawei:#ff0000 - label: 小米 value: xiaomi - icon: logos:xiaomi-icon + icon: simple-icons:xiaomi:#FF9500 - label: 谷歌 value: google - icon: logos:google-icon + icon: flat-color-icons:google - label: 微软 value: microsoft icon: logos:microsoft-icon @@ -54,7 +54,7 @@ input: icon: logos:twitter - label: 钉钉 value: dingtalk - icon: logos:dingtalk + icon: ant-design:dingding-outlined:#007AFF - label: Gitee value: gitee icon: simple-icons:gitee:#c71d23 diff --git a/packages/ui/certd-server/package.json b/packages/ui/certd-server/package.json index c044474b1..f3cfe3f90 100644 --- a/packages/ui/certd-server/package.json +++ b/packages/ui/certd-server/package.json @@ -1,6 +1,6 @@ { "name": "@certd/ui-server", - "version": "1.39.16", + "version": "1.40.0", "description": "fast-server base midway", "private": true, "type": "module", @@ -53,20 +53,20 @@ "@aws-sdk/client-sts": "^3.990.0", "@azure/arm-dns": "^5.1.0", "@azure/identity": "^4.13.1", - "@certd/acme-client": "^1.39.16", - "@certd/basic": "^1.39.16", - "@certd/commercial-core": "^1.39.16", + "@certd/acme-client": "^1.40.0", + "@certd/basic": "^1.40.0", + "@certd/commercial-core": "^1.40.0", "@certd/cv4pve-api-javascript": "^8.4.2", - "@certd/jdcloud": "^1.39.16", - "@certd/lib-huawei": "^1.39.16", - "@certd/lib-k8s": "^1.39.16", - "@certd/lib-server": "^1.39.16", - "@certd/midway-flyway-js": "^1.39.16", - "@certd/pipeline": "^1.39.16", - "@certd/plugin-cert": "^1.39.16", - "@certd/plugin-lib": "^1.39.16", - "@certd/plugin-plus": "^1.39.16", - "@certd/plus-core": "^1.39.16", + "@certd/jdcloud": "^1.40.0", + "@certd/lib-huawei": "^1.40.0", + "@certd/lib-k8s": "^1.40.0", + "@certd/lib-server": "^1.40.0", + "@certd/midway-flyway-js": "^1.40.0", + "@certd/pipeline": "^1.40.0", + "@certd/plugin-cert": "^1.40.0", + "@certd/plugin-lib": "^1.40.0", + "@certd/plugin-plus": "^1.40.0", + "@certd/plus-core": "^1.40.0", "@google-cloud/dns": "^5.3.1", "@google-cloud/publicca": "^1.3.0", "@huaweicloud/huaweicloud-sdk-cdn": "^3.1.185", From 58fc9a551ceaefd3e0f2d7bbbaeab2bda63f0511 Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Fri, 15 May 2026 00:49:57 +0800 Subject: [PATCH 08/34] build: trigger build image --- trigger/build.trigger | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trigger/build.trigger b/trigger/build.trigger index 66d5fdc1a..98f9e3b66 100644 --- a/trigger/build.trigger +++ b/trigger/build.trigger @@ -1 +1 @@ -14:22 +00:49 From b849d34be51ecaff38323eb5bb08c1b401b9c8a0 Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Fri, 15 May 2026 00:50:09 +0800 Subject: [PATCH 09/34] build: publish --- docs/guide/changelogs/CHANGELOG.md | 19 +++++++++++++++++++ packages/core/acme-client/package.json | 2 +- packages/core/basic/package.json | 2 +- packages/core/pipeline/package.json | 2 +- packages/libs/lib-huawei/package.json | 2 +- packages/libs/lib-iframe/package.json | 2 +- packages/libs/lib-jdcloud/package.json | 2 +- packages/libs/lib-k8s/package.json | 2 +- packages/libs/lib-server/package.json | 2 +- packages/libs/midway-flyway-js/package.json | 2 +- packages/plugins/plugin-cert/package.json | 2 +- packages/plugins/plugin-lib/package.json | 2 +- 12 files changed, 30 insertions(+), 11 deletions(-) diff --git a/docs/guide/changelogs/CHANGELOG.md b/docs/guide/changelogs/CHANGELOG.md index f3fe3de4c..701b07825 100644 --- a/docs/guide/changelogs/CHANGELOG.md +++ b/docs/guide/changelogs/CHANGELOG.md @@ -3,6 +3,25 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.40.0](https://github.com/certd/certd/compare/v1.39.16...v1.40.0) (2026-05-14) + +### Bug Fixes + +* 修复第三方登录丢失state时无法在用户信息页面绑定第三方账号的bug ([45dedf5](https://github.com/certd/certd/commit/45dedf5bc779fea852e1f33dda4f31db2765633c)) +* 修复群晖授权没有显示设备id输入框的bug ([2f172b5](https://github.com/certd/certd/commit/2f172b56e9411303ca15138d827bdb9bafdae4d1)) +* 修复自动注册后没有跳转到控制台的bug ([4681ec9](https://github.com/certd/certd/commit/4681ec90088a3eb665427b2ac4047ec5ccefd7b3)) +* 修复clogin登录丢失state问题 ([22f5cfc](https://github.com/certd/certd/commit/22f5cfcfd8462ca74128329eefb3f48b3ee0b7ea)) +* 修复clogin多选类型登录失败的bug ([9f878a3](https://github.com/certd/certd/commit/9f878a353cd49b7b10bb0a95610ad236bc920dd2)) + +### Features + +* 彩虹登录支持选择多种登录方式 ([7aa0c7e](https://github.com/certd/certd/commit/7aa0c7e491fe660abb62e68792ff5474f19bd5b8)) + +### Performance Improvements + +* 第三方登录自动注册的用户支持设置初始化密码 ([a815d02](https://github.com/certd/certd/commit/a815d0245b97efbb948b33d6fc9d49862ce06889)) +* 头像增加缓存时间 ([7015b1b](https://github.com/certd/certd/commit/7015b1b232602e5168a3eb8bee6d7f1776ae1e74)) + ## [1.39.16](https://github.com/certd/certd/compare/v1.39.15...v1.39.16) (2026-05-13) **Note:** Version bump only for package root diff --git a/packages/core/acme-client/package.json b/packages/core/acme-client/package.json index 3d7dbe351..6ef15453b 100644 --- a/packages/core/acme-client/package.json +++ b/packages/core/acme-client/package.json @@ -76,5 +76,5 @@ "bugs": { "url": "https://github.com/publishlab/node-acme-client/issues" }, - "gitHead": "1c6dc169ac04fd09ef94404a912a15cbb17e1452" + "gitHead": "5801f34b3a40cbbd591805e401613b397bec9775" } diff --git a/packages/core/basic/package.json b/packages/core/basic/package.json index a82887597..0bdfddf53 100644 --- a/packages/core/basic/package.json +++ b/packages/core/basic/package.json @@ -52,5 +52,5 @@ "tslib": "^2.8.1", "typescript": "^5.4.2" }, - "gitHead": "1c6dc169ac04fd09ef94404a912a15cbb17e1452" + "gitHead": "5801f34b3a40cbbd591805e401613b397bec9775" } diff --git a/packages/core/pipeline/package.json b/packages/core/pipeline/package.json index 72a88f124..681951acc 100644 --- a/packages/core/pipeline/package.json +++ b/packages/core/pipeline/package.json @@ -49,5 +49,5 @@ "tslib": "^2.8.1", "typescript": "^5.4.2" }, - "gitHead": "1c6dc169ac04fd09ef94404a912a15cbb17e1452" + "gitHead": "5801f34b3a40cbbd591805e401613b397bec9775" } diff --git a/packages/libs/lib-huawei/package.json b/packages/libs/lib-huawei/package.json index 4abf191bf..44de2fa41 100644 --- a/packages/libs/lib-huawei/package.json +++ b/packages/libs/lib-huawei/package.json @@ -27,5 +27,5 @@ "prettier": "^2.8.8", "tslib": "^2.8.1" }, - "gitHead": "bae5a04dcc0a679c290a9805c3ac4a6020eb6ec0" + "gitHead": "5801f34b3a40cbbd591805e401613b397bec9775" } diff --git a/packages/libs/lib-iframe/package.json b/packages/libs/lib-iframe/package.json index d1729cd5d..cc67a3c95 100644 --- a/packages/libs/lib-iframe/package.json +++ b/packages/libs/lib-iframe/package.json @@ -34,5 +34,5 @@ "tslib": "^2.8.1", "typescript": "^5.4.2" }, - "gitHead": "bae5a04dcc0a679c290a9805c3ac4a6020eb6ec0" + "gitHead": "5801f34b3a40cbbd591805e401613b397bec9775" } diff --git a/packages/libs/lib-jdcloud/package.json b/packages/libs/lib-jdcloud/package.json index 01d2144a6..a41480146 100644 --- a/packages/libs/lib-jdcloud/package.json +++ b/packages/libs/lib-jdcloud/package.json @@ -58,5 +58,5 @@ "fetch" ] }, - "gitHead": "bae5a04dcc0a679c290a9805c3ac4a6020eb6ec0" + "gitHead": "5801f34b3a40cbbd591805e401613b397bec9775" } diff --git a/packages/libs/lib-k8s/package.json b/packages/libs/lib-k8s/package.json index 091d96cf9..b67753a68 100644 --- a/packages/libs/lib-k8s/package.json +++ b/packages/libs/lib-k8s/package.json @@ -36,5 +36,5 @@ "tslib": "^2.8.1", "typescript": "^5.4.2" }, - "gitHead": "1c6dc169ac04fd09ef94404a912a15cbb17e1452" + "gitHead": "5801f34b3a40cbbd591805e401613b397bec9775" } diff --git a/packages/libs/lib-server/package.json b/packages/libs/lib-server/package.json index c862eaf36..04a4bfc6f 100644 --- a/packages/libs/lib-server/package.json +++ b/packages/libs/lib-server/package.json @@ -69,5 +69,5 @@ "typeorm": "^0.3.11", "typescript": "^5.4.2" }, - "gitHead": "1c6dc169ac04fd09ef94404a912a15cbb17e1452" + "gitHead": "5801f34b3a40cbbd591805e401613b397bec9775" } diff --git a/packages/libs/midway-flyway-js/package.json b/packages/libs/midway-flyway-js/package.json index 032b781bc..87b000fab 100644 --- a/packages/libs/midway-flyway-js/package.json +++ b/packages/libs/midway-flyway-js/package.json @@ -49,5 +49,5 @@ "typeorm": "^0.3.11", "typescript": "^5.4.2" }, - "gitHead": "bae5a04dcc0a679c290a9805c3ac4a6020eb6ec0" + "gitHead": "5801f34b3a40cbbd591805e401613b397bec9775" } diff --git a/packages/plugins/plugin-cert/package.json b/packages/plugins/plugin-cert/package.json index 9123b388e..2f2b5a4bb 100644 --- a/packages/plugins/plugin-cert/package.json +++ b/packages/plugins/plugin-cert/package.json @@ -41,5 +41,5 @@ "tslib": "^2.8.1", "typescript": "^5.4.2" }, - "gitHead": "1c6dc169ac04fd09ef94404a912a15cbb17e1452" + "gitHead": "5801f34b3a40cbbd591805e401613b397bec9775" } diff --git a/packages/plugins/plugin-lib/package.json b/packages/plugins/plugin-lib/package.json index 0abc42a70..d90e741b0 100644 --- a/packages/plugins/plugin-lib/package.json +++ b/packages/plugins/plugin-lib/package.json @@ -61,5 +61,5 @@ "tslib": "^2.8.1", "typescript": "^5.4.2" }, - "gitHead": "1c6dc169ac04fd09ef94404a912a15cbb17e1452" + "gitHead": "5801f34b3a40cbbd591805e401613b397bec9775" } From d131ea37902725ef4dc921bd56966d55ca0be717 Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Fri, 15 May 2026 01:14:12 +0800 Subject: [PATCH 10/34] build: release --- trigger/release.trigger | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trigger/release.trigger b/trigger/release.trigger index f852c9ed3..1d3b516af 100644 --- a/trigger/release.trigger +++ b/trigger/release.trigger @@ -1 +1 @@ -17:29 +01:14 From 59b9ffadd05faf3982151c48f8d83cbd97419865 Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Fri, 15 May 2026 23:18:51 +0800 Subject: [PATCH 11/34] =?UTF-8?q?fix:=20=E5=9B=BA=E5=8C=96=E5=8D=8E?= =?UTF-8?q?=E4=B8=BA=E4=BA=91sdk=E7=89=88=E6=9C=AC=EF=BC=8C=E9=81=BF?= =?UTF-8?q?=E5=85=8D=E5=8D=8E=E4=B8=BA=E4=BA=91=E8=B0=83=E7=94=A8=E6=8A=A5?= =?UTF-8?q?=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/ui/certd-server/package.json | 8 +-- pnpm-lock.yaml | 82 +++++++++++++-------------- 2 files changed, 45 insertions(+), 45 deletions(-) diff --git a/packages/ui/certd-server/package.json b/packages/ui/certd-server/package.json index f3cfe3f90..e505eea4f 100644 --- a/packages/ui/certd-server/package.json +++ b/packages/ui/certd-server/package.json @@ -69,10 +69,10 @@ "@certd/plus-core": "^1.40.0", "@google-cloud/dns": "^5.3.1", "@google-cloud/publicca": "^1.3.0", - "@huaweicloud/huaweicloud-sdk-cdn": "^3.1.185", - "@huaweicloud/huaweicloud-sdk-core": "^3.1.185", - "@huaweicloud/huaweicloud-sdk-elb": "^3.1.185", - "@huaweicloud/huaweicloud-sdk-iam": "^3.1.185", + "@huaweicloud/huaweicloud-sdk-cdn": "3.1.185", + "@huaweicloud/huaweicloud-sdk-core": "3.1.185", + "@huaweicloud/huaweicloud-sdk-elb": "3.1.185", + "@huaweicloud/huaweicloud-sdk-iam": "3.1.185", "@koa/cors": "^5.0.0", "@midwayjs/bootstrap": "3.20.11", "@midwayjs/cache": "3.14.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d481396cf..8c97bfcb2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -52,7 +52,7 @@ importers: packages/core/acme-client: dependencies: '@certd/basic': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../basic '@peculiar/x509': specifier: ^1.11.0 @@ -234,10 +234,10 @@ importers: packages/core/pipeline: dependencies: '@certd/basic': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../basic '@certd/plus-core': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../../pro/plus-core dayjs: specifier: ^1.11.7 @@ -457,7 +457,7 @@ importers: packages/libs/lib-k8s: dependencies: '@certd/basic': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../../core/basic '@kubernetes/client-node': specifier: 0.21.0 @@ -503,19 +503,19 @@ importers: packages/libs/lib-server: dependencies: '@certd/acme-client': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../../core/acme-client '@certd/basic': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../../core/basic '@certd/pipeline': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../../core/pipeline '@certd/plugin-lib': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../../plugins/plugin-lib '@certd/plus-core': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../../pro/plus-core '@midwayjs/cache': specifier: 3.14.0 @@ -679,16 +679,16 @@ importers: packages/plugins/plugin-cert: dependencies: '@certd/acme-client': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../../core/acme-client '@certd/basic': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../../core/basic '@certd/pipeline': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../../core/pipeline '@certd/plugin-lib': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../plugin-lib psl: specifier: ^1.9.0 @@ -758,16 +758,16 @@ importers: specifier: ^3.964.0 version: 3.964.0(aws-crt@1.26.2) '@certd/acme-client': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../../core/acme-client '@certd/basic': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../../core/basic '@certd/pipeline': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../../core/pipeline '@certd/plus-core': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../../pro/plus-core '@kubernetes/client-node': specifier: 0.21.0 @@ -867,16 +867,16 @@ importers: packages/pro/commercial-core: dependencies: '@certd/basic': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../../core/basic '@certd/lib-server': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../../libs/lib-server '@certd/pipeline': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../../core/pipeline '@certd/plus-core': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../plus-core '@midwayjs/core': specifier: 3.20.11 @@ -967,16 +967,16 @@ importers: packages/pro/plugin-plus: dependencies: '@certd/basic': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../../core/basic '@certd/pipeline': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../../core/pipeline '@certd/plugin-lib': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../../plugins/plugin-lib '@certd/plus-core': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../plus-core crypto-js: specifier: ^4.2.0 @@ -1061,7 +1061,7 @@ importers: packages/pro/plus-core: dependencies: '@certd/basic': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../../core/basic dayjs: specifier: ^1.11.7 @@ -1363,10 +1363,10 @@ importers: version: 0.1.3(zod@3.24.4) devDependencies: '@certd/lib-iframe': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../../libs/lib-iframe '@certd/pipeline': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../../core/pipeline '@rollup/plugin-commonjs': specifier: ^25.0.7 @@ -1573,46 +1573,46 @@ importers: specifier: ^4.13.1 version: 4.13.1 '@certd/acme-client': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../../core/acme-client '@certd/basic': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../../core/basic '@certd/commercial-core': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../../pro/commercial-core '@certd/cv4pve-api-javascript': specifier: ^8.4.2 version: 8.4.2 '@certd/jdcloud': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../../libs/lib-jdcloud '@certd/lib-huawei': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../../libs/lib-huawei '@certd/lib-k8s': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../../libs/lib-k8s '@certd/lib-server': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../../libs/lib-server '@certd/midway-flyway-js': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../../libs/midway-flyway-js '@certd/pipeline': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../../core/pipeline '@certd/plugin-cert': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../../plugins/plugin-cert '@certd/plugin-lib': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../../plugins/plugin-lib '@certd/plugin-plus': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../../pro/plugin-plus '@certd/plus-core': - specifier: ^1.39.16 + specifier: ^1.40.0 version: link:../../pro/plus-core '@google-cloud/dns': specifier: ^5.3.1 From c63745d1ba30904428ba6b13ab0785298baa5cae Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Sat, 16 May 2026 02:18:06 +0800 Subject: [PATCH 12/34] =?UTF-8?q?perf:=20=E5=95=86=E4=B8=9A=E7=89=88?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E9=99=90=E5=88=B6=E6=B3=9B=E5=9F=9F=E5=90=8D?= =?UTF-8?q?=E6=95=B0=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/locales/langs/en-US/certd/suite.ts | 11 +- .../src/locales/langs/zh-CN/certd/suite.ts | 11 +- .../src/views/certd/suite/mine/api.ts | 1 + .../src/views/certd/suite/mine/crud.tsx | 24 +- .../src/views/certd/suite/order-modal.vue | 5 +- .../src/views/certd/suite/product-info.vue | 8 +- .../framework/home/dashboard/suite-card.vue | 6 +- .../src/views/sys/suite/product/crud.tsx | 24 +- .../src/views/sys/suite/setting/index.vue | 1 + .../src/views/sys/suite/user-suite/crud.tsx | 23 ++ .../v10044__cert_wildcard_domain_count.sql | 1 + .../src/modules/auto/auto-a-register.ts | 2 +- .../src/modules/auto/auto-fix.test.ts | 301 ------------------ .../src/modules/auto/fix/auto-fix.test.ts | 33 ++ .../src/modules/auto/fix/auto-fix.ts | 28 ++ ...ert-info-wildcard-domain-count-fix.test.ts | 37 +++ .../cert-info-wildcard-domain-count-fix.ts | 45 +++ .../google-common-eab-account-key-fix.test.ts | 169 ++++++++++ .../google-common-eab-account-key-fix.ts} | 76 +---- .../fix/oauth-subtype-bound-type-fix.test.ts | 94 ++++++ .../auto/fix/oauth-subtype-bound-type-fix.ts | 68 ++++ ...-content-wildcard-domain-count-fix.test.ts | 72 +++++ ...suite-content-wildcard-domain-count-fix.ts | 54 ++++ .../src/modules/monitor/entity/cert-info.ts | 3 + .../monitor/service/cert-info-service.test.ts | 29 ++ .../monitor/service/cert-info-service.ts | 19 ++ .../pipeline/service/pipeline-service.ts | 32 +- .../service/pipeline-suite-limit.test.ts | 9 + .../pipeline/service/pipeline-suite-limit.ts | 3 + .../modules/suite/service/my-count-service.ts | 2 + pnpm-lock.yaml | 8 +- 31 files changed, 804 insertions(+), 395 deletions(-) create mode 100644 packages/ui/certd-server/db/migration/v10044__cert_wildcard_domain_count.sql delete mode 100644 packages/ui/certd-server/src/modules/auto/auto-fix.test.ts create mode 100644 packages/ui/certd-server/src/modules/auto/fix/auto-fix.test.ts create mode 100644 packages/ui/certd-server/src/modules/auto/fix/auto-fix.ts create mode 100644 packages/ui/certd-server/src/modules/auto/fix/cert-info-wildcard-domain-count-fix.test.ts create mode 100644 packages/ui/certd-server/src/modules/auto/fix/cert-info-wildcard-domain-count-fix.ts create mode 100644 packages/ui/certd-server/src/modules/auto/fix/google-common-eab-account-key-fix.test.ts rename packages/ui/certd-server/src/modules/auto/{auto-fix.ts => fix/google-common-eab-account-key-fix.ts} (51%) create mode 100644 packages/ui/certd-server/src/modules/auto/fix/oauth-subtype-bound-type-fix.test.ts create mode 100644 packages/ui/certd-server/src/modules/auto/fix/oauth-subtype-bound-type-fix.ts create mode 100644 packages/ui/certd-server/src/modules/auto/fix/suite-content-wildcard-domain-count-fix.test.ts create mode 100644 packages/ui/certd-server/src/modules/auto/fix/suite-content-wildcard-domain-count-fix.ts create mode 100644 packages/ui/certd-server/src/modules/monitor/service/cert-info-service.test.ts create mode 100644 packages/ui/certd-server/src/modules/pipeline/service/pipeline-suite-limit.test.ts create mode 100644 packages/ui/certd-server/src/modules/pipeline/service/pipeline-suite-limit.ts diff --git a/packages/ui/certd-client/src/locales/langs/en-US/certd/suite.ts b/packages/ui/certd-client/src/locales/langs/en-US/certd/suite.ts index 5fa3e3692..414bd2798 100644 --- a/packages/ui/certd-client/src/locales/langs/en-US/certd/suite.ts +++ b/packages/ui/certd-client/src/locales/langs/en-US/certd/suite.ts @@ -6,6 +6,9 @@ export default { specifications: "Specifications", pipeline: "Pipeline", domain: "Domain", + totalDomain: "Total Domain Count", + wildcardDomain: "Wildcard Domain", + includedWildcardDomain: "Included Wildcard Domain Count", deployTimes: "Deployments", monitorCount: "DomainMonitors", duration: "Duration", @@ -24,7 +27,8 @@ export default { please_select_package: "Please select a package", package: "Package", addon_package: "Addon Package", - domain_count: "Domain Count", + domain_count: "Total Domain Count", + wildcard_domain_count: "Wildcard Domain Count", unit_count: "pcs", pipeline_count: "Pipeline Count", unit_item: "items", @@ -42,6 +46,7 @@ export default { intro: "Introduction", packageContent: "Package Content", maxDomainCount: "Max Domain Count", + maxWildcardDomainCount: "Max Wildcard Domain Count", maxPipelineCount: "Max Pipeline Count", maxDeployCount: "Max Deploy Count", maxMonitorCount: "Max Monitor Count", @@ -51,6 +56,10 @@ export default { addon: "Addon", typeHelper: "Suite: Only the most recently purchased one is active at a time\nAddon: Multiple can be purchased, effective immediately without affecting the suite\nThe quantities of suite and addon can be accumulated", pipelineCount: "Pipeline Count", + wildcardDomainCount: "Wildcard Domain Count", + wildcardDomainCountPart: "Included Wildcard Domain Count", + wildcardDomainCountSub: "- Wildcard Domain Count", + wildcardDomainCountHelper: "Wildcard domains are also limited by the total domain count: each wildcard domain consumes both domain count and wildcard domain count quota.", unitPipeline: "pipelines", deployCount: "Deployment Count", unitDeploy: "times", diff --git a/packages/ui/certd-client/src/locales/langs/zh-CN/certd/suite.ts b/packages/ui/certd-client/src/locales/langs/zh-CN/certd/suite.ts index 76f0795bc..0c3578a60 100644 --- a/packages/ui/certd-client/src/locales/langs/zh-CN/certd/suite.ts +++ b/packages/ui/certd-client/src/locales/langs/zh-CN/certd/suite.ts @@ -6,6 +6,9 @@ export default { specifications: "规格", pipeline: "流水线", domain: "域名", + totalDomain: "域名总数量", + wildcardDomain: "泛域名", + includedWildcardDomain: "其中泛域名数量", deployTimes: "部署次数", monitorCount: "域名监控数", duration: "时长", @@ -24,7 +27,8 @@ export default { please_select_package: "请选择套餐", package: "套餐", addon_package: "加量包", - domain_count: "域名数量", + domain_count: "域名总数量", + wildcard_domain_count: "泛域名数量", unit_count: "个", pipeline_count: "流水线数量", unit_item: "条", @@ -42,6 +46,7 @@ export default { intro: "介绍", packageContent: "套餐内容", maxDomainCount: "最大域名数", + maxWildcardDomainCount: "最大泛域名数", maxPipelineCount: "最大流水线数", maxDeployCount: "最大部署数", maxMonitorCount: "最大监控数", @@ -51,6 +56,10 @@ export default { addon: "加量包", typeHelper: "套餐:同一时间只有最新购买的一个生效\n加量包:可购买多个,购买后立即生效,不影响套餐\n套餐和加量包数量可叠加", pipelineCount: "流水线数量", + wildcardDomainCount: "泛域名数量", + wildcardDomainCountPart: "其中泛域名数量", + wildcardDomainCountSub: "- 泛域名数量", + wildcardDomainCountHelper: "泛域名数量受域名总数量限制:泛域名会同时占用域名总数量和泛域名数量额度;注意:如果域名总数有限制,泛域名数量不要设置为无限制。", unitPipeline: "条", deployCount: "部署次数", unitDeploy: "次", diff --git a/packages/ui/certd-client/src/views/certd/suite/mine/api.ts b/packages/ui/certd-client/src/views/certd/suite/mine/api.ts index 1e1faa42b..64a09f5c7 100644 --- a/packages/ui/certd-client/src/views/certd/suite/mine/api.ts +++ b/packages/ui/certd-client/src/views/certd/suite/mine/api.ts @@ -14,6 +14,7 @@ export type SuiteDetail = { expiresTime?: number; pipelineCount?: SuiteValue; domainCount?: SuiteValue; + wildcardDomainCount?: SuiteValue; deployCount?: SuiteValue; monitorCount?: SuiteValue; }; diff --git a/packages/ui/certd-client/src/views/certd/suite/mine/crud.tsx b/packages/ui/certd-client/src/views/certd/suite/mine/crud.tsx index 1076630a7..f8ed1d21f 100644 --- a/packages/ui/certd-client/src/views/certd/suite/mine/crud.tsx +++ b/packages/ui/certd-client/src/views/certd/suite/mine/crud.tsx @@ -147,7 +147,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat }, }, "content.maxDomainCount": { - title: "域名数量", + title: "域名总数量", type: "text", form: { key: ["content", "maxDomainCount"], @@ -168,6 +168,28 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat align: "center", }, }, + "content.maxWildcardDomainCount": { + title: "其中泛域名数量", + type: "text", + form: { + key: ["content", "maxWildcardDomainCount"], + component: { + name: SuiteValueEdit, + vModel: "modelValue", + unit: "个", + }, + rules: [{ required: true, message: "此项必填" }], + }, + column: { + width: 120, + component: { + name: SuiteValue, + vModel: "modelValue", + unit: "个", + }, + align: "center", + }, + }, "content.maxPipelineCount": { title: "流水线数量", type: "text", diff --git a/packages/ui/certd-client/src/views/certd/suite/order-modal.vue b/packages/ui/certd-client/src/views/certd/suite/order-modal.vue index ad0ab1adf..ac195f127 100644 --- a/packages/ui/certd-client/src/views/certd/suite/order-modal.vue +++ b/packages/ui/certd-client/src/views/certd/suite/order-modal.vue @@ -11,7 +11,10 @@ {{ $t("certd.order.specifications") }}: {{ $t("certd.order.pipeline") }} - {{ $t("certd.order.domain") }} + {{ $t("certd.order.totalDomain") }} + + - {{ $t("certd.order.includedWildcardDomain") }}; + {{ $t("certd.order.deployTimes") }} {{ $t("certd.order.monitorCount") }} diff --git a/packages/ui/certd-client/src/views/certd/suite/product-info.vue b/packages/ui/certd-client/src/views/certd/suite/product-info.vue index 96699c9bd..917330a61 100644 --- a/packages/ui/certd-client/src/views/certd/suite/product-info.vue +++ b/packages/ui/certd-client/src/views/certd/suite/product-info.vue @@ -1,7 +1,7 @@