Skip to content

Commit a1ad2f3

Browse files
committed
Refactoring to remove code duplication
1 parent 7a055a9 commit a1ad2f3

File tree

5 files changed

+115
-189
lines changed

5 files changed

+115
-189
lines changed

lib/mcapi/crypto/field-level-crypto.js

Lines changed: 2 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -228,37 +228,12 @@ function isValidConfig(config) {
228228
"encryptedKeyHeaderName",
229229
"oaepHashingAlgorithmHeaderName",
230230
];
231-
const contains = (props) => {
232-
return props.every((elem) => {
233-
return config[elem] !== null && typeof config[elem] !== "undefined";
234-
});
235-
};
236-
if (typeof config !== "object" || config === null) {
237-
throw Error("Config not valid: config should be an object.");
238-
}
239-
if (
240-
config["paths"] === null ||
241-
typeof config["paths"] === "undefined" ||
242-
!(config["paths"] instanceof Array)
243-
) {
244-
throw Error("Config not valid: paths should be an array of path element.");
245-
}
246-
if (
247-
!contains(propertiesBasic) ||
248-
(!contains(propertiesField) && !contains(propertiesHeader))
249-
) {
250-
throw Error(
251-
"Config not valid: please check that all the properties are defined."
252-
);
253-
}
254-
if (config["paths"].length === 0) {
255-
throw Error("Config not valid: paths should be not empty.");
256-
}
231+
const contains = utils.checkConfigFieldsArePopulated(config, propertiesBasic, propertiesField, propertiesHeader);
257232
if (config["dataEncoding"] !== c.HEX && config["dataEncoding"] !== c.BASE64) {
258233
throw Error("Config not valid: dataEncoding should be 'hex' or 'base64'");
259234
}
260235
validateFingerprint(config, contains);
261-
validateRootMapping(config);
236+
utils.validateRootMapping(config);
262237
}
263238

264239
function validateFingerprint(config, contains) {
@@ -280,23 +255,4 @@ function validateFingerprint(config, contains) {
280255
}
281256
}
282257

283-
function validateRootMapping(config) {
284-
function multipleRoots(elem) {
285-
return (
286-
elem.length !== 1 &&
287-
elem.some((item) => {
288-
return item.obj === "$" || item.element === "$";
289-
})
290-
);
291-
}
292-
293-
config.paths.forEach((path) => {
294-
if (multipleRoots(path.toEncrypt) || multipleRoots(path.toDecrypt)) {
295-
throw Error(
296-
"Config not valid: found multiple configurations encrypt/decrypt with root mapping"
297-
);
298-
}
299-
});
300-
}
301-
302258
module.exports = FieldLevelCrypto;

lib/mcapi/crypto/jwe-crypto.js

Lines changed: 2 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -222,31 +222,9 @@ function isValidConfig(config) {
222222
throw Error("JWE Encryption is only supported on Node 13+");
223223
}
224224
const propertiesBasic = ["encryptionCertificate", "encryptedValueFieldName"];
225-
const contains = (props) => {
226-
return props.every((elem) => {
227-
return config[elem] !== null && typeof config[elem] !== "undefined";
228-
});
229-
};
230-
if (typeof config !== "object" || config === null) {
231-
throw Error("Config not valid: config should be an object.");
232-
}
233-
if (
234-
config["paths"] === null ||
235-
typeof config["paths"] === "undefined" ||
236-
!(config["paths"] instanceof Array)
237-
) {
238-
throw Error("Config not valid: paths should be an array of path element.");
239-
}
240-
if (!contains(propertiesBasic)) {
241-
throw Error(
242-
"Config not valid: please check that all the properties are defined."
243-
);
244-
}
245-
if (config["paths"].length === 0) {
246-
throw Error("Config not valid: paths should be not empty.");
247-
}
225+
const contains = utils.checkConfigFieldsArePopulated(config, propertiesBasic);
226+
utils.validateRootMapping(config);
248227
validateFingerprint(config, contains);
249-
validateRootMapping(config);
250228
}
251229

252230
/**
@@ -266,28 +244,6 @@ function validateFingerprint(config, contains) {
266244
}
267245
}
268246

269-
/**
270-
* @private
271-
*/
272-
function validateRootMapping(config) {
273-
function multipleRoots(elem) {
274-
return (
275-
elem.length !== 1 &&
276-
elem.some((item) => {
277-
return item.obj === "$" || item.element === "$";
278-
})
279-
);
280-
}
281-
282-
config.paths.forEach((path) => {
283-
if (multipleRoots(path.toEncrypt) || multipleRoots(path.toDecrypt)) {
284-
throw Error(
285-
"Config not valid: found multiple configurations encrypt/decrypt with root mapping"
286-
);
287-
}
288-
});
289-
}
290-
291247
/**
292248
* @private
293249
*/

