chg: [distributionNetwork] Integration with event index - WiP

pull/4309/head
mokaddem 2019-03-12 08:15:27 +01:00
parent 6a7efb92c5
commit 968d578e38
7 changed files with 102 additions and 475 deletions

View File

@ -862,6 +862,7 @@ class EventsController extends AppController
$this->set('analysisLevels', $this->Event->analysisLevels);
$this->set('distributionLevels', $this->Event->distributionLevels);
$this->set('shortDist', $this->Event->shortDist);
$this->set('distributionData', $this->genDistributionGraph(0));
if ($this->params['ext'] === 'csv') {
App::uses('CsvExport', 'Export');
$export = new CsvExport();
@ -4661,8 +4662,7 @@ class EventsController extends AppController
return new CakeResponse(array('body' => json_encode($json), 'status' => 200, 'type' => 'json'));
}
public function getDistributionGraph($id, $type = 'event')
{
private function genDistributionGraph($id, $type = 'event', $extended = 0) {
$validTools = array('event');
if (!in_array($type, $validTools)) {
throw new MethodNotAllowedException(__('Invalid type.'));
@ -4671,9 +4671,6 @@ class EventsController extends AppController
$this->loadModel('Organisation');
App::uses('DistributionGraphTool', 'Tools');
$grapher = new DistributionGraphTool();
$data = $this->request->is('post') ? $this->request->data : array();
$extended = isset($this->params['named']['extended']) ? 1 : 0;
$servers = $this->Server->find('list', array(
'fields' => array('name'),
@ -4686,6 +4683,34 @@ class EventsController extends AppController
$item = utf8_encode($item);
}
});
return $json;
}
public function getDistributionGraph($id, $type = 'event')
{
// $validTools = array('event');
// if (!in_array($type, $validTools)) {
// throw new MethodNotAllowedException(__('Invalid type.'));
// }
// $this->loadModel('Server');
// $this->loadModel('Organisation');
// App::uses('DistributionGraphTool', 'Tools');
// $grapher = new DistributionGraphTool();
//
$extended = isset($this->params['named']['extended']) ? 1 : 0;
//
// $servers = $this->Server->find('list', array(
// 'fields' => array('name'),
// ));
// $grapher->construct($this->Event, $servers, $this->Auth->user(), $extended);
// $json = $grapher->get_distributions_graph($id);
//
// array_walk_recursive($json, function (&$item, $key) {
// if (!mb_detect_encoding($item, 'utf-8', true)) {
// $item = utf8_encode($item);
// }
// });
$json = $this->genDistributionGraph($id, $type, $extended);
$this->response->type('json');
return new CakeResponse(array('body' => json_encode($json), 'status' => 200, 'type' => 'json'));
}

View File

@ -214,6 +214,15 @@
echo h($shortDist[$event['Event']['distribution']]);
endif;
?>
<?php
echo sprintf(
'<it type="button" title="%s" class="%s" aria-hidden="true" style="font-size: x-small;" data-event-distribution="%s" data-scope-id="%s"></it>',
'Toggle advanced sharing network viewer',
'fa fa-share-alt useCursorPointer distributionNetworkToggle',
h($event['Event']['distribution']),
h($event['Event']['id'])
)
?>
</td>
<td class="short action-links">
<?php
@ -239,5 +248,11 @@
$('.select').on('change', function() {
listCheckboxesChecked();
});
$('.distributionNetworkToggle').each(function() {
$(this).distributionNetwork({
distributionData: <?php echo json_encode($distributionData); ?>,
});
});
});
</script>

View File

@ -136,6 +136,12 @@
});
</script>
<?php
echo $this->Html->script('vis');
echo $this->Html->css('vis');
echo $this->Html->css('distribution-graph');
echo $this->Html->script('network-distribution-graph');
?>
<input type="hidden" class="keyboardShortcutsConfig" value="/shortcuts/event_index.json" />
<?php

View File

