mirror of https://github.com/certd/certd
chore: domain manager
parent
c451823c2b
commit
f3002e4fb6
|
@ -33,6 +33,7 @@
|
|||
import { Ref, ref, watch, nextTick } from "vue";
|
||||
import { HttpRecord } from "/@/components/plugins/cert/domains-verify-plan-editor/type";
|
||||
import { dict } from "@fast-crud/fast-crud";
|
||||
import { Dicts } from "/@/components/plugins/lib/dicts";
|
||||
|
||||
defineOptions({
|
||||
name: "HttpVerifyPlan",
|
||||
|
@ -68,17 +69,7 @@ async function onRecordChange() {
|
|||
emit("change", records.value);
|
||||
}
|
||||
|
||||
const uploaderTypeDict = dict({
|
||||
data: [
|
||||
{ label: "SFTP", value: "sftp" },
|
||||
{ label: "FTP", value: "ftp" },
|
||||
{ label: "阿里云OSS", value: "alioss" },
|
||||
{ label: "腾讯云COS", value: "tencentcos" },
|
||||
{ label: "七牛OSS", value: "qiniuoss" },
|
||||
{ label: "S3/Minio", value: "s3" },
|
||||
{ label: "SSH(已废弃,请选择SFTP方式)", value: "ssh", disabled: true },
|
||||
],
|
||||
});
|
||||
const uploaderTypeDict = Dicts.uploaderTypeDict;
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
import { dict } from "@fast-crud/fast-crud";
|
||||
|
||||
export const Dicts = {
|
||||
sslProviderDict: dict({
|
||||
data: [
|
||||
{ value: "letsencrypt", label: "Let‘s Encrypt" },
|
||||
{ value: "zerossl", label: "ZeroSSL" },
|
||||
],
|
||||
}),
|
||||
challengeTypeDict: dict({ data: [{ value: "dns", label: "DNS校验" }] }),
|
||||
dnsProviderTypeDict: dict({
|
||||
url: "pi/dnsProvider/dnsProviderTypeDict",
|
||||
}),
|
||||
uploaderTypeDict: dict({
|
||||
data: [
|
||||
{ label: "SFTP", value: "sftp" },
|
||||
{ label: "FTP", value: "ftp" },
|
||||
{ label: "阿里云OSS", value: "alioss" },
|
||||
{ label: "腾讯云COS", value: "tencentcos" },
|
||||
{ label: "七牛OSS", value: "qiniuoss" },
|
||||
{ label: "S3/Minio", value: "s3" },
|
||||
{ label: "SSH(已废弃,请选择SFTP方式)", value: "ssh", disabled: true },
|
||||
],
|
||||
}),
|
||||
};
|
|
@ -708,4 +708,14 @@ export default {
|
|||
showRunStrategyHelper: "Allow modify the run strategy of the task",
|
||||
},
|
||||
},
|
||||
domain: {
|
||||
domainManager: "Domain Manager",
|
||||
domain: "Domain",
|
||||
challengeType: "Challenge Type",
|
||||
dnsProviderType: "DNS Provider Type",
|
||||
dnsProviderAccess: "DNS Provider Access",
|
||||
httpUploaderType: "HTTP Uploader Type",
|
||||
httpUploaderAccess: "HTTP Uploader Access",
|
||||
httpUploadRootDir: "HTTP Upload Root Dir",
|
||||
},
|
||||
};
|
||||
|
|
|
@ -711,4 +711,14 @@ export default {
|
|||
showRunStrategyHelper: "任务设置中是否允许选择运行策略",
|
||||
},
|
||||
},
|
||||
domain: {
|
||||
domainManager: "域名管理",
|
||||
domain: "域名",
|
||||
challengeType: "校验类型",
|
||||
dnsProviderType: "DNS提供商类型",
|
||||
dnsProviderAccess: "DNS提供商授权",
|
||||
httpUploaderType: "上传方式",
|
||||
httpUploaderAccess: "上传授权信息",
|
||||
httpUploadRootDir: "网站根路径",
|
||||
},
|
||||
};
|
||||
|
|
|
@ -116,6 +116,17 @@ export const certdResources = [
|
|||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.domain.domainManager",
|
||||
name: "DomainManager",
|
||||
path: "/certd/cert/domain",
|
||||
component: "/certd/cert/domain/index.vue",
|
||||
meta: {
|
||||
icon: "material-symbols:approval-delegation-outline",
|
||||
auth: true,
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.cnameRecord",
|
||||
name: "CnameRecord",
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
import { request } from "/src/api/service";
|
||||
|
||||
const apiPrefix = "/cert/domain";
|
||||
|
||||
export async function GetList(query: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/page",
|
||||
method: "post",
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
|
||||
export async function AddObj(obj: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/add",
|
||||
method: "post",
|
||||
data: obj,
|
||||
});
|
||||
}
|
||||
|
||||
export async function UpdateObj(obj: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/update",
|
||||
method: "post",
|
||||
data: obj,
|
||||
});
|
||||
}
|
||||
|
||||
export async function DelObj(id: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/delete",
|
||||
method: "post",
|
||||
params: { id },
|
||||
});
|
||||
}
|
||||
|
||||
export async function GetObj(id: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/info",
|
||||
method: "post",
|
||||
params: { id },
|
||||
});
|
||||
}
|
||||
|
||||
export async function GetDetail(id: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/detail",
|
||||
method: "post",
|
||||
params: { id },
|
||||
});
|
||||
}
|
||||
|
||||
export async function DeleteBatch(ids: any[]) {
|
||||
return await request({
|
||||
url: apiPrefix + "/deleteByIds",
|
||||
method: "post",
|
||||
data: { ids },
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,166 @@
|
|||
import * as api from "./api";
|
||||
import { useI18n } from "/src/locales";
|
||||
import { Ref, ref } from "vue";
|
||||
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";
|
||||
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||
const router = useRouter();
|
||||
const { t } = useI18n();
|
||||
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
|
||||
return await api.GetList(query);
|
||||
};
|
||||
const editRequest = async ({ form, row }: EditReq) => {
|
||||
form.id = row.id;
|
||||
const res = await api.UpdateObj(form);
|
||||
return res;
|
||||
};
|
||||
const delRequest = async ({ row }: DelReq) => {
|
||||
return await api.DelObj(row.id);
|
||||
};
|
||||
|
||||
const addRequest = async ({ form }: AddReq) => {
|
||||
const res = await api.AddObj(form);
|
||||
return res;
|
||||
};
|
||||
|
||||
const userStore = useUserStore();
|
||||
const settingStore = useSettingStore();
|
||||
const selectedRowKeys: Ref<any[]> = ref([]);
|
||||
context.selectedRowKeys = selectedRowKeys;
|
||||
|
||||
return {
|
||||
crudOptions: {
|
||||
settings: {
|
||||
plugins: {
|
||||
//这里使用行选择插件,生成行选择crudOptions配置,最终会与crudOptions合并
|
||||
rowSelection: {
|
||||
enabled: true,
|
||||
order: -2,
|
||||
before: true,
|
||||
// handle: (pluginProps,useCrudProps)=>CrudOptions,
|
||||
props: {
|
||||
multiple: true,
|
||||
crossPage: true,
|
||||
selectedRowKeys,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
request: {
|
||||
pageRequest,
|
||||
addRequest,
|
||||
editRequest,
|
||||
delRequest,
|
||||
},
|
||||
tabs: {
|
||||
name: "status",
|
||||
show: true,
|
||||
},
|
||||
rowHandle: {
|
||||
minWidth: 200,
|
||||
fixed: "right",
|
||||
},
|
||||
columns: {
|
||||
id: {
|
||||
title: "ID",
|
||||
key: "id",
|
||||
type: "number",
|
||||
column: {
|
||||
width: 80,
|
||||
},
|
||||
form: {
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
domain: {
|
||||
title: t("certd.domain.domain"),
|
||||
type: "text",
|
||||
search: {
|
||||
show: true,
|
||||
},
|
||||
editForm: {
|
||||
component: {
|
||||
disabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
challengeType: {
|
||||
title: t("certd.domain.challengeType"),
|
||||
type: "dict-select",
|
||||
form: {
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
/**
|
||||
* challengeType varchar(50),
|
||||
* dnsProviderType varchar(50),
|
||||
* dnsProviderAccess bigint,
|
||||
* httpUploaderType varchar(50),
|
||||
* httpUploaderAccess bigint,
|
||||
* httpUploadRootDir varchar(512),
|
||||
*/
|
||||
dnsProviderType: {
|
||||
title: t("certd.domain.dnsProviderType"),
|
||||
type: "text",
|
||||
form: {
|
||||
component: {
|
||||
name: "DnsProviderSelector",
|
||||
},
|
||||
},
|
||||
},
|
||||
dnsProviderAccess: {
|
||||
title: t("certd.domain.dnsProviderAccess"),
|
||||
type: "text",
|
||||
form: {
|
||||
component: {
|
||||
name: "AccessSelector",
|
||||
type: compute(({ form }) => {
|
||||
return form.dnsProviderType;
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
httpUploaderType: {
|
||||
title: t("certd.domain.httpUploaderType"),
|
||||
type: "dict-text",
|
||||
dict: Dicts.uploaderTypeDict,
|
||||
},
|
||||
httpUploaderAccess: {
|
||||
title: t("certd.domain.httpUploaderAccess"),
|
||||
type: "text",
|
||||
form: {
|
||||
component: {
|
||||
name: "AccessSelector",
|
||||
},
|
||||
},
|
||||
},
|
||||
createTime: {
|
||||
title: t("certd.create_time"),
|
||||
type: "datetime",
|
||||
form: {
|
||||
show: false,
|
||||
},
|
||||
column: {
|
||||
sorter: true,
|
||||
width: 160,
|
||||
align: "center",
|
||||
},
|
||||
},
|
||||
updateTime: {
|
||||
title: t("certd.update_time"),
|
||||
type: "datetime",
|
||||
form: {
|
||||
show: false,
|
||||
},
|
||||
column: {
|
||||
show: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
<template>
|
||||
<fs-page class="page-cert">
|
||||
<template #header>
|
||||
<div class="title">
|
||||
{{ t("certd.domain.domainManager") }}
|
||||
<span class="sub"> </span>
|
||||
</div>
|
||||
</template>
|
||||
<fs-crud ref="crudRef" v-bind="crudBinding">
|
||||
<template #pagination-left>
|
||||
<a-tooltip :title="t('certd.batch_delete')">
|
||||
<fs-button icon="DeleteOutlined" @click="handleBatchDelete"></fs-button>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</fs-crud>
|
||||
</fs-page>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onActivated, onMounted } from "vue";
|
||||
import { useFs } from "@fast-crud/fast-crud";
|
||||
import createCrudOptions from "./crud";
|
||||
import { message, Modal } from "ant-design-vue";
|
||||
import { DeleteBatch } from "./api";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
defineOptions({
|
||||
name: "DomainManager",
|
||||
});
|
||||
const { crudBinding, crudRef, crudExpose, context } = useFs({ createCrudOptions });
|
||||
|
||||
const selectedRowKeys = context.selectedRowKeys;
|
||||
const handleBatchDelete = () => {
|
||||
if (selectedRowKeys.value?.length > 0) {
|
||||
Modal.confirm({
|
||||
title: t("certd.confirm"),
|
||||
content: t("certd.confirm_delete_count", { count: selectedRowKeys.value.length }),
|
||||
async onOk() {
|
||||
await DeleteBatch(selectedRowKeys.value);
|
||||
message.info(t("certd.delete_successful"));
|
||||
crudExpose.doRefresh();
|
||||
selectedRowKeys.value = [];
|
||||
},
|
||||
});
|
||||
} else {
|
||||
message.error(t("certd.please_select_records"));
|
||||
}
|
||||
};
|
||||
|
||||
// 页面打开后获取列表数据
|
||||
onMounted(() => {
|
||||
crudExpose.doRefresh();
|
||||
});
|
||||
onActivated(async () => {
|
||||
await crudExpose.doRefresh();
|
||||
});
|
||||
</script>
|
||||
<style lang="less"></style>
|
|
@ -1,14 +0,0 @@
|
|||
import { dict } from "@fast-crud/fast-crud";
|
||||
|
||||
export const Dicts = {
|
||||
sslProviderDict: dict({
|
||||
data: [
|
||||
{ value: "letsencrypt", label: "Let‘s Encrypt" },
|
||||
{ value: "zerossl", label: "ZeroSSL" },
|
||||
],
|
||||
}),
|
||||
challengeTypeDict: dict({ data: [{ value: "dns", label: "DNS校验" }] }),
|
||||
dnsProviderTypeDict: dict({
|
||||
url: "pi/dnsProvider/dnsProviderTypeDict",
|
||||
}),
|
||||
};
|
|
@ -0,0 +1,19 @@
|
|||
CREATE TABLE "cd_domain"
|
||||
(
|
||||
"id" integer PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
"user_id" integer,
|
||||
"domain" varchar(1024),
|
||||
challenge_type varchar(50),
|
||||
dns_provider_type varchar(50),
|
||||
dns_provider_access bigint,
|
||||
http_uploader_type varchar(50),
|
||||
http_uploader_access bigint,
|
||||
http_upload_root_dir varchar(512),
|
||||
"disabled" boolean NOT NULL DEFAULT (false),
|
||||
"create_time" datetime NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
"update_time" datetime NOT NULL DEFAULT (CURRENT_TIMESTAMP)
|
||||
);
|
||||
|
||||
CREATE INDEX "index_domain_user_id" ON "cd_domain" ("user_id");
|
||||
CREATE INDEX "index_domain_domain" ON "cd_domain" ("domain");
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
import { ALL, Body, Controller, Inject, Post, Provide, Query } from '@midwayjs/core';
|
||||
import { Constants, CrudController } from '@certd/lib-server';
|
||||
import {DomainService} from "../../../modules/cert/service/domain-service.js";
|
||||
|
||||
/**
|
||||
* 授权
|
||||
*/
|
||||
@Provide()
|
||||
@Controller('/api/cert/domain')
|
||||
export class DomainController extends CrudController<DomainService> {
|
||||
@Inject()
|
||||
service: DomainService;
|
||||
|
||||
getService(): DomainService {
|
||||
return this.service;
|
||||
}
|
||||
|
||||
@Post('/page', { summary: Constants.per.authOnly })
|
||||
async page(@Body(ALL) body: any) {
|
||||
body.query = body.query ?? {};
|
||||
body.query.userId = this.getUserId();
|
||||
const domain = body.query.domain;
|
||||
delete body.query.domain;
|
||||
|
||||
const bq = qb => {
|
||||
if (domain) {
|
||||
qb.andWhere('domain like :domain', { domain: `%${domain}%` });
|
||||
}
|
||||
};
|
||||
|
||||
const pageRet = await this.getService().page({
|
||||
query: body.query,
|
||||
page: body.page,
|
||||
sort: body.sort,
|
||||
buildQuery: bq,
|
||||
});
|
||||
return this.ok(pageRet);
|
||||
}
|
||||
|
||||
@Post('/list', { summary: Constants.per.authOnly })
|
||||
async list(@Body(ALL) body: any) {
|
||||
body.query = body.query ?? {};
|
||||
body.query.userId = this.getUserId();
|
||||
const list = await this.getService().list(body);
|
||||
return this.ok(list);
|
||||
}
|
||||
|
||||
@Post('/add', { summary: Constants.per.authOnly })
|
||||
async add(@Body(ALL) bean: any) {
|
||||
bean.userId = this.getUserId();
|
||||
return super.add(bean);
|
||||
}
|
||||
|
||||
@Post('/update', { summary: Constants.per.authOnly })
|
||||
async update(@Body(ALL) bean: any) {
|
||||
await this.service.checkUserId(bean.id, this.getUserId());
|
||||
delete bean.userId;
|
||||
return super.update(bean);
|
||||
}
|
||||
|
||||
@Post('/info', { summary: Constants.per.authOnly })
|
||||
async info(@Query('id') id: number) {
|
||||
await this.service.checkUserId(id, this.getUserId());
|
||||
return super.info(id);
|
||||
}
|
||||
|
||||
@Post('/delete', { summary: Constants.per.authOnly })
|
||||
async delete(@Query('id') id: number) {
|
||||
await this.service.checkUserId(id, this.getUserId());
|
||||
return super.delete(id);
|
||||
}
|
||||
|
||||
@Post('/deleteByIds', { summary: Constants.per.authOnly })
|
||||
async deleteByIds(@Body(ALL) body: any) {
|
||||
await this.service.delete(body.ids, {
|
||||
userId: this.getUserId(),
|
||||
});
|
||||
return this.ok();
|
||||
}
|
||||
|
||||
}
|
|
@ -13,26 +13,26 @@ export class DomainEntity {
|
|||
@Column({ comment: '主域名', length: 100 })
|
||||
domain: string;
|
||||
|
||||
@Column({ comment: '校验类型', name: 'challenge_type', length: 100 })
|
||||
@Column({ comment: '校验类型', name: 'challenge_type', length: 50 })
|
||||
challengeType : string;
|
||||
|
||||
@Column({ comment: 'DNS提供商', name: 'dns_provider_type', length: 100 })
|
||||
@Column({ comment: 'DNS提供商', name: 'dns_provider_type', length: 50 })
|
||||
dnsProviderType: string;
|
||||
|
||||
@Column({ comment: 'DNS提供商授权', name: 'dns_provider_access', length: 200 })
|
||||
@Column({ comment: 'DNS提供商授权', name: 'dns_provider_access' })
|
||||
dnsProviderAccess: number;
|
||||
|
||||
@Column({ comment: '是否禁用', name: 'disabled' })
|
||||
disabled: boolean;
|
||||
|
||||
|
||||
@Column({ comment: 'http上传类型', name: 'http_uploader_type', length: 200 })
|
||||
@Column({ comment: 'http上传类型', name: 'http_uploader_type', length: 50 })
|
||||
httpUploaderType: string;
|
||||
|
||||
@Column({ comment: 'http上传授权', name: 'http_uploader_access', length: 200 })
|
||||
@Column({ comment: 'http上传授权', name: 'http_uploader_access' })
|
||||
httpUploaderAccess: number;
|
||||
|
||||
@Column({ comment: 'http上传根目录', name: 'http_upload_root_dir', length: 200 })
|
||||
@Column({ comment: 'http上传根目录', name: 'http_upload_root_dir', length: 512 })
|
||||
httpUploadRootDir: string;
|
||||
|
||||
@Column({
|
||||
|
|
Loading…
Reference in New Issue