From 41f4617e6630478081106744a9b10fa7517991c5 Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Wed, 28 May 2025 15:12:54 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20=E4=BC=98=E5=8C=96=E7=AB=99=E7=82=B9ip?= =?UTF-8?q?=E6=A3=80=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/views/certd/monitor/site/crud.tsx | 35 +++++++++++- .../src/views/certd/monitor/site/ip/crud.tsx | 1 + .../user/monitor/site-ip-controller.ts | 6 +- .../monitor/service/site-info-service.ts | 49 ++++++++++++++-- .../monitor/service/site-ip-service.ts | 56 ++++++++++++++++--- 5 files changed, 132 insertions(+), 15 deletions(-) diff --git a/packages/ui/certd-client/src/views/certd/monitor/site/crud.tsx b/packages/ui/certd-client/src/views/certd/monitor/site/crud.tsx index 0b98c37b..d2534a91 100644 --- a/packages/ui/certd-client/src/views/certd/monitor/site/crud.tsx +++ b/packages/ui/certd-client/src/views/certd/monitor/site/crud.tsx @@ -136,6 +136,10 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat }, }, }, + tabs: { + name: "disabled", + show: true, + }, columns: { id: { title: "ID", @@ -210,6 +214,34 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat 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 ( +
+
证书颁发机构:{row.certProvider}
+
证书域名:{row.certDomains}
+
+ ); + }, + }; + return ( + + {row.certDomains} + + ); + }, + }, + }, certDomains: { title: "证书域名", search: { @@ -222,7 +254,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat column: { width: 200, sorter: true, - show: true, + show: false, cellRender({ value }) { return ( @@ -244,6 +276,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat column: { width: 200, sorter: true, + show: false, cellRender({ value }) { return {value}; }, diff --git a/packages/ui/certd-client/src/views/certd/monitor/site/ip/crud.tsx b/packages/ui/certd-client/src/views/certd/monitor/site/ip/crud.tsx index 60518bcf..b9276418 100644 --- a/packages/ui/certd-client/src/views/certd/monitor/site/ip/crud.tsx +++ b/packages/ui/certd-client/src/views/certd/monitor/site/ip/crud.tsx @@ -31,6 +31,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat const addRequest = async (req: AddReq) => { const { form } = req; + form.siteId = context.props.siteId; const res = await api.AddObj(form); return res; }; diff --git a/packages/ui/certd-server/src/controller/user/monitor/site-ip-controller.ts b/packages/ui/certd-server/src/controller/user/monitor/site-ip-controller.ts index e3797467..dc376037 100644 --- a/packages/ui/certd-server/src/controller/user/monitor/site-ip-controller.ts +++ b/packages/ui/certd-server/src/controller/user/monitor/site-ip-controller.ts @@ -68,8 +68,12 @@ export class SiteInfoController extends CrudController { @Post('/delete', { summary: Constants.per.authOnly }) async delete(@Query('id') id: number) { + const entity = await this.service.info(id); 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 }) diff --git a/packages/ui/certd-server/src/modules/monitor/service/site-info-service.ts b/packages/ui/certd-server/src/modules/monitor/service/site-info-service.ts index 35663f1b..5d237847 100644 --- a/packages/ui/certd-server/src/modules/monitor/service/site-info-service.ts +++ b/packages/ui/certd-server/src/modules/monitor/service/site-info-service.ts @@ -13,6 +13,7 @@ import { UserSuiteService } from '@certd/commercial-core'; import { UserSettingsService } from "../../mine/service/user-settings-service.js"; import { UserSiteMonitorSetting } from "../../mine/service/models.js"; import {SiteIpService} from "./site-ip-service.js"; +import {SiteIpEntity} from "../entity/site-ip.js"; @Provide() @Scope(ScopeEnum.Request, { allowDowngrade: true }) @@ -134,9 +135,7 @@ export class SiteInfoService extends BaseService { //检查ip - if( site.ipCheck){ - await this.siteIpService.checkAll(site) - } + await this.checkAllIp(site) if (!notify) { return; @@ -165,6 +164,43 @@ export class SiteInfoService extends BaseService { } } + 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 @@ -179,7 +215,7 @@ export class SiteInfoService extends BaseService { 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'); // 发邮件 await this.notificationService.send( @@ -188,8 +224,9 @@ export class SiteInfoService extends BaseService { logger: logger, body: { url, - title: `站点证书检查出错<${site.name}>`, + title: `站点证书${fromIpCheck?"(IP)":""}检查出错<${site.name}>`, content: `站点名称: ${site.name} \n站点域名: ${site.domain} \n错误信息:${site.error}`, + errorMessage: site.error, }, }, site.userId @@ -227,6 +264,7 @@ export class SiteInfoService extends BaseService { title: `站点证书已过期${-validDays}天<${site.name}>`, content, url, + errorMessage: "站点证书已过期" }, }, site.userId @@ -272,4 +310,5 @@ export class SiteInfoService extends BaseService { await this.siteIpService.sync(site) } } + } diff --git a/packages/ui/certd-server/src/modules/monitor/service/site-ip-service.ts b/packages/ui/certd-server/src/modules/monitor/service/site-ip-service.ts index 499417ed..b6f7bf68 100644 --- a/packages/ui/certd-server/src/modules/monitor/service/site-ip-service.ts +++ b/packages/ui/certd-server/src/modules/monitor/service/site-ip-service.ts @@ -18,6 +18,8 @@ import {PeerCertificate} from "tls"; export class SiteIpService extends BaseService { @InjectEntityModel(SiteIpEntity) repository: Repository; + @InjectEntityModel(SiteInfoEntity) + siteInfoRepository: Repository; @Inject() notificationService: NotificationService; @@ -36,14 +38,17 @@ export class SiteIpService extends BaseService { return this.repository; } - async add(data: SiteInfoEntity) { + async add(data: SiteIpEntity) { if (!data.userId) { throw new Error("userId is required"); } 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) { if (!data.id) { throw new Error("id is required"); @@ -80,7 +85,7 @@ export class SiteIpService extends BaseService { } await this.checkAll(entity); - + await this.updateIpCount(entity.id) } async check(ipId: number, domain: string, port: number) { @@ -131,6 +136,8 @@ export class SiteIpService extends BaseService { await this.update(updateData); + return updateData + } catch (e) { logger.error("check site ip error", e); await this.update({ @@ -139,10 +146,15 @@ export class SiteIpService extends BaseService { lastCheckTime: dayjs().valueOf(), 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 ips = await this.repository.find({ where: { @@ -152,17 +164,28 @@ export class SiteIpService extends BaseService { const domain = siteInfo.domain; const port = siteInfo.httpsPort; const promiseList = []; - for (const ip of ips) { + for (const item of ips) { const func = async () => { try { - await this.check(ip.id, domain, port); + return await this.check(item.id, domain, port); } catch (e) { - logger.error("check site ip error", e); + logger.error("check site item error", e); + return { + ...item, + error:e.message + } } } 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) { @@ -192,4 +215,21 @@ export class SiteIpService extends BaseService { 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 + }) + } }