mirror of https://github.com/MISP/misp-dashboard
new+chg: [livelog] Added basic filtering capabilities and fullscreen mode
Also, Improved table, reconnection mechanism and UIpull/82/head
parent
1e91b9b59c
commit
97a9465915
|
@ -43,7 +43,7 @@ class Live_helper:
|
||||||
jentry = json.loads(entry.decode('utf8'))
|
jentry = json.loads(entry.decode('utf8'))
|
||||||
to_ret.append(jentry)
|
to_ret.append(jentry)
|
||||||
return to_ret
|
return to_ret
|
||||||
|
|
||||||
|
|
||||||
def add_to_stream_log_cache(self, cacheKey, item):
|
def add_to_stream_log_cache(self, cacheKey, item):
|
||||||
rKey = self.prefix_redis_key+cacheKey
|
rKey = self.prefix_redis_key+cacheKey
|
||||||
|
|
98
server.py
98
server.py
|
@ -68,10 +68,10 @@ class LogItem():
|
||||||
FIELDNAME_ORDER_HEADER.append(item)
|
FIELDNAME_ORDER_HEADER.append(item)
|
||||||
FIELDNAME_ORDER.append(item)
|
FIELDNAME_ORDER.append(item)
|
||||||
|
|
||||||
def __init__(self, feed):
|
def __init__(self, feed, filters={}):
|
||||||
|
self.filters = filters
|
||||||
|
self.feed = feed
|
||||||
self.fields = []
|
self.fields = []
|
||||||
for f in feed:
|
|
||||||
self.fields.append(f)
|
|
||||||
|
|
||||||
def get_head_row(self):
|
def get_head_row(self):
|
||||||
to_ret = []
|
to_ret = []
|
||||||
|
@ -80,38 +80,70 @@ class LogItem():
|
||||||
return to_ret
|
return to_ret
|
||||||
|
|
||||||
def get_row(self):
|
def get_row(self):
|
||||||
|
if not self.pass_filter():
|
||||||
|
return False
|
||||||
|
|
||||||
to_ret = {}
|
to_ret = {}
|
||||||
#Number to keep them sorted (jsonify sort keys)
|
for i, field in enumerate(json.loads(cfg.get('Dashboard', 'fieldname_order'))):
|
||||||
for item in range(len(LogItem.FIELDNAME_ORDER)):
|
if type(field) is list:
|
||||||
try:
|
to_join = []
|
||||||
to_ret[item] = self.fields[item]
|
for subField in field:
|
||||||
except IndexError: # not enough field in rcv item
|
to_join.append(str(util.getFields(self.feed, subField)))
|
||||||
to_ret[item] = ''
|
to_add = cfg.get('Dashboard', 'char_separator').join(to_join)
|
||||||
|
else:
|
||||||
|
to_add = util.getFields(self.feed, field)
|
||||||
|
to_ret[i] = to_add if to_add is not None else ''
|
||||||
|
|
||||||
return to_ret
|
return to_ret
|
||||||
|
|
||||||
|
|
||||||
|
def pass_filter(self):
|
||||||
|
for filter, filterValue in self.filters.items():
|
||||||
|
jsonValue = util.getFields(self.feed, filter)
|
||||||
|
if jsonValue is None or jsonValue != filterValue:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
class EventMessage():
|
class EventMessage():
|
||||||
# Suppose the event message is a json with the format {name: 'feedName', log:'logData'}
|
# Suppose the event message is a json with the format {name: 'feedName', log:'logData'}
|
||||||
def __init__(self, msg):
|
def __init__(self, msg, filters):
|
||||||
msg = msg.decode('utf8')
|
if not isinstance(msg, dict):
|
||||||
try:
|
msg = msg.decode('utf8')
|
||||||
jsonMsg = json.loads(msg)
|
try:
|
||||||
except json.JSONDecodeError as e:
|
jsonMsg = json.loads(msg)
|
||||||
logger.error(e)
|
jsonMsg['log'] = json.loads(jsonMsg['log'])
|
||||||
jsonMsg = { 'name': "undefined" ,'log': json.loads(msg) }
|
except json.JSONDecodeError as e:
|
||||||
|
logger.error(e)
|
||||||
|
jsonMsg = { 'name': "undefined" ,'log': json.loads(msg) }
|
||||||
|
else:
|
||||||
|
jsonMsg = msg
|
||||||
|
|
||||||
self.name = jsonMsg['name']
|
self.name = jsonMsg['name']
|
||||||
self.zmqName = jsonMsg['zmqName']
|
self.zmqName = jsonMsg['zmqName']
|
||||||
self.feed = json.loads(jsonMsg['log'])
|
if self.name == 'Attribute':
|
||||||
self.feed = LogItem(self.feed).get_row()
|
self.feed = jsonMsg['log']
|
||||||
|
self.feed = LogItem(self.feed, filters).get_row()
|
||||||
|
else:
|
||||||
|
self.feed = jsonMsg['log']
|
||||||
|
|
||||||
def to_json_ev(self):
|
def to_json_ev(self):
|
||||||
to_ret = { 'log': self.feed, 'name': self.name, 'zmqName': self.zmqName }
|
if self.feed is not False:
|
||||||
return 'data: {}\n\n'.format(json.dumps(to_ret))
|
to_ret = { 'log': self.feed, 'name': self.name, 'zmqName': self.zmqName }
|
||||||
|
return 'data: {}\n\n'.format(json.dumps(to_ret))
|
||||||
|
else:
|
||||||
|
return ''
|
||||||
|
|
||||||
def to_json(self):
|
def to_json(self):
|
||||||
to_ret = { 'log': self.feed, 'name': self.name, 'zmqName': self.zmqName }
|
if self.feed is not False:
|
||||||
return json.dumps(to_ret)
|
to_ret = { 'log': self.feed, 'name': self.name, 'zmqName': self.zmqName }
|
||||||
|
return json.dumps(to_ret)
|
||||||
|
else:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
def to_dict(self):
|
||||||
|
return {'log': self.feed, 'name': self.name, 'zmqName': self.zmqName}
|
||||||
|
|
||||||
|
|
||||||
###########
|
###########
|
||||||
## ROUTE ##
|
## ROUTE ##
|
||||||
|
@ -226,9 +258,18 @@ def logs():
|
||||||
if request.accept_mimetypes.accept_json or request.method == 'POST':
|
if request.accept_mimetypes.accept_json or request.method == 'POST':
|
||||||
key = 'Attribute'
|
key = 'Attribute'
|
||||||
j = live_helper.get_stream_log_cache(key)
|
j = live_helper.get_stream_log_cache(key)
|
||||||
return jsonify(j)
|
to_ret = []
|
||||||
|
for item in j:
|
||||||
|
filters = request.cookies.get('filters', '{}')
|
||||||
|
filters = json.loads(filters)
|
||||||
|
ev = EventMessage(item, filters)
|
||||||
|
if ev is not None:
|
||||||
|
dico = ev.to_dict()
|
||||||
|
if dico['log'] != False:
|
||||||
|
to_ret.append(dico)
|
||||||
|
return jsonify(to_ret)
|
||||||
else:
|
else:
|
||||||
return Response(event_stream_log(), mimetype="text/event-stream")
|
return Response(stream_with_context(event_stream_log()), mimetype="text/event-stream")
|
||||||
|
|
||||||
@app.route("/_maps")
|
@app.route("/_maps")
|
||||||
def maps():
|
def maps():
|
||||||
|
@ -248,9 +289,14 @@ def event_stream_log():
|
||||||
subscriber_log.subscribe(live_helper.CHANNEL)
|
subscriber_log.subscribe(live_helper.CHANNEL)
|
||||||
try:
|
try:
|
||||||
for msg in subscriber_log.listen():
|
for msg in subscriber_log.listen():
|
||||||
|
filters = request.cookies.get('filters', '{}')
|
||||||
|
filters = json.loads(filters)
|
||||||
content = msg['data']
|
content = msg['data']
|
||||||
ev = EventMessage(content)
|
ev = EventMessage(content, filters)
|
||||||
yield ev.to_json_ev()
|
if ev is not None:
|
||||||
|
yield ev.to_json_ev()
|
||||||
|
else:
|
||||||
|
pass
|
||||||
except GeneratorExit:
|
except GeneratorExit:
|
||||||
subscriber_log.unsubscribe()
|
subscriber_log.unsubscribe()
|
||||||
|
|
||||||
|
|
|
@ -170,52 +170,67 @@ var curNumLog = 0;
|
||||||
var curMaxDataNumLog = 0;
|
var curMaxDataNumLog = 0;
|
||||||
var source_log;
|
var source_log;
|
||||||
|
|
||||||
function connect_source_log() {
|
// function connect_source_log() {
|
||||||
source_log = new EventSource(urlForLogs);
|
// source_log = new EventSource(urlForLogs);
|
||||||
|
//
|
||||||
source_log.onopen = function(){
|
// source_log.onopen = function(){
|
||||||
//console.log('connection is opened. '+source_log.readyState);
|
// //console.log('connection is opened. '+source_log.readyState);
|
||||||
};
|
// };
|
||||||
|
//
|
||||||
source_log.onerror = function(){
|
// source_log.onerror = function(){
|
||||||
console.log('error: '+source_log.readyState);
|
// console.log('error: '+source_log.readyState);
|
||||||
setTimeout(function() { connect_source_log(); }, 5000);
|
// setTimeout(function() { connect_source_log(); }, 5000);
|
||||||
};
|
// };
|
||||||
|
//
|
||||||
source_log.onmessage = function(event) {
|
// source_log.onmessage = function(event) {
|
||||||
var json = jQuery.parseJSON( event.data );
|
// var json = jQuery.parseJSON( event.data );
|
||||||
updateLogTable(json.name, json.log, json.zmqName);
|
// updateLogTable(json.name, json.log, json.zmqName);
|
||||||
};
|
// };
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
var livelog;
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
createHead(function() {
|
// createHead(function() {
|
||||||
if (!!window.EventSource) {
|
// if (!!window.EventSource) {
|
||||||
$.getJSON( urlForLogs, function( data ) {
|
// $.getJSON( urlForLogs, function( data ) {
|
||||||
data.forEach(function(item) {
|
// data.forEach(function(item) {
|
||||||
updateLogTable(item.name, item.log, item.zmqName);
|
// updateLogTable(item.name, item.log, item.zmqName);
|
||||||
});
|
// });
|
||||||
connect_source_log();
|
// connect_source_log();
|
||||||
});
|
// });
|
||||||
} else {
|
// } else {
|
||||||
console.log("No event source_log");
|
// console.log("No event source_log");
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
|
// });
|
||||||
|
|
||||||
|
$.getJSON(urlForHead, function(head) {
|
||||||
|
livelog = new $.livelog($("#divLogTable"), {
|
||||||
|
pollingFrequency: 5000,
|
||||||
|
tableHeader: head,
|
||||||
|
tableMaxEntries: 50,
|
||||||
|
animate: false,
|
||||||
|
preDataURL: urlForLogs,
|
||||||
|
endpoint: urlForLogs
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// LOG TABLE
|
// LOG TABLE
|
||||||
function updateLogTable(name, log, zmqName) {
|
function updateLogTable(name, log, zmqName, ignoreLed) {
|
||||||
if (log.length == 0)
|
if (log.length == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// update keepAlives
|
// update keepAlives
|
||||||
ledmanager.updateKeepAlive(zmqName);
|
if (ignoreLed !== true) {
|
||||||
|
ledmanager.updateKeepAlive(zmqName);
|
||||||
|
}
|
||||||
|
|
||||||
// Create new row
|
// Create new row
|
||||||
tableBody = document.getElementById('table_log_body');
|
// tableBody = document.getElementById('table_log_body');
|
||||||
|
|
||||||
// only add row for attribute
|
// only add row for attribute
|
||||||
if (name == "Attribute" ) {
|
if (name == "Attribute" ) {
|
||||||
|
@ -224,12 +239,12 @@ function updateLogTable(name, log, zmqName) {
|
||||||
sources.incCountOnSource(categName);
|
sources.incCountOnSource(categName);
|
||||||
sources.incCountOnSource('global');
|
sources.incCountOnSource('global');
|
||||||
updateChartDirect();
|
updateChartDirect();
|
||||||
createRow(tableBody, log);
|
// createRow(tableBody, log);
|
||||||
|
|
||||||
// Remove old row
|
// Remove old row
|
||||||
while ($("#table_log").height() >= $("#panelLogTable").height()-26){ //26 for margin
|
// while ($("#table_log").height() >= $("#panelLogTable").height()-26){ //26 for margin
|
||||||
tableBody.deleteRow(0);
|
// tableBody.deleteRow(0);
|
||||||
}
|
// }
|
||||||
|
|
||||||
} else if (name == "Keepalive") {
|
} else if (name == "Keepalive") {
|
||||||
// do nothing
|
// do nothing
|
||||||
|
@ -264,23 +279,6 @@ function getTextColour(rgb) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addObjectToLog(name, obj, td) {
|
|
||||||
if(name == "Tag") {
|
|
||||||
var a = document.createElement('A');
|
|
||||||
a.classList.add('tagElem');
|
|
||||||
a.style.backgroundColor = obj.colour;
|
|
||||||
a.style.color = getTextColour(obj.colour.substring(1,6));
|
|
||||||
a.innerHTML = obj.name;
|
|
||||||
td.appendChild(a);
|
|
||||||
td.appendChild(document.createElement('br'));
|
|
||||||
} else if (name == "mispObject") {
|
|
||||||
td.appendChild(document.createTextNode('mispObj'));
|
|
||||||
} else {
|
|
||||||
td.appendChild(document.createTextNode('nop'));
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function createRow(tableBody, log) {
|
function createRow(tableBody, log) {
|
||||||
var tr = document.createElement('TR');
|
var tr = document.createElement('TR');
|
||||||
|
|
||||||
|
@ -338,3 +336,554 @@ function createHead(callback) {
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* LIVE LOG */
|
||||||
|
(function(factory) {
|
||||||
|
"use strict";
|
||||||
|
if (typeof define === 'function' && define.amd) {
|
||||||
|
define(['jquery'], factory);
|
||||||
|
} else if (window.jQuery && !window.jQuery.fn.Livelog) {
|
||||||
|
factory(window.jQuery);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(function($) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// Livelog object
|
||||||
|
var Livelog = function(container, options) {
|
||||||
|
this._default_options = {
|
||||||
|
pollingFrequency: 5000,
|
||||||
|
tableHeader: undefined,
|
||||||
|
tableMaxEntries: undefined,
|
||||||
|
animate: true
|
||||||
|
}
|
||||||
|
|
||||||
|
options.container = container;
|
||||||
|
|
||||||
|
this.validateOptions(options);
|
||||||
|
this._options = $.extend({}, this._default_options, options);
|
||||||
|
|
||||||
|
// create table and draw header
|
||||||
|
this.origTableOptions = {
|
||||||
|
dom: "<'row'<'col-sm-12'<'dt-toolbar-led'>>>"
|
||||||
|
+ "<'row'<'col-sm-12'tr>>",
|
||||||
|
searching: false,
|
||||||
|
paging: false,
|
||||||
|
"order": [[ 0, "desc" ]],
|
||||||
|
responsive: true,
|
||||||
|
columnDefs: [
|
||||||
|
{ targets: 0, orderable: false },
|
||||||
|
{ targets: '_all', searchable: false, orderable: false,
|
||||||
|
render: function ( data, type, row ) {
|
||||||
|
// return data +' ('+ row[3]+')';
|
||||||
|
var $toRet;
|
||||||
|
if (typeof data === 'object') {
|
||||||
|
$toRet = $('<span></span>');
|
||||||
|
data.data.forEach(function(cur, i) {
|
||||||
|
switch (data.name) {
|
||||||
|
case 'Tag':
|
||||||
|
var $tag = $('<a></a>');
|
||||||
|
$tag.addClass('tagElem');
|
||||||
|
$tag.css({
|
||||||
|
backgroundColor: cur.colour,
|
||||||
|
color: getTextColour(cur.colour.substring(1,6))
|
||||||
|
});
|
||||||
|
$tag.text(cur.name)
|
||||||
|
$toRet.append($tag);
|
||||||
|
break;
|
||||||
|
case 'mispObject':
|
||||||
|
$toRet.append('MISP Object not supported yet')
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$toRet = $toRet[0].outerHTML;
|
||||||
|
} else if (data === undefined) {
|
||||||
|
$toRet = '';
|
||||||
|
} else {
|
||||||
|
var textToAddArray = data.split(char_separator);
|
||||||
|
$toRet = '';
|
||||||
|
textToAddArray.forEach(function(e, i) {
|
||||||
|
if (i > 0) {
|
||||||
|
$toRet += '<br>' + e;
|
||||||
|
} else {
|
||||||
|
$toRet += e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return $toRet;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
this.DOMTable = $('<table class="table table-striped table-bordered" style="width:100%"></table>');
|
||||||
|
this._options.container.append(this.DOMTable);
|
||||||
|
this.origTableOptions.columns = [];
|
||||||
|
var that = this;
|
||||||
|
this._options.tableHeader.forEach(function(field) {
|
||||||
|
var th = $('<th>'+field+'</th>');
|
||||||
|
that.origTableOptions.columns.push({ title: field });
|
||||||
|
});
|
||||||
|
this.dt = this.DOMTable.DataTable(this.origTableOptions);
|
||||||
|
|
||||||
|
this.fetch_predata();
|
||||||
|
|
||||||
|
// add status led
|
||||||
|
this._ev_timer = null;
|
||||||
|
this._ev_retry_frequency = this._options.pollingFrequency; // sec
|
||||||
|
this._cur_ev_retry_count = 0;
|
||||||
|
this._ev_retry_count_thres = 3;
|
||||||
|
var led_container = $('<div class="led-container" style="margin-left: 10px;"></div>');
|
||||||
|
var led = $('<div class="led-small led_red"></div>');
|
||||||
|
this.statusLed = led;
|
||||||
|
led_container.append(led);
|
||||||
|
var header = this._options.container.parent().parent().find('.panel-heading');
|
||||||
|
|
||||||
|
if (header.length > 0) { // add in panel header
|
||||||
|
header.append(led_container);
|
||||||
|
} else { // add over the map
|
||||||
|
// this._options.container.append(led_container);
|
||||||
|
led.css('display', 'inline-block');
|
||||||
|
led_container.append($('<span>Status</span>')).css('float', 'left');
|
||||||
|
$('.dt-toolbar-led').append(led_container)
|
||||||
|
}
|
||||||
|
this.data_source = undefined;
|
||||||
|
|
||||||
|
this.connect_to_data_source();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
Livelog.prototype = {
|
||||||
|
constructor: Livelog,
|
||||||
|
|
||||||
|
validateOptions: function(options) {
|
||||||
|
var o = options;
|
||||||
|
|
||||||
|
if (o.endpoint === undefined || typeof o.endpoint != 'string') {
|
||||||
|
throw "Livelog must have a valid endpoint";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (o.container === undefined) {
|
||||||
|
throw "Livelog must have a container";
|
||||||
|
} else {
|
||||||
|
o.container = o.container instanceof jQuery ? o.container : $('#'+o.container);
|
||||||
|
}
|
||||||
|
|
||||||
|
// pre-data is either the data to be shown or an URL from which the data should be taken from
|
||||||
|
if (Array.isArray(o.preData)){
|
||||||
|
o.preDataURL = null;
|
||||||
|
o.preData = o.preData;
|
||||||
|
} else if (o.preData !== undefined) { // should fetch
|
||||||
|
o.preDataURL = o.preData;
|
||||||
|
o.preData = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (o.tableHeader === undefined || !Array.isArray(o.tableHeader)) {
|
||||||
|
throw "Livelog must have a valid header";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (o.tableMaxEntries !== undefined) {
|
||||||
|
o.tableMaxEntries = parseInt(o.tableMaxEntries);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
fetch_predata: function() {
|
||||||
|
var that = this;
|
||||||
|
if (this._options.preDataURL !== null) {
|
||||||
|
$.when(
|
||||||
|
$.ajax({
|
||||||
|
dataType: "json",
|
||||||
|
url: this._options.preDataURL,
|
||||||
|
data: this._options.additionalOptions,
|
||||||
|
success: function(data) {
|
||||||
|
that._options.preData = data;
|
||||||
|
},
|
||||||
|
error: function(jqXHR, textStatus, errorThrown) {
|
||||||
|
console.log(textStatus);
|
||||||
|
that._options.preData = [];
|
||||||
|
}
|
||||||
|
})
|
||||||
|
).then(
|
||||||
|
function() { // success
|
||||||
|
// add data to the widget
|
||||||
|
that._options.preData.forEach(function(j) {
|
||||||
|
var name = j.name,
|
||||||
|
zmqName = j.zmqName,
|
||||||
|
entry = j.log;
|
||||||
|
updateLogTable(name, entry, zmqName, true);
|
||||||
|
switch (name) {
|
||||||
|
case 'Attribute':
|
||||||
|
that.add_entry(entry);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, function() { // fail
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
connect_to_data_source: function() {
|
||||||
|
var that = this;
|
||||||
|
if (!this.data_source) {
|
||||||
|
// var url_param = $.param( this.additionalOptions );
|
||||||
|
this.data_source = new EventSource(this._options.endpoint);
|
||||||
|
this.data_source.onmessage = function(event) {
|
||||||
|
var json = jQuery.parseJSON( event.data );
|
||||||
|
var name = json.name,
|
||||||
|
zmqName = json.zmqName,
|
||||||
|
entry = json.log;
|
||||||
|
updateLogTable(name, entry, zmqName);
|
||||||
|
switch (name) {
|
||||||
|
case 'Attribute':
|
||||||
|
that.add_entry(entry);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.data_source.onopen = function(){
|
||||||
|
that._cur_ev_retry_count = 0;
|
||||||
|
that.update_connection_state('connected');
|
||||||
|
};
|
||||||
|
this.data_source.onerror = function(){
|
||||||
|
if (that.data_source.readyState == 0) { // reconnecting
|
||||||
|
that.update_connection_state('connecting');
|
||||||
|
} else if (that.data_source.readyState == 2) { // closed, reconnect with new object
|
||||||
|
that.reconnection_logique();
|
||||||
|
} else {
|
||||||
|
that.update_connection_state('not connected');
|
||||||
|
that.reconnection_logique();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
reconnection_logique: function () {
|
||||||
|
var that = this;
|
||||||
|
if (that.data_source) {
|
||||||
|
that.data_source.close();
|
||||||
|
that.data_source = null;
|
||||||
|
}
|
||||||
|
if (that._ev_timer) {
|
||||||
|
clearTimeout(that._ev_timer);
|
||||||
|
}
|
||||||
|
if(that._cur_ev_retry_count >= that._ev_retry_count_thres) {
|
||||||
|
that.update_connection_state('not connected');
|
||||||
|
} else {
|
||||||
|
that._cur_ev_retry_count++;
|
||||||
|
that.update_connection_state('connecting');
|
||||||
|
}
|
||||||
|
that._ev_timer = setTimeout(function () { that.connect_to_data_source(); }, that._ev_retry_frequency*1000);
|
||||||
|
},
|
||||||
|
|
||||||
|
reconnect: function() {
|
||||||
|
if (this.data_source) {
|
||||||
|
this.data_source.close();
|
||||||
|
this.data_source = null;
|
||||||
|
this._cur_ev_retry_count = 0;
|
||||||
|
this.update_connection_state('reconnecting');
|
||||||
|
this.connect_to_data_source();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
update_connection_state: function(connectionState) {
|
||||||
|
this.connectionState = connectionState;
|
||||||
|
this.updateDOMState(this.statusLed, connectionState);
|
||||||
|
},
|
||||||
|
|
||||||
|
updateDOMState: function(led, state) {
|
||||||
|
switch (state) {
|
||||||
|
case 'connected':
|
||||||
|
led.removeClass("led_red");
|
||||||
|
led.removeClass("led_orange");
|
||||||
|
led.addClass("led_green");
|
||||||
|
break;
|
||||||
|
case 'not connected':
|
||||||
|
led.removeClass("led_green");
|
||||||
|
led.removeClass("led_orange");
|
||||||
|
led.addClass("led_red");
|
||||||
|
break;
|
||||||
|
case 'connecting':
|
||||||
|
led.removeClass("led_green");
|
||||||
|
led.removeClass("led_red");
|
||||||
|
led.addClass("led_orange");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
led.removeClass("led_green");
|
||||||
|
led.removeClass("led_orange");
|
||||||
|
led.addClass("led_red");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
add_entry: function(entry) {
|
||||||
|
var rowNode = this.dt.row.add(entry).draw().node();
|
||||||
|
if (this.animate) {
|
||||||
|
$( rowNode )
|
||||||
|
.css( 'background-color', '#5cb85c' )
|
||||||
|
.animate( { 'background-color': '', duration: 600 } );
|
||||||
|
}
|
||||||
|
// this.dt.row.add(entry).draw( false );
|
||||||
|
// remove entries
|
||||||
|
var numRows = this.dt.rows().count();
|
||||||
|
var rowsToRemove = numRows - this._options.tableMaxEntries;
|
||||||
|
if (rowsToRemove > 0 && this._options.tableMaxEntries != -1) {
|
||||||
|
//get row indexes as an array
|
||||||
|
var arraySlice = this.dt.rows().indexes().toArray();
|
||||||
|
//get row indexes to remove starting at row 0
|
||||||
|
arraySlice = arraySlice.slice(-rowsToRemove);
|
||||||
|
//remove the rows and redraw the table
|
||||||
|
var rows = this.dt.rows(arraySlice).remove().draw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$.livelog = Livelog;
|
||||||
|
$.fn.livelog = function(option) {
|
||||||
|
var pickerArgs = arguments;
|
||||||
|
|
||||||
|
return this.each(function() {
|
||||||
|
var $this = $(this),
|
||||||
|
inst = $this.data('livelog'),
|
||||||
|
options = ((typeof option === 'object') ? option : {});
|
||||||
|
if ((!inst) && (typeof option !== 'string')) {
|
||||||
|
$this.data('livelog', new Livelog(this, options));
|
||||||
|
} else {
|
||||||
|
if (typeof option === 'string') {
|
||||||
|
inst[option].apply(inst, Array.prototype.slice.call(pickerArgs, 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$.fn.livelog.constructor = Livelog;
|
||||||
|
|
||||||
|
}));
|
||||||
|
|
||||||
|
// ### ///
|
||||||
|
// ### ///
|
||||||
|
// ### ///
|
||||||
|
// ### ///
|
||||||
|
// ### ///
|
||||||
|
// ### ///
|
||||||
|
|
||||||
|
function recursiveInject(result, rules, isNot) {
|
||||||
|
if (rules.rules === undefined) { // add to result
|
||||||
|
var field = rules.field;
|
||||||
|
var value = rules.value;
|
||||||
|
var operator_notequal = rules.operator === 'not_equal' ? true : false;
|
||||||
|
var negate = isNot ^ operator_notequal;
|
||||||
|
value = negate ? '!' + value : value;
|
||||||
|
if (result.hasOwnProperty(field)) {
|
||||||
|
if (Array.isArray(result[field])) {
|
||||||
|
result[field].push(value);
|
||||||
|
} else {
|
||||||
|
result[field] = [result[field], value];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result[field] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (Array.isArray(rules.rules)) {
|
||||||
|
rules.rules.forEach(function(subrules) {
|
||||||
|
recursiveInject(result, subrules, isNot ^ rules.not) ;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function cleanRules(rules) {
|
||||||
|
var res = {};
|
||||||
|
recursiveInject(res, rules);
|
||||||
|
// clean up invalid and unset
|
||||||
|
Object.keys(res).forEach(function(k) {
|
||||||
|
var v = res[k];
|
||||||
|
if (v === undefined || v === '') {
|
||||||
|
delete res[k];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
var qbOptions = {
|
||||||
|
plugins: {
|
||||||
|
'filter-description' : {
|
||||||
|
mode: 'inline'
|
||||||
|
},
|
||||||
|
'unique-filter': null,
|
||||||
|
'bt-tooltip-errors': null,
|
||||||
|
},
|
||||||
|
allow_empty: true,
|
||||||
|
// lang: {
|
||||||
|
// operators: {
|
||||||
|
// equal: 'show',
|
||||||
|
// in: 'show'
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
filters: [],
|
||||||
|
rules: {
|
||||||
|
condition: 'AND',
|
||||||
|
not: false,
|
||||||
|
rules: [],
|
||||||
|
flags: {
|
||||||
|
no_add_group: true,
|
||||||
|
condition_readonly: true,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
icons: {
|
||||||
|
add_group: 'fa fa-plus-square',
|
||||||
|
add_rule: 'fa fa-plus-circle',
|
||||||
|
remove_group: 'fa fa-minus-square',
|
||||||
|
remove_rule: 'fa fa-minus-circle',
|
||||||
|
error: 'fa fa-exclamation-triangle'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// add filters and rules
|
||||||
|
[
|
||||||
|
'Attribute.category',
|
||||||
|
'Attribute.comment',
|
||||||
|
'Attribute.deleted',
|
||||||
|
'Attribute.disable_correlation',
|
||||||
|
'Attribute.distribution',
|
||||||
|
'Attribute.event_id',
|
||||||
|
'Attribute.id',
|
||||||
|
'Attribute.object_id',
|
||||||
|
'Attribute.object_relation',
|
||||||
|
'Attribute.sharing_group_id',
|
||||||
|
'Attribute.Tag.name',
|
||||||
|
'Attribute.timestamp',
|
||||||
|
'Attribute.to_ids',
|
||||||
|
'Attribute.type',
|
||||||
|
'Attribute.uuid',
|
||||||
|
'Attribute.value',
|
||||||
|
'Event.Org',
|
||||||
|
'Event.Orgc',
|
||||||
|
'Event.analysis',
|
||||||
|
'Event.attribute_count',
|
||||||
|
'Event.date',
|
||||||
|
'Event.disable_correlation',
|
||||||
|
'Event.distribution',
|
||||||
|
'Event.event_creator_email',
|
||||||
|
'Event.extends_uuid',
|
||||||
|
'Event.id',
|
||||||
|
'Event.info',
|
||||||
|
'Event.locked',
|
||||||
|
'Event.org_id',
|
||||||
|
'Event.orgc_id',
|
||||||
|
'Event.proposal_email_lock',
|
||||||
|
'Event.publish_timestamp',
|
||||||
|
'Event.published',
|
||||||
|
'Event.sharing_group_id',
|
||||||
|
'Event.threat_level_id',
|
||||||
|
'Event.Tag.name',
|
||||||
|
'Event.timestamp',
|
||||||
|
'Event.uuid',
|
||||||
|
'Org.id',
|
||||||
|
'Org.name',
|
||||||
|
'Org.uuid',
|
||||||
|
'Orgc.id',
|
||||||
|
'Orgc.name',
|
||||||
|
'Orgc.uuid'
|
||||||
|
].forEach(function(field) {
|
||||||
|
var tempFilter = {
|
||||||
|
"input": "text",
|
||||||
|
"type": "string",
|
||||||
|
"operators": [
|
||||||
|
"equal",
|
||||||
|
"not_equal"
|
||||||
|
],
|
||||||
|
"unique": true,
|
||||||
|
"id": field,
|
||||||
|
"label": field,
|
||||||
|
"description": "Perfom strict equality on " + field,
|
||||||
|
"validation": {
|
||||||
|
"allow_empty_value": true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
qbOptions.filters.push(tempFilter);
|
||||||
|
});
|
||||||
|
|
||||||
|
var filterCookie = getCookie('filters');
|
||||||
|
var filters = JSON.parse(filterCookie !== undefined && filterCookie !== '' ? filterCookie : "{}");
|
||||||
|
var activeFilters = Object.keys(filters)
|
||||||
|
var tempRule = [];
|
||||||
|
activeFilters.forEach(function(field) {
|
||||||
|
var v = filters[field];
|
||||||
|
var tmp = {
|
||||||
|
field: field,
|
||||||
|
id: field,
|
||||||
|
value: v
|
||||||
|
};
|
||||||
|
tempRule.push(tmp);
|
||||||
|
});
|
||||||
|
qbOptions.rules.rules = tempRule;
|
||||||
|
updateFilterButton(activeFilters);
|
||||||
|
|
||||||
|
var $ev = $('#filteringQB');
|
||||||
|
var querybuilderTool = $ev.queryBuilder(qbOptions);
|
||||||
|
querybuilderTool = querybuilderTool[0].queryBuilder;
|
||||||
|
|
||||||
|
$('#saveFilters').click(function() {
|
||||||
|
var rules = querybuilderTool.getRules({ skip_empty: true, allow_invalid: true });
|
||||||
|
var result = {};
|
||||||
|
recursiveInject(result, rules, false);
|
||||||
|
updateFilterButton(Object.keys(result));
|
||||||
|
var jres = JSON.stringify(result, null);
|
||||||
|
document.cookie = 'filters=' + jres;
|
||||||
|
$('#modalFilters').modal('hide');
|
||||||
|
livelog.dt
|
||||||
|
.clear()
|
||||||
|
.draw();
|
||||||
|
livelog.fetch_predata();
|
||||||
|
livelog.reconnect();
|
||||||
|
})
|
||||||
|
|
||||||
|
$('#log-fullscreen').click(function() {
|
||||||
|
var $this = $(this);
|
||||||
|
var $panel = $('#panelLogTable');
|
||||||
|
var isfullscreen = $this.data('isfullscreen');
|
||||||
|
if (isfullscreen === undefined || !isfullscreen) {
|
||||||
|
$panel.detach().prependTo('#page-wrapper')
|
||||||
|
$panel.addClass('liveLogFullScreen');
|
||||||
|
$this.data('isfullscreen', true);
|
||||||
|
} else {
|
||||||
|
$panel.detach().appendTo('#rightCol')
|
||||||
|
$panel.removeClass('liveLogFullScreen');
|
||||||
|
$this.data('isfullscreen', false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
function updateFilterButton(activeFilters) {
|
||||||
|
if (activeFilters.length > 0) {
|
||||||
|
$('#log-filter').removeClass('btn-default');
|
||||||
|
$('#log-filter').addClass('btn-success');
|
||||||
|
} else {
|
||||||
|
$('#log-filter').removeClass('btn-success');
|
||||||
|
$('#log-filter').addClass('btn-default');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCookie(cname) {
|
||||||
|
var name = cname + "=";
|
||||||
|
var decodedCookie = decodeURIComponent(document.cookie);
|
||||||
|
var ca = decodedCookie.split(';');
|
||||||
|
for(var i = 0; i <ca.length; i++) {
|
||||||
|
var c = ca[i];
|
||||||
|
while (c.charAt(0) == ' ') {
|
||||||
|
c = c.substring(1);
|
||||||
|
}
|
||||||
|
if (c.indexOf(name) == 0) {
|
||||||
|
return c.substring(name.length, c.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
|
@ -24,9 +24,28 @@
|
||||||
<script src="{{ url_for('static', filename='js/jquery.flot.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/jquery.flot.js') }}"></script>
|
||||||
<script src="{{ url_for('static', filename='js/jquery.flot.pie.min.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/jquery.flot.pie.min.js') }}"></script>
|
||||||
<script src="{{ url_for('static', filename='js/jquery.flot.resize.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/jquery.flot.resize.js') }}"></script>
|
||||||
|
|
||||||
|
<script src="{{ url_for('static', filename='js/jquery-ui.min.js') }}"></script>
|
||||||
|
<link href="{{ url_for('static', filename='css/jquery-ui.css') }}" type="text/css" rel="stylesheet">
|
||||||
|
|
||||||
<!-- Bootstrap Core JavaScript -->
|
<!-- Bootstrap Core JavaScript -->
|
||||||
<script src="{{ url_for('static', filename='js/bootstrap.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/bootstrap.js') }}"></script>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/jquery.dataTables.min.css') }}">
|
||||||
|
<script src="{{ url_for('static', filename='js/jquery.dataTables.min.js') }}"></script>
|
||||||
|
|
||||||
|
<link href="{{ url_for('static', filename='css/font-awesome.min.css') }}" type="text/css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/jquery-jvectormap-2.0.3.css') }}" type="text/css" media="screen"/>
|
||||||
|
<script src="{{ url_for('static', filename='js/jquery-jvectormap-2.0.3.min.js') }}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/jquery-jvectormap-world-mill.js') }}"></script>
|
||||||
|
|
||||||
|
|
||||||
|
<script src="{{ url_for('static', filename='js/doT.js') }}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/extendext.js') }}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/moment-with-locales.js') }}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/query-builder.js') }}"></script>
|
||||||
|
<link href="{{ url_for('static', filename='css/query-builder.default.css') }}" type="text/css" rel="stylesheet">
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -42,8 +61,9 @@
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
line-height: 14px;
|
line-height: 14px;
|
||||||
border-bottom-left-radius: 3px;
|
border-radius: 3px;
|
||||||
box-shadow: 3px 3px 3px #888888;
|
box-shadow: 3px 3px 3px #888888;
|
||||||
|
margin: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
table {
|
table {
|
||||||
|
@ -123,6 +143,56 @@ small {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.led_green {
|
||||||
|
background-color: #ABFF00;
|
||||||
|
box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #304701 0 -1px 6px, #89FF00 0 0px 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.led_red {
|
||||||
|
background-color: #F82222;
|
||||||
|
box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #304701 0 -1px 6px, #FF0303 0 0px 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.led_orange {
|
||||||
|
background-color: #FFB400;
|
||||||
|
box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #304701 0 -1px 6px, #FF9000 0 0px 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.led-small {
|
||||||
|
margin: auto auto;
|
||||||
|
margin-top: 6px;
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.led-container {
|
||||||
|
text-align: center;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.led-container > span {
|
||||||
|
margin: auto 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.dataTables_scrollHead table.dataTable {
|
||||||
|
margin-top: 0px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dataTables_scrollBody thead tr {
|
||||||
|
visibility: collapse !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.liveLogFullScreen {
|
||||||
|
position: absolute !important;
|
||||||
|
top: 66px !important;
|
||||||
|
left: 15px !important;
|
||||||
|
right: 10px !important;
|
||||||
|
z-index: 1001 !important;
|
||||||
|
bottom: 5px !important;
|
||||||
|
height: unset !important;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -198,7 +268,7 @@ small {
|
||||||
</div>
|
</div>
|
||||||
<!-- /.col-lg-6 -->
|
<!-- /.col-lg-6 -->
|
||||||
<!-- /.col-lg-6 -->
|
<!-- /.col-lg-6 -->
|
||||||
<div class="col-lg-{{ size_dashboard_width[1] }}">
|
<div id="rightCol" class="col-lg-{{ size_dashboard_width[1] }}">
|
||||||
|
|
||||||
<div class="panel panel-default" style="margin-top: 15px; height: {{ pannelSize[2] }}vh;">
|
<div class="panel panel-default" style="margin-top: 15px; height: {{ pannelSize[2] }}vh;">
|
||||||
<div id="panelbody" class="panel-body" style="height: 100%;">
|
<div id="panelbody" class="panel-body" style="height: 100%;">
|
||||||
|
@ -212,23 +282,12 @@ small {
|
||||||
<div id="panelLogTable" class="panel panel-default" style="height: {{ pannelSize[3] }}vh;">
|
<div id="panelLogTable" class="panel panel-default" style="height: {{ pannelSize[3] }}vh;">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<i class="fa fa-tasks fa-fw"></i> Logs
|
<i class="fa fa-tasks fa-fw"></i> Logs
|
||||||
<div class="pull-right">
|
<div style="display: inline-block; float: right;">
|
||||||
<input id="checkbox_log_info" type="checkbox" value="info"> INFO
|
<button id="log-filter" data-toggle="modal" data-target="#modalFilters" class="btn btn-xs btn-default" ><i class="fa fa-filter"></i></button>
|
||||||
<input id="checkbox_log_warning" type="checkbox" value="warning" checked="true"> WARNING
|
<button id="log-fullscreen" class="btn btn-xs btn-default"><i class="fa fa-expand"></i></button>
|
||||||
<input id="checkbox_log_critical" type="checkbox" value="critical" checked="true"> CRITICAL
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="divLogTable" class="panel-body" style="height: 98%; padding: 0px;">
|
<div id="divLogTable" class="panel-body" style="height: calc(100% - 46px); padding: 0px; overflow: hidden">
|
||||||
<div class="row" style="height: 100%;">
|
|
||||||
<div class="col-lg-12" style="height: 100%;">
|
|
||||||
<table class="table table-bordered table-hover table-striped" id="table_log">
|
|
||||||
<thead id="table_log_head">
|
|
||||||
</thead>
|
|
||||||
<tbody id="table_log_body">
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -254,6 +313,25 @@ small {
|
||||||
</div>
|
</div>
|
||||||
<!-- /#wrapper -->
|
<!-- /#wrapper -->
|
||||||
|
|
||||||
|
<!-- Modal -->
|
||||||
|
<div class="modal fade" id="modalFilters" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
|
||||||
|
<div class="modal-dialog modal-lg" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||||
|
<h4 class="modal-title" id="myModalLabel">Log filtering rules</h4>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div id="filteringQB"></div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||||
|
<button id="saveFilters" type="button" class="btn btn-primary">Save filters</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Index -->
|
<!-- Index -->
|
||||||
<script>
|
<script>
|
||||||
/* URL */
|
/* URL */
|
||||||
|
@ -299,11 +377,6 @@ small {
|
||||||
<script src="{{ url_for('static', filename='js/index/index_map.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/index/index_map.js') }}"></script>
|
||||||
<script src="{{ url_for('static', filename='js/index/index_pie.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/index/index_pie.js') }}"></script>
|
||||||
|
|
||||||
|
|
||||||
<link href="{{ url_for('static', filename='css/font-awesome.min.css') }}" rel="text/css">
|
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/jquery-jvectormap-2.0.3.css') }}" type="text/css" media="screen"/>
|
|
||||||
<script src="{{ url_for('static', filename='js/jquery-jvectormap-2.0.3.min.js') }}"></script>
|
|
||||||
<script src="{{ url_for('static', filename='js/jquery-jvectormap-world-mill.js') }}"></script>
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
19
util.py
19
util.py
|
@ -102,3 +102,22 @@ def sortByTrendingScore(toSort, topNum=5):
|
||||||
topArray.append(dailyCombi)
|
topArray.append(dailyCombi)
|
||||||
|
|
||||||
return topArray
|
return topArray
|
||||||
|
|
||||||
|
|
||||||
|
def getFields(obj, fields):
|
||||||
|
jsonWalker = fields.split('.')
|
||||||
|
itemToExplore = obj
|
||||||
|
lastName = ""
|
||||||
|
try:
|
||||||
|
for i in jsonWalker:
|
||||||
|
itemToExplore = itemToExplore[i]
|
||||||
|
lastName = i
|
||||||
|
if type(itemToExplore) is list:
|
||||||
|
return {'name': lastName, 'data': itemToExplore}
|
||||||
|
else:
|
||||||
|
if i == 'timestamp':
|
||||||
|
itemToExplore = datetime.datetime.utcfromtimestamp(
|
||||||
|
int(itemToExplore)).strftime('%Y-%m-%d %H:%M:%S')
|
||||||
|
return itemToExplore
|
||||||
|
except KeyError as e:
|
||||||
|
return None
|
||||||
|
|
|
@ -53,23 +53,6 @@ users_helper = users_helper.Users_helper(serv_redis_db, cfg)
|
||||||
trendings_helper = trendings_helper.Trendings_helper(serv_redis_db, cfg)
|
trendings_helper = trendings_helper.Trendings_helper(serv_redis_db, cfg)
|
||||||
|
|
||||||
|
|
||||||
def getFields(obj, fields):
|
|
||||||
jsonWalker = fields.split('.')
|
|
||||||
itemToExplore = obj
|
|
||||||
lastName = ""
|
|
||||||
try:
|
|
||||||
for i in jsonWalker:
|
|
||||||
itemToExplore = itemToExplore[i]
|
|
||||||
lastName = i
|
|
||||||
if type(itemToExplore) is list:
|
|
||||||
return { 'name': lastName , 'data': itemToExplore }
|
|
||||||
else:
|
|
||||||
if i == 'timestamp':
|
|
||||||
itemToExplore = datetime.datetime.utcfromtimestamp(int(itemToExplore)).strftime('%Y-%m-%d %H:%M:%S')
|
|
||||||
return itemToExplore
|
|
||||||
except KeyError as e:
|
|
||||||
return ""
|
|
||||||
|
|
||||||
##############
|
##############
|
||||||
## HANDLERS ##
|
## HANDLERS ##
|
||||||
##############
|
##############
|
||||||
|
@ -214,16 +197,6 @@ def handler_attribute(zmq_name, jsonobj, hasAlreadyBeenContributed=False):
|
||||||
pass
|
pass
|
||||||
trendings_helper.addTrendingTags(tags, timestamp)
|
trendings_helper.addTrendingTags(tags, timestamp)
|
||||||
|
|
||||||
to_push = []
|
|
||||||
for field in json.loads(cfg.get('Dashboard', 'fieldname_order')):
|
|
||||||
if type(field) is list:
|
|
||||||
to_join = []
|
|
||||||
for subField in field:
|
|
||||||
to_join.append(str(getFields(jsonobj, subField)))
|
|
||||||
to_add = cfg.get('Dashboard', 'char_separator').join(to_join)
|
|
||||||
else:
|
|
||||||
to_add = getFields(jsonobj, field)
|
|
||||||
to_push.append(to_add)
|
|
||||||
|
|
||||||
#try to get coord from ip
|
#try to get coord from ip
|
||||||
if jsonattr['category'] == "Network activity":
|
if jsonattr['category'] == "Network activity":
|
||||||
|
@ -242,7 +215,7 @@ def handler_attribute(zmq_name, jsonobj, hasAlreadyBeenContributed=False):
|
||||||
action,
|
action,
|
||||||
isLabeled=eventLabeled)
|
isLabeled=eventLabeled)
|
||||||
# Push to log
|
# Push to log
|
||||||
live_helper.publish_log(zmq_name, 'Attribute', to_push)
|
live_helper.publish_log(zmq_name, 'Attribute', jsonobj)
|
||||||
|
|
||||||
|
|
||||||
###############
|
###############
|
||||||
|
|
Loading…
Reference in New Issue