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//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//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//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