📝 Commit Details:
1. Updated various log files for better tracking and monitoring: - backend/logs/admin/admin.log - backend/logs/admin_api/admin_api.log - backend/logs/app/app.log - backend/logs/calendar/calendar.log - backend/logs/data_management/data_management.log - backend/logs/drucker_steuerung/drucker_
This commit is contained in:
@@ -216,13 +216,65 @@ def edit_user_page(user_id):
|
||||
@admin_blueprint.route("/printers")
|
||||
@admin_required
|
||||
def printers_overview():
|
||||
"""Druckerübersicht für Administratoren"""
|
||||
"""Druckerübersicht für Administratoren mit Hardware-Integration"""
|
||||
try:
|
||||
from utils.hardware_integration import get_drucker_steuerung
|
||||
|
||||
with get_cached_session() as db_session:
|
||||
# Nur TBA Marienfelde Drucker laden
|
||||
printers = db_session.query(Printer).filter(
|
||||
Printer.location == "TBA Marienfelde"
|
||||
).order_by(Printer.created_at.desc()).all()
|
||||
# Alle Drucker laden (nicht nur TBA Marienfelde)
|
||||
printers = db_session.query(Printer).order_by(Printer.created_at.desc()).all()
|
||||
|
||||
# Hardware-Steuerung für Echtzeit-Status
|
||||
drucker_steuerung = get_drucker_steuerung()
|
||||
status_data = drucker_steuerung.template_daten_sammeln()
|
||||
|
||||
# Erweiterte Drucker-Informationen mit Hardware-Status
|
||||
enriched_printers = []
|
||||
online_count = 0
|
||||
|
||||
for printer in printers:
|
||||
printer_data = {
|
||||
'id': printer.id,
|
||||
'name': printer.name,
|
||||
'model': printer.model,
|
||||
'location': printer.location,
|
||||
'ip_address': printer.ip_address,
|
||||
'plug_ip': printer.plug_ip,
|
||||
'status': printer.status,
|
||||
'active': printer.active,
|
||||
'created_at': printer.created_at,
|
||||
'last_checked': printer.last_checked,
|
||||
# Hardware-Status hinzufügen
|
||||
'plug_online': False,
|
||||
'plug_power_state': 'unknown',
|
||||
'energy_usage': {},
|
||||
'has_active_jobs': False,
|
||||
'active_jobs_count': 0
|
||||
}
|
||||
|
||||
# Hardware-Status aus Steuerung hinzufügen
|
||||
if printer.id in status_data.get('drucker_status', {}):
|
||||
hw_status = status_data['drucker_status'][printer.id]
|
||||
printer_data.update({
|
||||
'plug_online': hw_status.get('plug_online', False),
|
||||
'plug_power_state': hw_status.get('plug_state', 'unknown'),
|
||||
'energy_usage': hw_status.get('energy_usage', {}),
|
||||
'last_seen': hw_status.get('last_seen')
|
||||
})
|
||||
|
||||
if hw_status.get('plug_online', False):
|
||||
online_count += 1
|
||||
|
||||
# Aktive Jobs für diesen Drucker zählen
|
||||
active_jobs_count = db_session.query(Job).filter(
|
||||
Job.printer_id == printer.id,
|
||||
Job.status.in_(['pending', 'printing', 'scheduled'])
|
||||
).count()
|
||||
|
||||
printer_data['active_jobs_count'] = active_jobs_count
|
||||
printer_data['has_active_jobs'] = active_jobs_count > 0
|
||||
|
||||
enriched_printers.append(printer_data)
|
||||
|
||||
# Grundlegende Statistiken sammeln
|
||||
total_users = db_session.query(User).count()
|
||||
@@ -233,37 +285,54 @@ def printers_overview():
|
||||
active_jobs = db_session.query(Job).filter(
|
||||
Job.status.in_(['pending', 'printing', 'paused'])
|
||||
).count()
|
||||
|
||||
# Online-Drucker zählen (vereinfacht, da wir keinen Live-Status haben)
|
||||
online_printers = len([p for p in printers if p.status == 'online'])
|
||||
|
||||
stats = {
|
||||
'total_users': total_users,
|
||||
'total_printers': total_printers,
|
||||
'total_jobs': total_jobs,
|
||||
'active_jobs': active_jobs,
|
||||
'online_printers': online_printers
|
||||
'online_printers': online_count
|
||||
}
|
||||
|
||||
admin_logger.info(f"Druckerübersicht geladen von {current_user.username}")
|
||||
return render_template('admin.html', stats=stats, printers=printers, active_tab='printers')
|
||||
|
||||
except Exception as e:
|
||||
admin_logger.error(f"Fehler beim Laden der Druckerübersicht: {str(e)}")
|
||||
flash("Fehler beim Laden der Druckerdaten", "error")
|
||||
return render_template('admin.html', stats={}, printers=[], active_tab='printers')
|
||||
admin_logger.info(f"Druckerübersicht geladen von {current_user.username}: {total_printers} Drucker, {online_count} online")
|
||||
return render_template('admin.html', stats=stats, printers=enriched_printers, active_tab='printers')
|
||||
|
||||
@admin_blueprint.route("/printers/add", methods=["GET"])
|
||||
@admin_required
|
||||
@admin_blueprint.route("/printers/add")
|
||||
@admin_required
|
||||
def add_printer_page():
|
||||
"""Seite zum Hinzufügen eines neuen Druckers"""
|
||||
return render_template('admin_add_printer.html')
|
||||
try:
|
||||
with get_cached_session() as db_session:
|
||||
# Grundlegende Statistiken für Template
|
||||
total_users = db_session.query(User).count()
|
||||
total_printers = db_session.query(Printer).count()
|
||||
total_jobs = db_session.query(Job).count()
|
||||
active_jobs = db_session.query(Job).filter(
|
||||
Job.status.in_(['pending', 'printing', 'paused'])
|
||||
).count()
|
||||
|
||||
stats = {
|
||||
'total_users': total_users,
|
||||
'total_printers': total_printers,
|
||||
'total_jobs': total_jobs,
|
||||
'active_jobs': active_jobs
|
||||
}
|
||||
|
||||
admin_logger.info(f"Drucker-Hinzufügen-Seite aufgerufen von {current_user.username}")
|
||||
return render_template('admin_add_printer.html', stats=stats, active_tab='printers')
|
||||
|
||||
except Exception as e:
|
||||
admin_logger.error(f"Fehler beim Laden der Drucker-Hinzufügen-Seite: {str(e)}")
|
||||
flash("Fehler beim Laden der Seite", "error")
|
||||
return redirect(url_for('admin.printers_overview'))
|
||||
|
||||
@admin_blueprint.route("/printers/<int:printer_id>/edit", methods=["GET"])
|
||||
@admin_blueprint.route("/printers/<int:printer_id>/edit")
|
||||
@admin_required
|
||||
def edit_printer_page(printer_id):
|
||||
"""Seite zum Bearbeiten eines Druckers"""
|
||||
try:
|
||||
from utils.hardware_integration import get_drucker_steuerung
|
||||
|
||||
with get_cached_session() as db_session:
|
||||
printer = db_session.query(Printer).filter(Printer.id == printer_id).first()
|
||||
|
||||
@@ -271,13 +340,267 @@ def edit_printer_page(printer_id):
|
||||
flash("Drucker nicht gefunden", "error")
|
||||
return redirect(url_for('admin.printers_overview'))
|
||||
|
||||
return render_template('admin_edit_printer.html', printer=printer)
|
||||
# Hardware-Status für diesen Drucker abrufen
|
||||
drucker_steuerung = get_drucker_steuerung()
|
||||
status_data = drucker_steuerung.template_daten_sammeln()
|
||||
|
||||
# Erweiterte Drucker-Informationen
|
||||
printer_data = {
|
||||
'id': printer.id,
|
||||
'name': printer.name,
|
||||
'model': printer.model,
|
||||
'location': printer.location,
|
||||
'ip_address': printer.ip_address,
|
||||
'mac_address': printer.mac_address,
|
||||
'plug_ip': printer.plug_ip,
|
||||
'status': printer.status,
|
||||
'active': printer.active,
|
||||
'created_at': printer.created_at,
|
||||
'last_checked': printer.last_checked,
|
||||
# Hardware-Status
|
||||
'plug_online': False,
|
||||
'plug_power_state': 'unknown',
|
||||
'energy_usage': {}
|
||||
}
|
||||
|
||||
if printer.id in status_data.get('drucker_status', {}):
|
||||
hw_status = status_data['drucker_status'][printer.id]
|
||||
printer_data.update({
|
||||
'plug_online': hw_status.get('plug_online', False),
|
||||
'plug_power_state': hw_status.get('plug_state', 'unknown'),
|
||||
'energy_usage': hw_status.get('energy_usage', {}),
|
||||
'last_seen': hw_status.get('last_seen')
|
||||
})
|
||||
|
||||
# Aktive Jobs für diesen Drucker
|
||||
active_jobs = db_session.query(Job).filter(
|
||||
Job.printer_id == printer.id,
|
||||
Job.status.in_(['pending', 'printing', 'scheduled'])
|
||||
).all()
|
||||
|
||||
# Grundlegende Statistiken
|
||||
total_users = db_session.query(User).count()
|
||||
total_printers = db_session.query(Printer).count()
|
||||
total_jobs = db_session.query(Job).count()
|
||||
all_active_jobs = db_session.query(Job).filter(
|
||||
Job.status.in_(['pending', 'printing', 'paused'])
|
||||
).count()
|
||||
|
||||
stats = {
|
||||
'total_users': total_users,
|
||||
'total_printers': total_printers,
|
||||
'total_jobs': total_jobs,
|
||||
'active_jobs': all_active_jobs
|
||||
}
|
||||
|
||||
admin_logger.info(f"Drucker-Bearbeitung für '{printer.name}' aufgerufen von {current_user.username}")
|
||||
return render_template('admin_edit_printer.html',
|
||||
printer=printer_data,
|
||||
active_jobs=active_jobs,
|
||||
stats=stats,
|
||||
active_tab='printers')
|
||||
|
||||
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("/printers/<int:printer_id>/manage")
|
||||
@admin_required
|
||||
def manage_printer_page(printer_id):
|
||||
"""Vollständige Drucker-Verwaltungsseite - entspricht managePrinter() JavaScript-Funktion"""
|
||||
try:
|
||||
from utils.hardware_integration import get_drucker_steuerung
|
||||
|
||||
with get_cached_session() as db_session:
|
||||
printer = db_session.query(Printer).filter(Printer.id == printer_id).first()
|
||||
|
||||
if not printer:
|
||||
flash("Drucker nicht gefunden", "error")
|
||||
return redirect(url_for('admin.printers_overview'))
|
||||
|
||||
# Hardware-Steuerung für Echtzeit-Daten
|
||||
drucker_steuerung = get_drucker_steuerung()
|
||||
status_data = drucker_steuerung.template_daten_sammeln()
|
||||
|
||||
# Umfassende Drucker-Verwaltungsdaten sammeln
|
||||
management_data = {
|
||||
# Grunddaten
|
||||
'printer': printer.to_dict(),
|
||||
|
||||
# Hardware-Status
|
||||
'hardware_status': status_data.get('drucker_status', {}).get(printer.id, {}),
|
||||
|
||||
# Jobs
|
||||
'active_jobs': [],
|
||||
'recent_jobs': [],
|
||||
'job_statistics': {},
|
||||
|
||||
# Energieverbrauch
|
||||
'energy_stats': {},
|
||||
|
||||
# Wartungsinfo
|
||||
'maintenance_info': {},
|
||||
|
||||
# Verfügbare Aktionen
|
||||
'available_actions': []
|
||||
}
|
||||
|
||||
# Aktive Jobs
|
||||
active_jobs = db_session.query(Job).filter(
|
||||
Job.printer_id == printer.id,
|
||||
Job.status.in_(['pending', 'printing', 'scheduled'])
|
||||
).all()
|
||||
management_data['active_jobs'] = [job.to_dict() for job in active_jobs]
|
||||
|
||||
# Letzte 10 Jobs
|
||||
recent_jobs = db_session.query(Job).filter(
|
||||
Job.printer_id == printer.id
|
||||
).order_by(Job.created_at.desc()).limit(10).all()
|
||||
management_data['recent_jobs'] = [job.to_dict() for job in recent_jobs]
|
||||
|
||||
# Job-Statistiken
|
||||
completed_jobs = db_session.query(Job).filter(
|
||||
Job.printer_id == printer.id,
|
||||
Job.status == 'completed'
|
||||
).count()
|
||||
|
||||
failed_jobs = db_session.query(Job).filter(
|
||||
Job.printer_id == printer.id,
|
||||
Job.status.in_(['failed', 'cancelled'])
|
||||
).count()
|
||||
|
||||
management_data['job_statistics'] = {
|
||||
'total_jobs': len(recent_jobs),
|
||||
'active_jobs': len(active_jobs),
|
||||
'completed_jobs': completed_jobs,
|
||||
'failed_jobs': failed_jobs
|
||||
}
|
||||
|
||||
# Verfügbare Aktionen bestimmen
|
||||
available_actions = ['edit', 'view_settings']
|
||||
|
||||
if printer.plug_ip:
|
||||
hw_status = management_data['hardware_status']
|
||||
if hw_status.get('plug_online', False):
|
||||
if hw_status.get('plug_state') == 'on':
|
||||
available_actions.append('power_off')
|
||||
else:
|
||||
available_actions.append('power_on')
|
||||
available_actions.append('test_connection')
|
||||
|
||||
if len(active_jobs) == 0:
|
||||
available_actions.append('schedule_maintenance')
|
||||
|
||||
available_actions.extend(['view_logs', 'export_data', 'delete'])
|
||||
management_data['available_actions'] = available_actions
|
||||
|
||||
# Grundlegende Statistiken für Template
|
||||
total_users = db_session.query(User).count()
|
||||
total_printers = db_session.query(Printer).count()
|
||||
total_jobs = db_session.query(Job).count()
|
||||
all_active_jobs = db_session.query(Job).filter(
|
||||
Job.status.in_(['pending', 'printing', 'paused'])
|
||||
).count()
|
||||
|
||||
stats = {
|
||||
'total_users': total_users,
|
||||
'total_printers': total_printers,
|
||||
'total_jobs': total_jobs,
|
||||
'active_jobs': all_active_jobs
|
||||
}
|
||||
|
||||
admin_logger.info(f"Drucker-Verwaltung für '{printer.name}' aufgerufen von {current_user.username}")
|
||||
return render_template('admin_manage_printer.html',
|
||||
management_data=management_data,
|
||||
stats=stats,
|
||||
active_tab='printers')
|
||||
|
||||
except Exception as e:
|
||||
admin_logger.error(f"Fehler beim Laden der Drucker-Verwaltung: {str(e)}")
|
||||
flash("Fehler beim Laden der Drucker-Verwaltung", "error")
|
||||
return redirect(url_for('admin.printers_overview'))
|
||||
|
||||
@admin_blueprint.route("/printers/<int:printer_id>/settings")
|
||||
@admin_required
|
||||
def printer_settings_page(printer_id):
|
||||
"""Drucker-Einstellungsseite - entspricht showPrinterSettings() JavaScript-Funktion"""
|
||||
try:
|
||||
from utils.hardware_integration import get_drucker_steuerung
|
||||
|
||||
with get_cached_session() as db_session:
|
||||
printer = db_session.query(Printer).filter(Printer.id == printer_id).first()
|
||||
|
||||
if not printer:
|
||||
flash("Drucker nicht gefunden", "error")
|
||||
return redirect(url_for('admin.printers_overview'))
|
||||
|
||||
# Hardware-Status für erweiterte Einstellungen
|
||||
drucker_steuerung = get_drucker_steuerung()
|
||||
status_data = drucker_steuerung.template_daten_sammeln()
|
||||
|
||||
# Umfassende Einstellungsdaten
|
||||
settings_data = {
|
||||
# Grundeinstellungen
|
||||
'basic_settings': {
|
||||
'name': printer.name,
|
||||
'model': printer.model,
|
||||
'location': printer.location,
|
||||
'active': printer.active,
|
||||
'status': printer.status
|
||||
},
|
||||
|
||||
# Netzwerkeinstellungen
|
||||
'network_settings': {
|
||||
'ip_address': printer.ip_address,
|
||||
'mac_address': printer.mac_address,
|
||||
'plug_ip': printer.plug_ip
|
||||
},
|
||||
|
||||
# Hardware-Einstellungen
|
||||
'hardware_settings': status_data.get('drucker_status', {}).get(printer.id, {}),
|
||||
|
||||
# Erweiterte Einstellungen
|
||||
'advanced_settings': {
|
||||
'auto_power_management': printer.plug_ip is not None,
|
||||
'monitoring_enabled': True,
|
||||
'maintenance_mode': printer.status == 'maintenance'
|
||||
},
|
||||
|
||||
# Verfügbare Einstellungskategorien
|
||||
'setting_categories': [
|
||||
'basic', 'network', 'hardware', 'power_management',
|
||||
'monitoring', 'maintenance', 'security'
|
||||
]
|
||||
}
|
||||
|
||||
# Grundlegende Statistiken
|
||||
total_users = db_session.query(User).count()
|
||||
total_printers = db_session.query(Printer).count()
|
||||
total_jobs = db_session.query(Job).count()
|
||||
active_jobs = db_session.query(Job).filter(
|
||||
Job.status.in_(['pending', 'printing', 'paused'])
|
||||
).count()
|
||||
|
||||
stats = {
|
||||
'total_users': total_users,
|
||||
'total_printers': total_printers,
|
||||
'total_jobs': total_jobs,
|
||||
'active_jobs': active_jobs
|
||||
}
|
||||
|
||||
admin_logger.info(f"Drucker-Einstellungen für '{printer.name}' aufgerufen von {current_user.username}")
|
||||
return render_template('admin_printer_settings.html',
|
||||
printer=printer,
|
||||
settings_data=settings_data,
|
||||
stats=stats,
|
||||
active_tab='printers')
|
||||
|
||||
except Exception as e:
|
||||
admin_logger.error(f"Fehler beim Laden der Drucker-Einstellungen: {str(e)}")
|
||||
flash("Fehler beim Laden der Drucker-Einstellungen", "error")
|
||||
return redirect(url_for('admin.printers_overview'))
|
||||
|
||||
@admin_blueprint.route("/guest-requests")
|
||||
@admin_required
|
||||
def guest_requests():
|
||||
@@ -639,6 +962,256 @@ def delete_user_api(user_id):
|
||||
|
||||
# ===== DRUCKER-API-ROUTEN =====
|
||||
|
||||
@admin_api_blueprint.route("/printers", methods=["GET"])
|
||||
@admin_required
|
||||
def get_printers_api():
|
||||
"""Holt alle Drucker mit Status und Hardware-Integration"""
|
||||
try:
|
||||
from models import get_db_session, Printer
|
||||
from utils.hardware_integration import get_drucker_steuerung
|
||||
|
||||
with get_db_session() as db_session:
|
||||
printers = db_session.query(Printer).all()
|
||||
|
||||
# Hardware-Steuerung für Echtzeit-Status
|
||||
drucker_steuerung = get_drucker_steuerung()
|
||||
status_data = drucker_steuerung.template_daten_sammeln()
|
||||
|
||||
printers_data = []
|
||||
for printer in printers:
|
||||
printer_dict = printer.to_dict()
|
||||
|
||||
# Echtzeit-Status aus Hardware-Integration hinzufügen
|
||||
if printer.id in status_data.get('drucker_status', {}):
|
||||
hw_status = status_data['drucker_status'][printer.id]
|
||||
printer_dict.update({
|
||||
'plug_online': hw_status.get('plug_online', False),
|
||||
'plug_power_state': hw_status.get('plug_state', 'unknown'),
|
||||
'energy_usage': hw_status.get('energy_usage', {})
|
||||
})
|
||||
|
||||
printers_data.append(printer_dict)
|
||||
|
||||
admin_logger.debug(f"Drucker-Daten für API abgerufen: {len(printers_data)} Drucker")
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"printers": printers_data,
|
||||
"total_count": len(printers_data)
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
admin_logger.error(f"Fehler beim Abrufen der Drucker: {str(e)}")
|
||||
return jsonify({"error": "Fehler beim Abrufen der Drucker"}), 500
|
||||
|
||||
@admin_api_blueprint.route("/printers", methods=["POST"])
|
||||
@admin_required
|
||||
def create_printer_api():
|
||||
"""Erstellt einen neuen Drucker"""
|
||||
try:
|
||||
from models import get_db_session, Printer
|
||||
|
||||
data = request.get_json()
|
||||
|
||||
# Validierung der erforderlichen Felder
|
||||
required_fields = ['name', 'model', 'location']
|
||||
for field in required_fields:
|
||||
if not data.get(field):
|
||||
return jsonify({"error": f"Feld '{field}' ist erforderlich"}), 400
|
||||
|
||||
with get_db_session() as db_session:
|
||||
# Prüfen ob Name bereits existiert
|
||||
existing_printer = db_session.query(Printer).filter(
|
||||
Printer.name == data['name']
|
||||
).first()
|
||||
|
||||
if existing_printer:
|
||||
return jsonify({"error": "Ein Drucker mit diesem Namen existiert bereits"}), 400
|
||||
|
||||
# Neuen Drucker erstellen
|
||||
printer = Printer(
|
||||
name=data['name'],
|
||||
model=data['model'],
|
||||
location=data['location'],
|
||||
ip_address=data.get('ip_address', ''),
|
||||
mac_address=data.get('mac_address', ''),
|
||||
plug_ip=data.get('plug_ip', ''),
|
||||
active=data.get('active', True),
|
||||
status='offline' # Standard-Status
|
||||
)
|
||||
|
||||
db_session.add(printer)
|
||||
db_session.commit()
|
||||
|
||||
admin_logger.info(f"Neuer Drucker '{printer.name}' erstellt von Admin {current_user.username}")
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"message": "Drucker erfolgreich erstellt",
|
||||
"printer": printer.to_dict()
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
admin_logger.error(f"Fehler beim Erstellen des Druckers: {str(e)}")
|
||||
return jsonify({"error": "Fehler beim Erstellen des Druckers"}), 500
|
||||
|
||||
@admin_api_blueprint.route("/printers/<int:printer_id>", methods=["PUT"])
|
||||
@admin_required
|
||||
def update_printer_api(printer_id):
|
||||
"""Aktualisiert einen bestehenden Drucker"""
|
||||
try:
|
||||
from models import get_db_session, Printer, invalidate_model_cache
|
||||
|
||||
data = request.get_json()
|
||||
|
||||
with get_db_session() as db_session:
|
||||
printer = db_session.query(Printer).filter(Printer.id == printer_id).first()
|
||||
|
||||
if not printer:
|
||||
return jsonify({"error": "Drucker nicht gefunden"}), 404
|
||||
|
||||
# Aktualisierbare Felder
|
||||
updateable_fields = [
|
||||
'name', 'model', 'location', 'ip_address',
|
||||
'mac_address', 'plug_ip', 'active'
|
||||
]
|
||||
|
||||
updated_fields = []
|
||||
for field in updateable_fields:
|
||||
if field in data:
|
||||
old_value = getattr(printer, field)
|
||||
new_value = data[field]
|
||||
if old_value != new_value:
|
||||
setattr(printer, field, new_value)
|
||||
updated_fields.append(f"{field}: '{old_value}' → '{new_value}'")
|
||||
|
||||
if updated_fields:
|
||||
printer.updated_at = datetime.now()
|
||||
db_session.commit()
|
||||
|
||||
# Cache invalidieren
|
||||
invalidate_model_cache("Printer", printer_id)
|
||||
|
||||
admin_logger.info(f"Drucker '{printer.name}' aktualisiert von Admin {current_user.username}: {', '.join(updated_fields)}")
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"message": "Drucker erfolgreich aktualisiert",
|
||||
"printer": printer.to_dict(),
|
||||
"updated_fields": updated_fields
|
||||
})
|
||||
else:
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"message": "Keine Änderungen vorgenommen"
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
admin_logger.error(f"Fehler beim Aktualisieren des Druckers {printer_id}: {str(e)}")
|
||||
return jsonify({"error": "Fehler beim Aktualisieren des Druckers"}), 500
|
||||
|
||||
@admin_api_blueprint.route("/printers/<int:printer_id>/power", methods=["POST"])
|
||||
@admin_required
|
||||
def toggle_printer_power_api(printer_id):
|
||||
"""Schaltet Smart-Plug des Druckers ein/aus"""
|
||||
try:
|
||||
from models import get_db_session, Printer
|
||||
from utils.hardware_integration import get_drucker_steuerung
|
||||
|
||||
data = request.get_json()
|
||||
action = data.get('action') # 'on' oder 'off'
|
||||
|
||||
if action not in ['on', 'off']:
|
||||
return jsonify({"error": "Aktion muss 'on' oder 'off' sein"}), 400
|
||||
|
||||
with get_db_session() as db_session:
|
||||
printer = db_session.query(Printer).filter(Printer.id == printer_id).first()
|
||||
|
||||
if not printer:
|
||||
return jsonify({"error": "Drucker nicht gefunden"}), 404
|
||||
|
||||
if not printer.plug_ip:
|
||||
return jsonify({"error": "Kein Smart-Plug für diesen Drucker konfiguriert"}), 400
|
||||
|
||||
# Hardware-Steuerung verwenden
|
||||
drucker_steuerung = get_drucker_steuerung()
|
||||
grund = f"Admin-Aktion durch {current_user.username}"
|
||||
|
||||
if action == 'on':
|
||||
result = drucker_steuerung.drucker_einschalten(printer_id, grund)
|
||||
else:
|
||||
result = drucker_steuerung.drucker_ausschalten(printer_id, grund)
|
||||
|
||||
if result['success']:
|
||||
admin_logger.info(f"Drucker '{printer.name}' {action.upper()} geschaltet von Admin {current_user.username}")
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"message": f"Drucker erfolgreich {'eingeschaltet' if action == 'on' else 'ausgeschaltet'}",
|
||||
"new_state": action,
|
||||
"details": result
|
||||
})
|
||||
else:
|
||||
return jsonify({
|
||||
"error": f"Fehler beim {'Ein' if action == 'on' else 'Aus'}schalten: {result.get('error', 'Unbekannter Fehler')}"
|
||||
}), 500
|
||||
|
||||
except Exception as e:
|
||||
admin_logger.error(f"Fehler beim Schalten des Druckers {printer_id}: {str(e)}")
|
||||
return jsonify({"error": "Fehler beim Schalten des Druckers"}), 500
|
||||
|
||||
@admin_api_blueprint.route("/printers/<int:printer_id>/status", methods=["GET"])
|
||||
@admin_required
|
||||
def get_printer_status_api(printer_id):
|
||||
"""Holt detaillierten Status eines Druckers"""
|
||||
try:
|
||||
from models import get_db_session, Printer, Job
|
||||
from utils.hardware_integration import get_drucker_steuerung
|
||||
|
||||
with get_db_session() as db_session:
|
||||
printer = db_session.query(Printer).filter(Printer.id == printer_id).first()
|
||||
|
||||
if not printer:
|
||||
return jsonify({"error": "Drucker nicht gefunden"}), 404
|
||||
|
||||
# Hardware-Status abrufen
|
||||
drucker_steuerung = get_drucker_steuerung()
|
||||
status_data = drucker_steuerung.template_daten_sammeln()
|
||||
|
||||
# Aktuelle Jobs für diesen Drucker
|
||||
active_jobs = db_session.query(Job).filter(
|
||||
Job.printer_id == printer_id,
|
||||
Job.status.in_(['pending', 'printing', 'scheduled'])
|
||||
).all()
|
||||
|
||||
# Drucker-Daten mit erweiterten Informationen
|
||||
printer_data = printer.to_dict()
|
||||
|
||||
# Hardware-Status hinzufügen
|
||||
if printer_id in status_data.get('drucker_status', {}):
|
||||
hw_status = status_data['drucker_status'][printer_id]
|
||||
printer_data.update({
|
||||
'plug_online': hw_status.get('plug_online', False),
|
||||
'plug_power_state': hw_status.get('plug_state', 'unknown'),
|
||||
'energy_usage': hw_status.get('energy_usage', {}),
|
||||
'plug_last_seen': hw_status.get('last_seen')
|
||||
})
|
||||
|
||||
# Job-Informationen hinzufügen
|
||||
printer_data['active_jobs'] = [job.to_dict() for job in active_jobs]
|
||||
printer_data['active_jobs_count'] = len(active_jobs)
|
||||
|
||||
admin_logger.debug(f"Detaillierter Status für Drucker {printer_id} abgerufen")
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"printer": printer_data
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
admin_logger.error(f"Fehler beim Abrufen des Drucker-Status {printer_id}: {str(e)}")
|
||||
return jsonify({"error": "Fehler beim Abrufen des Drucker-Status"}), 500
|
||||
|
||||
@admin_api_blueprint.route("/printers/<int:printer_id>", methods=["DELETE"])
|
||||
@admin_required
|
||||
def delete_printer_api(printer_id):
|
||||
@@ -3197,4 +3770,297 @@ def api_admin_configure_printer_tapo():
|
||||
return jsonify({
|
||||
'success': False,
|
||||
'error': f'Systemfehler: {str(e)}'
|
||||
}), 500
|
||||
}), 500
|
||||
|
||||
# ===== BENUTZER-MANAGEMENT API-ENDPUNKTE =====
|
||||
|
||||
@admin_api_blueprint.route("/users", methods=["GET"])
|
||||
@admin_required
|
||||
def get_users_api():
|
||||
"""API-Endpunkt zum Abrufen aller Benutzer"""
|
||||
try:
|
||||
with get_cached_session() as db_session:
|
||||
users = db_session.query(User).order_by(User.created_at.desc()).all()
|
||||
|
||||
users_data = []
|
||||
for user in users:
|
||||
user_dict = {
|
||||
'id': user.id,
|
||||
'username': user.username,
|
||||
'email': user.email,
|
||||
'name': user.name,
|
||||
'role': user.role,
|
||||
'is_admin': user.is_admin,
|
||||
'is_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,
|
||||
'last_activity': user.last_activity.isoformat() if user.last_activity else None,
|
||||
'department': user.department,
|
||||
'position': user.position,
|
||||
'phone': user.phone,
|
||||
'bio': user.bio,
|
||||
'theme_preference': user.theme_preference,
|
||||
'language_preference': user.language_preference,
|
||||
'permission_level': user.get_permission_level(),
|
||||
'permissions': user.permissions.to_dict() if user.permissions else None
|
||||
}
|
||||
users_data.append(user_dict)
|
||||
|
||||
admin_api_logger.info(f"Benutzer-API aufgerufen von {current_user.username}: {len(users_data)} Benutzer")
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"users": users_data,
|
||||
"total_count": len(users_data)
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
admin_api_logger.error(f"Fehler beim Abrufen der Benutzer: {str(e)}")
|
||||
return jsonify({"error": "Fehler beim Abrufen der Benutzer"}), 500
|
||||
|
||||
@admin_api_blueprint.route("/users", methods=["POST"])
|
||||
@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', 'name', 'password']
|
||||
for field in required_fields:
|
||||
if not data.get(field):
|
||||
return jsonify({"error": f"Feld '{field}' ist erforderlich"}), 400
|
||||
|
||||
# E-Mail-Format validieren
|
||||
import re
|
||||
email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
|
||||
if not re.match(email_pattern, data['email']):
|
||||
return jsonify({"error": "Ungültiges E-Mail-Format"}), 400
|
||||
|
||||
with get_db_session() as db_session:
|
||||
# Prüfen, ob Benutzername oder E-Mail bereits existieren
|
||||
existing_user = db_session.query(User).filter(
|
||||
(User.username == data['username']) | (User.email == data['email'])
|
||||
).first()
|
||||
|
||||
if existing_user:
|
||||
if existing_user.username == data['username']:
|
||||
return jsonify({"error": "Benutzername bereits vergeben"}), 400
|
||||
else:
|
||||
return jsonify({"error": "E-Mail bereits registriert"}), 400
|
||||
|
||||
# Passwort hashen
|
||||
import bcrypt
|
||||
password_hash = bcrypt.hashpw(data['password'].encode('utf-8'), bcrypt.gensalt()).decode('utf-8')
|
||||
|
||||
# Neuen Benutzer erstellen
|
||||
new_user = User(
|
||||
username=data['username'],
|
||||
email=data['email'],
|
||||
name=data['name'],
|
||||
password_hash=password_hash,
|
||||
role=data.get('role', 'user'),
|
||||
active=data.get('active', True),
|
||||
department=data.get('department'),
|
||||
position=data.get('position'),
|
||||
phone=data.get('phone'),
|
||||
bio=data.get('bio'),
|
||||
theme_preference=data.get('theme_preference', 'auto'),
|
||||
language_preference=data.get('language_preference', 'de')
|
||||
)
|
||||
|
||||
db_session.add(new_user)
|
||||
db_session.flush() # Damit wir die ID bekommen
|
||||
|
||||
# Berechtigungen erstellen falls angegeben
|
||||
permissions_data = data.get('permissions', {})
|
||||
if permissions_data or data.get('role') == 'admin':
|
||||
from models import UserPermission
|
||||
user_permissions = UserPermission(
|
||||
user_id=new_user.id,
|
||||
can_start_jobs=permissions_data.get('can_start_jobs', data.get('role') == 'admin'),
|
||||
needs_approval=permissions_data.get('needs_approval', data.get('role') != 'admin'),
|
||||
can_approve_jobs=permissions_data.get('can_approve_jobs', data.get('role') == 'admin')
|
||||
)
|
||||
db_session.add(user_permissions)
|
||||
|
||||
db_session.commit()
|
||||
|
||||
admin_api_logger.info(f"Neuer Benutzer erstellt von {current_user.username}: {new_user.username} ({new_user.email})")
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"message": f"Benutzer '{new_user.username}' erfolgreich erstellt",
|
||||
"user_id": new_user.id
|
||||
}), 201
|
||||
|
||||
except Exception as e:
|
||||
admin_api_logger.error(f"Fehler beim Erstellen des Benutzers: {str(e)}")
|
||||
return jsonify({"error": "Fehler beim Erstellen des Benutzers"}), 500
|
||||
|
||||
@admin_api_blueprint.route("/users/<int:user_id>", methods=["PUT"])
|
||||
@admin_required
|
||||
def update_user_api(user_id):
|
||||
"""API-Endpunkt zum Aktualisieren eines Benutzers"""
|
||||
try:
|
||||
data = request.get_json()
|
||||
|
||||
with get_db_session() as db_session:
|
||||
user = db_session.query(User).filter(User.id == user_id).first()
|
||||
|
||||
if not user:
|
||||
return jsonify({"error": "Benutzer nicht gefunden"}), 404
|
||||
|
||||
# Verhindern, dass sich selbst deaktiviert oder degradiert
|
||||
if user.id == current_user.id:
|
||||
if 'active' in data and not data['active']:
|
||||
return jsonify({"error": "Sie können sich nicht selbst deaktivieren"}), 400
|
||||
if 'role' in data and data['role'] != 'admin' and user.is_admin:
|
||||
return jsonify({"error": "Sie können sich nicht selbst die Admin-Rechte entziehen"}), 400
|
||||
|
||||
# Prüfen auf doppelte E-Mail/Username (außer bei sich selbst)
|
||||
if 'email' in data and data['email'] != user.email:
|
||||
existing_user = db_session.query(User).filter(
|
||||
User.email == data['email'], User.id != user_id
|
||||
).first()
|
||||
if existing_user:
|
||||
return jsonify({"error": "E-Mail bereits vergeben"}), 400
|
||||
|
||||
if 'username' in data and data['username'] != user.username:
|
||||
existing_user = db_session.query(User).filter(
|
||||
User.username == data['username'], User.id != user_id
|
||||
).first()
|
||||
if existing_user:
|
||||
return jsonify({"error": "Benutzername bereits vergeben"}), 400
|
||||
|
||||
# Benutzer-Grunddaten aktualisieren
|
||||
updatable_fields = [
|
||||
'username', 'email', 'name', 'role', 'active', 'department',
|
||||
'position', 'phone', 'bio', 'theme_preference', 'language_preference'
|
||||
]
|
||||
|
||||
for field in updatable_fields:
|
||||
if field in data:
|
||||
setattr(user, field, data[field])
|
||||
|
||||
# Passwort aktualisieren falls angegeben
|
||||
if 'password' in data and data['password']:
|
||||
import bcrypt
|
||||
user.password_hash = bcrypt.hashpw(data['password'].encode('utf-8'), bcrypt.gensalt()).decode('utf-8')
|
||||
admin_api_logger.info(f"Passwort für Benutzer {user.username} wurde zurückgesetzt von Admin {current_user.username}")
|
||||
|
||||
# Berechtigungen aktualisieren
|
||||
if 'permissions' in data:
|
||||
from models import UserPermission
|
||||
|
||||
if not user.permissions:
|
||||
user_permissions = UserPermission(user_id=user.id)
|
||||
db_session.add(user_permissions)
|
||||
db_session.flush()
|
||||
else:
|
||||
user_permissions = user.permissions
|
||||
|
||||
permissions_data = data['permissions']
|
||||
user_permissions.can_start_jobs = permissions_data.get('can_start_jobs', False)
|
||||
user_permissions.needs_approval = permissions_data.get('needs_approval', True)
|
||||
user_permissions.can_approve_jobs = permissions_data.get('can_approve_jobs', False)
|
||||
|
||||
user.updated_at = datetime.now()
|
||||
db_session.commit()
|
||||
|
||||
admin_api_logger.info(f"Benutzer {user.username} aktualisiert von Admin {current_user.username}")
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"message": f"Benutzer '{user.username}' erfolgreich aktualisiert"
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
admin_api_logger.error(f"Fehler beim Aktualisieren des Benutzers {user_id}: {str(e)}")
|
||||
return jsonify({"error": "Fehler beim Aktualisieren des Benutzers"}), 500
|
||||
|
||||
@admin_api_blueprint.route("/users/<int:user_id>", methods=["DELETE"])
|
||||
@admin_required
|
||||
def delete_user_api(user_id):
|
||||
"""API-Endpunkt zum Löschen eines Benutzers"""
|
||||
try:
|
||||
with get_db_session() as db_session:
|
||||
user = db_session.query(User).filter(User.id == user_id).first()
|
||||
|
||||
if not user:
|
||||
return jsonify({"error": "Benutzer nicht gefunden"}), 404
|
||||
|
||||
# Verhindern, dass sich selbst löscht
|
||||
if user.id == current_user.id:
|
||||
return jsonify({"error": "Sie können sich nicht selbst löschen"}), 400
|
||||
|
||||
# Prüfen, ob der Benutzer noch aktive Jobs hat
|
||||
from models import Job
|
||||
active_jobs = db_session.query(Job).filter(
|
||||
Job.user_id == user_id,
|
||||
Job.status.in_(['pending', 'printing', 'paused'])
|
||||
).count()
|
||||
|
||||
if active_jobs > 0:
|
||||
return jsonify({"error": f"Benutzer hat noch {active_jobs} aktive Jobs. Löschen nicht möglich."}), 400
|
||||
|
||||
username = user.username
|
||||
|
||||
# Benutzer löschen (CASCADE löscht automatisch UserPermissions)
|
||||
db_session.delete(user)
|
||||
db_session.commit()
|
||||
|
||||
admin_api_logger.warning(f"Benutzer {username} (ID: {user_id}) gelöscht von Admin {current_user.username}")
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"message": f"Benutzer '{username}' erfolgreich gelöscht"
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
admin_api_logger.error(f"Fehler beim Löschen des Benutzers {user_id}: {str(e)}")
|
||||
return jsonify({"error": "Fehler beim Löschen des Benutzers"}), 500
|
||||
|
||||
@admin_api_blueprint.route("/users/<int:user_id>/permissions", methods=["PUT"])
|
||||
@admin_required
|
||||
def update_user_permissions_api(user_id):
|
||||
"""API-Endpunkt zum spezifischen Aktualisieren von Benutzerberechtigungen"""
|
||||
try:
|
||||
data = request.get_json()
|
||||
|
||||
with get_db_session() as db_session:
|
||||
user = db_session.query(User).filter(User.id == user_id).first()
|
||||
|
||||
if not user:
|
||||
return jsonify({"error": "Benutzer nicht gefunden"}), 404
|
||||
|
||||
from models import UserPermission
|
||||
|
||||
if not user.permissions:
|
||||
user_permissions = UserPermission(user_id=user.id)
|
||||
db_session.add(user_permissions)
|
||||
db_session.flush()
|
||||
else:
|
||||
user_permissions = user.permissions
|
||||
|
||||
# Berechtigungen aktualisieren
|
||||
if 'can_start_jobs' in data:
|
||||
user_permissions.can_start_jobs = data['can_start_jobs']
|
||||
if 'needs_approval' in data:
|
||||
user_permissions.needs_approval = data['needs_approval']
|
||||
if 'can_approve_jobs' in data:
|
||||
user_permissions.can_approve_jobs = data['can_approve_jobs']
|
||||
|
||||
db_session.commit()
|
||||
|
||||
admin_api_logger.info(f"Berechtigungen für Benutzer {user.username} aktualisiert von Admin {current_user.username}")
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"message": f"Berechtigungen für '{user.username}' erfolgreich aktualisiert",
|
||||
"permissions": user_permissions.to_dict()
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
admin_api_logger.error(f"Fehler beim Aktualisieren der Berechtigungen für Benutzer {user_id}: {str(e)}")
|
||||
return jsonify({"error": "Fehler beim Aktualisieren der Berechtigungen"}), 500
|
Reference in New Issue
Block a user