diff --git a/server/server.js b/server/server.js
index 51095365f..a19169063 100644
--- a/server/server.js
+++ b/server/server.js
@@ -26,6 +26,8 @@ debug("Importing http-graceful-shutdown");
const gracefulShutdown = require("http-graceful-shutdown");
debug("Importing prometheus-api-metrics");
const prometheusAPIMetrics = require("prometheus-api-metrics");
+debug("Importing compare-versions");
+const compareVersions = require("compare-versions");
debug("Importing 2FA Modules");
const notp = require("notp");
@@ -943,16 +945,20 @@ 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;
+ let version17x = compareVersions.compare(backupData.version, '1.7.0', '>=')
+
+ // If the import option is "overwrite" it'll clear most of the tables, except "settings" and "user"
if (importHandle == "overwrite") {
+ // Stops every monitor first, so it doesn't execute any heartbeat while importing
for (let id in monitorList) {
let monitor = monitorList[id];
await monitor.stop();
@@ -961,14 +967,19 @@ exports.entryPage = "dashboard";
await R.exec("DELETE FROM monitor_notification");
await R.exec("DELETE FROM monitor_tls_info");
await R.exec("DELETE FROM notification");
+ await R.exec("DELETE FROM monitor_tag");
+ await R.exec("DELETE FROM tag");
await R.exec("DELETE FROM monitor");
}
+ // Only starts importing if the backup file contains at least one notification
if (notificationListData.length >= 1) {
+ // Get every existing notification name and puts them in one simple string
let notificationNameList = await R.getAll("SELECT name FROM notification");
let notificationNameListString = JSON.stringify(notificationNameList);
for (let i = 0; i < notificationListData.length; i++) {
+ // Only starts importing the notification if the import option is "overwrite", "keep" or "skip" but the notification doesn't exists
if ((importHandle == "skip" && notificationNameListString.includes(notificationListData[i].name) == false) || importHandle == "keep" || importHandle == "overwrite") {
let notification = JSON.parse(notificationListData[i].config);
@@ -978,18 +989,39 @@ exports.entryPage = "dashboard";
}
}
+ // Only starts importing if the backup file contains at least one monitor
if (monitorListData.length >= 1) {
+ // Get every existing monitor name and puts them in one simple string
let monitorNameList = await R.getAll("SELECT name FROM monitor");
let monitorNameListString = JSON.stringify(monitorNameList);
for (let i = 0; i < monitorListData.length; i++) {
+ // Only starts importing the monitor if the import option is "overwrite", "keep" or "skip" but the notification doesn't exists
if ((importHandle == "skip" && monitorNameListString.includes(monitorListData[i].name) == false) || importHandle == "keep" || importHandle == "overwrite") {
+ // Define in here every new variable for monitors which where implemented after the first version of the Import/Export function (1.6.0)
+ // --- Start ---
+
+ // Define default values
+ let retryInterval = 0;
+
+ /*
+ Only replace the default value with the backup file data for the specific version, where it appears the first time
+ More information about that where "let version" will be defined
+ */
+ if (version17x) {
+ retryInterval = monitorListData[i].retryInterval;
+ }
+
+ // --- End ---
+
let monitor = {
+ // Define the new variable from earlier here
name: monitorListData[i].name,
type: monitorListData[i].type,
url: monitorListData[i].url,
interval: monitorListData[i].interval,
+ retryInterval: retryInterval,
hostname: monitorListData[i].hostname,
maxretries: monitorListData[i].maxretries,
port: monitorListData[i].port,
@@ -1015,8 +1047,43 @@ exports.entryPage = "dashboard";
bean.user_id = socket.userID;
await R.store(bean);
- await updateMonitorNotification(bean.id, notificationIDList);
+ // Only for backup files with the version 1.7.0 or higher, since there was the tag feature implemented
+ if (version17x) {
+ // Only import if the specific monitor has tags assigned
+ if (monitorListData[i].tags.length >= 1) {
+ for (let o = 0; o < monitorListData[i].tags.length; o++) {
+ // Check if tag already exists and get data ->
+ let tag = await R.findOne("tag", " name = ?", [
+ monitorListData[i].tags[o].name,
+ ])
+
+ // Set tagId to vaule from database
+ let tagId = tag.id
+
+ // -> If it doesn't, create new tag from backup file
+ if (! tag) {
+ let beanTag = R.dispense("tag")
+ beanTag.name = monitorListData[i].tags[o].name
+ beanTag.color = monitorListData[i].tags[o].color
+ await R.store(beanTag)
+
+ tagId = beanTag.id
+ }
+
+ // Assign the new created tag to the monitor
+ await R.exec("INSERT INTO monitor_tag (tag_id, monitor_id, value) VALUES (?, ?, ?)", [
+ tagId,
+ bean.id,
+ monitorListData[i].tags[o].value,
+ ])
+ }
+ }
+ }
+
+ await updateMonitorNotification(bean.id, notificationIDList)
+
+ // If monitor was active start it immediately, otherwise pause it
if (monitorListData[i].active == 1) {
await startMonitor(socket.userID, bean.id);
} else {
diff --git a/src/layouts/Layout.vue b/src/layouts/Layout.vue
index 2342ed1a8..6228d4fb8 100644
--- a/src/layouts/Layout.vue
+++ b/src/layouts/Layout.vue
@@ -23,7 +23,7 @@