From 20b57ed93ef5bf9611630bbac4f6d23f506b1442 Mon Sep 17 00:00:00 2001 From: Nikola Mihaylov Date: Fri, 26 Mar 2021 18:19:35 +0200 Subject: [PATCH 1/5] Implement Obfuscator.obfuscateError --- package-lock.json | 116 ++++++++++++++---------- package.json | 4 +- src/Obfuscator.ts | 32 ++++++- src/tests/index.test.ts | 2 +- src/tests/unit-tests/Obfuscator.test.ts | 33 ++++++- 5 files changed, 131 insertions(+), 56 deletions(-) diff --git a/package-lock.json b/package-lock.json index 29d6503..7e93be2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1118,6 +1118,12 @@ "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==", "dev": true }, + "@types/lodash": { + "version": "4.14.168", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.168.tgz", + "integrity": "sha512-oVfRvqHV/V6D1yifJbVRU3TMp8OT6o6BG+U9MkwuJ3U8/CsDHvalRpsxBqivn71ztOFZBTfJMvETbqHiaNSj7Q==", + "dev": true + }, "@types/node": { "version": "14.0.14", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.14.tgz", @@ -1164,13 +1170,13 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "4.14.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.14.2.tgz", - "integrity": "sha512-uMGfG7GFYK/nYutK/iqYJv6K/Xuog/vrRRZX9aEP4Zv1jsYXuvFUMDFLhUnc8WFv3D2R5QhNQL3VYKmvLS5zsQ==", + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.19.0.tgz", + "integrity": "sha512-CRQNQ0mC2Pa7VLwKFbrGVTArfdVDdefS+gTw0oC98vSI98IX5A8EVH4BzJ2FOB0YlCmm8Im36Elad/Jgtvveaw==", "dev": true, "requires": { - "@typescript-eslint/experimental-utils": "4.14.2", - "@typescript-eslint/scope-manager": "4.14.2", + "@typescript-eslint/experimental-utils": "4.19.0", + "@typescript-eslint/scope-manager": "4.19.0", "debug": "^4.1.1", "functional-red-black-tree": "^1.0.1", "lodash": "^4.17.15", @@ -1180,70 +1186,69 @@ } }, "@typescript-eslint/experimental-utils": { - "version": "4.14.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.14.2.tgz", - "integrity": "sha512-mV9pmET4C2y2WlyHmD+Iun8SAEqkLahHGBkGqDVslHkmoj3VnxnGP4ANlwuxxfq1BsKdl/MPieDbohCEQgKrwA==", + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.19.0.tgz", + "integrity": "sha512-9/23F1nnyzbHKuoTqFN1iXwN3bvOm/PRIXSBR3qFAYotK/0LveEOHr5JT1WZSzcD6BESl8kPOG3OoDRKO84bHA==", "dev": true, "requires": { "@types/json-schema": "^7.0.3", - "@typescript-eslint/scope-manager": "4.14.2", - "@typescript-eslint/types": "4.14.2", - "@typescript-eslint/typescript-estree": "4.14.2", + "@typescript-eslint/scope-manager": "4.19.0", + "@typescript-eslint/types": "4.19.0", + "@typescript-eslint/typescript-estree": "4.19.0", "eslint-scope": "^5.0.0", "eslint-utils": "^2.0.0" } }, "@typescript-eslint/parser": { - "version": "4.14.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.14.2.tgz", - "integrity": "sha512-ipqSP6EuUsMu3E10EZIApOJgWSpcNXeKZaFeNKQyzqxnQl8eQCbV+TSNsl+s2GViX2d18m1rq3CWgnpOxDPgHg==", + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.19.0.tgz", + "integrity": "sha512-/uabZjo2ZZhm66rdAu21HA8nQebl3lAIDcybUoOxoI7VbZBYavLIwtOOmykKCJy+Xq6Vw6ugkiwn8Js7D6wieA==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "4.14.2", - "@typescript-eslint/types": "4.14.2", - "@typescript-eslint/typescript-estree": "4.14.2", + "@typescript-eslint/scope-manager": "4.19.0", + "@typescript-eslint/types": "4.19.0", + "@typescript-eslint/typescript-estree": "4.19.0", "debug": "^4.1.1" } }, "@typescript-eslint/scope-manager": { - "version": "4.14.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.14.2.tgz", - "integrity": "sha512-cuV9wMrzKm6yIuV48aTPfIeqErt5xceTheAgk70N1V4/2Ecj+fhl34iro/vIssJlb7XtzcaD07hWk7Jk0nKghg==", + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.19.0.tgz", + "integrity": "sha512-GGy4Ba/hLXwJXygkXqMzduqOMc+Na6LrJTZXJWVhRrSuZeXmu8TAnniQVKgj8uTRKe4igO2ysYzH+Np879G75g==", "dev": true, "requires": { - "@typescript-eslint/types": "4.14.2", - "@typescript-eslint/visitor-keys": "4.14.2" + "@typescript-eslint/types": "4.19.0", + "@typescript-eslint/visitor-keys": "4.19.0" } }, "@typescript-eslint/types": { - "version": "4.14.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.14.2.tgz", - "integrity": "sha512-LltxawRW6wXy4Gck6ZKlBD05tCHQUj4KLn4iR69IyRiDHX3d3NCAhO+ix5OR2Q+q9bjCrHE/HKt+riZkd1At8Q==", + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.19.0.tgz", + "integrity": "sha512-A4iAlexVvd4IBsSTNxdvdepW0D4uR/fwxDrKUa+iEY9UWvGREu2ZyB8ylTENM1SH8F7bVC9ac9+si3LWNxcBuA==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "4.14.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.14.2.tgz", - "integrity": "sha512-ESiFl8afXxt1dNj8ENEZT12p+jl9PqRur+Y19m0Z/SPikGL6rqq4e7Me60SU9a2M28uz48/8yct97VQYaGl0Vg==", + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.19.0.tgz", + "integrity": "sha512-3xqArJ/A62smaQYRv2ZFyTA+XxGGWmlDYrsfZG68zJeNbeqRScnhf81rUVa6QG4UgzHnXw5VnMT5cg75dQGDkA==", "dev": true, "requires": { - "@typescript-eslint/types": "4.14.2", - "@typescript-eslint/visitor-keys": "4.14.2", + "@typescript-eslint/types": "4.19.0", + "@typescript-eslint/visitor-keys": "4.19.0", "debug": "^4.1.1", "globby": "^11.0.1", "is-glob": "^4.0.1", - "lodash": "^4.17.15", "semver": "^7.3.2", "tsutils": "^3.17.1" } }, "@typescript-eslint/visitor-keys": { - "version": "4.14.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.14.2.tgz", - "integrity": "sha512-KBB+xLBxnBdTENs/rUgeUKO0UkPBRs2vD09oMRRIkj5BEN8PX1ToXV532desXfpQnZsYTyLLviS7JrPhdL154w==", + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.19.0.tgz", + "integrity": "sha512-aGPS6kz//j7XLSlgpzU2SeTqHPsmRYxFztj2vPuMMFJXZudpRSehE3WCV+BaxwZFvfAqMoSd86TEuM0PQ59E/A==", "dev": true, "requires": { - "@typescript-eslint/types": "4.14.2", + "@typescript-eslint/types": "4.19.0", "eslint-visitor-keys": "^2.0.0" }, "dependencies": { @@ -2399,6 +2404,12 @@ "regexpp": "^3.0.0" } }, + "eslint-plugin-no-only-tests": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-no-only-tests/-/eslint-plugin-no-only-tests-2.4.0.tgz", + "integrity": "sha512-azP9PwQYfGtXJjW273nIxQH9Ygr+5/UyeW2wEjYoDtVYPI+WPKwbj0+qcAKYUXFZLRumq4HKkFaoDBAwBoXImQ==", + "dev": true + }, "eslint-plugin-node": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", @@ -2776,9 +2787,9 @@ "dev": true }, "fastq": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.10.1.tgz", - "integrity": "sha512-AWuv6Ery3pM+dY7LYS8YIaCiQvUaos9OB1RyNgaOWnaX+Tik7Onvcsf8x8c+YtDeT0maYLniBip2hox5KtEXXA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz", + "integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==", "dev": true, "requires": { "reusify": "^1.0.4" @@ -2994,9 +3005,9 @@ } }, "globby": { - "version": "11.0.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.2.tgz", - "integrity": "sha512-2ZThXDvvV8fYFRVIxnrMQBipZQDr7MxKAmQK1vujaj9/7eF0efG7BPUKJ7jP7G5SLF37xKDXvO4S/KKLj/Z0og==", + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz", + "integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==", "dev": true, "requires": { "array-union": "^2.1.0", @@ -5506,6 +5517,12 @@ "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", "dev": true }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, "react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -5750,10 +5767,13 @@ "dev": true }, "run-parallel": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz", - "integrity": "sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==", - "dev": true + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } }, "rxjs": { "version": "6.5.5", @@ -6678,9 +6698,9 @@ "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==" }, "tsutils": { - "version": "3.17.1", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz", - "integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==", + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", "dev": true, "requires": { "tslib": "^1.8.1" diff --git a/package.json b/package.json index fab45f0..b718d5b 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ }, "scripts": { "build": "rm -rf dist/ && tsc -d", - "lint": "eslint \"**/*.ts\" --cache", + "lint": "eslint \"**/*.ts\"", "lint:fix": "npm run lint -- --fix", "test": "jest --collectCoverage", "test:watch": "jest --watchAll", @@ -41,11 +41,13 @@ "devDependencies": { "@luckbox/eslint-rules": "^4.0.5", "@types/jest": "^26.0.3", + "@types/lodash": "^4.14.168", "@types/node": "^14.0.14", "@typescript-eslint/eslint-plugin": "^4.12.0", "@typescript-eslint/parser": "^4.12.0", "coveralls": "^3.1.0", "eslint": "^7.2.0", + "eslint-plugin-no-only-tests": "^2.4.0", "eslint-plugin-node": "^11.1.0", "husky": "^4.2.5", "jest": "^26.1.0", diff --git a/src/Obfuscator.ts b/src/Obfuscator.ts index 58057a4..c90eb21 100644 --- a/src/Obfuscator.ts +++ b/src/Obfuscator.ts @@ -6,7 +6,12 @@ enum Tag { } class Obfuscator { - public obfuscateObject(object: Record, obfuscateSettings: Array<[string, Tag]>): Record { + public obfuscateString(value: string, tag: Tag): string { + const upperCasedTag = tag.toUpperCase(); + return `[${upperCasedTag}]${value}[/${upperCasedTag}]`; + } + + public obfuscateObject>(object: T, obfuscateSettings: Array<[string, Tag]>): T { const clonedObj = lodash.cloneDeep(object); const allPaths: Array = this.collectPaths(object); @@ -27,16 +32,33 @@ class Obfuscator { if (!tag) { continue; } - lodash.set(clonedObj, path, this.obfuscateString(rawValue, tag)); + lodash.set(clonedObj, path, this.obfuscateString(rawValue as string, tag)); } } return clonedObj; } - public obfuscateString(value: string, tag: Tag): string { - const upperCasedTag = tag.toUpperCase(); - return `[${upperCasedTag}]${value}[/${upperCasedTag}]`; + public obfuscateError(err: T, obfuscateSettings: Array<[string, Tag]>): T { + const clonedErr = new Error(err.message); + Object.setPrototypeOf(clonedErr, Object.getPrototypeOf(err)); + + for (const prop of Object.getOwnPropertyNames(err)) { + let dataToAssign = err[prop]; + if (lodash.isPlainObject(dataToAssign)) { + const relevantSettings: Array<[string, Tag]> = obfuscateSettings.filter(([path]) => path.startsWith(prop) + '.').map(([path, tag]) => [path.slice(prop.length + 1, path.length), tag]); + + if (relevantSettings.length) { + dataToAssign = this.obfuscateObject(dataToAssign, relevantSettings); + } + } + + Object.assign(clonedErr, { + [prop]: dataToAssign, + }); + } + + return clonedErr as T; } private collectPaths(input: any, currentPath?: string) { diff --git a/src/tests/index.test.ts b/src/tests/index.test.ts index c36367e..e39d64d 100644 --- a/src/tests/index.test.ts +++ b/src/tests/index.test.ts @@ -218,7 +218,7 @@ describe('LoggerFactory', () => { it('should not throw when stringifying big int', () => { expect(() => { - consoleLogger.info({ id: BigInt(Number.MAX_SAFE_INTEGER + 1) }) + consoleLogger.info({ id: BigInt(Number.MAX_SAFE_INTEGER + 1) }); }).not.toThrow(); }); }); diff --git a/src/tests/unit-tests/Obfuscator.test.ts b/src/tests/unit-tests/Obfuscator.test.ts index 70e164e..ddeb4fd 100644 --- a/src/tests/unit-tests/Obfuscator.test.ts +++ b/src/tests/unit-tests/Obfuscator.test.ts @@ -2,7 +2,7 @@ import { Obfuscator, Tag } from '../../Obfuscator'; describe('Obfuscator', () => { const obfuscator = new Obfuscator(); - + describe('obfuscateString', () => { it('should wrap the provided tag around the string that needs to be obfuscated', () => { expect(obfuscator.obfuscateString('string', Tag.PII)).toEqual('[PII]string[/PII]'); @@ -27,4 +27,35 @@ describe('Obfuscator', () => { expect(obfuscator.obfuscateObject(originalObject, [['name', Tag.PII]])).toEqual(originalObject); }); }); + + describe('obfuscateError', () => { + it('should return a copy of the error and not modify the original', () => { + const originalError = new Error(); + const obfuscatedError = obfuscator.obfuscateError(originalError, [['bar', Tag.PII]]); + expect(obfuscatedError).not.toBe(originalError); + }); + + it('should preserve the prototype, name, message and stack of the error', () => { + class CustomError extends Error {} + const originalError = new CustomError(); + const obfuscatedError = obfuscator.obfuscateError(originalError, [['bar', Tag.PII]]); + + expect(obfuscatedError).toBeInstanceOf(CustomError); + expect(obfuscatedError.name).toEqual(originalError.name); + expect(obfuscatedError.message).toEqual(originalError.message); + expect(obfuscatedError.stack).toEqual(originalError.stack); + }); + + it('should obfuscate error specific props', () => { + class CustomError extends Error { + bar = { + foo: 'test', + } + } + const originalError = new CustomError(); + const obfuscatedError = obfuscator.obfuscateError(originalError, [['bar.foo', Tag.PII]]); + + expect(obfuscatedError.bar.foo).toEqual('[PII]test[/PII]'); + }); + }); }); From 84690c7d81b3803c71df971f5f793080aab08cd0 Mon Sep 17 00:00:00 2001 From: Nikola Mihaylov Date: Fri, 26 Mar 2021 18:21:38 +0200 Subject: [PATCH 2/5] Bump version --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7e93be2..f7a555f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@luckbox/logger-factory", - "version": "3.1.0", + "version": "3.2.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index b718d5b..57b4a4e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@luckbox/logger-factory", - "version": "3.1.0", + "version": "3.2.0", "description": "Easy to use logger with several levels of logging as well as different adapters that can be used separately or in combinations", "author": "Luckbox", "license": "ISC", From a27008e30db430e64db55636ab1fcbaa8f157a33 Mon Sep 17 00:00:00 2001 From: Nikola Mihaylov Date: Fri, 26 Mar 2021 18:28:13 +0200 Subject: [PATCH 3/5] Format --- src/Obfuscator.ts | 4 +++- src/tests/unit-tests/Obfuscator.test.ts | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Obfuscator.ts b/src/Obfuscator.ts index c90eb21..a154d8d 100644 --- a/src/Obfuscator.ts +++ b/src/Obfuscator.ts @@ -46,7 +46,9 @@ class Obfuscator { for (const prop of Object.getOwnPropertyNames(err)) { let dataToAssign = err[prop]; if (lodash.isPlainObject(dataToAssign)) { - const relevantSettings: Array<[string, Tag]> = obfuscateSettings.filter(([path]) => path.startsWith(prop) + '.').map(([path, tag]) => [path.slice(prop.length + 1, path.length), tag]); + const relevantSettings: Array<[string, Tag]> = obfuscateSettings + .filter(([path]) => path.startsWith(prop) + '.') + .map(([path, tag]) => [path.slice(prop.length + 1, path.length), tag]); if (relevantSettings.length) { dataToAssign = this.obfuscateObject(dataToAssign, relevantSettings); diff --git a/src/tests/unit-tests/Obfuscator.test.ts b/src/tests/unit-tests/Obfuscator.test.ts index ddeb4fd..a8197d5 100644 --- a/src/tests/unit-tests/Obfuscator.test.ts +++ b/src/tests/unit-tests/Obfuscator.test.ts @@ -53,7 +53,9 @@ describe('Obfuscator', () => { } } const originalError = new CustomError(); - const obfuscatedError = obfuscator.obfuscateError(originalError, [['bar.foo', Tag.PII]]); + const obfuscatedError = obfuscator.obfuscateError(originalError, [ + ['bar.foo', Tag.PII], + ]); expect(obfuscatedError.bar.foo).toEqual('[PII]test[/PII]'); }); From 7477e1a5167f04ad61994dcfbabbf2672403639b Mon Sep 17 00:00:00 2001 From: Nikola Mihaylov Date: Fri, 26 Mar 2021 19:42:44 +0200 Subject: [PATCH 4/5] Merge obfuscateError into obfuscateObject --- src/Obfuscator.ts | 40 ++++++++++++++----------- src/tests/unit-tests/Obfuscator.test.ts | 19 ++++++------ 2 files changed, 32 insertions(+), 27 deletions(-) diff --git a/src/Obfuscator.ts b/src/Obfuscator.ts index a154d8d..c41f737 100644 --- a/src/Obfuscator.ts +++ b/src/Obfuscator.ts @@ -5,15 +5,25 @@ enum Tag { SECRET = 'SECRET' } +type PlainObject = Record; + class Obfuscator { public obfuscateString(value: string, tag: Tag): string { const upperCasedTag = tag.toUpperCase(); return `[${upperCasedTag}]${value}[/${upperCasedTag}]`; } - public obfuscateObject>(object: T, obfuscateSettings: Array<[string, Tag]>): T { - const clonedObj = lodash.cloneDeep(object); - const allPaths: Array = this.collectPaths(object); + public obfuscateObject(object: T, obfuscateSettings: Array<[string, Tag]>): T { + if (this.isPlainObject(object)) { + return this.obfuscatePlainObject(object, obfuscateSettings); + } + + return this.obfuscateError(object as Error, obfuscateSettings) as T; + } + + private obfuscatePlainObject(plainObject: T, obfuscateSettings: Array<[string, Tag]>): T { + const clonedObj = lodash.cloneDeep(plainObject); + const allPaths: Array = this.collectPaths(plainObject); const pathToTagMap = new Map(); const allPathsToObfuscate = []; @@ -39,27 +49,17 @@ class Obfuscator { return clonedObj; } - public obfuscateError(err: T, obfuscateSettings: Array<[string, Tag]>): T { + private obfuscateError(err: T, obfuscateSettings: Array<[string, Tag]>): T { const clonedErr = new Error(err.message); Object.setPrototypeOf(clonedErr, Object.getPrototypeOf(err)); + const dataToAssign = {}; for (const prop of Object.getOwnPropertyNames(err)) { - let dataToAssign = err[prop]; - if (lodash.isPlainObject(dataToAssign)) { - const relevantSettings: Array<[string, Tag]> = obfuscateSettings - .filter(([path]) => path.startsWith(prop) + '.') - .map(([path, tag]) => [path.slice(prop.length + 1, path.length), tag]); - - if (relevantSettings.length) { - dataToAssign = this.obfuscateObject(dataToAssign, relevantSettings); - } - } - - Object.assign(clonedErr, { - [prop]: dataToAssign, - }); + dataToAssign[prop] = lodash.cloneDeep(err[prop]); } + Object.assign(clonedErr, this.obfuscatePlainObject(dataToAssign, obfuscateSettings)); + return clonedErr as T; } @@ -86,6 +86,10 @@ class Obfuscator { const tag = pathToTagMap.get(path); return tag; } + + private isPlainObject(value: any): value is PlainObject { + return lodash.isPlainObject(value); + } } export { diff --git a/src/tests/unit-tests/Obfuscator.test.ts b/src/tests/unit-tests/Obfuscator.test.ts index a8197d5..cbdc939 100644 --- a/src/tests/unit-tests/Obfuscator.test.ts +++ b/src/tests/unit-tests/Obfuscator.test.ts @@ -26,19 +26,17 @@ describe('Obfuscator', () => { const originalObject = { favouriteColor: 'red', nested: { field: 'value' } }; expect(obfuscator.obfuscateObject(originalObject, [['name', Tag.PII]])).toEqual(originalObject); }); - }); - describe('obfuscateError', () => { it('should return a copy of the error and not modify the original', () => { const originalError = new Error(); - const obfuscatedError = obfuscator.obfuscateError(originalError, [['bar', Tag.PII]]); + const obfuscatedError = obfuscator.obfuscateObject(originalError, [['bar', Tag.PII]]); expect(obfuscatedError).not.toBe(originalError); }); it('should preserve the prototype, name, message and stack of the error', () => { class CustomError extends Error {} const originalError = new CustomError(); - const obfuscatedError = obfuscator.obfuscateError(originalError, [['bar', Tag.PII]]); + const obfuscatedError = obfuscator.obfuscateObject(originalError, [['bar', Tag.PII]]); expect(obfuscatedError).toBeInstanceOf(CustomError); expect(obfuscatedError.name).toEqual(originalError.name); @@ -48,16 +46,19 @@ describe('Obfuscator', () => { it('should obfuscate error specific props', () => { class CustomError extends Error { - bar = { - foo: 'test', + bar = 'foo' + foo = { + test: 'test', } } const originalError = new CustomError(); - const obfuscatedError = obfuscator.obfuscateError(originalError, [ - ['bar.foo', Tag.PII], + const obfuscatedError = obfuscator.obfuscateObject(originalError, [ + ['bar', Tag.PII], + ['foo.test', Tag.PII], ]); - expect(obfuscatedError.bar.foo).toEqual('[PII]test[/PII]'); + expect(obfuscatedError.bar).toEqual('[PII]foo[/PII]'); + expect(obfuscatedError.foo.test).toEqual('[PII]test[/PII]'); }); }); }); From 910e379e9e47be9a67622c0a781410672b7d5511 Mon Sep 17 00:00:00 2001 From: Nikola Mihaylov Date: Mon, 29 Mar 2021 10:23:29 +0300 Subject: [PATCH 5/5] Favor unknown over any --- src/Obfuscator.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Obfuscator.ts b/src/Obfuscator.ts index c41f737..297be1b 100644 --- a/src/Obfuscator.ts +++ b/src/Obfuscator.ts @@ -87,7 +87,7 @@ class Obfuscator { return tag; } - private isPlainObject(value: any): value is PlainObject { + private isPlainObject(value: unknown): value is PlainObject { return lodash.isPlainObject(value); } }