mirror of
https://github.com/certd/certd.git
synced 2026-07-15 18:27:33 +08:00
Compare commits
6 Commits
5ccd6e64bc
...
1e7b057946
| Author | SHA1 | Date | |
|---|---|---|---|
| 1e7b057946 | |||
| fb5b00d73f | |||
| 09ccfa2624 | |||
| 5c80c99b94 | |||
| adcf570b15 | |||
| 787b52bef7 |
+2
-1
@@ -31,4 +31,5 @@ test/**/*.js
|
||||
/packages/pro/
|
||||
test.js
|
||||
.history
|
||||
/logs
|
||||
/logs
|
||||
.pnpm-lock.yaml
|
||||
@@ -33,6 +33,44 @@ version: 1.0.0
|
||||
7. 删除、审核通过、拒绝等危险操作必须保留确认弹窗和错误提示,成功后刷新当前 CRUD 列表。
|
||||
8. 对话框里只做纯确认时可以使用 `Modal.confirm`;只要需要字段输入、表单校验或提交字段,统一使用 `useFormDialog` / `openFormDialog`,不要在 `Modal.confirm` 的 `content` 里手写输入框。
|
||||
|
||||
|
||||
## crud 配置
|
||||
|
||||
const crudOptions ={
|
||||
id: string, //表格唯一标识,同一个页面的多个表格的列设置和字段设置会根据id进行区分保存
|
||||
request:{}, //http请求
|
||||
columns:{ //字段配置
|
||||
key:{ //字段key
|
||||
column:{}, //对应table-column配置
|
||||
form:{}, //表单中该字段的公共配置,viewForm、addForm、editForm、search会集成此配置,支持对应ui的form-item配置
|
||||
viewForm:{}, //查看表单中该字段的配置,支持对应ui的form-item配置
|
||||
addForm:{}, // 添加表单中该字段的配置,支持对应ui的form-item配置
|
||||
editForm:{}, //编辑表单中该字段的配置,支持对应ui的form-item配置
|
||||
search:{} //对应查询表单的form-item配置
|
||||
}
|
||||
},
|
||||
search:{ //查询框配置 ,对应fs-search组件
|
||||
options:{} //查询表单配置 ,对应el-from, a-form配置
|
||||
},
|
||||
actionbar:{}, //动作条,添加按钮,对应fs-actionbar组件
|
||||
toolbar:{}, //工具条 ,对应fs-toolbar组件
|
||||
table:{ //表格配置,对应fs-table
|
||||
// 对应 el-table / a-table的配置
|
||||
slots:{} // 对应el-table ,a-table的插槽
|
||||
},
|
||||
data:{}, //列表数据,无需配置,自动从pageRequest中获取
|
||||
// 如果你要手动改变表格数据,可以通过crudBinding.value.data直接赋值修改表格数据
|
||||
rowHandle:{}, //操作列配置,对应fs-row-handle
|
||||
form:{ //表单的公共配置,对应el-form,a-form配置
|
||||
wrapper:{} //表单外部容器(对话框)的配置,对应el-dialog,el-drawer,a-model,a-drawer的配置
|
||||
},
|
||||
viewForm:{}, //查看表单的独立配置
|
||||
editForm:{}, //编辑表单的独立配置
|
||||
addForm:{}, //添加表单的独立配置
|
||||
pagination:{}, //分页配置 ,对应el-pagination / a-pagination
|
||||
container:{}, //容器配置 ,对应fs-container
|
||||
}
|
||||
|
||||
## 布局高度
|
||||
|
||||
- Fast Crud 表格依赖外部容器高度计算。虽然表格本身有默认约 200px 高度,但页面内嵌 `fs-crud` 时,为了获得稳定可用的列表区域,必须让外层容器提供明确高度或剩余高度。
|
||||
|
||||
@@ -119,6 +119,7 @@ export default defineConfig({
|
||||
{text: "Certd本身的证书更新", link: "/guide/use/https/index.md"},
|
||||
{text: "js脚本插件使用", link: "/guide/use/custom-script/index.md"},
|
||||
{text: "邮箱配置", link: "/guide/use/email/index.md"},
|
||||
{text: "证书复用", link: "/guide/use/pretask/"},
|
||||
{text: "IPv6支持", link: "/guide/use/setting/ipv6.md"},
|
||||
{text: "ESXi", link: "/guide/use/ESXi/index.md"},
|
||||
{text: "宝塔动态IP白名单", link: "/guide/use/baota/white_list.md"},
|
||||
|
||||
@@ -59,4 +59,7 @@ DNS problem: NXDOMAIN looking up TXT for _acme-challenge.xxxxx - check that a D
|
||||
证书颁发机构向域名ns查询TXT验证记录失败,有以下几种可能
|
||||
1、域名的ns服务器修改成别的了,但申请证书时的DNS提供商选择错误(检查确认,配置正确的DNS提供商)
|
||||
2、证书颁发机构与ns域名服务器之间访问不通,无法查询到TXT记录(尝试更换证书颁发机构)
|
||||
3、ns服务商解析值生效慢(尝试修改证书申请任务里面的等待生效时长600-1000s)
|
||||
3、ns服务商解析值生效慢(尝试修改证书申请任务里面的等待生效时长600-1000s)
|
||||
|
||||
## 8. 同一份证书上传多次的问题
|
||||
同一份证书在阿里云、腾讯云中上传多次,[请使用证书复用功能](../use/pretask/index.md),避免重复上传。
|
||||
@@ -1,13 +1,13 @@
|
||||
# 带输出的前置任务
|
||||
# 证书复用
|
||||
|
||||
前置任务输出可以在后续任务中使用
|
||||
|
||||
比如上传证书到阿里云,会返回阿里云的CertId,之后其他阿里云的部署任务可以选择复用这个证书
|
||||
|
||||
## 复用证书
|
||||
## 使用方法
|
||||
|
||||

|
||||
|
||||
在后续任务中可以选择前置任务的输出
|
||||
|
||||

|
||||

|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
</div>
|
||||
<div class="flex-between mt-5">
|
||||
<div class="flex-o"><fs-icon icon="ant-design:check-outlined" class="color-green mr-5" /> 监控站点数:</div>
|
||||
<suite-value :model-value="detail.monitorCount.max" :used="detail.monitorCount.used" unit="次" />
|
||||
<suite-value :model-value="detail.monitorCount.max" :used="detail.monitorCount.used" unit="个" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -123,10 +123,15 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
value: "id",
|
||||
label: "nickName",
|
||||
}),
|
||||
editForm: {
|
||||
component: {
|
||||
disabled: true,
|
||||
},
|
||||
},
|
||||
form: {
|
||||
show: true,
|
||||
component: {
|
||||
disabled: true,
|
||||
disabled: false,
|
||||
crossPage: true,
|
||||
multiple: false,
|
||||
select: {
|
||||
@@ -170,11 +175,6 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
productType: {
|
||||
title: t("certd.type"),
|
||||
type: "dict-select",
|
||||
editForm: {
|
||||
component: {
|
||||
disabled: true,
|
||||
},
|
||||
},
|
||||
dict: dict({
|
||||
data: [
|
||||
{ label: t("certd.package"), value: "suite", color: "green" },
|
||||
@@ -182,7 +182,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
],
|
||||
}),
|
||||
form: {
|
||||
show: true,
|
||||
show: false,
|
||||
component: {
|
||||
disabled: true,
|
||||
},
|
||||
@@ -205,6 +205,9 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
"content.maxDomainCount": {
|
||||
title: t("certd.domain_count"),
|
||||
type: "text",
|
||||
addForm: {
|
||||
show: false,
|
||||
},
|
||||
form: {
|
||||
key: ["content", "maxDomainCount"],
|
||||
component: {
|
||||
@@ -227,6 +230,9 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
"content.maxWildcardDomainCount": {
|
||||
title: t("certd.wildcardDomainCountPart"),
|
||||
type: "text",
|
||||
addForm: {
|
||||
show: false,
|
||||
},
|
||||
form: {
|
||||
key: ["content", "maxWildcardDomainCount"],
|
||||
component: {
|
||||
@@ -249,6 +255,9 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
"content.maxPipelineCount": {
|
||||
title: t("certd.pipeline_count"),
|
||||
type: "text",
|
||||
addForm: {
|
||||
show: false,
|
||||
},
|
||||
form: {
|
||||
key: ["content", "maxPipelineCount"],
|
||||
component: {
|
||||
@@ -271,6 +280,9 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
"content.maxDeployCount": {
|
||||
title: t("certd.deploy_count"),
|
||||
type: "text",
|
||||
addForm: {
|
||||
show: false,
|
||||
},
|
||||
form: {
|
||||
key: ["content", "maxDeployCount"],
|
||||
component: {
|
||||
@@ -296,6 +308,9 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
"content.maxMonitorCount": {
|
||||
title: t("certd.monitor_count"),
|
||||
type: "text",
|
||||
addForm: {
|
||||
show: false,
|
||||
},
|
||||
form: {
|
||||
key: ["content", "maxMonitorCount"],
|
||||
component: {
|
||||
@@ -318,6 +333,9 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
duration: {
|
||||
title: t("certd.duration"),
|
||||
type: "text",
|
||||
addForm: {
|
||||
show: false,
|
||||
},
|
||||
form: {
|
||||
rules: [{ required: true, message: t("certd.field_required") }],
|
||||
},
|
||||
@@ -363,6 +381,9 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
expiresTime: {
|
||||
title: t("certd.expires_time"),
|
||||
type: "date",
|
||||
addForm: {
|
||||
show: false,
|
||||
},
|
||||
form: {
|
||||
valueBuilder: ({ value }) => {
|
||||
return dayjs(value);
|
||||
@@ -393,6 +414,9 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
{ label: t("certd.is_present_no"), value: false, color: "blue" },
|
||||
],
|
||||
}),
|
||||
addForm: {
|
||||
show: false,
|
||||
},
|
||||
form: {
|
||||
value: true,
|
||||
},
|
||||
@@ -404,6 +428,9 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
deployCountUsed: {
|
||||
title: t("certd.deploy_count_used"),
|
||||
type: "number",
|
||||
addForm: {
|
||||
show: false,
|
||||
},
|
||||
form: {
|
||||
value: 0,
|
||||
rules: [{ required: true, message: t("certd.field_required") }],
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
export function shouldSetDefaultNoCache(path: string, cacheControl?: string) {
|
||||
if(path === '/' || path === '/index.html' ){
|
||||
//首页不管怎样都不要缓存
|
||||
return true;
|
||||
}
|
||||
if (cacheControl) {
|
||||
return false;
|
||||
}
|
||||
return path === '/' || path === '/index.html' || path.startsWith('/api');
|
||||
// api也不要缓存,如果他本身有设置缓存除外
|
||||
return path.startsWith('/api');
|
||||
}
|
||||
|
||||
@@ -13,7 +13,9 @@ describe("shouldSetDefaultNoCache", () => {
|
||||
});
|
||||
|
||||
it("keeps explicit cache headers from file responses", () => {
|
||||
assert.equal(shouldSetDefaultNoCache("/api/basic/file/download", "public,max-age=259200"), false);
|
||||
assert.equal(shouldSetDefaultNoCache("/", "public,max-age=259200"), true);
|
||||
assert.equal(shouldSetDefaultNoCache("/index.html", "public,max-age=259200"), true);
|
||||
assert.equal(shouldSetDefaultNoCache("/api/basic/file/download", "public,max-age=259200"), false);
|
||||
});
|
||||
|
||||
it("ignores non-html and non-api paths", () => {
|
||||
|
||||
@@ -126,7 +126,7 @@ export class MainConfiguration {
|
||||
await next();
|
||||
const path = ctx.path;
|
||||
// 如果是首页则强制设置为不缓存
|
||||
if (path === '/' || path === '/index.html' || shouldSetDefaultNoCache(path, ctx.response.get('Cache-Control')) ) {
|
||||
if (shouldSetDefaultNoCache(path, ctx.response.get('Cache-Control')) ) {
|
||||
ctx.response.set('Cache-Control', 'public,max-age=0');
|
||||
}
|
||||
});
|
||||
@@ -138,5 +138,6 @@ export class MainConfiguration {
|
||||
|
||||
logger.info('当前环境:', this.app.getEnv()); // prod
|
||||
// throw new Error("address family not supported")
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import { SuiteContentWildcardDomainCountFix } from "./suite-content-wildcard-dom
|
||||
type AutoFixTask = {
|
||||
key: string;
|
||||
fix: {
|
||||
init(): Promise<void>;
|
||||
init(): Promise<boolean>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -56,8 +56,8 @@ export class AutoFix {
|
||||
if (setting.fixed?.[task.key]) {
|
||||
continue;
|
||||
}
|
||||
await task.fix.init();
|
||||
setting.fixed[task.key] = true;
|
||||
const ret = await task.fix.init();
|
||||
setting.fixed[task.key] = ret;
|
||||
await this.sysSettingsService.saveSetting(setting);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,8 +38,10 @@ export class CertInfoWildcardDomainCountFix {
|
||||
if (fixedCount > 0) {
|
||||
logger.info(`已修复证书泛域名数量历史数据,数量=${fixedCount}`);
|
||||
}
|
||||
return true
|
||||
} catch (e: any) {
|
||||
logger.error("修复证书泛域名数量历史数据失败", e);
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ export class GoogleCommonEabAccountKeyFix {
|
||||
|
||||
async init() {
|
||||
if (!isComm()) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
const certApplyConfig = await this.pluginConfigService.getPluginConfig({
|
||||
@@ -56,31 +56,33 @@ export class GoogleCommonEabAccountKeyFix {
|
||||
});
|
||||
const googleCommonEabAccessId = certApplyConfig?.sysSetting?.input?.googleCommonEabAccessId;
|
||||
if (!googleCommonEabAccessId) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
const eabAccess = await this.accessService.getAccessById(googleCommonEabAccessId, false);
|
||||
if (eabAccess.accountKey) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
if (!eabAccess.kid) {
|
||||
logger.info("公共Google EAB授权缺少KID,跳过历史ACME账号私钥修复");
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
const accountConfig = await this.getLegacyGoogleAccountConfig(eabAccess.email);
|
||||
const privateKey = accountConfig?.privateKey || accountConfig?.key || accountConfig?.accountKey;
|
||||
if (!privateKey) {
|
||||
logger.info("未找到可迁移到公共Google EAB授权的历史ACME账号私钥");
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
const accountKey = buildEabAccountKeyValue(eabAccess.kid, privateKey);
|
||||
await this.accessService.updateAccess({ id: googleCommonEabAccessId, eabType: "google", accountKey });
|
||||
logger.info(`已修复公共Google EAB授权的ACME账号私钥,accessId=${googleCommonEabAccessId}`);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
logger.error("修复公共Google EAB授权ACME账号私钥失败", e);
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
async getLegacyGoogleAccountConfig(email?: string) {
|
||||
|
||||
@@ -41,6 +41,7 @@ export class OauthSubtypeBoundTypeFix {
|
||||
await this.convertLegacyAddonLoginTypeToArray(addonEntity, legacyLoginType, manager);
|
||||
}
|
||||
});
|
||||
return true
|
||||
} catch (e: any) {
|
||||
logger.error("修复OAuth subtype绑定历史数据失败", e);
|
||||
}
|
||||
|
||||
+2
@@ -33,9 +33,11 @@ export class SuiteContentWildcardDomainCountFix {
|
||||
if (fixedCount > 0) {
|
||||
logger.info(`已修复套餐最大泛域名数量历史数据,数量=${fixedCount}`);
|
||||
}
|
||||
return true
|
||||
} catch (e: any) {
|
||||
logger.error("修复套餐最大泛域名数量历史数据失败", e);
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private async fixSuiteContentWildcardDomainCountByTable(entityManager: any, tableName: string) {
|
||||
|
||||
@@ -363,7 +363,6 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||
if (!old && userSuite?.pipelineCount.max != -1 && userSuite?.pipelineCount.used + 1 > userSuite?.pipelineCount.max) {
|
||||
throw new NeedSuiteException(`对不起,您最多只能创建${userSuite?.pipelineCount.max}条流水线,请购买或升级套餐`);
|
||||
}
|
||||
|
||||
let oldDomainCount = 0;
|
||||
let oldWildcardDomainCount = 0;
|
||||
if (old?.id) {
|
||||
|
||||
Generated
-27661
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user