2025-06-04 10:03:22 +02:00

335 lines
12 KiB
Python

"""
Admin-Blueprint für das 3D-Druck-Management-System
Dieses Modul enthält alle Admin-spezifischen Routen und Funktionen,
einschließlich Benutzerverwaltung, Systemüberwachung und Drucker-Administration.
"""
from flask import Blueprint, render_template, request, jsonify, redirect, url_for, flash
from flask_login import login_required, current_user
from functools import wraps
from models import User, Printer, Job, get_db_session, Stats, SystemLog
from utils.logging_config import get_logger
from datetime import datetime
# Blueprint erstellen
admin_blueprint = Blueprint('admin', __name__, url_prefix='/admin')
# Logger initialisieren
admin_logger = get_logger("admin")
def admin_required(f):
"""Decorator für Admin-Berechtigung"""
@wraps(f)
@login_required
def decorated_function(*args, **kwargs):
admin_logger.info(f"Admin-Check für Funktion {f.__name__}: User authenticated: {current_user.is_authenticated}, User ID: {current_user.id if current_user.is_authenticated else 'None'}, Is Admin: {current_user.is_admin if current_user.is_authenticated else 'None'}")
if not current_user.is_admin:
admin_logger.warning(f"Admin-Zugriff verweigert für User {current_user.id if current_user.is_authenticated else 'Anonymous'} auf Funktion {f.__name__}")
return jsonify({"error": "Nur Administratoren haben Zugriff"}), 403
return f(*args, **kwargs)
return decorated_function
@admin_blueprint.route("/")
@login_required
@admin_required
def admin_dashboard():
"""Admin-Dashboard-Hauptseite"""
try:
db_session = get_db_session()
# Grundlegende Statistiken sammeln
total_users = db_session.query(User).count()
total_printers = db_session.query(Printer).count()
total_jobs = db_session.query(Job).count()
# Aktive Jobs zählen
active_jobs = db_session.query(Job).filter(
Job.status.in_(['pending', 'printing', 'paused'])
).count()
db_session.close()
stats = {
'total_users': total_users,
'total_printers': total_printers,
'total_jobs': total_jobs,
'active_jobs': active_jobs
}
return render_template('admin/dashboard.html', stats=stats)
except Exception as e:
admin_logger.error(f"Fehler beim Laden des Admin-Dashboards: {str(e)}")
flash("Fehler beim Laden der Dashboard-Daten", "error")
return render_template('admin/dashboard.html', stats={})
@admin_blueprint.route("/users")
@login_required
@admin_required
def users_overview():
"""Benutzerübersicht für Administratoren"""
return render_template('admin/users.html')
@admin_blueprint.route("/users/add", methods=["GET"])
@login_required
@admin_required
def add_user_page():
"""Seite zum Hinzufügen eines neuen Benutzers"""
return render_template('admin/add_user.html')
@admin_blueprint.route("/users/<int:user_id>/edit", methods=["GET"])
@login_required
@admin_required
def edit_user_page(user_id):
"""Seite zum Bearbeiten eines Benutzers"""
try:
db_session = get_db_session()
user = db_session.query(User).filter(User.id == user_id).first()
if not user:
db_session.close()
flash("Benutzer nicht gefunden", "error")
return redirect(url_for('admin.users_overview'))
db_session.close()
return render_template('admin/edit_user.html', user=user)
except Exception as e:
admin_logger.error(f"Fehler beim Laden der Benutzer-Bearbeitung: {str(e)}")
flash("Fehler beim Laden der Benutzerdaten", "error")
return redirect(url_for('admin.users_overview'))
@admin_blueprint.route("/printers")
@login_required
@admin_required
def printers_overview():
"""Druckerübersicht für Administratoren"""
return render_template('admin/printers.html')
@admin_blueprint.route("/printers/add", methods=["GET"])
@login_required
@admin_required
def add_printer_page():
"""Seite zum Hinzufügen eines neuen Druckers"""
return render_template('admin/add_printer.html')
@admin_blueprint.route("/printers/<int:printer_id>/edit", methods=["GET"])
@login_required
@admin_required
def edit_printer_page(printer_id):
"""Seite zum Bearbeiten eines Druckers"""
try:
db_session = get_db_session()
printer = db_session.query(Printer).filter(Printer.id == printer_id).first()
if not printer:
db_session.close()
flash("Drucker nicht gefunden", "error")
return redirect(url_for('admin.printers_overview'))
db_session.close()
return render_template('admin/edit_printer.html', printer=printer)
except Exception as e:
admin_logger.error(f"Fehler beim Laden der Drucker-Bearbeitung: {str(e)}")
flash("Fehler beim Laden der Druckerdaten", "error")
return redirect(url_for('admin.printers_overview'))
@admin_blueprint.route("/guest-requests")
@login_required
@admin_required
def guest_requests():
"""Gäste-Anfragen-Übersicht"""
return render_template('admin/guest_requests.html')
@admin_blueprint.route("/advanced-settings")
@login_required
@admin_required
def advanced_settings():
"""Erweiterte Systemeinstellungen"""
return render_template('admin/advanced_settings.html')
@admin_blueprint.route("/system-health")
@login_required
@admin_required
def system_health():
"""System-Gesundheitsstatus"""
return render_template('admin/system_health.html')
@admin_blueprint.route("/logs")
@login_required
@admin_required
def logs_overview():
"""System-Logs-Übersicht"""
return render_template('admin/logs.html')
@admin_blueprint.route("/maintenance")
@login_required
@admin_required
def maintenance():
"""Wartungsseite"""
return render_template('admin/maintenance.html')
# API-Endpunkte für Admin-Funktionen
@admin_blueprint.route("/api/users", methods=["POST"])
@login_required
@admin_required
def create_user_api():
"""API-Endpunkt zum Erstellen eines neuen Benutzers"""
try:
data = request.get_json()
# Validierung der erforderlichen Felder
required_fields = ['username', 'email', 'password', 'name']
for field in required_fields:
if field not in data or not data[field]:
return jsonify({"error": f"Feld '{field}' ist erforderlich"}), 400
db_session = get_db_session()
# Überprüfung auf bereits existierende Benutzer
existing_user = db_session.query(User).filter(
(User.username == data['username']) | (User.email == data['email'])
).first()
if existing_user:
db_session.close()
return jsonify({"error": "Benutzername oder E-Mail bereits vergeben"}), 400
# Neuen Benutzer erstellen
new_user = User(
username=data['username'],
email=data['email'],
name=data['name'],
role=data.get('role', 'user'),
department=data.get('department'),
position=data.get('position'),
phone=data.get('phone'),
bio=data.get('bio')
)
new_user.set_password(data['password'])
db_session.add(new_user)
db_session.commit()
admin_logger.info(f"Neuer Benutzer erstellt: {new_user.username} von Admin {current_user.username}")
db_session.close()
return jsonify({
"success": True,
"message": "Benutzer erfolgreich erstellt",
"user_id": new_user.id
})
except Exception as e:
admin_logger.error(f"Fehler beim Erstellen des Benutzers: {str(e)}")
return jsonify({"error": "Fehler beim Erstellen des Benutzers"}), 500
@admin_blueprint.route("/api/users/<int:user_id>", methods=["GET"])
@login_required
@admin_required
def get_user_api(user_id):
"""API-Endpunkt zum Abrufen von Benutzerdaten"""
try:
db_session = get_db_session()
user = db_session.query(User).filter(User.id == user_id).first()
if not user:
db_session.close()
return jsonify({"error": "Benutzer nicht gefunden"}), 404
user_data = {
"id": user.id,
"username": user.username,
"email": user.email,
"name": user.name,
"role": user.role,
"active": user.active,
"created_at": user.created_at.isoformat() if user.created_at else None,
"last_login": user.last_login.isoformat() if user.last_login else None,
"department": user.department,
"position": user.position,
"phone": user.phone,
"bio": user.bio
}
db_session.close()
return jsonify(user_data)
except Exception as e:
admin_logger.error(f"Fehler beim Abrufen der Benutzerdaten: {str(e)}")
return jsonify({"error": "Fehler beim Abrufen der Benutzerdaten"}), 500
@admin_blueprint.route("/api/users/<int:user_id>", methods=["PUT"])
@login_required
@admin_required
def update_user_api(user_id):
"""API-Endpunkt zum Aktualisieren von Benutzerdaten"""
try:
data = request.get_json()
db_session = get_db_session()
user = db_session.query(User).filter(User.id == user_id).first()
if not user:
db_session.close()
return jsonify({"error": "Benutzer nicht gefunden"}), 404
# Aktualisierbare Felder
updatable_fields = ['username', 'email', 'name', 'role', 'active', 'department', 'position', 'phone', 'bio']
for field in updatable_fields:
if field in data:
setattr(user, field, data[field])
# Passwort separat behandeln
if 'password' in data and data['password']:
user.set_password(data['password'])
user.updated_at = datetime.now()
db_session.commit()
admin_logger.info(f"Benutzer {user.username} aktualisiert von Admin {current_user.username}")
db_session.close()
return jsonify({
"success": True,
"message": "Benutzer erfolgreich aktualisiert"
})
except Exception as e:
admin_logger.error(f"Fehler beim Aktualisieren des Benutzers: {str(e)}")
return jsonify({"error": "Fehler beim Aktualisieren des Benutzers"}), 500
@admin_blueprint.route("/api/users/<int:user_id>", methods=["DELETE"])
@login_required
@admin_required
def delete_user_api(user_id):
"""API-Endpunkt zum Löschen eines Benutzers"""
try:
if user_id == current_user.id:
return jsonify({"error": "Sie können sich nicht selbst löschen"}), 400
db_session = get_db_session()
user = db_session.query(User).filter(User.id == user_id).first()
if not user:
db_session.close()
return jsonify({"error": "Benutzer nicht gefunden"}), 404
username = user.username
db_session.delete(user)
db_session.commit()
admin_logger.info(f"Benutzer {username} gelöscht von Admin {current_user.username}")
db_session.close()
return jsonify({
"success": True,
"message": "Benutzer erfolgreich gelöscht"
})
except Exception as e:
admin_logger.error(f"Fehler beim Löschen des Benutzers: {str(e)}")
return jsonify({"error": "Fehler beim Löschen des Benutzers"}), 500