mirror of https://github.com/MISP/misp-dashboard
				
				
				
			Draft MISP-Users
							parent
							
								
									3ec4bcb7a4
								
							
						
					
					
						commit
						2f74406f64
					
				
							
								
								
									
										39
									
								
								server.py
								
								
								
								
							
							
						
						
									
										39
									
								
								server.py
								
								
								
								
							|  | @ -198,6 +198,45 @@ def users(): | |||
|     return render_template('users.html', | ||||
|             ) | ||||
| 
 | ||||
| 
 | ||||
| @app.route("/_getUserLogins") | ||||
| def getUserLogins(): | ||||
|     try: | ||||
|         date = datetime.datetime.fromtimestamp(float(request.args.get('date'))) | ||||
|     except: | ||||
|         date = datetime.datetime.now() | ||||
| 
 | ||||
|     keyname = "USER_LOGIN:{}" | ||||
|     prev_days = 6 | ||||
|     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 | ||||
|     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: | ||||
|             data.append([0 for x in range(24)]) | ||||
|     return jsonify(data) | ||||
| 
 | ||||
| ''' INDEX ''' | ||||
| 
 | ||||
| @app.route("/_logs") | ||||
|  |  | |||
|  | @ -0,0 +1,187 @@ | |||
| <!DOCTYPE html> | ||||
| <html lang="en"> | ||||
| 
 | ||||
| <head> | ||||
| 
 | ||||
|     <meta charset="utf-8"> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1"> | ||||
|     <meta name="description" content=""> | ||||
|     <meta name="author" content=""> | ||||
| 
 | ||||
|     <title>MISP live dashboard</title> | ||||
| 
 | ||||
|     <!-- Bootstrap Core CSS --> | ||||
|     <link href="{{ url_for('static', filename='css/bootstrap.min.css') }}" rel="stylesheet"> | ||||
|     <!-- Custom CSS --> | ||||
|     <link href="{{ url_for('static', filename='css/sb-admin-2.css') }}" rel="stylesheet"> | ||||
|     <!-- LeafLet --> | ||||
|     <link rel="stylesheet" href="{{ url_for('static', filename='css/leaflet.css') }}"> | ||||
|     <script src="{{ url_for('static', filename='js/leaflet.js') }}"></script> | ||||
| 
 | ||||
|     <!-- jQuery --> | ||||
|     <script src="{{ url_for('static', filename='js/jquery.min.js') }}"></script> | ||||
|     <!-- jQuery flot --> | ||||
|     <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.resize.js') }}"></script> | ||||
|     <!-- Bootstrap Core JavaScript --> | ||||
|     <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 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> | ||||
|     <link href="{{ url_for('static', filename='css/jquery-ui.min.css') }}" rel="stylesheet" type="text/css" /> | ||||
|     <script src="{{ url_for('static', filename='js/jquery-ui.min.js') }}"></script> | ||||
| 
 | ||||
|     <link rel="stylesheet" href="{{ url_for('static', filename='css/punchcard.css') }}"> | ||||
|     <script src="{{ url_for('static', filename='js/moment.js') }}"></script> | ||||
|     <script src="{{ url_for('static', filename='js/punchcard.js') }}"></script> | ||||
| 
 | ||||
| </head> | ||||
| 
 | ||||
| <style> | ||||
| 
 | ||||
|  .panel { | ||||
|      margin-bottom: 10px; | ||||
|  } | ||||
| 
 | ||||
| .col-lg-6 { | ||||
|     padding-right: 5px; | ||||
|     padding-left: 5px; | ||||
| } | ||||
| 
 | ||||
| .leftSepa { | ||||
|     border-left-color: rgb(221, 221, 221); | ||||
|     border-left-style: solid; | ||||
|     border-left-width: 2px; | ||||
|     padding-left: 8px; | ||||
| } | ||||
| 
 | ||||
| .textTopHeader { | ||||
|     height: 50px; | ||||
|     text-align: center; | ||||
|     margin-left: 8px; | ||||
|     float: left; | ||||
|     padding-top: 9px; | ||||
| } | ||||
| 
 | ||||
| .center { | ||||
|   display:block; | ||||
|   margin-left:auto; | ||||
|   margin-right:auto; | ||||
| } | ||||
| 
 | ||||
| small { | ||||
|     font-size: 100%; | ||||
|     font-weight: bold; | ||||
| } | ||||
| 
 | ||||
| </style> | ||||
| 
 | ||||
| <body> | ||||
| 
 | ||||
|     <div id="wrapper"> | ||||
| 
 | ||||
|         <!-- Navigation --> | ||||
|         <nav class="navbar navbar-default navbar-static-top" role="navigation" style="margin-bottom: 0; padding-left: 15px;"> | ||||
|             <div class="navbar-header"> | ||||
|                 <img src="{{ url_for('static', filename='pics/MISP.png') }}" alt="MISP" style="float: left; height: 40px; margin-top: 5px;"><a class="navbar-brand dropdown-toggle" data-toggle="dropdown" href="#">MISP Users | ||||
|                     <span class="caret"></span></a> | ||||
|                     <ul class="dropdown-menu"> | ||||
|                       <li><a href="{{ url_for('index') }}">MISP Live Dashboard</a></li> | ||||
|                       <li><a href="{{ url_for('geo') }}">MISP Geolocalisation</a></li> | ||||
|                       <li><a href="{{ url_for('contrib') }}">MISP Contributors</a></li> | ||||
|                     </ul> | ||||
|             </div> | ||||
|             <!-- /.navbar-header --> | ||||
| 
 | ||||