lib/mcapi/encryption/field-level-encryption.js

Lines changed: 10 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -24,43 +24,6 @@ function FieldLevelEncryption(config) {
2424
];
2525
}
2626

27-
/**
28-
* @private
29-
*/
30-
function hasConfig(config, endpoint) {
31-
if (config && endpoint) {
32-
endpoint = endpoint.split("?").shift();
33-
const conf = config.paths.find((elem) => {
34-
const regex = new RegExp(elem.path, "g");
35-
return endpoint.match(regex);
36-
});
37-
return conf ? conf : null;
38-
}
39-
return null;
40-
}
41-
42-
/**
43-
* @private
44-
*/
45-
function elemFromPath(path, obj) {
46-
try {
47-
let parent = null;
48-
const paths = path.split(".");
49-
if (path && paths.length > 0) {
50-
paths.forEach((e) => {
51-
parent = obj;
52-
obj = isJsonRoot(e) ? obj : obj[e];
53-
});
54-
}
55-
return {
56-
node: obj,
57-
parent: parent,
58-
};
59-
} catch (e) {
60-
return null;
61-
}
62-
}
63-
6427
/**
6528
* Set encryption header parameters
6629
*
@@ -86,7 +49,7 @@ function setHeader(header, params) {
8649
*/
8750
function encrypt(endpoint, header, body) {
8851
let bodyMap = body;
89-
const fleConfig = hasConfig(this.config, endpoint);
52+
const fleConfig = utils.hasConfig(this.config, endpoint);
9053
if (fleConfig) {
9154
if (!this.isWithHeader) {
9255
bodyMap = fleConfig.toEncrypt.map((v) => {
@@ -116,7 +79,7 @@ function encrypt(endpoint, header, body) {
11679
function decrypt(response) {
11780
const body = response.body;
11881
let bodyMap = response.body;
119-
const fleConfig = hasConfig(this.config, response.request.url);
82+
const fleConfig = utils.hasConfig(this.config, response.request.url);
12083
if (fleConfig) {
12184
bodyMap = fleConfig.toDecrypt.map((v) => {
12285
if (!this.isWithHeader) {
@@ -137,13 +100,13 @@ function decrypt(response) {
137100
* @param body Body to encrypt
138101
*/
139102
function encryptBody(path, body) {
140-
const elem = elemFromPath(path.element, body);
103+
const elem = utils.elemFromPath(path.element, body);
141104
if (elem && elem.node) {
142105
const encryptedData = this.crypto.encryptData({ data: elem.node });
143106
body = utils.mutateObjectProperty(path.obj, encryptedData, body);
144107
// delete encrypted field if not overridden
145108
if (
146-
!isJsonRoot(path.obj) &&
109+
!utils.isJsonRoot(path.obj) &&
147110
path.element !== path.obj + "." + this.config.encryptedValueFieldName
148111
) {
149112
utils.deleteNode(path.element, body);
@@ -162,13 +125,13 @@ function encryptBody(path, body) {
162125
* @returns {Object} Encrypted body
163126
*/
164127
function encryptWithHeader(encParams, path, body) {
165-
const elem = elemFromPath(path.element, body).node;
128+
const elem = utils.elemFromPath(path.element, body).node;
166129
const encrypted = this.crypto.encryptData({ data: elem }, encParams);
167130
const data = {
168131
[this.config.encryptedValueFieldName]:
169132
encrypted[this.config.encryptedValueFieldName],
170133
};
171-
return isJsonRoot(path.obj) ? data : { [path.obj]: data };
134+
return utils.isJsonRoot(path.obj) ? data : { [path.obj]: data };
172135
}
173136

174137
/**
@@ -180,7 +143,7 @@ function encryptWithHeader(encParams, path, body) {
180143
* @returns {Object} Decrypted body
181144
*/
182145
function decryptBody(path, body) {
183-
const elem = elemFromPath(path.element, body);
146+
const elem = utils.elemFromPath(path.element, body);
184147
if (elem && elem.node) {
185148
const decryptedObj = this.crypto.decryptData(
186149
elem.node[this.config.encryptedValueFieldName], // encrypted data
@@ -208,8 +171,8 @@ function decryptBody(path, body) {
208171
* @param response Response with header to update
209172
*/
210173
function decryptWithHeader(path, body, response) {
211-
const elemEncryptedNode = elemFromPath(path.obj, body);
212-
const node = isJsonRoot(path.element)
174+
const elemEncryptedNode = utils.elemFromPath(path.obj, body);
175+
const node = utils.isJsonRoot(path.element)
213176
? elemEncryptedNode.node
214177
: elemEncryptedNode.node[path.element];
215178
if (node) {
@@ -224,14 +187,10 @@ function decryptWithHeader(path, body, response) {
224187
response.header[this.config.oaepHashingAlgorithmHeaderName],
225188
response.header[this.config.encryptedKeyHeaderName]
226189
);
227-
return isJsonRoot(path.obj) ? decrypted : Object.assign(body, decrypted);
190+
return utils.isJsonRoot(path.obj) ? decrypted : Object.assign(body, decrypted);
228191
}
229192
}
230193

231-
function isJsonRoot(elem) {
232-
return elem === "$";
233-
}
234-
235194
function computeBody(configParam, body, bodyMap) {
236195
return hasEncryptionParam(configParam, bodyMap) ? bodyMap.pop() : body;
237196
}

lib/mcapi/encryption/jwe-encryption.js

Lines changed: 5 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -15,43 +15,6 @@ function JweEncryption(config) {
1515
this.crypto = new JweCrypto(config);
1616
}
1717

18-
/**
19-
* @private
20-
*/
21-
function hasConfig(config, endpoint) {
22-
if (config && endpoint) {
23-
endpoint = endpoint.split("?").shift();
24-
const conf = config.paths.find((elem) => {
25-
const regex = new RegExp(elem.path, "g");
26-
return endpoint.match(regex);
27-
});
28-
return conf ? conf : null;
29-
}
30-
return null;
31-
}
32-
33-
/**
34-
* @private
35-
*/
36-
function elemFromPath(path, obj) {
37-
try {
38-
let parent = null;
39-
const paths = path.split(".");
40-
if (path && paths.length > 0) {
41-
paths.forEach((e) => {
42-
parent = obj;
43-
obj = isJsonRoot(e) ? obj : obj[e];
44-
});
45-
}
46-
return {
47-
node: obj,
48-
parent: parent,
49-
};
50-
} catch (e) {
51-
return null;
52-
}
53-
}
54-
5518
/**
5619
* Encrypt parts of a HTTP request using the given config
5720
*
@@ -62,7 +25,7 @@ function elemFromPath(path, obj) {
6225
*/
6326
function encrypt(endpoint, header, body) {
6427
let bodyMap = body;
65-
const fleConfig = hasConfig(this.config, endpoint);
28+
const fleConfig = utils.hasConfig(this.config, endpoint);
6629
if (fleConfig) {
6730
bodyMap = fleConfig.toEncrypt.map((v) => {
6831
return encryptBody.call(this, v, body);
@@ -84,7 +47,7 @@ function encrypt(endpoint, header, body) {
8447
function decrypt(response) {
8548
const body = response.body;
8649
let bodyMap = response.body;
87-
const fleConfig = hasConfig(this.config, response.request.url);
50+
const fleConfig = utils.hasConfig(this.config, response.request.url);
8851
if (fleConfig) {
8952
bodyMap = fleConfig.toDecrypt.map((v) => {
9053
return decryptBody.call(this, v, body);
@@ -101,13 +64,13 @@ function decrypt(response) {
10164
* @param body Body to encrypt
10265
*/
10366
function encryptBody(path, body) {
104-
const elem = elemFromPath(path.element, body);
67+
const elem = utils.elemFromPath(path.element, body);
10568
if (elem && elem.node) {
10669
const encryptedData = this.crypto.encryptData({ data: elem.node });
10770
body = utils.mutateObjectProperty(path.obj, encryptedData, body);
10871
// delete encrypted field if not overridden
10972
if (
110-
!isJsonRoot(path.obj) &&
73+
!utils.isJsonRoot(path.obj) &&
11174
path.element !== path.obj + "." + this.config.encryptedValueFieldName
11275
) {
11376
utils.deleteNode(path.element, body);
@@ -125,7 +88,7 @@ function encryptBody(path, body) {
12588
* @returns {Object} Decrypted body
12689
*/
12790
function decryptBody(path, body) {
128-
const elem = elemFromPath(path.element, body);
91+
const elem = utils.elemFromPath(path.element, body);
12992
if (elem && elem.node) {
13093
const decryptedObj = this.crypto.decryptData(
13194
elem.node[this.config.encryptedValueFieldName]
@@ -141,10 +104,6 @@ function decryptBody(path, body) {
141104
return body;
142105
}
143106

144-
function isJsonRoot(elem) {
145-
return elem === "$";
146-
}
147-
148107
function computeBody(configParam, body, bodyMap) {
149108
return hasEncryptionParam(configParam, bodyMap) ? bodyMap.pop() : body;
150109
}

0 commit comments

Comments
 (0)