""" 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//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//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/", 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/", 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/", 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