From 531e728b13043bc701d00f0566237379b61a31d6 Mon Sep 17 00:00:00 2001 From: lelo Date: Wed, 26 Mar 2025 22:43:39 +0000 Subject: [PATCH] add device_id --- analytics.py | 68 +++++++++++++++++++++------------------- app.py | 3 +- auth.py | 5 +++ templates/dashboard.html | 18 +++++------ 4 files changed, 50 insertions(+), 44 deletions(-) diff --git a/analytics.py b/analytics.py index 0d2e500..203441d 100644 --- a/analytics.py +++ b/analytics.py @@ -32,17 +32,10 @@ def get_device_type(user_agent): else: return 'Other' -def shorten_referrer(url): - segments = [seg for seg in url.split('/') if seg] - segment = segments[-1] - # Decode all percent-encoded characters (like %20, %2F, etc.) - segment_decoded = unquote(segment) - return segment_decoded - -def log_file_access(full_path, ip_address, user_agent, referrer): +def log_file_access(rel_path, ip_address, user_agent, device_id): """ Log file access details to a SQLite database. - Records the timestamp, full file path, client IP, user agent, and referrer. + Records the timestamp, full file path, client IP, user agent, and device_id. """ global file_access_temp # Connect to the database (this will create the file if it doesn't exist) @@ -53,10 +46,10 @@ def log_file_access(full_path, ip_address, user_agent, referrer): CREATE TABLE IF NOT EXISTS file_access_log ( id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp TEXT, - full_path TEXT, + rel_path TEXT, ip_address TEXT, user_agent TEXT, - referrer TEXT + device_id TEXT ) ''') # Gather information from the request @@ -64,12 +57,12 @@ def log_file_access(full_path, ip_address, user_agent, referrer): # Insert the access record into the database cursor.execute(''' - INSERT INTO file_access_log (timestamp, full_path, ip_address, user_agent, referrer) + INSERT INTO file_access_log (timestamp, rel_path, ip_address, user_agent, device_id) VALUES (?, ?, ?, ?, ?) - ''', (timestamp, full_path, ip_address, user_agent, referrer)) + ''', (timestamp, rel_path, ip_address, user_agent, device_id)) conn.commit() conn.close() - file_access_temp.insert(0, [timestamp, full_path, ip_address, user_agent, referrer]) + file_access_temp.insert(0, [timestamp, rel_path, ip_address, user_agent, device_id]) return return_file_access() def return_file_access(): @@ -111,10 +104,10 @@ def dashboard(): # Raw file access counts for the table (top files) cursor.execute(''' - SELECT full_path, COUNT(*) as access_count + SELECT rel_path, COUNT(*) as access_count FROM file_access_log WHERE timestamp >= ? - GROUP BY full_path + GROUP BY rel_path ORDER BY access_count DESC LIMIT 20 ''', (start.isoformat(),)) @@ -132,14 +125,14 @@ def dashboard(): # Top files for bar chart cursor.execute(''' - SELECT full_path, COUNT(*) as access_count + SELECT rel_path, COUNT(*) as access_count FROM file_access_log WHERE timestamp >= ? - GROUP BY full_path + GROUP BY rel_path ORDER BY access_count DESC LIMIT 10 ''', (start.isoformat(),)) - top_files_data = [dict(full_path=row[0], access_count=row[1]) for row in cursor.fetchall()] + top_files_data = [dict(rel_path=row[0], access_count=row[1]) for row in cursor.fetchall()] # User agent distribution (aggregate by device type) cursor.execute(''' @@ -157,20 +150,29 @@ def dashboard(): # Rename to user_agent_data for compatibility with the frontend user_agent_data = [dict(device=device, count=count) for device, count in device_counts.items()] - # Referrer distribution (shorten links) + # Parent folder distribution cursor.execute(''' - SELECT referrer, COUNT(*) as count + SELECT rel_path, COUNT(*) as count FROM file_access_log WHERE timestamp >= ? - GROUP BY referrer + GROUP BY rel_path ORDER BY count DESC - LIMIT 10 ''', (start.isoformat(),)) - referrer_data = [] + folder_data = {} for row in cursor.fetchall(): - raw_ref = row[0] - shortened = shorten_referrer(raw_ref) if raw_ref else "Direct/None" - referrer_data.append(dict(referrer=shortened, count=row[1])) + rel_path = row[0] + parent_folder = rel_path.rsplit('/', 1)[0] if '/' in rel_path else "Root" + folder_data[parent_folder] = folder_data.get(parent_folder, 0) + row[1] + + # Convert the dictionary to a list of dictionaries + folder_data = [ + dict(folder=folder, count=count) + for folder, count in folder_data.items() + ] + + # Sort by count in descending order and take the top 10 + folder_data.sort(key=lambda x: x['count'], reverse=True) + folder_data = folder_data[:10] # Aggregate IP addresses with counts cursor.execute(''' @@ -208,13 +210,13 @@ def dashboard(): cursor.execute('SELECT COUNT(*) FROM file_access_log WHERE timestamp >= ?', (start.isoformat(),)) total_accesses = cursor.fetchone()[0] - # Use a separate query to count unique files (distinct full_path values) - cursor.execute('SELECT COUNT(DISTINCT full_path) FROM file_access_log WHERE timestamp >= ?', (start.isoformat(),)) + # Use a separate query to count unique files (distinct rel_path values) + cursor.execute('SELECT COUNT(DISTINCT rel_path) FROM file_access_log WHERE timestamp >= ?', (start.isoformat(),)) unique_files = cursor.fetchone()[0] # Use a separate query to count unique IP addresses - cursor.execute('SELECT COUNT(DISTINCT ip_address) FROM file_access_log WHERE timestamp >= ?', (start.isoformat(),)) - unique_ips = cursor.fetchone()[0] + cursor.execute('SELECT COUNT(DISTINCT device_id) FROM file_access_log WHERE timestamp >= ?', (start.isoformat(),)) + unique_user = cursor.fetchone()[0] conn.close() @@ -224,8 +226,8 @@ def dashboard(): daily_access_data=daily_access_data, top_files_data=top_files_data, user_agent_data=user_agent_data, - referrer_data=referrer_data, + folder_data=folder_data, location_data=location_data, total_accesses=total_accesses, unique_files=unique_files, - unique_ips=unique_ips) \ No newline at end of file + unique_user=unique_user) \ No newline at end of file diff --git a/app.py b/app.py index 5418f68..953a3e1 100755 --- a/app.py +++ b/app.py @@ -205,10 +205,9 @@ def serve_file(subpath): if request.method == 'GET' and (not range_header or (range_header.startswith("bytes=0-") and range_header != "bytes=0-1")): ip_address = request.remote_addr user_agent = request.headers.get('User-Agent') - referrer = request.headers.get('Referer') threading.Thread( target=a.log_file_access, - args=(full_path, ip_address, user_agent, referrer) + args=(subpath, ip_address, user_agent, session['device_id']) ).start() # Check cache first (using diskcache) diff --git a/auth.py b/auth.py index 0118009..182746c 100644 --- a/auth.py +++ b/auth.py @@ -2,6 +2,7 @@ from flask import Flask, render_template, request, redirect, url_for, session from functools import wraps from datetime import datetime, date, timedelta import io +import os import json import qrcode import base64 @@ -72,6 +73,10 @@ def require_secret(f): # 6) If we have folders, proceed; otherwise show index if session['folders']: + # assume since visitor has a valid secret, they are ok with annonymous tracking + # this is required to track the devices connecting over the same ip address + if 'device_id' not in session: + session['device_id'] = os.urandom(32).hex() return f(*args, **kwargs) else: return render_template('index.html') diff --git a/templates/dashboard.html b/templates/dashboard.html index e5f0dff..eb7b7ec 100644 --- a/templates/dashboard.html +++ b/templates/dashboard.html @@ -58,7 +58,7 @@
eindeutige Nutzer
-

{{ unique_ips }}

+

{{ unique_user }}

@@ -93,12 +93,12 @@ - +
Verteilung auf Ordner
- +
@@ -174,7 +174,7 @@ const topFilesData = {{ top_files_data|tojson }}; // Note: user_agent_data now contains 'device' and 'count' const userAgentData = {{ user_agent_data|tojson }}; - const referrerData = {{ referrer_data|tojson }}; + const folderData = {{ folder_data|tojson }}; // Access Trend Chart - Line Chart const ctxTrend = document.getElementById('accessTrendChart').getContext('2d'); @@ -235,14 +235,14 @@ options: { responsive: true } }); - // Referrer Distribution - Pie Chart (with shortened referrers) - const ctxReferrer = document.getElementById('referrerChart').getContext('2d'); - new Chart(ctxReferrer, { + // folder Distribution - Pie Chart (with shortened folders) + const ctxfolder = document.getElementById('folderChart').getContext('2d'); + new Chart(ctxfolder, { type: 'pie', data: { - labels: referrerData.map(item => item.referrer), + labels: folderData.map(item => item.folder), datasets: [{ - data: referrerData.map(item => item.count) + data: folderData.map(item => item.count) }] }, options: { responsive: true }