add device_id

This commit is contained in:
lelo 2025-03-26 22:43:39 +00:00
parent 2b58bd74cc
commit 531e728b13
4 changed files with 50 additions and 44 deletions

View File

@ -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)
unique_user=unique_user)

3
app.py
View File

@ -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)

View File

@ -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')

View File

@ -58,7 +58,7 @@
<div class="card text-white bg-warning">
<div class="card-body">
<h5 class="card-title">eindeutige Nutzer</h5>
<p class="card-text">{{ unique_ips }}</p>
<p class="card-text">{{ unique_user }}</p>
</div>
</div>
</div>
@ -93,12 +93,12 @@
</div>
</div>
</div>
<!-- Referrer Distribution Chart -->
<!-- Folder Distribution Chart -->
<div class="col-md-6 mb-4">
<div class="card">
<div class="card-body">
<h5 class="card-title">Verteilung auf Ordner</h5>
<canvas id="referrerChart"></canvas>
<canvas id="folderChart"></canvas>
</div>
</div>
</div>
@ -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 }