import logging from datetime import datetime, timedelta from zoneinfo import ZoneInfo from flask import Blueprint, request, send_file import config from auth.decorators import login_required from utils.export import create_excel_export, create_csv_export, prepare_audit_export_data, format_datetime_for_export from db import get_connection # Create Blueprint export_bp = Blueprint('export', __name__, url_prefix='/export') @export_bp.route("/licenses") @login_required def export_licenses(): """Exportiert Lizenzen als Excel-Datei""" conn = get_connection() cur = conn.cursor() try: # Nur reale Daten exportieren - keine Fake-Daten query = """ SELECT l.id, l.license_key, c.name as customer_name, c.email as customer_email, l.license_type, l.valid_from, l.valid_until, l.is_active, l.device_limit, l.created_at, l.is_fake, CASE WHEN l.valid_until < CURRENT_DATE THEN 'Abgelaufen' WHEN l.is_active = false THEN 'Deaktiviert' ELSE 'Aktiv' END as status, (SELECT COUNT(*) FROM sessions s WHERE s.license_key = l.license_key AND s.is_active = true) as active_sessions, (SELECT COUNT(DISTINCT hardware_id) FROM sessions s WHERE s.license_key = l.license_key) as registered_devices FROM licenses l LEFT JOIN customers c ON l.customer_id = c.id WHERE l.is_fake = false ORDER BY l.created_at DESC """ cur.execute(query) # Daten für Export vorbereiten data = [] columns = ['ID', 'Lizenzschlüssel', 'Kunde', 'E-Mail', 'Typ', 'Gültig von', 'Gültig bis', 'Aktiv', 'Gerätelimit', 'Erstellt am', 'Fake-Lizenz', 'Status', 'Aktive Sessions', 'Registrierte Geräte'] for row in cur.fetchall(): row_data = list(row) # Format datetime fields if row_data[5]: # valid_from row_data[5] = format_datetime_for_export(row_data[5]) if row_data[6]: # valid_until row_data[6] = format_datetime_for_export(row_data[6]) if row_data[9]: # created_at row_data[9] = format_datetime_for_export(row_data[9]) data.append(row_data) # Format prüfen format_type = request.args.get('format', 'excel').lower() if format_type == 'csv': # CSV-Datei erstellen return create_csv_export(data, columns, 'lizenzen') else: # Excel-Datei erstellen return create_excel_export(data, columns, 'lizenzen') except Exception as e: logging.error(f"Fehler beim Export: {str(e)}") return "Fehler beim Exportieren der Lizenzen", 500 finally: cur.close() conn.close() @export_bp.route("/audit") @login_required def export_audit(): """Exportiert Audit-Logs als Excel-Datei""" conn = get_connection() cur = conn.cursor() try: # Filter aus Request days = int(request.args.get('days', 30)) action_filter = request.args.get('action', '') entity_type_filter = request.args.get('entity_type', '') # Query aufbauen query = """ SELECT id, timestamp, username, action, entity_type, entity_id, ip_address, user_agent, old_values, new_values, additional_info FROM audit_log WHERE timestamp >= CURRENT_TIMESTAMP - INTERVAL '%s days' """ params = [days] if action_filter: query += " AND action = %s" params.append(action_filter) if entity_type_filter: query += " AND entity_type = %s" params.append(entity_type_filter) query += " ORDER BY timestamp DESC" cur.execute(query, params) # Daten in Dictionary-Format umwandeln audit_logs = [] for row in cur.fetchall(): audit_logs.append({ 'id': row[0], 'timestamp': row[1], 'username': row[2], 'action': row[3], 'entity_type': row[4], 'entity_id': row[5], 'ip_address': row[6], 'user_agent': row[7], 'old_values': row[8], 'new_values': row[9], 'additional_info': row[10] }) # Daten für Export vorbereiten data = prepare_audit_export_data(audit_logs) # Excel-Datei erstellen columns = ['ID', 'Zeitstempel', 'Benutzer', 'Aktion', 'Entität', 'Entität ID', 'IP-Adresse', 'User Agent', 'Alte Werte', 'Neue Werte', 'Zusatzinfo'] # Format prüfen format_type = request.args.get('format', 'excel').lower() if format_type == 'csv': # CSV-Datei erstellen return create_csv_export(data, columns, 'audit_log') else: # Excel-Datei erstellen return create_excel_export(data, columns, 'audit_log') except Exception as e: logging.error(f"Fehler beim Export: {str(e)}") return "Fehler beim Exportieren der Audit-Logs", 500 finally: cur.close() conn.close() @export_bp.route("/customers") @login_required def export_customers(): """Exportiert Kunden als Excel-Datei""" conn = get_connection() cur = conn.cursor() try: # SQL Query - nur reale Kunden exportieren cur.execute(""" SELECT c.id, c.name, c.email, c.phone, c.address, c.created_at, c.is_fake, COUNT(l.id) as license_count, COUNT(CASE WHEN l.is_active = true THEN 1 END) as active_licenses, COUNT(CASE WHEN l.valid_until < CURRENT_DATE THEN 1 END) as expired_licenses FROM customers c LEFT JOIN licenses l ON c.id = l.customer_id WHERE c.is_fake = false GROUP BY c.id, c.name, c.email, c.phone, c.address, c.created_at, c.is_fake ORDER BY c.name """) # Daten für Export vorbereiten data = [] columns = ['ID', 'Name', 'E-Mail', 'Telefon', 'Adresse', 'Erstellt am', 'Test-Kunde', 'Anzahl Lizenzen', 'Aktive Lizenzen', 'Abgelaufene Lizenzen'] for row in cur.fetchall(): # Format datetime fields (created_at ist Spalte 5) row_data = list(row) if row_data[5]: # created_at row_data[5] = format_datetime_for_export(row_data[5]) data.append(row_data) # Format prüfen format_type = request.args.get('format', 'excel').lower() if format_type == 'csv': # CSV-Datei erstellen return create_csv_export(data, columns, 'kunden') else: # Excel-Datei erstellen return create_excel_export(data, columns, 'kunden') except Exception as e: logging.error(f"Fehler beim Export: {str(e)}") return "Fehler beim Exportieren der Kunden", 500 finally: cur.close() conn.close() @export_bp.route("/sessions") @login_required def export_sessions(): """Exportiert Sessions als Excel-Datei""" conn = get_connection() cur = conn.cursor() try: # Filter aus Request days = int(request.args.get('days', 7)) active_only = request.args.get('active_only', 'false') == 'true' # SQL Query if active_only: query = """ SELECT s.id, s.license_key, l.customer_name, s.username, s.hardware_id, s.started_at, s.ended_at, s.last_heartbeat, s.is_active, l.license_type, l.is_fake FROM sessions s LEFT JOIN licenses l ON s.license_key = l.license_key WHERE s.is_active = true AND l.is_fake = false ORDER BY s.started_at DESC """ cur.execute(query) else: query = """ SELECT s.id, s.license_key, l.customer_name, s.username, s.hardware_id, s.started_at, s.ended_at, s.last_heartbeat, s.is_active, l.license_type, l.is_fake FROM sessions s LEFT JOIN licenses l ON s.license_key = l.license_key WHERE s.started_at >= CURRENT_TIMESTAMP - INTERVAL '%s days' AND l.is_fake = false ORDER BY s.started_at DESC """ cur.execute(query, (days,)) # Daten für Export vorbereiten data = [] columns = ['ID', 'Lizenzschlüssel', 'Kunde', 'Benutzer', 'Geräte-ID', 'Login-Zeit', 'Logout-Zeit', 'Letzte Aktivität', 'Aktiv', 'Lizenztyp', 'Fake-Lizenz'] for row in cur.fetchall(): row_data = list(row) # Format datetime fields if row_data[5]: # started_at row_data[5] = format_datetime_for_export(row_data[5]) if row_data[6]: # ended_at row_data[6] = format_datetime_for_export(row_data[6]) if row_data[7]: # last_heartbeat row_data[7] = format_datetime_for_export(row_data[7]) data.append(row_data) # Format prüfen format_type = request.args.get('format', 'excel').lower() if format_type == 'csv': # CSV-Datei erstellen return create_csv_export(data, columns, 'sessions') else: # Excel-Datei erstellen return create_excel_export(data, columns, 'sessions') except Exception as e: logging.error(f"Fehler beim Export: {str(e)}") return "Fehler beim Exportieren der Sessions", 500 finally: cur.close() conn.close() @export_bp.route("/resources") @login_required def export_resources(): """Exportiert Ressourcen als Excel-Datei""" conn = get_connection() cur = conn.cursor() try: # Filter aus Request resource_type = request.args.get('type', 'all') status_filter = request.args.get('status', 'all') # SQL Query aufbauen query = """ SELECT rp.id, rp.resource_type, rp.resource_value, rp.status, rp.is_fake, l.license_key, c.name as customer_name, rp.created_at, rp.created_by, rp.status_changed_at, rp.status_changed_by, rp.quarantine_reason FROM resource_pools rp LEFT JOIN licenses l ON rp.allocated_to_license = l.id LEFT JOIN customers c ON l.customer_id = c.id WHERE 1=1 """ params = [] if resource_type != 'all': query += " AND rp.resource_type = %s" params.append(resource_type) if status_filter != 'all': query += " AND rp.status = %s" params.append(status_filter) # Immer nur reale Ressourcen exportieren query += " AND rp.is_fake = false" query += " ORDER BY rp.resource_type, rp.resource_value" cur.execute(query, params) # Daten für Export vorbereiten data = [] columns = ['ID', 'Typ', 'Wert', 'Status', 'Test-Ressource', 'Lizenzschlüssel', 'Kunde', 'Erstellt am', 'Erstellt von', 'Status geändert am', 'Status geändert von', 'Quarantäne-Grund'] for row in cur.fetchall(): row_data = list(row) # Format datetime fields if row_data[7]: # created_at row_data[7] = format_datetime_for_export(row_data[7]) if row_data[9]: # status_changed_at row_data[9] = format_datetime_for_export(row_data[9]) data.append(row_data) # Format prüfen format_type = request.args.get('format', 'excel').lower() if format_type == 'csv': # CSV-Datei erstellen return create_csv_export(data, columns, 'ressourcen') else: # Excel-Datei erstellen return create_excel_export(data, columns, 'ressourcen') except Exception as e: logging.error(f"Fehler beim Export: {str(e)}") return "Fehler beim Exportieren der Ressourcen", 500 finally: cur.close() conn.close() @export_bp.route("/monitoring") @login_required def export_monitoring(): """Exportiert Monitoring-Daten als Excel/CSV-Datei""" conn = get_connection() cur = conn.cursor() try: # Zeitraum aus Request hours = int(request.args.get('hours', 24)) # Monitoring-Daten sammeln data = [] columns = ['Zeitstempel', 'Lizenz-ID', 'Lizenzschlüssel', 'Kunde', 'Hardware-ID', 'IP-Adresse', 'Ereignis-Typ', 'Schweregrad', 'Beschreibung'] # Query für Heartbeats und optionale Anomalien query = """ WITH monitoring_data AS ( -- Lizenz-Heartbeats SELECT lh.timestamp, lh.license_id, l.license_key, c.name as customer_name, lh.hardware_id, lh.ip_address, 'Heartbeat' as event_type, 'Normal' as severity, 'License validation' as description FROM license_heartbeats lh JOIN licenses l ON l.id = lh.license_id JOIN customers c ON c.id = l.customer_id WHERE lh.timestamp > CURRENT_TIMESTAMP - INTERVAL '%s hours' AND l.is_fake = false """ # Check if anomaly_detections table exists cur.execute(""" SELECT EXISTS ( SELECT FROM information_schema.tables WHERE table_name = 'anomaly_detections' ) """) has_anomalies = cur.fetchone()[0] if has_anomalies: query += """ UNION ALL -- Anomalien SELECT ad.detected_at as timestamp, ad.license_id, l.license_key, c.name as customer_name, ad.hardware_id, ad.ip_address, ad.anomaly_type as event_type, ad.severity, ad.description FROM anomaly_detections ad LEFT JOIN licenses l ON l.id = ad.license_id LEFT JOIN customers c ON c.id = l.customer_id WHERE ad.detected_at > CURRENT_TIMESTAMP - INTERVAL '%s hours' AND (l.is_fake = false OR l.is_fake IS NULL) """ params = [hours, hours] else: params = [hours] query += """ ) SELECT * FROM monitoring_data ORDER BY timestamp DESC """ cur.execute(query, params) for row in cur.fetchall(): row_data = list(row) # Format datetime field (timestamp ist Spalte 0) if row_data[0]: # timestamp row_data[0] = format_datetime_for_export(row_data[0]) data.append(row_data) # Format prüfen format_type = request.args.get('format', 'excel').lower() if format_type == 'csv': # CSV-Datei erstellen return create_csv_export(data, columns, 'monitoring') else: # Excel-Datei erstellen return create_excel_export(data, columns, 'monitoring') except Exception as e: logging.error(f"Fehler beim Export: {str(e)}") return "Fehler beim Exportieren der Monitoring-Daten", 500 finally: cur.close() conn.close()