add device_id
This commit is contained in:
parent
2b58bd74cc
commit
531e728b13
68
analytics.py
68
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)
|
||||
unique_user=unique_user)
|
||||
3
app.py
3
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)
|
||||
|
||||
5
auth.py
5
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')
|
||||
|
||||
@ -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 }
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user