"Feature: Update admin interface and database schema"

This commit is contained in:
Till Tomczak 2025-05-29 19:02:23 +02:00
parent cf297e8e16
commit ca9abadc6a
3 changed files with 67 additions and 37 deletions

View File

@ -354,15 +354,18 @@ def login():
@app.route("/auth/logout", methods=["GET", "POST"])
@login_required
def auth_logout():
username = current_user.username if hasattr(current_user, "username") else "Unbekannt"
"""Meldet den Benutzer ab."""
app_logger.info(f"Benutzer {current_user.email} hat sich abgemeldet")
logout_user()
auth_logger.info(f"Benutzer {username} hat sich abgemeldet")
# Unterscheiden zwischen JSON-Anfragen und normalen Anfragen
if request.is_json or request.headers.get('Content-Type') == 'application/json':
return jsonify({"success": True, "redirect_url": url_for("login")})
else:
return redirect(url_for("login"))
flash("Sie wurden erfolgreich abgemeldet.", "info")
return redirect(url_for("login"))
@app.route("/auth/reset-password-request", methods=["GET", "POST"])
def reset_password_request():
"""Passwort-Reset anfordern (Placeholder)."""
# TODO: Implement password reset functionality
flash("Passwort-Reset-Funktionalität ist noch nicht implementiert.", "info")
return redirect(url_for("login"))
@app.route("/auth/api/login", methods=["POST"])
def api_login():

Binary file not shown.

View File

@ -518,14 +518,20 @@
<div class="flex items-center justify-between mb-6">
<h2 class="text-2xl font-bold text-slate-900 dark:text-white">System Logs</h2>
<div class="flex space-x-3">
<select class="px-4 py-2 bg-white dark:bg-slate-700 border border-slate-300 dark:border-slate-600 rounded-xl text-slate-900 dark:text-white focus:ring-2 focus:ring-blue-500 focus:border-transparent">
<option>Alle Logs</option>
<option>Fehler</option>
<option>Warnungen</option>
<option>Info</option>
<option>Debug</option>
<select id="log-level-filter" class="px-4 py-2 bg-white dark:bg-slate-700 border border-slate-300 dark:border-slate-600 rounded-xl text-slate-900 dark:text-white focus:ring-2 focus:ring-blue-500 focus:border-transparent">
<option value="all">Alle Logs</option>
<option value="error">Fehler</option>
<option value="warning">Warnungen</option>
<option value="info">Info</option>
<option value="debug">Debug</option>
</select>
<button class="inline-flex items-center px-4 py-2 bg-gradient-to-r from-slate-500 to-slate-600 text-white rounded-xl hover:from-slate-600 hover:to-slate-700 transition-all duration-300 shadow-lg hover:shadow-xl">
<button id="refresh-logs-btn" class="inline-flex items-center px-4 py-2 bg-gradient-to-r from-green-500 to-green-600 text-white rounded-xl hover:from-green-600 hover:to-green-700 transition-all duration-300 shadow-lg hover:shadow-xl">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"/>
</svg>
Aktualisieren
</button>
<button id="export-logs-btn" class="inline-flex items-center px-4 py-2 bg-gradient-to-r from-slate-500 to-slate-600 text-white rounded-xl hover:from-slate-600 hover:to-slate-700 transition-all duration-300 shadow-lg hover:shadow-xl">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"/>
</svg>
@ -534,29 +540,12 @@
</div>
</div>
<!-- Log Entries -->
<div class="space-y-2 max-h-96 overflow-y-auto">
{% for log in logs %}
<div class="bg-white/60 dark:bg-slate-700/60 backdrop-blur-sm rounded-lg border border-slate-200 dark:border-slate-600 p-4 shadow-sm">
<div class="flex items-start justify-between">
<div class="flex items-start space-x-3">
{% set log_colors = {
'ERROR': 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200',
'WARNING': 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200',
'INFO': 'bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200',
'DEBUG': 'bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-200'
} %}
<span class="inline-flex px-2 py-1 text-xs font-semibold rounded-full {{ log_colors.get(log.level, 'bg-gray-100 text-gray-800') }}">
{{ log.level }}
</span>
<div>
<p class="text-sm text-slate-900 dark:text-white">{{ log.message }}</p>
<p class="text-xs text-slate-500 dark:text-slate-400 mt-1">{{ log.module }} - {{ log.timestamp | format_datetime('%d.%m.%Y %H:%M:%S') if log.timestamp else 'Unbekannt' }}</p>
</div>
</div>
</div>
<!-- Log Entries Container -->
<div id="logs-container" class="space-y-2 max-h-96 overflow-y-auto">
<!-- Logs werden hier dynamisch geladen -->
<div class="flex justify-center items-center py-12">
<div class="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 dark:border-blue-400"></div>
</div>
{% endfor %}
</div>
</div>
@ -690,6 +679,44 @@ document.addEventListener('DOMContentLoaded', function() {
});
});
// Logs-Tab Event-Handlers und Funktionen
const refreshLogsBtn = document.getElementById('refresh-logs-btn');
if (refreshLogsBtn) {
refreshLogsBtn.addEventListener('click', loadLogs);
}
const exportLogsBtn = document.getElementById('export-logs-btn');
if (exportLogsBtn) {
exportLogsBtn.addEventListener('click', function() {
window.location.href = '/api/admin/logs/export';
});
}
const logLevelFilter = document.getElementById('log-level-filter');
if (logLevelFilter) {
logLevelFilter.addEventListener('change', function() {
if (window.logsData) {
const level = this.value;
if (level === 'all') {
window.filteredLogs = [...window.logsData];
} else {
window.filteredLogs = window.logsData.filter(log =>
log.level.toLowerCase() === level.toLowerCase()
);
}
renderLogs();
}
});
}
// Logs beim Laden des Logs-Tabs automatisch laden
const urlParams = new URLSearchParams(window.location.search);
const activeTab = urlParams.get('tab');
if (activeTab === 'logs') {
// Kurz warten, damit das DOM vollständig geladen ist
setTimeout(loadLogs, 500);
}
// Start Live-Updates
startLiveUpdates();
});