mirror of https://github.com/certd/certd
perf: cname 域名映射记录可读性优化
parent
7ad4b55ee0
commit
b1117ed54a
|
@ -9,7 +9,7 @@ export * from './util.merge.js';
|
||||||
export * from './util.cache.js';
|
export * from './util.cache.js';
|
||||||
import sleep from './util.sleep.js';
|
import sleep from './util.sleep.js';
|
||||||
import { http } from './util.request.js';
|
import { http } from './util.request.js';
|
||||||
import { nanoid } from 'nanoid';
|
|
||||||
import { mergeUtils } from './util.merge.js';
|
import { mergeUtils } from './util.merge.js';
|
||||||
import { sp } from './util.sp.js';
|
import { sp } from './util.sp.js';
|
||||||
import { hashUtils } from './util.hash.js';
|
import { hashUtils } from './util.hash.js';
|
||||||
|
@ -20,7 +20,8 @@ import { cache } from './util.cache.js';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { domainUtils } from './util.domain.js';
|
import { domainUtils } from './util.domain.js';
|
||||||
import { optionsUtils } from './util.options.js';
|
import { optionsUtils } from './util.options.js';
|
||||||
|
import { nanoid } from 'nanoid';
|
||||||
|
import * as id from './util.id.js';
|
||||||
export const utils = {
|
export const utils = {
|
||||||
sleep,
|
sleep,
|
||||||
http,
|
http,
|
||||||
|
@ -32,6 +33,7 @@ export const utils = {
|
||||||
mergeUtils,
|
mergeUtils,
|
||||||
cache,
|
cache,
|
||||||
nanoid,
|
nanoid,
|
||||||
|
id,
|
||||||
dayjs,
|
dayjs,
|
||||||
domain: domainUtils,
|
domain: domainUtils,
|
||||||
options: optionsUtils,
|
options: optionsUtils,
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
import { customAlphabet } from 'nanoid';
|
||||||
|
|
||||||
|
export const simpleNanoId = customAlphabet('1234567890abcdefghijklmopqrstuvwxyz', 10);
|
|
@ -12,13 +12,18 @@ export class PlusService {
|
||||||
plusServerBaseUrls: string[];
|
plusServerBaseUrls: string[];
|
||||||
|
|
||||||
async getPlusRequestService() {
|
async getPlusRequestService() {
|
||||||
const installInfo: SysInstallInfo = await this.sysSettingsService.getSetting(SysInstallInfo);
|
const subjectId = await this.getSubjectId();
|
||||||
return new PlusRequestService({
|
return new PlusRequestService({
|
||||||
plusServerBaseUrls: this.plusServerBaseUrls,
|
plusServerBaseUrls: this.plusServerBaseUrls,
|
||||||
subjectId: installInfo.siteId,
|
subjectId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getSubjectId() {
|
||||||
|
const installInfo: SysInstallInfo = await this.sysSettingsService.getSetting(SysInstallInfo);
|
||||||
|
return installInfo.siteId;
|
||||||
|
}
|
||||||
|
|
||||||
async requestWithoutSign(config: any) {
|
async requestWithoutSign(config: any) {
|
||||||
const plusRequestService = await this.getPlusRequestService();
|
const plusRequestService = await this.getPlusRequestService();
|
||||||
return await plusRequestService.requestWithoutSign(config);
|
return await plusRequestService.requestWithoutSign(config);
|
||||||
|
|
|
@ -26,10 +26,10 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ant-design/colors": "^7.0.2",
|
"@ant-design/colors": "^7.0.2",
|
||||||
"@ant-design/icons-vue": "^6.1.0",
|
"@ant-design/icons-vue": "^6.1.0",
|
||||||
"@fast-crud/fast-crud": "^1.22.2",
|
"@fast-crud/fast-crud": "^1.22.3",
|
||||||
"@fast-crud/fast-extends": "^1.22.2",
|
"@fast-crud/fast-extends": "^1.22.3",
|
||||||
"@fast-crud/ui-antdv4": "^1.22.2",
|
"@fast-crud/ui-antdv4": "^1.22.3",
|
||||||
"@fast-crud/ui-interface": "^1.22.2",
|
"@fast-crud/ui-interface": "^1.22.3",
|
||||||
"@iconify/vue": "^4.1.1",
|
"@iconify/vue": "^4.1.1",
|
||||||
"@soerenmartius/vue3-clipboard": "^0.1.2",
|
"@soerenmartius/vue3-clipboard": "^0.1.2",
|
||||||
"@vue-js-cron/light": "^4.0.5",
|
"@vue-js-cron/light": "^4.0.5",
|
||||||
|
|
|
@ -15,7 +15,11 @@
|
||||||
<fs-values-format v-model="cnameRecord.status" :dict="statusDict" />
|
<fs-values-format v-model="cnameRecord.status" :dict="statusDict" />
|
||||||
</td>
|
</td>
|
||||||
<td class="center">
|
<td class="center">
|
||||||
<a-button v-if="cnameRecord.status !== 'valid'" type="primary" size="small" :loading="loading" @click="doVerify">点击验证</a-button>
|
<template v-if="cnameRecord.status !== 'valid'">
|
||||||
|
<a-button type="primary" size="small" :loading="loading" @click="doVerify">点击验证</a-button>
|
||||||
|
<cname-tip :record="cnameRecord"></cname-tip>
|
||||||
|
</template>
|
||||||
|
|
||||||
<div v-else class="helper">不要删除CNAME</div>
|
<div v-else class="helper">不要删除CNAME</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -27,6 +31,7 @@ import { CnameRecord, GetByDomain } from "/@/components/plugins/cert/domains-ver
|
||||||
import { ref, watch } from "vue";
|
import { ref, watch } from "vue";
|
||||||
import { dict } from "@fast-crud/fast-crud";
|
import { dict } from "@fast-crud/fast-crud";
|
||||||
import * as api from "./api.js";
|
import * as api from "./api.js";
|
||||||
|
import CnameTip from "./cname-tip.vue";
|
||||||
const statusDict = dict({
|
const statusDict = dict({
|
||||||
data: [
|
data: [
|
||||||
{ label: "待设置CNAME", value: "cname", color: "warning" },
|
{ label: "待设置CNAME", value: "cname", color: "warning" },
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
<template>
|
||||||
|
<a-tooltip :overlay-style="{ maxWidth: '400px' }">
|
||||||
|
<template #title>
|
||||||
|
<div>
|
||||||
|
<div>多试几次,如果仍然无法验证通过,请按如下步骤排查问题:</div>
|
||||||
|
<div>1. 解析记录应该添加在{{ record.domain }}域名下</div>
|
||||||
|
<div>2. 要添加的是CNAME类型的记录,不是TXT</div>
|
||||||
|
<div>3. 核对记录值是否是:{{ record.recordValue }}</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<fs-icon class="ml-5 pointer" icon="mingcute:question-line"></fs-icon>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
const props = defineProps<{
|
||||||
|
record: any;
|
||||||
|
}>();
|
||||||
|
</script>
|
|
@ -64,18 +64,22 @@ const steps = ref<Step[]>([
|
||||||
{
|
{
|
||||||
image: "/static/doc/images/3-add-success.png",
|
image: "/static/doc/images/3-add-success.png",
|
||||||
title: "流水线创建成功",
|
title: "流水线创建成功",
|
||||||
descriptions: ["此时证书申请任务已经建好", "点击手动触发即可测试证书申请", "接下来演示如何添加部署任务"]
|
descriptions: ["点击手动触发即可申请证书"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "接下来演示如何自动部署证书",
|
||||||
|
descriptions: ["如果您只需要申请证书,那么到这一步就可以了"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "添加部署证书任务",
|
title: "添加部署证书任务",
|
||||||
description: "演示部署到主机上的Nginx",
|
description: "这里演示部署证书到Nginx",
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
image: "/static/doc/images/5-1-add-host.png",
|
image: "/static/doc/images/5-1-add-host.png",
|
||||||
title: "添加nginx部署任务",
|
title: "添加证书部署任务",
|
||||||
descriptions: ["演示第一个部署任务,部署到nginx"]
|
descriptions: ["这里演示自动部署证书到nginx", "Certd提供茫茫多的部署插件,满足您的各种部署需求"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
image: "/static/doc/images/5-2-add-host.png",
|
image: "/static/doc/images/5-2-add-host.png",
|
||||||
|
@ -94,8 +98,8 @@ const steps = ref<Step[]>([
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
image: "/static/doc/images/5-5-plugin-list.png",
|
image: "/static/doc/images/5-5-plugin-list.png",
|
||||||
title: "还可以添加其他更多部署任务",
|
title: "本系统提供茫茫多的部署插件",
|
||||||
descriptions: ["插件列表"]
|
descriptions: ["您可以根据自身需求将证书部署到各种应用和平台"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -155,7 +155,7 @@ function openUpgrade() {
|
||||||
title = "续期专业版/升级商业版";
|
title = "续期专业版/升级商业版";
|
||||||
}
|
}
|
||||||
|
|
||||||
modal.confirm({
|
const modalRef = modal.confirm({
|
||||||
title,
|
title,
|
||||||
async onOk() {
|
async onOk() {
|
||||||
return await doActive();
|
return await doActive();
|
||||||
|
@ -206,6 +206,10 @@ function openUpgrade() {
|
||||||
</a-col>
|
</a-col>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
function goAccount() {
|
||||||
|
router.push("/sys/account");
|
||||||
|
modalRef.destroy();
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<div class="mt-10 mb-10 vip-active-modal">
|
<div class="mt-10 mb-10 vip-active-modal">
|
||||||
<div class="vip-type-vs">
|
<div class="vip-type-vs">
|
||||||
|
@ -226,6 +230,9 @@ function openUpgrade() {
|
||||||
没有激活码?
|
没有激活码?
|
||||||
{activationCodeGetWay}
|
{activationCodeGetWay}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="mt-10">
|
||||||
|
激活码使用过一次之后,不可再次使用,如果要更换站点,请<a onClick={goAccount}>绑定账号</a>,然后"转移VIP"即可
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -165,7 +165,7 @@ onMounted(async () => {
|
||||||
await settingStore.checkUrlBound();
|
await settingStore.checkUrlBound();
|
||||||
});
|
});
|
||||||
|
|
||||||
function menuClick(menu) {
|
function menuClick(menu: any) {
|
||||||
routerUtils.open(menu.path);
|
routerUtils.open(menu.path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, Edi
|
||||||
import { useUserStore } from "/@/store/modules/user";
|
import { useUserStore } from "/@/store/modules/user";
|
||||||
import { useSettingStore } from "/@/store/modules/settings";
|
import { useSettingStore } from "/@/store/modules/settings";
|
||||||
import { message } from "ant-design-vue";
|
import { message } from "ant-design-vue";
|
||||||
|
import CnameTip from "/@/components/plugins/cert/domains-verify-plan-editor/cname-tip.vue";
|
||||||
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
@ -126,11 +126,18 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||||
component: {
|
component: {
|
||||||
onDictChange: ({ form, dict }: any) => {
|
onDictChange: ({ form, dict }: any) => {
|
||||||
if (!form.cnameProviderId) {
|
if (!form.cnameProviderId) {
|
||||||
const item = dict.data.find((item: any) => item.isDefault);
|
const item = dict.data.find((item: any) => item.isDefault && !item.disabled);
|
||||||
if (item) {
|
if (item) {
|
||||||
form.cnameProviderId = item.id;
|
form.cnameProviderId = item.id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
renderLabel(item: any) {
|
||||||
|
if (item.title) {
|
||||||
|
return `${item.domain}<${item.title}>`;
|
||||||
|
} else {
|
||||||
|
return item.domain;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
helper: {
|
helper: {
|
||||||
|
@ -147,7 +154,13 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
column: {
|
column: {
|
||||||
show: false
|
cellRender({ value }) {
|
||||||
|
if (value < 0) {
|
||||||
|
return <a-tag color={"green"}>公共CNAME</a-tag>;
|
||||||
|
} else {
|
||||||
|
return <a-tag color={"blue"}>自定义CNAME</a-tag>;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
status: {
|
status: {
|
||||||
|
@ -183,6 +196,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||||
if (row.status === "valid") {
|
if (row.status === "valid") {
|
||||||
return "-";
|
return "-";
|
||||||
}
|
}
|
||||||
|
|
||||||
async function doVerify() {
|
async function doVerify() {
|
||||||
row._validating_ = true;
|
row._validating_ = true;
|
||||||
try {
|
try {
|
||||||
|
@ -199,9 +213,12 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<a-button onClick={doVerify} loading={row._validating_} size={"small"} type={"primary"}>
|
<div>
|
||||||
点击验证
|
<a-button onClick={doVerify} loading={row._validating_} size={"small"} type={"primary"}>
|
||||||
</a-button>
|
点击验证
|
||||||
|
</a-button>
|
||||||
|
<CnameTip record={row} />
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ export class FileController extends BaseController {
|
||||||
}
|
}
|
||||||
const filePath = this.fileService.getFile(key, userId);
|
const filePath = this.fileService.getFile(key, userId);
|
||||||
this.ctx.response.attachment(filePath);
|
this.ctx.response.attachment(filePath);
|
||||||
|
this.ctx.response.set('Cache-Control', 'public,max-age=2592000');
|
||||||
await send(this.ctx, filePath);
|
await send(this.ctx, filePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ export class CnameProviderController extends BaseController {
|
||||||
@Post('/list', { summary: Constants.per.authOnly })
|
@Post('/list', { summary: Constants.per.authOnly })
|
||||||
async list(@Body(ALL) body: any) {
|
async list(@Body(ALL) body: any) {
|
||||||
body.userId = this.getUserId();
|
body.userId = this.getUserId();
|
||||||
const res = await this.providerService.find({});
|
const res = await this.providerService.list({});
|
||||||
return this.ok(res);
|
return this.ok(res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,8 @@ export class CnameRecordController extends CrudController<CnameRecordService> {
|
||||||
@Post('/list', { summary: Constants.per.authOnly })
|
@Post('/list', { summary: Constants.per.authOnly })
|
||||||
async list(@Body(ALL) body: any) {
|
async list(@Body(ALL) body: any) {
|
||||||
body.userId = this.getUserId();
|
body.userId = this.getUserId();
|
||||||
return super.list(body);
|
const list = await this.getService().list(body);
|
||||||
|
return this.ok(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('/add', { summary: Constants.per.authOnly })
|
@Post('/add', { summary: Constants.per.authOnly })
|
||||||
|
|
|
@ -34,4 +34,6 @@ export class CnameProviderEntity {
|
||||||
default: () => 'CURRENT_TIMESTAMP',
|
default: () => 'CURRENT_TIMESTAMP',
|
||||||
})
|
})
|
||||||
updateTime: Date;
|
updateTime: Date;
|
||||||
|
|
||||||
|
title: string;
|
||||||
}
|
}
|
|
@ -1,8 +1,9 @@
|
||||||
import { Provide, Scope, ScopeEnum } from '@midwayjs/core';
|
import { Provide, Scope, ScopeEnum } from '@midwayjs/core';
|
||||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
import { BaseService, ValidateException } from '@certd/lib-server';
|
import { BaseService, ListReq, ValidateException } from '@certd/lib-server';
|
||||||
import { CnameProviderEntity } from '../entity/cname_provider.js';
|
import { CnameProviderEntity } from '../entity/cname-provider.js';
|
||||||
|
import { CommonProviders } from './common-provider.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 授权
|
* 授权
|
||||||
|
@ -19,7 +20,7 @@ export class CnameProviderService extends BaseService<CnameProviderEntity> {
|
||||||
}
|
}
|
||||||
|
|
||||||
async getDefault() {
|
async getDefault() {
|
||||||
return await this.repository.findOne({ where: { isDefault: true } });
|
return await this.repository.findOne({ where: { isDefault: true, disabled: false } });
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 新增
|
* 新增
|
||||||
|
@ -80,10 +81,24 @@ export class CnameProviderService extends BaseService<CnameProviderEntity> {
|
||||||
if (def) {
|
if (def) {
|
||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
const founds = await this.repository.find({ take: 1, order: { createTime: 'DESC' } });
|
const founds = await this.repository.find({ take: 1, order: { createTime: 'DESC' }, where: { disabled: false } });
|
||||||
if (founds && founds.length > 0) {
|
if (founds && founds.length > 0) {
|
||||||
return founds[0];
|
return founds[0];
|
||||||
}
|
}
|
||||||
return null;
|
return CommonProviders[0] as CnameProviderEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
async list(req: ListReq): Promise<any[]> {
|
||||||
|
const list = await super.list(req);
|
||||||
|
|
||||||
|
return [...list, ...CommonProviders];
|
||||||
|
}
|
||||||
|
|
||||||
|
async info(id: any, infoIgnoreProperty?: any): Promise<any | null> {
|
||||||
|
if (id < 0) {
|
||||||
|
//使用公共provider
|
||||||
|
return CommonProviders.find(p => p.id === id);
|
||||||
|
}
|
||||||
|
return await super.info(id, infoIgnoreProperty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core';
|
import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core';
|
||||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
import { BaseService, ValidateException } from '@certd/lib-server';
|
import { BaseService, PlusService, ValidateException } from '@certd/lib-server';
|
||||||
import { CnameRecordEntity, CnameRecordStatusType } from '../entity/cname-record.js';
|
import { CnameRecordEntity, CnameRecordStatusType } from '../entity/cname-record.js';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
|
||||||
import { createDnsProvider, IDnsProvider, parseDomain } from '@certd/plugin-cert';
|
import { createDnsProvider, IDnsProvider, parseDomain } from '@certd/plugin-cert';
|
||||||
import { cache, CnameProvider, http, logger, utils } from '@certd/pipeline';
|
import { cache, CnameProvider, http, logger, utils } from '@certd/pipeline';
|
||||||
import { AccessService } from '../../pipeline/service/access-service.js';
|
import { AccessService } from '../../pipeline/service/access-service.js';
|
||||||
import { isDev } from '../../../utils/env.js';
|
import { isDev } from '../../../utils/env.js';
|
||||||
import { walkTxtRecord } from '@certd/acme-client';
|
import { walkTxtRecord } from '@certd/acme-client';
|
||||||
import { CnameProviderService } from './cname-provider-service.js';
|
import { CnameProviderService } from './cname-provider-service.js';
|
||||||
import { CnameProviderEntity } from '../entity/cname_provider.js';
|
import { CnameProviderEntity } from '../entity/cname-provider.js';
|
||||||
|
import { CommonDnsProvider } from './common-provider.js';
|
||||||
|
|
||||||
type CnameCheckCacheValue = {
|
type CnameCheckCacheValue = {
|
||||||
validating: boolean;
|
validating: boolean;
|
||||||
|
@ -34,6 +34,10 @@ export class CnameRecordService extends BaseService<CnameRecordEntity> {
|
||||||
|
|
||||||
@Inject()
|
@Inject()
|
||||||
accessService: AccessService;
|
accessService: AccessService;
|
||||||
|
|
||||||
|
@Inject()
|
||||||
|
plusService: PlusService;
|
||||||
|
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
getRepository() {
|
getRepository() {
|
||||||
return this.repository;
|
return this.repository;
|
||||||
|
@ -85,8 +89,8 @@ export class CnameRecordService extends BaseService<CnameRecordEntity> {
|
||||||
}
|
}
|
||||||
param.hostRecord = hostRecord;
|
param.hostRecord = hostRecord;
|
||||||
|
|
||||||
const cnameKey = uuidv4().replaceAll('-', '');
|
const cnameKey = utils.id.simpleNanoId();
|
||||||
param.recordValue = `${cnameKey}.${cnameProvider.domain}`;
|
param.recordValue = `${param.domain}.${cnameKey}.${cnameProvider.domain}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
async update(param: any) {
|
async update(param: any) {
|
||||||
|
@ -189,6 +193,15 @@ export class CnameRecordService extends BaseService<CnameRecordEntity> {
|
||||||
if (cnameProvider == null) {
|
if (cnameProvider == null) {
|
||||||
throw new ValidateException(`CNAME服务:${bean.cnameProviderId} 已被删除,请修改CNAME记录,重新选择CNAME服务`);
|
throw new ValidateException(`CNAME服务:${bean.cnameProviderId} 已被删除,请修改CNAME记录,重新选择CNAME服务`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cnameProvider.id < 0) {
|
||||||
|
//公共CNAME
|
||||||
|
return new CommonDnsProvider({
|
||||||
|
config: cnameProvider,
|
||||||
|
plusService: this.plusService,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const access = await this.accessService.getById(cnameProvider.accessId, cnameProvider.userId);
|
const access = await this.accessService.getById(cnameProvider.accessId, cnameProvider.userId);
|
||||||
const context = { access, logger, http, utils };
|
const context = { access, logger, http, utils };
|
||||||
const dnsProvider: IDnsProvider = await createDnsProvider({
|
const dnsProvider: IDnsProvider = await createDnsProvider({
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
import { CreateRecordOptions, DnsProviderContext, IDnsProvider, RemoveRecordOptions } from '@certd/plugin-cert';
|
||||||
|
import { PlusService } from '@certd/lib-server';
|
||||||
|
|
||||||
|
export type CnameProvider = {
|
||||||
|
id: number;
|
||||||
|
domain: string;
|
||||||
|
title: string;
|
||||||
|
};
|
||||||
|
export const CommonProviders = [
|
||||||
|
{
|
||||||
|
id: -1,
|
||||||
|
domain: 'cname.certd.com.cn',
|
||||||
|
title: '公共CNAME服务',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export class CommonDnsProvider implements IDnsProvider {
|
||||||
|
ctx: DnsProviderContext;
|
||||||
|
config: CnameProvider;
|
||||||
|
plusService: PlusService;
|
||||||
|
|
||||||
|
constructor(opts: { config: CnameProvider; plusService: PlusService }) {
|
||||||
|
this.config = opts.config;
|
||||||
|
this.plusService = opts.plusService;
|
||||||
|
}
|
||||||
|
|
||||||
|
async onInstance() {}
|
||||||
|
async createRecord(options: CreateRecordOptions) {
|
||||||
|
if (!this.config.domain.endsWith(options.domain)) {
|
||||||
|
throw new Error('cname服务域名不匹配');
|
||||||
|
}
|
||||||
|
const res = await this.plusService.requestWithoutSign({
|
||||||
|
url: '/activation/certd/cname/recordCreate',
|
||||||
|
data: {
|
||||||
|
subjectId: this.plusService.getSubjectId(),
|
||||||
|
domain: options.domain,
|
||||||
|
hostRecord: options.hostRecord,
|
||||||
|
recordValue: options.value,
|
||||||
|
providerId: this.config.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
async removeRecord(options: RemoveRecordOptions<any>) {
|
||||||
|
const res = await this.plusService.requestWithoutSign({
|
||||||
|
url: '/activation/certd/cname/recordRemove',
|
||||||
|
data: {
|
||||||
|
subjectId: this.plusService.getSubjectId(),
|
||||||
|
domain: options.recordReq.domain,
|
||||||
|
hostRecord: options.recordReq.hostRecord,
|
||||||
|
recordValue: options.recordReq.value,
|
||||||
|
recordId: options.recordRes.id,
|
||||||
|
providerId: this.config.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
setCtx(ctx: DnsProviderContext): void {
|
||||||
|
this.ctx = ctx;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue