2021-07-27 17:47:13 +00:00
import { io } from "socket.io-client" ;
import { useToast } from "vue-toastification" ;
2021-11-09 14:37:05 +00:00
import jwt _decode from "jwt-decode" ;
2021-09-21 13:22:35 +00:00
const toast = useToast ( ) ;
2021-06-25 13:55:49 +00:00
let socket ;
2021-09-11 11:40:03 +00:00
const noSocketIOPages = [
2021-09-11 08:22:30 +00:00
"/status-page" ,
2021-09-25 14:44:29 +00:00
"/status" ,
2021-09-23 05:57:24 +00:00
"/"
2021-09-11 08:22:30 +00:00
] ;
2021-06-25 13:55:49 +00:00
export default {
data ( ) {
return {
2021-07-13 10:08:12 +00:00
info : { } ,
2021-06-25 13:55:49 +00:00
socket : {
token : null ,
firstConnect : true ,
connected : false ,
2021-06-29 08:06:20 +00:00
connectCount : 0 ,
2021-09-11 08:22:30 +00:00
initedSocketIO : false ,
2021-06-25 13:55:49 +00:00
} ,
2021-07-01 14:16:02 +00:00
remember : ( localStorage . remember !== "0" ) ,
2021-06-25 13:55:49 +00: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 05:11:16 +00:00
monitorList : { } ,
heartbeatList : { } ,
importantHeartbeatList : { } ,
avgPingList : { } ,
2021-07-09 06:14:03 +00:00
uptimeList : { } ,
2021-10-01 10:44:32 +00:00
tlsInfoList : { } ,
2021-07-09 06:14:03 +00:00
notificationList : [ ] ,
2021-08-08 05:47:29 +00:00
connectionErrorMsg : "Cannot connect to the socket server. Reconnecting..." ,
2021-09-21 13:22:35 +00:00
} ;
2021-06-25 13:55:49 +00:00
} ,
created ( ) {
2021-07-27 17:47:13 +00:00
window . addEventListener ( "resize" , this . onResize ) ;
2021-09-11 08:22:30 +00:00
this . initSocketIO ( ) ;
} ,
2021-07-11 07:23:28 +00:00
2021-09-11 08:22:30 +00:00
methods : {
2021-09-11 06:37:05 +00:00
2021-09-11 08:22:30 +00:00
initSocketIO ( bypass = false ) {
// No need to re-init
if ( this . socket . initedSocketIO ) {
return ;
}
2021-07-11 06:20:31 +00:00
2021-09-11 08:22:30 +00:00
// No need to connect to the socket.io for status page
2021-09-11 11:40:03 +00:00
if ( ! bypass && noSocketIOPages . includes ( location . pathname ) ) {
2021-09-11 08:22:30 +00:00
return ;
}
this . socket . initedSocketIO = true ;
2021-06-25 13:55:49 +00:00
2021-09-11 08:22:30 +00:00
let protocol = ( location . protocol === "https:" ) ? "wss://" : "ws://" ;
2021-07-09 06:14:03 +00:00
2021-09-11 08:22:30 +00:00
let wsHost ;
const env = process . env . NODE _ENV || "production" ;
if ( env === "development" || localStorage . dev === "dev" ) {
wsHost = protocol + location . hostname + ":3001" ;
} else {
wsHost = protocol + location . host ;
2021-06-27 08:10:55 +00:00
}
2021-09-11 08:22:30 +00:00
socket = io ( wsHost , {
transports : [ "websocket" ] ,
} ) ;
2021-06-30 13:04:58 +00:00
2021-09-11 08:22:30 +00:00
socket . on ( "info" , ( info ) => {
this . info = info ;
} ) ;
2021-06-30 13:04:58 +00:00
2021-09-11 08:22:30 +00:00
socket . on ( "setup" , ( monitorID , data ) => {
2021-09-21 13:22:35 +00:00
this . $router . push ( "/setup" ) ;
2021-09-11 08:22:30 +00:00
} ) ;
2021-06-30 13:04:58 +00:00
2021-09-11 08:22:30 +00:00
socket . on ( "autoLogin" , ( monitorID , data ) => {
this . loggedIn = true ;
this . storage ( ) . token = "autoLogin" ;
this . allowLoginDialog = false ;
} ) ;
socket . on ( "monitorList" , ( data ) => {
// Add Helper function
Object . entries ( data ) . forEach ( ( [ monitorID , monitor ] ) => {
monitor . getUrl = ( ) => {
try {
return new URL ( monitor . url ) ;
} catch ( _ ) {
return null ;
}
} ;
} ) ;
this . monitorList = data ;
} ) ;
socket . on ( "notificationList" , ( data ) => {
this . notificationList = data ;
} ) ;
socket . on ( "heartbeat" , ( data ) => {
if ( ! ( data . monitorID in this . heartbeatList ) ) {
this . heartbeatList [ data . monitorID ] = [ ] ;
2021-06-30 13:04:58 +00:00
}
2021-09-16 14:48:28 +00:00
this . heartbeatList [ data . monitorID ] . push ( data ) ;
if ( this . heartbeatList [ data . monitorID ] . length >= 150 ) {
this . heartbeatList [ data . monitorID ] . shift ( ) ;
}
2021-09-11 08:22:30 +00:00
// Add to important list if it is important
// Also toast
if ( data . important ) {
if ( data . status === 0 ) {
toast . error ( ` [ ${ this . monitorList [ data . monitorID ] . name } ] [DOWN] ${ data . msg } ` , {
timeout : false ,
} ) ;
} else if ( data . status === 1 ) {
toast . success ( ` [ ${ this . monitorList [ data . monitorID ] . name } ] [Up] ${ data . msg } ` , {
timeout : 20000 ,
} ) ;
} else {
toast ( ` [ ${ this . monitorList [ data . monitorID ] . name } ] ${ data . msg } ` ) ;
}
2021-06-27 08:10:55 +00:00
2021-09-11 08:22:30 +00:00
if ( ! ( data . monitorID in this . importantHeartbeatList ) ) {
this . importantHeartbeatList [ data . monitorID ] = [ ] ;
}
2021-06-29 08:06:20 +00:00
2021-09-21 13:22:35 +00:00
this . importantHeartbeatList [ data . monitorID ] . unshift ( data ) ;
2021-09-11 08:22:30 +00:00
}
} ) ;
2021-06-30 13:04:58 +00:00
2021-09-11 08:22:30 +00:00
socket . on ( "heartbeatList" , ( monitorID , data , overwrite = false ) => {
if ( ! ( monitorID in this . heartbeatList ) || overwrite ) {
this . heartbeatList [ monitorID ] = data ;
} else {
2021-09-21 13:22:35 +00:00
this . heartbeatList [ monitorID ] = data . concat ( this . heartbeatList [ monitorID ] ) ;
2021-09-11 08:22:30 +00:00
}
} ) ;
2021-07-01 05:11:16 +00:00
2021-09-11 08:22:30 +00:00
socket . on ( "avgPing" , ( monitorID , data ) => {
2021-09-21 13:22:35 +00:00
this . avgPingList [ monitorID ] = data ;
2021-09-11 08:22:30 +00:00
} ) ;
2021-07-21 04:09:09 +00:00
2021-09-11 08:22:30 +00:00
socket . on ( "uptime" , ( monitorID , type , data ) => {
2021-09-21 13:22:35 +00:00
this . uptimeList [ ` ${ monitorID } _ ${ type } ` ] = data ;
2021-09-11 08:22:30 +00:00
} ) ;
2021-06-25 13:55:49 +00:00
2021-09-11 08:22:30 +00:00
socket . on ( "certInfo" , ( monitorID , data ) => {
2021-10-01 10:44:32 +00:00
this . tlsInfoList [ monitorID ] = JSON . parse ( data ) ;
2021-09-11 08:22:30 +00:00
} ) ;
2021-07-31 15:41:24 +00:00
2021-09-11 08:22:30 +00:00
socket . on ( "importantHeartbeatList" , ( monitorID , data , overwrite ) => {
if ( ! ( monitorID in this . importantHeartbeatList ) || overwrite ) {
this . importantHeartbeatList [ monitorID ] = data ;
2021-08-03 05:07:20 +00:00
} else {
2021-09-21 13:22:35 +00:00
this . importantHeartbeatList [ monitorID ] = data . concat ( this . importantHeartbeatList [ monitorID ] ) ;
2021-09-11 08:22:30 +00:00
}
} ) ;
2021-08-03 05:07:20 +00:00
2021-09-11 08:22:30 +00:00
socket . on ( "connect_error" , ( err ) => {
console . error ( ` Failed to connect to the backend. Socket.io connect_error: ${ err . message } ` ) ;
this . connectionErrorMsg = ` Cannot connect to the socket server. [ ${ err } ] Reconnecting... ` ;
this . socket . connected = false ;
this . socket . firstConnect = false ;
} ) ;
2021-08-03 05:07:20 +00:00
2021-09-11 08:22:30 +00:00
socket . on ( "disconnect" , ( ) => {
2021-09-21 13:22:35 +00:00
console . log ( "disconnect" ) ;
2021-09-11 08:22:30 +00:00
this . connectionErrorMsg = "Lost connection to the socket server. Reconnecting..." ;
this . socket . connected = false ;
} ) ;
socket . on ( "connect" , ( ) => {
2021-10-05 12:27:43 +00:00
console . log ( "Connected to the socket server" ) ;
2021-09-11 08:22:30 +00:00
this . socket . connectCount ++ ;
this . socket . connected = true ;
// Reset Heartbeat list if it is re-connect
if ( this . socket . connectCount >= 2 ) {
2021-09-21 13:22:35 +00:00
this . clearData ( ) ;
2021-07-31 15:41:24 +00:00
}
2021-06-25 13:55:49 +00:00
2021-09-11 08:22:30 +00:00
let token = this . storage ( ) . token ;
2021-06-25 13:55:49 +00:00
2021-09-11 08:22:30 +00:00
if ( token ) {
if ( token !== "autoLogin" ) {
2021-09-21 13:22:35 +00:00
this . loginByToken ( token ) ;
2021-09-11 08:22:30 +00:00
} else {
2021-06-25 13:55:49 +00:00
2021-09-11 08:22:30 +00:00
// Timeout if it is not actually auto login
setTimeout ( ( ) => {
if ( ! this . loggedIn ) {
this . allowLoginDialog = true ;
this . $root . storage ( ) . removeItem ( "token" ) ;
}
} , 5000 ) ;
}
} else {
this . allowLoginDialog = true ;
}
this . socket . firstConnect = false ;
} ) ;
} ,
2021-06-27 08:10:55 +00:00
2021-07-01 14:16:02 +00:00
storage ( ) {
return ( this . remember ) ? localStorage : sessionStorage ;
} ,
2021-11-09 14:37:05 +00:00
getJWTPayload ( ) {
const jwtToken = this . $root . storage ( ) . token ;
if ( jwtToken && jwtToken !== "autoLogin" ) {
return jwt _decode ( jwtToken ) ;
}
return undefined ;
} ,
2021-06-25 13:55:49 +00:00
getSocket ( ) {
2021-07-18 18:46:45 +00:00
return socket ;
2021-06-25 13:55:49 +00:00
} ,
2021-06-27 08:10:55 +00:00
2021-06-25 13:55:49 +00:00
toastRes ( res ) {
if ( res . ok ) {
toast . success ( res . msg ) ;
} else {
toast . error ( res . msg ) ;
}
} ,
2021-06-27 08:10:55 +00:00
2021-09-09 19:10:31 +00:00
login ( username , password , token , callback ) {
2021-06-25 13:55:49 +00:00
socket . emit ( "login" , {
username ,
password ,
2021-09-09 19:10:31 +00:00
token ,
2021-06-25 13:55:49 +00:00
} , ( res ) => {
2021-09-09 19:10:31 +00:00
if ( res . tokenRequired ) {
2021-09-21 13:22:35 +00:00
callback ( res ) ;
2021-09-09 19:10:31 +00:00
}
2021-06-25 13:55:49 +00:00
if ( res . ok ) {
2021-07-01 14:16:02 +00:00
this . storage ( ) . token = res . token ;
2021-06-25 13:55:49 +00:00
this . socket . token = res . token ;
this . loggedIn = true ;
// Trigger Chrome Save Password
2021-09-21 13:22:35 +00:00
history . pushState ( { } , "" ) ;
2021-06-25 13:55:49 +00:00
}
2021-09-21 13:22:35 +00:00
callback ( res ) ;
} ) ;
2021-06-25 13:55:49 +00:00
} ,
2021-06-27 08:10:55 +00:00
2021-06-25 13:55:49 +00:00
loginByToken ( token ) {
socket . emit ( "loginByToken" , token , ( res ) => {
this . allowLoginDialog = true ;
if ( ! res . ok ) {
2021-09-21 13:22:35 +00:00
this . logout ( ) ;
2021-06-25 13:55:49 +00:00
} else {
this . loggedIn = true ;
}
2021-09-21 13:22:35 +00:00
} ) ;
2021-06-25 13:55:49 +00:00
} ,
2021-06-27 08:10:55 +00:00
2021-06-25 13:55:49 +00:00
logout ( ) {
2021-10-30 15:33:20 +00:00
socket . emit ( "logout" , ( ) => { } ) ;
2021-07-01 14:16:02 +00:00
this . storage ( ) . removeItem ( "token" ) ;
2021-06-25 13:55:49 +00:00
this . socket . token = null ;
2021-06-30 13:04:58 +00:00
this . loggedIn = false ;
2021-09-21 13:22:35 +00:00
this . clearData ( ) ;
2021-06-25 13:55:49 +00:00
} ,
2021-06-27 08:10:55 +00:00
2021-09-09 19:10:31 +00:00
prepare2FA ( callback ) {
2021-09-21 13:22:35 +00:00
socket . emit ( "prepare2FA" , callback ) ;
2021-09-09 19:10:31 +00:00
} ,
save2FA ( secret , callback ) {
2021-09-21 13:22:35 +00:00
socket . emit ( "save2FA" , callback ) ;
2021-09-09 19:10:31 +00:00
} ,
disable2FA ( callback ) {
2021-09-21 13:22:35 +00:00
socket . emit ( "disable2FA" , callback ) ;
2021-09-09 19:10:31 +00:00
} ,
verifyToken ( token , callback ) {
2021-09-21 13:22:35 +00:00
socket . emit ( "verifyToken" , token , callback ) ;
2021-09-09 19:10:31 +00:00
} ,
twoFAStatus ( callback ) {
2021-09-21 13:22:35 +00:00
socket . emit ( "twoFAStatus" , callback ) ;
2021-09-09 19:10:31 +00:00
} ,
2021-08-26 10:55:19 +00:00
getMonitorList ( callback ) {
2021-10-01 07:47:51 +00:00
if ( ! callback ) {
callback = ( ) => { } ;
}
2021-09-21 13:22:35 +00:00
socket . emit ( "getMonitorList" , callback ) ;
2021-08-26 10:55:19 +00:00
} ,
2021-06-25 13:55:49 +00:00
add ( monitor , callback ) {
2021-09-21 13:22:35 +00:00
socket . emit ( "add" , monitor , callback ) ;
2021-06-25 13:55:49 +00:00
} ,
2021-06-27 08:10:55 +00:00
2021-06-25 13:55:49 +00:00
deleteMonitor ( monitorID , callback ) {
2021-09-21 13:22:35 +00:00
socket . emit ( "deleteMonitor" , monitorID , callback ) ;
2021-06-25 13:55:49 +00:00
} ,
2021-06-30 13:04:58 +00:00
clearData ( ) {
2021-09-21 13:22:35 +00:00
console . log ( "reset heartbeat list" ) ;
this . heartbeatList = { } ;
this . importantHeartbeatList = { } ;
2021-06-30 13:04:58 +00:00
} ,
2021-09-11 19:53:17 +00:00
uploadBackup ( uploadedJSON , importHandle , callback ) {
2021-09-21 13:22:35 +00:00
socket . emit ( "uploadBackup" , uploadedJSON , importHandle , callback ) ;
2021-09-01 15:09:32 +00:00
} ,
2021-09-07 12:12:53 +00:00
2021-08-29 16:47:01 +00:00
clearEvents ( monitorID , callback ) {
2021-09-21 13:22:35 +00:00
socket . emit ( "clearEvents" , monitorID , callback ) ;
2021-08-29 16:47:01 +00:00
} ,
clearHeartbeats ( monitorID , callback ) {
2021-09-21 13:22:35 +00:00
socket . emit ( "clearHeartbeats" , monitorID , callback ) ;
2021-08-29 16:47:01 +00:00
} ,
2021-08-31 22:36:24 +00:00
clearStatistics ( callback ) {
2021-09-21 13:22:35 +00:00
socket . emit ( "clearStatistics" , callback ) ;
2021-08-31 22:36:24 +00:00
} ,
2021-10-18 11:00:39 +00:00
getMonitorBeats ( monitorID , period , callback ) {
socket . emit ( "getMonitorBeats" , monitorID , period , callback ) ;
}
2021-06-25 13:55:49 +00:00
} ,
computed : {
2021-07-01 13:47:14 +00:00
2021-06-27 08:10:55 +00:00
lastHeartbeatList ( ) {
2021-09-21 13:22:35 +00:00
let result = { } ;
2021-06-27 08:10:55 +00: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 13:22:35 +00:00
let result = { } ;
2021-06-25 13:55:49 +00:00
2021-06-27 08:10:55 +00:00
let unknown = {
2021-10-18 16:19:26 +00:00
text : this . $t ( "Unknown" ) ,
2021-07-27 17:47:13 +00:00
color : "secondary" ,
2021-09-21 13:22:35 +00:00
} ;
2021-06-27 08:10:55 +00:00
for ( let monitorID in this . lastHeartbeatList ) {
2021-09-21 13:22:35 +00:00
let lastHeartBeat = this . lastHeartbeatList [ monitorID ] ;
2021-06-27 08:10:55 +00:00
if ( ! lastHeartBeat ) {
result [ monitorID ] = unknown ;
} else if ( lastHeartBeat . status === 1 ) {
result [ monitorID ] = {
2021-10-18 16:19:26 +00:00
text : this . $t ( "Up" ) ,
2021-07-27 17:47:13 +00:00
color : "primary" ,
2021-06-27 08:10:55 +00:00
} ;
} else if ( lastHeartBeat . status === 0 ) {
result [ monitorID ] = {
2021-10-18 16:19:26 +00:00
text : this . $t ( "Down" ) ,
2021-07-27 17:47:13 +00:00
color : "danger" ,
2021-06-27 08:10:55 +00:00
} ;
2021-07-19 16:23:06 +00:00
} else if ( lastHeartBeat . status === 2 ) {
result [ monitorID ] = {
2021-10-18 16:19:26 +00:00
text : this . $t ( "Pending" ) ,
2021-07-27 17:47:13 +00:00
color : "warning" ,
2021-07-19 16:23:06 +00:00
} ;
2021-06-27 08:10:55 +00:00
} else {
result [ monitorID ] = unknown ;
}
}
return result ;
2021-07-27 17:47:13 +00:00
} ,
2021-07-01 14:16:02 +00:00
} ,
watch : {
2021-07-13 10:08:12 +00:00
// Reload the SPA if the server version is changed.
"info.version" ( to , from ) {
2021-07-27 17:47:13 +00:00
if ( from && from !== to ) {
2021-09-21 13:22:35 +00:00
window . location . reload ( ) ;
2021-07-27 17:47:13 +00:00
}
2021-07-13 10:08:12 +00:00
} ,
2021-07-01 14:16:02 +00:00
remember ( ) {
2021-09-21 13:22:35 +00:00
localStorage . remember = ( this . remember ) ? "1" : "0" ;
2021-07-27 17:47:13 +00:00
} ,
2021-07-01 14:16:02 +00:00
2021-09-11 08:22:30 +00:00
// Reconnect the socket io, if status-page to dashboard
"$route.fullPath" ( newValue , oldValue ) {
2021-09-11 11:40:03 +00:00
if ( noSocketIOPages . includes ( newValue ) ) {
2021-09-11 08:22:30 +00:00
return ;
}
this . initSocketIO ( ) ;
} ,
2021-07-27 17:47:13 +00:00
} ,
2021-06-25 13:55:49 +00:00
2021-09-21 13:22:35 +00:00
} ;