Die Dateien wurden in mehreren Log- und Cache-Ordnern geändert:
This commit is contained in:
Binary file not shown.
@ -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")
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user