From 3f22c8b8e0a1463d41d65ce7d902d2d4ff731502 Mon Sep 17 00:00:00 2001 From: Bill Church Date: Thu, 19 May 2022 12:10:41 -0400 Subject: [PATCH] refactor: move some functions out of app.js --- app/server/app.js | 115 ++++++------------------------------------- app/server/routes.js | 93 ++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+), 100 deletions(-) create mode 100644 app/server/routes.js diff --git a/app/server/app.js b/app/server/app.js index ad5ac48..ab8a7c1 100644 --- a/app/server/app.js +++ b/app/server/app.js @@ -14,12 +14,12 @@ const logger = require('morgan'); const app = express(); const server = require('http').Server(app); -const validator = require('validator'); const favicon = require('serve-favicon'); const io = require('socket.io')(server, config.socketio); const session = require('express-session')(config.express); const appSocket = require('./socket'); const myutil = require('./util'); +const { reauth, connect, notfound, handleErrors } = require('./routes'); myutil.setDefaultCredentials(config); @@ -35,6 +35,19 @@ function safeShutdownGuard(req, res, next) { return next(); } } +// express +app.use(safeShutdownGuard); +app.use(session); +if (config.accesslog) app.use(logger('common')); +app.disable('x-powered-by'); +app.use(favicon(path.join(publicPath, 'favicon.ico'))); +app.use('/ssh', express.static(publicPath, config.express.ssh)); +app.use(myutil.basicAuth); +app.get('/ssh/reauth', reauth); +app.get('/ssh/host/:host?', connect); +app.use(notfound); +app.use(handleErrors); + // clean stop function stopApp(reason) { shutdownMode = false; @@ -44,105 +57,6 @@ function stopApp(reason) { server.close(); } -module.exports = { server, config }; -// express -app.use(safeShutdownGuard); -app.use(session); -app.use(myutil.basicAuth); -if (config.accesslog) app.use(logger('common')); -app.disable('x-powered-by'); - -// static files -app.use('/ssh', express.static(publicPath, config.express.ssh)); - -// favicon from root if being pre-fetched by browser to prevent a 404 -app.use(favicon(path.join(publicPath, 'favicon.ico'))); - -app.get('/ssh/reauth', (req, res) => { - const r = req.headers.referer || '/'; - res - .status(401) - .send( - `` - ); -}); - -// eslint-disable-next-line complexity -app.get('/ssh/host/:host?', (req, res) => { - res.sendFile(path.join(path.join(publicPath, 'client.htm'))); - // capture, assign, and validate variables - req.session.ssh = { - host: - config.ssh.host || - (validator.isIP(`${req.params.host}`) && req.params.host) || - (validator.isFQDN(req.params.host) && req.params.host) || - (/^(([a-z]|[A-Z]|\d|[!^(){}\-_~])+)?\w$/.test(req.params.host) && req.params.host), - port: - (validator.isInt(`${req.query.port}`, { min: 1, max: 65535 }) && req.query.port) || - config.ssh.port, - localAddress: config.ssh.localAddress, - localPort: config.ssh.localPort, - header: { - name: req.query.header || config.header.text, - background: req.query.headerBackground || config.header.background, - }, - algorithms: config.algorithms, - keepaliveInterval: config.ssh.keepaliveInterval, - keepaliveCountMax: config.ssh.keepaliveCountMax, - allowedSubnets: config.ssh.allowedSubnets, - term: - (/^(([a-z]|[A-Z]|\d|[!^(){}\-_~])+)?\w$/.test(req.query.sshterm) && req.query.sshterm) || - config.ssh.term, - terminal: { - cursorBlink: validator.isBoolean(`${req.query.cursorBlink}`) - ? myutil.parseBool(req.query.cursorBlink) - : config.terminal.cursorBlink, - scrollback: - validator.isInt(`${req.query.scrollback}`, { min: 1, max: 200000 }) && req.query.scrollback - ? req.query.scrollback - : config.terminal.scrollback, - tabStopWidth: - validator.isInt(`${req.query.tabStopWidth}`, { min: 1, max: 100 }) && req.query.tabStopWidth - ? req.query.tabStopWidth - : config.terminal.tabStopWidth, - bellStyle: - req.query.bellStyle && ['sound', 'none'].indexOf(req.query.bellStyle) > -1 - ? req.query.bellStyle - : config.terminal.bellStyle, - }, - allowreplay: - config.options.challengeButton || - (validator.isBoolean(`${req.headers.allowreplay}`) - ? myutil.parseBool(req.headers.allowreplay) - : false), - allowreauth: config.options.allowreauth || false, - mrhsession: - validator.isAlphanumeric(`${req.headers.mrhsession}`) && req.headers.mrhsession - ? req.headers.mrhsession - : 'none', - serverlog: { - client: config.serverlog.client || false, - server: config.serverlog.server || false, - }, - readyTimeout: - (validator.isInt(`${req.query.readyTimeout}`, { min: 1, max: 300000 }) && - req.query.readyTimeout) || - config.ssh.readyTimeout, - }; - if (req.session.ssh.header.name) validator.escape(req.session.ssh.header.name); - if (req.session.ssh.header.background) validator.escape(req.session.ssh.header.background); -}); - -// express error handling -app.use((req, res) => { - res.status(404).send("Sorry, can't find that!"); -}); - -app.use((err, req, res) => { - console.error(err.stack); - res.status(500).send('Something broke!'); -}); - // bring up socket io.on('connection', appSocket); @@ -187,3 +101,4 @@ signals.forEach((signal) => } else stopApp(); }) ); +module.exports = { server, config }; diff --git a/app/server/routes.js b/app/server/routes.js new file mode 100644 index 0000000..5326ae7 --- /dev/null +++ b/app/server/routes.js @@ -0,0 +1,93 @@ +/* eslint-disable no-console */ +// ssh.js +const validator = require('validator'); +const path = require('path'); + +const nodeRoot = path.dirname(require.main.filename); + +const publicPath = path.join(nodeRoot, 'client', 'public'); +const { parseBool } = require('./util'); +const config = require('./config'); + +exports.reauth = function reauth(req, res) { + const r = req.headers.referer || '/'; + res + .status(401) + .send( + `` + ); +}; + +exports.connect = function connect(req, res) { + res.sendFile(path.join(path.join(publicPath, 'client.htm'))); + // capture, assign, and validate variables + req.session.ssh = { + host: + config.ssh.host || + (validator.isIP(`${req.params.host}`) && req.params.host) || + (validator.isFQDN(req.params.host) && req.params.host) || + (/^(([a-z]|[A-Z]|\d|[!^(){}\-_~])+)?\w$/.test(req.params.host) && req.params.host), + port: + (validator.isInt(`${req.query.port}`, { min: 1, max: 65535 }) && req.query.port) || + config.ssh.port, + localAddress: config.ssh.localAddress, + localPort: config.ssh.localPort, + header: { + name: req.query.header || config.header.text, + background: req.query.headerBackground || config.header.background, + }, + algorithms: config.algorithms, + keepaliveInterval: config.ssh.keepaliveInterval, + keepaliveCountMax: config.ssh.keepaliveCountMax, + allowedSubnets: config.ssh.allowedSubnets, + term: + (/^(([a-z]|[A-Z]|\d|[!^(){}\-_~])+)?\w$/.test(req.query.sshterm) && req.query.sshterm) || + config.ssh.term, + terminal: { + cursorBlink: validator.isBoolean(`${req.query.cursorBlink}`) + ? parseBool(req.query.cursorBlink) + : config.terminal.cursorBlink, + scrollback: + validator.isInt(`${req.query.scrollback}`, { min: 1, max: 200000 }) && req.query.scrollback + ? req.query.scrollback + : config.terminal.scrollback, + tabStopWidth: + validator.isInt(`${req.query.tabStopWidth}`, { min: 1, max: 100 }) && req.query.tabStopWidth + ? req.query.tabStopWidth + : config.terminal.tabStopWidth, + bellStyle: + req.query.bellStyle && ['sound', 'none'].indexOf(req.query.bellStyle) > -1 + ? req.query.bellStyle + : config.terminal.bellStyle, + }, + allowreplay: + config.options.challengeButton || + (validator.isBoolean(`${req.headers.allowreplay}`) + ? parseBool(req.headers.allowreplay) + : false), + allowreauth: config.options.allowreauth || false, + mrhsession: + validator.isAlphanumeric(`${req.headers.mrhsession}`) && req.headers.mrhsession + ? req.headers.mrhsession + : 'none', + serverlog: { + client: config.serverlog.client || false, + server: config.serverlog.server || false, + }, + readyTimeout: + (validator.isInt(`${req.query.readyTimeout}`, { min: 1, max: 300000 }) && + req.query.readyTimeout) || + config.ssh.readyTimeout, + }; + if (req.session.ssh.header.name) validator.escape(req.session.ssh.header.name); + if (req.session.ssh.header.background) validator.escape(req.session.ssh.header.background); +}; + +exports.notfound = function notfound(req, res) { + res.status(404).send("Sorry, can't find that!"); +}; + +exports.handleErrors = function handleErrors(err, req, res) { + console.error(err.stack); + res.status(500).send('Something broke!'); +};