mirror of https://github.com/MISP/misp-dashboard
Added linked pie plot with server
parent
71837d3308
commit
8942a43c18
33
server.py
33
server.py
|
@ -12,6 +12,7 @@ import os
|
||||||
import util
|
import util
|
||||||
import contributor_helper
|
import contributor_helper
|
||||||
import users_helper
|
import users_helper
|
||||||
|
import trendings_helper
|
||||||
|
|
||||||
configfile = os.path.join(os.environ['DASH_CONFIG'], 'config.cfg')
|
configfile = os.path.join(os.environ['DASH_CONFIG'], 'config.cfg')
|
||||||
cfg = configparser.ConfigParser()
|
cfg = configparser.ConfigParser()
|
||||||
|
@ -34,6 +35,7 @@ serv_redis_db = redis.StrictRedis(
|
||||||
|
|
||||||
contributor_helper = contributor_helper.Contributor_helper(serv_redis_db, cfg)
|
contributor_helper = contributor_helper.Contributor_helper(serv_redis_db, cfg)
|
||||||
users_helper = users_helper.Users_helper(serv_redis_db, cfg)
|
users_helper = users_helper.Users_helper(serv_redis_db, cfg)
|
||||||
|
trendings_helper = trendings_helper.Trendings_helper(serv_redis_db, cfg)
|
||||||
|
|
||||||
subscriber_log = redis_server_log.pubsub(ignore_subscribe_messages=True)
|
subscriber_log = redis_server_log.pubsub(ignore_subscribe_messages=True)
|
||||||
subscriber_log.psubscribe(cfg.get('RedisLog', 'channel'))
|
subscriber_log.psubscribe(cfg.get('RedisLog', 'channel'))
|
||||||
|
@ -485,6 +487,37 @@ def getLoginVSCOntribution():
|
||||||
data = users_helper.getLoginVSCOntribution(date)
|
data = users_helper.getLoginVSCOntribution(date)
|
||||||
return jsonify(data)
|
return jsonify(data)
|
||||||
|
|
||||||
|
''' TRENDINGS '''
|
||||||
|
@app.route("/_getTrendingEvents")
|
||||||
|
def getTrendingEvents():
|
||||||
|
try:
|
||||||
|
date = datetime.datetime.fromtimestamp(float(request.args.get('date')))
|
||||||
|
except:
|
||||||
|
date = datetime.datetime.now()
|
||||||
|
|
||||||
|
data = trendings_helper.getTrendingEvents(date)
|
||||||
|
return jsonify(data)
|
||||||
|
|
||||||
|
@app.route("/_getTrendingCategs")
|
||||||
|
def getTrendingCategs():
|
||||||
|
try:
|
||||||
|
date = datetime.datetime.fromtimestamp(float(request.args.get('date')))
|
||||||
|
except:
|
||||||
|
date = datetime.datetime.now()
|
||||||
|
|
||||||
|
data = trendings_helper.getTrendingCategs(date)
|
||||||
|
return jsonify(data)
|
||||||
|
|
||||||
|
@app.route("/_getTrendingTags")
|
||||||
|
def getTrendingTags():
|
||||||
|
try:
|
||||||
|
date = datetime.datetime.fromtimestamp(float(request.args.get('date')))
|
||||||
|
except:
|
||||||
|
date = datetime.datetime.now()
|
||||||
|
|
||||||
|
data = trendings_helper.getTrendingTags(date)
|
||||||
|
return jsonify(data)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app.run(host='localhost', port=8001, threaded=True)
|
app.run(host='localhost', port=8001, threaded=True)
|
||||||
|
|
|
@ -1,22 +1,115 @@
|
||||||
|
/* VARS */
|
||||||
|
var date;
|
||||||
|
var eventPie = ["#eventPie"];
|
||||||
|
var eventLine = ["#eventLine"];
|
||||||
|
var categPie = ["#categPie"];
|
||||||
|
var categLine = ["#categLine"];
|
||||||
|
var tagPie = ["#tagPie"];
|
||||||
|
var tagLine = ["#tagLine"];
|
||||||
|
var sightingEventPieWidget;
|
||||||
|
var sightingCategLineWidget;
|
||||||
|
|
||||||
|
/* OPTIONS */
|
||||||
|
var datePickerOptions = {
|
||||||
|
showOn: "button",
|
||||||
|
maxDate: 0,
|
||||||
|
buttonImage: urlIconCalendar,
|
||||||
|
buttonImageOnly: true,
|
||||||
|
buttonText: "Select date",
|
||||||
|
showAnim: "slideDown",
|
||||||
|
onSelect: dateChanged
|
||||||
|
};
|
||||||
|
var lineChartOption = {
|
||||||
|
lines: {
|
||||||
|
show: true,
|
||||||
|
steps: true,
|
||||||
|
fill: true
|
||||||
|
},
|
||||||
|
xaxis: {
|
||||||
|
mode: "time",
|
||||||
|
minTickSize: [1, "day"],
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var pieChartOption = {
|
||||||
|
series: {
|
||||||
|
pie: {
|
||||||
|
innerRadius: 0.5,
|
||||||
|
show: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* FUNCTIONS */
|
||||||
|
|
||||||
|
function updatePie(pie, data) {
|
||||||
|
pieID = pie[0];
|
||||||
|
pieWidget = pie[1];
|
||||||
|
if (data === undefined || data.length == 0 || (data[0] == 0 && data[1] == 0)) {
|
||||||
|
toPlot = [{ label: 'No data', data: 100 }];
|
||||||
|
} else {
|
||||||
|
toPlot = [];
|
||||||
|
for (item of data) {
|
||||||
|
toPlot.push({label: item[0], data: item[1]});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(toPlot);
|
||||||
|
if (!(pieWidget === undefined)) {
|
||||||
|
pieWidget.setData(toPlot);
|
||||||
|
pieWidget.setupGrid();
|
||||||
|
pieWidget.draw();
|
||||||
|
} else {
|
||||||
|
pieWidget = $.plot(pieID, toPlot, pieChartOption);
|
||||||
|
pie.push(pieWidget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateLine(line, data) {
|
||||||
|
lineID = line[0];
|
||||||
|
lineWidget = line[1];
|
||||||
|
temp = [];
|
||||||
|
var i=0;
|
||||||
|
for (item of data) {
|
||||||
|
temp.push([new Date(item[0]*1000), item[1]]);
|
||||||
|
}
|
||||||
|
data = {label: 'Overtime', data: temp}
|
||||||
|
if (!(lineWidget === undefined)) {
|
||||||
|
lineWidget.setData(toPlot);
|
||||||
|
lineWidget.draw();
|
||||||
|
} else {
|
||||||
|
lineWidget = $.plot(lineID, [data], lineChartOption);
|
||||||
|
line.push(lineWidget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updatePieLine(pie, line, url) {
|
||||||
|
// format date
|
||||||
|
// var now = new Date();
|
||||||
|
// if (date.toDateString() == now.toDateString()) {
|
||||||
|
// date = now;
|
||||||
|
// } else {
|
||||||
|
// date.setTime(date.getTime() + (24*60*60*1000-1)); // include data of selected date
|
||||||
|
// }
|
||||||
|
$.getJSON( url+"?date="+parseInt(date.getTime()/1000), function( data ) {
|
||||||
|
updatePie(pie, data[0][1]);
|
||||||
|
updateLine(line, data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function dateChanged() {
|
function dateChanged() {
|
||||||
var date = datePickerWidget.datepicker( "getDate" );
|
date = datePickerWidget.datepicker( "getDate" );
|
||||||
console.log(date);
|
updatePieLine(eventPie, eventLine, url_getTrendingEvent)
|
||||||
|
updatePieLine(categPie, categLine, url_getTrendingCateg)
|
||||||
|
updatePieLine(tagPie, tagLine, url_getTrendingTag)
|
||||||
}
|
}
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
|
|
||||||
var datePickerOptions = {
|
datePickerWidget = $( "#datepicker" ).datepicker(datePickerOptions);
|
||||||
showOn: "button",
|
|
||||||
maxDate: 0,
|
|
||||||
buttonImage: urlIconCalendar,
|
|
||||||
buttonImageOnly: true,
|
|
||||||
buttonText: "Select date",
|
|
||||||
showAnim: "slideDown",
|
|
||||||
onSelect: dateChanged
|
|
||||||
};
|
|
||||||
var datePickerOptions = jQuery.extend({}, datePickerOptions);
|
|
||||||
datePickerWidget = $( "#datepicker" );
|
|
||||||
datePickerWidget.datepicker(datePickerOptions);
|
|
||||||
datePickerWidget.datepicker("setDate", new Date());
|
datePickerWidget.datepicker("setDate", new Date());
|
||||||
|
date = datePickerWidget.datepicker( "getDate" );
|
||||||
|
|
||||||
|
updatePieLine(eventPie, eventLine, url_getTrendingEvent)
|
||||||
|
updatePieLine(categPie, categLine, url_getTrendingCateg)
|
||||||
|
updatePieLine(tagPie, tagLine, url_getTrendingTag)
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -122,8 +122,9 @@ small {
|
||||||
<b>Most active events</b>
|
<b>Most active events</b>
|
||||||
</div>
|
</div>
|
||||||
<div id="panelbody" class="panel-body" style="">
|
<div id="panelbody" class="panel-body" style="">
|
||||||
<div id="eventPie" style="width:100%; height: 100%;"></div>
|
<div id="eventPie" style="width:100%; height: 15vh;"></div>
|
||||||
<div id="eventLine" style="width:100%; height: 100%;"></div>
|
<div style="height: 10px;"></div>
|
||||||
|
<div id="eventLine" style="width:100%; height: 20vh;"></div>
|
||||||
</div>
|
</div>
|
||||||
</div><!-- /.panel-body -->
|
</div><!-- /.panel-body -->
|
||||||
</div>
|
</div>
|
||||||
|
@ -134,8 +135,9 @@ small {
|
||||||
<b>Most active categories</b>
|
<b>Most active categories</b>
|
||||||
</div>
|
</div>
|
||||||
<div id="panelbody" class="panel-body" style="">
|
<div id="panelbody" class="panel-body" style="">
|
||||||
<div id="categPie" style="width:100%; height: 100%;"></div>
|
<div id="categPie" style="width:100%; height: 15vh;"></div>
|
||||||
<div id="categLine" style="width:100%; height: 100%;"></div>
|
<div style="height: 10px;"></div>
|
||||||
|
<div id="categLine" style="width:100%; height: 20vh;"></div>
|
||||||
</div>
|
</div>
|
||||||
</div><!-- /.panel-body -->
|
</div><!-- /.panel-body -->
|
||||||
</div>
|
</div>
|
||||||
|
@ -143,11 +145,12 @@ small {
|
||||||
<div class="col-lg-4">
|
<div class="col-lg-4">
|
||||||
<div class="panel panel-default" style="">
|
<div class="panel panel-default" style="">
|
||||||
<div class="panel-heading bg-info" style="font-weight: bold;">
|
<div class="panel-heading bg-info" style="font-weight: bold;">
|
||||||
<b>Popular tags</b>
|
<b>Most popular tags</b>
|
||||||
</div>
|
</div>
|
||||||
<div id="panelbody" class="panel-body" style="">
|
<div id="panelbody" class="panel-body" style="">
|
||||||
<div id="tagsPie" style="width:100%; height: 100%;"></div>
|
<div id="tagPie" style="width:100%; height: 15vh;"></div>
|
||||||
<div id="tagsLine" style="width:100%; height: 100%;"></div>
|
<div style="height: 10px;"></div>
|
||||||
|
<div id="tagLine" style="width:100%; height: 20vh;"></div>
|
||||||
</div>
|
</div>
|
||||||
</div><!-- /.panel-body -->
|
</div><!-- /.panel-body -->
|
||||||
</div>
|
</div>
|
||||||
|
@ -160,8 +163,8 @@ small {
|
||||||
<b>Sightings</b>
|
<b>Sightings</b>
|
||||||
</div>
|
</div>
|
||||||
<div id="panelbody" class="panel-body" style="">
|
<div id="panelbody" class="panel-body" style="">
|
||||||
<div id="sightingEventPie" style="width:100%; height: 100%;"></div>
|
<div id="sightingEventPie" style="width:100%; height: 10vh;"></div>
|
||||||
<div id="sightingCategLine" style="width:100%; height: 100%;"></div>
|
<div id="sightingCategLine" style="width:100%; height: 10vh;"></div>
|
||||||
</div>
|
</div>
|
||||||
</div><!-- /.panel-body -->
|
</div><!-- /.panel-body -->
|
||||||
</div>
|
</div>
|
||||||
|
@ -171,7 +174,7 @@ small {
|
||||||
<b>Empty</b>
|
<b>Empty</b>
|
||||||
</div>
|
</div>
|
||||||
<div id="panelbody" class="panel-body" style="">
|
<div id="panelbody" class="panel-body" style="">
|
||||||
<div id="" style="width:100%; height: 100%;"></div>
|
<div id="" style="width:100%; height: 10vh;"></div>
|
||||||
</div>
|
</div>
|
||||||
</div><!-- /.panel-body -->
|
</div><!-- /.panel-body -->
|
||||||
</div>
|
</div>
|
||||||
|
@ -191,6 +194,9 @@ small {
|
||||||
<script>
|
<script>
|
||||||
/* URL */
|
/* URL */
|
||||||
var urlIconCalendar = "{{ url_for('static', filename='pics/calendar.gif') }}";
|
var urlIconCalendar = "{{ url_for('static', filename='pics/calendar.gif') }}";
|
||||||
|
var url_getTrendingEvent = "{{ url_for('getTrendingEvents') }}";
|
||||||
|
var url_getTrendingCateg = "{{ url_for('getTrendingCategs') }}";
|
||||||
|
var url_getTrendingTag = "{{ url_for('getTrendingTags') }}";
|
||||||
|
|
||||||
/* DATA FROM CONF */
|
/* DATA FROM CONF */
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ import geoip2.database
|
||||||
import util
|
import util
|
||||||
import contributor_helper
|
import contributor_helper
|
||||||
import users_helper
|
import users_helper
|
||||||
|
import trendings_helper
|
||||||
|
|
||||||
configfile = os.path.join(os.environ['DASH_CONFIG'], 'config.cfg')
|
configfile = os.path.join(os.environ['DASH_CONFIG'], 'config.cfg')
|
||||||
cfg = configparser.ConfigParser()
|
cfg = configparser.ConfigParser()
|
||||||
|
@ -55,6 +56,7 @@ serv_redis_db = redis.StrictRedis(
|
||||||
|
|
||||||
contributor_helper = contributor_helper.Contributor_helper(serv_redis_db, cfg)
|
contributor_helper = contributor_helper.Contributor_helper(serv_redis_db, cfg)
|
||||||
users_helper = users_helper.Users_helper(serv_redis_db, cfg)
|
users_helper = users_helper.Users_helper(serv_redis_db, cfg)
|
||||||
|
trendings_helper = trendings_helper.Trendings_helper(serv_redis_db, cfg)
|
||||||
|
|
||||||
reader = geoip2.database.Reader(PATH_TO_DB)
|
reader = geoip2.database.Reader(PATH_TO_DB)
|
||||||
|
|
||||||
|
@ -190,15 +192,15 @@ def handler_keepalive(zmq_name, jsonevent):
|
||||||
publish_log(zmq_name, 'Keepalive', to_push)
|
publish_log(zmq_name, 'Keepalive', to_push)
|
||||||
|
|
||||||
def handler_user(zmq_name, jsondata):
|
def handler_user(zmq_name, jsondata):
|
||||||
|
action = jsondata['action']
|
||||||
json_user = jsondata['User']
|
json_user = jsondata['User']
|
||||||
userID = json_user['id']
|
json_org = jsondata['Organisation']
|
||||||
org = userID
|
org = json_org['name']
|
||||||
try: #only consider user login
|
if action == 'login': #only consider user login
|
||||||
timestamp = json_user['current_login']
|
timestamp = int(time.time())
|
||||||
except KeyError:
|
|
||||||
return
|
|
||||||
if timestamp != 0: # "invited_by": "xxxx" ???
|
|
||||||
users_helper.add_user_login(timestamp, org)
|
users_helper.add_user_login(timestamp, org)
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
|
||||||
def handler_conversation(zmq_name, jsonevent):
|
def handler_conversation(zmq_name, jsonevent):
|
||||||
try: #only consider POST, not THREAD
|
try: #only consider POST, not THREAD
|
||||||
|
@ -234,6 +236,20 @@ def handler_sighting(zmq_name, jsondata):
|
||||||
def handler_event(zmq_name, jsonobj):
|
def handler_event(zmq_name, jsonobj):
|
||||||
#fields: threat_level_id, id, info
|
#fields: threat_level_id, id, info
|
||||||
jsonevent = jsonobj['Event']
|
jsonevent = jsonobj['Event']
|
||||||
|
|
||||||
|
#Add trending
|
||||||
|
eventName = jsonevent['info']
|
||||||
|
timestamp = jsonevent['timestamp']
|
||||||
|
trendings_helper.addTrendingEvent(eventName, timestamp)
|
||||||
|
try:
|
||||||
|
temp = jsonobj['EventTag']
|
||||||
|
tags = []
|
||||||
|
for tag in temp:
|
||||||
|
tags.append(tag['Tag'])
|
||||||
|
except KeyError:
|
||||||
|
tags = []
|
||||||
|
trendings_helper.addTrendingTags(tags, timestamp)
|
||||||
|
|
||||||
#redirect to handler_attribute
|
#redirect to handler_attribute
|
||||||
if 'Attribute' in jsonevent:
|
if 'Attribute' in jsonevent:
|
||||||
attributes = jsonevent['Attribute']
|
attributes = jsonevent['Attribute']
|
||||||
|
@ -270,6 +286,19 @@ def handler_attribute(zmq_name, jsonobj, hasAlreadyBeenContributed=False):
|
||||||
if 'Attribute' in jsonobj:
|
if 'Attribute' in jsonobj:
|
||||||
jsonattr = jsonobj['Attribute']
|
jsonattr = jsonobj['Attribute']
|
||||||
|
|
||||||
|
#Add trending
|
||||||
|
categName = jsonattr['category']
|
||||||
|
timestamp = jsonattr['timestamp']
|
||||||
|
trendings_helper.addTrendingCateg(categName, timestamp)
|
||||||
|
try:
|
||||||
|
temp = jsonattr['Tag']
|
||||||
|
tags = []
|
||||||
|
for tag in temp:
|
||||||
|
tags.append(tag['Tag'])
|
||||||
|
except KeyError:
|
||||||
|
tags = []
|
||||||
|
trendings_helper.addTrendingTags(tags, timestamp)
|
||||||
|
|
||||||
to_push = []
|
to_push = []
|
||||||
for field in json.loads(cfg.get('Log', 'fieldname_order')):
|
for field in json.loads(cfg.get('Log', 'fieldname_order')):
|
||||||
if type(field) is list:
|
if type(field) is list:
|
||||||
|
|
Loading…
Reference in New Issue