{"version":3,"sources":["../src/library/RedactionHandler.ts"],"sourcesContent":["import {\n\tdefaultJsonRedactionText,\n\tdefaultUrlRedactionText,\n} from \"../constants/defaultRedactionRules\";\nimport { isValidUrl } from \"../helpers/urlHelpers\";\nimport { RedactionManager } from \"../types/redactionHandling/RedactionManager\";\nimport {\n\tRedactionManagerConfig,\n\tRedactionRule,\n} from \"../types/redactionHandling/RedactionManagerConfig\";\n\nclass RedactionHandler implements RedactionManager {\n\tpaths: RedactionRule[];\n\tproperties: RedactionRule[];\n\twhitelistPaths: RedactionRule[];\n\tincludes: RedactionRule[];\n\tjsonRedactionText: string;\n\turlRedactionText: string;\n\n\tconstructor(config: RedactionManagerConfig) {\n\t\tthis.paths = config.paths ?? [];\n\t\tthis.properties = config.properties ?? [];\n\t\tthis.whitelistPaths = config.whitelistPaths ?? [];\n\t\tthis.includes = config.includes ?? [];\n\t\tthis.jsonRedactionText =\n\t\t\tconfig.jsonRedactionText ?? defaultJsonRedactionText;\n\t\tthis.urlRedactionText =\n\t\t\tconfig.urlRedactionText ?? defaultUrlRedactionText;\n\t}\n\n\tredact<T>(\n\t\tdata: T,\n\t\tcurrentPath?: string\n\t): T extends number | boolean ? string | T : T {\n\t\tif (\n\t\t\ttypeof data === \"string\" ||\n\t\t\ttypeof data === \"number\" ||\n\t\t\ttypeof data === \"boolean\"\n\t\t) {\n\t\t\t// TODO fix use of any\n\t\t\tif (!currentPath) {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t\"Value passed to redact is a basic type, only objects can be redacted.\"\n\t\t\t\t);\n\t\t\t\treturn data as any;\n\t\t\t} else {\n\t\t\t\tif (this.shouldRedact(currentPath)) {\n\t\t\t\t\treturn this.jsonRedactionText as any;\n\t\t\t\t}\n\t\t\t\tif (typeof data === \"string\" && isValidUrl(data)) {\n\t\t\t\t\treturn this.redactUrl(data) as any;\n\t\t\t\t}\n\t\t\t\treturn data as any;\n\t\t\t}\n\t\t} else if (typeof data === \"object\") {\n\t\t\tif (Array.isArray(data)) {\n\t\t\t\treturn data.map((datum) =>\n\t\t\t\t\tthis.redact(datum, currentPath)\n\t\t\t\t) as any;\n\t\t\t} else if (data) {\n\t\t\t\tObject.keys(data).forEach((key) => {\n\t\t\t\t\t(data as any)[key] = this.redact(\n\t\t\t\t\t\tdata[key as keyof T],\n\t\t\t\t\t\tcurrentPath ? `${currentPath}.${key}` : key\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn data as any;\n\t}\n\n\tredactUrl(inputUrl: string): string {\n\t\tconst url = new URL(inputUrl);\n\t\tconst urlParams = new URLSearchParams(url.search);\n\t\tfor (let [key] of urlParams.entries()) {\n\t\t\tif (this.shouldRedact(this.urlQueryKeyToObjectPath(key))) {\n\t\t\t\turlParams.set(key, this.urlRedactionText);\n\t\t\t}\n\t\t}\n\n\t\turl.search = urlParams.toString();\n\n\t\treturn url.toString();\n\t}\n\n\t// assumes keys of string only\n\tprivate urlQueryKeyToObjectPath(urlQueryKey: string): string {\n\t\tlet urlQueryKeyOpenBracketSplit = urlQueryKey.split(\"[\");\n\t\tif (urlQueryKeyOpenBracketSplit.length === 1) {\n\t\t\treturn urlQueryKey;\n\t\t} else {\n\t\t\tlet objectPath: string = urlQueryKeyOpenBracketSplit.splice(\n\t\t\t\t0,\n\t\t\t\t1\n\t\t\t)[0];\n\n\t\t\turlQueryKeyOpenBracketSplit.forEach((openBracketSplitValue, n) => {\n\t\t\t\tconst closeBracketSplit = openBracketSplitValue.split(\"]\");\n\t\t\t\tif (closeBracketSplit.length !== 2) {\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t`Object in URL params in incorrect format: [${urlQueryKeyOpenBracketSplit[n]}`\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t} else {\n\t\t\t\t\tif (closeBracketSplit[0].match(/^-?\\d+$/)) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tobjectPath += `.${closeBracketSplit[0]}`;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn objectPath;\n\t\t}\n\t}\n\n\tprivate shouldRedact(path: string): boolean {\n\t\tlet ruleIsSatisfied = this.testRedactionRules(\n\t\t\tpath,\n\t\t\tthis.whitelistPaths\n\t\t);\n\t\tif (ruleIsSatisfied) {\n\t\t\treturn false;\n\t\t}\n\n\t\truleIsSatisfied = this.testRedactionRules(path, this.paths);\n\t\tif (ruleIsSatisfied) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst properties = path.split(\".\");\n\t\tconst propertyName = properties[properties.length - 1];\n\n\t\truleIsSatisfied = this.testRedactionRules(\n\t\t\tpropertyName,\n\t\t\tthis.properties\n\t\t);\n\t\tif (ruleIsSatisfied) {\n\t\t\treturn true;\n\t\t}\n\n\t\tfor (let n = 0; n < this.includes.length; n++) {\n\t\t\tif (\n\t\t\t\tpropertyName.includes(this.includes[n].value) ||\n\t\t\t\t(!this.includes[n].caseSensitive &&\n\t\t\t\t\tpropertyName\n\t\t\t\t\t\t.toLowerCase()\n\t\t\t\t\t\t.includes(this.includes[n].value.toLowerCase()))\n\t\t\t) {\n\t\t\t\tn = this.includes.length;\n\t\t\t\truleIsSatisfied = true;\n\t\t\t}\n\t\t}\n\t\treturn ruleIsSatisfied;\n\t}\n\n\tprivate testRedactionRules(path: string, rules: RedactionRule[]): boolean {\n\t\tlet ruleIsSatisfied = false;\n\t\tfor (let n = 0; n < rules.length; n++) {\n\t\t\tif (\n\t\t\t\tpath === rules[n].value ||\n\t\t\t\t(!rules[n].caseSensitive &&\n\t\t\t\t\tpath.toLowerCase() === rules[n].value.toLowerCase())\n\t\t\t) {\n\t\t\t\tn = rules.length;\n\t\t\t\truleIsSatisfied = true;\n\t\t\t}\n\t\t}\n\t\treturn ruleIsSatisfied;\n\t}\n}\n\nexport { RedactionHandler };\n"],"mappings":"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","names":[]}