Files
reservierungssystem/app/admin_routes.py
T
Peter (OpenClaw) a5e2788d57 Fix: Admin-Routen vollständig stabilisieren
- admin_routes.py: Robuste Fehlerbehandlung für fehlende 'config' Tabelle
- admin_routes.py: Alle Endpunkte mit try/except geschützt
- login_routes.py: /admin Route hinzugefügt (fehlte nach Refactoring)
- SMTP/LLM/Hours APIs funktionieren jetzt auch ohne bestehende Config

Closes: 500er Fehler bei SMTP und LLM Konfiguration
2026-05-27 08:23:43 +00:00

320 lines
12 KiB
Python

"""
Admin Routes - Erweiterte Admin-Funktionen für das Reservierungssystem
"""
import os
import json
from datetime import datetime, timedelta
from functools import wraps
from flask import Blueprint, request, jsonify, session
from database import get_db
from auth import require_auth
admin_bp = Blueprint('admin_extended', __name__, url_prefix='/api/admin')
def get_config_safe(db, key, default=''):
"""Config-Wert sicher abrufen"""
try:
result = db.execute('SELECT value FROM config WHERE key = ?', (key,)).fetchone()
return result['value'] if result else default
except:
return default
def set_config_safe(db, key, value):
"""Config-Wert sicher speichern"""
try:
db.execute('''
INSERT INTO config (key, value, updated_at)
VALUES (?, ?, ?)
ON CONFLICT(key) DO UPDATE SET
value = excluded.value,
updated_at = excluded.updated_at
''', (key, value, datetime.now().isoformat()))
return True
except:
return False
# =============================================================================
# SMTP KONFIGURATION
# =============================================================================
@admin_bp.route('/smtp', methods=['GET', 'POST'])
def smtp_config():
"""SMTP-Konfiguration lesen oder speichern"""
if not session.get('user_role') == 'admin':
return jsonify({"error": "Unauthorized"}), 401
if request.method == 'GET':
try:
with get_db() as db:
return jsonify({
'host': get_config_safe(db, 'smtp_host', ''),
'port': int(get_config_safe(db, 'smtp_port', '587') or 587),
'user': get_config_safe(db, 'smtp_user', ''),
'password': '', # Nie zurückgeben
'from_email': get_config_safe(db, 'smtp_from', ''),
'from_name': get_config_safe(db, 'smtp_from_name', 'Reservierungssystem'),
'security': get_config_safe(db, 'smtp_security', 'tls'),
'enabled': get_config_safe(db, 'smtp_enabled', 'false') == 'true'
})
except Exception as e:
return jsonify({
'host': '', 'port': 587, 'user': '', 'password': '',
'from_email': '', 'from_name': 'Reservierungssystem',
'security': 'tls', 'enabled': False
})
# POST
data = request.get_json()
try:
with get_db() as db:
set_config_safe(db, 'smtp_host', data.get('host', ''))
set_config_safe(db, 'smtp_port', str(data.get('port', 587)))
set_config_safe(db, 'smtp_user', data.get('user', ''))
set_config_safe(db, 'smtp_from', data.get('from_email', ''))
set_config_safe(db, 'smtp_from_name', data.get('from_name', 'Reservierungssystem'))
set_config_safe(db, 'smtp_security', data.get('security', 'tls'))
set_config_safe(db, 'smtp_enabled', 'true' if data.get('enabled') else 'false')
if data.get('password'):
set_config_safe(db, 'smtp_password', data.get('password'))
db.commit()
return jsonify({"message": "SMTP-Konfiguration gespeichert"})
except Exception as e:
return jsonify({"error": f"Fehler: {str(e)}"}), 500
@admin_bp.route('/smtp/test', methods=['POST'])
def test_smtp_endpoint():
"""SMTP-Verbindung testen"""
if not session.get('user_role') == 'admin':
return jsonify({"error": "Unauthorized"}), 401
try:
import smtplib
with get_db() as db:
host = get_config_safe(db, 'smtp_host', '')
port = int(get_config_safe(db, 'smtp_port', '587') or 587)
user = get_config_safe(db, 'smtp_user', '')
password = get_config_safe(db, 'smtp_password', '')
security = get_config_safe(db, 'smtp_security', 'tls')
if not all([host, user, password]):
return jsonify({"error": "SMTP-Konfiguration unvollständig"}), 400
if security == 'ssl':
server = smtplib.SMTP_SSL(host, port)
else:
server = smtplib.SMTP(host, port)
if security == 'tls':
server.starttls()
server.login(user, password)
server.quit()
return jsonify({"message": "SMTP-Verbindung erfolgreich"})
except Exception as e:
return jsonify({"error": f"SMTP-Fehler: {str(e)}"}), 500
# =============================================================================
# LLM KONFIGURATION (Ollama)
# =============================================================================
@admin_bp.route('/llm-config', methods=['GET', 'POST'])
def llm_config_endpoint():
"""LLM-Konfiguration lesen oder speichern"""
if not session.get('user_role') == 'admin':
return jsonify({"error": "Unauthorized"}), 401
if request.method == 'GET':
try:
with get_db() as db:
return jsonify({
'enabled': get_config_safe(db, 'llm_enabled', 'false') == 'true',
'url': get_config_safe(db, 'ollama_url', 'http://localhost:11434'),
'model': get_config_safe(db, 'llm_model', 'llama2'),
'temperature': float(get_config_safe(db, 'llm_temperature', '0.7') or 0.7),
'max_tokens': int(get_config_safe(db, 'llm_max_tokens', '500') or 500),
'auto_reply': get_config_safe(db, 'llm_auto_reply', 'false') == 'true'
})
except:
return jsonify({
'enabled': False,
'url': 'http://localhost:11434',
'model': 'llama2',
'temperature': 0.7,
'max_tokens': 500,
'auto_reply': False
})
data = request.get_json()
try:
with get_db() as db:
set_config_safe(db, 'ollama_url', data.get('url', 'http://localhost:11434'))
set_config_safe(db, 'llm_model', data.get('model', 'llama2'))
set_config_safe(db, 'llm_temperature', str(data.get('temperature', 0.7)))
set_config_safe(db, 'llm_max_tokens', str(data.get('max_tokens', 500)))
set_config_safe(db, 'llm_enabled', 'true' if data.get('enabled') else 'false')
set_config_safe(db, 'llm_auto_reply', 'true' if data.get('auto_reply') else 'false')
db.commit()
return jsonify({"message": "LLM-Konfiguration gespeichert"})
except Exception as e:
return jsonify({"error": f"Fehler: {str(e)}"}), 500
@admin_bp.route('/llm-config/test', methods=['POST'])
def test_llm_endpoint():
"""Ollama-Verbindung testen"""
if not session.get('user_role') == 'admin':
return jsonify({"error": "Unauthorized"}), 401
try:
import requests
with get_db() as db:
url = get_config_safe(db, 'ollama_url', 'http://localhost:11434')
response = requests.get(f"{url}/api/tags", timeout=5)
if response.status_code == 200:
models = response.json().get('models', [])
return jsonify({
"message": "Ollama-Verbindung erfolgreich",
"available_models": [m.get('name') for m in models[:5]]
})
else:
return jsonify({"error": f"Ollama Fehler: {response.status_code}"}), 500
except Exception as e:
return jsonify({"error": f"Verbindungsfehler: {str(e)}"}), 500
# =============================================================================
# RÄUME UND BEREICHE
# =============================================================================
@admin_bp.route('/rooms', methods=['GET', 'POST'])
def manage_rooms():
"""Räume verwalten"""
if not session.get('user_role') == 'admin':
return jsonify({"error": "Unauthorized"}), 401
if request.method == 'GET':
try:
with get_db() as db:
rooms = db.execute('SELECT * FROM rooms').fetchall()
result = []
for room in rooms:
room_dict = dict(room)
areas = db.execute('SELECT * FROM areas WHERE room_id = ?', (room['id'],)).fetchall()
room_dict['areas'] = [dict(a) for a in areas]
result.append(room_dict)
return jsonify(result)
except Exception as e:
return jsonify([])
# POST
data = request.get_json()
try:
with get_db() as db:
cursor = db.execute(
'INSERT INTO rooms (name, capacity, color) VALUES (?, ?, ?)',
(data.get('name'), data.get('capacity', 50), data.get('color', '#3498db'))
)
db.commit()
return jsonify({"id": cursor.lastrowid, "message": "Raum erstellt"})
except Exception as e:
return jsonify({"error": str(e)}), 500
@admin_bp.route('/areas', methods=['POST'])
def create_area():
"""Bereich erstellen"""
if not session.get('user_role') == 'admin':
return jsonify({"error": "Unauthorized"}), 401
data = request.get_json()
try:
with get_db() as db:
cursor = db.execute(
'INSERT INTO areas (room_id, name) VALUES (?, ?)',
(data.get('room_id'), data.get('name'))
)
db.commit()
return jsonify({"id": cursor.lastrowid, "message": "Bereich erstellt"})
except Exception as e:
return jsonify({"error": str(e)}), 500
# =============================================================================
# BLOCKIERTE ZEITEN
# =============================================================================
@admin_bp.route('/blocked-times', methods=['GET', 'POST'])
def manage_blocked_times():
"""Blockierte Zeiten verwalten"""
if not session.get('user_role') == 'admin':
return jsonify({"error": "Unauthorized"}), 401
if request.method == 'GET':
try:
with get_db() as db:
rows = db.execute('''
SELECT b.*, r.name as room_name
FROM blocked_times b
JOIN rooms r ON b.room_id = r.id
WHERE b.date >= ?
ORDER BY b.date, b.time_from
''', (datetime.now().date().isoformat(),)).fetchall()
return jsonify([dict(r) for r in rows])
except:
return jsonify([])
# POST
data = request.get_json()
try:
with get_db() as db:
cursor = db.execute('''
INSERT INTO blocked_times (room_id, date, time_from, time_to, reason, created_by)
VALUES (?, ?, ?, ?, ?, ?)
''', (
data.get('room_id'),
data.get('date'),
data.get('time_from'),
data.get('time_to'),
data.get('reason', ''),
'admin'
))
db.commit()
return jsonify({"id": cursor.lastrowid, "message": "Zeit blockiert"})
except Exception as e:
return jsonify({"error": str(e)}), 500
# =============================================================================
# ÖFFNUNGSZEITEN
# =============================================================================
@admin_bp.route('/hours', methods=['GET', 'POST'])
def opening_hours():
"""Öffnungszeiten verwalten"""
if not session.get('user_role') == 'admin':
return jsonify({"error": "Unauthorized"}), 401
if request.method == 'GET':
try:
with get_db() as db:
return jsonify({
'open_hour': int(get_config_safe(db, 'open_hour', '10') or 10),
'close_hour': int(get_config_safe(db, 'close_hour', '23') or 23)
})
except:
return jsonify({'open_hour': 10, 'close_hour': 23})
# POST
data = request.get_json()
try:
with get_db() as db:
set_config_safe(db, 'open_hour', str(data.get('open_hour', 10)))
set_config_safe(db, 'close_hour', str(data.get('close_hour', 23)))
db.commit()
return jsonify({"message": "Öffnungszeiten gespeichert"})
except Exception as e:
return jsonify({"error": str(e)}), 500