From d6ee6c0411620a8dd0363ccd86f163b13ab3b022 Mon Sep 17 00:00:00 2001 From: Cadence Fish Date: Sat, 22 Feb 2020 23:44:17 +1300 Subject: [PATCH] Add updater page, disabled by default --- src/lib/constants.js | 4 ++- src/site/api/admin.js | 62 +++++++++++++++++++++++++++++++++++ src/site/pug/admin_update.pug | 32 ++++++++++++++++++ src/site/sass/main.sass | 26 +++++++++++++++ 4 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 src/site/api/admin.js create mode 100644 src/site/pug/admin_update.pug diff --git a/src/lib/constants.js b/src/lib/constants.js index 412c8b0..9ad2dac 100644 --- a/src/lib/constants.js +++ b/src/lib/constants.js @@ -25,13 +25,15 @@ let constants = { settings: { rss_enabled: true, - display_feed_validation_buttons: false + display_feed_validation_buttons: false, + enable_updater_page: false }, caching: { image_cache_control: `public, max-age=${7*24*60*60}`, resource_cache_time: 30*60*1000, instance_list_cache_time: 3*60*1000, + updater_cache_time: 2*60*1000, db_user_id: true, db_post_n3: true }, diff --git a/src/site/api/admin.js b/src/site/api/admin.js new file mode 100644 index 0000000..cb96b43 --- /dev/null +++ b/src/site/api/admin.js @@ -0,0 +1,62 @@ +const child_process = require("child_process") +const constants = require("../../lib/constants") +const {render} = require("pinski/plugins") + +function run(command) { + return new Promise((resolve, reject) => { + child_process.exec(command, {encoding: "utf8"}, (error, stdout, stderr) => { + if (error) reject(error) + else resolve({stdout, stderr}) + }) + }) +} + +let lastFetchRunAt = 0 +async function fetch() { + if (lastFetchRunAt + constants.caching.updater_cache_time < Date.now()) { + await run("git fetch origin") + lastFetchRunAt = Date.now() + } +} + +module.exports = [ + {route: "/admin/updater", methods: ["GET"], code: async () => { + if (constants.settings.enable_updater_page) { + let {stdout: current} = await run("git rev-parse --abbrev-ref HEAD") + current = current.trim() + let {stdout: upstream} = await run("git rev-parse --abbrev-ref '@{u}'") + upstream = upstream.trim() + if (current !== "master" || upstream !== "origin/master") { + return render(200, "pug/admin_update.pug", {error: `Refusing to automatically update: current is ${current}, upstream is ${upstream}, need master and origin/master`}) + } else { + await fetch() + let {stdout: log} = await run("git log --oneline origin/master ^master") + log = log.trim() + const numberOfCommits = log === "" ? 0 : log.split("\n").length + const {stdout: changedFiles} = await run("git diff master origin/master --name-only") + const changedFilesList = changedFiles.trim().split("\n") + let requiresRestart = false + let requiresDeps = false + if (changedFilesList.some(c => c.startsWith("src/lib") || c === "server.js")) { + requiresRestart = true + } + if (changedFilesList.some(c => c === "package.json" || c === "package-lock.json")) { + requiresDeps = true + requiresRestart = true + } + const formattedLog = log.split("\n").map(line => { + if (!line) return line // skip for empty string + const [hash, message] = line.match(/(\w+) (.*)$/).slice(1) + return {hash, message} + }) + return render(200, "pug/admin_update.pug", {formattedLog, numberOfCommits, requiresDeps, requiresRestart}) + } + } else { + return render(403, "pug/friendlyerror.pug", { + statusCode: 403, + title: "Updater page disabled", + message: "Updater page disabled" + }) + } + }} +] diff --git a/src/site/pug/admin_update.pug b/src/site/pug/admin_update.pug new file mode 100644 index 0000000..1e46f2b --- /dev/null +++ b/src/site/pug/admin_update.pug @@ -0,0 +1,32 @@ +//- Needs {error} or {formattedLog, numberOfCommits, requiresDeps, requiresRestart} + +doctype html +html + head + title Updater | Bibliogram + include includes/head + body.updater-page + if error + h1 Aw man. + div= error + else + h1 Bibliogram updater + if numberOfCommits > 0 + div You are #{numberOfCommits} commits behind (most recent first): + div.commits + each line in formattedLog + div.commit + code.hash= line.hash + span.message= line.message + div + if requiresDeps + span.attention You must run #[code npm install] after pulling. + else + span No changes to dependencies. + div + if requiresRestart + span.attention You must restart Bibliogram after pulling. + else + span You do not need to restart Bibliogram after pulling. + else + div You are running the latest version. Hurrah! diff --git a/src/site/sass/main.sass b/src/site/sass/main.sass index ef0e10d..ef90438 100644 --- a/src/site/sass/main.sass +++ b/src/site/sass/main.sass @@ -518,3 +518,29 @@ body border: 2px solid #aaa font-weight: bold background-color: #282828 + +.updater-page + font-size: 20px + max-width: 800px + margin: 0 auto + color: #222 + + code + font-size: 0.9em + background: #ccc + color: #000 + padding: 0px 4px + border-radius: 2px + + .commits + border-left: 2px solid #555 + margin: 10px 0px + padding-left: 10px + + .hash + margin-right: 6px + + .attention + border-left: 2px solid + padding-left: 8px + color: #700