Files

180 lines
5.8 KiB
Python

"""
ADMIN ROUTES FÜR app.py
Diese Routes sollten zu app.py hinzugefügt werden (nach den Error Handlers, vor if __name__)
"""
# ============================================================================
# ADMIN ROUTES (diese zeilen in app.py hinzufügen!)
# ============================================================================
@app.route("/admin", methods=["GET"])
@auth.login_required
def admin_dashboard():
"""Admin Dashboard - nur für Admin-Benutzer"""
user = auth.current_user()
if user not in ADMIN_USERS:
log_access(user, "/admin", "GET", 403)
return jsonify({"error": "Unauthorized - Admin access required"}), 403
log_access(user, "/admin", "GET")
return render_template("admin.html")
@app.route("/api/admin/stats", methods=["GET"])
@auth.login_required
def get_admin_stats():
"""Statistiken für Admin Dashboard"""
user = auth.current_user()
if user not in ADMIN_USERS:
log_access(user, "/api/admin/stats", "GET", 403)
return jsonify({"error": "Unauthorized"}), 403
log_access(user, "/api/admin/stats", "GET")
logs = []
if os.path.exists(LOG_FILE):
try:
with open(LOG_FILE, "r") as f:
logs = json.load(f)
except json.JSONDecodeError:
logs = []
# Berechne Statistiken
total_requests = len(logs)
unique_users = len(set(log.get("username", "unknown") for log in logs))
failed_logins = len([l for l in logs if l.get("status") == 401])
return jsonify({
"total_requests": total_requests,
"unique_users": unique_users,
"failed_logins": failed_logins,
"timestamp": datetime.now().isoformat()
}), 200
@app.route("/api/admin/logs", methods=["GET"])
@auth.login_required
def get_admin_logs():
"""Access Logs für Admin Dashboard"""
user = auth.current_user()
if user not in ADMIN_USERS:
log_access(user, "/api/admin/logs", "GET", 403)
return jsonify({"error": "Unauthorized"}), 403
log_access(user, "/api/admin/logs", "GET")
logs = []
if os.path.exists(LOG_FILE):
try:
with open(LOG_FILE, "r") as f:
logs = json.load(f)
except json.JSONDecodeError:
logs = []
# Sortiere nach Zeitstempel absteigend (neueste zuerst)
logs_sorted = sorted(logs, key=lambda x: x.get("timestamp", ""), reverse=True)
# Optionales Limit (letzte 500 Logs)
return jsonify({"logs": logs_sorted[-500:]}), 200
@app.route("/api/admin/export", methods=["GET"])
@auth.login_required
def export_logs():
"""Exportiere Logs als CSV/JSON"""
user = auth.current_user()
if user not in ADMIN_USERS:
return jsonify({"error": "Unauthorized"}), 403
log_access(user, "/api/admin/export", "GET")
logs = []
if os.path.exists(LOG_FILE):
try:
with open(LOG_FILE, "r") as f:
logs = json.load(f)
except json.JSONDecodeError:
logs = []
# Optional: Als CSV exportieren
fmt = request.args.get("format", "json")
if fmt == "csv":
import csv
from io import StringIO
output = StringIO()
writer = csv.DictWriter(output, fieldnames=["timestamp", "username", "endpoint", "method", "status"])
writer.writeheader()
writer.writerows(logs)
response = app.make_response(output.getvalue())
response.headers["Content-Disposition"] = f"attachment; filename=logs_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv"
response.headers["Content-Type"] = "text/csv"
return response
else:
response = app.make_response(json.dumps(logs, indent=2))
response.headers["Content-Disposition"] = f"attachment; filename=logs_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
response.headers["Content-Type"] = "application/json"
return response
# ============================================================================
# OPTIONAL: Admin-Utility-Routes
# ============================================================================
@app.route("/api/admin/clear-logs", methods=["POST"])
@auth.login_required
def clear_logs():
"""Lösche alle Logs (nur für Admin, mit Bestätigung)"""
user = auth.current_user()
if user not in ADMIN_USERS:
return jsonify({"error": "Unauthorized"}), 403
# Safety: Verlange "confirm=true" Query Parameter
confirm = request.args.get("confirm") == "true"
if not confirm:
return jsonify({"error": "Confirmation required (add ?confirm=true)"}), 400
log_access(user, "/api/admin/clear-logs", "POST")
# Backup erstellen vor dem Löschen
if os.path.exists(LOG_FILE):
backup_file = LOG_FILE + f".backup_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
import shutil
shutil.copy(LOG_FILE, backup_file)
# Logs leeren
with open(LOG_FILE, "w") as f:
json.dump([], f)
return jsonify({
"status": "success",
"message": "Alle Logs wurden gelöscht (Backup erstellt)"
}), 200
@app.route("/api/admin/system-info", methods=["GET"])
@auth.login_required
def get_system_info():
"""System-Information für Admin"""
user = auth.current_user()
if user not in ADMIN_USERS:
return jsonify({"error": "Unauthorized"}), 403
log_access(user, "/api/admin/system-info", "GET")
import psutil
return jsonify({
"environment": os.getenv("FLASK_ENV", "production"),
"debug_mode": app.debug,
"database_file": LOG_FILE,
"database_size_kb": os.path.getsize(LOG_FILE) / 1024 if os.path.exists(LOG_FILE) else 0,
"timestamp": datetime.now().isoformat(),
# Optional: CPU/RAM Info
# "cpu_percent": psutil.cpu_percent(),
# "memory_percent": psutil.virtual_memory().percent,
}), 200