@hackylabs/deep-redact 2.2.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +36 -56
- package/dist/cjs/index.js +10 -131
- package/dist/cjs/utils/index.js +429 -0
- package/dist/cjs/utils/standardTransformers/bigint.js +10 -0
- package/dist/cjs/utils/standardTransformers/date.js +9 -0
- package/dist/cjs/utils/standardTransformers/error.js +16 -0
- package/dist/cjs/utils/standardTransformers/index.js +19 -0
- package/dist/cjs/utils/standardTransformers/map.js +9 -0
- package/dist/cjs/utils/standardTransformers/regex.js +15 -0
- package/dist/cjs/utils/standardTransformers/set.js +9 -0
- package/dist/cjs/utils/standardTransformers/url.js +9 -0
- package/dist/esm/index.mjs +9 -128
- package/dist/esm/utils/index.mjs +423 -0
- package/dist/esm/utils/standardTransformers/bigint.js +6 -0
- package/dist/esm/utils/standardTransformers/date.js +5 -0
- package/dist/esm/utils/standardTransformers/error.js +12 -0
- package/dist/esm/utils/standardTransformers/index.js +16 -0
- package/dist/esm/utils/standardTransformers/map.js +5 -0
- package/dist/esm/utils/standardTransformers/regex.js +11 -0
- package/dist/esm/utils/standardTransformers/set.js +5 -0
- package/dist/esm/utils/standardTransformers/url.js +5 -0
- package/dist/types/index.d.ts +3 -38
- package/dist/types/types.d.ts +48 -17
- package/dist/types/utils/index.d.ts +130 -0
- package/dist/types/utils/standardTransformers/bigint.d.ts +2 -0
- package/dist/types/utils/standardTransformers/date.d.ts +2 -0
- package/dist/types/utils/standardTransformers/error.d.ts +2 -0
- package/dist/types/utils/standardTransformers/index.d.ts +2 -0
- package/dist/types/utils/standardTransformers/map.d.ts +2 -0
- package/dist/types/utils/standardTransformers/regex.d.ts +2 -0
- package/dist/types/utils/standardTransformers/set.d.ts +2 -0
- package/dist/types/utils/standardTransformers/url.d.ts +2 -0
- package/package.json +66 -13
- package/dist/cjs/utils/redactorUtils.js +0 -263
- package/dist/esm/utils/redactorUtils.mjs +0 -264
- package/dist/types/utils/redactorUtils.d.ts +0 -91
|
@@ -1,263 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const defaultConfig = {
|
|
4
|
-
stringTests: [],
|
|
5
|
-
blacklistedKeys: [],
|
|
6
|
-
partialStringTests: [],
|
|
7
|
-
blacklistedKeysTransformed: [],
|
|
8
|
-
fuzzyKeyMatch: false,
|
|
9
|
-
caseSensitiveKeyMatch: true,
|
|
10
|
-
retainStructure: false,
|
|
11
|
-
remove: false,
|
|
12
|
-
replaceStringByLength: false,
|
|
13
|
-
replacement: '[REDACTED]',
|
|
14
|
-
types: ['string'],
|
|
15
|
-
};
|
|
16
|
-
class RedactorUtils {
|
|
17
|
-
constructor(customConfig) {
|
|
18
|
-
var _a, _b, _c, _d;
|
|
19
|
-
/**
|
|
20
|
-
* The configuration for the redaction.
|
|
21
|
-
* @private
|
|
22
|
-
*/
|
|
23
|
-
this.config = defaultConfig;
|
|
24
|
-
/**
|
|
25
|
-
* Get the configuration for an object key. This will check the key against the transformed blacklisted keys.
|
|
26
|
-
* @private
|
|
27
|
-
* @param {string} key The key of the configuration to get.
|
|
28
|
-
* @returns {Required<BlacklistKeyConfig> | undefined} The configuration for the key.
|
|
29
|
-
*/
|
|
30
|
-
this.getBlacklistedKeyConfig = (key) => {
|
|
31
|
-
var _a;
|
|
32
|
-
if (!key)
|
|
33
|
-
return undefined;
|
|
34
|
-
return (_a = this.config.blacklistedKeysTransformed) === null || _a === void 0 ? void 0 : _a.find((redactableKey) => {
|
|
35
|
-
return RedactorUtils.complexKeyMatch(key, redactableKey);
|
|
36
|
-
});
|
|
37
|
-
};
|
|
38
|
-
/**
|
|
39
|
-
* Get the recursion configuration for a key. This will check the key against the transformed blacklisted keys.
|
|
40
|
-
* If the key is found, the configuration for the key will be returned, otherwise undefined.
|
|
41
|
-
* @private
|
|
42
|
-
* @param {string} key The key of the configuration to get.
|
|
43
|
-
* @returns {Required<Pick<BlacklistKeyConfig, 'remove' | 'replacement' | 'retainStructure'>>} The configuration for the key.
|
|
44
|
-
*/
|
|
45
|
-
this.getRecursionConfig = (key) => {
|
|
46
|
-
const fallback = {
|
|
47
|
-
remove: this.config.remove,
|
|
48
|
-
replacement: this.config.replacement,
|
|
49
|
-
retainStructure: this.config.retainStructure,
|
|
50
|
-
};
|
|
51
|
-
if (!key)
|
|
52
|
-
return fallback;
|
|
53
|
-
const blacklistedKeyConfig = this.getBlacklistedKeyConfig(key);
|
|
54
|
-
if (!blacklistedKeyConfig)
|
|
55
|
-
return fallback;
|
|
56
|
-
return {
|
|
57
|
-
remove: blacklistedKeyConfig.remove,
|
|
58
|
-
replacement: blacklistedKeyConfig.replacement,
|
|
59
|
-
retainStructure: blacklistedKeyConfig.retainStructure,
|
|
60
|
-
};
|
|
61
|
-
};
|
|
62
|
-
/**
|
|
63
|
-
* Determine if a key should be redacted. This will check the key against the blacklisted keys, using the default configuration.
|
|
64
|
-
* @private
|
|
65
|
-
* @param {string} key The key to check.
|
|
66
|
-
* @returns {boolean} Whether the key should be redacted.
|
|
67
|
-
*/
|
|
68
|
-
this.shouldRedactObjectValue = (key) => {
|
|
69
|
-
if (!key)
|
|
70
|
-
return false;
|
|
71
|
-
return this.config.blacklistedKeysTransformed.some((redactableKey) => {
|
|
72
|
-
return RedactorUtils.complexKeyMatch(key, redactableKey);
|
|
73
|
-
});
|
|
74
|
-
};
|
|
75
|
-
/**
|
|
76
|
-
* Redact a string. This will redact the string based on the configuration, redacting the string if it matches a pattern or if the parent key should be redacted.
|
|
77
|
-
* @private
|
|
78
|
-
* @param value
|
|
79
|
-
* @param replacement
|
|
80
|
-
* @param remove
|
|
81
|
-
* @param shouldRedact
|
|
82
|
-
*/
|
|
83
|
-
this.redactString = (value, replacement, remove, shouldRedact) => {
|
|
84
|
-
if (!value || typeof value !== 'string')
|
|
85
|
-
return value;
|
|
86
|
-
const { stringTests } = this.config;
|
|
87
|
-
if (!shouldRedact) {
|
|
88
|
-
const result = stringTests === null || stringTests === void 0 ? void 0 : stringTests.map((test) => {
|
|
89
|
-
if (test instanceof RegExp) {
|
|
90
|
-
if (!test.test(value))
|
|
91
|
-
return value;
|
|
92
|
-
if (remove)
|
|
93
|
-
return undefined;
|
|
94
|
-
if (typeof replacement === 'function')
|
|
95
|
-
return replacement(value);
|
|
96
|
-
if (this.config.replaceStringByLength)
|
|
97
|
-
return replacement.repeat(value.length);
|
|
98
|
-
return replacement;
|
|
99
|
-
}
|
|
100
|
-
if (remove && test.pattern.test(value))
|
|
101
|
-
return undefined;
|
|
102
|
-
return test.replacer(value, test.pattern);
|
|
103
|
-
}).filter(Boolean)[0];
|
|
104
|
-
if (result)
|
|
105
|
-
return result;
|
|
106
|
-
if (remove)
|
|
107
|
-
return undefined;
|
|
108
|
-
return value;
|
|
109
|
-
}
|
|
110
|
-
if (remove)
|
|
111
|
-
return undefined;
|
|
112
|
-
if (typeof replacement === 'function')
|
|
113
|
-
return replacement(value);
|
|
114
|
-
if (this.config.replaceStringByLength)
|
|
115
|
-
return replacement.repeat(value.length);
|
|
116
|
-
return replacement;
|
|
117
|
-
};
|
|
118
|
-
/**
|
|
119
|
-
* Redact a primitive value. This will redact the value if it is a supported type, not an object or array, otherwise it will return the value unchanged.
|
|
120
|
-
* @private
|
|
121
|
-
* @param {unknown} value The value to redact.
|
|
122
|
-
* @param {Transformer | string} replacement The replacement value for redacted data.
|
|
123
|
-
* @param {boolean} remove Whether the redacted data should be removed.
|
|
124
|
-
* @param {boolean} shouldRedact Whether the value should be redacted based on the parent key.
|
|
125
|
-
* @returns {unknown} The redacted value.
|
|
126
|
-
*/
|
|
127
|
-
this.redactPrimitive = (value, replacement, remove, shouldRedact) => {
|
|
128
|
-
if (!this.config.types.includes(typeof value))
|
|
129
|
-
return value;
|
|
130
|
-
if (remove && shouldRedact && typeof value !== 'string')
|
|
131
|
-
return undefined;
|
|
132
|
-
if (typeof value === 'string')
|
|
133
|
-
return this.redactString(value, replacement, remove, shouldRedact);
|
|
134
|
-
if (!shouldRedact)
|
|
135
|
-
return value;
|
|
136
|
-
if (typeof replacement === 'function')
|
|
137
|
-
return replacement(value);
|
|
138
|
-
return replacement;
|
|
139
|
-
};
|
|
140
|
-
/**
|
|
141
|
-
* Redact an array. This will redact each value in the array using the `recurse` method.
|
|
142
|
-
* @private
|
|
143
|
-
* @param {unknown[]} value The array to redact.
|
|
144
|
-
* @returns {unknown[]} The redacted array.
|
|
145
|
-
*/
|
|
146
|
-
this.redactArray = (value) => value.map((val) => this.recurse(val));
|
|
147
|
-
/**
|
|
148
|
-
* Redact an object. This will recursively redact the object based on the configuration, redacting the keys and values as required.
|
|
149
|
-
* @param {Object} value The object to redact.
|
|
150
|
-
* @param {string | null} key The key of the object if it is part of another object.
|
|
151
|
-
* @param {boolean} parentShouldRedact Whether the item should be redacted based on the key within the parent object.
|
|
152
|
-
*/
|
|
153
|
-
this.redactObject = (value, key, parentShouldRedact) => {
|
|
154
|
-
return Object.fromEntries(Object.entries(value).map(([prop, val]) => {
|
|
155
|
-
const shouldRedact = parentShouldRedact || this.shouldRedactObjectValue(prop);
|
|
156
|
-
if (shouldRedact) {
|
|
157
|
-
const { remove } = this.getRecursionConfig(prop);
|
|
158
|
-
if (remove)
|
|
159
|
-
return [];
|
|
160
|
-
}
|
|
161
|
-
return [prop, this.recurse(val, key !== null && key !== void 0 ? key : prop, shouldRedact)];
|
|
162
|
-
}).filter(([prop]) => prop !== undefined));
|
|
163
|
-
};
|
|
164
|
-
this.partialStringRedact = (value) => {
|
|
165
|
-
const { partialStringTests } = this.config;
|
|
166
|
-
if (partialStringTests.length === 0)
|
|
167
|
-
return value;
|
|
168
|
-
let result;
|
|
169
|
-
if (typeof value === 'string') {
|
|
170
|
-
result = value;
|
|
171
|
-
}
|
|
172
|
-
else {
|
|
173
|
-
try {
|
|
174
|
-
result = JSON.stringify(value);
|
|
175
|
-
}
|
|
176
|
-
catch (error) {
|
|
177
|
-
// It should never reach this point, but if it does, it will throw an error that must not contain sensitive data.
|
|
178
|
-
throw new Error('Failed to stringify value for partialStringRedact. Did you replace the rewriteUnsupported method with something that returns non-serialisable data?');
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
partialStringTests.forEach((test) => {
|
|
182
|
-
result = test.replacer(result, test.pattern);
|
|
183
|
-
});
|
|
184
|
-
return typeof value === 'string' ? result : JSON.parse(result);
|
|
185
|
-
};
|
|
186
|
-
/**
|
|
187
|
-
* Redact a value. If the value is an object or array, the redaction will be performed recursively, otherwise the value will be redacted if it is a supported type using the `replace` method.
|
|
188
|
-
* @private
|
|
189
|
-
* @param {unknown} value The value to redact.
|
|
190
|
-
* @param {string | null} key The key of the value if it is part of an object.
|
|
191
|
-
* @param {boolean} parentShouldRedact Whether the parent object should be redacted.
|
|
192
|
-
* @returns {unknown} The redacted value.
|
|
193
|
-
*/
|
|
194
|
-
this.recurse = (value, key, parentShouldRedact) => {
|
|
195
|
-
if (value === null)
|
|
196
|
-
return value;
|
|
197
|
-
const { remove, replacement, retainStructure } = this.getRecursionConfig(key);
|
|
198
|
-
if (!(value instanceof Object))
|
|
199
|
-
return this.redactPrimitive(value, replacement, remove, Boolean(key && parentShouldRedact));
|
|
200
|
-
if (parentShouldRedact) {
|
|
201
|
-
if (!retainStructure) {
|
|
202
|
-
return typeof replacement === 'function'
|
|
203
|
-
? replacement(value)
|
|
204
|
-
: replacement;
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
if (Array.isArray(value))
|
|
208
|
-
return this.redactArray(value);
|
|
209
|
-
return this.redactObject(value, key, parentShouldRedact);
|
|
210
|
-
};
|
|
211
|
-
this.config = Object.assign(Object.assign(Object.assign({}, defaultConfig), customConfig), { partialStringTests: (_a = customConfig.partialStringTests) !== null && _a !== void 0 ? _a : [], blacklistedKeys: (_b = customConfig.blacklistedKeys) !== null && _b !== void 0 ? _b : [], blacklistedKeysTransformed: (_d = (_c = customConfig.blacklistedKeys) === null || _c === void 0 ? void 0 : _c.map((key) => {
|
|
212
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
213
|
-
const isObject = !(typeof key === 'string' || key instanceof RegExp);
|
|
214
|
-
const setKey = isObject ? key.key : key;
|
|
215
|
-
const fallback = {
|
|
216
|
-
fuzzyKeyMatch: (_a = customConfig.fuzzyKeyMatch) !== null && _a !== void 0 ? _a : defaultConfig.fuzzyKeyMatch,
|
|
217
|
-
caseSensitiveKeyMatch: (_b = customConfig.caseSensitiveKeyMatch) !== null && _b !== void 0 ? _b : defaultConfig.caseSensitiveKeyMatch,
|
|
218
|
-
retainStructure: (_c = customConfig.retainStructure) !== null && _c !== void 0 ? _c : defaultConfig.retainStructure,
|
|
219
|
-
replacement: (_d = customConfig.replacement) !== null && _d !== void 0 ? _d : defaultConfig.replacement,
|
|
220
|
-
remove: (_e = customConfig.remove) !== null && _e !== void 0 ? _e : defaultConfig.remove,
|
|
221
|
-
key: setKey,
|
|
222
|
-
};
|
|
223
|
-
if (isObject) {
|
|
224
|
-
return {
|
|
225
|
-
fuzzyKeyMatch: (_f = key.fuzzyKeyMatch) !== null && _f !== void 0 ? _f : fallback.fuzzyKeyMatch,
|
|
226
|
-
caseSensitiveKeyMatch: (_g = key.caseSensitiveKeyMatch) !== null && _g !== void 0 ? _g : fallback.caseSensitiveKeyMatch,
|
|
227
|
-
retainStructure: (_h = key.retainStructure) !== null && _h !== void 0 ? _h : fallback.retainStructure,
|
|
228
|
-
replacement: (_j = key.replacement) !== null && _j !== void 0 ? _j : fallback.replacement,
|
|
229
|
-
remove: (_k = key.remove) !== null && _k !== void 0 ? _k : fallback.remove,
|
|
230
|
-
key: setKey,
|
|
231
|
-
};
|
|
232
|
-
}
|
|
233
|
-
return fallback;
|
|
234
|
-
})) !== null && _d !== void 0 ? _d : [] });
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
/**
|
|
238
|
-
* Normalise a string for comparison. This will convert the string to lowercase and remove any non-word characters.
|
|
239
|
-
* @private
|
|
240
|
-
* @param str The string to normalise.
|
|
241
|
-
* @returns {string} The normalised string.
|
|
242
|
-
*/
|
|
243
|
-
RedactorUtils.normaliseString = (str) => str.toLowerCase().replaceAll(/\W/g, '');
|
|
244
|
-
/**
|
|
245
|
-
* Determine if a key matches a given blacklistedKeyConfig. This will check the key against the blacklisted keys,
|
|
246
|
-
* using the configuration option for the given key falling back to the default configuration.
|
|
247
|
-
* @private
|
|
248
|
-
* @param {string} key The key to check.
|
|
249
|
-
* @param {BlacklistKeyConfig} blacklistKeyConfig The configuration for the key.
|
|
250
|
-
* @returns {boolean} Whether the key should be redacted.
|
|
251
|
-
*/
|
|
252
|
-
RedactorUtils.complexKeyMatch = (key, blacklistKeyConfig) => {
|
|
253
|
-
if (blacklistKeyConfig.key instanceof RegExp)
|
|
254
|
-
return blacklistKeyConfig.key.test(key);
|
|
255
|
-
if (blacklistKeyConfig.fuzzyKeyMatch && blacklistKeyConfig.caseSensitiveKeyMatch)
|
|
256
|
-
return key.includes(blacklistKeyConfig.key);
|
|
257
|
-
if (blacklistKeyConfig.fuzzyKeyMatch && !blacklistKeyConfig.caseSensitiveKeyMatch)
|
|
258
|
-
return RedactorUtils.normaliseString(key).includes(RedactorUtils.normaliseString(blacklistKeyConfig.key));
|
|
259
|
-
if (!blacklistKeyConfig.fuzzyKeyMatch && blacklistKeyConfig.caseSensitiveKeyMatch)
|
|
260
|
-
return key === blacklistKeyConfig.key;
|
|
261
|
-
return RedactorUtils.normaliseString(blacklistKeyConfig.key) === RedactorUtils.normaliseString(key);
|
|
262
|
-
};
|
|
263
|
-
exports.default = RedactorUtils;
|
|
@@ -1,264 +0,0 @@
|
|
|
1
|
-
const defaultConfig = {
|
|
2
|
-
stringTests: [],
|
|
3
|
-
blacklistedKeys: [],
|
|
4
|
-
partialStringTests: [],
|
|
5
|
-
blacklistedKeysTransformed: [],
|
|
6
|
-
fuzzyKeyMatch: false,
|
|
7
|
-
caseSensitiveKeyMatch: true,
|
|
8
|
-
retainStructure: false,
|
|
9
|
-
remove: false,
|
|
10
|
-
replaceStringByLength: false,
|
|
11
|
-
replacement: '[REDACTED]',
|
|
12
|
-
types: ['string'],
|
|
13
|
-
};
|
|
14
|
-
class RedactorUtils {
|
|
15
|
-
/**
|
|
16
|
-
* The configuration for the redaction.
|
|
17
|
-
* @private
|
|
18
|
-
*/
|
|
19
|
-
config = defaultConfig;
|
|
20
|
-
constructor(customConfig) {
|
|
21
|
-
this.config = {
|
|
22
|
-
...defaultConfig,
|
|
23
|
-
...customConfig,
|
|
24
|
-
partialStringTests: customConfig.partialStringTests ?? [],
|
|
25
|
-
blacklistedKeys: customConfig.blacklistedKeys ?? [],
|
|
26
|
-
blacklistedKeysTransformed: customConfig.blacklistedKeys?.map((key) => {
|
|
27
|
-
const isObject = !(typeof key === 'string' || key instanceof RegExp);
|
|
28
|
-
const setKey = isObject ? key.key : key;
|
|
29
|
-
const fallback = {
|
|
30
|
-
fuzzyKeyMatch: customConfig.fuzzyKeyMatch ?? defaultConfig.fuzzyKeyMatch,
|
|
31
|
-
caseSensitiveKeyMatch: customConfig.caseSensitiveKeyMatch ?? defaultConfig.caseSensitiveKeyMatch,
|
|
32
|
-
retainStructure: customConfig.retainStructure ?? defaultConfig.retainStructure,
|
|
33
|
-
replacement: customConfig.replacement ?? defaultConfig.replacement,
|
|
34
|
-
remove: customConfig.remove ?? defaultConfig.remove,
|
|
35
|
-
key: setKey,
|
|
36
|
-
};
|
|
37
|
-
if (isObject) {
|
|
38
|
-
return {
|
|
39
|
-
fuzzyKeyMatch: key.fuzzyKeyMatch ?? fallback.fuzzyKeyMatch,
|
|
40
|
-
caseSensitiveKeyMatch: key.caseSensitiveKeyMatch ?? fallback.caseSensitiveKeyMatch,
|
|
41
|
-
retainStructure: key.retainStructure ?? fallback.retainStructure,
|
|
42
|
-
replacement: key.replacement ?? fallback.replacement,
|
|
43
|
-
remove: key.remove ?? fallback.remove,
|
|
44
|
-
key: setKey,
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
return fallback;
|
|
48
|
-
}) ?? [],
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Normalise a string for comparison. This will convert the string to lowercase and remove any non-word characters.
|
|
53
|
-
* @private
|
|
54
|
-
* @param str The string to normalise.
|
|
55
|
-
* @returns {string} The normalised string.
|
|
56
|
-
*/
|
|
57
|
-
static normaliseString = (str) => str.toLowerCase().replaceAll(/\W/g, '');
|
|
58
|
-
/**
|
|
59
|
-
* Determine if a key matches a given blacklistedKeyConfig. This will check the key against the blacklisted keys,
|
|
60
|
-
* using the configuration option for the given key falling back to the default configuration.
|
|
61
|
-
* @private
|
|
62
|
-
* @param {string} key The key to check.
|
|
63
|
-
* @param {BlacklistKeyConfig} blacklistKeyConfig The configuration for the key.
|
|
64
|
-
* @returns {boolean} Whether the key should be redacted.
|
|
65
|
-
*/
|
|
66
|
-
static complexKeyMatch = (key, blacklistKeyConfig) => {
|
|
67
|
-
if (blacklistKeyConfig.key instanceof RegExp)
|
|
68
|
-
return blacklistKeyConfig.key.test(key);
|
|
69
|
-
if (blacklistKeyConfig.fuzzyKeyMatch && blacklistKeyConfig.caseSensitiveKeyMatch)
|
|
70
|
-
return key.includes(blacklistKeyConfig.key);
|
|
71
|
-
if (blacklistKeyConfig.fuzzyKeyMatch && !blacklistKeyConfig.caseSensitiveKeyMatch)
|
|
72
|
-
return RedactorUtils.normaliseString(key).includes(RedactorUtils.normaliseString(blacklistKeyConfig.key));
|
|
73
|
-
if (!blacklistKeyConfig.fuzzyKeyMatch && blacklistKeyConfig.caseSensitiveKeyMatch)
|
|
74
|
-
return key === blacklistKeyConfig.key;
|
|
75
|
-
return RedactorUtils.normaliseString(blacklistKeyConfig.key) === RedactorUtils.normaliseString(key);
|
|
76
|
-
};
|
|
77
|
-
/**
|
|
78
|
-
* Get the configuration for an object key. This will check the key against the transformed blacklisted keys.
|
|
79
|
-
* @private
|
|
80
|
-
* @param {string} key The key of the configuration to get.
|
|
81
|
-
* @returns {Required<BlacklistKeyConfig> | undefined} The configuration for the key.
|
|
82
|
-
*/
|
|
83
|
-
getBlacklistedKeyConfig = (key) => {
|
|
84
|
-
if (!key)
|
|
85
|
-
return undefined;
|
|
86
|
-
return this.config.blacklistedKeysTransformed?.find((redactableKey) => {
|
|
87
|
-
return RedactorUtils.complexKeyMatch(key, redactableKey);
|
|
88
|
-
});
|
|
89
|
-
};
|
|
90
|
-
/**
|
|
91
|
-
* Get the recursion configuration for a key. This will check the key against the transformed blacklisted keys.
|
|
92
|
-
* If the key is found, the configuration for the key will be returned, otherwise undefined.
|
|
93
|
-
* @private
|
|
94
|
-
* @param {string} key The key of the configuration to get.
|
|
95
|
-
* @returns {Required<Pick<BlacklistKeyConfig, 'remove' | 'replacement' | 'retainStructure'>>} The configuration for the key.
|
|
96
|
-
*/
|
|
97
|
-
getRecursionConfig = (key) => {
|
|
98
|
-
const fallback = {
|
|
99
|
-
remove: this.config.remove,
|
|
100
|
-
replacement: this.config.replacement,
|
|
101
|
-
retainStructure: this.config.retainStructure,
|
|
102
|
-
};
|
|
103
|
-
if (!key)
|
|
104
|
-
return fallback;
|
|
105
|
-
const blacklistedKeyConfig = this.getBlacklistedKeyConfig(key);
|
|
106
|
-
if (!blacklistedKeyConfig)
|
|
107
|
-
return fallback;
|
|
108
|
-
return {
|
|
109
|
-
remove: blacklistedKeyConfig.remove,
|
|
110
|
-
replacement: blacklistedKeyConfig.replacement,
|
|
111
|
-
retainStructure: blacklistedKeyConfig.retainStructure,
|
|
112
|
-
};
|
|
113
|
-
};
|
|
114
|
-
/**
|
|
115
|
-
* Determine if a key should be redacted. This will check the key against the blacklisted keys, using the default configuration.
|
|
116
|
-
* @private
|
|
117
|
-
* @param {string} key The key to check.
|
|
118
|
-
* @returns {boolean} Whether the key should be redacted.
|
|
119
|
-
*/
|
|
120
|
-
shouldRedactObjectValue = (key) => {
|
|
121
|
-
if (!key)
|
|
122
|
-
return false;
|
|
123
|
-
return this.config.blacklistedKeysTransformed.some((redactableKey) => {
|
|
124
|
-
return RedactorUtils.complexKeyMatch(key, redactableKey);
|
|
125
|
-
});
|
|
126
|
-
};
|
|
127
|
-
/**
|
|
128
|
-
* Redact a string. This will redact the string based on the configuration, redacting the string if it matches a pattern or if the parent key should be redacted.
|
|
129
|
-
* @private
|
|
130
|
-
* @param value
|
|
131
|
-
* @param replacement
|
|
132
|
-
* @param remove
|
|
133
|
-
* @param shouldRedact
|
|
134
|
-
*/
|
|
135
|
-
redactString = (value, replacement, remove, shouldRedact) => {
|
|
136
|
-
if (!value || typeof value !== 'string')
|
|
137
|
-
return value;
|
|
138
|
-
const { stringTests } = this.config;
|
|
139
|
-
if (!shouldRedact) {
|
|
140
|
-
const result = stringTests?.map((test) => {
|
|
141
|
-
if (test instanceof RegExp) {
|
|
142
|
-
if (!test.test(value))
|
|
143
|
-
return value;
|
|
144
|
-
if (remove)
|
|
145
|
-
return undefined;
|
|
146
|
-
if (typeof replacement === 'function')
|
|
147
|
-
return replacement(value);
|
|
148
|
-
if (this.config.replaceStringByLength)
|
|
149
|
-
return replacement.repeat(value.length);
|
|
150
|
-
return replacement;
|
|
151
|
-
}
|
|
152
|
-
if (remove && test.pattern.test(value))
|
|
153
|
-
return undefined;
|
|
154
|
-
return test.replacer(value, test.pattern);
|
|
155
|
-
}).filter(Boolean)[0];
|
|
156
|
-
if (result)
|
|
157
|
-
return result;
|
|
158
|
-
if (remove)
|
|
159
|
-
return undefined;
|
|
160
|
-
return value;
|
|
161
|
-
}
|
|
162
|
-
if (remove)
|
|
163
|
-
return undefined;
|
|
164
|
-
if (typeof replacement === 'function')
|
|
165
|
-
return replacement(value);
|
|
166
|
-
if (this.config.replaceStringByLength)
|
|
167
|
-
return replacement.repeat(value.length);
|
|
168
|
-
return replacement;
|
|
169
|
-
};
|
|
170
|
-
/**
|
|
171
|
-
* Redact a primitive value. This will redact the value if it is a supported type, not an object or array, otherwise it will return the value unchanged.
|
|
172
|
-
* @private
|
|
173
|
-
* @param {unknown} value The value to redact.
|
|
174
|
-
* @param {Transformer | string} replacement The replacement value for redacted data.
|
|
175
|
-
* @param {boolean} remove Whether the redacted data should be removed.
|
|
176
|
-
* @param {boolean} shouldRedact Whether the value should be redacted based on the parent key.
|
|
177
|
-
* @returns {unknown} The redacted value.
|
|
178
|
-
*/
|
|
179
|
-
redactPrimitive = (value, replacement, remove, shouldRedact) => {
|
|
180
|
-
if (!this.config.types.includes(typeof value))
|
|
181
|
-
return value;
|
|
182
|
-
if (remove && shouldRedact && typeof value !== 'string')
|
|
183
|
-
return undefined;
|
|
184
|
-
if (typeof value === 'string')
|
|
185
|
-
return this.redactString(value, replacement, remove, shouldRedact);
|
|
186
|
-
if (!shouldRedact)
|
|
187
|
-
return value;
|
|
188
|
-
if (typeof replacement === 'function')
|
|
189
|
-
return replacement(value);
|
|
190
|
-
return replacement;
|
|
191
|
-
};
|
|
192
|
-
/**
|
|
193
|
-
* Redact an array. This will redact each value in the array using the `recurse` method.
|
|
194
|
-
* @private
|
|
195
|
-
* @param {unknown[]} value The array to redact.
|
|
196
|
-
* @returns {unknown[]} The redacted array.
|
|
197
|
-
*/
|
|
198
|
-
redactArray = (value) => value.map((val) => this.recurse(val));
|
|
199
|
-
/**
|
|
200
|
-
* Redact an object. This will recursively redact the object based on the configuration, redacting the keys and values as required.
|
|
201
|
-
* @param {Object} value The object to redact.
|
|
202
|
-
* @param {string | null} key The key of the object if it is part of another object.
|
|
203
|
-
* @param {boolean} parentShouldRedact Whether the item should be redacted based on the key within the parent object.
|
|
204
|
-
*/
|
|
205
|
-
redactObject = (value, key, parentShouldRedact) => {
|
|
206
|
-
return Object.fromEntries(Object.entries(value).map(([prop, val]) => {
|
|
207
|
-
const shouldRedact = parentShouldRedact || this.shouldRedactObjectValue(prop);
|
|
208
|
-
if (shouldRedact) {
|
|
209
|
-
const { remove } = this.getRecursionConfig(prop);
|
|
210
|
-
if (remove)
|
|
211
|
-
return [];
|
|
212
|
-
}
|
|
213
|
-
return [prop, this.recurse(val, key ?? prop, shouldRedact)];
|
|
214
|
-
}).filter(([prop]) => prop !== undefined));
|
|
215
|
-
};
|
|
216
|
-
partialStringRedact = (value) => {
|
|
217
|
-
const { partialStringTests } = this.config;
|
|
218
|
-
if (partialStringTests.length === 0)
|
|
219
|
-
return value;
|
|
220
|
-
let result;
|
|
221
|
-
if (typeof value === 'string') {
|
|
222
|
-
result = value;
|
|
223
|
-
}
|
|
224
|
-
else {
|
|
225
|
-
try {
|
|
226
|
-
result = JSON.stringify(value);
|
|
227
|
-
}
|
|
228
|
-
catch (error) {
|
|
229
|
-
// It should never reach this point, but if it does, it will throw an error that must not contain sensitive data.
|
|
230
|
-
throw new Error('Failed to stringify value for partialStringRedact. Did you replace the rewriteUnsupported method with something that returns non-serialisable data?');
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
partialStringTests.forEach((test) => {
|
|
234
|
-
result = test.replacer(result, test.pattern);
|
|
235
|
-
});
|
|
236
|
-
return typeof value === 'string' ? result : JSON.parse(result);
|
|
237
|
-
};
|
|
238
|
-
/**
|
|
239
|
-
* Redact a value. If the value is an object or array, the redaction will be performed recursively, otherwise the value will be redacted if it is a supported type using the `replace` method.
|
|
240
|
-
* @private
|
|
241
|
-
* @param {unknown} value The value to redact.
|
|
242
|
-
* @param {string | null} key The key of the value if it is part of an object.
|
|
243
|
-
* @param {boolean} parentShouldRedact Whether the parent object should be redacted.
|
|
244
|
-
* @returns {unknown} The redacted value.
|
|
245
|
-
*/
|
|
246
|
-
recurse = (value, key, parentShouldRedact) => {
|
|
247
|
-
if (value === null)
|
|
248
|
-
return value;
|
|
249
|
-
const { remove, replacement, retainStructure } = this.getRecursionConfig(key);
|
|
250
|
-
if (!(value instanceof Object))
|
|
251
|
-
return this.redactPrimitive(value, replacement, remove, Boolean(key && parentShouldRedact));
|
|
252
|
-
if (parentShouldRedact) {
|
|
253
|
-
if (!retainStructure) {
|
|
254
|
-
return typeof replacement === 'function'
|
|
255
|
-
? replacement(value)
|
|
256
|
-
: replacement;
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
if (Array.isArray(value))
|
|
260
|
-
return this.redactArray(value);
|
|
261
|
-
return this.redactObject(value, key, parentShouldRedact);
|
|
262
|
-
};
|
|
263
|
-
}
|
|
264
|
-
export default RedactorUtils;
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import { RedactorUtilsConfig } from '../types';
|
|
2
|
-
declare class RedactorUtils {
|
|
3
|
-
/**
|
|
4
|
-
* The configuration for the redaction.
|
|
5
|
-
* @private
|
|
6
|
-
*/
|
|
7
|
-
private readonly config;
|
|
8
|
-
constructor(customConfig: Omit<RedactorUtilsConfig, 'blacklistedKeysTransformed'>);
|
|
9
|
-
/**
|
|
10
|
-
* Normalise a string for comparison. This will convert the string to lowercase and remove any non-word characters.
|
|
11
|
-
* @private
|
|
12
|
-
* @param str The string to normalise.
|
|
13
|
-
* @returns {string} The normalised string.
|
|
14
|
-
*/
|
|
15
|
-
private static normaliseString;
|
|
16
|
-
/**
|
|
17
|
-
* Determine if a key matches a given blacklistedKeyConfig. This will check the key against the blacklisted keys,
|
|
18
|
-
* using the configuration option for the given key falling back to the default configuration.
|
|
19
|
-
* @private
|
|
20
|
-
* @param {string} key The key to check.
|
|
21
|
-
* @param {BlacklistKeyConfig} blacklistKeyConfig The configuration for the key.
|
|
22
|
-
* @returns {boolean} Whether the key should be redacted.
|
|
23
|
-
*/
|
|
24
|
-
private static complexKeyMatch;
|
|
25
|
-
/**
|
|
26
|
-
* Get the configuration for an object key. This will check the key against the transformed blacklisted keys.
|
|
27
|
-
* @private
|
|
28
|
-
* @param {string} key The key of the configuration to get.
|
|
29
|
-
* @returns {Required<BlacklistKeyConfig> | undefined} The configuration for the key.
|
|
30
|
-
*/
|
|
31
|
-
private getBlacklistedKeyConfig;
|
|
32
|
-
/**
|
|
33
|
-
* Get the recursion configuration for a key. This will check the key against the transformed blacklisted keys.
|
|
34
|
-
* If the key is found, the configuration for the key will be returned, otherwise undefined.
|
|
35
|
-
* @private
|
|
36
|
-
* @param {string} key The key of the configuration to get.
|
|
37
|
-
* @returns {Required<Pick<BlacklistKeyConfig, 'remove' | 'replacement' | 'retainStructure'>>} The configuration for the key.
|
|
38
|
-
*/
|
|
39
|
-
private getRecursionConfig;
|
|
40
|
-
/**
|
|
41
|
-
* Determine if a key should be redacted. This will check the key against the blacklisted keys, using the default configuration.
|
|
42
|
-
* @private
|
|
43
|
-
* @param {string} key The key to check.
|
|
44
|
-
* @returns {boolean} Whether the key should be redacted.
|
|
45
|
-
*/
|
|
46
|
-
private shouldRedactObjectValue;
|
|
47
|
-
/**
|
|
48
|
-
* Redact a string. This will redact the string based on the configuration, redacting the string if it matches a pattern or if the parent key should be redacted.
|
|
49
|
-
* @private
|
|
50
|
-
* @param value
|
|
51
|
-
* @param replacement
|
|
52
|
-
* @param remove
|
|
53
|
-
* @param shouldRedact
|
|
54
|
-
*/
|
|
55
|
-
private redactString;
|
|
56
|
-
/**
|
|
57
|
-
* Redact a primitive value. This will redact the value if it is a supported type, not an object or array, otherwise it will return the value unchanged.
|
|
58
|
-
* @private
|
|
59
|
-
* @param {unknown} value The value to redact.
|
|
60
|
-
* @param {Transformer | string} replacement The replacement value for redacted data.
|
|
61
|
-
* @param {boolean} remove Whether the redacted data should be removed.
|
|
62
|
-
* @param {boolean} shouldRedact Whether the value should be redacted based on the parent key.
|
|
63
|
-
* @returns {unknown} The redacted value.
|
|
64
|
-
*/
|
|
65
|
-
private redactPrimitive;
|
|
66
|
-
/**
|
|
67
|
-
* Redact an array. This will redact each value in the array using the `recurse` method.
|
|
68
|
-
* @private
|
|
69
|
-
* @param {unknown[]} value The array to redact.
|
|
70
|
-
* @returns {unknown[]} The redacted array.
|
|
71
|
-
*/
|
|
72
|
-
private redactArray;
|
|
73
|
-
/**
|
|
74
|
-
* Redact an object. This will recursively redact the object based on the configuration, redacting the keys and values as required.
|
|
75
|
-
* @param {Object} value The object to redact.
|
|
76
|
-
* @param {string | null} key The key of the object if it is part of another object.
|
|
77
|
-
* @param {boolean} parentShouldRedact Whether the item should be redacted based on the key within the parent object.
|
|
78
|
-
*/
|
|
79
|
-
private redactObject;
|
|
80
|
-
partialStringRedact: (value: unknown) => unknown;
|
|
81
|
-
/**
|
|
82
|
-
* Redact a value. If the value is an object or array, the redaction will be performed recursively, otherwise the value will be redacted if it is a supported type using the `replace` method.
|
|
83
|
-
* @private
|
|
84
|
-
* @param {unknown} value The value to redact.
|
|
85
|
-
* @param {string | null} key The key of the value if it is part of an object.
|
|
86
|
-
* @param {boolean} parentShouldRedact Whether the parent object should be redacted.
|
|
87
|
-
* @returns {unknown} The redacted value.
|
|
88
|
-
*/
|
|
89
|
-
recurse: (value: unknown, key?: string | null, parentShouldRedact?: boolean) => unknown;
|
|
90
|
-
}
|
|
91
|
-
export default RedactorUtils;
|