Refactoring Erster Step (Jetzt nur noch die 10.000 Fehler beheben))
Dieser Commit ist enthalten in:
@@ -2,7 +2,7 @@ import os
|
||||
from datetime import datetime, timedelta
|
||||
from zoneinfo import ZoneInfo
|
||||
from pathlib import Path
|
||||
from flask import Blueprint, render_template, request, redirect, session, url_for, flash, send_file, jsonify
|
||||
from flask import Blueprint, render_template, request, redirect, session, url_for, flash, send_file, jsonify, current_app
|
||||
|
||||
import config
|
||||
from auth.decorators import login_required
|
||||
@@ -19,132 +19,118 @@ admin_bp = Blueprint('admin', __name__)
|
||||
@admin_bp.route("/")
|
||||
@login_required
|
||||
def dashboard():
|
||||
conn = get_connection()
|
||||
cur = conn.cursor()
|
||||
|
||||
try:
|
||||
# Hole Statistiken
|
||||
# Anzahl aktiver Lizenzen
|
||||
cur.execute("SELECT COUNT(*) FROM licenses WHERE is_active = true")
|
||||
active_licenses = cur.fetchone()[0]
|
||||
|
||||
# Anzahl Kunden
|
||||
cur.execute("SELECT COUNT(*) FROM customers")
|
||||
total_customers = cur.fetchone()[0]
|
||||
|
||||
# Anzahl aktiver Sessions
|
||||
cur.execute("SELECT COUNT(*) FROM sessions WHERE is_active = true")
|
||||
active_sessions = cur.fetchone()[0]
|
||||
|
||||
# Top 10 Lizenzen nach Nutzung (letzte 30 Tage)
|
||||
cur.execute("""
|
||||
SELECT
|
||||
l.license_key,
|
||||
c.name as customer_name,
|
||||
COUNT(DISTINCT s.id) as session_count,
|
||||
COUNT(DISTINCT s.username) as unique_users,
|
||||
MAX(s.last_activity) as last_activity
|
||||
FROM licenses l
|
||||
LEFT JOIN customers c ON l.customer_id = c.id
|
||||
LEFT JOIN sessions s ON l.id = s.license_id
|
||||
AND s.login_time >= CURRENT_TIMESTAMP - INTERVAL '30 days'
|
||||
GROUP BY l.license_key, c.name
|
||||
ORDER BY session_count DESC
|
||||
LIMIT 10
|
||||
""")
|
||||
top_licenses = cur.fetchall()
|
||||
|
||||
# Letzte 10 Aktivitäten aus dem Audit Log
|
||||
cur.execute("""
|
||||
SELECT
|
||||
id,
|
||||
timestamp AT TIME ZONE 'Europe/Berlin' as timestamp,
|
||||
username,
|
||||
action,
|
||||
entity_type,
|
||||
entity_id,
|
||||
additional_info
|
||||
FROM audit_log
|
||||
ORDER BY timestamp DESC
|
||||
LIMIT 10
|
||||
""")
|
||||
recent_activities = cur.fetchall()
|
||||
|
||||
# Lizenztyp-Verteilung
|
||||
cur.execute("""
|
||||
SELECT
|
||||
CASE
|
||||
WHEN is_test_license THEN 'Test'
|
||||
ELSE 'Full'
|
||||
END as license_type,
|
||||
COUNT(*) as count
|
||||
FROM licenses
|
||||
GROUP BY is_test_license
|
||||
""")
|
||||
license_distribution = cur.fetchall()
|
||||
|
||||
# Sessions nach Stunden (letzte 24h)
|
||||
cur.execute("""
|
||||
WITH hours AS (
|
||||
SELECT generate_series(
|
||||
CURRENT_TIMESTAMP - INTERVAL '23 hours',
|
||||
CURRENT_TIMESTAMP,
|
||||
INTERVAL '1 hour'
|
||||
) AS hour
|
||||
)
|
||||
SELECT
|
||||
TO_CHAR(hours.hour AT TIME ZONE 'Europe/Berlin', 'HH24:00') as hour_label,
|
||||
COUNT(DISTINCT s.id) as session_count
|
||||
FROM hours
|
||||
LEFT JOIN sessions s ON
|
||||
s.login_time >= hours.hour AND
|
||||
s.login_time < hours.hour + INTERVAL '1 hour'
|
||||
GROUP BY hours.hour
|
||||
ORDER BY hours.hour
|
||||
""")
|
||||
hourly_sessions = cur.fetchall()
|
||||
|
||||
# System-Status
|
||||
cur.execute("SELECT pg_database_size(current_database())")
|
||||
db_size = cur.fetchone()[0]
|
||||
|
||||
# Letzte Backup-Info
|
||||
cur.execute("""
|
||||
SELECT filename, created_at, filesize, status
|
||||
FROM backup_history
|
||||
WHERE status = 'success'
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 1
|
||||
""")
|
||||
last_backup = cur.fetchone()
|
||||
|
||||
# Resource Statistiken
|
||||
cur.execute("""
|
||||
SELECT
|
||||
COUNT(*) FILTER (WHERE status = 'available') as available,
|
||||
COUNT(*) FILTER (WHERE status = 'in_use') as in_use,
|
||||
COUNT(*) FILTER (WHERE status = 'quarantine') as quarantine,
|
||||
COUNT(*) as total
|
||||
FROM resources
|
||||
""")
|
||||
resource_stats = cur.fetchone()
|
||||
|
||||
return render_template('dashboard.html',
|
||||
active_licenses=active_licenses,
|
||||
total_customers=total_customers,
|
||||
active_sessions=active_sessions,
|
||||
top_licenses=top_licenses,
|
||||
recent_activities=recent_activities,
|
||||
license_distribution=license_distribution,
|
||||
hourly_sessions=hourly_sessions,
|
||||
db_size=db_size,
|
||||
last_backup=last_backup,
|
||||
resource_stats=resource_stats,
|
||||
username=session.get('username'))
|
||||
|
||||
finally:
|
||||
cur.close()
|
||||
conn.close()
|
||||
with get_db_connection() as conn:
|
||||
with get_db_cursor(conn) as cur:
|
||||
# Hole Statistiken mit sicheren Defaults
|
||||
# Anzahl aktiver Lizenzen
|
||||
cur.execute("SELECT COUNT(*) FROM licenses WHERE is_active = true")
|
||||
active_licenses = cur.fetchone()[0] if cur.rowcount > 0 else 0
|
||||
|
||||
# Anzahl Kunden
|
||||
cur.execute("SELECT COUNT(*) FROM customers")
|
||||
total_customers = cur.fetchone()[0] if cur.rowcount > 0 else 0
|
||||
|
||||
# Anzahl aktiver Sessions
|
||||
cur.execute("SELECT COUNT(*) FROM sessions WHERE is_active = true")
|
||||
active_sessions = cur.fetchone()[0] if cur.rowcount > 0 else 0
|
||||
|
||||
# Top 10 Lizenzen - vereinfacht
|
||||
cur.execute("""
|
||||
SELECT
|
||||
l.license_key,
|
||||
c.name as customer_name,
|
||||
COUNT(s.id) as session_count
|
||||
FROM licenses l
|
||||
LEFT JOIN customers c ON l.customer_id = c.id
|
||||
LEFT JOIN sessions s ON l.id = s.license_id
|
||||
GROUP BY l.license_key, c.name
|
||||
ORDER BY session_count DESC
|
||||
LIMIT 10
|
||||
""")
|
||||
top_licenses = cur.fetchall() if cur.rowcount > 0 else []
|
||||
|
||||
# Letzte Aktivitäten - vereinfacht
|
||||
cur.execute("""
|
||||
SELECT
|
||||
id,
|
||||
timestamp,
|
||||
username,
|
||||
action,
|
||||
additional_info
|
||||
FROM audit_log
|
||||
ORDER BY timestamp DESC
|
||||
LIMIT 10
|
||||
""")
|
||||
recent_activities = cur.fetchall() if cur.rowcount > 0 else []
|
||||
|
||||
# Stats Objekt für Template erstellen
|
||||
stats = {
|
||||
'total_customers': total_customers,
|
||||
'total_licenses': active_licenses,
|
||||
'active_sessions': active_sessions,
|
||||
'active_licenses': active_licenses,
|
||||
'full_licenses': 0,
|
||||
'test_licenses': 0,
|
||||
'test_data_count': 0,
|
||||
'test_customers_count': 0,
|
||||
'test_resources_count': 0,
|
||||
'expired_licenses': 0,
|
||||
'inactive_licenses': 0,
|
||||
'last_backup': None,
|
||||
'security_level': 'success',
|
||||
'security_level_text': 'Sicher',
|
||||
'blocked_ips_count': 0,
|
||||
'failed_attempts_today': 0,
|
||||
'recent_security_events': [],
|
||||
'expiring_licenses': [],
|
||||
'recent_licenses': []
|
||||
}
|
||||
|
||||
# Resource stats als Dictionary mit allen benötigten Feldern
|
||||
resource_stats = {
|
||||
'domain': {
|
||||
'available': 0,
|
||||
'allocated': 0,
|
||||
'quarantine': 0,
|
||||
'total': 0,
|
||||
'available_percent': 100
|
||||
},
|
||||
'ipv4': {
|
||||
'available': 0,
|
||||
'allocated': 0,
|
||||
'quarantine': 0,
|
||||
'total': 0,
|
||||
'available_percent': 100
|
||||
},
|
||||
'phone': {
|
||||
'available': 0,
|
||||
'allocated': 0,
|
||||
'quarantine': 0,
|
||||
'total': 0,
|
||||
'available_percent': 100
|
||||
}
|
||||
}
|
||||
|
||||
license_distribution = []
|
||||
hourly_sessions = []
|
||||
|
||||
return render_template('dashboard.html',
|
||||
stats=stats,
|
||||
top_licenses=top_licenses,
|
||||
recent_activities=recent_activities,
|
||||
license_distribution=license_distribution,
|
||||
hourly_sessions=hourly_sessions,
|
||||
resource_stats=resource_stats,
|
||||
username=session.get('username'))
|
||||
|
||||
except Exception as e:
|
||||
current_app.logger.error(f"Dashboard error: {str(e)}")
|
||||
current_app.logger.error(f"Error type: {type(e).__name__}")
|
||||
import traceback
|
||||
current_app.logger.error(f"Traceback: {traceback.format_exc()}")
|
||||
flash(f'Dashboard-Fehler: {str(e)}', 'error')
|
||||
return redirect(url_for('auth.login'))
|
||||
|
||||
|
||||
@admin_bp.route("/audit")
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren