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.
		
		
		
		
		
			
		
			
				
					
					
						
							100 lines
						
					
					
						
							3.0 KiB
						
					
					
				
			
		
		
	
	
							100 lines
						
					
					
						
							3.0 KiB
						
					
					
				| 'use strict'
 | |
| 
 | |
| const rx = require('./rx')
 | |
| 
 | |
| module.exports = redactor
 | |
| 
 | |
| function redactor ({ secret, serialize, wcLen, strict, isCensorFct, censorFctTakesPath }, 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, censorFctTakesPath)}
 | |
|     this.compileRestore()
 | |
|     ${dynamicRedactTmpl(wcLen > 0, isCensorFct, censorFctTakesPath)}
 | |
|     ${resultTmpl(serialize)}
 | |
|   `).bind(state)
 | |
| 
 | |
|   if (serialize === false) {
 | |
|     redact.restore = (o) => state.restore(o)
 | |
|   }
 | |
| 
 | |
|   return redact
 | |
| }
 | |
| 
 | |
| function redactTmpl (secret, isCensorFct, censorFctTakesPath) {
 | |
|   return Object.keys(secret).map((path) => {
 | |
|     const { escPath, leadingBracket, path: arrPath } = 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')}
 | |
|       }
 | |
|     `
 | |
| 
 | |
|     const censorArgs = censorFctTakesPath
 | |
|       ? `val, ${JSON.stringify(arrPath)}`
 | |
|       : `val`
 | |
| 
 | |
|     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(${censorArgs})` : 'censor'}
 | |
|           ${circularDetection}
 | |
|         }
 | |
|       }
 | |
|     `
 | |
|   }).join('\n')
 | |
| }
 | |
| 
 | |
| function dynamicRedactTmpl (hasWildcards, isCensorFct, censorFctTakesPath) {
 | |
|   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}, ${censorFctTakesPath})
 | |
|         } else secret[beforeStr] = groupRedact(o, before, censor, ${isCensorFct}, ${censorFctTakesPath})
 | |
|       }
 | |
|     }
 | |
|   ` : ''
 | |
| }
 | |
| 
 | |
| 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)`
 | |
| }
 |