mirror of
https://github.com/valitydev/wazuh-kibana-app.git
synced 2024-11-06 09:55:18 +00:00
257 lines
8.1 KiB
JavaScript
257 lines
8.1 KiB
JavaScript
/*
|
|
* Wazuh app - Elasticsearch data table raw response parser
|
|
* Copyright (C) 2015-2019 Wazuh, Inc.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Find more information about this on the LICENSE file.
|
|
*/
|
|
|
|
/**
|
|
* Aggregation which starts in level 2
|
|
* @param {*} data_set The raw response.
|
|
*/
|
|
const parse_start_2 = data_set => {
|
|
const tree = {};
|
|
for (const main_bucket of data_set.aggregations['2'].buckets) {
|
|
if (!tree[main_bucket.key]) tree[main_bucket.key] = {};
|
|
if (main_bucket['3'] && main_bucket['3'].buckets) {
|
|
for (const sub_bucket of main_bucket['3'].buckets) {
|
|
if (!tree[main_bucket.key][sub_bucket.key])
|
|
tree[main_bucket.key][sub_bucket.key] = {};
|
|
|
|
if (sub_bucket['4'] && sub_bucket['4'].buckets) {
|
|
for (const sub_sub_bucket of sub_bucket['4'].buckets) {
|
|
if (!tree[main_bucket.key][sub_bucket.key][sub_sub_bucket.key])
|
|
tree[main_bucket.key][sub_bucket.key][sub_sub_bucket.key] = {};
|
|
|
|
if (sub_sub_bucket['5'] && sub_sub_bucket['5'].buckets) {
|
|
for (const sub_sub_sub_bucket of sub_sub_bucket['5'].buckets) {
|
|
if (
|
|
!tree[main_bucket.key][sub_bucket.key][sub_sub_bucket.key][
|
|
sub_sub_sub_bucket.key
|
|
]
|
|
) {
|
|
tree[main_bucket.key][sub_bucket.key][sub_sub_bucket.key][
|
|
sub_sub_sub_bucket.key
|
|
] = {};
|
|
tree[main_bucket.key][sub_bucket.key][sub_sub_bucket.key][
|
|
sub_sub_sub_bucket.key
|
|
][sub_sub_sub_bucket.doc_count] = false;
|
|
}
|
|
}
|
|
} else {
|
|
tree[main_bucket.key][sub_bucket.key][sub_sub_bucket.key] = {};
|
|
tree[main_bucket.key][sub_bucket.key][sub_sub_bucket.key][
|
|
sub_sub_bucket.doc_count
|
|
] = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (sub_bucket['5'] && sub_bucket['5'].buckets) {
|
|
for (const sub_sub_bucket of sub_bucket['5'].buckets) {
|
|
if (!tree[main_bucket.key][sub_bucket.key][sub_sub_bucket.key]) {
|
|
tree[main_bucket.key][sub_bucket.key][sub_sub_bucket.key] = {};
|
|
tree[main_bucket.key][sub_bucket.key][sub_sub_bucket.key][
|
|
sub_sub_bucket.doc_count
|
|
] = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (
|
|
!(sub_bucket['4'] && sub_bucket['4'].buckets) &&
|
|
!(sub_bucket['5'] && sub_bucket['5'].buckets)
|
|
) {
|
|
tree[main_bucket.key][sub_bucket.key] = {};
|
|
tree[main_bucket.key][sub_bucket.key][sub_bucket.doc_count] = false;
|
|
}
|
|
}
|
|
} else {
|
|
tree[main_bucket.key] = {};
|
|
tree[main_bucket.key][main_bucket.doc_count] = false;
|
|
}
|
|
}
|
|
return tree;
|
|
};
|
|
|
|
/**
|
|
* Aggregation which starts in level 3
|
|
* @param {*} data_set The raw response.
|
|
*/
|
|
const parse_start_3 = data_set => {
|
|
const tree = {};
|
|
|
|
for (const sub_bucket of data_set.aggregations['3'].buckets) {
|
|
if (!tree[sub_bucket.key]) tree[sub_bucket.key] = {};
|
|
|
|
if (sub_bucket['4'] && sub_bucket['4'].buckets) {
|
|
for (const sub_sub_bucket of sub_bucket['4'].buckets) {
|
|
if (!tree[sub_bucket.key][sub_sub_bucket.key])
|
|
tree[sub_bucket.key][sub_sub_bucket.key] = {};
|
|
|
|
if (sub_sub_bucket['5'] && sub_sub_bucket['5'].buckets) {
|
|
for (const sub_sub_sub_bucket of sub_sub_bucket['5'].buckets) {
|
|
if (
|
|
!tree[sub_bucket.key][sub_sub_bucket.key][sub_sub_sub_bucket.key]
|
|
) {
|
|
tree[sub_bucket.key][sub_sub_bucket.key][
|
|
sub_sub_sub_bucket.key
|
|
] = {};
|
|
tree[sub_bucket.key][sub_sub_bucket.key][sub_sub_sub_bucket.key][
|
|
sub_sub_sub_bucket.doc_count
|
|
] = false;
|
|
}
|
|
}
|
|
} else {
|
|
tree[sub_bucket.key][sub_sub_bucket.key] = {};
|
|
tree[sub_bucket.key][sub_sub_bucket.key][
|
|
sub_sub_bucket.doc_count
|
|
] = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (sub_bucket['5'] && sub_bucket['5'].buckets) {
|
|
for (const sub_sub_bucket of sub_bucket['5'].buckets) {
|
|
if (!tree[sub_bucket.key][sub_sub_bucket.key]) {
|
|
tree[sub_bucket.key][sub_sub_bucket.key] = {};
|
|
tree[sub_bucket.key][sub_sub_bucket.key][
|
|
sub_sub_bucket.doc_count
|
|
] = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (
|
|
!(sub_bucket['4'] && sub_bucket['4'].buckets) &&
|
|
!(sub_bucket['5'] && sub_bucket['5'].buckets)
|
|
) {
|
|
tree[sub_bucket.key] = {};
|
|
tree[sub_bucket.key][sub_bucket.doc_count] = false;
|
|
}
|
|
}
|
|
|
|
return tree;
|
|
};
|
|
|
|
/**
|
|
* Aggregation which starts in level 3 and continues with level 2 buckets
|
|
* @param {*} data_set The raw response.
|
|
*/
|
|
const parse_start_3_mix_2 = data_set => {
|
|
const tree = {};
|
|
|
|
for (const sub_bucket of data_set.aggregations['3'].buckets) {
|
|
if (!tree[sub_bucket.key]) tree[sub_bucket.key] = {};
|
|
|
|
if (sub_bucket['2'] && sub_bucket['2'].buckets) {
|
|
for (const sub_sub_bucket of sub_bucket['2'].buckets) {
|
|
if (!tree[sub_bucket.key][sub_sub_bucket.key])
|
|
tree[sub_bucket.key][sub_sub_bucket.key] = {};
|
|
|
|
if (sub_sub_bucket['6'] && sub_sub_bucket['6'].buckets) {
|
|
for (const sub_sub_sub_bucket of sub_sub_bucket['6'].buckets) {
|
|
if (
|
|
!tree[sub_bucket.key][sub_sub_bucket.key][sub_sub_sub_bucket.key]
|
|
) {
|
|
tree[sub_bucket.key][sub_sub_bucket.key][
|
|
sub_sub_sub_bucket.key
|
|
] = {};
|
|
tree[sub_bucket.key][sub_sub_bucket.key][sub_sub_sub_bucket.key][
|
|
sub_sub_sub_bucket.doc_count
|
|
] = false;
|
|
}
|
|
}
|
|
} else {
|
|
tree[sub_bucket.key][sub_sub_bucket.key] = {};
|
|
tree[sub_bucket.key][sub_sub_bucket.key][
|
|
sub_sub_bucket.doc_count
|
|
] = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return tree;
|
|
};
|
|
|
|
/**
|
|
* Generates a hierarchical tree from the raw response.
|
|
* @param {*} data_set The raw response. Must have aggregations and buckets for level 0.
|
|
*/
|
|
const generate_tree = data_set => {
|
|
// If we have no aggregations just return empty object
|
|
if (!data_set || !data_set.aggregations) {
|
|
return {};
|
|
}
|
|
|
|
// If the aggregation from Elasticsearch starts using level 2
|
|
if (data_set.aggregations['2'] && data_set.aggregations['2'].buckets) {
|
|
return parse_start_2(data_set);
|
|
}
|
|
|
|
// If the aggregation from Elasticsearch starts using level 3 and continues using level 2
|
|
if (
|
|
data_set.aggregations['3'] &&
|
|
data_set.aggregations['3'].buckets &&
|
|
data_set.aggregations['3'].buckets[0] &&
|
|
data_set.aggregations['3'].buckets[0]['2'] &&
|
|
data_set.aggregations['3'].buckets[0]['2'].buckets
|
|
) {
|
|
return parse_start_3_mix_2(data_set);
|
|
}
|
|
|
|
// If the aggregation from Elasticsearch starts using level 3
|
|
if (data_set.aggregations['3'] && data_set.aggregations['3'].buckets) {
|
|
return parse_start_3(data_set);
|
|
}
|
|
|
|
// If none of the above conditions are true, return empty object
|
|
return {};
|
|
};
|
|
|
|
/**
|
|
* Generates a matrix which includes each parsed row
|
|
* @param {*} item Hierarchical tree generated from a raw response
|
|
*/
|
|
const generate_rows = item => {
|
|
const iter = (r, p) => {
|
|
const keys = Object.keys(r);
|
|
if (keys.length) {
|
|
return keys.forEach(x => iter(r[x], p.concat(x)));
|
|
}
|
|
result.push(p);
|
|
};
|
|
const result = [];
|
|
iter(item, []);
|
|
return result;
|
|
};
|
|
|
|
/**
|
|
* Public function to enter the module.
|
|
* Always returns an array (could be empty)
|
|
* @param {*} data_set The raw response.
|
|
*/
|
|
export default (data_set, cols) => {
|
|
try {
|
|
const tree = generate_tree(data_set);
|
|
|
|
const min_size = cols.length;
|
|
|
|
// Minimum validation for the generated tree
|
|
if (!tree || !Object.keys(tree) || !Object.keys(tree).length) return [];
|
|
|
|
// All rows must have same length
|
|
const rows = generate_rows(tree).filter(item => item.length === min_size);
|
|
|
|
return rows;
|
|
} catch (error) {
|
|
return [];
|
|
}
|
|
};
|