From 9b51fcc5c03add770c30a242a34b3ff29bb5c904 Mon Sep 17 00:00:00 2001 From: Justin Wind Date: Tue, 29 Mar 2022 11:39:07 -0700 Subject: [PATCH] minor updates --- server.js | 6 +-- src/logger.js | 74 ---------------------------------- src/logger/data-sanitizers.js | 25 ++++++++++++ src/logger/index.js | 13 ++++++ src/manager.js | 3 +- src/service.js | 24 ++++++----- src/template/root-html.js | 20 +++++---- static/index.html | 2 +- static/muRL.png | Bin 0 -> 7373 bytes static/theme.css | 4 ++ 10 files changed, 74 insertions(+), 97 deletions(-) delete mode 100644 src/logger.js create mode 100644 src/logger/data-sanitizers.js create mode 100644 src/logger/index.js create mode 100644 static/muRL.png diff --git a/server.js b/server.js index 404a7c5..17302b7 100644 --- a/server.js +++ b/server.js @@ -9,7 +9,7 @@ const Service = require('./src/service'); const { fileScope } = require('./src/common'); const { version } = require('./package.json'); -const _fileScope = fileScope(__filename)('main'); +const _scope = fileScope(__filename)('main'); const PORT = process.env.PORT || 3001; const ADDR = process.env.LISTEN_ADDR || '127.0.0.1'; @@ -32,8 +32,8 @@ http.createServer((req, res) => { service.dispatch(req, res); }).listen(PORT, ADDR, (err) => { if (err) { - logger.error(_fileScope, 'error starting server:', err); + logger.error(_scope, 'error starting server:', err); throw err; } - logger.info(_fileScope, `server (version ${version}) started on ${ADDR}:${PORT}`); + logger.info(_scope, 'server started', { version, listenAddress: ADDR, listenPort: PORT }); }); diff --git a/src/logger.js b/src/logger.js deleted file mode 100644 index 7c8e3cb..0000000 --- a/src/logger.js +++ /dev/null @@ -1,74 +0,0 @@ -'use strict'; - -/** - * Log as JSON to stdout/stderr. - */ - -const common = require('./common'); - -// This is uncomfortable, but is the simplest way to let logging work for BigInts. -// TODO: revisit with better solution -BigInt.prototype.toJSON = function() { - return this.toString(); -} - -// Also uncomfortable -Object.defineProperty(Error.prototype, 'toJSON', { - configurable: true, - value: function () { - const result = {}; - const dupKey = function (key) { - // eslint-disable-next-line security/detect-object-injection - result[key] = this[key]; - }; - Object.getOwnPropertyNames(this).forEach(dupKey, this); - return result; - }, -}); - -const defaultOptions = { - ignoreBelowLevel: 'debug', - backend: console, -}; - -class Logger { - constructor(options = {}) { - common.setOptions(this, defaultOptions, options); - - this.logLevels = [ - 'error', - 'warn', - 'info', - 'log', - 'debug', - ]; - - const ignoreLevelIdx = this.logLevels.indexOf(this.ignoreBelowLevel); - this.logLevels.forEach((level) => { - // eslint-disable-next-line security/detect-object-injection - this[level] = (this.logLevels.indexOf(level) > ignoreLevelIdx) ? - () => {} : - Logger.levelTemplateFn(this.backend, level); - }); - } - - static levelTemplateFn(backend, level) { - return function (...args) { - // eslint-disable-next-line security/detect-object-injection - backend[level](Logger.payload(level, ...args)); - }; - } - - static payload(level, scope, message, data, ...other) { - return JSON.stringify({ - timestamp: Date.now(), - level: level, - scope: scope || '[unknown]', - message: message || '', - data: data || {}, - ...(other.length && { other }), - }); - } -} - -module.exports = Logger; diff --git a/src/logger/data-sanitizers.js b/src/logger/data-sanitizers.js new file mode 100644 index 0000000..a6b444b --- /dev/null +++ b/src/logger/data-sanitizers.js @@ -0,0 +1,25 @@ +'use strict'; + +/** + * Scrub credential from POST login body data. + * @param {Object} data + * @param {Boolean} sanitize + * @returns {Boolean} + */ +function sanitizePostCredential(data, sanitize = true) { + let unclean = false; + + const credentialLength = data && data.ctx && data.ctx.parsedBody && data.ctx.parsedBody.credential && data.ctx.parsedBody.credential.length; + if (credentialLength) { + unclean = true; + } + if (unclean && sanitize) { + data.ctx.parsedBody.credential = '*'.repeat(credentialLength); + } + + return unclean; +} + +module.exports = { + sanitizePostCredential, +}; \ No newline at end of file diff --git a/src/logger/index.js b/src/logger/index.js new file mode 100644 index 0000000..7944cf6 --- /dev/null +++ b/src/logger/index.js @@ -0,0 +1,13 @@ +'use strict'; + +const BaseLogger = require('@squeep/logger-json-console'); +const dataSanitizers = require('./data-sanitizers'); + +class Logger extends BaseLogger { + constructor(options, ...args) { + super(options, ...args); + Array.prototype.push.apply(this.dataSanitizers, Object.values(dataSanitizers)); + } +} + +module.exports = Logger; \ No newline at end of file diff --git a/src/manager.js b/src/manager.js index a5035cd..a46db55 100644 --- a/src/manager.js +++ b/src/manager.js @@ -11,6 +11,7 @@ const _fileScope = common.fileScope(__filename); const defaultOptions = { pageTitle: require('../package.json').name, + logoUrl: '/static/muRL.png', selfBaseUrl: '', staticDirectory: '/static/', }; @@ -44,7 +45,7 @@ class Manager { case Enum.ContentType.TextHTML: default: - return Template.rootHTML(ctx, this.pageTitle); + return Template.rootHTML(ctx, this.pageTitle, this.logoUrl); } } diff --git a/src/service.js b/src/service.js index 1b09d2d..97ed85e 100644 --- a/src/service.js +++ b/src/service.js @@ -68,13 +68,13 @@ class Service extends Dingus { * @param {string} contentType * @param {object} ctx */ - parseBody(contentType, ctx) { + parseBody(contentType, ctx, rawBody) { // eslint-disable-next-line sonarjs/no-small-switch switch (contentType) { // Handle any additional content types here default: - super.parseBody(contentType, ctx); + super.parseBody(contentType, ctx, rawBody); } } @@ -107,10 +107,12 @@ class Service extends Dingus { */ async handlerPostRoot(req, res, ctx) { const _scope = _fileScope('handlerPostRoot'); - this.logger.debug(_scope, 'called', { req: common.requestLogData(req), ctx }); + this.logger.debug(_scope, 'called', { req, ctx }); this.setResponseType(this.responseTypes, req, res, ctx); - await this.ingestBody(req, res, ctx); + await this.ingestBody(req, res, ctx, { + maximumBodySize: 1024 * 8, + }); await this._postRootAuth(req, res, ctx); await this.manager.postRoot(res, ctx); @@ -127,7 +129,7 @@ class Service extends Dingus { const responseTypes = [ Enum.ContentType.TextHTML, ]; - this.logger.debug(_scope, 'called', { req: common.requestLogData(req), ctx }); + this.logger.debug(_scope, 'called', { req, ctx }); Dingus.setHeadHandler(req, res, ctx); @@ -146,7 +148,7 @@ class Service extends Dingus { */ async handlerGetId(req, res, ctx) { const _scope = _fileScope('handlerGetId'); - this.logger.debug(_scope, 'called', { req: common.requestLogData(req), ctx }); + this.logger.debug(_scope, 'called', { req, ctx }); Dingus.setHeadHandler(req, res, ctx); @@ -172,7 +174,7 @@ class Service extends Dingus { */ async handlerDeleteId(req, res, ctx) { const _scope = _fileScope('handlerDeleteId'); - this.logger.debug(_scope, 'called', { req: common.requestLogData(req), ctx }); + this.logger.debug(_scope, 'called', { req, ctx }); this.setResponseType(this.responseTypes, req, res, ctx); await this.authenticator.required(req, res, ctx); @@ -188,7 +190,7 @@ class Service extends Dingus { */ async handlerPutId(req, res, ctx) { const _scope = _fileScope('handlerPutId'); - this.logger.debug(_scope, 'called', { req: common.requestLogData(req), ctx }); + this.logger.debug(_scope, 'called', { req, ctx }); this.setResponseType(this.responseTypes, req, res, ctx); await this.ingestBody(req, res, ctx); @@ -205,7 +207,7 @@ class Service extends Dingus { */ async handlerGetIdInfo(req, res, ctx) { const _scope = _fileScope('handlerGetIdInfo'); - this.logger.debug(_scope, 'called', { req: common.requestLogData(req), ctx }); + this.logger.debug(_scope, 'called', { req, ctx }); Dingus.setHeadHandler(req, res, ctx); @@ -223,7 +225,7 @@ class Service extends Dingus { */ async handlerGetStatic(req, res, ctx) { const _scope = _fileScope('handlerGetStatic'); - this.logger.debug(_scope, 'called', { req: common.requestLogData(req), ctx }); + this.logger.debug(_scope, 'called', { req, ctx }); Dingus.setHeadHandler(req, res, ctx); @@ -242,7 +244,7 @@ class Service extends Dingus { */ async handlerGetAdminReport(req, res, ctx) { const _scope = _fileScope('handlerAdminReport'); - this.logger.debug(_scope, 'called', { req: common.requestLogData(req), ctx }); + this.logger.debug(_scope, 'called', { req, ctx }); Dingus.setHeadHandler(req, res, ctx); diff --git a/src/template/root-html.js b/src/template/root-html.js index 65e34c7..c7550c5 100644 --- a/src/template/root-html.js +++ b/src/template/root-html.js @@ -1,6 +1,7 @@ 'use strict'; -module.exports = (ctx, pageTitle) => { +module.exports = (ctx, pageTitle, logoUrl) => { + const logoImg = logoUrl ? `` : ''; return ` @@ -10,21 +11,26 @@ module.exports = (ctx, pageTitle) => { - + });`) + ` +
-

${pageTitle}

+

${logoImg}${pageTitle}

` + (!ctx.createdLink ? '' : `