mirror of https://github.com/MISP/misp-dashboard
Merge branch 'users' into trendings
commit
e3a63e863f
10
server.py
10
server.py
|
@ -487,6 +487,16 @@ def getLoginVSCOntribution():
|
|||
data = users_helper.getLoginVSCOntribution(date)
|
||||
return jsonify(data)
|
||||
|
||||
@app.route("/_getUserLoginsAndContribOvertime")
|
||||
def getUserLoginsAndContribOvertime():
|
||||
try:
|
||||
date = datetime.datetime.fromtimestamp(float(request.args.get('date')))
|
||||
except:
|
||||
date = datetime.datetime.now()
|
||||
|
||||
data = users_helper.getUserLoginsAndContribOvertime(date)
|
||||
return jsonify(data)
|
||||
|
||||
''' TRENDINGS '''
|
||||
@app.route("/_getTrendingEvents")
|
||||
def getTrendingEvents():
|
||||
|
|
|
@ -527,17 +527,24 @@ function updateProgressHeader(org) {
|
|||
categ = trophy_categ_list[i];
|
||||
$('#trophy_'+categ).attr('src', source);
|
||||
$('#trophy_'+categ).attr('title', "");
|
||||
$('#trophy_'+categ).popover("destroy")
|
||||
}
|
||||
for(var i=0; i<data.length; i++) { // add
|
||||
categ = data[i].categ;
|
||||
rank = data[i].trophy_true_rank;
|
||||
trophy_points = data[i].trophy_points
|
||||
source = url_baseTrophyLogo+rank+'.png'
|
||||
$('#trophy_'+categ).attr('src', source);
|
||||
$('#trophy_'+categ).attr('title', trophy_title[rank]);
|
||||
$('#trophy_'+categ).popover({title: trophy_title[rank], content: 'Level: '+rank+' ('+trophy_points+' points)', trigger: "hover", placement: "bottom"});
|
||||
try { // in case popover not created
|
||||
var pop = $('#trophy_'+categ).data('bs.popover');
|
||||
pop.destroy();
|
||||
} catch(err) {
|
||||
|
||||
}
|
||||
}
|
||||
setTimeout(function() { // avoid race condition with destroy
|
||||
for(var i=0; i<data.length; i++) { // add
|
||||
categ = data[i].categ;
|
||||
rank = data[i].trophy_true_rank;
|
||||
trophy_points = data[i].trophy_points
|
||||
source = url_baseTrophyLogo+rank+'.png'
|
||||
$('#trophy_'+categ).attr('src', source);
|
||||
$('#trophy_'+categ).attr('title', trophy_title[rank]);
|
||||
$('#trophy_'+categ).popover({title: trophy_title[rank], content: 'Level: '+rank+' ('+trophy_points+' points)', trigger: "hover", placement: "bottom"});
|
||||
}
|
||||
}, 300);
|
||||
});
|
||||
|
||||
//update overtake points
|
||||
|
|
|
@ -123,13 +123,25 @@ function updateDateOvertime() {
|
|||
} else {
|
||||
date.setTime(date.getTime() + (24*60*60*1000-1)); // include data of selected date
|
||||
}
|
||||
$.getJSON( url_getUserLoginsOvertime+"?date="+parseInt(date.getTime()/1000), function( data ) {
|
||||
temp = [];
|
||||
$.getJSON( url_getUserLoginsAndContribOvertime+"?date="+parseInt(date.getTime()/1000), function( data ) {
|
||||
console.log(data);
|
||||
data_log = data['login'];
|
||||
data_contrib = data['contrib'];
|
||||
temp_log = [];
|
||||
var i=0;
|
||||
for (item of data) {
|
||||
temp.push([new Date(item[0]*1000), item[1]]);
|
||||
for (item of data_log) {
|
||||
var date = new Date(item[0]*1000);
|
||||
date = new Date(date.valueOf() - date.getTimezoneOffset() * 60000); // center the data around the day
|
||||
temp_log.push([date, item[1]]);
|
||||
}
|
||||
toPlot = [{label: 'Login overtime', data: temp}];
|
||||
temp_contrib= [];
|
||||
var i=0;
|
||||
for (item of data_contrib) {
|
||||
var date = new Date(item[0]*1000);
|
||||
date = new Date(date.valueOf() - date.getTimezoneOffset() * 60000); // center the data around the day
|
||||
temp_contrib.push([date, item[1]]);
|
||||
}
|
||||
toPlot = [{label: 'Login', data: temp_log}, {label: 'Contribution', data: temp_contrib}];
|
||||
if (!(overtimeWidget === undefined)) {
|
||||
overtimeWidget.setData(toPlot);
|
||||
overtimeWidget.setupGrid();
|
||||
|
|
|
@ -167,7 +167,7 @@ small {
|
|||
<div class="col-lg-12">
|
||||
<div class="panel panel-default" style="">
|
||||
<div class="panel-heading bg-info" style="font-weight: bold;">
|
||||
<b>Login overtime</b>
|
||||
<b title="Login is unique per organisation during one hour, contribution is unique per organisation during the day">Login and contribution overtime</b>
|
||||
<strong class='leftSepa textTopHeader' style="float: none; padding: 11px;">Dates:
|
||||
<input type="text" id="datepickerOvertimeLogin" size="10" style="">
|
||||
</strong>
|
||||
|
@ -195,7 +195,7 @@ small {
|
|||
var url_getUserLogins = "{{ url_for('getUserLogins') }}";
|
||||
var url_getTopOrglogin = "{{ url_for('getTopOrglogin') }}";
|
||||
var url_getLoginVSCOntribution = "{{ url_for('getLoginVSCOntribution') }}";
|
||||
var url_getUserLoginsOvertime = "{{ url_for('getUserLoginsOvertime') }}";
|
||||
var url_getUserLoginsAndContribOvertime = "{{ url_for('getUserLoginsAndContribOvertime') }}";
|
||||
|
||||
/* DATA FROM CONF */
|
||||
|
||||
|
|
|
@ -136,13 +136,22 @@ class Users_helper:
|
|||
data = [data[6]]+data[:6]
|
||||
return data
|
||||
|
||||
def getUserLoginsOvertime(self, date, prev_days=6):
|
||||
def getUserLoginsAndContribOvertime(self, date, prev_days=6):
|
||||
dico_hours_contrib = {}
|
||||
dico_hours = {}
|
||||
for curDate in util.getXPrevHoursSpan(date, prev_days*24):
|
||||
dico_hours[util.getTimestamp(curDate)] = 0 # populate with empty data
|
||||
dico_hours_contrib[util.getTimestamp(curDate)] = 0 # populate with empty data
|
||||
|
||||
for curDate in util.getXPrevDaysSpan(date, prev_days):
|
||||
timestamps = self.getUserLogins(curDate)
|
||||
keyname = "CONTRIB_DAY:{}".format(util.getDateStrFormat(curDate))
|
||||
|
||||
orgs_contri = self.serv_redis_db.zrange(keyname, 0, -1, desc=True, withscores=False)
|
||||
orgs_contri_num = len(orgs_contri)
|
||||
for curDate in util.getHoursSpanOfDate(curDate, adaptToFitCurrentTime=True): #fill hole day
|
||||
dico_hours_contrib[util.getTimestamp(curDate)] = orgs_contri_num
|
||||
|
||||
for timestamp in timestamps: # sum occurence during the current hour
|
||||
dateTimestamp = datetime.datetime.fromtimestamp(float(timestamp))
|
||||
dateTimestamp = dateTimestamp.replace(minute=0, second=0, microsecond=0)
|
||||
|
@ -152,9 +161,18 @@ class Users_helper:
|
|||
pass
|
||||
|
||||
# Format data
|
||||
# login
|
||||
to_ret = {}
|
||||
data = []
|
||||
for curDate, occ in dico_hours.items():
|
||||
data.append([curDate, occ])
|
||||
|
||||
data.sort(key=lambda x: x[0])
|
||||
return data
|
||||
to_ret['login'] = data
|
||||
# contrib
|
||||
data = []
|
||||
for curDate, occ in dico_hours_contrib.items():
|
||||
data.append([curDate, occ])
|
||||
data.sort(key=lambda x: x[0])
|
||||
to_ret['contrib'] = data
|
||||
|
||||
return to_ret
|
||||
|
|
12
util.py
12
util.py
|
@ -35,6 +35,18 @@ def getXPrevHoursSpan(date, hours):
|
|||
to_return.append(de - datetime.timedelta(hours=i))
|
||||
return to_return
|
||||
|
||||
def getHoursSpanOfDate(date, adaptToFitCurrentTime=True, daySpanned=6):
|
||||
ds = date
|
||||
ds = ds.replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
to_return = []
|
||||
now = datetime.datetime.now()
|
||||
for i in range(0, 24):
|
||||
the_date = ds + datetime.timedelta(hours=i)
|
||||
if the_date > now or the_date < now - datetime.timedelta(days=daySpanned): # avoid going outside
|
||||
continue
|
||||
to_return.append(the_date)
|
||||
return to_return
|
||||
|
||||
def getDateStrFormat(date):
|
||||
return str(date.year)+str(date.month).zfill(2)+str(date.day).zfill(2)
|
||||
|
||||
|
|
Loading…
Reference in New Issue