|         </nav> | ||||
| 
 | ||||
|         <!-- Page Content --> | ||||
|         <div id="page-wrapper" style="margin: 0px; padding: 0px;"> | ||||
|             <div class="container-fluid"> | ||||
|                 <div class="row"> | ||||
|                     <div style="height: 10px;"></div> | ||||
| 
 | ||||
|                     <div class="col-lg-8"> | ||||
|                         <div class="panel panel-default" style=""> | ||||
|                             <div class="panel-heading bg-info" style="font-weight: bold;"> | ||||
|                                 <b>Punch card - login</b> | ||||
|                             </div> | ||||
|                             <div id="panelbody" class="panel-body" style=""> | ||||
|                                 <div id="punchcard" style="width:100%; height: 100%;"></div> | ||||
|                             </div> | ||||
|                         </div><!-- /.panel-body --> | ||||
|                     </div> | ||||
| 
 | ||||
|                     <div class="col-lg-4"> | ||||
|                         <div class="panel panel-default" style=""> | ||||
|                             <div class="panel-heading bg-info" style="font-weight: bold;"> | ||||
|                                 <b>Contribution after login (API vs non-API)</b> | ||||
|                             </div> | ||||
|                             <div id="panelbody" class="panel-body" style=""> | ||||
|                                 <div id="pieChart" style="width:100%; height: 20vh;"></div> | ||||
|                             </div> | ||||
|                         </div><!-- /.panel-body --> | ||||
|                     </div> | ||||
| 
 | ||||
|                     </div><!-- /.col-lg-12 --> | ||||
|                 </div><!-- /.row --> | ||||
| 
 | ||||
|             </div> <!-- /.container-fluid --> | ||||
| 
 | ||||
|         </div> | ||||
|         <!-- /#page-wrapper --> | ||||
| 
 | ||||
|     </div> | ||||
| <!-- /#wrapper --> | ||||
| 
 | ||||
|     <!-- Index --> | ||||
|     <script> | ||||
|         /* URL */ | ||||
| 
 | ||||
|         /* DATA FROM CONF */ | ||||
| 
 | ||||
|     </script> | ||||
| 
 | ||||
|     <script> | ||||
|         $(document).ready(function () { | ||||
| 
 | ||||
|             $.getJSON( "{{ url_for('getUserLogins') }}", function( data ) { | ||||
|                 $('#punchcard').punchcard({ | ||||
|                     data: data, | ||||
|                     singular: 'login', | ||||
|                     plural: 'logins', | ||||
|                     timezones: ['local'], | ||||
|                     timezoneIndex:0 | ||||
|                 }); | ||||
|             }); | ||||
| 
 | ||||
|             $.getJSON( "{{ url_for('getUserLogins') }}", function( data ) { | ||||
|                 data = [{ | ||||
|                     label: "Contribution with login", | ||||
|                     data: Math.floor(Math.random() * 100) + 1 | ||||
|                 }, | ||||
|                 { | ||||
|                     label: "Contribution without login", | ||||
|                     data: Math.floor(Math.random() * 100) + 1 | ||||
|                     } | ||||
|                 ]; | ||||
|                 $.plot('#pieChart', data, { | ||||
|                     series: { | ||||
|                         pie: { | ||||
|                             innerRadius: 0.5, | ||||
|                             show: true | ||||
|                         } | ||||
|                     } | ||||
|                 }); | ||||
|             }); | ||||
| 
 | ||||
| 
 | ||||
|         }); | ||||
|     </script> | ||||
| 
 | ||||
| </body> | ||||
| 
 | ||||
| </html> | ||||
|  | @ -187,6 +187,18 @@ def handler_keepalive(zmq_name, jsonevent): | |||
|     to_push = [ jsonevent['uptime'] ] | ||||
|     publish_log(zmq_name, 'Keepalive', to_push) | ||||
| 
 | ||||
| def handler_user(zmq_name, jsondata): | ||||
|     json_user = jsondata['User'] | ||||
|     userID = json_user['id'] | ||||
|     try: #only consider user login | ||||
|         timestamp = json_user['current_login'] | ||||
|     except KeyError: | ||||
|         return | ||||
|     now = datetime.datetime.now() | ||||
|     today_str = util.getDateStrFormat(now) | ||||
|     keyname = "{}:{}".format('USER_LOGIN', today_str) | ||||
|     serv_redis_db.sadd(keyname, timestamp) | ||||
| 
 | ||||
| def handler_conversation(zmq_name, jsonevent): | ||||
|     try: #only consider POST, not THREAD | ||||
|         jsonpost = jsonevent['Post'] | ||||
|  | @ -323,7 +335,7 @@ dico_action = { | |||
|         "misp_json_object":         handler_object, | ||||
|         "misp_json_sighting":       handler_sighting, | ||||
|         "misp_json_organisation":   handler_log, | ||||
|         "misp_json_user":           handler_log, | ||||
|         "misp_json_user":           handler_user, | ||||
|         "misp_json_conversation":   handler_conversation | ||||
|         } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Sami Mokaddem
						Sami Mokaddem