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")
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -125,8 +125,8 @@ def system_status():
|
||||
def heartbeat():
|
||||
"""Heartbeat-Endpunkt für Frontend-Verbindungsmonitoring"""
|
||||
try:
|
||||
# Session-Aktivität aktualisieren
|
||||
session['last_heartbeat'] = datetime.now().strftime('%H:%M:%S')
|
||||
# Session-Aktivität NICHT in Cookie speichern
|
||||
# session['last_heartbeat'] = datetime.now().strftime('%H:%M:%S') # ENTFERNT
|
||||
session.permanent = True
|
||||
|
||||
return jsonify({
|
||||
|
@ -25,8 +25,8 @@ def heartbeat():
|
||||
Verhindert automatischen Logout bei aktiven Benutzern.
|
||||
"""
|
||||
try:
|
||||
# Session-Aktivität aktualisieren
|
||||
session['last_activity'] = datetime.now().isoformat()
|
||||
# Session-Aktivität NICHT in Cookie speichern - verwende externen Store
|
||||
# session['last_activity'] = datetime.now().isoformat() # ENTFERNT
|
||||
session.permanent = True
|
||||
|
||||
# Benutzer-Aktivität in Datenbank aktualisieren
|
||||
@ -108,9 +108,9 @@ def extend():
|
||||
if not current_user.is_admin:
|
||||
return jsonify({'error': 'Keine Berechtigung zum Verlängern der Session'}), 403
|
||||
|
||||
# Session-Start zurücksetzen
|
||||
session['session_start'] = datetime.now().isoformat()
|
||||
session['last_activity'] = datetime.now().isoformat()
|
||||
# Session-Daten NICHT in Cookie speichern - verwende externen Store
|
||||
# session['session_start'] = datetime.now().isoformat() # ENTFERNT
|
||||
# session['last_activity'] = datetime.now().isoformat() # ENTFERNT
|
||||
session.permanent = True
|
||||
|
||||
# SystemLog erstellen
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user