Merge branch 'master' into feature/local-service-monitor

This commit is contained in:
iotux
2025-12-21 15:05:08 +07:00
committed by GitHub
17 changed files with 926 additions and 14 deletions
+61 -8
View File
@@ -60,13 +60,35 @@
<div class="mt-1 mb-3 ps-2 cert-exp-days col-12 col-xl-6">
<div v-for="day in settings.tlsExpiryNotifyDays" :key="day" class="d-flex align-items-center justify-content-between cert-exp-day-row py-2">
<span>{{ day }} {{ $tc("day", day) }}</span>
<button type="button" class="btn-rm-expiry btn btn-outline-danger ms-2 py-1" :aria-label="$t('Remove the expiry notification')" @click="removeExpiryNotifDay(day)">
<button type="button" class="btn-rm-expiry btn btn-outline-danger ms-2 py-1" :aria-label="$t('Remove the expiry notification')" @click="removeTlsExpiryNotifDay(day)">
<font-awesome-icon icon="times" />
</button>
</div>
</div>
<div class="col-12 col-xl-6">
<ActionInput v-model="expiryNotifInput" :type="'number'" :placeholder="$t('day')" :icon="'plus'" :action="() => addExpiryNotifDay(expiryNotifInput)" :action-aria-label="$t('Add a new expiry notification day')" />
<ActionInput v-model="tlsExpiryNotifInput" :type="'number'" :placeholder="$t('day')" :icon="'plus'" :action="() => addTlsExpiryNotifDay(tlsExpiryNotifInput)" :action-aria-label="$t('Add a new expiry notification day')" />
</div>
<div>
<button class="btn btn-primary" type="button" @click="saveSettings()">
{{ $t("Save") }}
</button>
</div>
</div>
<div class="my-4 pt-4">
<h5 class="my-4 settings-subheading">{{ $t("settingsDomainExpiry") }}</h5>
<p>{{ $t("domainExpiryDescription") }}</p>
<p>{{ $t("notificationDescription") }}</p>
<div class="mt-1 mb-3 ps-2 cert-exp-days col-12 col-xl-6">
<div v-for="day in settings.domainExpiryNotifyDays" :key="day" class="d-flex align-items-center justify-content-between cert-exp-day-row py-2">
<span>{{ day }} {{ $tc("day", day) }}</span>
<button type="button" class="btn-rm-expiry btn btn-outline-danger ms-2 py-1" :aria-label="$t('Remove the expiry notification')" @click="removeDomainExpiryNotifDay(day)">
<font-awesome-icon icon="times" />
</button>
</div>
</div>
<div class="col-12 col-xl-6">
<ActionInput v-model="domainExpiryNotifInput" :type="'number'" :placeholder="$t('day')" :icon="'plus'" :action="() => addDomainExpiryNotifDay(domainExpiryNotifInput)" :action-aria-label="$t('Add a new expiry notification day')" />
</div>
<div>
<button class="btn btn-primary" type="button" @click="saveSettings()">
@@ -96,7 +118,8 @@ export default {
/**
* Variable to store the input for new certificate expiry day.
*/
expiryNotifInput: null,
tlsExpiryNotifInput: null,
domainExpiryNotifInput: null,
};
},
@@ -134,15 +157,15 @@ export default {
methods: {
/**
* Remove a day from expiry notification days.
* Remove a day from tls expiry notification days.
* @param {number} day The day to remove.
* @returns {void}
*/
removeExpiryNotifDay(day) {
removeTlsExpiryNotifDay(day) {
this.settings.tlsExpiryNotifyDays = this.settings.tlsExpiryNotifyDays.filter(d => d !== day);
},
/**
* Add a new expiry notification day.
* Add a new tls expiry notification day.
* Will verify:
* - day is not null or empty string.
* - day is a number.
@@ -151,14 +174,44 @@ export default {
* @param {number} day The day number to add.
* @returns {void}
*/
addExpiryNotifDay(day) {
addTlsExpiryNotifDay(day) {
if (day != null && day !== "") {
const parsedDay = parseInt(day);
if (parsedDay != null && !isNaN(parsedDay) && parsedDay > 0) {
if (!this.settings.tlsExpiryNotifyDays.includes(parsedDay)) {
this.settings.tlsExpiryNotifyDays.push(parseInt(day));
this.settings.tlsExpiryNotifyDays.sort((a, b) => a - b);
this.expiryNotifInput = null;
this.tlsExpiryNotifInput = null;
}
}
}
},
/**
* Remove a day from domain expiry notification days.
* @param {number} day The day to remove.
* @returns {void}
*/
removeDomainExpiryNotifDay(day) {
this.settings.domainExpiryNotifyDays = this.settings.domainExpiryNotifyDays.filter(d => d !== day);
},
/**
* Add a new domain expiry notification day.
* Will verify:
* - day is not null or empty string.
* - day is a number.
* - day is > 0.
* - The day is not already in the list.
* @param {number} day The day number to add.
* @returns {void}
*/
addDomainExpiryNotifDay(day) {
if (day != null && day !== "") {
const parsedDay = parseInt(day);
if (parsedDay != null && !isNaN(parsedDay) && parsedDay > 0) {
if (!this.settings.domainExpiryNotifyDays.includes(parsedDay)) {
this.settings.domainExpiryNotifyDays.push(parseInt(day));
this.settings.domainExpiryNotifyDays.sort((a, b) => a - b);
this.domainExpiryNotifInput = null;
}
}
}
+4
View File
@@ -1243,6 +1243,10 @@
"Browser not supported": "Browser not supported",
"Unable to get permission to notify": "Unable to get permission to notify (request either denied or ignored).",
"Webpush Helptext": "Web push only works with SSL (HTTPS) connections. For iOS devices, webpage must be added to homescreen beforehand.",
"settingsDomainExpiry": "Domain Expiry",
"labelDomainExpiry": "Domain Exp.",
"labelDomainNameExpiryNotification": "Domain Name Expiry Notification",
"domainExpiryDescription": "Trigger notification when domain names expires in:",
"minimumIntervalWarning": "Intervals below 20 seconds may result in poor performance.",
"lowIntervalWarning": "Are you sure want to set the interval value below 20 seconds? Performance may be degraded, particularly if there are a large number of monitors."
}
+6
View File
@@ -45,6 +45,7 @@ export default {
avgPingList: { },
uptimeList: { },
tlsInfoList: {},
domainInfoList: {},
notificationList: [],
dockerHostList: [],
remoteBrowserList: [],
@@ -250,6 +251,11 @@ export default {
this.tlsInfoList[monitorID] = JSON.parse(data);
});
socket.on("domainInfo", (monitorID, daysRemaining, expiresOn) => {
this.domainInfoList[monitorID] = { daysRemaining: daysRemaining,
expiresOn: expiresOn };
});
socket.on("connect_error", (err) => {
console.error(`Failed to connect to the backend. Socket.io connect_error: ${err.message}`);
this.connectionErrorMsg = `${this.$t("Cannot connect to the socket server.")} [${err}] ${this.$t("Reconnecting...")}`;
+19
View File
@@ -298,6 +298,21 @@
<font-awesome-icon v-if="tlsInfo.hostnameMatchMonitorUrl === false" class="cert-info-warn" icon="exclamation-triangle" :title="$t('certHostnameMismatch')" />
</span>
</div>
<div
v-if="domainInfo"
class="col-12 col-sm col row d-flex align-items-center d-sm-block"
>
<h4 class="col-4 col-sm-12">{{ $t("labelDomainExpiry") }}</h4>
<p class="col-4 col-sm-12 mb-0 mb-sm-2">
(<Datetime
:value="domainInfo.expiresOn"
date-only
/>)
</p>
<span class="col-4 col-sm-12 num">
{{ domainInfo.daysRemaining }} {{ $tc("day", domainInfo.daysRemaining ) }}
</span>
</div>
</div>
</div>
@@ -626,6 +641,10 @@ export default {
return null;
},
domainInfo() {
return this.$root.domainInfoList[this.monitor.id] || null;
},
showCertInfoBox() {
return this.tlsInfo != null && this.toggleCertInfoBox;
},
+29
View File
@@ -853,6 +853,14 @@
</div>
</div>
<div v-if="hasDomain" class="my-3 form-check">
<input id="domain-expiry-notification" v-model="monitor.domainExpiryNotification" class="form-check-input" type="checkbox">
<label class="form-check-label" for="domain-expiry-notification">
{{ $t("labelDomainNameExpiryNotification") }}
</label>
<div class="form-text">
</div>
</div>
<div v-if="monitor.type === 'websocket-upgrade' " class="my-3 form-check">
<input id="wsIgnoreSecWebsocketAcceptHeader" v-model="monitor.wsIgnoreSecWebsocketAcceptHeader" class="form-check-input" type="checkbox">
<i18n-t tag="label" keypath="Ignore Sec-WebSocket-Accept header" class="form-check-label" for="wsIgnoreSecWebsocketAcceptHeader">
@@ -1387,6 +1395,7 @@ const monitorDefaults = {
ignoreTls: false,
upsideDown: false,
expiryNotification: false,
domainExpiryNotification: true,
maxredirects: 10,
accepted_statuscodes: [ "200-299" ],
dns_resolve_type: "A",
@@ -1444,6 +1453,7 @@ export default {
notificationIDList: {},
// Do not add default value here, please check init() method
},
hasDomain: false,
acceptedStatusCodeOptions: [],
dnsresolvetypeOptions: [],
kafkaSaslMechanismOptions: [],
@@ -1518,6 +1528,16 @@ export default {
return null;
},
monitorTypeUrlHost() {
const { type, url, hostname, grpcUrl } = this.monitor;
return {
type,
url,
hostname,
grpcUrl
};
},
pageName() {
let name = "Add New Monitor";
if (this.isClone) {
@@ -1795,6 +1815,15 @@ message HealthCheckResponse {
}
},
"monitorTypeUrlHost"(data) {
this.$root.getSocket().emit("checkMointor", data, (res) => {
this.hasDomain = !!res?.domain;
if (!res?.domain) {
this.monitor.domainExpiryNotification = false;
}
});
},
"monitor.type"(newType, oldType) {
if (oldType && this.monitor.type === "websocket-upgrade") {
this.monitor.url = "wss://";
+4
View File
@@ -179,6 +179,10 @@ export default {
this.settings.tlsExpiryNotifyDays = [ 7, 14, 21 ];
}
if (this.settings.domainExpiryNotifyDays === undefined) {
this.settings.domainExpiryNotifyDays = [ 7, 14, 21 ];
}
if (this.settings.trustProxy === undefined) {
this.settings.trustProxy = false;
}