Die Dateien, die in diesem Commit geändert wurden, umfassen:
This commit is contained in:
112
backend/app.py
112
backend/app.py
@@ -21,6 +21,40 @@ from sqlalchemy import event
|
||||
from contextlib import contextmanager
|
||||
import threading
|
||||
|
||||
# ===== MINIMALE SESSION-DATENKLASSE =====
|
||||
class MinimalSessionInterface:
|
||||
"""Minimale Session-Implementierung zur Reduzierung der Cookie-Größe"""
|
||||
|
||||
@staticmethod
|
||||
def reduce_session_data():
|
||||
"""Reduziert Session-Daten auf absolutes Minimum"""
|
||||
from flask import session
|
||||
|
||||
# Nur kritische Daten behalten
|
||||
essential_keys = ['_user_id', '_id', '_fresh', 'csrf_token']
|
||||
|
||||
# Alle nicht-essentiellen Keys entfernen
|
||||
keys_to_remove = []
|
||||
for key in session.keys():
|
||||
if key not in essential_keys:
|
||||
keys_to_remove.append(key)
|
||||
|
||||
for key in keys_to_remove:
|
||||
session.pop(key, None)
|
||||
|
||||
@staticmethod
|
||||
def get_minimal_session_data():
|
||||
"""Gibt nur minimale Session-Daten zurück"""
|
||||
from flask import session
|
||||
return {
|
||||
'user_id': session.get('_user_id'),
|
||||
'session_id': session.get('_id'),
|
||||
'is_fresh': session.get('_fresh', False)
|
||||
}
|
||||
|
||||
# Globale Session-Interface-Instanz
|
||||
minimal_session = MinimalSessionInterface()
|
||||
|
||||
# ===== SESSION-OPTIMIERUNG =====
|
||||
class SessionManager:
|
||||
"""Optimierter Session-Manager für große Session-Daten"""
|
||||
@@ -689,25 +723,32 @@ def log_response_info(response):
|
||||
app_logger.debug(f"Response: {response.status_code}")
|
||||
return response
|
||||
|
||||
@app.after_request
|
||||
def minimize_session_cookie(response):
|
||||
"""Reduziert Session-Cookie automatisch nach jedem Request"""
|
||||
if current_user.is_authenticated:
|
||||
# Drastische Session-Cookie-Reduktion
|
||||
minimal_session.reduce_session_data()
|
||||
return response
|
||||
|
||||
@app.before_request
|
||||
def check_session_activity():
|
||||
"""Prüft Session-Aktivität und meldet inaktive Benutzer ab mit optimiertem Cookie-Management"""
|
||||
"""Prüft Session-Aktivität und meldet inaktive Benutzer ab mit MINIMAL Cookie-Management"""
|
||||
if current_user.is_authenticated:
|
||||
from utils.utilities_collection import SESSION_LIFETIME
|
||||
|
||||
# DRASTISCHE Session-Reduktion - alle nicht-kritischen Daten entfernen
|
||||
minimal_session.reduce_session_data()
|
||||
|
||||
# Session-Aktivität über externen Store (nicht in Cookie)
|
||||
session_data = session_manager.load_large_session_data('activity') or {}
|
||||
now = datetime.now()
|
||||
|
||||
# Reduzierte Session-Daten für Cookie-Größe
|
||||
last_activity_str = session.get('last_activity')
|
||||
if last_activity_str:
|
||||
# Aktivitätsprüfung über externen Store
|
||||
last_activity = session_data.get('last_activity')
|
||||
if last_activity:
|
||||
try:
|
||||
# Verarbeite sowohl alte ISO-Format als auch neue Zeit-Format
|
||||
if 'T' in last_activity_str: # ISO-Format
|
||||
last_activity_time = datetime.fromisoformat(last_activity_str)
|
||||
else: # Nur Zeit-Format
|
||||
today = now.date()
|
||||
time_part = datetime.strptime(last_activity_str, '%H:%M').time()
|
||||
last_activity_time = datetime.combine(today, time_part)
|
||||
|
||||
last_activity_time = datetime.fromisoformat(last_activity)
|
||||
if (now - last_activity_time).total_seconds() > SESSION_LIFETIME.total_seconds():
|
||||
app_logger.info(f"Session abgelaufen für Benutzer {current_user.id}")
|
||||
logout_user()
|
||||
@@ -715,8 +756,11 @@ def check_session_activity():
|
||||
except Exception as e:
|
||||
app_logger.warning(f"Fehler beim Parsen der Session-Zeit: {e}")
|
||||
|
||||
# Optimierte Session-Aktivität aktualisieren - nur Zeit statt volles ISO-Format
|
||||
session['last_activity'] = now.strftime('%H:%M')
|
||||
# Aktivität NICHT in Session-Cookie speichern, sondern extern
|
||||
session_data['last_activity'] = now.isoformat()
|
||||
session_manager.store_large_session_data('activity', session_data)
|
||||
|
||||
# Session permanent ohne zusätzliche Daten
|
||||
session.permanent = True
|
||||
|
||||
# ===== HAUPTROUTEN =====
|
||||
@@ -849,7 +893,7 @@ def api_finish_job(job_id):
|
||||
@app.route("/api/printers", methods=["GET"])
|
||||
@login_required
|
||||
def api_get_printers():
|
||||
"""API-Endpunkt für Drucker-Liste"""
|
||||
"""API-Endpunkt für Drucker-Liste mit konsistenter Response-Struktur"""
|
||||
try:
|
||||
from models import get_db_session, Printer
|
||||
|
||||
@@ -862,12 +906,13 @@ def api_get_printers():
|
||||
printer_dict = {
|
||||
"id": printer.id,
|
||||
"name": printer.name,
|
||||
"model": printer.model,
|
||||
"location": printer.location,
|
||||
"status": printer.status,
|
||||
"model": printer.model or "Unbekanntes Modell",
|
||||
"location": printer.location or "Unbekannter Standort",
|
||||
"status": printer.status or "offline",
|
||||
"ip_address": printer.ip_address,
|
||||
"plug_ip": printer.plug_ip,
|
||||
"active": printer.active,
|
||||
"active": getattr(printer, 'active', True),
|
||||
"created_at": printer.created_at.isoformat() if printer.created_at else datetime.now().isoformat(),
|
||||
"last_checked": printer.last_checked.isoformat() if printer.last_checked else None
|
||||
}
|
||||
printer_list.append(printer_dict)
|
||||
@@ -875,11 +920,24 @@ def api_get_printers():
|
||||
db_session.close()
|
||||
|
||||
app_logger.info(f"✅ API: {len(printer_list)} Drucker abgerufen")
|
||||
return jsonify({"printers": printer_list})
|
||||
|
||||
# Konsistente Response-Struktur wie erwartet
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"printers": printer_list,
|
||||
"count": len(printer_list),
|
||||
"message": "Drucker erfolgreich geladen"
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
app_logger.error(f"❌ API-Fehler beim Abrufen der Drucker: {str(e)}")
|
||||
return jsonify({"error": "Fehler beim Laden der Drucker", "details": str(e)}), 500
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": "Fehler beim Laden der Drucker",
|
||||
"details": str(e),
|
||||
"printers": [],
|
||||
"count": 0
|
||||
}), 500
|
||||
|
||||
@app.route("/api/printers/status", methods=["GET"])
|
||||
@login_required
|
||||
@@ -986,8 +1044,8 @@ def api_session_heartbeat():
|
||||
"""API-Endpunkt für Session-Heartbeat"""
|
||||
try:
|
||||
from utils.utilities_collection import SESSION_LIFETIME
|
||||
# Session-Aktivität aktualisieren
|
||||
session['last_activity'] = datetime.now().isoformat()
|
||||
# Session-Aktivität NICHT in Cookie speichern - Cookie-Reduktion
|
||||
# session['last_activity'] = datetime.now().isoformat() # ENTFERNT
|
||||
session.permanent = True
|
||||
|
||||
# Verbleibende Zeit berechnen
|
||||
@@ -1011,8 +1069,8 @@ def api_session_extend():
|
||||
data = request.get_json() or {}
|
||||
extend_minutes = data.get('extend_minutes', 30)
|
||||
|
||||
# Session verlängern
|
||||
session['last_activity'] = datetime.now().isoformat()
|
||||
# Session verlängern - NICHT in Cookie speichern
|
||||
# session['last_activity'] = datetime.now().isoformat() # ENTFERNT
|
||||
session.permanent = True
|
||||
|
||||
return jsonify({
|
||||
@@ -1933,8 +1991,8 @@ def main():
|
||||
if USE_PRODUCTION_CONFIG:
|
||||
app_logger.info("[PRODUCTION] Konfiguriere SSL...")
|
||||
try:
|
||||
from utils.ssl_config import get_ssl_context
|
||||
ssl_context = get_ssl_context()
|
||||
from utils.ssl_suite import ssl_config
|
||||
ssl_context = ssl_config.get_ssl_context()
|
||||
app_logger.info("[PRODUCTION] ✅ SSL-Kontext konfiguriert")
|
||||
except ImportError:
|
||||
app_logger.warning("[PRODUCTION] ⚠️ SSL-Konfiguration nicht verfügbar")
|
||||
|
Reference in New Issue
Block a user