const { R } = require("redbean-node"); const { checkLogin, setSettings } = require("../util-server"); const dayjs = require("dayjs"); const { log, log_info, log_debug, log_error } = require("../../src/util"); const ImageDataURI = require("../image-data-uri"); const Database = require("../database"); const apicache = require("../modules/apicache"); module.exports.statusPageSocketHandler = (socket) => { // Post or edit incident socket.on("postIncident", async (incident, callback) => { try { checkLogin(socket); await R.exec("UPDATE incident SET pin = 0 "); let incidentBean; if (incident.id) { incidentBean = await R.findOne("incident", " id = ?", [ incident.id ]); } if (incidentBean == null) { incidentBean = R.dispense("incident"); } incidentBean.title = incident.title; incidentBean.content = incident.content; incidentBean.style = incident.style; incidentBean.pin = true; if (incident.id) { incidentBean.lastUpdatedDate = R.isoDateTime(dayjs.utc()); } else { incidentBean.createdDate = R.isoDateTime(dayjs.utc()); } await R.store(incidentBean); callback({ ok: true, incident: incidentBean.toPublicJSON(), }); } catch (error) { callback({ ok: false, msg: error.message, }); } }); socket.on("unpinIncident", async (callback) => { try { checkLogin(socket); await R.exec("UPDATE incident SET pin = 0 WHERE pin = 1"); callback({ ok: true, }); } catch (error) { callback({ ok: false, msg: error.message, }); } }); // Save Status Page // imgDataUrl Only Accept PNG! socket.on("saveStatusPage", async (config, imgDataUrl, publicGroupList, callback) => { try { checkLogin(socket); apicache.clear(); const header = "data:image/png;base64,"; // Check logo format // If is image data url, convert to png file // Else assume it is a url, nothing to do if (imgDataUrl.startsWith("data:")) { if (! imgDataUrl.startsWith(header)) { throw new Error("Only allowed PNG logo."); } // Convert to file await ImageDataURI.outputFile(imgDataUrl, Database.uploadDir + "logo.png"); config.logo = "/upload/logo.png?t=" + Date.now(); } else { config.icon = imgDataUrl; } // Save Config await setSettings("statusPage", config); // Save Public Group List const groupIDList = []; let groupOrder = 1; for (let group of publicGroupList) { let groupBean; if (group.id) { groupBean = await R.findOne("group", " id = ? AND public = 1 ", [ group.id ]); } else { groupBean = R.dispense("group"); } groupBean.name = group.name; groupBean.public = true; groupBean.weight = groupOrder++; await R.store(groupBean); await R.exec("DELETE FROM monitor_group WHERE group_id = ? ", [ groupBean.id ]); let monitorOrder = 1; log_info("socket", group.monitorList); for (let monitor of group.monitorList) { let relationBean = R.dispense("monitor_group"); relationBean.weight = monitorOrder++; relationBean.group_id = groupBean.id; relationBean.monitor_id = monitor.id; await R.store(relationBean); } groupIDList.push(groupBean.id); group.id = groupBean.id; } // Delete groups that are not in the list log_debug("socket", "Delete groups that are not in the list"); const slots = groupIDList.map(() => "?").join(","); await R.exec(`DELETE FROM \`group\` WHERE id NOT IN (${slots})`, groupIDList); callback({ ok: true, publicGroupList, }); } catch (error) { log_error("socket", error); callback({ ok: false, msg: error.message, }); } }); };