diff --git a/app.js b/app.js index c884a511..512341d4 100644 --- a/app.js +++ b/app.js @@ -25,6 +25,8 @@ var response = require('./lib/response') var models = require('./lib/models') var csp = require('./lib/csp') +const { versionCheckMiddleware, checkVersion } = require('./lib/web/middleware/checkVersion') + function createHttpServer () { if (config.useSSL) { const ca = (function () { @@ -167,6 +169,11 @@ app.use(require('./lib/middleware/checkURIValid')) app.use(require('./lib/middleware/redirectWithoutTrailingSlashes')) app.use(require('./lib/middleware/codiMDVersion')) +if (config.autoVersionCheck) { + checkVersion(app) + app.use(versionCheckMiddleware) +} + // routes need sessions // template files app.set('views', config.viewPath) @@ -200,6 +207,10 @@ app.locals.authProviders = { email: config.isEmailEnable, allowEmailRegister: config.allowEmailRegister } +app.locals.versionInfo = { + latest: true, + versionItem: null +} // Export/Import menu items app.locals.enableDropBoxSave = config.isDropboxEnable diff --git a/lib/config/default.js b/lib/config/default.js index 1167cb75..2e76b143 100644 --- a/lib/config/default.js +++ b/lib/config/default.js @@ -178,5 +178,6 @@ module.exports = { // Generated id: "31-good-morning-my-friend---do-you-have-5" // 2nd appearance: "31-good-morning-my-friend---do-you-have-5-1" // 3rd appearance: "31-good-morning-my-friend---do-you-have-5-2" - linkifyHeaderStyle: 'keep-case' + linkifyHeaderStyle: 'keep-case', + autoVersionCheck: true } diff --git a/lib/config/environment.js b/lib/config/environment.js index 3a62985c..8426d82f 100644 --- a/lib/config/environment.js +++ b/lib/config/environment.js @@ -142,5 +142,6 @@ module.exports = { allowPDFExport: toBooleanConfig(process.env.CMD_ALLOW_PDF_EXPORT), openID: toBooleanConfig(process.env.CMD_OPENID), defaultUseHardbreak: toBooleanConfig(process.env.CMD_DEFAULT_USE_HARD_BREAK), - linkifyHeaderStyle: process.env.CMD_LINKIFY_HEADER_STYLE + linkifyHeaderStyle: process.env.CMD_LINKIFY_HEADER_STYLE, + autoVersionCheck: toBooleanConfig(process.env.CMD_AUTO_VERSION_CHECK) } diff --git a/lib/web/middleware/checkVersion.js b/lib/web/middleware/checkVersion.js new file mode 100644 index 00000000..9cd9325e --- /dev/null +++ b/lib/web/middleware/checkVersion.js @@ -0,0 +1,67 @@ +'use strict' + +const { promisify } = require('util') + +const request = require('request') + +const logger = require('../../logger') +const config = require('../../config') + +let lastCheckAt + +const VERSION_CHECK_ENDPOINT = 'https://evangelion.codimd.dev/' +const CHECK_TIMEOUT = 1000 * 60 * 60 * 24 // 1 day + +const rp = promisify(request) + +exports.checkVersion = checkVersion +/** + * @param {Express.Application|Express.Request} ctx + */ +async function checkVersion (ctx) { + if (lastCheckAt && (lastCheckAt + CHECK_TIMEOUT > Date.now())) { + return + } + + // update lastCheckAt whether the check would fail or not + lastCheckAt = Date.now() + + try { + const { statusCode, body: data } = await rp({ + url: `${VERSION_CHECK_ENDPOINT}?v=${config.version}`, + method: 'GET', + json: true + }) + + if (statusCode !== 200 || data.status === 'error') { + logger.error('Version check failed.') + return + } + + const locals = ctx.locals ? ctx.locals : ctx.app.locals + + locals.versionInfo.latest = data.latest + locals.versionInfo.versionItem = data.latest ? null : data.versionItem + + if (!data.latest) { + const { version, link } = data.versionItem + + logger.warn(`Your CodiMD version is out of date! The latest version is ${version}. Please see what's new on ${link}.`) + } + } catch (err) { + // ignore and skip version check + logger.error('Version check failed.') + logger.error(err) + } +} + +exports.versionCheckMiddleware = function (req, res, next) { + checkVersion(req) + .then(() => { + next() + }) + .catch((err) => { + logger.error(err) + next() + }) +}