mirror of
https://github.com/certd/certd.git
synced 2026-10-13 15:49:25 +08:00
perf(monitor): 站点证书监控支持手动选中触发检查
This commit is contained in:
@@ -19,6 +19,7 @@ export default {
|
||||
subdomainConfirmContent: "{domain} appears to be a subdomain. Only delegated subdomains and free second-level subdomains need to be maintained here. Otherwise certificate application may fail. Continue?",
|
||||
importFromProvider: "Import from Domain Provider",
|
||||
importFromResolveRecords: "Import from DNS Records",
|
||||
importFromResolveRecordsTooltip: "Import DNS records as monitoring sites",
|
||||
syncExpirationDate: "Sync Domain Expiration Time",
|
||||
syncTaskSubmitted: "Sync task submitted",
|
||||
syncExpirationProgress: "Sync Domain Expiration Progress",
|
||||
|
||||
@@ -7,6 +7,8 @@ export default {
|
||||
settingLink: "Site Monitoring Settings",
|
||||
limitInfo: "Basic edition limited to 1, professional and above unlimited, current",
|
||||
checkAll: "Check All",
|
||||
checkBatch: "Check Selected",
|
||||
batchCheckConfirm: "Check the {count} selected sites now?",
|
||||
checkNow: "Check Now",
|
||||
batchDelete: "Batch Delete",
|
||||
confirmTitle: "Confirm",
|
||||
|
||||
@@ -19,6 +19,7 @@ export default {
|
||||
subdomainConfirmContent: "检测到{domain}为子域名,只有托管子域名和免费二级子域名才需要在此处维护,否则会导致申请证书失败,请确认是否继续?",
|
||||
importFromProvider: "从域名提供商导入",
|
||||
importFromResolveRecords: "从解析记录导入",
|
||||
importFromResolveRecordsTooltip: "从域名的解析记录中导入并作为监控站点",
|
||||
syncExpirationDate: "同步域名过期时间",
|
||||
syncTaskSubmitted: "同步任务已提交",
|
||||
syncExpirationProgress: "同步域名过期时间进度",
|
||||
|
||||
@@ -7,6 +7,8 @@ export default {
|
||||
settingLink: "站点监控设置",
|
||||
limitInfo: "基础版限制1条,专业版以上无限制,当前",
|
||||
checkAll: "检查全部",
|
||||
checkBatch: "检查选中",
|
||||
batchCheckConfirm: "确认触发检查选中的{count}个站点吗?",
|
||||
checkNow: "立即检查",
|
||||
batchDelete: "批量删除",
|
||||
confirmTitle: "确认",
|
||||
|
||||
@@ -63,6 +63,13 @@ export const siteInfoApi = {
|
||||
method: "post",
|
||||
});
|
||||
},
|
||||
async CheckBatch(ids: number[]) {
|
||||
return await request({
|
||||
url: apiPrefix + "/checkBatch",
|
||||
method: "post",
|
||||
data: { ids },
|
||||
});
|
||||
},
|
||||
|
||||
async Import(form: any) {
|
||||
return await request({
|
||||
|
||||
@@ -100,6 +100,23 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
});
|
||||
}
|
||||
|
||||
function checkBatch() {
|
||||
if (selectedRowKeys.value.length === 0) {
|
||||
notification.error({ message: t("monitor.selectRecordsFirst") });
|
||||
return;
|
||||
}
|
||||
Modal.confirm({
|
||||
title: t("monitor.confirmTitle"),
|
||||
content: t("monitor.batchCheckConfirm", { count: selectedRowKeys.value.length }),
|
||||
onOk: async () => {
|
||||
await siteInfoApi.CheckBatch(selectedRowKeys.value);
|
||||
notification.success({ message: t("monitor.checkSubmitted") });
|
||||
selectedRowKeys.value = [];
|
||||
await crudExpose.doRefresh();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const GroupTypeSite = "site";
|
||||
const groupDictRef = createGroupDictRef(GroupTypeSite);
|
||||
|
||||
@@ -253,6 +270,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
show: hasActionPermission("write"),
|
||||
title: t("certd.domain.importFromResolveRecords"),
|
||||
text: t("certd.domain.importFromResolveRecords"),
|
||||
tooltip: { title: t("certd.domain.importFromResolveRecordsTooltip") },
|
||||
type: "primary",
|
||||
// needPlus: true,
|
||||
color: "gold",
|
||||
@@ -274,6 +292,15 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
checkAll();
|
||||
},
|
||||
},
|
||||
checkBatch: {
|
||||
show: true,
|
||||
text: t("monitor.checkBatch"),
|
||||
type: "primary",
|
||||
icon: "ion:play-forward-outline",
|
||||
click() {
|
||||
checkBatch();
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
rowHandle: {
|
||||
|
||||
@@ -134,6 +134,14 @@ export class SiteInfoController extends CrudController<SiteInfoService> {
|
||||
return this.ok();
|
||||
}
|
||||
|
||||
@Post("/checkBatch", { description: Constants.per.authOnly, summary: "批量检查站点监控" })
|
||||
async checkBatch(@Body(ALL) body: any) {
|
||||
const { projectId, userId } = await this.getProjectUserIdRead();
|
||||
const count = await this.service.checkBatch(body.ids, userId, projectId);
|
||||
this.auditLog({ content: `批量检查了${count}条站点监控` });
|
||||
return this.ok({ count });
|
||||
}
|
||||
|
||||
@Post("/checkAll", { description: Constants.per.authOnly, summary: "检查所有站点监控" })
|
||||
async checkAll() {
|
||||
const { projectId, userId } = await this.getProjectUserIdWrite();
|
||||
|
||||
@@ -324,6 +324,23 @@ export class SiteInfoService extends BaseService<SiteInfoEntity> {
|
||||
return;
|
||||
}
|
||||
|
||||
async checkBatch(ids: number[], userId: number, projectId?: number) {
|
||||
const validIds = this.filterIds(ids);
|
||||
if (validIds.length === 0) {
|
||||
return 0;
|
||||
}
|
||||
const userProjectQuery = this.buildUserProjectQuery(userId, projectId);
|
||||
const sites = await this.repository.find({
|
||||
where: {
|
||||
id: In(validIds),
|
||||
...userProjectQuery,
|
||||
disabled: false,
|
||||
},
|
||||
});
|
||||
await this.checkList(sites);
|
||||
return sites.length;
|
||||
}
|
||||
|
||||
async sendCheckErrorNotify(siteId: number, fromIpCheck = false, setting: UserSiteMonitorSetting) {
|
||||
const site = await this.info(siteId);
|
||||
const url = await this.notificationService.getBindUrl("#/certd/monitor/site");
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { BaseNotification, IsNotification, NotificationBody, NotificationInput } from "@certd/pipeline";
|
||||
import { stringUtils } from "@certd/basic";
|
||||
import qs from "qs";
|
||||
|
||||
@IsNotification({
|
||||
@@ -95,17 +96,6 @@ export class WebhookNotification extends BaseNotification {
|
||||
})
|
||||
skipSslVerify: boolean;
|
||||
|
||||
replaceTemplate(target: string, body: any, urlEncode = false) {
|
||||
let bodyStr = target;
|
||||
const keys = Object.keys(body);
|
||||
for (const key of keys) {
|
||||
let value = urlEncode ? encodeURIComponent(body[key]) : body[key];
|
||||
value = value.replaceAll(`\n`, "\\n");
|
||||
bodyStr = bodyStr.replaceAll(`{${key}}`, value);
|
||||
}
|
||||
return bodyStr;
|
||||
}
|
||||
|
||||
async send(body: NotificationBody) {
|
||||
if (!this.template) {
|
||||
throw new Error("模版不能为空");
|
||||
@@ -119,7 +109,7 @@ export class WebhookNotification extends BaseNotification {
|
||||
content: body.content,
|
||||
url: body.url,
|
||||
};
|
||||
const bodyStr = this.replaceTemplate(this.template, replaceBody);
|
||||
const bodyStr = stringUtils.replaceTemplate(this.template, replaceBody);
|
||||
let data = JSON.parse(bodyStr);
|
||||
|
||||
let url = this.webhook;
|
||||
|
||||
Reference in New Issue
Block a user