X-Git-Url: http://git.squeep.com/?p=squeep-indie-auther;a=blobdiff_plain;f=src%2Flogger%2Fdata-sanitizers.js;fp=src%2Flogger%2Fdata-sanitizers.js;h=450842ed20367e6a52e182ccff6d6717d4de69a6;hp=0000000000000000000000000000000000000000;hb=b0103b0d496262c438b40bc20304081dbfe41e73;hpb=8ed81748bce7cea7904cac7225b20a60cafdfc16 diff --git a/src/logger/data-sanitizers.js b/src/logger/data-sanitizers.js new file mode 100644 index 0000000..450842e --- /dev/null +++ b/src/logger/data-sanitizers.js @@ -0,0 +1,116 @@ +'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?.ctx?.parsedBody?.credential?.length; + if (credentialLength) { + unclean = true; + } + if (unclean && sanitize) { + data.ctx.parsedBody.credential = '*'.repeat(credentialLength); + } + + return unclean; +} + + +/** + * Reduce logged data about scopes from profilesScopes. + * For all referenced scopes, only include profiles list. + * Remove scopes without profile references from scopeIndex. + * @param {Object} data + * @param {Boolean} sanitize + */ +function reduceScopeVerbosity(data, sanitize = true) { + let unclean = false; + + const { + scopesEntries: ctxScopesEntries, + profilesEntries: ctxProfilesEntries, + needsSanitize: ctxNeedsSanitize, + } = _scopesFrom(data?.ctx?.profilesScopes); + + const { + scopesEntries: sessionScopesEntries, + profilesEntries: sessionProfilesEntries, + needsSanitize: sessionNeedsSanitize, + } = _scopesFrom(data?.ctx?.session); + + if (ctxNeedsSanitize || sessionNeedsSanitize) { + unclean = true; + } + if (unclean && sanitize) { + if (ctxNeedsSanitize) { + Object.assign(data.ctx.profilesScopes, _sanitizeProfilesScopes(ctxScopesEntries, ctxProfilesEntries)); + } + if (sessionNeedsSanitize) { + Object.assign(data.ctx.session, _sanitizeProfilesScopes(sessionScopesEntries, sessionProfilesEntries)); + } + } + + return unclean; +} + + +/** + * Return any scope entries on an object, and whether sanitization is needed. + * @param {Object=} obj + * @returns {Object} + */ +const _scopesFrom = (obj) => { + const scopesEntries = Object.entries(obj?.scopeIndex || {}); + const profilesEntries = Object.entries(obj?.profileScopes || {}); + const needsSanitize = scopesEntries.length || profilesEntries.length; + return { + scopesEntries, + profilesEntries, + needsSanitize, + }; +}; + + +/** + * @typedef {[String, Object]} ScopeEntry + */ +/** + * Return new list of entries with scrubbed scopeDetails. + * @param {ScopeEntry[]} entries + * @returns {ScopeEntry[]} + */ +const _scopeEntriesScrubber = (entries) => entries.map(([scopeName, scopeDetails]) => ([scopeName, { profiles: scopeDetails.profiles }])); + + +/** + * Create a new profilesScopes type object with scrubbed scope details. + * @param {ScopeEntry[]} scopesEntries + * @param {ScopeEntry[]} profilesEntries + * @returns {Object} + */ +const _sanitizeProfilesScopes = (scopesEntries, profilesEntries) => { + const referencedScopesEntries = scopesEntries.filter(([_scopeName, scopeDetails]) => scopeDetails?.profiles?.length); // eslint-disable-line no-unused-vars + const scrubbedScopesEntries = _scopeEntriesScrubber(referencedScopesEntries); + + const scrubbedProfilesEntries = profilesEntries.map(([profileName, profileScopes]) => { + const profileScopeEntries = Object.entries(profileScopes); + const scrubbedProfileScopeEntries = _scopeEntriesScrubber(profileScopeEntries); + const scrubbedProfileScopes = Object.fromEntries(scrubbedProfileScopeEntries); + return [profileName, scrubbedProfileScopes]; + }); + + return { + scopeIndex: Object.fromEntries(scrubbedScopesEntries), + profileScopes: Object.fromEntries(scrubbedProfilesEntries), + }; +}; + +module.exports = { + sanitizePostCredential, + reduceScopeVerbosity, +}; \ No newline at end of file