Skip to content

Commit

Permalink
Added **conflict_strategy**, **overwrite_by_source** and **overwrite_…
Browse files Browse the repository at this point in the history
…by_destination** parameters to control key conflicts. (#23225) (#23365)
  • Loading branch information
content-bot authored and MosheEichler committed Jan 2, 2023
1 parent e0ca0f1 commit 1134008
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 23 deletions.
4 changes: 4 additions & 0 deletions Packs/FiltersAndTransformers/ReleaseNotes/1_1_7.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

#### Scripts
##### MergeDictArray
- Added **conflict_strategy**, **overwrite_by_source** and **overwrite_by_destination** parameters to control key conflicts.
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,46 @@ function is_object(o) {
return o instanceof Object && !(o instanceof Array);
}

function set_object_value(obj, path, value, append) {
function merge_value(dst, src, key, conflict_strategy, overwrite_by_src, overwrite_by_dst) {
if (overwrite_by_src.indexOf(key) >= 0) {
return src;
} else if (overwrite_by_dst.indexOf(key) >= 0) {
return dst;
}
switch (conflict_strategy) {
case 'destination':
return dst;
case 'source':
return src;
case 'merge':
let dst_array = Array.isArray(dst) ? dst.concat() : (dst !== null ? [dst] : []);
let src_array = Array.isArray(src) ? src : (src !== null ? [src] : []);
src_array.forEach(v => {
if (dst_array.indexOf(v) < 0) {
dst_array.push(v);
}
});
if (dst_array.length == 1 && (!Array.isArray(src) || !Array.isArray(dst))) {
return dst_array[0];
} else if (dst_array.length >= 1) {
return dst_array;
}
return dst !== null ? dst : src;
default:
throw 'Invalid conflict_strategy: ' + conflict_strategy;
}
}

function set_object_value(obj, path, value, append, conflict_strategy, overwrite_by_src, overwrite_by_dst) {
const root = obj;
path.split('.').forEach((key, i, keys) => {
if (!key) {
throw path + ' has an emtpy node.';
}else if (keys.length-1 === i) {
if (!append || !(key in obj)) {
obj[key] = value;
} else if (Array.isArray(obj[key])) {
obj[key] = obj[key].concat(value);
} else {
obj[key] = [obj[key], value];
obj[key] = merge_value(obj[key], value, key, conflict_strategy, overwrite_by_src, overwrite_by_dst);
}
} else {
if (!is_object(obj[key])) {
Expand Down Expand Up @@ -72,7 +100,7 @@ function contains_object_value(dval, sval, kmap) {
return true;
}

function merge_object_value(dst, src) {
function merge_object_value(dst, src, conflict_strategy, overwrite_by_src, overwrite_by_dst) {
if (!is_object(dst)) {
throw 'Invalid object in destination value: ' + JSON.stringify(dst);
}
Expand All @@ -83,15 +111,7 @@ function merge_object_value(dst, src) {
for (const k in src) {
if (k in dst) {
for (const sval of Array.isArray(src[k]) ? src[k] : [src[k]]) {
if (Array.isArray(dst[k])) {
if (dst[k].indexOf(sval) < 0) {
out[k] = dst[k].concat(sval);
}
} else {
if (dst[k] != sval) {
out[k] = [dst[k], sval];
}
}
out[k] = merge_value(dst[k], sval, k, conflict_strategy, overwrite_by_src, overwrite_by_dst);
}
} else {
out[k] = src[k];
Expand All @@ -100,17 +120,19 @@ function merge_object_value(dst, src) {
return out;
}

function merge_array(dst, src, kmap, out_key, appendable) {
function merge_array(dst, src, kmap, out_key, appendable, conflict_strategy, overwrite_by_src, overwrite_by_dst) {
dst = dst.concat();
src.forEach(sval => {
let merged = false;
if (is_object(sval)) {
dst.forEach((dval, index) => {
if (contains_object_value(dval, sval, kmap)) {
if (out_key) {
dst[index] = set_object_value(dval, out_key, sval, true);
dst[index] = set_object_value(dval, out_key, sval, true,
conflict_strategy, overwrite_by_src, overwrite_by_dst);
} else {
dst[index] = merge_object_value(dval, sval);
dst[index] = merge_object_value(dval, sval,
conflict_strategy, overwrite_by_src, overwrite_by_dst);
}
merged = true;
}
Expand All @@ -127,25 +149,37 @@ let dst_value = args.value;
const src_array = Array.isArray(args.merge_with) ? args.merge_with : [args.merge_with];
const key_map = make_keymap(args.mapping);
const appendable = args.appendable.toLowerCase() == 'true';
const conflict_strategy = args.conflict_strategy ? args.conflict_strategy : 'merge';
const overwrite_by_src = argToList(args.overwrite_by_source);
const overwrite_by_dst = argToList(args.overwrite_by_destination);

if (overwrite_by_src.filter((v) => overwrite_by_dst.indexOf(v) >= 0).length !==0 ){
throw 'A key is conflict in overwrite_by_source and overwrite_by_destination.';
}
if (src_array && args.merge_with !== null) {
if (args.array_path) {
dst_value.forEach(v => {
let dst_array = dq(v, args.array_path);
let new_array;
if (!Array.isArray(dst_array)) {
new_array = merge_array([dst_array], src_array, key_map, args.out_key, appendable);
new_array = merge_array([dst_array], src_array, key_map, args.out_key, appendable,
conflict_strategy, overwrite_by_src, overwrite_by_dst);
if (new_array.length == 1) {
new_array = new_array[0];
}
} else {
new_array = merge_array(dst_array, src_array, key_map, args.out_key, appendable);
new_array = merge_array(dst_array, src_array, key_map, args.out_key, appendable,
conflict_strategy, overwrite_by_src, overwrite_by_dst);
}
set_object_value(v, args.out_path ? args.out_path : args.array_path, new_array, false);
set_object_value(v, args.out_path ? args.out_path : args.array_path, new_array, false,
conflict_strategy, overwrite_by_src, overwrite_by_dst);
});
} else {
dst_value = merge_array(dst_value, src_array, key_map, args.out_key, appendable);
dst_value = merge_array(dst_value, src_array, key_map, args.out_key, appendable,
conflict_strategy, overwrite_by_src, overwrite_by_dst);
if (args.out_path) {
dst_value = [set_object_value({}, args.out_path, dst_value, false)];
dst_value = [set_object_value({}, args.out_path, dst_value, false,
conflict_strategy, overwrite_by_src, overwrite_by_dst)];
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,21 @@ args:
predefined:
- "true"
- "false"
- name: conflict_strategy
auto: PREDEFINED
predefined:
- merge
- source
- destination
description: How to merge the values if the key conflicts. 'source'
means data of 'merge_with', 'destination' means data of 'array_path'.
defaultValue: merge
- name: overwrite_by_source
description: The comma separeted list of keys to overwrite by source value when the key conflicts.
isArray: true
- name: overwrite_by_destination
description: The comma separeted list of keys to overwrite by destination value when the key conflicts.
isArray: true
comment: Each entry in an array is merged into the existing array if the keyed-value matches.
commonfields:
id: MergeDictArray
Expand Down
3 changes: 3 additions & 0 deletions Packs/FiltersAndTransformers/Scripts/MergeDictArray/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ Each entry in an array is merged into the existing array if the keyed-value matc
| out_key | The key to the value where each of the destination value is to be set |
| out_path | The relative path to the destination array where the marged array is set |
| appendable | true if it allows to simply append source entries which doesn't match, otherwise false |
| conflict_strategy | How to merge the values if the key conflicts. 'source' means data of 'merge_with', 'destination' means data of 'array_path'. Default is 'merge'.|
| overwrite_by_source | The comma separeted list of keys to overwrite by source value if the key conflicts. |
| overwrite_by_destination | The comma separeted list of keys to overwrite by destination value if the key conflicts. |

## Outputs
---
Expand Down
2 changes: 1 addition & 1 deletion Packs/FiltersAndTransformers/pack_metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "Filters And Transformers",
"description": "Frequently used filters and transformers pack.",
"support": "xsoar",
"currentVersion": "1.1.6",
"currentVersion": "1.1.7",
"author": "Cortex XSOAR",
"url": "https://www.paloaltonetworks.com/cortex",
"email": "",
Expand Down

0 comments on commit 1134008

Please sign in to comment.