chore: 优化站点ip检查

pull/409/head
xiaojunnuo 2025-05-28 15:12:54 +08:00
parent a463711b03
commit 41f4617e66
5 changed files with 132 additions and 15 deletions

View File

@ -136,6 +136,10 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
}, },
}, },
}, },
tabs: {
name: "disabled",
show: true,
},
columns: { columns: {
id: { id: {
title: "ID", title: "ID",
@ -210,6 +214,34 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
show: false, show: false,
}, },
}, },
certInfo: {
title: "证书信息",
type: "text",
form: { show: false },
column: {
width: 200,
sorter: false,
show: true,
conditionalRender: false,
cellRender({ value, row }) {
const slots = {
content() {
return (
<div>
<div>{row.certProvider}</div>
<div>{row.certDomains}</div>
</div>
);
},
};
return (
<a-popover placement="left" v-slots={slots} overlayStyle={{ maxWidth: "30%" }}>
{row.certDomains}
</a-popover>
);
},
},
},
certDomains: { certDomains: {
title: "证书域名", title: "证书域名",
search: { search: {
@ -222,7 +254,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
column: { column: {
width: 200, width: 200,
sorter: true, sorter: true,
show: true, show: false,
cellRender({ value }) { cellRender({ value }) {
return ( return (
<a-tooltip title={value} placement="left"> <a-tooltip title={value} placement="left">
@ -244,6 +276,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
column: { column: {
width: 200, width: 200,
sorter: true, sorter: true,
show: false,
cellRender({ value }) { cellRender({ value }) {
return <a-tooltip title={value}>{value}</a-tooltip>; return <a-tooltip title={value}>{value}</a-tooltip>;
}, },

View File

@ -31,6 +31,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
const addRequest = async (req: AddReq) => { const addRequest = async (req: AddReq) => {
const { form } = req; const { form } = req;
form.siteId = context.props.siteId;
const res = await api.AddObj(form); const res = await api.AddObj(form);
return res; return res;
}; };

View File

@ -68,8 +68,12 @@ export class SiteInfoController extends CrudController<SiteIpService> {
@Post('/delete', { summary: Constants.per.authOnly }) @Post('/delete', { summary: Constants.per.authOnly })
async delete(@Query('id') id: number) { async delete(@Query('id') id: number) {
const entity = await this.service.info(id);
await this.service.checkUserId(id, this.getUserId()); await this.service.checkUserId(id, this.getUserId());
return await super.delete(id);
const res = await super.delete(id);
await this.service.updateIpCount(entity.siteId)
return res
} }
@Post('/check', { summary: Constants.per.authOnly }) @Post('/check', { summary: Constants.per.authOnly })

View File

@ -13,6 +13,7 @@ import { UserSuiteService } from '@certd/commercial-core';
import { UserSettingsService } from "../../mine/service/user-settings-service.js"; import { UserSettingsService } from "../../mine/service/user-settings-service.js";
import { UserSiteMonitorSetting } from "../../mine/service/models.js"; import { UserSiteMonitorSetting } from "../../mine/service/models.js";
import {SiteIpService} from "./site-ip-service.js"; import {SiteIpService} from "./site-ip-service.js";
import {SiteIpEntity} from "../entity/site-ip.js";
@Provide() @Provide()
@Scope(ScopeEnum.Request, { allowDowngrade: true }) @Scope(ScopeEnum.Request, { allowDowngrade: true })
@ -134,9 +135,7 @@ export class SiteInfoService extends BaseService<SiteInfoEntity> {
//检查ip //检查ip
if( site.ipCheck){ await this.checkAllIp(site)
await this.siteIpService.checkAll(site)
}
if (!notify) { if (!notify) {
return; return;
@ -165,6 +164,43 @@ export class SiteInfoService extends BaseService<SiteInfoEntity> {
} }
} }
async checkAllIp(site:SiteInfoEntity){
if( !site.ipCheck){
return;
}
const certExpiresTime = site.certExpiresTime;
const onFinished = async (list:SiteIpEntity[])=>{
let errorCount = 0
let errorMessage = ""
for (const item of list) {
errorCount++
if(item.error){
errorMessage += `${item.ipAddress}${item.error} \n`
}else if(item.certExpiresTime!==certExpiresTime){
errorMessage += `${item.ipAddress}:与主站证书过期时间不一致; \n`
}else{
errorCount--
}
}
if (errorCount<=0){
return
}
await this.update({
id: site.id,
checkStatus: 'error',
error: errorMessage,
ipErrorCount: errorCount,
})
try {
site = await this.info(site.id)
await this.sendCheckErrorNotify(site,true);
} catch (e) {
logger.error('send notify error', e);
}
}
await this.siteIpService.checkAll(site,onFinished)
}
/** /**
* *
* @param id * @param id
@ -179,7 +215,7 @@ export class SiteInfoService extends BaseService<SiteInfoEntity> {
return await this.doCheck(site, notify, retryTimes); return await this.doCheck(site, notify, retryTimes);
} }
async sendCheckErrorNotify(site: SiteInfoEntity) { async sendCheckErrorNotify(site: SiteInfoEntity,fromIpCheck=false) {
const url = await this.notificationService.getBindUrl('#/certd/monitor/site'); const url = await this.notificationService.getBindUrl('#/certd/monitor/site');
// 发邮件 // 发邮件
await this.notificationService.send( await this.notificationService.send(
@ -188,8 +224,9 @@ export class SiteInfoService extends BaseService<SiteInfoEntity> {
logger: logger, logger: logger,
body: { body: {
url, url,
title: `站点证书检查出错<${site.name}>`, title: `站点证书${fromIpCheck?"(IP)":""}检查出错<${site.name}>`,
content: `站点名称: ${site.name} \n站点域名 ${site.domain} \n错误信息${site.error}`, content: `站点名称: ${site.name} \n站点域名 ${site.domain} \n错误信息${site.error}`,
errorMessage: site.error,
}, },
}, },
site.userId site.userId
@ -227,6 +264,7 @@ export class SiteInfoService extends BaseService<SiteInfoEntity> {
title: `站点证书已过期${-validDays}天<${site.name}>`, title: `站点证书已过期${-validDays}天<${site.name}>`,
content, content,
url, url,
errorMessage: "站点证书已过期"
}, },
}, },
site.userId site.userId
@ -272,4 +310,5 @@ export class SiteInfoService extends BaseService<SiteInfoEntity> {
await this.siteIpService.sync(site) await this.siteIpService.sync(site)
} }
} }
} }

View File

@ -18,6 +18,8 @@ import {PeerCertificate} from "tls";
export class SiteIpService extends BaseService<SiteIpEntity> { export class SiteIpService extends BaseService<SiteIpEntity> {
@InjectEntityModel(SiteIpEntity) @InjectEntityModel(SiteIpEntity)
repository: Repository<SiteIpEntity>; repository: Repository<SiteIpEntity>;
@InjectEntityModel(SiteInfoEntity)
siteInfoRepository: Repository<SiteInfoEntity>;
@Inject() @Inject()
notificationService: NotificationService; notificationService: NotificationService;
@ -36,14 +38,17 @@ export class SiteIpService extends BaseService<SiteIpEntity> {
return this.repository; return this.repository;
} }
async add(data: SiteInfoEntity) { async add(data: SiteIpEntity) {
if (!data.userId) { if (!data.userId) {
throw new Error("userId is required"); throw new Error("userId is required");
} }
data.disabled = false; data.disabled = false;
return await super.add(data); const res= await super.add(data);
await this.updateIpCount(data.siteId)
return res
} }
async update(data: any) { async update(data: any) {
if (!data.id) { if (!data.id) {
throw new Error("id is required"); throw new Error("id is required");
@ -80,7 +85,7 @@ export class SiteIpService extends BaseService<SiteIpEntity> {
} }
await this.checkAll(entity); await this.checkAll(entity);
await this.updateIpCount(entity.id)
} }
async check(ipId: number, domain: string, port: number) { async check(ipId: number, domain: string, port: number) {
@ -131,6 +136,8 @@ export class SiteIpService extends BaseService<SiteIpEntity> {
await this.update(updateData); await this.update(updateData);
return updateData
} catch (e) { } catch (e) {
logger.error("check site ip error", e); logger.error("check site ip error", e);
await this.update({ await this.update({
@ -139,10 +146,15 @@ export class SiteIpService extends BaseService<SiteIpEntity> {
lastCheckTime: dayjs().valueOf(), lastCheckTime: dayjs().valueOf(),
error: e.message error: e.message
}); });
return {
id: entity.id,
ipAddress: entity.ipAddress,
error: e.message
}
} }
} }
async checkAll(siteInfo: SiteInfoEntity) { async checkAll(siteInfo: SiteInfoEntity,onFinish?: (e: any) => void) {
const siteId = siteInfo.id; const siteId = siteInfo.id;
const ips = await this.repository.find({ const ips = await this.repository.find({
where: { where: {
@ -152,17 +164,28 @@ export class SiteIpService extends BaseService<SiteIpEntity> {
const domain = siteInfo.domain; const domain = siteInfo.domain;
const port = siteInfo.httpsPort; const port = siteInfo.httpsPort;
const promiseList = []; const promiseList = [];
for (const ip of ips) { for (const item of ips) {
const func = async () => { const func = async () => {
try { try {
await this.check(ip.id, domain, port); return await this.check(item.id, domain, port);
} catch (e) { } catch (e) {
logger.error("check site ip error", e); logger.error("check site item error", e);
return {
...item,
error:e.message
}
} }
} }
promiseList.push(func()); promiseList.push(func());
} }
Promise.all(promiseList); Promise.all(promiseList).then((res)=>{
const finished = res.filter(item=>{
return item
})
if (finished.length > 0) {
onFinish && onFinish(finished)
}
})
} }
async getAllIpsFromDomain(domain: string) { async getAllIpsFromDomain(domain: string) {
@ -192,4 +215,21 @@ export class SiteIpService extends BaseService<SiteIpEntity> {
return [...res[0], ...res[1]]; return [...res[0], ...res[1]];
}); });
} }
async updateIpCount(siteId:number){
const count = await this.repository.count({
where:{
siteId
}
})
await this.siteInfoRepository.update({
//where
id:siteId,
},
{
//update
ipCount:count
})
}
} }