X-Git-Url: https://git.squeep.com/?a=blobdiff_plain;f=lib%2Fcommon.js;h=5563254f0bab35b7b54322dd46ad0cfa9c49e3c4;hb=4c4e541aaf46de91b9b5e9b4640d7336ffe29f5b;hp=816b65c5bea9ad23052eaf75b06961a20e999037;hpb=392502c5cc0cb12cf3c00ecd06c5c69b3e00d7e3;p=squeep-authentication-module diff --git a/lib/common.js b/lib/common.js index 816b65c..5563254 100644 --- a/lib/common.js +++ b/lib/common.js @@ -1,17 +1,20 @@ 'use strict'; const { common } = require('@squeep/api-dingus'); +const { randomBytes } = require('node:crypto'); +const { promisify } = require('node:util'); +const randomBytesAsync = promisify(randomBytes); /** * Recursively freeze an object. - * @param {Object} o - * @returns {Object} + * @param {object} o object to freeze + * @returns {object} frozen object */ const freezeDeep = (o) => { Object.freeze(o); Object.getOwnPropertyNames(o).forEach((prop) => { - if (Object.hasOwnProperty.call(o, prop) + if (Object.hasOwn(o, prop) && ['object', 'function'].includes(typeof o[prop]) // eslint-disable-line security/detect-object-injection && !Object.isFrozen(o[prop])) { // eslint-disable-line security/detect-object-injection return freezeDeep(o[prop]); // eslint-disable-line security/detect-object-injection @@ -20,10 +23,23 @@ const freezeDeep = (o) => { return o; }; +/** + * Return a new object duplicating `o`, without the properties specified. + * @param {object} o source object + * @param {string[]} props list of property names to omit + * @returns {object} pruned object + */ const omit = (o, props) => { return Object.fromEntries(Object.entries(o).filter(([k]) => !props.includes(k))); }; +/** + * Helper to log mystery-box statistics. + * @param {object} logger logger + * @param {Function} logger.debug log debug + * @param {string} scope scope + * @returns {Function} stats log decorator + */ const mysteryBoxLogger = (logger, scope) => { return (s) => { logger.debug(scope, `${s.packageName}@${s.packageVersion}:${s.method}`, omit(s, [ @@ -34,8 +50,24 @@ const mysteryBoxLogger = (logger, scope) => { }; }; +/** + * Hide sensitive part of an Authorization header. + * @param {string} authHeader header value + * @returns {string} scrubbed header value + */ +const obscureAuthorizationHeader = (authHeader) => { + if (!authHeader) { + return authHeader; + } + const space = authHeader.indexOf(' '); + // This blurs entire string if no space found, because -1. + return authHeader.slice(0, space + 1) + '*'.repeat(authHeader.length - (space + 1)); +}; + module.exports = Object.assign(Object.create(common), { freezeDeep, mysteryBoxLogger, + obscureAuthorizationHeader, omit, -}); \ No newline at end of file + randomBytesAsync, +});