2021-07-27 19:47:13 +02:00
import { io } from "socket.io-client" ;
import { useToast } from "vue-toastification" ;
2022-04-17 01:39:49 +08:00
import jwtDecode from "jwt-decode" ;
2021-10-29 22:25:32 -03:00
import Favico from "favico.js" ;
2022-12-12 22:57:57 +08:00
import dayjs from "dayjs" ;
2023-09-23 19:03:45 +08:00
import mitt from "mitt" ;
2023-01-17 17:25:35 +08:00
import { DOWN , MAINTENANCE , PENDING , UP } from "../util.ts" ;
2023-09-06 19:52:54 +08:00
import { getDevContainerServerHostname , isDevContainer , getToastSuccessTimeout , getToastErrorTimeout } from "../util-frontend.js" ;
2021-09-21 21:22:35 +08:00
const toast = useToast ( ) ;
2021-06-25 21:55:49 +08:00
let socket ;
2021-09-11 19:40:03 +08:00
const noSocketIOPages = [
2022-03-15 12:00:29 +08:00
/^\/status-page$/ , // /status-page
/^\/status/ , // /status**
/^\/$/ // /
2021-09-11 16:22:30 +08:00
] ;
2021-10-29 22:25:32 -03:00
const favicon = new Favico ( {
animation : "none"
} ) ;
2021-06-25 21:55:49 +08:00
export default {
data ( ) {
return {
2021-07-13 18:08:12 +08:00
info : { } ,
2021-06-25 21:55:49 +08:00
socket : {
token : null ,
firstConnect : true ,
connected : false ,
2021-06-29 16:06:20 +08:00
connectCount : 0 ,
2021-09-11 16:22:30 +08:00
initedSocketIO : false ,
2021-06-25 21:55:49 +08:00
} ,
2022-04-19 19:40:28 +08:00
username : null ,
2021-07-01 22:16:02 +08:00
remember : ( localStorage . remember !== "0" ) ,
2021-06-25 21:55:49 +08:00
allowLoginDialog : false , // Allowed to show login dialog, but "loggedIn" have to be true too. This exists because prevent the login dialog show 0.1s in first before the socket server auth-ed.
loggedIn : false ,
2021-07-01 13:11:16 +08:00
monitorList : { } ,
2023-02-14 19:49:04 +00:00
maintenanceList : { } ,
apiKeyList : { } ,
2021-07-01 13:11:16 +08:00
heartbeatList : { } ,
avgPingList : { } ,
2021-07-09 14:14:03 +08:00
uptimeList : { } ,
2021-10-01 18:44:32 +08:00
tlsInfoList : { } ,
2021-07-09 14:14:03 +08:00
notificationList : [ ] ,
2022-07-22 15:47:04 +00:00
dockerHostList : [ ] ,
2023-12-01 07:29:10 +00:00
remoteBrowserList : [ ] ,
2022-03-17 19:07:05 +08:00
statusPageListLoaded : false ,
2022-03-10 21:34:30 +08:00
statusPageList : [ ] ,
2021-10-30 20:37:15 +03:00
proxyList : [ ] ,
2023-06-11 22:43:33 +02:00
connectionErrorMsg : ` ${ this . $t ( "Cannot connect to the socket server." ) } ${ this . $t ( "Reconnecting..." ) } ` ,
2022-03-22 23:46:13 +08:00
showReverseProxyGuide : true ,
2022-03-30 01:49:45 +08:00
cloudflared : {
cloudflareTunnelToken : "" ,
installed : null ,
running : false ,
message : "" ,
errorMessage : "" ,
2022-03-30 11:59:49 +08:00
currentPassword : "" ,
2023-08-01 15:12:17 +08:00
} ,
faviconUpdateDebounce : null ,
2023-09-23 19:03:45 +08:00
emitter : mitt ( ) ,
2021-09-21 21:22:35 +08:00
} ;
2021-06-25 21:55:49 +08:00
} ,
created ( ) {
2021-09-11 16:22:30 +08:00
this . initSocketIO ( ) ;
} ,
2021-07-11 15:23:28 +08:00
2021-09-11 16:22:30 +08:00
methods : {
2021-09-11 14:37:05 +08:00
2022-06-02 10:38:17 +01:00
/ * *
* Initialize connection to socket server
2023-08-11 09:46:41 +02:00
* @ param { boolean } bypass Should the check for if we
2022-06-02 10:38:17 +01:00
* are on a status page be bypassed ?
2023-08-11 09:46:41 +02:00
* @ returns { void }
2022-06-02 10:38:17 +01:00
* /
2021-09-11 16:22:30 +08:00
initSocketIO ( bypass = false ) {
// No need to re-init
if ( this . socket . initedSocketIO ) {
return ;
}
2021-07-11 14:20:31 +08:00
2021-09-11 16:22:30 +08:00
// No need to connect to the socket.io for status page
2022-03-15 12:00:29 +08:00
if ( ! bypass && location . pathname ) {
for ( let page of noSocketIOPages ) {
if ( location . pathname . match ( page ) ) {
return ;
}
}
2021-09-11 16:22:30 +08:00
}
2023-02-11 14:41:02 +08:00
// Also don't need to connect to the socket.io for setup database page
if ( location . pathname === "/setup-database" ) {
return ;
}
2021-09-11 16:22:30 +08:00
this . socket . initedSocketIO = true ;
2021-06-25 21:55:49 +08:00
2023-12-12 16:23:41 +08:00
let protocol = location . protocol + "//" ;
2021-07-09 14:14:03 +08:00
2023-12-12 16:23:41 +08:00
let url ;
2021-09-11 16:22:30 +08:00
const env = process . env . NODE _ENV || "production" ;
2023-07-17 14:54:40 +08:00
if ( env === "development" && isDevContainer ( ) ) {
2023-12-12 16:23:41 +08:00
url = protocol + getDevContainerServerHostname ( ) ;
2023-07-17 14:54:40 +08:00
} else if ( env === "development" || localStorage . dev === "dev" ) {
2023-12-12 16:23:41 +08:00
url = protocol + location . hostname + ":3001" ;
2021-09-11 16:22:30 +08:00
} else {
2023-12-12 16:23:41 +08:00
// Connect to the current url
url = undefined ;
2021-06-27 16:10:55 +08:00
}
2023-12-12 16:23:41 +08:00
socket = io ( url ) ;
2021-06-30 21:04:58 +08:00
2021-09-11 16:22:30 +08:00
socket . on ( "info" , ( info ) => {
this . info = info ;
} ) ;
2021-06-30 21:04:58 +08:00
2021-09-11 16:22:30 +08:00
socket . on ( "setup" , ( monitorID , data ) => {
2021-09-21 21:22:35 +08:00
this . $router . push ( "/setup" ) ;
2021-09-11 16:22:30 +08:00
} ) ;
2021-06-30 21:04:58 +08:00
2021-09-11 16:22:30 +08:00
socket . on ( "autoLogin" , ( monitorID , data ) => {
this . loggedIn = true ;
this . storage ( ) . token = "autoLogin" ;
2022-04-20 22:39:07 +08:00
this . socket . token = "autoLogin" ;
2021-09-11 16:22:30 +08:00
this . allowLoginDialog = false ;
} ) ;
2024-04-21 20:39:44 +02:00
socket . on ( "loginRequired" , ( ) => {
let token = this . storage ( ) . token ;
if ( token && token !== "autoLogin" ) {
this . loginByToken ( token ) ;
} else {
this . $root . storage ( ) . removeItem ( "token" ) ;
this . allowLoginDialog = true ;
}
} ) ;
2021-09-11 16:22:30 +08:00
socket . on ( "monitorList" , ( data ) => {
// Add Helper function
2022-04-17 15:27:35 +08:00
Object . entries ( data ) . forEach ( ( [ monitorID , monitor ] ) => {
2021-09-11 16:22:30 +08:00
monitor . getUrl = ( ) => {
try {
return new URL ( monitor . url ) ;
} catch ( _ ) {
return null ;
}
} ;
} ) ;
this . monitorList = data ;
} ) ;
2022-01-23 15:22:00 +01:00
socket . on ( "maintenanceList" , ( data ) => {
this . maintenanceList = data ;
} ) ;
2023-02-14 19:49:04 +00:00
socket . on ( "apiKeyList" , ( data ) => {
this . apiKeyList = data ;
} ) ;
2021-09-11 16:22:30 +08:00
socket . on ( "notificationList" , ( data ) => {
this . notificationList = data ;
} ) ;
2022-03-10 21:34:30 +08:00
socket . on ( "statusPageList" , ( data ) => {
2022-03-17 19:07:05 +08:00
this . statusPageListLoaded = true ;
2022-03-10 21:34:30 +08:00
this . statusPageList = data ;
} ) ;
2021-10-30 20:37:15 +03:00
socket . on ( "proxyList" , ( data ) => {
this . proxyList = data . map ( item => {
item . auth = ! ! item . auth ;
item . active = ! ! item . active ;
item . default = ! ! item . default ;
return item ;
} ) ;
} ) ;
2022-07-22 15:47:04 +00:00
socket . on ( "dockerHostList" , ( data ) => {
this . dockerHostList = data ;
2022-07-22 15:57:40 +00:00
} ) ;
2022-07-22 15:47:04 +00:00
2023-12-01 07:29:10 +00:00
socket . on ( "remoteBrowserList" , ( data ) => {
this . remoteBrowserList = data ;
} ) ;
2021-09-11 16:22:30 +08:00
socket . on ( "heartbeat" , ( data ) => {
if ( ! ( data . monitorID in this . heartbeatList ) ) {
this . heartbeatList [ data . monitorID ] = [ ] ;
2021-06-30 21:04:58 +08:00
}
2021-09-16 22:48:28 +08:00
this . heartbeatList [ data . monitorID ] . push ( data ) ;
if ( this . heartbeatList [ data . monitorID ] . length >= 150 ) {
this . heartbeatList [ data . monitorID ] . shift ( ) ;
}
2021-09-11 16:22:30 +08:00
// Add to important list if it is important
// Also toast
if ( data . important ) {
2023-08-02 15:09:13 +08:00
if ( this . monitorList [ data . monitorID ] !== undefined ) {
if ( data . status === 0 ) {
toast . error ( ` [ ${ this . monitorList [ data . monitorID ] . name } ] [DOWN] ${ data . msg } ` , {
2023-09-06 19:52:54 +08:00
timeout : getToastErrorTimeout ( ) ,
2023-08-02 15:09:13 +08:00
} ) ;
} else if ( data . status === 1 ) {
toast . success ( ` [ ${ this . monitorList [ data . monitorID ] . name } ] [Up] ${ data . msg } ` , {
2023-09-06 19:52:54 +08:00
timeout : getToastSuccessTimeout ( ) ,
2023-08-02 15:09:13 +08:00
} ) ;
} else {
toast ( ` [ ${ this . monitorList [ data . monitorID ] . name } ] ${ data . msg } ` ) ;
}
2021-09-11 16:22:30 +08:00
}
2021-06-27 16:10:55 +08:00
2023-09-23 19:03:45 +08:00
this . emitter . emit ( "newImportantHeartbeat" , data ) ;
2021-09-11 16:22:30 +08:00
}
} ) ;
2021-06-30 21:04:58 +08:00
2021-09-11 16:22:30 +08:00
socket . on ( "heartbeatList" , ( monitorID , data , overwrite = false ) => {
if ( ! ( monitorID in this . heartbeatList ) || overwrite ) {
this . heartbeatList [ monitorID ] = data ;
} else {
2021-09-21 21:22:35 +08:00
this . heartbeatList [ monitorID ] = data . concat ( this . heartbeatList [ monitorID ] ) ;
2021-09-11 16:22:30 +08:00
}
} ) ;
2021-07-01 13:11:16 +08:00
2021-09-11 16:22:30 +08:00
socket . on ( "avgPing" , ( monitorID , data ) => {
2021-09-21 21:22:35 +08:00
this . avgPingList [ monitorID ] = data ;
2021-09-11 16:22:30 +08:00
} ) ;
2021-07-21 12:09:09 +08:00
2021-09-11 16:22:30 +08:00
socket . on ( "uptime" , ( monitorID , type , data ) => {
2021-09-21 21:22:35 +08:00
this . uptimeList [ ` ${ monitorID } _ ${ type } ` ] = data ;
2021-09-11 16:22:30 +08:00
} ) ;
2021-06-25 21:55:49 +08:00
2021-09-11 16:22:30 +08:00
socket . on ( "certInfo" , ( monitorID , data ) => {
2021-10-01 18:44:32 +08:00
this . tlsInfoList [ monitorID ] = JSON . parse ( data ) ;
2021-09-11 16:22:30 +08:00
} ) ;
2021-07-31 23:41:24 +08:00
2021-09-11 16:22:30 +08:00
socket . on ( "connect_error" , ( err ) => {
console . error ( ` Failed to connect to the backend. Socket.io connect_error: ${ err . message } ` ) ;
2023-06-11 22:43:33 +02:00
this . connectionErrorMsg = ` ${ this . $t ( "Cannot connect to the socket server." ) } [ ${ err } ] ${ this . $t ( "Reconnecting..." ) } ` ;
2022-03-22 23:46:13 +08:00
this . showReverseProxyGuide = true ;
2021-09-11 16:22:30 +08:00
this . socket . connected = false ;
this . socket . firstConnect = false ;
} ) ;
2021-08-03 13:07:20 +08:00
2021-09-11 16:22:30 +08:00
socket . on ( "disconnect" , ( ) => {
2021-09-21 21:22:35 +08:00
console . log ( "disconnect" ) ;
2021-09-11 16:22:30 +08:00
this . connectionErrorMsg = "Lost connection to the socket server. Reconnecting..." ;
this . socket . connected = false ;
} ) ;
socket . on ( "connect" , ( ) => {
2021-10-05 20:27:43 +08:00
console . log ( "Connected to the socket server" ) ;
2021-09-11 16:22:30 +08:00
this . socket . connectCount ++ ;
this . socket . connected = true ;
2022-03-22 23:46:13 +08:00
this . showReverseProxyGuide = false ;
2021-09-11 16:22:30 +08:00
// Reset Heartbeat list if it is re-connect
if ( this . socket . connectCount >= 2 ) {
2021-09-21 21:22:35 +08:00
this . clearData ( ) ;
2021-07-31 23:41:24 +08:00
}
2021-06-25 21:55:49 +08:00
2021-09-11 16:22:30 +08:00
this . socket . firstConnect = false ;
} ) ;
2022-03-30 01:49:45 +08:00
// cloudflared
socket . on ( "cloudflared_installed" , ( res ) => this . cloudflared . installed = res ) ;
socket . on ( "cloudflared_running" , ( res ) => this . cloudflared . running = res ) ;
socket . on ( "cloudflared_message" , ( res ) => this . cloudflared . message = res ) ;
socket . on ( "cloudflared_errorMessage" , ( res ) => this . cloudflared . errorMessage = res ) ;
socket . on ( "cloudflared_token" , ( res ) => this . cloudflared . cloudflareTunnelToken = res ) ;
2022-12-12 22:57:57 +08:00
socket . on ( "initServerTimezone" , ( ) => {
socket . emit ( "initServerTimezone" , dayjs . tz . guess ( ) ) ;
} ) ;
2023-12-10 20:40:40 +08:00
socket . on ( "refresh" , ( ) => {
location . reload ( ) ;
} ) ;
2021-09-11 16:22:30 +08:00
} ,
2021-06-27 16:10:55 +08:00
2022-06-02 10:38:17 +01:00
/ * *
* The storage currently in use
2023-08-11 09:46:41 +02:00
* @ returns { Storage } Current storage
2022-06-02 10:38:17 +01:00
* /
2021-07-01 22:16:02 +08:00
storage ( ) {
return ( this . remember ) ? localStorage : sessionStorage ;
} ,
2022-06-02 10:38:17 +01:00
/ * *
* Get payload of JWT cookie
2023-08-11 09:46:41 +02:00
* @ returns { ( object | undefined ) } JWT payload
2022-06-02 10:38:17 +01:00
* /
2021-11-09 22:37:05 +08:00
getJWTPayload ( ) {
const jwtToken = this . $root . storage ( ) . token ;
if ( jwtToken && jwtToken !== "autoLogin" ) {
2022-04-17 01:39:49 +08:00
return jwtDecode ( jwtToken ) ;
2021-11-09 22:37:05 +08:00
}
return undefined ;
} ,
2022-06-02 10:38:17 +01:00
/ * *
* Get current socket
2023-08-11 09:46:41 +02:00
* @ returns { Socket } Current socket
2022-06-02 10:38:17 +01:00
* /
2021-06-25 21:55:49 +08:00
getSocket ( ) {
2021-07-18 20:46:45 +02:00
return socket ;
2021-06-25 21:55:49 +08:00
} ,
2021-06-27 16:10:55 +08:00
2022-06-02 10:38:17 +01:00
/ * *
2024-04-16 22:59:07 +08:00
* Show success or error toast dependent on response status code
2023-08-11 09:46:41 +02:00
* @ param { object } res Response object
* @ returns { void }
2022-06-02 10:38:17 +01:00
* /
2021-06-25 21:55:49 +08:00
toastRes ( res ) {
2023-09-01 20:51:28 +08:00
let msg = res . msg ;
if ( res . msgi18n ) {
if ( msg != null && typeof msg === "object" ) {
msg = this . $t ( msg . key , msg . values ) ;
} else {
msg = this . $t ( msg ) ;
}
}
2021-06-25 21:55:49 +08:00
if ( res . ok ) {
2023-09-01 20:51:28 +08:00
toast . success ( msg ) ;
2021-06-25 21:55:49 +08:00
} else {
2023-09-01 20:51:28 +08:00
toast . error ( msg ) ;
2021-06-25 21:55:49 +08:00
}
} ,
2021-06-27 16:10:55 +08:00
2022-06-02 10:38:17 +01:00
/ * *
* Show a success toast
* @ param { string } msg Message to show
2023-08-11 09:46:41 +02:00
* @ returns { void }
2022-06-02 10:38:17 +01:00
* /
2022-03-17 23:38:43 +08:00
toastSuccess ( msg ) {
2023-10-14 19:00:27 +08:00
toast . success ( this . $t ( msg ) ) ;
2022-03-17 23:38:43 +08:00
} ,
2022-06-02 10:38:17 +01:00
/ * *
* Show an error toast
* @ param { string } msg Message to show
2023-08-11 09:46:41 +02:00
* @ returns { void }
2022-06-02 10:38:17 +01:00
* /
2022-03-17 23:38:43 +08:00
toastError ( msg ) {
2023-10-14 19:00:27 +08:00
toast . error ( this . $t ( msg ) ) ;
2022-03-17 23:38:43 +08:00
} ,
2022-06-02 10:38:17 +01:00
/ * *
* Callback for login
* @ callback loginCB
2023-08-11 09:46:41 +02:00
* @ param { object } res Response object
2022-06-02 10:38:17 +01:00
* /
/ * *
* Send request to log user in
* @ param { string } username Username to log in with
* @ param { string } password Password to log in with
* @ param { string } token User token
* @ param { loginCB } callback Callback to call with result
2023-08-11 09:46:41 +02:00
* @ returns { void }
2022-06-02 10:38:17 +01:00
* /
2021-09-09 21:10:31 +02:00
login ( username , password , token , callback ) {
2021-06-25 21:55:49 +08:00
socket . emit ( "login" , {
username ,
password ,
2021-09-09 21:10:31 +02:00
token ,
2021-06-25 21:55:49 +08:00
} , ( res ) => {
2021-09-09 21:10:31 +02:00
if ( res . tokenRequired ) {
2021-09-21 21:22:35 +08:00
callback ( res ) ;
2021-09-09 21:10:31 +02:00
}
2021-06-25 21:55:49 +08:00
if ( res . ok ) {
2021-07-01 22:16:02 +08:00
this . storage ( ) . token = res . token ;
2021-06-25 21:55:49 +08:00
this . socket . token = res . token ;
this . loggedIn = true ;
2022-04-19 19:40:28 +08:00
this . username = this . getJWTPayload ( ) ? . username ;
2021-06-25 21:55:49 +08:00
// Trigger Chrome Save Password
2021-09-21 21:22:35 +08:00
history . pushState ( { } , "" ) ;
2021-06-25 21:55:49 +08:00
}
2021-09-21 21:22:35 +08:00
callback ( res ) ;
} ) ;
2021-06-25 21:55:49 +08:00
} ,
2021-06-27 16:10:55 +08:00
2022-06-02 10:38:17 +01:00
/ * *
* Log in using a token
* @ param { string } token Token to log in with
2023-08-11 09:46:41 +02:00
* @ returns { void }
2022-06-02 10:38:17 +01:00
* /
2021-06-25 21:55:49 +08:00
loginByToken ( token ) {
socket . emit ( "loginByToken" , token , ( res ) => {
this . allowLoginDialog = true ;
if ( ! res . ok ) {
2021-09-21 21:22:35 +08:00
this . logout ( ) ;
2021-06-25 21:55:49 +08:00
} else {
this . loggedIn = true ;
2022-04-19 19:40:28 +08:00
this . username = this . getJWTPayload ( ) ? . username ;
2021-06-25 21:55:49 +08:00
}
2021-09-21 21:22:35 +08:00
} ) ;
2021-06-25 21:55:49 +08:00
} ,
2021-06-27 16:10:55 +08:00
2023-08-11 09:46:41 +02:00
/ * *
* Log out of the web application
* @ returns { void }
* /
2021-06-25 21:55:49 +08:00
logout ( ) {
2021-10-30 23:33:20 +08:00
socket . emit ( "logout" , ( ) => { } ) ;
2021-07-01 22:16:02 +08:00
this . storage ( ) . removeItem ( "token" ) ;
2021-06-25 21:55:49 +08:00
this . socket . token = null ;
2021-06-30 21:04:58 +08:00
this . loggedIn = false ;
2022-04-19 19:40:28 +08:00
this . username = null ;
2021-09-21 21:22:35 +08:00
this . clearData ( ) ;
2021-06-25 21:55:49 +08:00
} ,
2021-06-27 16:10:55 +08:00
2022-06-02 10:38:17 +01:00
/ * *
* Callback for general socket requests
* @ callback socketCB
2023-08-11 09:46:41 +02:00
* @ param { object } res Result of operation
* /
/ * *
* Prepare 2 FA configuration
* @ param { socketCB } callback Callback for socket response
* @ returns { void }
2022-06-02 10:38:17 +01:00
* /
2021-09-09 21:10:31 +02:00
prepare2FA ( callback ) {
2021-09-21 21:22:35 +08:00
socket . emit ( "prepare2FA" , callback ) ;
2021-09-09 21:10:31 +02:00
} ,
2022-06-02 10:38:17 +01:00
/ * *
* Save the current 2 FA configuration
* @ param { any } secret Unused
2023-08-11 09:46:41 +02:00
* @ param { socketCB } callback Callback for socket response
* @ returns { void }
2022-06-02 10:38:17 +01:00
* /
2021-09-09 21:10:31 +02:00
save2FA ( secret , callback ) {
2021-09-21 21:22:35 +08:00
socket . emit ( "save2FA" , callback ) ;
2021-09-09 21:10:31 +02:00
} ,
2022-06-02 10:38:17 +01:00
/ * *
* Disable 2 FA for this user
2023-08-11 09:46:41 +02:00
* @ param { socketCB } callback Callback for socket response
* @ returns { void }
2022-06-02 10:38:17 +01:00
* /
2021-09-09 21:10:31 +02:00
disable2FA ( callback ) {
2021-09-21 21:22:35 +08:00
socket . emit ( "disable2FA" , callback ) ;
2021-09-09 21:10:31 +02:00
} ,
2022-06-02 10:38:17 +01:00
/ * *
* Verify the provided 2 FA token
* @ param { string } token Token to verify
2023-08-11 09:46:41 +02:00
* @ param { socketCB } callback Callback for socket response
* @ returns { void }
2022-06-02 10:38:17 +01:00
* /
2021-09-09 21:10:31 +02:00
verifyToken ( token , callback ) {
2021-09-21 21:22:35 +08:00
socket . emit ( "verifyToken" , token , callback ) ;
2021-09-09 21:10:31 +02:00
} ,
2022-06-02 10:38:17 +01:00
/ * *
* Get current 2 FA status
2023-08-11 09:46:41 +02:00
* @ param { socketCB } callback Callback for socket response
* @ returns { void }
2022-06-02 10:38:17 +01:00
* /
2021-09-09 21:10:31 +02:00
twoFAStatus ( callback ) {
2021-09-21 21:22:35 +08:00
socket . emit ( "twoFAStatus" , callback ) ;
2021-09-09 21:10:31 +02:00
} ,
2022-06-02 10:38:17 +01:00
/ * *
* Get list of monitors
2023-08-11 09:46:41 +02:00
* @ param { socketCB } callback Callback for socket response
* @ returns { void }
2022-06-02 10:38:17 +01:00
* /
2021-08-26 18:55:19 +08:00
getMonitorList ( callback ) {
2021-10-01 15:47:51 +08:00
if ( ! callback ) {
callback = ( ) => { } ;
}
2021-09-21 21:22:35 +08:00
socket . emit ( "getMonitorList" , callback ) ;
2021-08-26 18:55:19 +08:00
} ,
2023-01-05 22:55:51 +00:00
/ * *
* Get list of maintenances
2023-08-11 09:46:41 +02:00
* @ param { socketCB } callback Callback for socket response
* @ returns { void }
2023-01-05 22:55:51 +00:00
* /
2022-01-23 15:22:00 +01:00
getMaintenanceList ( callback ) {
if ( ! callback ) {
callback = ( ) => { } ;
}
socket . emit ( "getMaintenanceList" , callback ) ;
} ,
2023-02-14 19:49:04 +00:00
/ * *
* Send list of API keys
2023-08-11 09:46:41 +02:00
* @ param { socketCB } callback Callback for socket response
* @ returns { void }
2023-02-14 19:49:04 +00:00
* /
getAPIKeyList ( callback ) {
if ( ! callback ) {
callback = ( ) => { } ;
}
socket . emit ( "getAPIKeyList" , callback ) ;
} ,
2022-06-02 10:38:17 +01:00
/ * *
* Add a monitor
2023-08-11 09:46:41 +02:00
* @ param { object } monitor Object representing monitor to add
* @ param { socketCB } callback Callback for socket response
* @ returns { void }
2022-06-02 10:38:17 +01:00
* /
2021-06-25 21:55:49 +08:00
add ( monitor , callback ) {
2021-09-21 21:22:35 +08:00
socket . emit ( "add" , monitor , callback ) ;
2021-06-25 21:55:49 +08:00
} ,
2021-06-27 16:10:55 +08:00
2023-01-05 22:55:51 +00:00
/ * *
2023-08-11 09:46:41 +02:00
* Adds a maintenance
* @ param { object } maintenance Maintenance to add
* @ param { socketCB } callback Callback for socket response
* @ returns { void }
2023-01-05 22:55:51 +00:00
* /
2022-01-23 15:22:00 +01:00
addMaintenance ( maintenance , callback ) {
socket . emit ( "addMaintenance" , maintenance , callback ) ;
} ,
2023-01-05 22:55:51 +00:00
/ * *
* Add monitors to maintenance
2023-08-11 09:46:41 +02:00
* @ param { number } maintenanceID Maintenance to modify
* @ param { number [ ] } monitors IDs of monitors to add
* @ param { socketCB } callback Callback for socket response
* @ returns { void }
2023-01-05 22:55:51 +00:00
* /
2022-01-23 15:22:00 +01:00
addMonitorMaintenance ( maintenanceID , monitors , callback ) {
socket . emit ( "addMonitorMaintenance" , maintenanceID , monitors , callback ) ;
} ,
2023-01-05 22:55:51 +00:00
/ * *
* Add status page to maintenance
2023-08-11 09:46:41 +02:00
* @ param { number } maintenanceID Maintenance to modify
* @ param { number } statusPages ID of status page to add
* @ param { socketCB } callback Callback for socket response
* @ returns { void }
2023-01-05 22:55:51 +00:00
* /
2022-04-30 17:17:22 +02:00
addMaintenanceStatusPage ( maintenanceID , statusPages , callback ) {
socket . emit ( "addMaintenanceStatusPage" , maintenanceID , statusPages , callback ) ;
} ,
2023-01-05 22:55:51 +00:00
/ * *
* Get monitors affected by maintenance
2023-08-11 09:46:41 +02:00
* @ param { number } maintenanceID Maintenance to read
* @ param { socketCB } callback Callback for socket response
* @ returns { void }
2023-01-05 22:55:51 +00:00
* /
2022-01-23 15:22:00 +01:00
getMonitorMaintenance ( maintenanceID , callback ) {
socket . emit ( "getMonitorMaintenance" , maintenanceID , callback ) ;
} ,
2023-01-05 22:55:51 +00:00
/ * *
* Get status pages where maintenance is shown
2023-08-11 09:46:41 +02:00
* @ param { number } maintenanceID Maintenance to read
* @ param { socketCB } callback Callback for socket response
* @ returns { void }
2023-01-05 22:55:51 +00:00
* /
2022-04-30 17:17:22 +02:00
getMaintenanceStatusPage ( maintenanceID , callback ) {
socket . emit ( "getMaintenanceStatusPage" , maintenanceID , callback ) ;
} ,
2022-06-02 10:38:17 +01:00
/ * *
* Delete monitor by ID
* @ param { number } monitorID ID of monitor to delete
2023-08-11 09:46:41 +02:00
* @ param { socketCB } callback Callback for socket response
* @ returns { void }
2022-06-02 10:38:17 +01:00
* /
2021-06-25 21:55:49 +08:00
deleteMonitor ( monitorID , callback ) {
2021-09-21 21:22:35 +08:00
socket . emit ( "deleteMonitor" , monitorID , callback ) ;
2021-06-25 21:55:49 +08:00
} ,
2023-01-05 22:55:51 +00:00
/ * *
* Delete specified maintenance
2023-08-11 09:46:41 +02:00
* @ param { number } maintenanceID Maintenance to delete
* @ param { socketCB } callback Callback for socket response
* @ returns { void }
2023-01-05 22:55:51 +00:00
* /
2022-01-23 15:22:00 +01:00
deleteMaintenance ( maintenanceID , callback ) {
socket . emit ( "deleteMaintenance" , maintenanceID , callback ) ;
} ,
2023-02-14 19:49:04 +00:00
/ * *
* Add an API key
2023-08-11 09:46:41 +02:00
* @ param { object } key API key to add
* @ param { socketCB } callback Callback for socket response
* @ returns { void }
2023-02-14 19:49:04 +00:00
* /
addAPIKey ( key , callback ) {
socket . emit ( "addAPIKey" , key , callback ) ;
} ,
/ * *
* Delete specified API key
* @ param { int } keyID ID of key to delete
2023-08-11 09:46:41 +02:00
* @ param { socketCB } callback Callback for socket response
* @ returns { void }
2023-02-14 19:49:04 +00:00
* /
deleteAPIKey ( keyID , callback ) {
socket . emit ( "deleteAPIKey" , keyID , callback ) ;
} ,
2023-08-11 09:46:41 +02:00
/ * *
* Clear the hearbeat list
* @ returns { void }
* /
2021-06-30 21:04:58 +08:00
clearData ( ) {
2021-09-21 21:22:35 +08:00
console . log ( "reset heartbeat list" ) ;
this . heartbeatList = { } ;
2021-06-30 21:04:58 +08:00
} ,
2022-06-02 10:38:17 +01:00
/ * *
* Upload the provided backup
* @ param { string } uploadedJSON JSON to upload
* @ param { string } importHandle Type of import . If set to
* most data in database will be replaced
2023-08-11 09:46:41 +02:00
* @ param { socketCB } callback Callback for socket response
* @ returns { void }
2022-06-02 10:38:17 +01:00
* /
2021-09-11 21:53:17 +02:00
uploadBackup ( uploadedJSON , importHandle , callback ) {
2021-09-21 21:22:35 +08:00
socket . emit ( "uploadBackup" , uploadedJSON , importHandle , callback ) ;
2021-09-01 17:09:32 +02:00
} ,
2021-09-07 14:12:53 +02:00
2022-06-02 10:38:17 +01:00
/ * *
* Clear events for a specified monitor
* @ param { number } monitorID ID of monitor to clear
2023-08-11 09:46:41 +02:00
* @ param { socketCB } callback Callback for socket response
* @ returns { void }
2022-06-02 10:38:17 +01:00
* /
2021-08-29 18:47:01 +02:00
clearEvents ( monitorID , callback ) {
2021-09-21 21:22:35 +08:00
socket . emit ( "clearEvents" , monitorID , callback ) ;
2021-08-29 18:47:01 +02:00
} ,
2022-06-02 10:38:17 +01:00
/ * *
* Clear the heartbeats of a specified monitor
* @ param { number } monitorID Id of monitor to clear
2023-08-11 09:46:41 +02:00
* @ param { socketCB } callback Callback for socket response
* @ returns { void }
2022-06-02 10:38:17 +01:00
* /
2021-08-29 18:47:01 +02:00
clearHeartbeats ( monitorID , callback ) {
2021-09-21 21:22:35 +08:00
socket . emit ( "clearHeartbeats" , monitorID , callback ) ;
2021-08-29 18:47:01 +02:00
} ,
2021-09-01 00:36:24 +02:00
2022-06-02 10:38:17 +01:00
/ * *
* Clear all statistics
2023-08-11 09:46:41 +02:00
* @ param { socketCB } callback Callback for socket response
* @ returns { void }
2022-06-02 10:38:17 +01:00
* /
2021-09-01 00:36:24 +02:00
clearStatistics ( callback ) {
2021-09-21 21:22:35 +08:00
socket . emit ( "clearStatistics" , callback ) ;
2021-09-01 00:36:24 +02:00
} ,
2021-10-18 19:00:39 +08:00
2022-06-02 10:38:17 +01:00
/ * *
* Get monitor beats for a specific monitor in a time range
* @ param { number } monitorID ID of monitor to fetch
* @ param { number } period Time in hours from now
2023-08-11 09:46:41 +02:00
* @ param { socketCB } callback Callback for socket response
* @ returns { void }
2022-06-02 10:38:17 +01:00
* /
2021-10-18 19:00:39 +08:00
getMonitorBeats ( monitorID , period , callback ) {
socket . emit ( "getMonitorBeats" , monitorID , period , callback ) ;
2023-09-06 19:52:54 +08:00
} ,
2024-05-20 04:03:32 +08:00
/ * *
* Retrieves monitor chart data .
* @ param { string } monitorID - The ID of the monitor .
* @ param { number } period - The time period for the chart data , in hours .
* @ param { socketCB } callback - The callback function to handle the chart data .
* @ returns { void }
* /
getMonitorChartData ( monitorID , period , callback ) {
socket . emit ( "getMonitorChartData" , monitorID , period , callback ) ;
}
2021-06-25 21:55:49 +08:00
} ,
computed : {
2021-07-01 21:47:14 +08:00
2022-04-19 19:40:28 +08:00
usernameFirstChar ( ) {
if ( typeof this . username == "string" && this . username . length >= 1 ) {
return this . username . charAt ( 0 ) . toUpperCase ( ) ;
} else {
return "🐻" ;
}
} ,
2021-06-27 16:10:55 +08:00
lastHeartbeatList ( ) {
2021-09-21 21:22:35 +08:00
let result = { } ;
2021-06-27 16:10:55 +08:00
for ( let monitorID in this . heartbeatList ) {
let index = this . heartbeatList [ monitorID ] . length - 1 ;
result [ monitorID ] = this . heartbeatList [ monitorID ] [ index ] ;
}
return result ;
} ,
statusList ( ) {
2021-09-21 21:22:35 +08:00
let result = { } ;
2021-06-25 21:55:49 +08:00
2021-06-27 16:10:55 +08:00
let unknown = {
2021-10-19 00:19:26 +08:00
text : this . $t ( "Unknown" ) ,
2021-07-27 19:47:13 +02:00
color : "secondary" ,
2021-09-21 21:22:35 +08:00
} ;
2021-06-27 16:10:55 +08:00
for ( let monitorID in this . lastHeartbeatList ) {
2021-09-21 21:22:35 +08:00
let lastHeartBeat = this . lastHeartbeatList [ monitorID ] ;
2021-06-27 16:10:55 +08:00
2023-01-17 17:34:47 +08:00
if ( ! lastHeartBeat ) {
2021-06-27 16:10:55 +08:00
result [ monitorID ] = unknown ;
2023-01-17 17:34:47 +08:00
} else if ( lastHeartBeat . status === UP ) {
2021-06-27 16:10:55 +08:00
result [ monitorID ] = {
2021-10-19 00:19:26 +08:00
text : this . $t ( "Up" ) ,
2021-07-27 19:47:13 +02:00
color : "primary" ,
2021-06-27 16:10:55 +08:00
} ;
2023-01-17 17:34:47 +08:00
} else if ( lastHeartBeat . status === DOWN ) {
2021-06-27 16:10:55 +08:00
result [ monitorID ] = {
2021-10-19 00:19:26 +08:00
text : this . $t ( "Down" ) ,
2021-07-27 19:47:13 +02:00
color : "danger" ,
2021-06-27 16:10:55 +08:00
} ;
2023-01-17 17:34:47 +08:00
} else if ( lastHeartBeat . status === PENDING ) {
2021-07-19 18:23:06 +02:00
result [ monitorID ] = {
2021-10-19 00:19:26 +08:00
text : this . $t ( "Pending" ) ,
2021-07-27 19:47:13 +02:00
color : "warning" ,
2021-07-19 18:23:06 +02:00
} ;
2023-01-17 17:34:47 +08:00
} else if ( lastHeartBeat . status === MAINTENANCE ) {
result [ monitorID ] = {
text : this . $t ( "statusMaintenance" ) ,
color : "maintenance" ,
} ;
2021-06-27 16:10:55 +08:00
} else {
result [ monitorID ] = unknown ;
}
}
return result ;
2021-07-27 19:47:13 +02:00
} ,
2022-03-12 15:10:45 +08:00
stats ( ) {
let result = {
2023-06-26 13:23:06 +08:00
active : 0 ,
2022-03-12 15:10:45 +08:00
up : 0 ,
down : 0 ,
2022-04-30 14:33:54 +02:00
maintenance : 0 ,
2023-06-26 13:23:06 +08:00
pending : 0 ,
2022-03-12 15:10:45 +08:00
unknown : 0 ,
pause : 0 ,
} ;
for ( let monitorID in this . $root . monitorList ) {
let beat = this . $root . lastHeartbeatList [ monitorID ] ;
let monitor = this . $root . monitorList [ monitorID ] ;
2023-01-17 17:25:35 +08:00
if ( monitor && ! monitor . active ) {
2022-03-12 15:10:45 +08:00
result . pause ++ ;
} else if ( beat ) {
2023-06-26 13:23:06 +08:00
result . active ++ ;
2023-01-17 17:25:35 +08:00
if ( beat . status === UP ) {
2022-03-12 15:10:45 +08:00
result . up ++ ;
2023-01-17 17:25:35 +08:00
} else if ( beat . status === DOWN ) {
2022-03-12 15:10:45 +08:00
result . down ++ ;
2023-01-17 17:25:35 +08:00
} else if ( beat . status === PENDING ) {
2023-06-26 13:23:06 +08:00
result . pending ++ ;
2023-01-17 17:25:35 +08:00
} else if ( beat . status === MAINTENANCE ) {
result . maintenance ++ ;
2022-03-12 15:10:45 +08:00
} else {
result . unknown ++ ;
}
} else {
result . unknown ++ ;
}
}
return result ;
} ,
2022-06-28 21:55:05 +08:00
/ * *
* Frontend Version
* It should be compiled to a static value while building the frontend .
* Please see . / config / vite . config . js , it is defined via vite . js
2023-08-11 09:46:41 +02:00
* @ returns { string } Current version
2022-06-28 21:55:05 +08:00
* /
frontendVersion ( ) {
// eslint-disable-next-line no-undef
return FRONTEND _VERSION ;
} ,
/ * *
* Are both frontend and backend in the same version ?
2023-08-11 09:46:41 +02:00
* @ returns { boolean } The frontend and backend match ?
2022-06-28 21:55:05 +08:00
* /
isFrontendBackendVersionMatched ( ) {
if ( ! this . info . version ) {
return true ;
}
return this . info . version === this . frontendVersion ;
}
2021-07-01 22:16:02 +08:00
} ,
watch : {
2022-03-12 15:10:45 +08:00
// Update Badge
"stats.down" ( to , from ) {
if ( to !== from ) {
2023-08-01 15:12:17 +08:00
if ( this . faviconUpdateDebounce != null ) {
clearTimeout ( this . faviconUpdateDebounce ) ;
}
this . faviconUpdateDebounce = setTimeout ( ( ) => {
favicon . badge ( to ) ;
} , 1000 ) ;
2022-03-12 15:10:45 +08:00
}
} ,
2021-07-13 18:08:12 +08:00
// Reload the SPA if the server version is changed.
"info.version" ( to , from ) {
2021-07-27 19:47:13 +02:00
if ( from && from !== to ) {
2021-09-21 21:22:35 +08:00
window . location . reload ( ) ;
2021-07-27 19:47:13 +02:00
}
2021-07-13 18:08:12 +08:00
} ,
2021-07-01 22:16:02 +08:00
remember ( ) {
2021-09-21 21:22:35 +08:00
localStorage . remember = ( this . remember ) ? "1" : "0" ;
2021-07-27 19:47:13 +02:00
} ,
2021-07-01 22:16:02 +08:00
2021-09-11 16:22:30 +08:00
// Reconnect the socket io, if status-page to dashboard
"$route.fullPath" ( newValue , oldValue ) {
2022-03-15 12:00:29 +08:00
if ( newValue ) {
for ( let page of noSocketIOPages ) {
if ( newValue . match ( page ) ) {
return ;
}
}
2021-09-11 16:22:30 +08:00
}
2022-03-15 12:00:29 +08:00
2021-09-11 16:22:30 +08:00
this . initSocketIO ( ) ;
} ,
2021-07-27 19:47:13 +02:00
} ,
2021-06-25 21:55:49 +08:00
2021-09-21 21:22:35 +08:00
} ;