160 lines
6.3 KiB
Python
160 lines
6.3 KiB
Python
"""
|
|
Session-Blueprint für das 3D-Druck-Management-System
|
|
|
|
Dieses Modul enthält alle Routen und Funktionen für Session-Management.
|
|
"""
|
|
|
|
from flask import Blueprint, jsonify, request, session
|
|
from flask_login import login_required, current_user
|
|
from datetime import datetime, timedelta
|
|
from models import User, get_db_session, SystemLog
|
|
from utils.logging_config import get_logger
|
|
|
|
# Blueprint erstellen
|
|
sessions_blueprint = Blueprint('sessions', __name__, url_prefix='/api/session')
|
|
|
|
# Logger initialisieren
|
|
sessions_logger = get_logger("sessions")
|
|
|
|
# Session-Lifetime sicher importieren und validieren
|
|
def get_session_lifetime_td():
|
|
"""Sichere SESSION_LIFETIME Konvertierung zu timedelta"""
|
|
try:
|
|
from utils.utilities_collection import SESSION_LIFETIME
|
|
# Sicherstellen, dass es ein timedelta ist
|
|
if isinstance(SESSION_LIFETIME, (int, float)):
|
|
return timedelta(seconds=SESSION_LIFETIME)
|
|
elif isinstance(SESSION_LIFETIME, timedelta):
|
|
return SESSION_LIFETIME
|
|
elif hasattr(SESSION_LIFETIME, 'total_seconds'):
|
|
# Bereits ein timedelta-artiges Objekt
|
|
return SESSION_LIFETIME
|
|
else:
|
|
sessions_logger.warning(f"SESSION_LIFETIME hat unerwarteten Typ: {type(SESSION_LIFETIME)}, verwende Fallback")
|
|
return timedelta(hours=1)
|
|
except ImportError:
|
|
sessions_logger.warning("SESSION_LIFETIME konnte nicht importiert werden, verwende Fallback (1h)")
|
|
return timedelta(hours=1)
|
|
except Exception as e:
|
|
sessions_logger.error(f"Fehler beim Importieren von SESSION_LIFETIME: {e}, verwende Fallback")
|
|
return timedelta(hours=1)
|
|
|
|
SESSION_LIFETIME_TD = get_session_lifetime_td()
|
|
|
|
@sessions_blueprint.route('/heartbeat', methods=['POST'])
|
|
@login_required
|
|
def heartbeat():
|
|
"""
|
|
Session-Heartbeat zum Aktualisieren der letzten Aktivität.
|
|
Verhindert automatischen Logout bei aktiven Benutzern.
|
|
"""
|
|
try:
|
|
# 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
|
|
with get_db_session() as db_session:
|
|
user = db_session.query(User).filter_by(id=current_user.id).first()
|
|
if user:
|
|
user.last_activity = datetime.now()
|
|
db_session.commit()
|
|
|
|
# Verbleibende Session-Zeit berechnen
|
|
session_start = session.get('session_start')
|
|
if session_start:
|
|
elapsed = (datetime.now() - datetime.fromisoformat(session_start)).total_seconds()
|
|
remaining = max(0, SESSION_LIFETIME_TD.total_seconds() - elapsed)
|
|
else:
|
|
remaining = SESSION_LIFETIME_TD.total_seconds()
|
|
|
|
return jsonify({
|
|
'success': True,
|
|
'remaining_seconds': int(remaining),
|
|
'session_lifetime': int(SESSION_LIFETIME_TD.total_seconds())
|
|
})
|
|
|
|
except Exception as e:
|
|
sessions_logger.error(f"Fehler beim Session-Heartbeat: {str(e)}")
|
|
return jsonify({'error': 'Fehler beim Aktualisieren der Session'}), 500
|
|
|
|
@sessions_blueprint.route('/status', methods=['GET'])
|
|
@login_required
|
|
def status():
|
|
"""Gibt den aktuellen Session-Status zurück"""
|
|
try:
|
|
# Session-Informationen sammeln
|
|
session_start = session.get('session_start')
|
|
last_activity = session.get('last_activity')
|
|
|
|
# Verbleibende Zeit berechnen
|
|
if session_start:
|
|
elapsed = (datetime.now() - datetime.fromisoformat(session_start)).total_seconds()
|
|
remaining = max(0, SESSION_LIFETIME_TD.total_seconds() - elapsed)
|
|
else:
|
|
remaining = SESSION_LIFETIME_TD.total_seconds()
|
|
|
|
# Inaktivitätszeit berechnen
|
|
if last_activity:
|
|
inactive_seconds = (datetime.now() - datetime.fromisoformat(last_activity)).total_seconds()
|
|
else:
|
|
inactive_seconds = 0
|
|
|
|
return jsonify({
|
|
'success': True,
|
|
'user': {
|
|
'id': current_user.id,
|
|
'username': current_user.username,
|
|
'email': current_user.email,
|
|
'name': current_user.name,
|
|
'is_admin': current_user.is_admin
|
|
},
|
|
'session': {
|
|
'start_time': session_start,
|
|
'last_activity': last_activity,
|
|
'remaining_seconds': int(remaining),
|
|
'inactive_seconds': int(inactive_seconds),
|
|
'lifetime_seconds': int(SESSION_LIFETIME_TD.total_seconds()),
|
|
'is_permanent': session.permanent
|
|
}
|
|
})
|
|
|
|
except Exception as e:
|
|
sessions_logger.error(f"Fehler beim Abrufen des Session-Status: {str(e)}")
|
|
return jsonify({'error': 'Fehler beim Abrufen des Session-Status'}), 500
|
|
|
|
@sessions_blueprint.route('/extend', methods=['POST'])
|
|
@login_required
|
|
def extend():
|
|
"""Verlängert die aktuelle Session"""
|
|
try:
|
|
# Nur Admins können Sessions verlängern
|
|
if not current_user.is_admin:
|
|
return jsonify({'error': 'Keine Berechtigung zum Verlängern der Session'}), 403
|
|
|
|
# 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
|
|
with get_db_session() as db_session:
|
|
SystemLog.log_system_event(
|
|
level="INFO",
|
|
message=f"Session verlängert für Benutzer {current_user.username}",
|
|
module="sessions",
|
|
user_id=current_user.id
|
|
)
|
|
db_session.commit()
|
|
|
|
sessions_logger.info(f"Session verlängert für Benutzer {current_user.id}")
|
|
|
|
return jsonify({
|
|
'success': True,
|
|
'message': 'Session wurde verlängert',
|
|
'new_lifetime_seconds': int(SESSION_LIFETIME_TD.total_seconds())
|
|
})
|
|
|
|
except Exception as e:
|
|
sessions_logger.error(f"Fehler beim Verlängern der Session: {str(e)}")
|
|
return jsonify({'error': 'Fehler beim Verlängern der Session'}), 500 |