feat: add domain registration expiry monitoring

Adds a GET /monitors/domain/:monitorId endpoint that looks up the
registrable domain's WHOIS expiry date (walking up from subdomains),
and displays it next to the certificate expiry on the uptime details
page.

Fixes #2094
This commit is contained in:
colinjtsen2010 committed 2026-08-11 00:34:21 +08:00
1 parent 4b921f4986
commit e5959ca91d
13 files changed
+333 -5

No files matched your search

@@ -10,6 +10,7 @@ import {
editMonitorBodyValidation,
pauseMonitorParamValidation,
getCertificateParamValidation,
getDomainParamValidation,
getHardwareDetailsByIdParamValidation,
getHardwareDetailsByIdQueryValidation,
getUptimeDetailsByIdParamValidation,
@@ -18,13 +19,15 @@ import {
bulkPauseMonitorBodyValidation,
} from "@/api/validation/monitorValidation.js";
import sslChecker from "ssl-checker";
import { fetchMonitorCertificate, requireTeamId, requireUserId } from "@/api/controllers/controllerUtils.js";
import * as whoiser from "whoiser";
import { fetchMonitorCertificate, fetchMonitorDomain, requireTeamId, requireUserId } from "@/api/controllers/controllerUtils.js";
import { AppError } from "@/utils/AppError.js";
import { IMonitorService } from "@/domain/monitors/monitor.service.js";
import { INotificationsService } from "@/domain/notifications/notification.service.js";
export interface IMonitorController {
getMonitorCertificate: RequestHandler;
getMonitorDomain: RequestHandler;
getUptimeDetailsById: RequestHandler;
getHardwareDetailsById: RequestHandler;
getPageSpeedDetailsById: RequestHandler;
@@ -68,6 +71,22 @@ class MonitorController implements IMonitorController {
});
});
getMonitorDomain = catchAsync(async (req: Request, res: Response) => {
const validatedParams = getDomainParamValidation.parse(req.params);
const teamId = requireTeamId(req.user?.teamId);
const monitor = await this.monitorService.getMonitorById({ teamId, monitorId: validatedParams.monitorId });
const domainExpiry = await fetchMonitorDomain(whoiser, monitor);
return res.status(200).json({
success: true,
msg: "Domain expiry retrieved successfully",
data: {
domain: domainExpiry.domain,
expiryDate: new Date(domainExpiry.expiryDate),
},
});
});
getUptimeDetailsById = catchAsync(async (req: Request, res: Response) => {
const validatedParams = getUptimeDetailsByIdParamValidation.parse(req.params);
const validatedQuery = getUptimeDetailsByIdQueryValidation.parse(req.query);