|  |  | @ -8,12 +8,12 @@ console.log("Node Env: " + process.env.NODE_ENV); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | const { sleep, debug, TimeLogger, getRandomInt } = require("../src/util"); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | console.log("Importing Node libraries") | 
			
		
	
		
			
				
					|  |  |  | console.log("Importing Node libraries"); | 
			
		
	
		
			
				
					|  |  |  | const fs = require("fs"); | 
			
		
	
		
			
				
					|  |  |  | const http = require("http"); | 
			
		
	
		
			
				
					|  |  |  | const https = require("https"); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | console.log("Importing 3rd-party libraries") | 
			
		
	
		
			
				
					|  |  |  | console.log("Importing 3rd-party libraries"); | 
			
		
	
		
			
				
					|  |  |  | debug("Importing express"); | 
			
		
	
		
			
				
					|  |  |  | const express = require("express"); | 
			
		
	
		
			
				
					|  |  |  | debug("Importing socket.io"); | 
			
		
	
	
		
			
				
					|  |  | @ -70,7 +70,7 @@ if (! fs.existsSync(Database.dataDir)) { | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | console.log(`Data Dir: ${Database.dataDir}`); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | console.log("Creating express and socket.io instance") | 
			
		
	
		
			
				
					|  |  |  | console.log("Creating express and socket.io instance"); | 
			
		
	
		
			
				
					|  |  |  | const app = express(); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | let server; | 
			
		
	
	
		
			
				
					|  |  | @ -157,6 +157,9 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     app.use("/", express.static("dist")); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     // ./data/upload
 | 
			
		
	
		
			
				
					|  |  |  |     app.use("/upload", express.static(Database.uploadDir)); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     app.get("/.well-known/change-password", async (_, response) => { | 
			
		
	
		
			
				
					|  |  |  |         response.redirect("https://github.com/louislam/uptime-kuma/wiki/Reset-Password-via-CLI"); | 
			
		
	
		
			
				
					|  |  |  |     }); | 
			
		
	
	
		
			
				
					|  |  | @ -167,22 +170,26 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     // Universal Route Handler, must be at the end of all express route.
 | 
			
		
	
		
			
				
					|  |  |  |     app.get("*", async (_request, response) => { | 
			
		
	
		
			
				
					|  |  |  |         if (_request.originalUrl.startsWith("/upload/")) { | 
			
		
	
		
			
				
					|  |  |  |             response.status(404).send("File not found."); | 
			
		
	
		
			
				
					|  |  |  |         } else { | 
			
		
	
		
			
				
					|  |  |  |             response.send(indexHTML); | 
			
		
	
		
			
				
					|  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |     }); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     console.log("Adding socket handler") | 
			
		
	
		
			
				
					|  |  |  |     console.log("Adding socket handler"); | 
			
		
	
		
			
				
					|  |  |  |     io.on("connection", async (socket) => { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         socket.emit("info", { | 
			
		
	
		
			
				
					|  |  |  |             version: checkVersion.version, | 
			
		
	
		
			
				
					|  |  |  |             latestVersion: checkVersion.latestVersion, | 
			
		
	
		
			
				
					|  |  |  |         }) | 
			
		
	
		
			
				
					|  |  |  |         }); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         totalClient++; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         if (needSetup) { | 
			
		
	
		
			
				
					|  |  |  |             console.log("Redirect to setup page") | 
			
		
	
		
			
				
					|  |  |  |             socket.emit("setup") | 
			
		
	
		
			
				
					|  |  |  |             console.log("Redirect to setup page"); | 
			
		
	
		
			
				
					|  |  |  |             socket.emit("setup"); | 
			
		
	
		
			
				
					|  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         socket.on("disconnect", () => { | 
			
		
	
	
		
			
				
					|  |  | @ -198,44 +205,44 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  |             try { | 
			
		
	
		
			
				
					|  |  |  |                 let decoded = jwt.verify(token, jwtSecret); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 console.log("Username from JWT: " + decoded.username) | 
			
		
	
		
			
				
					|  |  |  |                 console.log("Username from JWT: " + decoded.username); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 let user = await R.findOne("user", " username = ? AND active = 1 ", [ | 
			
		
	
		
			
				
					|  |  |  |                     decoded.username, | 
			
		
	
		
			
				
					|  |  |  |                 ]) | 
			
		
	
		
			
				
					|  |  |  |                 ]); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 if (user) { | 
			
		
	
		
			
				
					|  |  |  |                     debug("afterLogin") | 
			
		
	
		
			
				
					|  |  |  |                     debug("afterLogin"); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                     afterLogin(socket, user) | 
			
		
	
		
			
				
					|  |  |  |                     afterLogin(socket, user); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                     debug("afterLogin ok") | 
			
		
	
		
			
				
					|  |  |  |                     debug("afterLogin ok"); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                     callback({ | 
			
		
	
		
			
				
					|  |  |  |                         ok: true, | 
			
		
	
		
			
				
					|  |  |  |                     }) | 
			
		
	
		
			
				
					|  |  |  |                     }); | 
			
		
	
		
			
				
					|  |  |  |                 } else { | 
			
		
	
		
			
				
					|  |  |  |                     callback({ | 
			
		
	
		
			
				
					|  |  |  |                         ok: false, | 
			
		
	
		
			
				
					|  |  |  |                         msg: "The user is inactive or deleted.", | 
			
		
	
		
			
				
					|  |  |  |                     }) | 
			
		
	
		
			
				
					|  |  |  |                     }); | 
			
		
	
		
			
				
					|  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |             } catch (error) { | 
			
		
	
		
			
				
					|  |  |  |                 callback({ | 
			
		
	
		
			
				
					|  |  |  |                     ok: false, | 
			
		
	
		
			
				
					|  |  |  |                     msg: "Invalid token.", | 
			
		
	
		
			
				
					|  |  |  |                 }) | 
			
		
	
		
			
				
					|  |  |  |                 }); | 
			
		
	
		
			
				
					|  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         }); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         socket.on("login", async (data, callback) => { | 
			
		
	
		
			
				
					|  |  |  |             console.log("Login") | 
			
		
	
		
			
				
					|  |  |  |             console.log("Login"); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |             let user = await login(data.username, data.password) | 
			
		
	
		
			
				
					|  |  |  |             let user = await login(data.username, data.password); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |             if (user) { | 
			
		
	
		
			
				
					|  |  |  |                 afterLogin(socket, user) | 
			
		
	
		
			
				
					|  |  |  |                 afterLogin(socket, user); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 if (user.twofaStatus == 0) { | 
			
		
	
		
			
				
					|  |  |  |                     callback({ | 
			
		
	
	
		
			
				
					|  |  | @ -243,13 +250,13 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  |                         token: jwt.sign({ | 
			
		
	
		
			
				
					|  |  |  |                             username: data.username, | 
			
		
	
		
			
				
					|  |  |  |                         }, jwtSecret), | 
			
		
	
		
			
				
					|  |  |  |                     }) | 
			
		
	
		
			
				
					|  |  |  |                     }); | 
			
		
	
		
			
				
					|  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 if (user.twofaStatus == 1 && !data.token) { | 
			
		
	
		
			
				
					|  |  |  |                     callback({ | 
			
		
	
		
			
				
					|  |  |  |                         tokenRequired: true, | 
			
		
	
		
			
				
					|  |  |  |                     }) | 
			
		
	
		
			
				
					|  |  |  |                     }); | 
			
		
	
		
			
				
					|  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 if (data.token) { | 
			
		
	
	
		
			
				
					|  |  | @ -261,39 +268,39 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  |                             token: jwt.sign({ | 
			
		
	
		
			
				
					|  |  |  |                                 username: data.username, | 
			
		
	
		
			
				
					|  |  |  |                             }, jwtSecret), | 
			
		
	
		
			
				
					|  |  |  |                         }) | 
			
		
	
		
			
				
					|  |  |  |                         }); | 
			
		
	
		
			
				
					|  |  |  |                     } else { | 
			
		
	
		
			
				
					|  |  |  |                         callback({ | 
			
		
	
		
			
				
					|  |  |  |                             ok: false, | 
			
		
	
		
			
				
					|  |  |  |                             msg: "Invalid Token!", | 
			
		
	
		
			
				
					|  |  |  |                         }) | 
			
		
	
		
			
				
					|  |  |  |                         }); | 
			
		
	
		
			
				
					|  |  |  |                     } | 
			
		
	
		
			
				
					|  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |             } else { | 
			
		
	
		
			
				
					|  |  |  |                 callback({ | 
			
		
	
		
			
				
					|  |  |  |                     ok: false, | 
			
		
	
		
			
				
					|  |  |  |                     msg: "Incorrect username or password.", | 
			
		
	
		
			
				
					|  |  |  |                 }) | 
			
		
	
		
			
				
					|  |  |  |                 }); | 
			
		
	
		
			
				
					|  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         }); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         socket.on("logout", async (callback) => { | 
			
		
	
		
			
				
					|  |  |  |             socket.leave(socket.userID) | 
			
		
	
		
			
				
					|  |  |  |             socket.leave(socket.userID); | 
			
		
	
		
			
				
					|  |  |  |             socket.userID = null; | 
			
		
	
		
			
				
					|  |  |  |             callback(); | 
			
		
	
		
			
				
					|  |  |  |         }); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         socket.on("prepare2FA", async (callback) => { | 
			
		
	
		
			
				
					|  |  |  |             try { | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket) | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 let user = await R.findOne("user", " id = ? AND active = 1 ", [ | 
			
		
	
		
			
				
					|  |  |  |                     socket.userID, | 
			
		
	
		
			
				
					|  |  |  |                 ]) | 
			
		
	
		
			
				
					|  |  |  |                 ]); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 if (user.twofa_status == 0) { | 
			
		
	
		
			
				
					|  |  |  |                     let newSecret = await genSecret() | 
			
		
	
		
			
				
					|  |  |  |                     let newSecret = await genSecret(); | 
			
		
	
		
			
				
					|  |  |  |                     let encodedSecret = base32.encode(newSecret); | 
			
		
	
		
			
				
					|  |  |  |                     let uri = `otpauth://totp/Uptime%20Kuma:${user.username}?secret=${encodedSecret}`; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  | @ -305,24 +312,24 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  |                     callback({ | 
			
		
	
		
			
				
					|  |  |  |                         ok: true, | 
			
		
	
		
			
				
					|  |  |  |                         uri: uri, | 
			
		
	
		
			
				
					|  |  |  |                     }) | 
			
		
	
		
			
				
					|  |  |  |                     }); | 
			
		
	
		
			
				
					|  |  |  |                 } else { | 
			
		
	
		
			
				
					|  |  |  |                     callback({ | 
			
		
	
		
			
				
					|  |  |  |                         ok: false, | 
			
		
	
		
			
				
					|  |  |  |                         msg: "2FA is already enabled.", | 
			
		
	
		
			
				
					|  |  |  |                     }) | 
			
		
	
		
			
				
					|  |  |  |                     }); | 
			
		
	
		
			
				
					|  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |             } catch (error) { | 
			
		
	
		
			
				
					|  |  |  |                 callback({ | 
			
		
	
		
			
				
					|  |  |  |                     ok: false, | 
			
		
	
		
			
				
					|  |  |  |                     msg: "Error while trying to prepare 2FA.", | 
			
		
	
		
			
				
					|  |  |  |                 }) | 
			
		
	
		
			
				
					|  |  |  |                 }); | 
			
		
	
		
			
				
					|  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |         }); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         socket.on("save2FA", async (callback) => { | 
			
		
	
		
			
				
					|  |  |  |             try { | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket) | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 await R.exec("UPDATE `user` SET twofa_status = 1 WHERE id = ? ", [ | 
			
		
	
		
			
				
					|  |  |  |                     socket.userID, | 
			
		
	
	
		
			
				
					|  |  | @ -331,18 +338,18 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  |                 callback({ | 
			
		
	
		
			
				
					|  |  |  |                     ok: true, | 
			
		
	
		
			
				
					|  |  |  |                     msg: "2FA Enabled.", | 
			
		
	
		
			
				
					|  |  |  |                 }) | 
			
		
	
		
			
				
					|  |  |  |                 }); | 
			
		
	
		
			
				
					|  |  |  |             } catch (error) { | 
			
		
	
		
			
				
					|  |  |  |                 callback({ | 
			
		
	
		
			
				
					|  |  |  |                     ok: false, | 
			
		
	
		
			
				
					|  |  |  |                     msg: "Error while trying to change 2FA.", | 
			
		
	
		
			
				
					|  |  |  |                 }) | 
			
		
	
		
			
				
					|  |  |  |                 }); | 
			
		
	
		
			
				
					|  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |         }); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         socket.on("disable2FA", async (callback) => { | 
			
		
	
		
			
				
					|  |  |  |             try { | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket) | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 await R.exec("UPDATE `user` SET twofa_status = 0 WHERE id = ? ", [ | 
			
		
	
		
			
				
					|  |  |  |                     socket.userID, | 
			
		
	
	
		
			
				
					|  |  | @ -351,19 +358,19 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  |                 callback({ | 
			
		
	
		
			
				
					|  |  |  |                     ok: true, | 
			
		
	
		
			
				
					|  |  |  |                     msg: "2FA Disabled.", | 
			
		
	
		
			
				
					|  |  |  |                 }) | 
			
		
	
		
			
				
					|  |  |  |                 }); | 
			
		
	
		
			
				
					|  |  |  |             } catch (error) { | 
			
		
	
		
			
				
					|  |  |  |                 callback({ | 
			
		
	
		
			
				
					|  |  |  |                     ok: false, | 
			
		
	
		
			
				
					|  |  |  |                     msg: "Error while trying to change 2FA.", | 
			
		
	
		
			
				
					|  |  |  |                 }) | 
			
		
	
		
			
				
					|  |  |  |                 }); | 
			
		
	
		
			
				
					|  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |         }); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         socket.on("verifyToken", async (token, callback) => { | 
			
		
	
		
			
				
					|  |  |  |             let user = await R.findOne("user", " id = ? AND active = 1 ", [ | 
			
		
	
		
			
				
					|  |  |  |                 socket.userID, | 
			
		
	
		
			
				
					|  |  |  |             ]) | 
			
		
	
		
			
				
					|  |  |  |             ]); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |             let verify = notp.totp.verify(token, user.twofa_secret); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  | @ -371,40 +378,40 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  |                 callback({ | 
			
		
	
		
			
				
					|  |  |  |                     ok: true, | 
			
		
	
		
			
				
					|  |  |  |                     valid: true, | 
			
		
	
		
			
				
					|  |  |  |                 }) | 
			
		
	
		
			
				
					|  |  |  |                 }); | 
			
		
	
		
			
				
					|  |  |  |             } else { | 
			
		
	
		
			
				
					|  |  |  |                 callback({ | 
			
		
	
		
			
				
					|  |  |  |                     ok: false, | 
			
		
	
		
			
				
					|  |  |  |                     msg: "Invalid Token.", | 
			
		
	
		
			
				
					|  |  |  |                     valid: false, | 
			
		
	
		
			
				
					|  |  |  |                 }) | 
			
		
	
		
			
				
					|  |  |  |                 }); | 
			
		
	
		
			
				
					|  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |         }); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         socket.on("twoFAStatus", async (callback) => { | 
			
		
	
		
			
				
					|  |  |  |             checkLogin(socket) | 
			
		
	
		
			
				
					|  |  |  |             checkLogin(socket); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |             try { | 
			
		
	
		
			
				
					|  |  |  |                 let user = await R.findOne("user", " id = ? AND active = 1 ", [ | 
			
		
	
		
			
				
					|  |  |  |                     socket.userID, | 
			
		
	
		
			
				
					|  |  |  |                 ]) | 
			
		
	
		
			
				
					|  |  |  |                 ]); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 if (user.twofa_status == 1) { | 
			
		
	
		
			
				
					|  |  |  |                     callback({ | 
			
		
	
		
			
				
					|  |  |  |                         ok: true, | 
			
		
	
		
			
				
					|  |  |  |                         status: true, | 
			
		
	
		
			
				
					|  |  |  |                     }) | 
			
		
	
		
			
				
					|  |  |  |                     }); | 
			
		
	
		
			
				
					|  |  |  |                 } else { | 
			
		
	
		
			
				
					|  |  |  |                     callback({ | 
			
		
	
		
			
				
					|  |  |  |                         ok: true, | 
			
		
	
		
			
				
					|  |  |  |                         status: false, | 
			
		
	
		
			
				
					|  |  |  |                     }) | 
			
		
	
		
			
				
					|  |  |  |                     }); | 
			
		
	
		
			
				
					|  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |             } catch (error) { | 
			
		
	
		
			
				
					|  |  |  |                 callback({ | 
			
		
	
		
			
				
					|  |  |  |                     ok: false, | 
			
		
	
		
			
				
					|  |  |  |                     msg: "Error while trying to get 2FA status.", | 
			
		
	
		
			
				
					|  |  |  |                 }) | 
			
		
	
		
			
				
					|  |  |  |                 }); | 
			
		
	
		
			
				
					|  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |         }); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  | @ -415,13 +422,13 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  |         socket.on("setup", async (username, password, callback) => { | 
			
		
	
		
			
				
					|  |  |  |             try { | 
			
		
	
		
			
				
					|  |  |  |                 if ((await R.count("user")) !== 0) { | 
			
		
	
		
			
				
					|  |  |  |                     throw new Error("Uptime Kuma has been setup. If you want to setup again, please delete the database.") | 
			
		
	
		
			
				
					|  |  |  |                     throw new Error("Uptime Kuma has been setup. If you want to setup again, please delete the database."); | 
			
		
	
		
			
				
					|  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 let user = R.dispense("user") | 
			
		
	
		
			
				
					|  |  |  |                 let user = R.dispense("user"); | 
			
		
	
		
			
				
					|  |  |  |                 user.username = username; | 
			
		
	
		
			
				
					|  |  |  |                 user.password = passwordHash.generate(password) | 
			
		
	
		
			
				
					|  |  |  |                 await R.store(user) | 
			
		
	
		
			
				
					|  |  |  |                 user.password = passwordHash.generate(password); | 
			
		
	
		
			
				
					|  |  |  |                 await R.store(user); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 needSetup = false; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  | @ -445,8 +452,8 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  |         // Add a new monitor
 | 
			
		
	
		
			
				
					|  |  |  |         socket.on("add", async (monitor, callback) => { | 
			
		
	
		
			
				
					|  |  |  |             try { | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket) | 
			
		
	
		
			
				
					|  |  |  |                 let bean = R.dispense("monitor") | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket); | 
			
		
	
		
			
				
					|  |  |  |                 let bean = R.dispense("monitor"); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 let notificationIDList = monitor.notificationIDList; | 
			
		
	
		
			
				
					|  |  |  |                 delete monitor.notificationIDList; | 
			
		
	
	
		
			
				
					|  |  | @ -454,11 +461,11 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  |                 monitor.accepted_statuscodes_json = JSON.stringify(monitor.accepted_statuscodes); | 
			
		
	
		
			
				
					|  |  |  |                 delete monitor.accepted_statuscodes; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 bean.import(monitor) | 
			
		
	
		
			
				
					|  |  |  |                 bean.user_id = socket.userID | 
			
		
	
		
			
				
					|  |  |  |                 await R.store(bean) | 
			
		
	
		
			
				
					|  |  |  |                 bean.import(monitor); | 
			
		
	
		
			
				
					|  |  |  |                 bean.user_id = socket.userID; | 
			
		
	
		
			
				
					|  |  |  |                 await R.store(bean); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 await updateMonitorNotification(bean.id, notificationIDList) | 
			
		
	
		
			
				
					|  |  |  |                 await updateMonitorNotification(bean.id, notificationIDList); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 await startMonitor(socket.userID, bean.id); | 
			
		
	
		
			
				
					|  |  |  |                 await sendMonitorList(socket); | 
			
		
	
	
		
			
				
					|  |  | @ -480,18 +487,18 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  |         // Edit a monitor
 | 
			
		
	
		
			
				
					|  |  |  |         socket.on("editMonitor", async (monitor, callback) => { | 
			
		
	
		
			
				
					|  |  |  |             try { | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket) | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 let bean = await R.findOne("monitor", " id = ? ", [ monitor.id ]) | 
			
		
	
		
			
				
					|  |  |  |                 let bean = await R.findOne("monitor", " id = ? ", [ monitor.id ]); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 if (bean.user_id !== socket.userID) { | 
			
		
	
		
			
				
					|  |  |  |                     throw new Error("Permission denied.") | 
			
		
	
		
			
				
					|  |  |  |                     throw new Error("Permission denied."); | 
			
		
	
		
			
				
					|  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 bean.name = monitor.name | 
			
		
	
		
			
				
					|  |  |  |                 bean.type = monitor.type | 
			
		
	
		
			
				
					|  |  |  |                 bean.url = monitor.url | 
			
		
	
		
			
				
					|  |  |  |                 bean.interval = monitor.interval | 
			
		
	
		
			
				
					|  |  |  |                 bean.name = monitor.name; | 
			
		
	
		
			
				
					|  |  |  |                 bean.type = monitor.type; | 
			
		
	
		
			
				
					|  |  |  |                 bean.url = monitor.url; | 
			
		
	
		
			
				
					|  |  |  |                 bean.interval = monitor.interval; | 
			
		
	
		
			
				
					|  |  |  |                 bean.retryInterval = monitor.retryInterval; | 
			
		
	
		
			
				
					|  |  |  |                 bean.hostname = monitor.hostname; | 
			
		
	
		
			
				
					|  |  |  |                 bean.maxretries = monitor.maxretries; | 
			
		
	
	
		
			
				
					|  |  | @ -504,12 +511,12 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  |                 bean.dns_resolve_type = monitor.dns_resolve_type; | 
			
		
	
		
			
				
					|  |  |  |                 bean.dns_resolve_server = monitor.dns_resolve_server; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 await R.store(bean) | 
			
		
	
		
			
				
					|  |  |  |                 await R.store(bean); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 await updateMonitorNotification(bean.id, monitor.notificationIDList) | 
			
		
	
		
			
				
					|  |  |  |                 await updateMonitorNotification(bean.id, monitor.notificationIDList); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 if (bean.active) { | 
			
		
	
		
			
				
					|  |  |  |                     await restartMonitor(socket.userID, bean.id) | 
			
		
	
		
			
				
					|  |  |  |                     await restartMonitor(socket.userID, bean.id); | 
			
		
	
		
			
				
					|  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 await sendMonitorList(socket); | 
			
		
	
	
		
			
				
					|  |  | @ -521,7 +528,7 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  |                 }); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |             } catch (e) { | 
			
		
	
		
			
				
					|  |  |  |                 console.error(e) | 
			
		
	
		
			
				
					|  |  |  |                 console.error(e); | 
			
		
	
		
			
				
					|  |  |  |                 callback({ | 
			
		
	
		
			
				
					|  |  |  |                     ok: false, | 
			
		
	
		
			
				
					|  |  |  |                     msg: e.message, | 
			
		
	
	
		
			
				
					|  |  | @ -531,13 +538,13 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         socket.on("getMonitorList", async (callback) => { | 
			
		
	
		
			
				
					|  |  |  |             try { | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket) | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket); | 
			
		
	
		
			
				
					|  |  |  |                 await sendMonitorList(socket); | 
			
		
	
		
			
				
					|  |  |  |                 callback({ | 
			
		
	
		
			
				
					|  |  |  |                     ok: true, | 
			
		
	
		
			
				
					|  |  |  |                 }); | 
			
		
	
		
			
				
					|  |  |  |             } catch (e) { | 
			
		
	
		
			
				
					|  |  |  |                 console.error(e) | 
			
		
	
		
			
				
					|  |  |  |                 console.error(e); | 
			
		
	
		
			
				
					|  |  |  |                 callback({ | 
			
		
	
		
			
				
					|  |  |  |                     ok: false, | 
			
		
	
		
			
				
					|  |  |  |                     msg: e.message, | 
			
		
	
	
		
			
				
					|  |  | @ -547,14 +554,14 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         socket.on("getMonitor", async (monitorID, callback) => { | 
			
		
	
		
			
				
					|  |  |  |             try { | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket) | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 console.log(`Get Monitor: ${monitorID} User ID: ${socket.userID}`) | 
			
		
	
		
			
				
					|  |  |  |                 console.log(`Get Monitor: ${monitorID} User ID: ${socket.userID}`); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 let bean = await R.findOne("monitor", " id = ? AND user_id = ? ", [ | 
			
		
	
		
			
				
					|  |  |  |                     monitorID, | 
			
		
	
		
			
				
					|  |  |  |                     socket.userID, | 
			
		
	
		
			
				
					|  |  |  |                 ]) | 
			
		
	
		
			
				
					|  |  |  |                 ]); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 callback({ | 
			
		
	
		
			
				
					|  |  |  |                     ok: true, | 
			
		
	
	
		
			
				
					|  |  | @ -572,7 +579,7 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  |         // Start or Resume the monitor
 | 
			
		
	
		
			
				
					|  |  |  |         socket.on("resumeMonitor", async (monitorID, callback) => { | 
			
		
	
		
			
				
					|  |  |  |             try { | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket) | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket); | 
			
		
	
		
			
				
					|  |  |  |                 await startMonitor(socket.userID, monitorID); | 
			
		
	
		
			
				
					|  |  |  |                 await sendMonitorList(socket); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  | @ -591,8 +598,8 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         socket.on("pauseMonitor", async (monitorID, callback) => { | 
			
		
	
		
			
				
					|  |  |  |             try { | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket) | 
			
		
	
		
			
				
					|  |  |  |                 await pauseMonitor(socket.userID, monitorID) | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket); | 
			
		
	
		
			
				
					|  |  |  |                 await pauseMonitor(socket.userID, monitorID); | 
			
		
	
		
			
				
					|  |  |  |                 await sendMonitorList(socket); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 callback({ | 
			
		
	
	
		
			
				
					|  |  | @ -610,13 +617,13 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         socket.on("deleteMonitor", async (monitorID, callback) => { | 
			
		
	
		
			
				
					|  |  |  |             try { | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket) | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 console.log(`Delete Monitor: ${monitorID} User ID: ${socket.userID}`) | 
			
		
	
		
			
				
					|  |  |  |                 console.log(`Delete Monitor: ${monitorID} User ID: ${socket.userID}`); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 if (monitorID in monitorList) { | 
			
		
	
		
			
				
					|  |  |  |                     monitorList[monitorID].stop(); | 
			
		
	
		
			
				
					|  |  |  |                     delete monitorList[monitorID] | 
			
		
	
		
			
				
					|  |  |  |                     delete monitorList[monitorID]; | 
			
		
	
		
			
				
					|  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 await R.exec("DELETE FROM monitor WHERE id = ? AND user_id = ? ", [ | 
			
		
	
	
		
			
				
					|  |  | @ -641,9 +648,9 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         socket.on("getTags", async (callback) => { | 
			
		
	
		
			
				
					|  |  |  |             try { | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket) | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 const list = await R.findAll("tag") | 
			
		
	
		
			
				
					|  |  |  |                 const list = await R.findAll("tag"); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 callback({ | 
			
		
	
		
			
				
					|  |  |  |                     ok: true, | 
			
		
	
	
		
			
				
					|  |  | @ -660,12 +667,12 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         socket.on("addTag", async (tag, callback) => { | 
			
		
	
		
			
				
					|  |  |  |             try { | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket) | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 let bean = R.dispense("tag") | 
			
		
	
		
			
				
					|  |  |  |                 bean.name = tag.name | 
			
		
	
		
			
				
					|  |  |  |                 bean.color = tag.color | 
			
		
	
		
			
				
					|  |  |  |                 await R.store(bean) | 
			
		
	
		
			
				
					|  |  |  |                 let bean = R.dispense("tag"); | 
			
		
	
		
			
				
					|  |  |  |                 bean.name = tag.name; | 
			
		
	
		
			
				
					|  |  |  |                 bean.color = tag.color; | 
			
		
	
		
			
				
					|  |  |  |                 await R.store(bean); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 callback({ | 
			
		
	
		
			
				
					|  |  |  |                     ok: true, | 
			
		
	
	
		
			
				
					|  |  | @ -682,12 +689,12 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         socket.on("editTag", async (tag, callback) => { | 
			
		
	
		
			
				
					|  |  |  |             try { | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket) | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 let bean = await R.findOne("monitor", " id = ? ", [ tag.id ]) | 
			
		
	
		
			
				
					|  |  |  |                 bean.name = tag.name | 
			
		
	
		
			
				
					|  |  |  |                 bean.color = tag.color | 
			
		
	
		
			
				
					|  |  |  |                 await R.store(bean) | 
			
		
	
		
			
				
					|  |  |  |                 let bean = await R.findOne("monitor", " id = ? ", [ tag.id ]); | 
			
		
	
		
			
				
					|  |  |  |                 bean.name = tag.name; | 
			
		
	
		
			
				
					|  |  |  |                 bean.color = tag.color; | 
			
		
	
		
			
				
					|  |  |  |                 await R.store(bean); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 callback({ | 
			
		
	
		
			
				
					|  |  |  |                     ok: true, | 
			
		
	
	
		
			
				
					|  |  | @ -704,9 +711,9 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         socket.on("deleteTag", async (tagID, callback) => { | 
			
		
	
		
			
				
					|  |  |  |             try { | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket) | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 await R.exec("DELETE FROM tag WHERE id = ? ", [ tagID ]) | 
			
		
	
		
			
				
					|  |  |  |                 await R.exec("DELETE FROM tag WHERE id = ? ", [ tagID ]); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 callback({ | 
			
		
	
		
			
				
					|  |  |  |                     ok: true, | 
			
		
	
	
		
			
				
					|  |  | @ -723,13 +730,13 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         socket.on("addMonitorTag", async (tagID, monitorID, value, callback) => { | 
			
		
	
		
			
				
					|  |  |  |             try { | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket) | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 await R.exec("INSERT INTO monitor_tag (tag_id, monitor_id, value) VALUES (?, ?, ?)", [ | 
			
		
	
		
			
				
					|  |  |  |                     tagID, | 
			
		
	
		
			
				
					|  |  |  |                     monitorID, | 
			
		
	
		
			
				
					|  |  |  |                     value, | 
			
		
	
		
			
				
					|  |  |  |                 ]) | 
			
		
	
		
			
				
					|  |  |  |                 ]); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 callback({ | 
			
		
	
		
			
				
					|  |  |  |                     ok: true, | 
			
		
	
	
		
			
				
					|  |  | @ -746,13 +753,13 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         socket.on("editMonitorTag", async (tagID, monitorID, value, callback) => { | 
			
		
	
		
			
				
					|  |  |  |             try { | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket) | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 await R.exec("UPDATE monitor_tag SET value = ? WHERE tag_id = ? AND monitor_id = ?", [ | 
			
		
	
		
			
				
					|  |  |  |                     value, | 
			
		
	
		
			
				
					|  |  |  |                     tagID, | 
			
		
	
		
			
				
					|  |  |  |                     monitorID, | 
			
		
	
		
			
				
					|  |  |  |                 ]) | 
			
		
	
		
			
				
					|  |  |  |                 ]); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 callback({ | 
			
		
	
		
			
				
					|  |  |  |                     ok: true, | 
			
		
	
	
		
			
				
					|  |  | @ -769,13 +776,13 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         socket.on("deleteMonitorTag", async (tagID, monitorID, value, callback) => { | 
			
		
	
		
			
				
					|  |  |  |             try { | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket) | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 await R.exec("DELETE FROM monitor_tag WHERE tag_id = ? AND monitor_id = ? AND value = ?", [ | 
			
		
	
		
			
				
					|  |  |  |                     tagID, | 
			
		
	
		
			
				
					|  |  |  |                     monitorID, | 
			
		
	
		
			
				
					|  |  |  |                     value, | 
			
		
	
		
			
				
					|  |  |  |                 ]) | 
			
		
	
		
			
				
					|  |  |  |                 ]); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 // Cleanup unused Tags
 | 
			
		
	
		
			
				
					|  |  |  |                 await R.exec("delete from tag where ( select count(*) from monitor_tag mt where tag.id = mt.tag_id ) = 0"); | 
			
		
	
	
		
			
				
					|  |  | @ -795,15 +802,15 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         socket.on("changePassword", async (password, callback) => { | 
			
		
	
		
			
				
					|  |  |  |             try { | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket) | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 if (! password.currentPassword) { | 
			
		
	
		
			
				
					|  |  |  |                     throw new Error("Invalid new password") | 
			
		
	
		
			
				
					|  |  |  |                     throw new Error("Invalid new password"); | 
			
		
	
		
			
				
					|  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 let user = await R.findOne("user", " id = ? AND active = 1 ", [ | 
			
		
	
		
			
				
					|  |  |  |                     socket.userID, | 
			
		
	
		
			
				
					|  |  |  |                 ]) | 
			
		
	
		
			
				
					|  |  |  |                 ]); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 if (user && passwordHash.verify(password.currentPassword, user.password)) { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  | @ -812,9 +819,9 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  |                     callback({ | 
			
		
	
		
			
				
					|  |  |  |                         ok: true, | 
			
		
	
		
			
				
					|  |  |  |                         msg: "Password has been updated successfully.", | 
			
		
	
		
			
				
					|  |  |  |                     }) | 
			
		
	
		
			
				
					|  |  |  |                     }); | 
			
		
	
		
			
				
					|  |  |  |                 } else { | 
			
		
	
		
			
				
					|  |  |  |                     throw new Error("Incorrect current password") | 
			
		
	
		
			
				
					|  |  |  |                     throw new Error("Incorrect current password"); | 
			
		
	
		
			
				
					|  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |             } catch (e) { | 
			
		
	
	
		
			
				
					|  |  | @ -827,7 +834,7 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         socket.on("getSettings", async (callback) => { | 
			
		
	
		
			
				
					|  |  |  |             try { | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket) | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 callback({ | 
			
		
	
		
			
				
					|  |  |  |                     ok: true, | 
			
		
	
	
		
			
				
					|  |  | @ -844,7 +851,7 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         socket.on("setSettings", async (data, callback) => { | 
			
		
	
		
			
				
					|  |  |  |             try { | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket) | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 await setSettings("general", data); | 
			
		
	
		
			
				
					|  |  |  |                 exports.entryPage = data.entryPage; | 
			
		
	
	
		
			
				
					|  |  | @ -865,10 +872,10 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  |         // Add or Edit
 | 
			
		
	
		
			
				
					|  |  |  |         socket.on("addNotification", async (notification, notificationID, callback) => { | 
			
		
	
		
			
				
					|  |  |  |             try { | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket) | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 let notificationBean = await Notification.save(notification, notificationID, socket.userID) | 
			
		
	
		
			
				
					|  |  |  |                 await sendNotificationList(socket) | 
			
		
	
		
			
				
					|  |  |  |                 let notificationBean = await Notification.save(notification, notificationID, socket.userID); | 
			
		
	
		
			
				
					|  |  |  |                 await sendNotificationList(socket); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 callback({ | 
			
		
	
		
			
				
					|  |  |  |                     ok: true, | 
			
		
	
	
		
			
				
					|  |  | @ -886,10 +893,10 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         socket.on("deleteNotification", async (notificationID, callback) => { | 
			
		
	
		
			
				
					|  |  |  |             try { | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket) | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 await Notification.delete(notificationID, socket.userID) | 
			
		
	
		
			
				
					|  |  |  |                 await sendNotificationList(socket) | 
			
		
	
		
			
				
					|  |  |  |                 await Notification.delete(notificationID, socket.userID); | 
			
		
	
		
			
				
					|  |  |  |                 await sendNotificationList(socket); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 callback({ | 
			
		
	
		
			
				
					|  |  |  |                     ok: true, | 
			
		
	
	
		
			
				
					|  |  | @ -906,9 +913,9 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         socket.on("testNotification", async (notification, callback) => { | 
			
		
	
		
			
				
					|  |  |  |             try { | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket) | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 let msg = await Notification.send(notification, notification.name + " Testing") | 
			
		
	
		
			
				
					|  |  |  |                 let msg = await Notification.send(notification, notification.name + " Testing"); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 callback({ | 
			
		
	
		
			
				
					|  |  |  |                     ok: true, | 
			
		
	
	
		
			
				
					|  |  | @ -916,7 +923,7 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  |                 }); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |             } catch (e) { | 
			
		
	
		
			
				
					|  |  |  |                 console.error(e) | 
			
		
	
		
			
				
					|  |  |  |                 console.error(e); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 callback({ | 
			
		
	
		
			
				
					|  |  |  |                     ok: false, | 
			
		
	
	
		
			
				
					|  |  | @ -927,7 +934,7 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         socket.on("checkApprise", async (callback) => { | 
			
		
	
		
			
				
					|  |  |  |             try { | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket) | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket); | 
			
		
	
		
			
				
					|  |  |  |                 callback(Notification.checkApprise()); | 
			
		
	
		
			
				
					|  |  |  |             } catch (e) { | 
			
		
	
		
			
				
					|  |  |  |                 callback(false); | 
			
		
	
	
		
			
				
					|  |  | @ -936,19 +943,19 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         socket.on("uploadBackup", async (uploadedJSON, importHandle, callback) => { | 
			
		
	
		
			
				
					|  |  |  |             try { | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket) | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 let backupData = JSON.parse(uploadedJSON); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 console.log(`Importing Backup, User ID: ${socket.userID}, Version: ${backupData.version}`) | 
			
		
	
		
			
				
					|  |  |  |                 console.log(`Importing Backup, User ID: ${socket.userID}, Version: ${backupData.version}`); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 let notificationListData = backupData.notificationList; | 
			
		
	
		
			
				
					|  |  |  |                 let monitorListData = backupData.monitorList; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 if (importHandle == "overwrite") { | 
			
		
	
		
			
				
					|  |  |  |                     for (let id in monitorList) { | 
			
		
	
		
			
				
					|  |  |  |                         let monitor = monitorList[id] | 
			
		
	
		
			
				
					|  |  |  |                         await monitor.stop() | 
			
		
	
		
			
				
					|  |  |  |                         let monitor = monitorList[id]; | 
			
		
	
		
			
				
					|  |  |  |                         await monitor.stop(); | 
			
		
	
		
			
				
					|  |  |  |                     } | 
			
		
	
		
			
				
					|  |  |  |                     await R.exec("DELETE FROM heartbeat"); | 
			
		
	
		
			
				
					|  |  |  |                     await R.exec("DELETE FROM monitor_notification"); | 
			
		
	
	
		
			
				
					|  |  | @ -965,7 +972,7 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  |                         if ((importHandle == "skip" && notificationNameListString.includes(notificationListData[i].name) == false) || importHandle == "keep" || importHandle == "overwrite") { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                             let notification = JSON.parse(notificationListData[i].config); | 
			
		
	
		
			
				
					|  |  |  |                             await Notification.save(notification, null, socket.userID) | 
			
		
	
		
			
				
					|  |  |  |                             await Notification.save(notification, null, socket.userID); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                         } | 
			
		
	
		
			
				
					|  |  |  |                     } | 
			
		
	
	
		
			
				
					|  |  | @ -994,9 +1001,9 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  |                                 dns_resolve_type: monitorListData[i].dns_resolve_type, | 
			
		
	
		
			
				
					|  |  |  |                                 dns_resolve_server: monitorListData[i].dns_resolve_server, | 
			
		
	
		
			
				
					|  |  |  |                                 notificationIDList: {}, | 
			
		
	
		
			
				
					|  |  |  |                             } | 
			
		
	
		
			
				
					|  |  |  |                             }; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                             let bean = R.dispense("monitor") | 
			
		
	
		
			
				
					|  |  |  |                             let bean = R.dispense("monitor"); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                             let notificationIDList = monitor.notificationIDList; | 
			
		
	
		
			
				
					|  |  |  |                             delete monitor.notificationIDList; | 
			
		
	
	
		
			
				
					|  |  | @ -1004,11 +1011,11 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  |                             monitor.accepted_statuscodes_json = JSON.stringify(monitor.accepted_statuscodes); | 
			
		
	
		
			
				
					|  |  |  |                             delete monitor.accepted_statuscodes; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                             bean.import(monitor) | 
			
		
	
		
			
				
					|  |  |  |                             bean.user_id = socket.userID | 
			
		
	
		
			
				
					|  |  |  |                             await R.store(bean) | 
			
		
	
		
			
				
					|  |  |  |                             bean.import(monitor); | 
			
		
	
		
			
				
					|  |  |  |                             bean.user_id = socket.userID; | 
			
		
	
		
			
				
					|  |  |  |                             await R.store(bean); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                             await updateMonitorNotification(bean.id, notificationIDList) | 
			
		
	
		
			
				
					|  |  |  |                             await updateMonitorNotification(bean.id, notificationIDList); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                             if (monitorListData[i].active == 1) { | 
			
		
	
		
			
				
					|  |  |  |                                 await startMonitor(socket.userID, bean.id); | 
			
		
	
	
		
			
				
					|  |  | @ -1019,7 +1026,7 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  |                         } | 
			
		
	
		
			
				
					|  |  |  |                     } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                     await sendNotificationList(socket) | 
			
		
	
		
			
				
					|  |  |  |                     await sendNotificationList(socket); | 
			
		
	
		
			
				
					|  |  |  |                     await sendMonitorList(socket); | 
			
		
	
		
			
				
					|  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  | @ -1038,9 +1045,9 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         socket.on("clearEvents", async (monitorID, callback) => { | 
			
		
	
		
			
				
					|  |  |  |             try { | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket) | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 console.log(`Clear Events Monitor: ${monitorID} User ID: ${socket.userID}`) | 
			
		
	
		
			
				
					|  |  |  |                 console.log(`Clear Events Monitor: ${monitorID} User ID: ${socket.userID}`); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 await R.exec("UPDATE heartbeat SET msg = ?, important = ? WHERE monitor_id = ? ", [ | 
			
		
	
		
			
				
					|  |  |  |                     "", | 
			
		
	
	
		
			
				
					|  |  | @ -1064,9 +1071,9 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         socket.on("clearHeartbeats", async (monitorID, callback) => { | 
			
		
	
		
			
				
					|  |  |  |             try { | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket) | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 console.log(`Clear Heartbeats Monitor: ${monitorID} User ID: ${socket.userID}`) | 
			
		
	
		
			
				
					|  |  |  |                 console.log(`Clear Heartbeats Monitor: ${monitorID} User ID: ${socket.userID}`); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 await R.exec("DELETE FROM heartbeat WHERE monitor_id = ?", [ | 
			
		
	
		
			
				
					|  |  |  |                     monitorID | 
			
		
	
	
		
			
				
					|  |  | @ -1088,9 +1095,9 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         socket.on("clearStatistics", async (callback) => { | 
			
		
	
		
			
				
					|  |  |  |             try { | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket) | 
			
		
	
		
			
				
					|  |  |  |                 checkLogin(socket); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 console.log(`Clear Statistics User ID: ${socket.userID}`) | 
			
		
	
		
			
				
					|  |  |  |                 console.log(`Clear Statistics User ID: ${socket.userID}`); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 await R.exec("DELETE FROM heartbeat"); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  | @ -1115,18 +1122,18 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  |         // Better do anything after added all socket handlers here
 | 
			
		
	
		
			
				
					|  |  |  |         // ***************************
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         debug("check auto login") | 
			
		
	
		
			
				
					|  |  |  |         debug("check auto login"); | 
			
		
	
		
			
				
					|  |  |  |         if (await setting("disableAuth")) { | 
			
		
	
		
			
				
					|  |  |  |             console.log("Disabled Auth: auto login to admin") | 
			
		
	
		
			
				
					|  |  |  |             afterLogin(socket, await R.findOne("user")) | 
			
		
	
		
			
				
					|  |  |  |             socket.emit("autoLogin") | 
			
		
	
		
			
				
					|  |  |  |             console.log("Disabled Auth: auto login to admin"); | 
			
		
	
		
			
				
					|  |  |  |             afterLogin(socket, await R.findOne("user")); | 
			
		
	
		
			
				
					|  |  |  |             socket.emit("autoLogin"); | 
			
		
	
		
			
				
					|  |  |  |         } else { | 
			
		
	
		
			
				
					|  |  |  |             debug("need auth") | 
			
		
	
		
			
				
					|  |  |  |             debug("need auth"); | 
			
		
	
		
			
				
					|  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     }); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     console.log("Init the server") | 
			
		
	
		
			
				
					|  |  |  |     console.log("Init the server"); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     server.once("error", async (err) => { | 
			
		
	
		
			
				
					|  |  |  |         console.error("Cannot listen: " + err.message); | 
			
		
	
	
		
			
				
					|  |  | @ -1148,14 +1155,14 @@ exports.entryPage = "dashboard"; | 
			
		
	
		
			
				
					|  |  |  | async function updateMonitorNotification(monitorID, notificationIDList) { | 
			
		
	
		
			
				
					|  |  |  |     await R.exec("DELETE FROM monitor_notification WHERE monitor_id = ? ", [ | 
			
		
	
		
			
				
					|  |  |  |         monitorID, | 
			
		
	
		
			
				
					|  |  |  |     ]) | 
			
		
	
		
			
				
					|  |  |  |     ]); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     for (let notificationID in notificationIDList) { | 
			
		
	
		
			
				
					|  |  |  |         if (notificationIDList[notificationID]) { | 
			
		
	
		
			
				
					|  |  |  |             let relation = R.dispense("monitor_notification"); | 
			
		
	
		
			
				
					|  |  |  |             relation.monitor_id = monitorID; | 
			
		
	
		
			
				
					|  |  |  |             relation.notification_id = notificationID; | 
			
		
	
		
			
				
					|  |  |  |             await R.store(relation) | 
			
		
	
		
			
				
					|  |  |  |             await R.store(relation); | 
			
		
	
		
			
				
					|  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
	
		
			
				
					|  |  | @ -1164,7 +1171,7 @@ async function checkOwner(userID, monitorID) { | 
			
		
	
		
			
				
					|  |  |  |     let row = await R.getRow("SELECT id FROM monitor WHERE id = ? AND user_id = ? ", [ | 
			
		
	
		
			
				
					|  |  |  |         monitorID, | 
			
		
	
		
			
				
					|  |  |  |         userID, | 
			
		
	
		
			
				
					|  |  |  |     ]) | 
			
		
	
		
			
				
					|  |  |  |     ]); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     if (! row) { | 
			
		
	
		
			
				
					|  |  |  |         throw new Error("You do not own this monitor."); | 
			
		
	
	
		
			
				
					|  |  | @ -1173,16 +1180,16 @@ async function checkOwner(userID, monitorID) { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | async function sendMonitorList(socket) { | 
			
		
	
		
			
				
					|  |  |  |     let list = await getMonitorJSONList(socket.userID); | 
			
		
	
		
			
				
					|  |  |  |     io.to(socket.userID).emit("monitorList", list) | 
			
		
	
		
			
				
					|  |  |  |     io.to(socket.userID).emit("monitorList", list); | 
			
		
	
		
			
				
					|  |  |  |     return list; | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | async function afterLogin(socket, user) { | 
			
		
	
		
			
				
					|  |  |  |     socket.userID = user.id; | 
			
		
	
		
			
				
					|  |  |  |     socket.join(user.id) | 
			
		
	
		
			
				
					|  |  |  |     socket.join(user.id); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     let monitorList = await sendMonitorList(socket) | 
			
		
	
		
			
				
					|  |  |  |     sendNotificationList(socket) | 
			
		
	
		
			
				
					|  |  |  |     let monitorList = await sendMonitorList(socket); | 
			
		
	
		
			
				
					|  |  |  |     sendNotificationList(socket); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     await sleep(500); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  | @ -1195,7 +1202,7 @@ async function afterLogin(socket, user) { | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     for (let monitorID in monitorList) { | 
			
		
	
		
			
				
					|  |  |  |         await Monitor.sendStats(io, monitorID, user.id) | 
			
		
	
		
			
				
					|  |  |  |         await Monitor.sendStats(io, monitorID, user.id); | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  | @ -1204,7 +1211,7 @@ async function getMonitorJSONList(userID) { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     let monitorList = await R.find("monitor", " user_id = ? ORDER BY weight DESC, name", [ | 
			
		
	
		
			
				
					|  |  |  |         userID, | 
			
		
	
		
			
				
					|  |  |  |     ]) | 
			
		
	
		
			
				
					|  |  |  |     ]); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     for (let monitor of monitorList) { | 
			
		
	
		
			
				
					|  |  |  |         result[monitor.id] = await monitor.toJSON(); | 
			
		
	
	
		
			
				
					|  |  | @ -1215,16 +1222,16 @@ async function getMonitorJSONList(userID) { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | async function initDatabase() { | 
			
		
	
		
			
				
					|  |  |  |     if (! fs.existsSync(Database.path)) { | 
			
		
	
		
			
				
					|  |  |  |         console.log("Copying Database") | 
			
		
	
		
			
				
					|  |  |  |         console.log("Copying Database"); | 
			
		
	
		
			
				
					|  |  |  |         fs.copyFileSync(Database.templatePath, Database.path); | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     console.log("Connecting to Database") | 
			
		
	
		
			
				
					|  |  |  |     console.log("Connecting to Database"); | 
			
		
	
		
			
				
					|  |  |  |     await Database.connect(); | 
			
		
	
		
			
				
					|  |  |  |     console.log("Connected") | 
			
		
	
		
			
				
					|  |  |  |     console.log("Connected"); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     // Patch the database
 | 
			
		
	
		
			
				
					|  |  |  |     await Database.patch() | 
			
		
	
		
			
				
					|  |  |  |     await Database.patch(); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     let jwtSecretBean = await R.findOne("setting", " `key` = ? ", [ | 
			
		
	
		
			
				
					|  |  |  |         "jwtSecret", | 
			
		
	
	
		
			
				
					|  |  | @ -1240,7 +1247,7 @@ async function initDatabase() { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     // If there is no record in user table, it is a new Uptime Kuma instance, need to setup
 | 
			
		
	
		
			
				
					|  |  |  |     if ((await R.count("user")) === 0) { | 
			
		
	
		
			
				
					|  |  |  |         console.log("No user, need setup") | 
			
		
	
		
			
				
					|  |  |  |         console.log("No user, need setup"); | 
			
		
	
		
			
				
					|  |  |  |         needSetup = true; | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  | @ -1248,9 +1255,9 @@ async function initDatabase() { | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | async function startMonitor(userID, monitorID) { | 
			
		
	
		
			
				
					|  |  |  |     await checkOwner(userID, monitorID) | 
			
		
	
		
			
				
					|  |  |  |     await checkOwner(userID, monitorID); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     console.log(`Resume Monitor: ${monitorID} User ID: ${userID}`) | 
			
		
	
		
			
				
					|  |  |  |     console.log(`Resume Monitor: ${monitorID} User ID: ${userID}`); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     await R.exec("UPDATE monitor SET active = 1 WHERE id = ? AND user_id = ? ", [ | 
			
		
	
		
			
				
					|  |  |  |         monitorID, | 
			
		
	
	
		
			
				
					|  |  | @ -1259,24 +1266,24 @@ async function startMonitor(userID, monitorID) { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     let monitor = await R.findOne("monitor", " id = ? ", [ | 
			
		
	
		
			
				
					|  |  |  |         monitorID, | 
			
		
	
		
			
				
					|  |  |  |     ]) | 
			
		
	
		
			
				
					|  |  |  |     ]); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     if (monitor.id in monitorList) { | 
			
		
	
		
			
				
					|  |  |  |         monitorList[monitor.id].stop(); | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     monitorList[monitor.id] = monitor; | 
			
		
	
		
			
				
					|  |  |  |     monitor.start(io) | 
			
		
	
		
			
				
					|  |  |  |     monitor.start(io); | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | async function restartMonitor(userID, monitorID) { | 
			
		
	
		
			
				
					|  |  |  |     return await startMonitor(userID, monitorID) | 
			
		
	
		
			
				
					|  |  |  |     return await startMonitor(userID, monitorID); | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | async function pauseMonitor(userID, monitorID) { | 
			
		
	
		
			
				
					|  |  |  |     await checkOwner(userID, monitorID) | 
			
		
	
		
			
				
					|  |  |  |     await checkOwner(userID, monitorID); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     console.log(`Pause Monitor: ${monitorID} User ID: ${userID}`) | 
			
		
	
		
			
				
					|  |  |  |     console.log(`Pause Monitor: ${monitorID} User ID: ${userID}`); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     await R.exec("UPDATE monitor SET active = 0 WHERE id = ? AND user_id = ? ", [ | 
			
		
	
		
			
				
					|  |  |  |         monitorID, | 
			
		
	
	
		
			
				
					|  |  | @ -1292,7 +1299,7 @@ async function pauseMonitor(userID, monitorID) { | 
			
		
	
		
			
				
					|  |  |  |  * Resume active monitors | 
			
		
	
		
			
				
					|  |  |  |  */ | 
			
		
	
		
			
				
					|  |  |  | async function startMonitors() { | 
			
		
	
		
			
				
					|  |  |  |     let list = await R.find("monitor", " active = 1 ") | 
			
		
	
		
			
				
					|  |  |  |     let list = await R.find("monitor", " active = 1 "); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     for (let monitor of list) { | 
			
		
	
		
			
				
					|  |  |  |         monitorList[monitor.id] = monitor; | 
			
		
	
	
		
			
				
					|  |  | @ -1309,10 +1316,10 @@ async function shutdownFunction(signal) { | 
			
		
	
		
			
				
					|  |  |  |     console.log("Shutdown requested"); | 
			
		
	
		
			
				
					|  |  |  |     console.log("Called signal: " + signal); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     console.log("Stopping all monitors") | 
			
		
	
		
			
				
					|  |  |  |     console.log("Stopping all monitors"); | 
			
		
	
		
			
				
					|  |  |  |     for (let id in monitorList) { | 
			
		
	
		
			
				
					|  |  |  |         let monitor = monitorList[id] | 
			
		
	
		
			
				
					|  |  |  |         monitor.stop() | 
			
		
	
		
			
				
					|  |  |  |         let monitor = monitorList[id]; | 
			
		
	
		
			
				
					|  |  |  |         monitor.stop(); | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |     await sleep(2000); | 
			
		
	
		
			
				
					|  |  |  |     await Database.close(); | 
			
		
	
	
		
			
				
					|  |  | 
 |