chore: remove domain expiry from systemd and some other monitors by allowlisting insted of denylisting (#6643)

This commit is contained in:
Frank Elsinga 2026-01-08 11:01:33 +01:00 committed by GitHub
parent 65b21d2c4b
commit 79b3274441
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 50 additions and 31 deletions

View File

@ -129,7 +129,7 @@ npm run dev # Starts frontend (port 3000) and backend (port 3001)
## Database
- Primary: SQLite (also supports MariaDB/MySQL/PostgreSQL)
- Primary: SQLite (also supports MariaDB/MySQL)
- Migrations in `db/knex_migrations/` using Knex.js
- Filename format validated by CI: `node ./extra/check-knex-filenames.mjs`

View File

@ -1,17 +1,12 @@
const { BeanModel } = require("redbean-node/dist/bean-model");
const { R } = require("redbean-node");
const { log } = require("../../src/util");
const { log, TYPES_WITH_DOMAIN_EXPIRY_SUPPORT_VIA_FIELD } = require("../../src/util");
const { parse: parseTld } = require("tldts");
const { getDaysRemaining, getDaysBetween, setting, setSetting } = require("../util-server");
const { Notification } = require("../notification");
const { default: NodeFetchCache, MemoryCache } = require("node-fetch-cache");
const TranslatableError = require("../translatable-error");
const TABLE = "domain_expiry";
// NOTE: Keep these type filters in sync with `showDomainExpiryNotification` in `src/pages/EditMonitor.vue`.
const urlTypes = [ "websocket-upgrade", "http", "keyword", "json-query", "real-browser" ];
const excludeTypes = [ "docker", "group", "push", "manual", "rabbitmq", "redis" ];
const cachedFetch = process.env.NODE_ENV ? NodeFetchCache.create({
// cache for 8h
cache: new MemoryCache({ ttl: 1000 * 60 * 60 * 8 })
@ -113,7 +108,7 @@ class DomainExpiry extends BeanModel {
* @returns {Promise<DomainExpiry>} Domain bean
*/
static async findByName(domain) {
return R.findOne(TABLE, "domain = ?", [ domain ]);
return R.findOne("domain_expiry", "domain = ?", [ domain ]);
}
/**
@ -121,7 +116,7 @@ class DomainExpiry extends BeanModel {
* @returns {DomainExpiry} Domain bean
*/
static createByName(domain) {
const d = R.dispense(TABLE);
const d = R.dispense("domain_expiry");
d.domain = domain;
return d;
}
@ -149,19 +144,11 @@ class DomainExpiry extends BeanModel {
* @returns {Promise<{ domain: string, tld: string }>} Domain expiry support info
*/
static async checkSupport(monitor) {
if (excludeTypes.includes(monitor.type) || monitor.type?.match(/sql$/)) {
if (!(monitor.type in TYPES_WITH_DOMAIN_EXPIRY_SUPPORT_VIA_FIELD)) {
throw new TranslatableError("domain_expiry_unsupported_monitor_type");
}
let target;
if (urlTypes.includes(monitor.type)) {
target = monitor.url;
} else if (monitor.type === "grpc-keyword") {
target = monitor.grpcUrl;
} else {
target = monitor.hostname;
}
const targetField = TYPES_WITH_DOMAIN_EXPIRY_SUPPORT_VIA_FIELD[monitor.type];
const target = monitor[targetField];
if (typeof target !== "string" || target.length === 0) {
throw new TranslatableError("domain_expiry_unsupported_missing_target");
}

View File

@ -29,7 +29,6 @@
monitor.type === 'http' ||
monitor.type === 'keyword' ||
monitor.type === 'json-query' ||
monitor.type === 'mp-health' ||
monitor.type === 'real-browser' ||
monitor.type === 'websocket-upgrade'
"

View File

@ -1356,6 +1356,7 @@ import {
MAX_INTERVAL_SECOND,
MIN_INTERVAL_SECOND,
sleep,
TYPES_WITH_DOMAIN_EXPIRY_SUPPORT_VIA_FIELD,
} from "../util.ts";
import { timeDurationFormatter } from "../util-frontend";
import isFQDN from "validator/lib/isFQDN";
@ -1521,15 +1522,7 @@ export default {
},
showDomainExpiryNotification() {
// NOTE: Keep this list in sync with `excludeTypes` in `server/model/domain_expiry.js`.
const excludedTypes = [ "docker", "group", "push", "manual", "rabbitmq", "redis" ];
const type = this.monitor.type;
if (!type) {
return false;
}
return !excludedTypes.includes(type) && !type.match(/sql$/);
return this.monitor.type in TYPES_WITH_DOMAIN_EXPIRY_SUPPORT_VIA_FIELD;
},
pageName() {

View File

@ -11,7 +11,7 @@
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.CONSOLE_STYLE_FgPink = exports.CONSOLE_STYLE_FgBrown = exports.CONSOLE_STYLE_FgViolet = exports.CONSOLE_STYLE_FgLightBlue = exports.CONSOLE_STYLE_FgLightGreen = exports.CONSOLE_STYLE_FgOrange = exports.CONSOLE_STYLE_FgGray = exports.CONSOLE_STYLE_FgWhite = exports.CONSOLE_STYLE_FgCyan = exports.CONSOLE_STYLE_FgMagenta = exports.CONSOLE_STYLE_FgBlue = exports.CONSOLE_STYLE_FgYellow = exports.CONSOLE_STYLE_FgGreen = exports.CONSOLE_STYLE_FgRed = exports.CONSOLE_STYLE_FgBlack = exports.CONSOLE_STYLE_Hidden = exports.CONSOLE_STYLE_Reverse = exports.CONSOLE_STYLE_Blink = exports.CONSOLE_STYLE_Underscore = exports.CONSOLE_STYLE_Dim = exports.CONSOLE_STYLE_Bright = exports.CONSOLE_STYLE_Reset = exports.PING_PER_REQUEST_TIMEOUT_DEFAULT = exports.PING_PER_REQUEST_TIMEOUT_MAX = exports.PING_PER_REQUEST_TIMEOUT_MIN = exports.PING_COUNT_DEFAULT = exports.PING_COUNT_MAX = exports.PING_COUNT_MIN = exports.PING_GLOBAL_TIMEOUT_DEFAULT = exports.PING_GLOBAL_TIMEOUT_MAX = exports.PING_GLOBAL_TIMEOUT_MIN = exports.PING_PACKET_SIZE_DEFAULT = exports.PING_PACKET_SIZE_MAX = exports.PING_PACKET_SIZE_MIN = exports.MIN_INTERVAL_SECOND = exports.MAX_INTERVAL_SECOND = exports.SQL_DATETIME_FORMAT_WITHOUT_SECOND = exports.SQL_DATETIME_FORMAT = exports.SQL_DATE_FORMAT = exports.STATUS_PAGE_MAINTENANCE = exports.STATUS_PAGE_PARTIAL_DOWN = exports.STATUS_PAGE_ALL_UP = exports.STATUS_PAGE_ALL_DOWN = exports.MAINTENANCE = exports.PENDING = exports.UP = exports.DOWN = exports.appName = exports.isNode = exports.isDev = void 0;
exports.evaluateJsonQuery = exports.intHash = exports.localToUTC = exports.utcToLocal = exports.utcToISODateTime = exports.isoToUTCDateTime = exports.parseTimeFromTimeObject = exports.parseTimeObject = exports.getMonitorRelativeURL = exports.genSecret = exports.getCryptoRandomInt = exports.getRandomInt = exports.getRandomArbitrary = exports.TimeLogger = exports.polyfill = exports.log = exports.debug = exports.ucfirst = exports.sleep = exports.flipStatus = exports.badgeConstants = exports.CONSOLE_STYLE_BgGray = exports.CONSOLE_STYLE_BgWhite = exports.CONSOLE_STYLE_BgCyan = exports.CONSOLE_STYLE_BgMagenta = exports.CONSOLE_STYLE_BgBlue = exports.CONSOLE_STYLE_BgYellow = exports.CONSOLE_STYLE_BgGreen = exports.CONSOLE_STYLE_BgRed = exports.CONSOLE_STYLE_BgBlack = void 0;
exports.TYPES_WITH_DOMAIN_EXPIRY_SUPPORT_VIA_FIELD = exports.evaluateJsonQuery = exports.intHash = exports.localToUTC = exports.utcToLocal = exports.utcToISODateTime = exports.isoToUTCDateTime = exports.parseTimeFromTimeObject = exports.parseTimeObject = exports.getMonitorRelativeURL = exports.genSecret = exports.getCryptoRandomInt = exports.getRandomInt = exports.getRandomArbitrary = exports.TimeLogger = exports.polyfill = exports.log = exports.debug = exports.ucfirst = exports.sleep = exports.flipStatus = exports.badgeConstants = exports.CONSOLE_STYLE_BgGray = exports.CONSOLE_STYLE_BgWhite = exports.CONSOLE_STYLE_BgCyan = exports.CONSOLE_STYLE_BgMagenta = exports.CONSOLE_STYLE_BgBlue = exports.CONSOLE_STYLE_BgYellow = exports.CONSOLE_STYLE_BgGreen = exports.CONSOLE_STYLE_BgRed = exports.CONSOLE_STYLE_BgBlack = void 0;
const dayjs_1 = require("dayjs");
const jsonata = require("jsonata");
exports.isDev = process.env.NODE_ENV === "development";
@ -441,3 +441,22 @@ async function evaluateJsonQuery(data, jsonPath, jsonPathOperator, expectedValue
}
}
exports.evaluateJsonQuery = evaluateJsonQuery;
exports.TYPES_WITH_DOMAIN_EXPIRY_SUPPORT_VIA_FIELD = {
'http': 'url',
'keyword': 'url',
'json-query': 'url',
'real-browser': 'url',
'websocket-upgrade': 'url',
'port': 'hostname',
'ping': 'hostname',
'grpc-keyword': 'grpcUrl',
'dns': 'hostname',
'smtp': 'hostname',
'snmp': 'hostname',
'gamedig': 'hostname',
'steam': 'hostname',
'mqtt': 'hostname',
'radius': 'hostname',
'tailscale-ping': 'hostname',
'sip-options': 'hostname'
};

View File

@ -722,3 +722,24 @@ export async function evaluateJsonQuery(data: any, jsonPath: string, jsonPathOpe
throw new Error(`Error evaluating JSON query: ${err.message}. Response from server was: ${response}`);
}
}
// these types will have domain expiry support via the specified field
export const TYPES_WITH_DOMAIN_EXPIRY_SUPPORT_VIA_FIELD = {
'http': 'url',
'keyword': 'url',
'json-query': 'url',
'real-browser': 'url',
'websocket-upgrade': 'url',
'port': 'hostname',
'ping': 'hostname',
'grpc-keyword': 'grpcUrl',
'dns': 'hostname',
'smtp': 'hostname',
'snmp': 'hostname',
'gamedig': 'hostname',
'steam': 'hostname',
'mqtt': 'hostname',
'radius': 'hostname',
'tailscale-ping': 'hostname',
'sip-options': 'hostname'
} as const;