Merge branch 'v2-dev' of https://github.com/certd/certd into v2-dev

This commit is contained in:
xiaojunnuo
2025-12-10 14:17:20 +08:00
23 changed files with 104 additions and 13 deletions
+2 -1
View File
@@ -9,5 +9,6 @@
"[typescript]": { "[typescript]": {
"editor.defaultFormatter": "vscode.typescript-language-features" "editor.defaultFormatter": "vscode.typescript-language-features"
}, },
"editor.tabSize": 2 "editor.tabSize": 2,
"explorer.autoReveal": false
} }
+50 -5
View File
@@ -65,9 +65,54 @@ docker-compose up -d
## 二、从旧版的sqlite切换数据库 ## 二、从旧版的sqlite切换数据库
1. 先将`旧certd`升级到最新版 `建议:备份sqlite数据库` 从旧版`sqlite`迁移到`mysql``postgresql`数据库
2. 按照上面全新安装方式部署一套`新的certd` `注意:新旧版本的certd要一致`
3. 使用数据库工具将数据从sqlite导入到mysql或postgresql `注意:flyway_history数据表不要导入`
4. 重启新certd
5. 确认没有问题之后,删除旧版certd
下面以 `SQLite``MySQL` 为例进行演示
![db-0.png](images/db-0.png)
#### 0.前提条件:
1. SQLite版Certd站点已经`升级到最新版` `建议:备份sqlite数据库`
2. `全新安装`MySQL版本Certd`确保是全新的,因为里面的数据会被清空覆盖`
3. 两套Certd站点版本一致
#### 1. 安装DBeaver工具
[https://dbeaver.io/download/](https://dbeaver.io/download/)
![db-1.png](images/db-1.png)
#### 2. 连接到sqlite数据库
![db-2.png](images/db-sqlite-1.png)
![db-3.png](images/db-sqlite-2.png)
#### 3. 连接到mysql或postgresql数据库
![db-4.png](images/db-mysql-1.png)
![db-5.png](images/db-mysql-2.png)
#### 4. 开始同步数据
选择mysql数据库,选择所有的表(`flyway_history除外`),右键导入数据
> 切记flyway_history数据表不要导入
![db-6.png](images/db-sync-1.jpg)
![db-7.png](images/db-sync-2.png)
![db-8.png](images/db-sync-3.png)
下一步、下一步,直到数据加载设置,勾选`在加载前截断目标表`(此选项很重要,并且会清空mysql certd数据库中的数据)
![db-7.png](images/db-sync-4.png)
#### 5. 导入完成
![db-9.png](images/db-success.png)
#### 6. 重启MySQL版本Certd
访问MySQL版本测试,数据已成功迁移
确认没有问题之后,删除旧版certd
Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 194 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

@@ -631,7 +631,7 @@ export default {
autoHideTime: "Auto Hide Time", autoHideTime: "Auto Hide Time",
autoHideTimeHelper: "Minutes without requests before auto hiding", autoHideTimeHelper: "Minutes without requests before auto hiding",
hideOpenApi: "Hide Open API", hideOpenApi: "Hide Open API",
hideOpenApiHelper: "Whether to hide open APIs; whether to expose /api/v1 prefixed endpoints", hideOpenApiHelper: "Whether to hide open APIs; whether to hide /api/v1 prefixed endpoints",
hideSiteImmediately: "Hide Site Immediately", hideSiteImmediately: "Hide Site Immediately",
hideImmediately: "Hide Immediately", hideImmediately: "Hide Immediately",
confirmHideSiteTitle: "Are you sure to hide the site immediately?", confirmHideSiteTitle: "Are you sure to hide the site immediately?",
@@ -635,7 +635,7 @@ export default {
autoHideTime: "自动隐藏时间", autoHideTime: "自动隐藏时间",
autoHideTimeHelper: "多少分钟内无请求自动隐藏", autoHideTimeHelper: "多少分钟内无请求自动隐藏",
hideOpenApi: "隐藏开放接口", hideOpenApi: "隐藏开放接口",
hideOpenApiHelper: "是否隐藏开放接口,是否放开/api/v1开头的接口", hideOpenApiHelper: "是否隐藏开放接口,是否同时隐藏/api/v1开头的接口",
hideSiteImmediately: "立即隐藏站点", hideSiteImmediately: "立即隐藏站点",
hideImmediately: "立即隐藏", hideImmediately: "立即隐藏",
confirmHideSiteTitle: "确定要立即隐藏站点吗?", confirmHideSiteTitle: "确定要立即隐藏站点吗?",
@@ -21,6 +21,7 @@
}, },
}, },
}" }"
:disabled="disabled"
:show-current="false" :show-current="false"
:show-select="false" :show-select="false"
:dialog="{ width: 960 }" :dialog="{ width: 960 }"
@@ -7,7 +7,7 @@
<vip-button class="ml-5" mode="button"></vip-button> <vip-button class="ml-5" mode="button"></vip-button>
</div> </div>
</a-form-item> </a-form-item>
<a-form-item v-if="formState.public.oauthEnabled" :label="t('certd.sys.setting.oauthProviders')" :name="['public', 'oauthProviders']"> <a-form-item :label="t('certd.sys.setting.oauthProviders')" :name="['public', 'oauthProviders']">
<div class="flex flex-wrap"> <div class="flex flex-wrap">
<table class="w-full table-auto border-collapse border border-gray-400"> <table class="w-full table-auto border-collapse border border-gray-400">
<thead> <thead>
@@ -31,7 +31,14 @@
</fs-copyable> </fs-copyable>
</td> </td>
<td class="border border-gray-300 px-4 py-2"> <td class="border border-gray-300 px-4 py-2">
<AddonSelector v-model:model-value="item.addonId" addon-type="oauth" from="sys" :type="item.name" :placeholder="t('certd.sys.setting.oauthProviderSelectorPlaceholder')" /> <AddonSelector
v-model:model-value="item.addonId"
:disabled="!formState.public.oauthEnabled"
addon-type="oauth"
from="sys"
:type="item.name"
:placeholder="t('certd.sys.setting.oauthProviderSelectorPlaceholder')"
/>
</td> </td>
</tr> </tr>
</tbody> </tbody>
@@ -0,0 +1,2 @@
ALTER TABLE `sys_settings` MODIFY COLUMN `setting` longtext NULL;
ALTER TABLE `user_settings` MODIFY COLUMN `setting` longtext NULL;
@@ -0,0 +1,20 @@
update cd_access set create_time = '2024-08-08 00:00:00.000' where create_time < '999999999999999999999';
update cd_access set update_time = '2024-08-08 00:00:00.000' where update_time < '999999999999999999999';
update pi_history set create_time = '2024-08-08 00:00:00.000' where create_time < '999999999999999999999';
update pi_history set update_time = '2024-08-08 00:00:00.000' where update_time < '999999999999999999999';
update pi_history_log set create_time = '2024-08-08 00:00:00.000' where create_time < '999999999999999999999';
update pi_history_log set update_time = '2024-08-08 00:00:00.000' where update_time < '999999999999999999999';
update pi_pipeline set create_time = '2024-08-08 00:00:00.000' where create_time < '999999999999999999999';
update pi_pipeline set update_time = '2024-08-08 00:00:00.000' where update_time < '999999999999999999999';
update sys_permission set create_time = '2024-08-08 00:00:00.000' where create_time < '999999999999999999999';
update sys_permission set update_time = '2024-08-08 00:00:00.000' where update_time < '999999999999999999999';
update sys_role set create_time = '2024-08-08 00:00:00.000' where create_time < '999999999999999999999';
update sys_role set update_time = '2024-08-08 00:00:00.000' where update_time < '999999999999999999999';
update sys_user set create_time = '2024-08-08 00:00:00.000' where create_time < '999999999999999999999';
update sys_user set update_time = '2024-08-08 00:00:00.000' where update_time < '999999999999999999999';
@@ -158,6 +158,9 @@ export class WestAccess extends BaseAccess {
}, },
}); });
if (res.msg !== 'success') { if (res.msg !== 'success') {
if(res.msg.includes('500 already exists')){
return res;
}
throw new Error(`${JSON.stringify(res.msg)}`); throw new Error(`${JSON.stringify(res.msg)}`);
} }
return res; return res;
@@ -253,6 +256,9 @@ token=md5(zhangsan + 5dh232kfg!* + 1554691950854)=cfcd208495d565ef66e7dff9f98764
}); });
this.ctx.logger.info(`request ${url} ${method} res:${JSON.stringify(res)}`); this.ctx.logger.info(`request ${url} ${method} res:${JSON.stringify(res)}`);
if (res.msg !== 'success' && res.result!= 200) { if (res.msg !== 'success' && res.result!= 200) {
if(res.msg.includes('500 already exists')){
return res;
}
throw new Error(`${JSON.stringify(res.msg)}`); throw new Error(`${JSON.stringify(res.msg)}`);
} }
return res; return res;
@@ -73,11 +73,16 @@ export class WestDnsProviderDomain extends AbstractDnsProvider<westRecord> {
} }
//这里调用删除txt dns解析记录接口 //这里调用删除txt dns解析记录接口
const record_id = record?.body?.record_id;
if (!record_id) {
this.logger.info('record_id不存在');
return;
}
// 准备要发送到API的请求体 // 准备要发送到API的请求体
const requestBody = { const requestBody = {
act: 'dnsrec.remove', // API动作类型 act: 'dnsrec.remove', // API动作类型
domain: domain, // 域名 domain: domain, // 域名
record_id: record.body.record_id, record_id: record_id,
hostname: fullRecord, // 完整的记录名 hostname: fullRecord, // 完整的记录名
record_type: 'TXT', // DNS记录类型 record_type: 'TXT', // DNS记录类型
record_line: '', // 记录线路 record_line: '', // 记录线路
@@ -107,12 +107,16 @@ export class WestDnsProvider extends AbstractDnsProvider<westRecord> {
return; return;
} }
//这里调用删除txt dns解析记录接口 //这里调用删除txt dns解析记录接口
const record_id = record.data?.id;
if (!record_id) {
this.logger.info('record_id不存在');
return;
}
// 准备要发送到API的请求体 // 准备要发送到API的请求体
const requestBody = { const requestBody = {
act: 'deldnsrecord', // API动作类型 act: 'deldnsrecord', // API动作类型
domain: domain, // 域名 domain: domain, // 域名
id: record.data?.id, id: record_id,
}; };
const url = '/v2/domain/'; const url = '/v2/domain/';