You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

95 lines
2.7 KiB

'use strict'
const rx = require('./rx')
module.exports = redactor
function redactor ({ secret, serialize, wcLen, strict, isCensorFct }, state) {
/* eslint-disable-next-line */
const redact = Function('o', `
if (typeof o !== 'object' || o == null) {
${strictImpl(strict, serialize)}
}
const { censor, secret } = this
${redactTmpl(secret, isCensorFct)}
this.compileRestore()
${dynamicRedactTmpl(wcLen > 0, isCensorFct)}
${resultTmpl(serialize)}
`).bind(state)
if (serialize === false) {
redact.restore = (o) => state.restore(o)
}
return redact
}
function redactTmpl (secret, isCensorFct) {
return Object.keys(secret).map((path) => {
const { escPath, leadingBracket } = secret[path]
const skip = leadingBracket ? 1 : 0
const delim = leadingBracket ? '' : '.'
const hops = []
var match
while ((match = rx.exec(path)) !== null) {
const [ , ix ] = match
const { index, input } = match
if (index > skip) hops.push(input.substring(0, index - (ix ? 0 : 1)))
}
var existence = hops.map((p) => `o${delim}${p}`).join(' && ')
if (existence.length === 0) existence += `o${delim}${path} != null`
else existence += ` && o${delim}${path} != null`
const circularDetection = `
switch (true) {
${hops.reverse().map((p) => `
case o${delim}${p} === censor:
secret[${escPath}].circle = ${JSON.stringify(p)}
break
`).join('\n')}
}
`
return `
if (${existence}) {
const val = o${delim}${path}
if (val === censor) {
secret[${escPath}].precensored = true
} else {
secret[${escPath}].val = val
o${delim}${path} = ${isCensorFct ? 'censor(val)' : 'censor'}
${circularDetection}
}
}
`
}).join('\n')
}
function dynamicRedactTmpl (hasWildcards, isCensorFct) {
return hasWildcards === true ? `
{
const { wildcards, wcLen, groupRedact, nestedRedact } = this
for (var i = 0; i < wcLen; i++) {
const { before, beforeStr, after, nested } = wildcards[i]
if (nested === true) {
secret[beforeStr] = secret[beforeStr] || []
nestedRedact(secret[beforeStr], o, before, after, censor, ${isCensorFct})
} else secret[beforeStr] = groupRedact(o, before, censor, ${isCensorFct})
}
}
` : ''
}
function resultTmpl (serialize) {
return serialize === false ? `return o` : `
var s = this.serialize(o)
this.restore(o)
return s
`
}
function strictImpl (strict, serialize) {
return strict === true
? `throw Error('fast-redact: primitives cannot be redacted')`
: serialize === false ? `return o` : `return this.serialize(o)`
}