Die Dateien wurden in mehreren Log- und Cache-Ordnern geändert:
This commit is contained in:
@ -20,6 +20,7 @@ import os
|
||||
import json
|
||||
import time
|
||||
import zipfile
|
||||
import bcrypt
|
||||
from datetime import datetime, timedelta
|
||||
from functools import wraps
|
||||
|
||||
@ -380,6 +381,52 @@ def guest_requests():
|
||||
"""Gäste-Anfragen-Übersicht"""
|
||||
return render_template('admin_guest_requests.html')
|
||||
|
||||
@admin_blueprint.route("/requests")
|
||||
@admin_required
|
||||
def requests_overview():
|
||||
"""Anträge-Übersicht für Admin-Dashboard"""
|
||||
try:
|
||||
with get_cached_session() as db_session:
|
||||
# Grundlegende Statistiken sammeln für das Template
|
||||
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()
|
||||
|
||||
# Online-Drucker zählen
|
||||
online_printers = db_session.query(Printer).filter(
|
||||
Printer.status.in_(['idle', 'busy'])
|
||||
).count()
|
||||
|
||||
# Alle Anträge laden
|
||||
requests = db_session.query(GuestRequest).order_by(
|
||||
GuestRequest.created_at.desc()
|
||||
).all()
|
||||
|
||||
stats = {
|
||||
'total_users': total_users,
|
||||
'total_printers': total_printers,
|
||||
'total_jobs': total_jobs,
|
||||
'active_jobs': active_jobs,
|
||||
'online_printers': online_printers
|
||||
}
|
||||
|
||||
admin_logger.info(f"Anträge-Übersicht geladen: {len(requests)} Anträge")
|
||||
|
||||
return render_template('admin.html',
|
||||
active_tab='requests',
|
||||
stats=stats,
|
||||
requests=requests)
|
||||
|
||||
except Exception as e:
|
||||
admin_logger.error(f"Fehler beim Laden der Anträge-Übersicht: {str(e)}")
|
||||
flash("Fehler beim Laden der Anträge", "error")
|
||||
return redirect(url_for('admin.dashboard'))
|
||||
|
||||
@admin_blueprint.route("/advanced-settings")
|
||||
@admin_required
|
||||
def advanced_settings():
|
||||
@ -1762,6 +1809,110 @@ def get_pending_guest_otps_api():
|
||||
admin_logger.error(f"Fehler beim Abrufen aktiver OTP-Codes: {str(e)}")
|
||||
return jsonify({"error": "Fehler beim Laden der OTP-Codes"}), 500
|
||||
|
||||
@admin_api_blueprint.route("/guest-requests/<int:request_id>/approve", methods=["POST"])
|
||||
@admin_required
|
||||
def approve_guest_request_api(request_id):
|
||||
"""API-Endpunkt zum Genehmigen einer Gastanfrage"""
|
||||
try:
|
||||
data = request.get_json() or {}
|
||||
approval_notes = data.get('approval_notes', '').strip()
|
||||
printer_id = data.get('printer_id') # Optional: Drucker zuweisen
|
||||
|
||||
with get_cached_session() as db_session:
|
||||
guest_request = db_session.query(GuestRequest).filter_by(id=request_id).first()
|
||||
|
||||
if not guest_request:
|
||||
return jsonify({"error": "Gastanfrage nicht gefunden"}), 404
|
||||
|
||||
if guest_request.status != 'pending':
|
||||
return jsonify({"error": f"Gastanfrage ist bereits {guest_request.status}"}), 400
|
||||
|
||||
# Optional: Drucker validieren falls angegeben
|
||||
if printer_id:
|
||||
printer = db_session.query(Printer).filter_by(id=printer_id).first()
|
||||
if not printer:
|
||||
return jsonify({"error": "Angegebener Drucker nicht gefunden"}), 400
|
||||
guest_request.assigned_printer_id = printer_id
|
||||
|
||||
# Gastanfrage genehmigen
|
||||
guest_request.status = 'approved'
|
||||
guest_request.processed_by = current_user.id
|
||||
guest_request.processed_at = datetime.now()
|
||||
guest_request.approved_by = current_user.id
|
||||
guest_request.approved_at = datetime.now()
|
||||
guest_request.approval_notes = approval_notes
|
||||
guest_request.updated_at = datetime.now()
|
||||
|
||||
# OTP-Code generieren
|
||||
import secrets
|
||||
import string
|
||||
otp_code = ''.join(secrets.choice(string.digits) for _ in range(6))
|
||||
guest_request.otp_code_plain = otp_code
|
||||
guest_request.otp_code = bcrypt.hashpw(otp_code.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')
|
||||
guest_request.otp_expires_at = datetime.now() + timedelta(hours=72) # 72h gültig
|
||||
|
||||
db_session.commit()
|
||||
|
||||
admin_logger.info(f"Gastanfrage {request_id} von Admin {current_user.name} genehmigt")
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"message": "Gastanfrage erfolgreich genehmigt",
|
||||
"otp_code": otp_code,
|
||||
"request_id": request_id,
|
||||
"guest_name": guest_request.name,
|
||||
"expires_at": guest_request.otp_expires_at.isoformat()
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
admin_logger.error(f"Fehler beim Genehmigen der Gastanfrage {request_id}: {str(e)}")
|
||||
return jsonify({"error": "Fehler beim Genehmigen der Gastanfrage"}), 500
|
||||
|
||||
@admin_api_blueprint.route("/guest-requests/<int:request_id>/reject", methods=["POST"])
|
||||
@admin_required
|
||||
def reject_guest_request_api(request_id):
|
||||
"""API-Endpunkt zum Ablehnen einer Gastanfrage"""
|
||||
try:
|
||||
data = request.get_json() or {}
|
||||
rejection_reason = data.get('rejection_reason', '').strip()
|
||||
|
||||
if not rejection_reason:
|
||||
return jsonify({"error": "Ablehnungsgrund ist erforderlich"}), 400
|
||||
|
||||
with get_cached_session() as db_session:
|
||||
guest_request = db_session.query(GuestRequest).filter_by(id=request_id).first()
|
||||
|
||||
if not guest_request:
|
||||
return jsonify({"error": "Gastanfrage nicht gefunden"}), 404
|
||||
|
||||
if guest_request.status != 'pending':
|
||||
return jsonify({"error": f"Gastanfrage ist bereits {guest_request.status}"}), 400
|
||||
|
||||
# Gastanfrage ablehnen
|
||||
guest_request.status = 'rejected'
|
||||
guest_request.processed_by = current_user.id
|
||||
guest_request.processed_at = datetime.now()
|
||||
guest_request.rejected_by = current_user.id
|
||||
guest_request.rejected_at = datetime.now()
|
||||
guest_request.rejection_reason = rejection_reason
|
||||
guest_request.updated_at = datetime.now()
|
||||
|
||||
db_session.commit()
|
||||
|
||||
admin_logger.info(f"Gastanfrage {request_id} von Admin {current_user.name} abgelehnt: {rejection_reason}")
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"message": "Gastanfrage erfolgreich abgelehnt",
|
||||
"request_id": request_id,
|
||||
"guest_name": guest_request.name,
|
||||
"rejection_reason": rejection_reason
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
admin_logger.error(f"Fehler beim Ablehnen der Gastanfrage {request_id}: {str(e)}")
|
||||
return jsonify({"error": "Fehler beim Ablehnen der Gastanfrage"}), 500
|
||||
|
||||
# ===== ADMIN-UI ROUTES FÜR GAST-OTP-VERWALTUNG =====
|
||||
|
||||
@admin_blueprint.route("/guest-otps")
|
||||
|
Reference in New Issue
Block a user