add recent connection
This commit is contained in:
parent
48a4316d66
commit
0e3d5e1c1f
76
app.py
76
app.py
@ -7,7 +7,10 @@ import mimetypes
|
||||
import sqlite3
|
||||
from datetime import datetime, date, timedelta
|
||||
import diskcache
|
||||
import threading
|
||||
import json
|
||||
import time
|
||||
from flask_socketio import SocketIO
|
||||
import geoip2.database
|
||||
from functools import lru_cache
|
||||
from urllib.parse import urlparse, unquote
|
||||
@ -26,6 +29,13 @@ if os.environ.get('FLASK_ENV') == 'production':
|
||||
with open('folder_config.json') as file:
|
||||
app.config['folder_config'] = json.load(file)
|
||||
|
||||
socketio = SocketIO(app)
|
||||
|
||||
# Global variables to track the number of connected clients and the background thread
|
||||
clients_connected = 0
|
||||
background_thread = None
|
||||
thread_lock = threading.Lock()
|
||||
|
||||
def require_secret(f):
|
||||
@wraps(f)
|
||||
def decorated_function(*args, **kwargs):
|
||||
@ -558,6 +568,68 @@ def crawl_and_cache(subpath):
|
||||
# Return the list of cached files as a JSON response
|
||||
return json.dumps({"cached_files": cached_files}, indent=4), 200
|
||||
|
||||
def query_recent_connections():
|
||||
"""
|
||||
Every 5 seconds, query the database for connections in the last 60 seconds,
|
||||
sorted by timestamp (most recent first), and emit the data to clients.
|
||||
This loop will exit when there are no connected clients.
|
||||
"""
|
||||
global clients_connected
|
||||
while clients_connected > 0:
|
||||
cutoff = datetime.now() - timedelta(seconds=60)
|
||||
cutoff_iso = cutoff.isoformat()
|
||||
|
||||
# Query the SQLite database for recent connections
|
||||
conn = sqlite3.connect('access_log.db')
|
||||
cursor = conn.cursor()
|
||||
cursor.execute('''
|
||||
SELECT * FROM file_access_log
|
||||
WHERE timestamp >= ?
|
||||
ORDER BY timestamp DESC
|
||||
''', (cutoff_iso,))
|
||||
rows = cursor.fetchall()
|
||||
conn.close()
|
||||
|
||||
# Convert rows to dictionaries for the client, including all columns.
|
||||
connections = []
|
||||
for row in rows:
|
||||
# Row order: (id, timestamp, full_path, ip_address, user_agent, referrer)
|
||||
connections.append({
|
||||
'id': row[0],
|
||||
'timestamp': row[1],
|
||||
'full_path': row[2],
|
||||
'ip_address': row[3],
|
||||
'user_agent': row[4],
|
||||
'referrer': row[5]
|
||||
})
|
||||
|
||||
# Emit the result over Socket.IO (to the default namespace)
|
||||
socketio.emit('recent_connections', connections)
|
||||
time.sleep(5)
|
||||
# When no clients are connected, exit the thread.
|
||||
print("No clients connected; stopping query thread.")
|
||||
|
||||
@socketio.on('connect')
|
||||
def handle_connect():
|
||||
global clients_connected, background_thread
|
||||
clients_connected += 1
|
||||
print("Client connected. Total clients:", clients_connected)
|
||||
with thread_lock:
|
||||
# Start the background task if it's not already running.
|
||||
if background_thread is None or not background_thread.is_alive():
|
||||
background_thread = socketio.start_background_task(query_recent_connections)
|
||||
print("Started background query task.")
|
||||
|
||||
@socketio.on('disconnect')
|
||||
def handle_disconnect():
|
||||
global clients_connected
|
||||
clients_connected -= 1
|
||||
print("Client disconnected. Total clients:", clients_connected)
|
||||
|
||||
@app.route('/network')
|
||||
def network():
|
||||
return render_template('network.html')
|
||||
|
||||
# Catch-all route to serve the single-page application template.
|
||||
@app.route('/', defaults={'path': ''})
|
||||
@app.route('/<path:path>')
|
||||
@ -565,5 +637,5 @@ def crawl_and_cache(subpath):
|
||||
def index(path):
|
||||
return render_template("app.html")
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run(debug=True, host='0.0.0.0')
|
||||
if __name__ == '__main__':
|
||||
socketio.run(app, debug=True, host='0.0.0.0')
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
flask
|
||||
flask_socketio
|
||||
pillow
|
||||
diskcache
|
||||
geoip2
|
||||
|
||||
@ -1,22 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Web Analytics Dashboard</title>
|
||||
<!-- Using Bootstrap for responsive layout -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Dashboard - Verbindungsanalyse</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<style>
|
||||
body { margin: 20px; }
|
||||
.card { margin-bottom: 20px; }
|
||||
canvas { max-width: 100%; }
|
||||
</style>
|
||||
</head>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1 class="mb-4">Web Analytics Dashboard ({{ timeframe }})</h1>
|
||||
<h1 class="mb-4">Dashboard - Verbindungsanalyse({{ timeframe }})</h1>
|
||||
<!-- Timeframe selection buttons -->
|
||||
<div class="mb-3">
|
||||
<a href="{{ url_for('index') }}" class="btn btn-primary">Home</a>
|
||||
<a href="{{ url_for('network') }}" class="btn btn-primary">Netzwerk</a>
|
||||
<a href="{{ url_for('dashboard', timeframe='today') }}" class="btn btn-primary">Today</a>
|
||||
<a href="{{ url_for('dashboard', timeframe='7days') }}" class="btn btn-primary">Last 7 Days</a>
|
||||
<a href="{{ url_for('dashboard', timeframe='30days') }}" class="btn btn-primary">Last 30 Days</a>
|
||||
|
||||
81
templates/network.html
Normal file
81
templates/network.html
Normal file
@ -0,0 +1,81 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Recent Connections</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<style>
|
||||
body { margin: 20px; }
|
||||
canvas { max-width: 100%; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1 class="mb-4">kürzlich verbunden... (in der letzten Minute)</h1>
|
||||
<div class="mb-3">
|
||||
<a href="{{ url_for('index') }}" class="btn btn-primary">Home</a>
|
||||
<a href="{{ url_for('dashboard') }}" class="btn btn-primary">Dashboard</a>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover">
|
||||
<thead class="table-info">
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Timestamp</th>
|
||||
<th>Full Path</th>
|
||||
<th>IP Address</th>
|
||||
<th>User Agent</th>
|
||||
<th>Referrer</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="connectionsTableBody">
|
||||
<!-- Rows will be dynamically inserted here -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Socket.IO client library -->
|
||||
<script src="https://cdn.socket.io/4.0.0/socket.io.min.js"></script>
|
||||
<!-- Using vanilla JavaScript for dynamic DOM updates -->
|
||||
<script>
|
||||
const socket = io();
|
||||
socket.on('recent_connections', function(data) {
|
||||
const tbody = document.getElementById('connectionsTableBody');
|
||||
tbody.innerHTML = ''; // Clear previous content
|
||||
|
||||
data.forEach(record => {
|
||||
const row = document.createElement('tr');
|
||||
|
||||
// Create cells for each column
|
||||
const idCell = document.createElement('td');
|
||||
idCell.textContent = record.id;
|
||||
const timestampCell = document.createElement('td');
|
||||
timestampCell.textContent = record.timestamp;
|
||||
const fullPathCell = document.createElement('td');
|
||||
fullPathCell.textContent = record.full_path;
|
||||
const ipCell = document.createElement('td');
|
||||
ipCell.textContent = record.ip_address;
|
||||
const userAgentCell = document.createElement('td');
|
||||
userAgentCell.textContent = record.user_agent;
|
||||
const referrerCell = document.createElement('td');
|
||||
referrerCell.textContent = record.referrer;
|
||||
|
||||
// Append cells to the row
|
||||
row.appendChild(idCell);
|
||||
row.appendChild(timestampCell);
|
||||
row.appendChild(fullPathCell);
|
||||
row.appendChild(ipCell);
|
||||
row.appendChild(userAgentCell);
|
||||
row.appendChild(referrerCell);
|
||||
|
||||
// Append the row to the table body
|
||||
tbody.appendChild(row);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<!-- Bootstrap 5 JS Bundle -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
x
Reference in New Issue
Block a user