diff --git a/keyserver/src/utils/validation-utils.js b/keyserver/src/utils/validation-utils.js --- a/keyserver/src/utils/validation-utils.js +++ b/keyserver/src/utils/validation-utils.js @@ -142,6 +142,7 @@ input, redactedTypes, () => redactedString, + { dontValidateInput: true }, ); } diff --git a/keyserver/src/utils/validation-utils.test.js b/keyserver/src/utils/validation-utils.test.js --- a/keyserver/src/utils/validation-utils.test.js +++ b/keyserver/src/utils/validation-utils.test.js @@ -87,4 +87,42 @@ const redacted = { passwords: [{ password: redactedString }] }; expect(sanitizeInput(validator, object)).toStrictEqual(redacted); }); + + it('should redact a string inside an object even if it fails validation', () => { + const validator = tShape<{ +password: string, +blah: string }>({ + password: tPassword, + blah: t.String, + }); + const object = { password: 'password' }; + const redacted = { password: redactedString }; + expect(sanitizeInput(validator, object)).toStrictEqual(redacted); + }); + + it('should redact a string inside a nested object even if inner fails validation', () => { + const validator = tShape<{ + +nested: { +blah: string, +password: string }, + }>({ + nested: tShape<{ +blah: string, +password: string }>({ + blah: t.String, + password: tPassword, + }), + }); + const object = { nested: { password: 'password' } }; + const redacted = { nested: { password: redactedString } }; + expect(sanitizeInput(validator, object)).toStrictEqual(redacted); + }); + it('should redact a string inside a nested object even if outer fails validation', () => { + const validator = tShape<{ + +blah: string, + +nested: { +password: string }, + }>({ + blah: t.String, + nested: tShape<{ +password: string }>({ + password: tPassword, + }), + }); + const object = { nested: { password: 'password' } }; + const redacted = { nested: { password: redactedString } }; + expect(sanitizeInput(validator, object)).toStrictEqual(redacted); + }); }); diff --git a/lib/utils/conversion-utils.js b/lib/utils/conversion-utils.js --- a/lib/utils/conversion-utils.js +++ b/lib/utils/conversion-utils.js @@ -74,24 +74,29 @@ return [...result]; } +type ConvertObjectOptions = { + +dontValidateInput?: ?boolean, +}; function convertObject( validator: TType, input: I, typesToConvert: $ReadOnlyArray>, conversionFunction: T => T, + options?: ?ConvertObjectOptions, ): I { if (input === null || input === undefined) { return input; } + const dontValidateInput = options?.dontValidateInput; // While they should be the same runtime object, - // `TValidator` is `TType` and `validator` is `TType`. + // `tValidator` is `TType` and `validator` is `TType`. // Having them have different types allows us to use `assertWithValidator` // to change `input` flow type - const TValidator = typesToConvert[typesToConvert.indexOf(validator)]; - if (TValidator && TValidator.is(input)) { - const TInput = assertWithValidator(input, TValidator); - const converted = conversionFunction(TInput); + const tValidator = typesToConvert[typesToConvert.indexOf(validator)]; + if (tValidator && tValidator.is(input)) { + const tInput = assertWithValidator(input, tValidator); + const converted = conversionFunction(tInput); return assertWithValidator(converted, validator); } @@ -101,6 +106,7 @@ input, typesToConvert, conversionFunction, + options, ); } if (validator.meta.kind === 'interface' && typeof input === 'object') { @@ -113,9 +119,14 @@ input[key], typesToConvert, conversionFunction, + options, ); } - return assertWithValidator(result, recastValidator); + if (dontValidateInput) { + return (result: any); + } else { + return assertWithValidator(result, recastValidator); + } } if (validator.meta.kind === 'union') { for (const innerValidator of validator.meta.types) { @@ -125,6 +136,7 @@ input, typesToConvert, conversionFunction, + options, ); } } @@ -133,7 +145,13 @@ if (validator.meta.kind === 'list' && Array.isArray(input)) { const innerValidator = validator.meta.type; return (input.map(value => - convertObject(innerValidator, value, typesToConvert, conversionFunction), + convertObject( + innerValidator, + value, + typesToConvert, + conversionFunction, + options, + ), ): any); } if (validator.meta.kind === 'dict' && typeof input === 'object') { @@ -148,6 +166,7 @@ value, typesToConvert, conversionFunction, + options, ), )(input); }