mirror of https://github.com/certd/certd
chore: 优化站点ip检查
parent
a463711b03
commit
41f4617e66
|
@ -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 (
|
||||
<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: {
|
||||
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 (
|
||||
<a-tooltip title={value} placement="left">
|
||||
|
@ -244,6 +276,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
column: {
|
||||
width: 200,
|
||||
sorter: true,
|
||||
show: false,
|
||||
cellRender({ value }) {
|
||||
return <a-tooltip title={value}>{value}</a-tooltip>;
|
||||
},
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -68,8 +68,12 @@ export class SiteInfoController extends CrudController<SiteIpService> {
|
|||
|
||||
@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 })
|
||||
|
|
|
@ -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<SiteInfoEntity> {
|
|||
|
||||
|
||||
//检查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<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
|
||||
|
@ -179,7 +215,7 @@ export class SiteInfoService extends BaseService<SiteInfoEntity> {
|
|||
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<SiteInfoEntity> {
|
|||
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<SiteInfoEntity> {
|
|||
title: `站点证书已过期${-validDays}天<${site.name}>`,
|
||||
content,
|
||||
url,
|
||||
errorMessage: "站点证书已过期"
|
||||
},
|
||||
},
|
||||
site.userId
|
||||
|
@ -272,4 +310,5 @@ export class SiteInfoService extends BaseService<SiteInfoEntity> {
|
|||
await this.siteIpService.sync(site)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@ import {PeerCertificate} from "tls";
|
|||
export class SiteIpService extends BaseService<SiteIpEntity> {
|
||||
@InjectEntityModel(SiteIpEntity)
|
||||
repository: Repository<SiteIpEntity>;
|
||||
@InjectEntityModel(SiteInfoEntity)
|
||||
siteInfoRepository: Repository<SiteInfoEntity>;
|
||||
|
||||
@Inject()
|
||||
notificationService: NotificationService;
|
||||
|
@ -36,14 +38,17 @@ export class SiteIpService extends BaseService<SiteIpEntity> {
|
|||
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<SiteIpEntity> {
|
|||
}
|
||||
|
||||
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<SiteIpEntity> {
|
|||
|
||||
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<SiteIpEntity> {
|
|||
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<SiteIpEntity> {
|
|||
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<SiteIpEntity> {
|
|||
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
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue