a5e2788d57
- 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
320 lines
12 KiB
Python
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 |