2025-10-14 21:27:41 +02:00

187 lines
6.9 KiB
Python

from flask import Blueprint, render_template, request, redirect, url_for, flash, jsonify
from flask_login import login_required, current_user
from functools import wraps
from app.models import User, db
from werkzeug.security import generate_password_hash
admin_bp = Blueprint('admin', __name__, url_prefix='/admin')
def admin_required(f):
@wraps(f)
@login_required
def decorated_function(*args, **kwargs):
if not current_user.is_admin:
flash('Zugriff verweigert. Administrator-Rechte erforderlich.', 'error')
return redirect(url_for('main.dashboard'))
return f(*args, **kwargs)
return decorated_function
@admin_bp.route('/')
@admin_required
def admin_dashboard():
"""Admin Dashboard mit Benutzerübersicht"""
users = User.query.order_by(User.created_at.desc()).all()
return render_template('admin/dashboard.html', users=users)
@admin_bp.route('/users')
@admin_required
def users():
"""Benutzerverwaltung"""
users = User.query.order_by(User.created_at.desc()).all()
return render_template('admin/users.html', users=users)
@admin_bp.route('/users/create', methods=['GET', 'POST'])
@admin_required
def create_user():
"""Neuen Benutzer erstellen"""
if request.method == 'POST':
username = request.form.get('username', '').strip()
email = request.form.get('email', '').strip()
password = request.form.get('password', '').strip()
is_admin = 'is_admin' in request.form
# Validierung
if not username or not email or not password:
flash('Alle Felder sind erforderlich.', 'error')
return render_template('admin/create_user.html')
# Prüfe ob Benutzername bereits existiert
if User.query.filter_by(username=username).first():
flash('Benutzername bereits vergeben.', 'error')
return render_template('admin/create_user.html')
# Prüfe ob E-Mail bereits existiert
if User.query.filter_by(email=email).first():
flash('E-Mail-Adresse bereits vergeben.', 'error')
return render_template('admin/create_user.html')
try:
# Benutzer erstellen
user = User(
username=username,
email=email,
is_admin=is_admin
)
user.set_password(password)
db.session.add(user)
db.session.commit()
flash(f'Benutzer "{username}" erfolgreich erstellt.', 'success')
return redirect(url_for('admin.users'))
except Exception as e:
db.session.rollback()
flash(f'Fehler beim Erstellen des Benutzers: {str(e)}', 'error')
return render_template('admin/create_user.html')
@admin_bp.route('/users/<int:user_id>/edit', methods=['GET', 'POST'])
@admin_required
def edit_user(user_id):
"""Benutzer bearbeiten"""
user = User.query.get_or_404(user_id)
if request.method == 'POST':
username = request.form.get('username', '').strip()
email = request.form.get('email', '').strip()
password = request.form.get('password', '').strip()
is_admin = 'is_admin' in request.form
# Validierung
if not username or not email:
flash('Benutzername und E-Mail sind erforderlich.', 'error')
return render_template('admin/edit_user.html', user=user)
# Prüfe ob Benutzername bereits von anderem User verwendet wird
existing_user = User.query.filter_by(username=username).first()
if existing_user and existing_user.id != user_id:
flash('Benutzername bereits vergeben.', 'error')
return render_template('admin/edit_user.html', user=user)
# Prüfe ob E-Mail bereits von anderem User verwendet wird
existing_email = User.query.filter_by(email=email).first()
if existing_email and existing_email.id != user_id:
flash('E-Mail-Adresse bereits vergeben.', 'error')
return render_template('admin/edit_user.html', user=user)
try:
# Benutzer aktualisieren
user.username = username
user.email = email
user.is_admin = is_admin
# Passwort nur ändern wenn angegeben
if password:
user.set_password(password)
db.session.commit()
flash(f'Benutzer "{username}" erfolgreich aktualisiert.', 'success')
return redirect(url_for('admin.users'))
except Exception as e:
db.session.rollback()
flash(f'Fehler beim Aktualisieren des Benutzers: {str(e)}', 'error')
return render_template('admin/edit_user.html', user=user)
@admin_bp.route('/users/<int:user_id>/delete', methods=['POST'])
@admin_required
def delete_user(user_id):
"""Benutzer löschen"""
user = User.query.get_or_404(user_id)
# Verhindere dass der Admin sich selbst löscht
if user.id == current_user.id:
flash('Sie können sich nicht selbst löschen.', 'error')
return redirect(url_for('admin.users'))
# Verhindere das Löschen des letzten Admins
if user.is_admin:
admin_count = User.query.filter_by(is_admin=True).count()
if admin_count <= 1:
flash('Der letzte Administrator kann nicht gelöscht werden.', 'error')
return redirect(url_for('admin.users'))
try:
username = user.username
db.session.delete(user)
db.session.commit()
flash(f'Benutzer "{username}" erfolgreich gelöscht.', 'success')
except Exception as e:
db.session.rollback()
flash(f'Fehler beim Löschen des Benutzers: {str(e)}', 'error')
return redirect(url_for('admin.users'))
@admin_bp.route('/users/<int:user_id>/toggle_admin', methods=['POST'])
@admin_required
def toggle_admin(user_id):
"""Admin-Status umschalten"""
user = User.query.get_or_404(user_id)
# Verhindere dass der Admin sich selbst die Admin-Rechte entzieht
if user.id == current_user.id and user.is_admin:
return jsonify({'error': 'Sie können sich nicht selbst die Admin-Rechte entziehen.'}), 400
# Verhindere das Entziehen der Admin-Rechte des letzten Admins
if user.is_admin:
admin_count = User.query.filter_by(is_admin=True).count()
if admin_count <= 1:
return jsonify({'error': 'Der letzte Administrator kann nicht degradiert werden.'}), 400
try:
user.is_admin = not user.is_admin
db.session.commit()
status = 'Administrator' if user.is_admin else 'Benutzer'
return jsonify({
'success': True,
'message': f'{user.username} ist jetzt {status}.',
'is_admin': user.is_admin
})
except Exception as e:
db.session.rollback()
return jsonify({'error': str(e)}), 500