Added recovery feature

If the database get corrupted, the admin can restore it through the website.
This commit is contained in:
2025-05-15 13:58:50 +03:00
parent 9adb9a4068
commit e21ba3e213
3 changed files with 57 additions and 7 deletions
+3 -3
View File
@@ -1,4 +1,4 @@
const db = require("../database/sqlite.database.js"); var db = require("../database/sqlite.database.js");
const logger = require("../utils/logger.util.js"); const logger = require("../utils/logger.util.js");
const Database = require("better-sqlite3"); const Database = require("better-sqlite3");
const path = require("path"); const path = require("path");
@@ -13,6 +13,7 @@ function errorPageRenderer(res, emoji, message) {
res.render("error", { res.render("error", {
page_title: app_conf.name, page_title: app_conf.name,
css_path: path.join(app_conf.paths.css.web, "stylesheet.css"), css_path: path.join(app_conf.paths.css.web, "stylesheet.css"),
js_path: path.join(app_conf.paths.js.web, "error.js"),
error_emoji: emoji, error_emoji: emoji,
error_message: message error_message: message
}) })
@@ -51,8 +52,6 @@ router.post("/upload", async (req, res) => {
db = new Database(db_conf.path, { fileMustExist: true }); db = new Database(db_conf.path, { fileMustExist: true });
} catch (error) { } catch (error) {
logger.error(error); logger.error(error);
shutting_down = true;
shutdown();
} }
} }
}); });
@@ -240,6 +239,7 @@ router.get("/edit", async (req, res) => {
} }
} catch (error) { } catch (error) {
logger.error(error.message); logger.error(error.message);
errorPageRenderer(res, "🌋💥", "Internal server error. Check logs for more information.");
} }
} else { } else {
errorPageRenderer(res, "✋⛔", "Bad request."); errorPageRenderer(res, "✋⛔", "Bad request.");
+9 -4
View File
@@ -12,13 +12,18 @@
href="https://fonts.googleapis.com/css2?family=Ubuntu:ital,wght@0,300;0,400;0,500;0,700;1,300;1,400;1,500;1,700&display=swap" href="https://fonts.googleapis.com/css2?family=Ubuntu:ital,wght@0,300;0,400;0,500;0,700;1,300;1,400;1,500;1,700&display=swap"
rel="stylesheet"> rel="stylesheet">
<link rel="stylesheet" href="<%= css_path %>"> <link rel="stylesheet" href="<%= css_path %>">
<script src="<%= js_path %>" defer></script>
</head> </head>
<body> <body>
<div class="control_div"> <input type="file" id="file_input" accept=".db" style="display: none;" />
<label <div class="control_div" style="display: flex; flex-direction: row; justify-content: space-between;">
style='font-family: "Ubuntu", sans-serif; font-weight: 500; font-style: normal; font-size: 200%;'>CRTelemetry <label style="font-size: 200%;">CRTelemetry SQLite3</label>
SQLite3</label> <div style="display: flex;align-items: center;">
<label id="upload" style="cursor: pointer; margin-left: 10px; margin-right: 10px;"><span>&#129093; </span>Upload</label>
<label id="download" style="cursor: pointer; margin-left: 10px; margin-right: 10px;"><span>&#129095; </span>Download</label>
<label id="logout" style="cursor: pointer; margin-left: 10px;"><span>&#129092; </span>Logout</label>
</div>
</div> </div>
<div class="main_div"> <div class="main_div">
<label style="font-size: 150%;"> <label style="font-size: 150%;">
+45
View File
@@ -0,0 +1,45 @@
const upload = document.getElementById("upload");
const download = document.getElementById("download");
const logout = document.getElementById("logout");
function setEventListeners(element, cb) {
element.onmouseenter = async function () {
this.style.backgroundColor = "blue";
};
element.onmouseleave = async function () {
this.style.backgroundColor = "";
};
element.onmousedown = async function () {
this.style.backgroundColor = "red";
};
element.ondblclick = async function () {
this.style.backgroundColor = "blue";
cb();
};
}
setEventListeners(upload, async () => {
const input = document.getElementById("file_input");
const upload = (file) => {
const formData = new FormData();
formData.append('file', file);
fetch('/app/upload', {
method: 'POST',
body: formData
}).then((response) => {
location.reload();
});
}
const onSelectFile = () => upload(input.files[0]);
input.addEventListener('change', onSelectFile, false);
input.click();
});
setEventListeners(download, () => {
window.location.href = "/app/download";
});
setEventListeners(logout, () => {
window.location.href = `${window.location.protocol}//logout@${window.location.host}/`;
});