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.
		
		
		
		
		
			
		
			
				
					86 lines
				
				2.4 KiB
			
		
		
			
		
	
	
					86 lines
				
				2.4 KiB
			| 
											3 years ago
										 | 'use strict' | ||
|  | 
 | ||
|  | const { groupRestore, nestedRestore } = require('./modifiers') | ||
|  | 
 | ||
|  | module.exports = restorer | ||
|  | 
 | ||
|  | function restorer ({ secret, wcLen }) { | ||
|  |   return function compileRestore () { | ||
|  |     if (this.restore) return | ||
|  |     const paths = Object.keys(secret) | ||
|  |     const resetters = resetTmpl(secret, paths) | ||
|  |     const hasWildcards = wcLen > 0 | ||
|  |     const state = hasWildcards ? { secret, groupRestore, nestedRestore } : { secret } | ||
|  |     /* eslint-disable-next-line */ | ||
|  |     this.restore = Function( | ||
|  |       'o', | ||
|  |       restoreTmpl(resetters, paths, hasWildcards) | ||
|  |     ).bind(state) | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Mutates the original object to be censored by restoring its original values | ||
|  |  * prior to censoring. | ||
|  |  * | ||
|  |  * @param {object} secret Compiled object describing which target fields should | ||
|  |  * be censored and the field states. | ||
|  |  * @param {string[]} paths The list of paths to censor as provided at | ||
|  |  * initialization time. | ||
|  |  * | ||
|  |  * @returns {string} String of JavaScript to be used by `Function()`. The | ||
|  |  * string compiles to the function that does the work in the description. | ||
|  |  */ | ||
|  | function resetTmpl (secret, paths) { | ||
|  |   return paths.map((path) => { | ||
|  |     const { circle, escPath, leadingBracket } = secret[path] | ||
|  |     const delim = leadingBracket ? '' : '.' | ||
|  |     const reset = circle | ||
|  |       ? `o.${circle} = secret[${escPath}].val` | ||
|  |       : `o${delim}${path} = secret[${escPath}].val` | ||
|  |     const clear = `secret[${escPath}].val = undefined` | ||
|  |     return `
 | ||
|  |       if (secret[${escPath}].val !== undefined) { | ||
|  |         try { ${reset} } catch (e) {} | ||
|  |         ${clear} | ||
|  |       } | ||
|  |     `
 | ||
|  |   }).join('') | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Creates the body of the restore function | ||
|  |  * | ||
|  |  * Restoration of the redacted object happens | ||
|  |  * backwards, in reverse order of redactions, | ||
|  |  * so that repeated redactions on the same object | ||
|  |  * property can be eventually rolled back to the | ||
|  |  * original value. | ||
|  |  * | ||
|  |  * This way dynamic redactions are restored first, | ||
|  |  * starting from the last one working backwards and | ||
|  |  * followed by the static ones. | ||
|  |  * | ||
|  |  * @returns {string} the body of the restore function | ||
|  |  */ | ||
|  | function restoreTmpl (resetters, paths, hasWildcards) { | ||
|  |   const dynamicReset = hasWildcards === true ? `
 | ||
|  |     const keys = Object.keys(secret) | ||
|  |     const len = keys.length | ||
|  |     for (var i = len - 1; i >= ${paths.length}; i--) { | ||
|  |       const k = keys[i] | ||
|  |       const o = secret[k] | ||
|  |       if (o.flat === true) this.groupRestore(o) | ||
|  |       else this.nestedRestore(o) | ||
|  |       secret[k] = null | ||
|  |     } | ||
|  |   ` : ''
 | ||
|  | 
 | ||
|  |   return `
 | ||
|  |     const secret = this.secret | ||
|  |     ${dynamicReset} | ||
|  |     ${resetters} | ||
|  |     return o | ||
|  |   `
 | ||
|  | } |