✨ Add comprehensive admin panel with user management
Features added: - Admin authentication system with is_admin field - Complete admin dashboard with user statistics - User management (create, edit, delete, toggle admin) - Protected admin routes with @admin_required decorator - Security features (prevent self-deletion, last admin protection) - Responsive admin UI with Bootstrap integration - Database migration script for admin field - Admin navigation link for authorized users Technical improvements: - Enhanced 3-column dashboard layout (tables | editor | saved queries) - Removed plus button and made right sidebar more compact - Admin user (admin/admin123) automatically created with admin privileges - Full CRUD operations for user management - Flash messages for user feedback - Form validation and error handling
This commit is contained in:
@@ -46,7 +46,7 @@ def create_app():
|
||||
from app.models import User
|
||||
admin = User.query.filter_by(username='admin').first()
|
||||
if not admin:
|
||||
admin = User(username='admin', email='admin@example.com')
|
||||
admin = User(username='admin', email='admin@example.com', is_admin=True)
|
||||
admin.set_password('admin123')
|
||||
db.session.add(admin)
|
||||
db.session.commit()
|
||||
|
||||
Binary file not shown.
88
app/templates/admin/create_user.html
Normal file
88
app/templates/admin/create_user.html
Normal file
@@ -0,0 +1,88 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Neuen Benutzer erstellen{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h2><i class="fas fa-user-plus"></i> Neuen Benutzer erstellen</h2>
|
||||
<a href="{{ url_for('admin.users') }}" class="btn btn-outline-secondary">
|
||||
<i class="fas fa-arrow-left"></i> Zurück
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<form method="POST">
|
||||
<div class="mb-3">
|
||||
<label for="username" class="form-label">
|
||||
<i class="fas fa-user"></i> Benutzername *
|
||||
</label>
|
||||
<input type="text" class="form-control" id="username" name="username"
|
||||
required maxlength="80" placeholder="z.B. john.doe">
|
||||
<div class="form-text">Der Benutzername muss eindeutig sein</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="email" class="form-label">
|
||||
<i class="fas fa-envelope"></i> E-Mail-Adresse *
|
||||
</label>
|
||||
<input type="email" class="form-control" id="email" name="email"
|
||||
required maxlength="120" placeholder="john.doe@example.com">
|
||||
<div class="form-text">Die E-Mail-Adresse muss eindeutig sein</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="password" class="form-label">
|
||||
<i class="fas fa-lock"></i> Passwort *
|
||||
</label>
|
||||
<input type="password" class="form-control" id="password" name="password"
|
||||
required minlength="6" placeholder="Mindestens 6 Zeichen">
|
||||
<div class="form-text">Mindestens 6 Zeichen erforderlich</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="is_admin" name="is_admin">
|
||||
<label class="form-check-label" for="is_admin">
|
||||
<i class="fas fa-user-shield text-danger"></i> Administrator-Rechte gewähren
|
||||
</label>
|
||||
<div class="form-text">
|
||||
Administratoren können andere Benutzer verwalten und haben Vollzugriff
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-grid gap-2">
|
||||
<button type="submit" class="btn btn-success">
|
||||
<i class="fas fa-user-plus"></i> Benutzer erstellen
|
||||
</button>
|
||||
<a href="{{ url_for('admin.users') }}" class="btn btn-outline-secondary">
|
||||
<i class="fas fa-times"></i> Abbrechen
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Hinweise -->
|
||||
<div class="card mt-4">
|
||||
<div class="card-header">
|
||||
<h6><i class="fas fa-info-circle"></i> Wichtige Hinweise</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<ul class="mb-0">
|
||||
<li>Alle mit * markierten Felder sind Pflichtfelder</li>
|
||||
<li>Der Benutzername und die E-Mail-Adresse müssen eindeutig sein</li>
|
||||
<li>Das Passwort sollte sicher gewählt werden</li>
|
||||
<li>Administrator-Rechte gewähren Vollzugriff auf alle Funktionen</li>
|
||||
<li>Neue Benutzer können sich sofort mit ihren Anmeldedaten einloggen</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
173
app/templates/admin/dashboard.html
Normal file
173
app/templates/admin/dashboard.html
Normal file
@@ -0,0 +1,173 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Admin Dashboard{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h2><i class="fas fa-users-cog"></i> Admin Dashboard</h2>
|
||||
<a href="{{ url_for('main.dashboard') }}" class="btn btn-outline-secondary">
|
||||
<i class="fas fa-arrow-left"></i> Zurück zum Dashboard
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Statistiken -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-3">
|
||||
<div class="card bg-primary text-white">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h4>{{ users|length }}</h4>
|
||||
<small>Benutzer gesamt</small>
|
||||
</div>
|
||||
<i class="fas fa-users fa-2x opacity-75"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card bg-success text-white">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h4>{{ users|selectattr('is_admin')|list|length }}</h4>
|
||||
<small>Administratoren</small>
|
||||
</div>
|
||||
<i class="fas fa-user-shield fa-2x opacity-75"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card bg-info text-white">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h4>{{ users|rejectattr('is_admin')|list|length }}</h4>
|
||||
<small>Standard-Benutzer</small>
|
||||
</div>
|
||||
<i class="fas fa-user fa-2x opacity-75"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card bg-warning text-white">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h4>{{ (users|selectattr('created_at')|map(attribute='created_at')|list|length) }}</h4>
|
||||
<small>Aktive Benutzer</small>
|
||||
</div>
|
||||
<i class="fas fa-chart-line fa-2x opacity-75"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Schnellzugriff -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5><i class="fas fa-tachometer-alt"></i> Schnellzugriff</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<a href="{{ url_for('admin.users') }}" class="btn btn-outline-primary btn-lg w-100">
|
||||
<i class="fas fa-users"></i>
|
||||
<div class="mt-2">
|
||||
<strong>Benutzerverwaltung</strong>
|
||||
<br><small class="text-muted">Benutzer anzeigen, bearbeiten und erstellen</small>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<a href="{{ url_for('admin.create_user') }}" class="btn btn-outline-success btn-lg w-100">
|
||||
<i class="fas fa-user-plus"></i>
|
||||
<div class="mt-2">
|
||||
<strong>Neuen Benutzer erstellen</strong>
|
||||
<br><small class="text-muted">Schnell einen neuen Benutzer hinzufügen</small>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Letzte Benutzer -->
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5><i class="fas fa-clock"></i> Letzte Benutzer</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if users %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Benutzername</th>
|
||||
<th>E-Mail</th>
|
||||
<th>Rolle</th>
|
||||
<th>Erstellt am</th>
|
||||
<th>Aktionen</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for user in users[:5] %}
|
||||
<tr>
|
||||
<td>
|
||||
<strong>{{ user.username }}</strong>
|
||||
{% if user.id == current_user.id %}
|
||||
<span class="badge bg-primary ms-1">Sie</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ user.email }}</td>
|
||||
<td>
|
||||
{% if user.is_admin %}
|
||||
<span class="badge bg-danger"><i class="fas fa-user-shield"></i> Administrator</span>
|
||||
{% else %}
|
||||
<span class="badge bg-secondary"><i class="fas fa-user"></i> Benutzer</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ user.created_at.strftime('%d.%m.%Y %H:%M') }}</td>
|
||||
<td>
|
||||
<a href="{{ url_for('admin.edit_user', user_id=user.id) }}"
|
||||
class="btn btn-sm btn-outline-primary" title="Bearbeiten">
|
||||
<i class="fas fa-edit"></i>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="text-center mt-3">
|
||||
<a href="{{ url_for('admin.users') }}" class="btn btn-primary">
|
||||
Alle Benutzer anzeigen <i class="fas fa-arrow-right"></i>
|
||||
</a>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="text-center text-muted py-4">
|
||||
<i class="fas fa-users fa-3x mb-3"></i>
|
||||
<h5>Keine Benutzer gefunden</h5>
|
||||
<p>Erstellen Sie den ersten Benutzer über den Button oben.</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
145
app/templates/admin/edit_user.html
Normal file
145
app/templates/admin/edit_user.html
Normal file
@@ -0,0 +1,145 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Benutzer bearbeiten{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h2><i class="fas fa-user-edit"></i> Benutzer bearbeiten</h2>
|
||||
<a href="{{ url_for('admin.users') }}" class="btn btn-outline-secondary">
|
||||
<i class="fas fa-arrow-left"></i> Zurück
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5>
|
||||
{{ user.username }}
|
||||
{% if user.id == current_user.id %}
|
||||
<span class="badge bg-primary">Sie</span>
|
||||
{% endif %}
|
||||
{% if user.is_admin %}
|
||||
<span class="badge bg-danger">Administrator</span>
|
||||
{% endif %}
|
||||
</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form method="POST">
|
||||
<div class="mb-3">
|
||||
<label for="username" class="form-label">
|
||||
<i class="fas fa-user"></i> Benutzername *
|
||||
</label>
|
||||
<input type="text" class="form-control" id="username" name="username"
|
||||
value="{{ user.username }}" required maxlength="80"
|
||||
placeholder="z.B. john.doe">
|
||||
<div class="form-text">Der Benutzername muss eindeutig sein</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="email" class="form-label">
|
||||
<i class="fas fa-envelope"></i> E-Mail-Adresse *
|
||||
</label>
|
||||
<input type="email" class="form-control" id="email" name="email"
|
||||
value="{{ user.email }}" required maxlength="120"
|
||||
placeholder="john.doe@example.com">
|
||||
<div class="form-text">Die E-Mail-Adresse muss eindeutig sein</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="password" class="form-label">
|
||||
<i class="fas fa-lock"></i> Neues Passwort
|
||||
</label>
|
||||
<input type="password" class="form-control" id="password" name="password"
|
||||
minlength="6" placeholder="Leer lassen um Passwort beizubehalten">
|
||||
<div class="form-text">Nur ausfüllen wenn Sie das Passwort ändern möchten (mindestens 6 Zeichen)</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="is_admin" name="is_admin"
|
||||
{% if user.is_admin %}checked{% endif %}
|
||||
{% if user.id == current_user.id %}disabled{% endif %}>
|
||||
<label class="form-check-label" for="is_admin">
|
||||
<i class="fas fa-user-shield text-danger"></i> Administrator-Rechte
|
||||
</label>
|
||||
{% if user.id == current_user.id %}
|
||||
<div class="form-text text-warning">
|
||||
<i class="fas fa-exclamation-triangle"></i> Sie können Ihre eigenen Admin-Rechte nicht ändern
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="form-text">
|
||||
Administratoren können andere Benutzer verwalten und haben Vollzugriff
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-grid gap-2">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="fas fa-save"></i> Änderungen speichern
|
||||
</button>
|
||||
<a href="{{ url_for('admin.users') }}" class="btn btn-outline-secondary">
|
||||
<i class="fas fa-times"></i> Abbrechen
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Benutzer-Informationen -->
|
||||
<div class="card mt-4">
|
||||
<div class="card-header">
|
||||
<h6><i class="fas fa-info-circle"></i> Benutzer-Informationen</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-sm-4"><strong>Benutzer-ID:</strong></div>
|
||||
<div class="col-sm-8">{{ user.id }}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-4"><strong>Erstellt am:</strong></div>
|
||||
<div class="col-sm-8">{{ user.created_at.strftime('%d.%m.%Y %H:%M:%S') }}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-4"><strong>Rolle:</strong></div>
|
||||
<div class="col-sm-8">
|
||||
{% if user.is_admin %}
|
||||
<span class="badge bg-danger">Administrator</span>
|
||||
{% else %}
|
||||
<span class="badge bg-secondary">Standard-Benutzer</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-4"><strong>Anzahl Queries:</strong></div>
|
||||
<div class="col-sm-8">{{ user.saved_queries|length }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Lösch-Option -->
|
||||
{% if user.id != current_user.id %}
|
||||
<div class="card mt-4 border-danger">
|
||||
<div class="card-header bg-danger text-white">
|
||||
<h6><i class="fas fa-exclamation-triangle"></i> Gefahrenbereich</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="text-danger">
|
||||
<strong>Achtung:</strong> Das Löschen eines Benutzers kann nicht rückgängig gemacht werden.
|
||||
Alle gespeicherten Queries dieses Benutzers gehen verloren.
|
||||
</p>
|
||||
<form method="POST" action="{{ url_for('admin.delete_user', user_id=user.id) }}"
|
||||
onsubmit="return confirm('Benutzer {{ user.username }} wirklich unwiderruflich löschen?\\n\\nAlle gespeicherten Queries gehen verloren!')">
|
||||
<button type="submit" class="btn btn-danger">
|
||||
<i class="fas fa-trash"></i> Benutzer löschen
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
154
app/templates/admin/users.html
Normal file
154
app/templates/admin/users.html
Normal file
@@ -0,0 +1,154 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Benutzerverwaltung{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h2><i class="fas fa-users"></i> Benutzerverwaltung</h2>
|
||||
<div>
|
||||
<a href="{{ url_for('admin.create_user') }}" class="btn btn-success">
|
||||
<i class="fas fa-user-plus"></i> Neuen Benutzer erstellen
|
||||
</a>
|
||||
<a href="{{ url_for('admin.admin_dashboard') }}" class="btn btn-outline-secondary">
|
||||
<i class="fas fa-arrow-left"></i> Admin Dashboard
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if users %}
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Benutzername</th>
|
||||
<th>E-Mail</th>
|
||||
<th>Rolle</th>
|
||||
<th>Erstellt am</th>
|
||||
<th>Aktionen</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for user in users %}
|
||||
<tr id="user-row-{{ user.id }}">
|
||||
<td>{{ user.id }}</td>
|
||||
<td>
|
||||
<strong>{{ user.username }}</strong>
|
||||
{% if user.id == current_user.id %}
|
||||
<span class="badge bg-primary ms-1">Sie</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ user.email }}</td>
|
||||
<td>
|
||||
<div class="d-flex align-items-center">
|
||||
{% if user.is_admin %}
|
||||
<span class="badge bg-danger me-2">
|
||||
<i class="fas fa-user-shield"></i> Administrator
|
||||
</span>
|
||||
{% else %}
|
||||
<span class="badge bg-secondary me-2">
|
||||
<i class="fas fa-user"></i> Benutzer
|
||||
</span>
|
||||
{% endif %}
|
||||
|
||||
{% if user.id != current_user.id %}
|
||||
<button class="btn btn-xs btn-outline-info"
|
||||
onclick="toggleAdmin({{ user.id }})"
|
||||
title="Rolle wechseln">
|
||||
<i class="fas fa-exchange-alt"></i>
|
||||
</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
</td>
|
||||
<td>{{ user.created_at.strftime('%d.%m.%Y %H:%M') }}</td>
|
||||
<td>
|
||||
<div class="btn-group btn-group-sm">
|
||||
<a href="{{ url_for('admin.edit_user', user_id=user.id) }}"
|
||||
class="btn btn-outline-primary" title="Bearbeiten">
|
||||
<i class="fas fa-edit"></i>
|
||||
</a>
|
||||
|
||||
{% if user.id != current_user.id %}
|
||||
<form method="POST" action="{{ url_for('admin.delete_user', user_id=user.id) }}"
|
||||
class="d-inline" onsubmit="return confirm('Benutzer {{ user.username }} wirklich löschen?')">
|
||||
<button type="submit" class="btn btn-outline-danger" title="Löschen">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="card">
|
||||
<div class="card-body text-center py-5">
|
||||
<i class="fas fa-users fa-3x text-muted mb-3"></i>
|
||||
<h4>Keine Benutzer gefunden</h4>
|
||||
<p class="text-muted">Erstellen Sie den ersten Benutzer.</p>
|
||||
<a href="{{ url_for('admin.create_user') }}" class="btn btn-success">
|
||||
<i class="fas fa-user-plus"></i> Ersten Benutzer erstellen
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
async function toggleAdmin(userId) {
|
||||
try {
|
||||
const response = await fetch(`/admin/users/${userId}/toggle_admin`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
showAlert(data.message, 'success');
|
||||
// Seite neu laden um Änderungen anzuzeigen
|
||||
setTimeout(() => window.location.reload(), 1000);
|
||||
} else {
|
||||
showAlert(data.error, 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
showAlert(`Fehler: ${error.message}`, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
function showAlert(message, type = 'info') {
|
||||
const alertClass = type === 'error' ? 'alert-danger' :
|
||||
type === 'success' ? 'alert-success' : 'alert-info';
|
||||
|
||||
const alertHtml = `
|
||||
<div class="alert ${alertClass} alert-dismissible fade show" role="alert">
|
||||
${message}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Alert am Anfang der Seite einfügen
|
||||
const container = document.querySelector('.container-fluid');
|
||||
const existingAlert = container.querySelector('.alert');
|
||||
if (existingAlert) {
|
||||
existingAlert.remove();
|
||||
}
|
||||
|
||||
container.insertAdjacentHTML('afterbegin', alertHtml);
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -23,8 +23,16 @@
|
||||
|
||||
{% if current_user.is_authenticated %}
|
||||
<div class="navbar-nav ms-auto">
|
||||
{% if current_user.is_admin %}
|
||||
<a class="nav-link me-3" href="{{ url_for('admin.admin_dashboard') }}">
|
||||
<i class="fas fa-users-cog"></i> Admin
|
||||
</a>
|
||||
{% endif %}
|
||||
<span class="navbar-text me-3">
|
||||
<i class="fas fa-user"></i> {{ current_user.username }}
|
||||
{% if current_user.is_admin %}
|
||||
<span class="badge bg-danger ms-1">Admin</span>
|
||||
{% endif %}
|
||||
</span>
|
||||
<a class="nav-link" href="{{ url_for('auth.logout') }}">
|
||||
<i class="fas fa-sign-out-alt"></i> Abmelden
|
||||
|
||||
Reference in New Issue
Block a user