@ -39,6 +39,7 @@
echo $this->Html->css('query-builder.default');
echo $this->Html->script('query-builder');
echo $this->Html->css('attack_matrix');
echo $this->Html->script('network-distribution-graph');
?>
<div class="events view">
<?php
@ -160,10 +161,9 @@
$this->element('view_event_distribution_graph')
),
sprintf(
'<it type="button" id="showAdvancedSharingButton" title="%s" class="%s" aria-hidden="true" style="margin-left: 5px;" onclick="%s"></it>',
'<it type="button" id="showAdvancedSharingButton" title="%s" class="%s" aria-hidden="true" style="margin-left: 5px;"></it>',
'Toggle advanced sharing network viewer',
'fa fa-share-alt useCursorPointer',
'showAdvancedSharing(this)'
'fa fa-share-alt useCursorPointer'
)
)
);
@ -507,6 +507,7 @@ $(document).ready(function () {
$.get("/threads/view/<?php echo h($event['Event']['id']); ?>/true", function(data) {
$("#discussions_div").html(data);
});
});
function enable_correlation_graph() {

View File

@ -2,6 +2,44 @@
color: #333333;
}
.eventgraph_header {
background: #f9f9f9;
box-shadow: 0px 0px 6px #B2B2B2;
margin-bottom: 2px;
width: 100%;
height: 40px;
overflow: hidden;
}
select.center-in-network-header {
margin-bottom: 0px;
width: fit-content;
}
input[type="text"].center-in-network-header {
top: 5px;
margin: 0px;
margin-left: 5px;
}
input[type="checkbox"].center-in-network-header {
top: 0px;
margin: 0px;
margin-left: 5px;
}
label.center-in-network-header {
user-select: none;
font-weight: bold;
}
.center-in-network-header {
position: relative;
display: inline-block;
top: 5px;
margin-left: 5px;
}
.loadingPopover {
position: absolute;
left: 50%;

View File

@ -7,12 +7,6 @@ var payload = {};
var distribution_chart;
var distributionData;
var EDGE_LENGTH_HUB = 300;
var cacheAddedOrgName = {};
var nodes_distri;
var edges_distri;
var advancedSharingNetwork;
function clickHandlerGraph(evt) {
var firstPoint = distribution_chart.getElementAtEvent(evt)[0];
var distribution_id;
@ -226,38 +220,6 @@ function add_level_to_pb(distribution, additionalInfo, maxLevel) {
}
function showAdvancedSharing(clicked) {
$clicked = $(clicked);
var network_active = $clicked.data('networkactive');
if (network_active !== undefined && network_active === true) {
$('#advancedSharingNetworkWrapper').hide('slide', {direction: 'right'}, 300);
$clicked.data('networkactive', false);
return;
} else if (network_active !== undefined && network_active === false) {
$('#advancedSharingNetworkWrapper').show('slide', {direction: 'right'}, 300);
$clicked.data('networkactive', true);
return;
}
$clicked.data('networkactive', true);
var $popover = $('#eventdistri_graph').parent().parent();
var boundingRect = $popover[0].getBoundingClientRect()
var $div = $('<div id="advancedSharingNetworkWrapper" class="advancedSharingNetwork hidden">'
+ '<div class="eventgraph_header" style="border-radius: 5px; display: flex;">'
+ '<it class="fa fa-circle-o" style="margin: auto 10px; font-size: x-large"></it>'
+ '<input type="text" id="sharingNetworkTargetId" class="center-in-network-header network-typeahead" style="width: 200px;" disabled></input>'
+ '<div class="form-group" style="margin: auto 10px;"><div class="checkbox">'
+ '<label style="user-select: none;"><input id="interactive_picking_mode" type="checkbox" title="Click on a element to see how it is distributed" style="margin-top: 4px;">Enable interactive picking mode</label>'
+ '</div></div>'
+ '<select type="text" id="sharingNetworkOrgFinder" class="center-in-network-header network-typeahead sharingNetworkOrgFinder" style="width: 200px;"></select>'
+ '<button type="button" class="close" style="margin: 1px 5px; right: 0px; position: absolute;" onclick="$(\'#showAdvancedSharingButton\').click();">×</button>'
+ '</div><div id="advancedSharingNetwork"></div></div>');
$('body').append($div);
$div.toggle('slide', {direction: 'right'}, 300);
construct_network();
}
function construct_piechart(data) {
$('.toBeCleared').remove();
@ -422,432 +384,6 @@ function construct_piechart(data) {
distri_graph.append(div);
}
function construct_network(target_distribution, scope_text, overwriteSg) {
cacheAddedOrgName = {};
if (advancedSharingNetwork !== undefined) {
advancedSharingNetwork.destroy();
}
if (scope_text == undefined) {
scope_text = 'Event ' + scope_id;
}
$('#sharingNetworkTargetId').val(scope_text);
nodes_distri = new vis.DataSet([
{id: 'root', group: 'root', label: scope_text, x: 0, y: 0, fixed: true, mass: 20},
{id: distributionData.additionalDistributionInfo[0][0], label: distributionData.additionalDistributionInfo[0][0], group: 'org-only'},
]);
edges_distri = new vis.DataSet([
{from: 'root', to: distributionData.additionalDistributionInfo[0][0], length: 30, width: 3},
]);
if (target_distribution === undefined || target_distribution == 5) {
target_distribution = event_distribution;
}
if (target_distribution !== 0) {
// Event always restrict propagation (sharing group is a special case)
var temp_target_disti = target_distribution;
if (target_distribution !== 4 && temp_target_disti >= event_distribution) {
while (temp_target_disti >= event_distribution) {
var toID = false;
switch (temp_target_disti) {
case 0:
break;
case 1:
toID = 'this-community';
break;
case 2:
toID = 'connected-community';
break;
case 3:
toID = 'all-community';
break;
case 4:
toID = 'sharing-group';
break;
default:
break;
}
var edgeData = {from: 'root', to: toID, width: 3};
if (temp_target_disti != event_distribution) {
edgeData.label = 'X';
edgeData.title = 'The distribution of the Event restricts the distribution level of this element';
edgeData.font = {
size: 50,
color: '#ff0000',
strokeWidth: 6,
strokeColor: '#ff0000'
};
}
if (toID !== false) {
edges_distri.add(edgeData);
}
temp_target_disti--;
}
} else {
switch (temp_target_disti) {
case 0:
break;
case 1:
toID = 'this-community';
break;
case 2:
toID = 'connected-community';
break;
case 3:
toID = 'all-community';
break;
case 4:
toID = 'sharing-group';
break;
default:
break;
}
var edgeData = {from: 'root', to: toID, width: 3};
if (toID !== false) {
edges_distri.add(edgeData);
}
}
}
var nodesToAdd = [];
var edgesToAdd = [];
cacheAddedOrgName[distributionData.additionalDistributionInfo[0][0]] = 1;
// Community
if (target_distribution >= 1 && target_distribution != 4
&& (distributionData.event[1] > 0 || distributionData.event[2] > 0 || distributionData.event[3] > 0)
) {
nodesToAdd.push({id: 'this-community', label: 'This community', group: 'root-this-community'});
inject_this_community_org(nodesToAdd, edgesToAdd, distributionData.additionalDistributionInfo[1], 'this-community', 'this-community');
}
// Connected Community
if (target_distribution >= 2 && target_distribution != 4
&& (distributionData.event[2] > 0 || distributionData.event[3] > 0)
) {
nodesToAdd.push({id: 'connected-community', label: 'Connected community', group: 'root-connected-community'});
distributionData.additionalDistributionInfo[2].forEach(function(orgName) {
if (orgName === 'This community') {
edgesToAdd.push({from: 'connected-community', to: 'this-community', length: EDGE_LENGTH_HUB});
} else {
nodesToAdd.push({
id: 'connected-community_' + orgName,
label: orgName,
group: 'connected-community'
});
edgesToAdd.push({from: 'connected-community', to: 'connected-community_' + orgName});
}
});
}
// All Community
if (target_distribution >= 3 && target_distribution != 4 && distributionData.event[3] > 0) {
nodesToAdd.push({id: 'all-community', label: 'All community', group: 'web'});
distributionData.additionalDistributionInfo[3].forEach(function(orgName) {
if (orgName === 'This community') {
edgesToAdd.push({from: 'all-community', to: 'this-community', length: EDGE_LENGTH_HUB});
} else if (orgName === 'All other communities') {
edgesToAdd.push({from: 'all-community', to: 'connected-community', length: EDGE_LENGTH_HUB});
}
});
}
// Sharing Group
if (distributionData.event[4] > 0) {
distributionData.allSharingGroup.forEach(function(sg) {
var sgName = sg.SharingGroup.name;
if (overwriteSg === undefined) { // if overwriteSg not set, use the one from the event
overwriteSg = distributionData.additionalDistributionInfo[4];
}
if (overwriteSg.indexOf(sgName) == -1) {
return true;
}
nodesToAdd.push({
id: 'sharing-group_' + sgName,
label: sgName,
group: 'root-sharing-group'
});
edgesToAdd.push({from: 'root', to: 'sharing-group_' + sgName, width: 3});
sg.SharingGroupOrg.forEach(function(org) {
var sgOrgName = org.Organisation.name;
if (cacheAddedOrgName[sgOrgName] === undefined) {
nodesToAdd.push({
id: sgOrgName,
label: sgOrgName,
group: 'sharing-group'
});
cacheAddedOrgName[sgOrgName] = 1;
}
edgesToAdd.push({
from: 'sharing-group_' + sgName,
to: sgOrgName,
arrows: {
to: { enabled: false }
},
color: { opacity: 0.4 }
});
});
});
}
var options = '<option></option>';
$('#sharingNetworkOrgFinder').empty();
Object.keys(cacheAddedOrgName).forEach(function(org) {
options += '<option value="'+org+'">'+org+'</option>';
});
$('#sharingNetworkOrgFinder').append(options)
.trigger('chosen:updated')
.chosen({
inherit_select_classes: true,
no_results_text: "Focus to an organisation",
placeholder_text_single: "Focus to an organisation",
allow_single_deselect: true
})
.off('change')
.on('change', function(evt, params) {
if (this.value !== '') {
advancedSharingNetwork.focus(this.value, {animation: true});
advancedSharingNetwork.selectNodes([this.value]);
} else {
advancedSharingNetwork.fit({animation: true})
}
});
nodes_distri.add(nodesToAdd);
edges_distri.add(edgesToAdd);
var data = { nodes: nodes_distri, edges: edges_distri };
var network_options = {
width: '800px',
height: '759px',
layout: {randomSeed: 0},
edges: {
arrowStrikethrough: false,
arrows: {
to: {enabled: true, scaleFactor:1, type:'arrow'},
},
shadow: {
enabled: true,
size: 7,
x: 3,
y: 3
}
},
physics:{
barnesHut: {
gravitationalConstant: -10000,
centralGravity: 0.3,
springLength: 150,
springConstant: 0.02,
damping: 0.09,
avoidOverlap: 0
},
repulsion: {
centralGravity: 0.2,
springLength: 200,
springConstant: 0.02,
nodeDistance: 200,
damping: 0.15
},
solver: 'barnesHut'
},
nodes: {
shadow: {
enabled: true,
size: 7,
x: 3,
y: 3
}
},
groups: {
'root': {
shape: 'icon',
icon: {
face: 'FontAwesome',
code: '\uf10c',
color: '#000000',
size: 50
},
font: {size: 30},
color: '#000000',
},
'org-only': {
shape: 'icon',
icon: {
face: 'FontAwesome',
code: '\uf2c2',
color: '#ff0000',
size: 30
},
font: {
size: 14, // px
color: '#ff0000',
background: 'rgba(255, 255, 255, 0.7)'
},
color: '#ff0000',
},
'root-this-community': {
shape: 'icon',
icon: {
face: 'FontAwesome',
code: '\uf1e1',
color: '#ff9725',
size: 70
},
font: {
size: 18, // px
color: '#ff9725',
background: 'rgba(255, 255, 255, 0.7)'
},
color: '#ff9725',
},
'this-community': {
font: {color: 'white'},
color: '#ff9725',
shape: 'box',
margin: 3
},
'root-connected-community': {
shape: 'icon',
icon: {
face: 'FontAwesome',
code: '\uf0e8',
color: '#9b6e1b',
size: 70
},
font: {
size: 18, // px
color: '#9b6e1b',
background: 'rgba(255, 255, 255, 0.7)'
},
color: '#9b6e1b',
},
'connected-community': {
shape: 'image',
image: '/img/orgs/MISP.png'
},
'web': {
shape: 'icon',
icon: {
face: 'FontAwesome',
code: '\uf0ac',
color: '#007d20',
size: 70
},
font: {
size: 18, // px
color: '#007d20',
background: 'rgba(255, 255, 255, 0.7)'
},
color: '#007d20',
},
'root-sharing-group': {
shape: 'icon',
icon: {
face: 'FontAwesome',
code: '\uf0c0',
color: '#1369a0',
size: 70
},
font: {
size: 18, // px
color: '#1369a0',
background: 'rgba(255, 255, 255, 0.7)'
},
color: '#1369a0',
}
}
};
advancedSharingNetwork = new vis.Network(document.getElementById('advancedSharingNetwork'), data, network_options);
advancedSharingNetwork.on("dragStart", function (params) {
params.nodes.forEach(function(nodeId) {
nodes_distri.update({id: nodeId, fixed: {x: false, y: false}});
});
});
advancedSharingNetwork.on("dragEnd", function (params) {
params.nodes.forEach(function(nodeId) {
nodes_distri.update({id: nodeId, fixed: {x: true, y: true}});
});
});
$('#interactive_picking_mode').off('change').on('change', function(e) {
var target_id = $(this).val();
if (this.checked) {
toggleRowListener(true);
} else {
toggleRowListener(false);
construct_network(event_distribution)
}
});
}
function toggleRowListener(toAdd) {
if (toAdd) {
$('#attributes_div table tr').off('click.advancedSharing').on('click.advancedSharing', function() {
var $row = $(this);
var clicked_type = $row.attr('id').split('_')[0];
var clicked_id = $row.attr('id').split('_')[1];
// var $dist_cell = $row.find('#'+clicked_type+'_'+clicked_id+'_distribution_solid');
var $dist_cell = $row.find('div').filter(function() {
return $(this).attr('id') !== undefined && $(this).attr('id').includes(clicked_id+'_distribution');
});
var distribution_value;
var overwriteSg;
switch ($dist_cell.text().trim()) {
case 'Organisation':
distribution_value = 0;
break;
case 'Community':
distribution_value = 1;
break;
case 'Connected':
distribution_value = 2;
break;
case 'All':
distribution_value = 3;
break;
case 'Inherit':
distribution_value = 5;
if (event_distribution == 4) {
overwriteSg = event_distribution_text.trim();
}
break;
default:
distribution_value = 4;
overwriteSg = $dist_cell.text().trim();
break
}
construct_network(distribution_value, clicked_type+' '+clicked_id, [overwriteSg]);
});
} else {
$('#attributes_div table tr').off('click.advancedSharing');
}
}
function inject_this_community_org(nodesToAdd, edgesToAdd, orgs, group, root) {
orgs.forEach(function(orgName) {
if (cacheAddedOrgName[orgName] === undefined) {
nodesToAdd.push({
id: orgName,
label: orgName,
group: group
});
cacheAddedOrgName[orgName] = 1;
}
edgesToAdd.push({
from: root,
to: orgName,
arrows: {
to: { enabled: false }
},
color: { opacity: 0.4 }
});
});
}
function fetchDistributionData(callback) {
$.ajax({
url: "/events/"+"getDistributionGraph"+"/"+scope_id+"/event.json",
@ -894,10 +430,11 @@ $(document).ready(function() {
if (distributionData !== undefined) {
construct_piechart(distributionData);
} else {
fetchDistributionData(function(data) { construct_piechart(data); });
fetchDistributionData(function(data) {
construct_piechart(data);
});
}
}).on('hide.bs.popover', function(e) {
// $('#advancedSharingNetworkWrapper').hide('slide', {direction: 'right'}, 200, function() { $('#advancedSharingNetworkWrapper').remove(); });
});
$('body').on('mouseup', function(e) {
@ -909,5 +446,10 @@ $(document).ready(function() {
fetchDistributionData(function(data) {
drawBarChart(data);
$('#showAdvancedSharingButton').distributionNetwork({
event_distribution: event_distribution,
distributionData: data,
scope_id: scope_id
});
});
});

@ -1 +1 @@
Subproject commit 469d17bceeed65373da3ac3b4f96600dfea8ca68
Subproject commit 407f346eb8118d57b43035ef0da47e2ff77ed00e