mirror of https://github.com/certd/certd
chore: auto
parent
4b335db31c
commit
785bee2b39
|
@ -1,6 +1,6 @@
|
|||
import {Inject, Provide, Scope, ScopeEnum} from '@midwayjs/core';
|
||||
import {InjectEntityModel} from '@midwayjs/typeorm';
|
||||
import {Repository} from 'typeorm';
|
||||
import { In, Repository } from "typeorm";
|
||||
import {AccessGetter, BaseService, PageReq, PermissionException, ValidateException} from '../../../index.js';
|
||||
import {AccessEntity} from '../entity/access.js';
|
||||
import {AccessDefine, accessRegistry, newAccess} from '@certd/pipeline';
|
||||
|
@ -175,4 +175,27 @@ export class AccessService extends BaseService<AccessEntity> {
|
|||
getDefineByType(type: string) {
|
||||
return accessRegistry.getDefine(type);
|
||||
}
|
||||
|
||||
|
||||
async getSimpleByIds(ids: number[], userId: any) {
|
||||
if (ids.length === 0) {
|
||||
return [];
|
||||
}
|
||||
if (!userId) {
|
||||
return [];
|
||||
}
|
||||
return await this.repository.find({
|
||||
where: {
|
||||
id: In(ids),
|
||||
userId,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
type: true,
|
||||
userId:true
|
||||
},
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,3 +59,32 @@ export interface ISubDomainsGetter {
|
|||
export interface IDomainParser {
|
||||
parse(fullDomain: string): Promise<string>;
|
||||
}
|
||||
|
||||
export type DnsVerifier = {
|
||||
// dns直接校验
|
||||
dnsProviderType: string;
|
||||
dnsProviderAccessId: number;
|
||||
};
|
||||
|
||||
export type CnameVerifier = {
|
||||
cnameRecord: string;
|
||||
};
|
||||
|
||||
export type HttpVerifier = {
|
||||
// http校验
|
||||
httpUploaderType: string;
|
||||
httpUploaderAccess: string;
|
||||
httpUploadRootDir: string;
|
||||
};
|
||||
export type DomainVerifier = {
|
||||
domain: string;
|
||||
mainDomain: string;
|
||||
challengeType: string;
|
||||
dns?: DnsVerifier;
|
||||
cname?: CnameVerifier;
|
||||
http?: HttpVerifier;
|
||||
};
|
||||
|
||||
export interface IDomainVerifierGetter {
|
||||
getVerifiers(domains: string[]): Promise<DomainVerifier[]>;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import { utils } from "@certd/basic";
|
|||
import type { CertInfo, CnameVerifyPlan, DomainsVerifyPlan, HttpVerifyPlan, PrivateKeyType, SSLProvider } from "./acme.js";
|
||||
import { AcmeService } from "./acme.js";
|
||||
import * as _ from "lodash-es";
|
||||
import { createDnsProvider, DnsProviderContext, IDnsProvider, ISubDomainsGetter } from "../../dns-provider/index.js";
|
||||
import { createDnsProvider, DnsProviderContext, DomainVerifier, IDnsProvider, IDomainVerifierGetter, ISubDomainsGetter } from "../../dns-provider/index.js";
|
||||
import { CertReader } from "./cert-reader.js";
|
||||
import { CertApplyBasePlugin } from "./base.js";
|
||||
import { GoogleClient } from "../../libs/google.js";
|
||||
|
@ -66,6 +66,7 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
|
|||
{ value: "cname", label: "CNAME代理验证" },
|
||||
{ value: "http", label: "HTTP文件验证" },
|
||||
{ value: "dnses", label: "多DNS提供商" },
|
||||
{ value: "auto", label: "自动选择" },
|
||||
],
|
||||
},
|
||||
required: true,
|
||||
|
@ -73,6 +74,7 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
|
|||
2. <b>CNAME代理验证</b>:支持任何注册商的域名,第一次需要手动添加CNAME记录(建议将DNS服务器修改为阿里云/腾讯云的,然后使用DNS直接验证)
|
||||
3. <b>HTTP文件验证</b>:不支持泛域名,需要配置网站文件上传
|
||||
4. <b>多DNS提供商</b>:每个域名可以选择独立的DNS提供商
|
||||
5. <b>自动选择</b>:需要在[域名管理](#/certd/cert/domain)中事先配置好校验方式
|
||||
`,
|
||||
})
|
||||
challengeType!: string;
|
||||
|
@ -408,7 +410,11 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
|
|||
let dnsProvider: IDnsProvider = null;
|
||||
let domainsVerifyPlan: DomainsVerifyPlan = null;
|
||||
if (this.challengeType === "cname" || this.challengeType === "http" || this.challengeType === "dnses") {
|
||||
domainsVerifyPlan = await this.createDomainsVerifyPlan();
|
||||
domainsVerifyPlan = await this.createDomainsVerifyPlan(this.domainsVerifyPlan);
|
||||
}
|
||||
if (this.challengeType === "auto") {
|
||||
const planInput = await this.buildVerifyPlanInputByAuto();
|
||||
domainsVerifyPlan = await this.createDomainsVerifyPlan(planInput);
|
||||
} else {
|
||||
const dnsProviderType = this.dnsProviderType;
|
||||
const access = await this.getAccess(this.dnsProviderAccess);
|
||||
|
@ -451,10 +457,10 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
|
|||
});
|
||||
}
|
||||
|
||||
async createDomainsVerifyPlan(): Promise<DomainsVerifyPlan> {
|
||||
async createDomainsVerifyPlan(verifyPlanSetting: DomainsVerifyPlanInput): Promise<DomainsVerifyPlan> {
|
||||
const plan: DomainsVerifyPlan = {};
|
||||
for (const domain in this.domainsVerifyPlan) {
|
||||
const domainVerifyPlan = this.domainsVerifyPlan[domain];
|
||||
for (const domain in verifyPlanSetting) {
|
||||
const domainVerifyPlan = verifyPlanSetting[domain];
|
||||
let dnsProvider = null;
|
||||
const cnameVerifyPlan: Record<string, CnameVerifyPlan> = {};
|
||||
const httpVerifyPlan: Record<string, HttpVerifyPlan> = {};
|
||||
|
@ -511,6 +517,66 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
|
|||
}
|
||||
return plan;
|
||||
}
|
||||
|
||||
private async buildVerifyPlanInputByAuto() {
|
||||
//从数据库里面自动选择校验方式
|
||||
// domain list
|
||||
const domainList = new Set<string>();
|
||||
//整理域名
|
||||
for (let domain in this.domains) {
|
||||
domain = domain.replaceAll("*.", "");
|
||||
domainList.add(domain);
|
||||
}
|
||||
const domainVerifierGetter: IDomainVerifierGetter = await this.ctx.serviceGetter.get("DomainVerifierGetter");
|
||||
|
||||
const verifiers = await domainVerifierGetter.getVerifiers([...domainList]);
|
||||
|
||||
const verifyPlanInput: DomainsVerifyPlanInput = {};
|
||||
|
||||
for (const verifier of verifiers) {
|
||||
const domain = verifier.domain;
|
||||
const mainDomain = verifier.mainDomain;
|
||||
let plan = verifyPlanInput[mainDomain];
|
||||
if (!plan) {
|
||||
plan = {
|
||||
domain: mainDomain,
|
||||
type: "cname",
|
||||
};
|
||||
verifyPlanInput[mainDomain] = plan;
|
||||
}
|
||||
if (verifier.challengeType === "cname") {
|
||||
verifyPlanInput[domain] = {
|
||||
type: "cname",
|
||||
domain: domain,
|
||||
cnameVerifyPlan: {
|
||||
[domain]: {
|
||||
id: 0,
|
||||
status: "validate",
|
||||
},
|
||||
},
|
||||
};
|
||||
} else if (verifier.challengeType === "http") {
|
||||
//http
|
||||
const http = verifier.http;
|
||||
verifyPlanInput[domain] = {
|
||||
type: "http",
|
||||
domain: domain,
|
||||
httpVerifyPlan: {
|
||||
[domain]: {
|
||||
domain: domain,
|
||||
httpUploaderType: http.httpUploaderType,
|
||||
httpUploaderAccess: http.httpUploaderAccess,
|
||||
httpUploadRootDir: http.httpUploadRootDir,
|
||||
},
|
||||
},
|
||||
};
|
||||
} else {
|
||||
//dns
|
||||
}
|
||||
}
|
||||
|
||||
return verifyPlanInput;
|
||||
}
|
||||
}
|
||||
|
||||
new CertApplyPlugin();
|
||||
|
|
|
@ -9,9 +9,9 @@ export const Dicts = {
|
|||
}),
|
||||
challengeTypeDict: dict({
|
||||
data: [
|
||||
{ value: "dns", label: "DNS校验" },
|
||||
{ value: "cname", label: "CNAME代理校验" },
|
||||
{ value: "http", label: "HTTP校验" },
|
||||
{ value: "dns", label: "DNS校验", color: "green" },
|
||||
{ value: "cname", label: "CNAME代理校验", color: "blue" },
|
||||
{ value: "http", label: "HTTP校验", color: "yellow" },
|
||||
],
|
||||
}),
|
||||
dnsProviderTypeDict: dict({
|
||||
|
|
|
@ -55,6 +55,14 @@ export function createAccessApi(from = "user") {
|
|||
});
|
||||
},
|
||||
|
||||
async GetDictByIds(ids: number[]) {
|
||||
return await request({
|
||||
url: apiPrefix + "/getDictByIds",
|
||||
method: "post",
|
||||
data: { ids },
|
||||
});
|
||||
},
|
||||
|
||||
async GetSecretPlain(id: number, key: string) {
|
||||
return await request({
|
||||
url: apiPrefix + "/getSecretPlain",
|
||||
|
|
|
@ -5,8 +5,9 @@ import { useRouter } from "vue-router";
|
|||
import { AddReq, compute, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
|
||||
import { useUserStore } from "/@/store/user";
|
||||
import { useSettingStore } from "/@/store/settings";
|
||||
import { message } from "ant-design-vue";
|
||||
import { Dicts } from "/@/components/plugins/lib/dicts";
|
||||
import { createAccessApi } from "/@/views/certd/access/api";
|
||||
|
||||
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||
const router = useRouter();
|
||||
const { t } = useI18n();
|
||||
|
@ -32,6 +33,21 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
const selectedRowKeys: Ref<any[]> = ref([]);
|
||||
context.selectedRowKeys = selectedRowKeys;
|
||||
|
||||
const accessApi = createAccessApi();
|
||||
const accessDict = dict({
|
||||
value: "id",
|
||||
label: "name",
|
||||
url: "accessDict",
|
||||
async getNodesByValues(ids: number[]) {
|
||||
return await accessApi.GetDictByIds(ids);
|
||||
},
|
||||
});
|
||||
|
||||
const httpUploaderTypeDict = Dicts.uploaderTypeDict;
|
||||
|
||||
const dnsProviderTypeDict = dict({
|
||||
url: "pi/dnsProvider/dnsProviderTypeDict",
|
||||
});
|
||||
return {
|
||||
crudOptions: {
|
||||
settings: {
|
||||
|
@ -90,6 +106,9 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
disabled: false,
|
||||
},
|
||||
},
|
||||
column: {
|
||||
sorter: true,
|
||||
},
|
||||
},
|
||||
challengeType: {
|
||||
title: t("certd.domain.challengeType"),
|
||||
|
@ -98,6 +117,9 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
form: {
|
||||
required: true,
|
||||
},
|
||||
column: {
|
||||
sorter: true,
|
||||
},
|
||||
},
|
||||
/**
|
||||
* challengeType varchar(50),
|
||||
|
@ -109,7 +131,8 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
*/
|
||||
dnsProviderType: {
|
||||
title: t("certd.domain.dnsProviderType"),
|
||||
type: "text",
|
||||
type: "dict-select",
|
||||
dict: dnsProviderTypeDict,
|
||||
form: {
|
||||
component: {
|
||||
name: "DnsProviderSelector",
|
||||
|
@ -119,10 +142,17 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
}),
|
||||
required: true,
|
||||
},
|
||||
column: {
|
||||
show: false,
|
||||
component: {
|
||||
color: "auto",
|
||||
},
|
||||
},
|
||||
},
|
||||
dnsProviderAccess: {
|
||||
title: t("certd.domain.dnsProviderAccess"),
|
||||
type: "text",
|
||||
type: "dict-select",
|
||||
dict: accessDict,
|
||||
form: {
|
||||
component: {
|
||||
name: "AccessSelector",
|
||||
|
@ -136,10 +166,16 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
}),
|
||||
required: true,
|
||||
},
|
||||
column: {
|
||||
show: false,
|
||||
component: {
|
||||
color: "auto",
|
||||
},
|
||||
},
|
||||
},
|
||||
httpUploaderType: {
|
||||
title: t("certd.domain.httpUploaderType"),
|
||||
type: "dict-text",
|
||||
type: "dict-select",
|
||||
dict: Dicts.uploaderTypeDict,
|
||||
form: {
|
||||
show: compute(({ form }) => {
|
||||
|
@ -147,6 +183,12 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
}),
|
||||
required: true,
|
||||
},
|
||||
column: {
|
||||
show: false,
|
||||
component: {
|
||||
color: "auto",
|
||||
},
|
||||
},
|
||||
},
|
||||
httpUploaderAccess: {
|
||||
title: t("certd.domain.httpUploaderAccess"),
|
||||
|
@ -160,6 +202,12 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
}),
|
||||
required: true,
|
||||
},
|
||||
column: {
|
||||
show: false,
|
||||
component: {
|
||||
color: "auto",
|
||||
},
|
||||
},
|
||||
},
|
||||
httpUploadRootDir: {
|
||||
title: t("certd.domain.httpUploadRootDir"),
|
||||
|
@ -170,14 +218,47 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
}),
|
||||
required: true,
|
||||
},
|
||||
column: {
|
||||
show: false,
|
||||
component: {
|
||||
color: "auto",
|
||||
},
|
||||
},
|
||||
},
|
||||
challengeSetting: {
|
||||
title: "校验配置",
|
||||
type: "text",
|
||||
form: { show: false },
|
||||
column: {
|
||||
width: 400,
|
||||
conditionalRender: false,
|
||||
cellRender({ row }) {
|
||||
if (row.challengeType === "dns") {
|
||||
return (
|
||||
<div class={"flex"}>
|
||||
<fs-values-format modelValue={row.dnsProviderType} dict={dnsProviderTypeDict} color={"auto"}></fs-values-format>
|
||||
<fs-values-format class={"ml-5"} modelValue={row.dnsProviderAccess} dict={accessDict} color={"auto"}></fs-values-format>
|
||||
</div>
|
||||
);
|
||||
} else if (row.challengeType === "http") {
|
||||
return (
|
||||
<div class={"flex"}>
|
||||
<fs-values-format modelValue={row.httpUploaderType} dict={httpUploaderTypeDict} color={"auto"}></fs-values-format>
|
||||
<fs-values-format class={"ml-5"} modelValue={row.httpUploaderAccess} dict={accessDict} color={"auto"}></fs-values-format>
|
||||
<a-tag class={"ml-5"}>{row.httpUploadRootDir}</a-tag>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
disabled: {
|
||||
title: t("certd.domain.disabled"),
|
||||
type: "dict-switch",
|
||||
dict: dict({
|
||||
data: [
|
||||
{ label: "启用", value: false },
|
||||
{ label: "禁用", value: true },
|
||||
{ label: "启用", value: false, color: "green" },
|
||||
{ label: "禁用", value: true, color: "red" },
|
||||
],
|
||||
}),
|
||||
form: {
|
||||
|
@ -185,7 +266,8 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
required: true,
|
||||
},
|
||||
column: {
|
||||
width: 80,
|
||||
width: 100,
|
||||
sorter: true,
|
||||
},
|
||||
},
|
||||
createTime: {
|
||||
|
|
|
@ -101,4 +101,10 @@ export class AccessController extends CrudController<AccessService> {
|
|||
const res = await this.service.getSimpleInfo(id);
|
||||
return this.ok(res);
|
||||
}
|
||||
|
||||
@Post('/getDictByIds', { summary: Constants.per.authOnly })
|
||||
async getDictByIds(@Body('ids') ids: number[]) {
|
||||
const res = await this.service.getSimpleByIds(ids, this.getUserId());
|
||||
return this.ok(res);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue