diff --git a/packages/plugins/plugin-cert/src/plugin/cert-plugin/acme.ts b/packages/plugins/plugin-cert/src/plugin/cert-plugin/acme.ts index ac5fce5e..550b7f2a 100644 --- a/packages/plugins/plugin-cert/src/plugin/cert-plugin/acme.ts +++ b/packages/plugins/plugin-cert/src/plugin/cert-plugin/acme.ts @@ -249,6 +249,9 @@ export class AcmeService { const httpVerifyPlan = domainVerifyPlan.httpVerifyPlan; if (httpVerifyPlan) { const httpChallenge = getChallenge("http-01"); + if (httpChallenge == null) { + throw new Error("该域名不支持http-01方式校验"); + } const plan = httpVerifyPlan[fullDomain]; return await doHttpVerify(httpChallenge, plan.httpUploader); } else { diff --git a/packages/plugins/plugin-cert/src/plugin/cert-plugin/base.ts b/packages/plugins/plugin-cert/src/plugin/cert-plugin/base.ts index a16c75f5..e4b561e6 100644 --- a/packages/plugins/plugin-cert/src/plugin/cert-plugin/base.ts +++ b/packages/plugins/plugin-cert/src/plugin/cert-plugin/base.ts @@ -17,6 +17,7 @@ export abstract class CertApplyBasePlugin extends AbstractTaskPlugin { vModel: "value", mode: "tags", open: false, + placeholder: "foo.com / *.foo.com / *.bar.com", tokenSeparators: [",", " ", ",", "、", "|"], }, rules: [{ type: "domains" }], @@ -26,9 +27,9 @@ export abstract class CertApplyBasePlugin extends AbstractTaskPlugin { }, order: -999, helper: - "1、支持通配符域名,例如: *.foo.com、foo.com、*.test.handsfree.work\n" + - "2、支持多个域名、多个子域名、多个通配符域名打到一个证书上(域名必须是在同一个DNS提供商解析)\n" + - "3、多级子域名要分成多个域名输入(*.foo.com的证书不能用于xxx.yyy.foo.com、foo.com)\n" + + "1、支持多个域名打到一个证书上,例如: foo.com,*.foo.com,*.bar.com\n" + + "2、子域名被通配符包含的不要填写,例如:www.foo.com已经被*.foo.com包含,不要填写www.foo.com\n" + + "3、泛域名只能通配*号那一级(*.foo.com的证书不能用于xxx.yyy.foo.com、不能用于foo.com)\n" + "4、输入一个,空格之后,再输入下一个", }) domains!: string[]; diff --git a/packages/ui/certd-client/src/components/plugins/cert/domains-verify-plan-editor/api.ts b/packages/ui/certd-client/src/components/plugins/cert/domains-verify-plan-editor/api.ts index baeaee01..717b04ac 100644 --- a/packages/ui/certd-client/src/components/plugins/cert/domains-verify-plan-editor/api.ts +++ b/packages/ui/certd-client/src/components/plugins/cert/domains-verify-plan-editor/api.ts @@ -9,6 +9,12 @@ export type CnameRecord = { recordValue?: string; }; +export type DomainGroupItem = { + domain: string; + domains?: string[]; + keySubDomains?: string[]; +}; + export async function GetList() { return await request({ url: apiPrefix + "/list", diff --git a/packages/ui/certd-client/src/components/plugins/cert/domains-verify-plan-editor/http-verify-plan.vue b/packages/ui/certd-client/src/components/plugins/cert/domains-verify-plan-editor/http-verify-plan.vue index 6b58e7fa..2c75a6f6 100644 --- a/packages/ui/certd-client/src/components/plugins/cert/domains-verify-plan-editor/http-verify-plan.vue +++ b/packages/ui/certd-client/src/components/plugins/cert/domains-verify-plan-editor/http-verify-plan.vue @@ -52,7 +52,6 @@ watch( }, (value: any) => { if (value) { - debugger; records.value = { ...value }; diff --git a/packages/ui/certd-client/src/components/plugins/cert/domains-verify-plan-editor/index.vue b/packages/ui/certd-client/src/components/plugins/cert/domains-verify-plan-editor/index.vue index 0c77e74a..54a40d3d 100644 --- a/packages/ui/certd-client/src/components/plugins/cert/domains-verify-plan-editor/index.vue +++ b/packages/ui/certd-client/src/components/plugins/cert/domains-verify-plan-editor/index.vue @@ -80,10 +80,11 @@ import { dict, FsDictSelect } from "@fast-crud/fast-crud"; import AccessSelector from "/@/views/certd/access/access-selector/index.vue"; import CnameVerifyPlan from "./cname-verify-plan.vue"; import HttpVerifyPlan from "./http-verify-plan.vue"; +//@ts-ignore import psl from "psl"; import { Form } from "ant-design-vue"; import { DomainsVerifyPlanInput } from "./type"; -import { CnameRecord } from "./api"; +import { CnameRecord, DomainGroupItem } from "./api"; defineOptions({ name: "DomainsVerifyPlanEditor" }); @@ -136,7 +137,7 @@ function showError(error: string) { errorMessageRef.value = error; } -type DomainGroup = Record>; +type DomainGroup = Record; function onDomainsChanged(domains: string[]) { if (domains == null) { @@ -145,8 +146,8 @@ function onDomainsChanged(domains: string[]) { const domainGroups: DomainGroup = {}; for (let domain of domains) { - domain = domain.replace("*.", ""); - const parsed = psl.parse(domain); + const keyDomain = domain.replace("*.", ""); + const parsed = psl.parse(keyDomain); if (parsed.error) { showError(`域名${domain}解析失败: ${JSON.stringify(parsed.error)}`); continue; @@ -157,15 +158,20 @@ function onDomainsChanged(domains: string[]) { } let group = domainGroups[mainDomain]; if (!group) { - group = {}; + group = { + domain: mainDomain, + domains: [], + keySubDomains: [] + } as DomainGroupItem; domainGroups[mainDomain] = group; } - group[domain] = {}; + group.domains.push(domain); + group.keySubDomains.push(keyDomain); } for (const domain in domainGroups) { let planItem = planRef.value[domain]; - const subDomains = domainGroups[domain]; + const domainGroupItem = domainGroups[domain]; if (!planItem) { planItem = { domain, @@ -178,12 +184,15 @@ function onDomainsChanged(domains: string[]) { }; planRef.value[domain] = planItem; } + planItem.domains = domainGroupItem.domains; const cnameOrigin = planItem.cnameVerifyPlan; const httpOrigin = planItem.httpVerifyPlan; planItem.cnameVerifyPlan = {}; planItem.httpVerifyPlan = {}; - for (const subDomain in subDomains) { + const cnamePlan = planItem.cnameVerifyPlan; + const httpPlan = planItem.httpVerifyPlan; + for (const subDomain of domainGroupItem.keySubDomains) { if (!cnameOrigin[subDomain]) { //@ts-ignore planItem.cnameVerifyPlan[subDomain] = { @@ -192,8 +201,14 @@ function onDomainsChanged(domains: string[]) { } else { planItem.cnameVerifyPlan[subDomain] = cnameOrigin[subDomain]; } - } - for (const subDomain in subDomains) { + + if (!cnamePlan[subDomain]) { + //@ts-ignore + cnamePlan[subDomain] = { + id: 0 + }; + } + if (!httpOrigin[subDomain]) { //@ts-ignore planItem.httpVerifyPlan[subDomain] = { @@ -202,27 +217,7 @@ function onDomainsChanged(domains: string[]) { } else { planItem.httpVerifyPlan[subDomain] = httpOrigin[subDomain]; } - } - const cnamePlan = planItem.cnameVerifyPlan; - for (const subDomain in subDomains) { - if (!cnamePlan[subDomain]) { - //@ts-ignore - cnamePlan[subDomain] = { - id: 0 - }; - } - } - for (const subDomain of Object.keys(cnamePlan)) { - if (!subDomains[subDomain]) { - delete cnamePlan[subDomain]; - } - } - - // httpVerifyPlan - const httpPlan = planItem.httpVerifyPlan; - for (const subDomain in subDomains) { - debugger; if (!httpPlan[subDomain]) { //@ts-ignore httpPlan[subDomain] = { @@ -230,8 +225,15 @@ function onDomainsChanged(domains: string[]) { }; } } + + for (const subDomain of Object.keys(cnamePlan)) { + if (!domainGroupItem.keySubDomains.includes(subDomain)) { + delete cnamePlan[subDomain]; + } + } + for (const subDomain of Object.keys(httpPlan)) { - if (!subDomains[subDomain]) { + if (!domainGroupItem.keySubDomains.includes(subDomain)) { delete httpPlan[subDomain]; } } @@ -242,7 +244,6 @@ function onDomainsChanged(domains: string[]) { delete planRef.value[domain]; } } - debugger; } watch( @@ -324,12 +325,15 @@ watch( padding: 10px 6px; } td { - border-bottom: 1px solid #e8e8e8; + border-bottom: 2px solid #d8d8d8; border-left: 1px solid #e8e8e8; padding: 6px 6px; } .plan { + td { + border-right: 1px solid #e8e8e8 !important; + } font-size: 14px; .ant-select { width: 100%; diff --git a/packages/ui/certd-client/src/components/plugins/cert/domains-verify-plan-editor/type.ts b/packages/ui/certd-client/src/components/plugins/cert/domains-verify-plan-editor/type.ts index cfaed15e..bf8a5740 100644 --- a/packages/ui/certd-client/src/components/plugins/cert/domains-verify-plan-editor/type.ts +++ b/packages/ui/certd-client/src/components/plugins/cert/domains-verify-plan-editor/type.ts @@ -9,6 +9,7 @@ export type HttpRecord = { export type DomainVerifyPlanInput = { domain: string; + domains: string[]; type: "cname" | "dns" | "http"; dnsProviderType?: string; dnsProviderAccessId?: number; diff --git a/packages/ui/certd-client/src/components/plugins/cert/domains-verify-plan-editor/validator.ts b/packages/ui/certd-client/src/components/plugins/cert/domains-verify-plan-editor/validator.ts index b91b5536..4e7c73f6 100644 --- a/packages/ui/certd-client/src/components/plugins/cert/domains-verify-plan-editor/validator.ts +++ b/packages/ui/certd-client/src/components/plugins/cert/domains-verify-plan-editor/validator.ts @@ -18,21 +18,31 @@ function checkDomainVerifyPlan(rule: any, value: DomainsVerifyPlanInput) { } } } else if (type === "http") { + const domains = value[domain].domains || []; + for (const item of domains) { + //如果有通配符域名则不允许使用http校验 + if (item.startsWith("*.")) { + throw new Error(`域名${item}为通配符域名,不支持HTTP校验`); + } + } + const subDomains = Object.keys(value[domain].httpVerifyPlan); if (subDomains.length > 0) { for (const subDomain of subDomains) { const plan = value[domain].httpVerifyPlan[subDomain]; - if (plan.httpUploaderType == null) { + if (!plan.httpUploaderType) { throw new Error(`域名${subDomain}的上传方式必须填写`); - } else if (plan.httpUploaderAccess == null) { + } + if (!plan.httpUploaderAccess) { throw new Error(`域名${subDomain}的上传授权信息必须填写`); - } else if (plan.httpUploadRootDir == null) { + } + if (!plan.httpUploadRootDir) { throw new Error(`域名${subDomain}的网站根路径必须填写`); } } } } else if (type === "dns") { - if (value[domain].dnsProviderType == null || value[domain].dnsProviderAccessId == null) { + if (!value[domain].dnsProviderType || !value[domain].dnsProviderAccessId) { throw new Error(`DNS模式下,域名${domain}的DNS类型和授权信息必须填写`); } } diff --git a/packages/ui/certd-client/src/views/sys/suite/user-suite/crud.tsx b/packages/ui/certd-client/src/views/sys/suite/user-suite/crud.tsx index 1caf0062..0ea1a77a 100644 --- a/packages/ui/certd-client/src/views/sys/suite/user-suite/crud.tsx +++ b/packages/ui/certd-client/src/views/sys/suite/user-suite/crud.tsx @@ -157,7 +157,6 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat ] }, valueResolve({ form, value }) { - debugger; if (value && value.productId) { form.productId = value.productId; form.duration = value.duration; diff --git a/packages/ui/certd-server/test/controller/api.test.ts b/packages/ui/certd-server/test/controller/api.test.ts index 3214ec33..b18554a5 100755 --- a/packages/ui/certd-server/test/controller/api.test.ts +++ b/packages/ui/certd-server/test/controller/api.test.ts @@ -4,14 +4,13 @@ import assert from 'assert'; import { getApp } from '../setup.js'; describe('test/controller/home.test.ts', () => { - it('should POST /api/get_user', async function (this: any) { const app: Application = getApp(); // make request const result = await createHttpRequest(app).get('/api/get_user').query({ uid: 123 }); // use expect by jest - assert(result.status ===200); + assert(result.status === 200); assert(result.body.message === 'OK'); }); });