mirror of https://github.com/MISP/misp-dashboard
Added login overtime + users_helper script
parent
2f74406f64
commit
c1105aba73
38
server.py
38
server.py
|
@ -11,6 +11,7 @@ import os
|
||||||
|
|
||||||
import util
|
import util
|
||||||
import contributor_helper
|
import contributor_helper
|
||||||
|
import users_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()
|
||||||
|
@ -32,6 +33,7 @@ serv_redis_db = redis.StrictRedis(
|
||||||
db=cfg.getint('RedisDB', 'db'))
|
db=cfg.getint('RedisDB', 'db'))
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
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'))
|
||||||
|
@ -206,35 +208,17 @@ def getUserLogins():
|
||||||
except:
|
except:
|
||||||
date = datetime.datetime.now()
|
date = datetime.datetime.now()
|
||||||
|
|
||||||
keyname = "USER_LOGIN:{}"
|
data = users_helper.getUserLoginsForPunchCard(date)
|
||||||
prev_days = 6
|
return jsonify(data)
|
||||||
week = {}
|
|
||||||
for curDate in util.getXPrevDaysSpan(date, prev_days):
|
|
||||||
timestamps = serv_redis_db.smembers(keyname.format(util.getDateStrFormat(curDate)))
|
|
||||||
timestamps = [int(timestamp.decode('utf8')) for timestamp in timestamps]
|
|
||||||
day = {}
|
|
||||||
for timestamp in timestamps:
|
|
||||||
date = datetime.datetime.fromtimestamp(float(timestamp))
|
|
||||||
if date.hour not in day:
|
|
||||||
day[date.hour] = 0
|
|
||||||
day[date.hour] += 1
|
|
||||||
week[curDate.weekday()] = day
|
|
||||||
|
|
||||||
# Format data
|
@app.route("/_getUserLoginsOvertime")
|
||||||
data = []
|
def getUserLoginsOvertime():
|
||||||
for d in range(7):
|
|
||||||
try:
|
try:
|
||||||
to_append = []
|
date = datetime.datetime.fromtimestamp(float(request.args.get('date')))
|
||||||
for h in range(24):
|
except:
|
||||||
try:
|
date = datetime.datetime.now()
|
||||||
to_append.append(week[d][h])
|
|
||||||
except KeyError:
|
data = users_helper.getUserLoginsOvertime(date)
|
||||||
to_append.append(0)
|
|
||||||
# swap 24 and 1. (punchcard starts at 1h)
|
|
||||||
temp = to_append[1:]+[to_append[0]]
|
|
||||||
data.append(temp)
|
|
||||||
except KeyError:
|
|
||||||
data.append([0 for x in range(24)])
|
|
||||||
return jsonify(data)
|
return jsonify(data)
|
||||||
|
|
||||||
''' INDEX '''
|
''' INDEX '''
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
<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.flot.time.js') }}"></script>
|
||||||
<!-- 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 href="{{ url_for('static', filename='css/font-awesome.min.css') }}" rel="text/css">
|
<link href="{{ url_for('static', filename='css/font-awesome.min.css') }}" rel="text/css">
|
||||||
|
@ -104,6 +105,7 @@ small {
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div style="height: 10px;"></div>
|
<div style="height: 10px;"></div>
|
||||||
|
|
||||||
|
<div class="col-lg-12">
|
||||||
<div class="col-lg-8">
|
<div class="col-lg-8">
|
||||||
<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;">
|
||||||
|
@ -116,6 +118,15 @@ small {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-lg-4">
|
<div class="col-lg-4">
|
||||||
|
<div class="panel panel-default" style="">
|
||||||
|
<div class="panel-heading bg-info" style="font-weight: bold;">
|
||||||
|
<b>Top login per organisation</b>
|
||||||
|
</div>
|
||||||
|
<div id="panelbody" class="panel-body" style="">
|
||||||
|
<div id="barChart" style="width:100%; height: 20vh;"></div>
|
||||||
|
</div>
|
||||||
|
</div><!-- /.panel-body -->
|
||||||
|
|
||||||
<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>Contribution after login (API vs non-API)</b>
|
<b>Contribution after login (API vs non-API)</b>
|
||||||
|
@ -127,6 +138,17 @@ small {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div><!-- /.col-lg-12 -->
|
</div><!-- /.col-lg-12 -->
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
<div id="panelbody" class="panel-body" style="">
|
||||||
|
<div id="lineChart" style="width:100%; height: 20vh;"></div>
|
||||||
|
</div>
|
||||||
|
</div><!-- /.panel-body -->
|
||||||
|
</div><!-- /.col-lg-12 -->
|
||||||
|
|
||||||
</div><!-- /.row -->
|
</div><!-- /.row -->
|
||||||
|
|
||||||
</div> <!-- /.container-fluid -->
|
</div> <!-- /.container-fluid -->
|
||||||
|
@ -178,6 +200,40 @@ small {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$.getJSON( "{{ url_for('getUserLogins') }}", function( data ) {
|
||||||
|
data = [{label: 'org1', data:[ Math.floor(Math.random() * 100) + 1]},
|
||||||
|
{label: 'org2', data:[ Math.floor(Math.random() * 100) + 1]},
|
||||||
|
{label: 'org3', data:[ Math.floor(Math.random() * 100) + 1]}]
|
||||||
|
$.plot('#barChart', data, {
|
||||||
|
series: {
|
||||||
|
pie: {
|
||||||
|
innerRadius: 0.5,
|
||||||
|
show: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$.getJSON( "{{ url_for('getUserLoginsOvertime') }}", function( data ) {
|
||||||
|
temp = [];
|
||||||
|
var i=0;
|
||||||
|
for (item of data) {
|
||||||
|
temp.push([new Date(item[0]*1000), item[1]]);
|
||||||
|
}
|
||||||
|
console.log(temp);
|
||||||
|
data = {label: 'Login overtime', data: temp}
|
||||||
|
$.plot('#lineChart', [data], {
|
||||||
|
lines: {
|
||||||
|
show: true,
|
||||||
|
steps: true,
|
||||||
|
fill: true
|
||||||
|
},
|
||||||
|
xaxis: {
|
||||||
|
mode: "time",
|
||||||
|
minTickSize: [1, "hour"],
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
import math, random
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
import datetime, time
|
||||||
|
|
||||||
|
import util
|
||||||
|
|
||||||
|
class Users_helper:
|
||||||
|
def __init__(self, serv_redis_db, cfg):
|
||||||
|
self.serv_redis_db = serv_redis_db
|
||||||
|
self.cfg = cfg
|
||||||
|
|
||||||
|
def add_user_login(self, timestamp):
|
||||||
|
timestampDate = datetime.datetime.fromtimestamp(float(timestamp))
|
||||||
|
timestampDate_str = util.getDateStrFormat(timestampDate)
|
||||||
|
keyname = "{}:{}".format('USER_LOGIN', timestampDate_str)
|
||||||
|
self.serv_redis_db.sadd(keyname, timestamp)
|
||||||
|
|
||||||
|
def getUserLogins(self, date):
|
||||||
|
keyname = "USER_LOGIN:{}"
|
||||||
|
timestamps = self.serv_redis_db.smembers(keyname.format(util.getDateStrFormat(date)))
|
||||||
|
timestamps = [int(timestamp.decode('utf8')) for timestamp in timestamps]
|
||||||
|
return timestamps
|
||||||
|
|
||||||
|
def getUserLoginsForPunchCard(self, date, prev_days=6):
|
||||||
|
week = {}
|
||||||
|
for curDate in util.getXPrevDaysSpan(date, prev_days):
|
||||||
|
timestamps = self.getUserLogins(curDate)
|
||||||
|
day = {}
|
||||||
|
for timestamp in timestamps:
|
||||||
|
date = datetime.datetime.fromtimestamp(float(timestamp))
|
||||||
|
if date.hour not in day:
|
||||||
|
day[date.hour] = 0
|
||||||
|
day[date.hour] += 1
|
||||||
|
week[curDate.weekday()] = day
|
||||||
|
|
||||||
|
# Format data
|
||||||
|
data = []
|
||||||
|
for d in range(7):
|
||||||
|
try:
|
||||||
|
to_append = []
|
||||||
|
for h in range(24):
|
||||||
|
try:
|
||||||
|
to_append.append(week[d][h])
|
||||||
|
except KeyError:
|
||||||
|
to_append.append(0)
|
||||||
|
# swap 24 and 1. (punchcard starts at 1h)
|
||||||
|
temp = to_append[1:]+[to_append[0]]
|
||||||
|
data.append(temp)
|
||||||
|
except KeyError: # no data
|
||||||
|
data.append([0 for x in range(24)])
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
def getUserLoginsOvertime(self, date, prev_days=6):
|
||||||
|
dico_hours = {}
|
||||||
|
for curDate in util.getXPrevHoursSpan(date, prev_days*24):
|
||||||
|
dico_hours[util.getTimestamp(curDate)] = 0 # populate with empty data
|
||||||
|
|
||||||
|
for curDate in util.getXPrevDaysSpan(date, prev_days):
|
||||||
|
timestamps = self.getUserLogins(curDate)
|
||||||
|
for timestamp in timestamps: # sum occurence during the current hour
|
||||||
|
date = datetime.datetime.fromtimestamp(float(timestamp))
|
||||||
|
date = date.replace(minute=0, second=0, microsecond=0)
|
||||||
|
dico_hours[util.getTimestamp(date)] += 1
|
||||||
|
|
||||||
|
# Format data
|
||||||
|
data = []
|
||||||
|
for date, occ in dico_hours.items():
|
||||||
|
data.append([date, occ])
|
||||||
|
|
||||||
|
data.sort(key=lambda x: x[0])
|
||||||
|
return data
|
13
util.py
13
util.py
|
@ -24,8 +24,19 @@ def getXPrevDaysSpan(date, days):
|
||||||
to_return.append(de - datetime.timedelta(days=i))
|
to_return.append(de - datetime.timedelta(days=i))
|
||||||
return to_return
|
return to_return
|
||||||
|
|
||||||
|
def getXPrevHoursSpan(date, hours):
|
||||||
|
de = date
|
||||||
|
de = de.replace(minute=0, second=0, microsecond=0)
|
||||||
|
ds = de - datetime.timedelta(hours=hours)
|
||||||
|
|
||||||
|
delta = de - ds
|
||||||
|
to_return = []
|
||||||
|
for i in range(0, int(delta.total_seconds()/3600)+1):
|
||||||
|
to_return.append(de - datetime.timedelta(hours=i))
|
||||||
|
return to_return
|
||||||
|
|
||||||
def getDateStrFormat(date):
|
def getDateStrFormat(date):
|
||||||
return str(date.year)+str(date.month).zfill(2)+str(date.day).zfill(2)
|
return str(date.year)+str(date.month).zfill(2)+str(date.day).zfill(2)
|
||||||
|
|
||||||
def getTimestamp(date):
|
def getTimestamp(date):
|
||||||
return time.mktime(date.timetuple())
|
return int(time.mktime(date.timetuple()))
|
||||||
|
|
|
@ -16,6 +16,7 @@ import geoip2.database
|
||||||
|
|
||||||
import util
|
import util
|
||||||
import contributor_helper
|
import contributor_helper
|
||||||
|
import users_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()
|
||||||
|
@ -53,6 +54,7 @@ serv_redis_db = redis.StrictRedis(
|
||||||
db=cfg.getint('RedisDB', 'db'))
|
db=cfg.getint('RedisDB', 'db'))
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
reader = geoip2.database.Reader(PATH_TO_DB)
|
reader = geoip2.database.Reader(PATH_TO_DB)
|
||||||
|
|
||||||
|
@ -194,10 +196,8 @@ def handler_user(zmq_name, jsondata):
|
||||||
timestamp = json_user['current_login']
|
timestamp = json_user['current_login']
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return
|
return
|
||||||
now = datetime.datetime.now()
|
if timestamp != 0: # "invited_by": "xxxx" ???
|
||||||
today_str = util.getDateStrFormat(now)
|
users_helper.add_user_login(timestamp)
|
||||||
keyname = "{}:{}".format('USER_LOGIN', today_str)
|
|
||||||
serv_redis_db.sadd(keyname, timestamp)
|
|
||||||
|
|
||||||
def handler_conversation(zmq_name, jsonevent):
|
def handler_conversation(zmq_name, jsonevent):
|
||||||
try: #only consider POST, not THREAD
|
try: #only consider POST, not THREAD
|
||||||
|
|
Loading…
Reference in New Issue