🎉 Refactored backend structure: Removed unused files including app_cleaned.py, admin_api.py, admin.py, user.py, and others. Updated settings.local.json to include additional Bash commands. Enhanced admin templates for better navigation and functionality. Improved logging and error handling across various modules.
This commit is contained in:
335
backend/blueprints/deprecated/admin.py
Normal file
335
backend/blueprints/deprecated/admin.py
Normal file
@@ -0,0 +1,335 @@
|
||||
"""
|
||||
Admin-Blueprint für das 3D-Druck-Management-System
|
||||
|
||||
Dieses Modul enthält alle Admin-spezifischen Routen und Funktionen,
|
||||
einschließlich Benutzerverwaltung, Systemüberwachung und Drucker-Administration.
|
||||
"""
|
||||
|
||||
from flask import Blueprint, render_template, request, jsonify, redirect, url_for, flash
|
||||
from flask_login import login_required, current_user
|
||||
from functools import wraps
|
||||
from models import User, Printer, Job, get_db_session, Stats, SystemLog
|
||||
from utils.logging_config import get_logger
|
||||
from datetime import datetime
|
||||
|
||||
# Blueprint erstellen
|
||||
admin_blueprint = Blueprint('admin', __name__, url_prefix='/admin')
|
||||
|
||||
# Logger initialisieren
|
||||
admin_logger = get_logger("admin")
|
||||
|
||||
def admin_required(f):
|
||||
"""Decorator für Admin-Berechtigung"""
|
||||
@wraps(f)
|
||||
@login_required
|
||||
def decorated_function(*args, **kwargs):
|
||||
admin_logger.info(f"Admin-Check für Funktion {f.__name__}: User authenticated: {current_user.is_authenticated}, User ID: {current_user.id if current_user.is_authenticated else 'None'}, Is Admin: {current_user.is_admin if current_user.is_authenticated else 'None'}")
|
||||
if not current_user.is_admin:
|
||||
admin_logger.warning(f"Admin-Zugriff verweigert für User {current_user.id if current_user.is_authenticated else 'Anonymous'} auf Funktion {f.__name__}")
|
||||
return jsonify({"error": "Nur Administratoren haben Zugriff"}), 403
|
||||
return f(*args, **kwargs)
|
||||
return decorated_function
|
||||
|
||||
@admin_blueprint.route("/")
|
||||
@login_required
|
||||
@admin_required
|
||||
def admin_dashboard():
|
||||
"""Admin-Dashboard-Hauptseite"""
|
||||
try:
|
||||
db_session = get_db_session()
|
||||
|
||||
# Grundlegende Statistiken sammeln
|
||||
total_users = db_session.query(User).count()
|
||||
total_printers = db_session.query(Printer).count()
|
||||
total_jobs = db_session.query(Job).count()
|
||||
|
||||
# Aktive Jobs zählen
|
||||
active_jobs = db_session.query(Job).filter(
|
||||
Job.status.in_(['pending', 'printing', 'paused'])
|
||||
).count()
|
||||
|
||||
db_session.close()
|
||||
|
||||
stats = {
|
||||
'total_users': total_users,
|
||||
'total_printers': total_printers,
|
||||
'total_jobs': total_jobs,
|
||||
'active_jobs': active_jobs
|
||||
}
|
||||
|
||||
return render_template('admin/dashboard.html', stats=stats)
|
||||
|
||||
except Exception as e:
|
||||
admin_logger.error(f"Fehler beim Laden des Admin-Dashboards: {str(e)}")
|
||||
flash("Fehler beim Laden der Dashboard-Daten", "error")
|
||||
return render_template('admin/dashboard.html', stats={})
|
||||
|
||||
@admin_blueprint.route("/users")
|
||||
@login_required
|
||||
@admin_required
|
||||
def users_overview():
|
||||
"""Benutzerübersicht für Administratoren"""
|
||||
return render_template('admin/users.html')
|
||||
|
||||
@admin_blueprint.route("/users/add", methods=["GET"])
|
||||
@login_required
|
||||
@admin_required
|
||||
def add_user_page():
|
||||
"""Seite zum Hinzufügen eines neuen Benutzers"""
|
||||
return render_template('admin/add_user.html')
|
||||
|
||||
@admin_blueprint.route("/users/<int:user_id>/edit", methods=["GET"])
|
||||
@login_required
|
||||
@admin_required
|
||||
def edit_user_page(user_id):
|
||||
"""Seite zum Bearbeiten eines Benutzers"""
|
||||
try:
|
||||
db_session = get_db_session()
|
||||
user = db_session.query(User).filter(User.id == user_id).first()
|
||||
|
||||
if not user:
|
||||
db_session.close()
|
||||
flash("Benutzer nicht gefunden", "error")
|
||||
return redirect(url_for('admin.users_overview'))
|
||||
|
||||
db_session.close()
|
||||
return render_template('admin/edit_user.html', user=user)
|
||||
|
||||
except Exception as e:
|
||||
admin_logger.error(f"Fehler beim Laden der Benutzer-Bearbeitung: {str(e)}")
|
||||
flash("Fehler beim Laden der Benutzerdaten", "error")
|
||||
return redirect(url_for('admin.users_overview'))
|
||||
|
||||
@admin_blueprint.route("/printers")
|
||||
@login_required
|
||||
@admin_required
|
||||
def printers_overview():
|
||||
"""Druckerübersicht für Administratoren"""
|
||||
return render_template('admin/printers.html')
|
||||
|
||||
@admin_blueprint.route("/printers/add", methods=["GET"])
|
||||
@login_required
|
||||
@admin_required
|
||||
def add_printer_page():
|
||||
"""Seite zum Hinzufügen eines neuen Druckers"""
|
||||
return render_template('admin/add_printer.html')
|
||||
|
||||
@admin_blueprint.route("/printers/<int:printer_id>/edit", methods=["GET"])
|
||||
@login_required
|
||||
@admin_required
|
||||
def edit_printer_page(printer_id):
|
||||
"""Seite zum Bearbeiten eines Druckers"""
|
||||
try:
|
||||
db_session = get_db_session()
|
||||
printer = db_session.query(Printer).filter(Printer.id == printer_id).first()
|
||||
|
||||
if not printer:
|
||||
db_session.close()
|
||||
flash("Drucker nicht gefunden", "error")
|
||||
return redirect(url_for('admin.printers_overview'))
|
||||
|
||||
db_session.close()
|
||||
return render_template('admin/edit_printer.html', printer=printer)
|
||||
|
||||
except Exception as e:
|
||||
admin_logger.error(f"Fehler beim Laden der Drucker-Bearbeitung: {str(e)}")
|
||||
flash("Fehler beim Laden der Druckerdaten", "error")
|
||||
return redirect(url_for('admin.printers_overview'))
|
||||
|
||||
@admin_blueprint.route("/guest-requests")
|
||||
@login_required
|
||||
@admin_required
|
||||
def guest_requests():
|
||||
"""Gäste-Anfragen-Übersicht"""
|
||||
return render_template('admin/guest_requests.html')
|
||||
|
||||
@admin_blueprint.route("/advanced-settings")
|
||||
@login_required
|
||||
@admin_required
|
||||
def advanced_settings():
|
||||
"""Erweiterte Systemeinstellungen"""
|
||||
return render_template('admin/advanced_settings.html')
|
||||
|
||||
@admin_blueprint.route("/system-health")
|
||||
@login_required
|
||||
@admin_required
|
||||
def system_health():
|
||||
"""System-Gesundheitsstatus"""
|
||||
return render_template('admin/system_health.html')
|
||||
|
||||
@admin_blueprint.route("/logs")
|
||||
@login_required
|
||||
@admin_required
|
||||
def logs_overview():
|
||||
"""System-Logs-Übersicht"""
|
||||
return render_template('admin/logs.html')
|
||||
|
||||
@admin_blueprint.route("/maintenance")
|
||||
@login_required
|
||||
@admin_required
|
||||
def maintenance():
|
||||
"""Wartungsseite"""
|
||||
return render_template('admin/maintenance.html')
|
||||
|
||||
# API-Endpunkte für Admin-Funktionen
|
||||
@admin_blueprint.route("/api/users", methods=["POST"])
|
||||
@login_required
|
||||
@admin_required
|
||||
def create_user_api():
|
||||
"""API-Endpunkt zum Erstellen eines neuen Benutzers"""
|
||||
try:
|
||||
data = request.get_json()
|
||||
|
||||
# Validierung der erforderlichen Felder
|
||||
required_fields = ['username', 'email', 'password', 'name']
|
||||
for field in required_fields:
|
||||
if field not in data or not data[field]:
|
||||
return jsonify({"error": f"Feld '{field}' ist erforderlich"}), 400
|
||||
|
||||
db_session = get_db_session()
|
||||
|
||||
# Überprüfung auf bereits existierende Benutzer
|
||||
existing_user = db_session.query(User).filter(
|
||||
(User.username == data['username']) | (User.email == data['email'])
|
||||
).first()
|
||||
|
||||
if existing_user:
|
||||
db_session.close()
|
||||
return jsonify({"error": "Benutzername oder E-Mail bereits vergeben"}), 400
|
||||
|
||||
# Neuen Benutzer erstellen
|
||||
new_user = User(
|
||||
username=data['username'],
|
||||
email=data['email'],
|
||||
name=data['name'],
|
||||
role=data.get('role', 'user'),
|
||||
department=data.get('department'),
|
||||
position=data.get('position'),
|
||||
phone=data.get('phone'),
|
||||
bio=data.get('bio')
|
||||
)
|
||||
new_user.set_password(data['password'])
|
||||
|
||||
db_session.add(new_user)
|
||||
db_session.commit()
|
||||
|
||||
admin_logger.info(f"Neuer Benutzer erstellt: {new_user.username} von Admin {current_user.username}")
|
||||
|
||||
db_session.close()
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"message": "Benutzer erfolgreich erstellt",
|
||||
"user_id": new_user.id
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
admin_logger.error(f"Fehler beim Erstellen des Benutzers: {str(e)}")
|
||||
return jsonify({"error": "Fehler beim Erstellen des Benutzers"}), 500
|
||||
|
||||
@admin_blueprint.route("/api/users/<int:user_id>", methods=["GET"])
|
||||
@login_required
|
||||
@admin_required
|
||||
def get_user_api(user_id):
|
||||
"""API-Endpunkt zum Abrufen von Benutzerdaten"""
|
||||
try:
|
||||
db_session = get_db_session()
|
||||
user = db_session.query(User).filter(User.id == user_id).first()
|
||||
|
||||
if not user:
|
||||
db_session.close()
|
||||
return jsonify({"error": "Benutzer nicht gefunden"}), 404
|
||||
|
||||
user_data = {
|
||||
"id": user.id,
|
||||
"username": user.username,
|
||||
"email": user.email,
|
||||
"name": user.name,
|
||||
"role": user.role,
|
||||
"active": user.active,
|
||||
"created_at": user.created_at.isoformat() if user.created_at else None,
|
||||
"last_login": user.last_login.isoformat() if user.last_login else None,
|
||||
"department": user.department,
|
||||
"position": user.position,
|
||||
"phone": user.phone,
|
||||
"bio": user.bio
|
||||
}
|
||||
|
||||
db_session.close()
|
||||
return jsonify(user_data)
|
||||
|
||||
except Exception as e:
|
||||
admin_logger.error(f"Fehler beim Abrufen der Benutzerdaten: {str(e)}")
|
||||
return jsonify({"error": "Fehler beim Abrufen der Benutzerdaten"}), 500
|
||||
|
||||
@admin_blueprint.route("/api/users/<int:user_id>", methods=["PUT"])
|
||||
@login_required
|
||||
@admin_required
|
||||
def update_user_api(user_id):
|
||||
"""API-Endpunkt zum Aktualisieren von Benutzerdaten"""
|
||||
try:
|
||||
data = request.get_json()
|
||||
|
||||
db_session = get_db_session()
|
||||
user = db_session.query(User).filter(User.id == user_id).first()
|
||||
|
||||
if not user:
|
||||
db_session.close()
|
||||
return jsonify({"error": "Benutzer nicht gefunden"}), 404
|
||||
|
||||
# Aktualisierbare Felder
|
||||
updatable_fields = ['username', 'email', 'name', 'role', 'active', 'department', 'position', 'phone', 'bio']
|
||||
|
||||
for field in updatable_fields:
|
||||
if field in data:
|
||||
setattr(user, field, data[field])
|
||||
|
||||
# Passwort separat behandeln
|
||||
if 'password' in data and data['password']:
|
||||
user.set_password(data['password'])
|
||||
|
||||
user.updated_at = datetime.now()
|
||||
db_session.commit()
|
||||
|
||||
admin_logger.info(f"Benutzer {user.username} aktualisiert von Admin {current_user.username}")
|
||||
|
||||
db_session.close()
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"message": "Benutzer erfolgreich aktualisiert"
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
admin_logger.error(f"Fehler beim Aktualisieren des Benutzers: {str(e)}")
|
||||
return jsonify({"error": "Fehler beim Aktualisieren des Benutzers"}), 500
|
||||
|
||||
@admin_blueprint.route("/api/users/<int:user_id>", methods=["DELETE"])
|
||||
@login_required
|
||||
@admin_required
|
||||
def delete_user_api(user_id):
|
||||
"""API-Endpunkt zum Löschen eines Benutzers"""
|
||||
try:
|
||||
if user_id == current_user.id:
|
||||
return jsonify({"error": "Sie können sich nicht selbst löschen"}), 400
|
||||
|
||||
db_session = get_db_session()
|
||||
user = db_session.query(User).filter(User.id == user_id).first()
|
||||
|
||||
if not user:
|
||||
db_session.close()
|
||||
return jsonify({"error": "Benutzer nicht gefunden"}), 404
|
||||
|
||||
username = user.username
|
||||
db_session.delete(user)
|
||||
db_session.commit()
|
||||
|
||||
admin_logger.info(f"Benutzer {username} gelöscht von Admin {current_user.username}")
|
||||
|
||||
db_session.close()
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"message": "Benutzer erfolgreich gelöscht"
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
admin_logger.error(f"Fehler beim Löschen des Benutzers: {str(e)}")
|
||||
return jsonify({"error": "Fehler beim Löschen des Benutzers"}), 500
|
489
backend/blueprints/deprecated/admin_api.py
Normal file
489
backend/blueprints/deprecated/admin_api.py
Normal file
@@ -0,0 +1,489 @@
|
||||
"""
|
||||
Admin-API Blueprint für erweiterte Verwaltungsfunktionen
|
||||
|
||||
Dieses Blueprint stellt zusätzliche Admin-API-Endpunkte bereit für:
|
||||
- System-Backups
|
||||
- Datenbank-Optimierung
|
||||
- Cache-Verwaltung
|
||||
|
||||
Autor: MYP Team
|
||||
Datum: 2025-06-01
|
||||
"""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import zipfile
|
||||
import sqlite3
|
||||
import glob
|
||||
from datetime import datetime, timedelta
|
||||
from flask import Blueprint, request, jsonify, current_app
|
||||
from flask_login import login_required, current_user
|
||||
from functools import wraps
|
||||
from utils.logging_config import get_logger
|
||||
|
||||
# Blueprint erstellen
|
||||
admin_api_blueprint = Blueprint('admin_api', __name__, url_prefix='/api/admin')
|
||||
|
||||
# Logger initialisieren
|
||||
admin_logger = get_logger("admin_api")
|
||||
|
||||
def admin_required(f):
|
||||
"""Decorator um sicherzustellen, dass nur Admins auf Endpunkte zugreifen können."""
|
||||
@wraps(f)
|
||||
@login_required
|
||||
def decorated_function(*args, **kwargs):
|
||||
if not current_user.is_authenticated or current_user.role != 'admin':
|
||||
admin_logger.warning(f"Unauthorized admin access attempt by user {getattr(current_user, 'id', 'anonymous')}")
|
||||
return jsonify({'error': 'Admin-Berechtigung erforderlich'}), 403
|
||||
return f(*args, **kwargs)
|
||||
return decorated_function
|
||||
|
||||
@admin_api_blueprint.route('/backup/create', methods=['POST'])
|
||||
@admin_required
|
||||
def create_backup():
|
||||
"""
|
||||
Erstellt ein manuelles System-Backup.
|
||||
|
||||
Erstellt eine Sicherung aller wichtigen Systemdaten einschließlich
|
||||
Datenbank, Konfigurationsdateien und Benutzer-Uploads.
|
||||
|
||||
Returns:
|
||||
JSON: Erfolgs-Status und Backup-Informationen
|
||||
"""
|
||||
try:
|
||||
admin_logger.info(f"Backup-Erstellung angefordert von Admin {current_user.username}")
|
||||
|
||||
# Backup-Verzeichnis sicherstellen
|
||||
backup_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'database', 'backups')
|
||||
os.makedirs(backup_dir, exist_ok=True)
|
||||
|
||||
# Eindeutigen Backup-Namen erstellen
|
||||
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
|
||||
backup_name = f"system_backup_{timestamp}.zip"
|
||||
backup_path = os.path.join(backup_dir, backup_name)
|
||||
|
||||
created_files = []
|
||||
backup_size = 0
|
||||
|
||||
with zipfile.ZipFile(backup_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
|
||||
# 1. Datenbank-Datei hinzufügen
|
||||
try:
|
||||
from utils.settings import DATABASE_PATH
|
||||
if os.path.exists(DATABASE_PATH):
|
||||
zipf.write(DATABASE_PATH, 'database/main.db')
|
||||
created_files.append('database/main.db')
|
||||
admin_logger.debug("✅ Hauptdatenbank zur Sicherung hinzugefügt")
|
||||
|
||||
# WAL- und SHM-Dateien falls vorhanden
|
||||
wal_path = DATABASE_PATH + '-wal'
|
||||
shm_path = DATABASE_PATH + '-shm'
|
||||
|
||||
if os.path.exists(wal_path):
|
||||
zipf.write(wal_path, 'database/main.db-wal')
|
||||
created_files.append('database/main.db-wal')
|
||||
|
||||
if os.path.exists(shm_path):
|
||||
zipf.write(shm_path, 'database/main.db-shm')
|
||||
created_files.append('database/main.db-shm')
|
||||
|
||||
except Exception as db_error:
|
||||
admin_logger.warning(f"Fehler beim Hinzufügen der Datenbank: {str(db_error)}")
|
||||
|
||||
# 2. Konfigurationsdateien
|
||||
try:
|
||||
config_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'config')
|
||||
if os.path.exists(config_dir):
|
||||
for root, dirs, files in os.walk(config_dir):
|
||||
for file in files:
|
||||
if file.endswith(('.py', '.json', '.yaml', '.yml', '.toml')):
|
||||
file_path = os.path.join(root, file)
|
||||
arc_path = os.path.relpath(file_path, os.path.dirname(os.path.dirname(__file__)))
|
||||
zipf.write(file_path, arc_path)
|
||||
created_files.append(arc_path)
|
||||
admin_logger.debug("✅ Konfigurationsdateien zur Sicherung hinzugefügt")
|
||||
except Exception as config_error:
|
||||
admin_logger.warning(f"Fehler beim Hinzufügen der Konfiguration: {str(config_error)}")
|
||||
|
||||
# 3. Wichtige User-Uploads (limitiert auf die letzten 1000 Dateien)
|
||||
try:
|
||||
uploads_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'uploads')
|
||||
if os.path.exists(uploads_dir):
|
||||
file_count = 0
|
||||
max_files = 1000 # Limit für Performance
|
||||
|
||||
for root, dirs, files in os.walk(uploads_dir):
|
||||
for file in files[:max_files - file_count]:
|
||||
if file_count >= max_files:
|
||||
break
|
||||
|
||||
file_path = os.path.join(root, file)
|
||||
file_size = os.path.getsize(file_path)
|
||||
|
||||
# Nur Dateien unter 50MB hinzufügen
|
||||
if file_size < 50 * 1024 * 1024:
|
||||
arc_path = os.path.relpath(file_path, os.path.dirname(os.path.dirname(__file__)))
|
||||
zipf.write(file_path, arc_path)
|
||||
created_files.append(arc_path)
|
||||
file_count += 1
|
||||
|
||||
if file_count >= max_files:
|
||||
break
|
||||
|
||||
admin_logger.debug(f"✅ {file_count} Upload-Dateien zur Sicherung hinzugefügt")
|
||||
except Exception as uploads_error:
|
||||
admin_logger.warning(f"Fehler beim Hinzufügen der Uploads: {str(uploads_error)}")
|
||||
|
||||
# 4. System-Logs (nur die letzten 100 Log-Dateien)
|
||||
try:
|
||||
logs_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'logs')
|
||||
if os.path.exists(logs_dir):
|
||||
log_files = []
|
||||
for root, dirs, files in os.walk(logs_dir):
|
||||
for file in files:
|
||||
if file.endswith(('.log', '.txt')):
|
||||
file_path = os.path.join(root, file)
|
||||
log_files.append((file_path, os.path.getmtime(file_path)))
|
||||
|
||||
# Sortiere nach Datum (neueste zuerst) und nimm nur die letzten 100
|
||||
log_files.sort(key=lambda x: x[1], reverse=True)
|
||||
for file_path, _ in log_files[:100]:
|
||||
arc_path = os.path.relpath(file_path, os.path.dirname(os.path.dirname(__file__)))
|
||||
zipf.write(file_path, arc_path)
|
||||
created_files.append(arc_path)
|
||||
|
||||
admin_logger.debug(f"✅ {len(log_files[:100])} Log-Dateien zur Sicherung hinzugefügt")
|
||||
except Exception as logs_error:
|
||||
admin_logger.warning(f"Fehler beim Hinzufügen der Logs: {str(logs_error)}")
|
||||
|
||||
# Backup-Größe bestimmen
|
||||
if os.path.exists(backup_path):
|
||||
backup_size = os.path.getsize(backup_path)
|
||||
|
||||
admin_logger.info(f"✅ System-Backup erfolgreich erstellt: {backup_name} ({backup_size / 1024 / 1024:.2f} MB)")
|
||||
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'message': f'Backup erfolgreich erstellt: {backup_name}',
|
||||
'backup_info': {
|
||||
'filename': backup_name,
|
||||
'size_bytes': backup_size,
|
||||
'size_mb': round(backup_size / 1024 / 1024, 2),
|
||||
'files_count': len(created_files),
|
||||
'created_at': datetime.now().isoformat(),
|
||||
'path': backup_path
|
||||
}
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
admin_logger.error(f"❌ Fehler beim Erstellen des Backups: {str(e)}")
|
||||
return jsonify({
|
||||
'success': False,
|
||||
'message': f'Fehler beim Erstellen des Backups: {str(e)}'
|
||||
}), 500
|
||||
|
||||
@admin_api_blueprint.route('/database/optimize', methods=['POST'])
|
||||
@admin_required
|
||||
def optimize_database():
|
||||
"""
|
||||
Führt Datenbank-Optimierung durch.
|
||||
|
||||
Optimiert die SQLite-Datenbank durch VACUUM, ANALYZE und weitere
|
||||
Wartungsoperationen für bessere Performance.
|
||||
|
||||
Returns:
|
||||
JSON: Erfolgs-Status und Optimierungs-Statistiken
|
||||
"""
|
||||
try:
|
||||
admin_logger.info(f"Datenbank-Optimierung angefordert von Admin {current_user.username}")
|
||||
|
||||
from utils.settings import DATABASE_PATH
|
||||
|
||||
optimization_results = {
|
||||
'vacuum_completed': False,
|
||||
'analyze_completed': False,
|
||||
'integrity_check': False,
|
||||
'wal_checkpoint': False,
|
||||
'size_before': 0,
|
||||
'size_after': 0,
|
||||
'space_saved': 0
|
||||
}
|
||||
|
||||
# Datenbankgröße vor Optimierung
|
||||
if os.path.exists(DATABASE_PATH):
|
||||
optimization_results['size_before'] = os.path.getsize(DATABASE_PATH)
|
||||
|
||||
# Verbindung zur Datenbank herstellen
|
||||
conn = sqlite3.connect(DATABASE_PATH, timeout=30.0)
|
||||
cursor = conn.cursor()
|
||||
|
||||
try:
|
||||
# 1. Integritätsprüfung
|
||||
admin_logger.debug("🔍 Führe Integritätsprüfung durch...")
|
||||
cursor.execute("PRAGMA integrity_check")
|
||||
integrity_result = cursor.fetchone()
|
||||
optimization_results['integrity_check'] = integrity_result[0] == 'ok'
|
||||
|
||||
if not optimization_results['integrity_check']:
|
||||
admin_logger.warning(f"⚠️ Integritätsprüfung ergab: {integrity_result[0]}")
|
||||
else:
|
||||
admin_logger.debug("✅ Integritätsprüfung erfolgreich")
|
||||
|
||||
# 2. WAL-Checkpoint (falls WAL-Modus aktiv)
|
||||
try:
|
||||
admin_logger.debug("🔄 Führe WAL-Checkpoint durch...")
|
||||
cursor.execute("PRAGMA wal_checkpoint(TRUNCATE)")
|
||||
optimization_results['wal_checkpoint'] = True
|
||||
admin_logger.debug("✅ WAL-Checkpoint erfolgreich")
|
||||
except Exception as wal_error:
|
||||
admin_logger.debug(f"ℹ️ WAL-Checkpoint nicht möglich: {str(wal_error)}")
|
||||
|
||||
# 3. ANALYZE - Statistiken aktualisieren
|
||||
admin_logger.debug("📊 Aktualisiere Datenbank-Statistiken...")
|
||||
cursor.execute("ANALYZE")
|
||||
optimization_results['analyze_completed'] = True
|
||||
admin_logger.debug("✅ ANALYZE erfolgreich")
|
||||
|
||||
# 4. VACUUM - Datenbank komprimieren und reorganisieren
|
||||
admin_logger.debug("🗜️ Komprimiere und reorganisiere Datenbank...")
|
||||
cursor.execute("VACUUM")
|
||||
optimization_results['vacuum_completed'] = True
|
||||
admin_logger.debug("✅ VACUUM erfolgreich")
|
||||
|
||||
# 5. Performance-Optimierungen
|
||||
try:
|
||||
# Cache-Größe optimieren
|
||||
cursor.execute("PRAGMA cache_size = 10000") # 10MB Cache
|
||||
|
||||
# Journal-Modus auf WAL setzen für bessere Concurrent-Performance
|
||||
cursor.execute("PRAGMA journal_mode = WAL")
|
||||
|
||||
# Synchronous auf NORMAL für Balance zwischen Performance und Sicherheit
|
||||
cursor.execute("PRAGMA synchronous = NORMAL")
|
||||
|
||||
# Page-Größe optimieren (falls noch nicht gesetzt)
|
||||
cursor.execute("PRAGMA page_size = 4096")
|
||||
|
||||
admin_logger.debug("✅ Performance-Optimierungen angewendet")
|
||||
except Exception as perf_error:
|
||||
admin_logger.warning(f"⚠️ Performance-Optimierungen teilweise fehlgeschlagen: {str(perf_error)}")
|
||||
|
||||
finally:
|
||||
cursor.close()
|
||||
conn.close()
|
||||
|
||||
# Datenbankgröße nach Optimierung
|
||||
if os.path.exists(DATABASE_PATH):
|
||||
optimization_results['size_after'] = os.path.getsize(DATABASE_PATH)
|
||||
optimization_results['space_saved'] = optimization_results['size_before'] - optimization_results['size_after']
|
||||
|
||||
# Ergebnisse loggen
|
||||
space_saved_mb = optimization_results['space_saved'] / 1024 / 1024
|
||||
admin_logger.info(f"✅ Datenbank-Optimierung abgeschlossen - {space_saved_mb:.2f} MB Speicher gespart")
|
||||
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'message': 'Datenbank erfolgreich optimiert',
|
||||
'results': {
|
||||
'vacuum_completed': optimization_results['vacuum_completed'],
|
||||
'analyze_completed': optimization_results['analyze_completed'],
|
||||
'integrity_check_passed': optimization_results['integrity_check'],
|
||||
'wal_checkpoint_completed': optimization_results['wal_checkpoint'],
|
||||
'size_before_mb': round(optimization_results['size_before'] / 1024 / 1024, 2),
|
||||
'size_after_mb': round(optimization_results['size_after'] / 1024 / 1024, 2),
|
||||
'space_saved_mb': round(space_saved_mb, 2),
|
||||
'optimization_timestamp': datetime.now().isoformat()
|
||||
}
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
admin_logger.error(f"❌ Fehler bei Datenbank-Optimierung: {str(e)}")
|
||||
return jsonify({
|
||||
'success': False,
|
||||
'message': f'Fehler bei Datenbank-Optimierung: {str(e)}'
|
||||
}), 500
|
||||
|
||||
@admin_api_blueprint.route('/cache/clear', methods=['POST'])
|
||||
@admin_required
|
||||
def clear_cache():
|
||||
"""
|
||||
Leert den System-Cache.
|
||||
|
||||
Entfernt alle temporären Dateien, Cache-Verzeichnisse und
|
||||
Python-Bytecode um Speicher freizugeben und Performance zu verbessern.
|
||||
|
||||
Returns:
|
||||
JSON: Erfolgs-Status und Lösch-Statistiken
|
||||
"""
|
||||
try:
|
||||
admin_logger.info(f"Cache-Leerung angefordert von Admin {current_user.username}")
|
||||
|
||||
cleared_stats = {
|
||||
'files_deleted': 0,
|
||||
'dirs_deleted': 0,
|
||||
'space_freed': 0,
|
||||
'categories': {}
|
||||
}
|
||||
|
||||
app_root = os.path.dirname(os.path.dirname(__file__))
|
||||
|
||||
# 1. Python-Bytecode-Cache leeren (__pycache__)
|
||||
try:
|
||||
pycache_count = 0
|
||||
pycache_size = 0
|
||||
|
||||
for root, dirs, files in os.walk(app_root):
|
||||
if '__pycache__' in root:
|
||||
for file in files:
|
||||
file_path = os.path.join(root, file)
|
||||
try:
|
||||
pycache_size += os.path.getsize(file_path)
|
||||
os.remove(file_path)
|
||||
pycache_count += 1
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Versuche das __pycache__-Verzeichnis zu löschen
|
||||
try:
|
||||
os.rmdir(root)
|
||||
cleared_stats['dirs_deleted'] += 1
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
cleared_stats['categories']['python_bytecode'] = {
|
||||
'files': pycache_count,
|
||||
'size_mb': round(pycache_size / 1024 / 1024, 2)
|
||||
}
|
||||
cleared_stats['files_deleted'] += pycache_count
|
||||
cleared_stats['space_freed'] += pycache_size
|
||||
|
||||
admin_logger.debug(f"✅ Python-Bytecode-Cache: {pycache_count} Dateien, {pycache_size / 1024 / 1024:.2f} MB")
|
||||
|
||||
except Exception as pycache_error:
|
||||
admin_logger.warning(f"⚠️ Fehler beim Leeren des Python-Cache: {str(pycache_error)}")
|
||||
|
||||
# 2. Temporäre Dateien im uploads/temp Verzeichnis
|
||||
try:
|
||||
temp_count = 0
|
||||
temp_size = 0
|
||||
temp_dir = os.path.join(app_root, 'uploads', 'temp')
|
||||
|
||||
if os.path.exists(temp_dir):
|
||||
for root, dirs, files in os.walk(temp_dir):
|
||||
for file in files:
|
||||
file_path = os.path.join(root, file)
|
||||
try:
|
||||
temp_size += os.path.getsize(file_path)
|
||||
os.remove(file_path)
|
||||
temp_count += 1
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
cleared_stats['categories']['temp_uploads'] = {
|
||||
'files': temp_count,
|
||||
'size_mb': round(temp_size / 1024 / 1024, 2)
|
||||
}
|
||||
cleared_stats['files_deleted'] += temp_count
|
||||
cleared_stats['space_freed'] += temp_size
|
||||
|
||||
admin_logger.debug(f"✅ Temporäre Upload-Dateien: {temp_count} Dateien, {temp_size / 1024 / 1024:.2f} MB")
|
||||
|
||||
except Exception as temp_error:
|
||||
admin_logger.warning(f"⚠️ Fehler beim Leeren des Temp-Verzeichnisses: {str(temp_error)}")
|
||||
|
||||
# 3. System-Cache-Verzeichnisse (falls vorhanden)
|
||||
try:
|
||||
cache_count = 0
|
||||
cache_size = 0
|
||||
|
||||
cache_dirs = [
|
||||
os.path.join(app_root, 'static', 'cache'),
|
||||
os.path.join(app_root, 'cache'),
|
||||
os.path.join(app_root, '.cache')
|
||||
]
|
||||
|
||||
for cache_dir in cache_dirs:
|
||||
if os.path.exists(cache_dir):
|
||||
for root, dirs, files in os.walk(cache_dir):
|
||||
for file in files:
|
||||
file_path = os.path.join(root, file)
|
||||
try:
|
||||
cache_size += os.path.getsize(file_path)
|
||||
os.remove(file_path)
|
||||
cache_count += 1
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
cleared_stats['categories']['system_cache'] = {
|
||||
'files': cache_count,
|
||||
'size_mb': round(cache_size / 1024 / 1024, 2)
|
||||
}
|
||||
cleared_stats['files_deleted'] += cache_count
|
||||
cleared_stats['space_freed'] += cache_size
|
||||
|
||||
admin_logger.debug(f"✅ System-Cache: {cache_count} Dateien, {cache_size / 1024 / 1024:.2f} MB")
|
||||
|
||||
except Exception as cache_error:
|
||||
admin_logger.warning(f"⚠️ Fehler beim Leeren des System-Cache: {str(cache_error)}")
|
||||
|
||||
# 4. Alte Log-Dateien (älter als 30 Tage)
|
||||
try:
|
||||
logs_count = 0
|
||||
logs_size = 0
|
||||
logs_dir = os.path.join(app_root, 'logs')
|
||||
cutoff_date = datetime.now().timestamp() - (30 * 24 * 60 * 60) # 30 Tage
|
||||
|
||||
if os.path.exists(logs_dir):
|
||||
for root, dirs, files in os.walk(logs_dir):
|
||||
for file in files:
|
||||
if file.endswith(('.log', '.log.1', '.log.2', '.log.3')):
|
||||
file_path = os.path.join(root, file)
|
||||
try:
|
||||
if os.path.getmtime(file_path) < cutoff_date:
|
||||
logs_size += os.path.getsize(file_path)
|
||||
os.remove(file_path)
|
||||
logs_count += 1
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
cleared_stats['categories']['old_logs'] = {
|
||||
'files': logs_count,
|
||||
'size_mb': round(logs_size / 1024 / 1024, 2)
|
||||
}
|
||||
cleared_stats['files_deleted'] += logs_count
|
||||
cleared_stats['space_freed'] += logs_size
|
||||
|
||||
admin_logger.debug(f"✅ Alte Log-Dateien: {logs_count} Dateien, {logs_size / 1024 / 1024:.2f} MB")
|
||||
|
||||
except Exception as logs_error:
|
||||
admin_logger.warning(f"⚠️ Fehler beim Leeren alter Log-Dateien: {str(logs_error)}")
|
||||
|
||||
# 5. Application-Level Cache leeren (falls Models-Cache existiert)
|
||||
try:
|
||||
from models import clear_model_cache
|
||||
clear_model_cache()
|
||||
admin_logger.debug("✅ Application-Level Cache geleert")
|
||||
except (ImportError, AttributeError):
|
||||
admin_logger.debug("ℹ️ Kein Application-Level Cache verfügbar")
|
||||
|
||||
# Ergebnisse zusammenfassen
|
||||
total_space_mb = cleared_stats['space_freed'] / 1024 / 1024
|
||||
admin_logger.info(f"✅ Cache-Leerung abgeschlossen: {cleared_stats['files_deleted']} Dateien, {total_space_mb:.2f} MB freigegeben")
|
||||
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'message': f'Cache erfolgreich geleert - {total_space_mb:.2f} MB freigegeben',
|
||||
'statistics': {
|
||||
'total_files_deleted': cleared_stats['files_deleted'],
|
||||
'total_dirs_deleted': cleared_stats['dirs_deleted'],
|
||||
'total_space_freed_mb': round(total_space_mb, 2),
|
||||
'categories': cleared_stats['categories'],
|
||||
'cleanup_timestamp': datetime.now().isoformat()
|
||||
}
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
admin_logger.error(f"❌ Fehler beim Leeren des Cache: {str(e)}")
|
||||
return jsonify({
|
||||
'success': False,
|
||||
'message': f'Fehler beim Leeren des Cache: {str(e)}'
|
||||
}), 500
|
359
backend/blueprints/deprecated/user.py
Normal file
359
backend/blueprints/deprecated/user.py
Normal file
@@ -0,0 +1,359 @@
|
||||
"""
|
||||
Benutzer-Blueprint für das 3D-Druck-Management-System
|
||||
|
||||
Dieses Modul enthält alle Benutzer-spezifischen Routen und Funktionen,
|
||||
einschließlich Profilverwaltung, Einstellungen und Passwort-Änderung.
|
||||
"""
|
||||
|
||||
import json
|
||||
from datetime import datetime
|
||||
from flask import Blueprint, render_template, request, jsonify, redirect, url_for, flash, make_response
|
||||
from flask_login import login_required, current_user
|
||||
from werkzeug.security import check_password_hash
|
||||
from models import User, get_db_session
|
||||
from utils.logging_config import get_logger
|
||||
|
||||
# Blueprint erstellen
|
||||
user_blueprint = Blueprint('user', __name__, url_prefix='/user')
|
||||
|
||||
# Logger initialisieren
|
||||
user_logger = get_logger("user")
|
||||
|
||||
@user_blueprint.route("/profile", methods=["GET"])
|
||||
@login_required
|
||||
def profile():
|
||||
"""Benutzerprofil anzeigen"""
|
||||
return render_template('user/profile.html', user=current_user)
|
||||
|
||||
@user_blueprint.route("/settings", methods=["GET"])
|
||||
@login_required
|
||||
def settings():
|
||||
"""Benutzereinstellungen anzeigen"""
|
||||
return render_template('user/settings.html', user=current_user)
|
||||
|
||||
@user_blueprint.route("/update-profile", methods=["POST"])
|
||||
@login_required
|
||||
def update_profile():
|
||||
"""Benutzerprofil aktualisieren (Form-basiert)"""
|
||||
try:
|
||||
db_session = get_db_session()
|
||||
user = db_session.query(User).filter(User.id == current_user.id).first()
|
||||
|
||||
if not user:
|
||||
db_session.close()
|
||||
flash("Benutzer nicht gefunden", "error")
|
||||
return redirect(url_for('user.profile'))
|
||||
|
||||
# Aktualisierbare Felder aus dem Formular
|
||||
user.name = request.form.get('name', user.name)
|
||||
user.email = request.form.get('email', user.email)
|
||||
user.department = request.form.get('department', user.department)
|
||||
user.position = request.form.get('position', user.position)
|
||||
user.phone = request.form.get('phone', user.phone)
|
||||
user.bio = request.form.get('bio', user.bio)
|
||||
|
||||
user.updated_at = datetime.now()
|
||||
db_session.commit()
|
||||
|
||||
user_logger.info(f"Profil aktualisiert für Benutzer {user.username}")
|
||||
flash("Profil erfolgreich aktualisiert", "success")
|
||||
|
||||
db_session.close()
|
||||
return redirect(url_for('user.profile'))
|
||||
|
||||
except Exception as e:
|
||||
user_logger.error(f"Fehler beim Aktualisieren des Profils: {str(e)}")
|
||||
flash("Fehler beim Aktualisieren des Profils", "error")
|
||||
return redirect(url_for('user.profile'))
|
||||
|
||||
@user_blueprint.route("/api/update-settings", methods=["POST"])
|
||||
@login_required
|
||||
def api_update_settings():
|
||||
"""API-Endpunkt für Einstellungen-Updates"""
|
||||
try:
|
||||
data = request.get_json()
|
||||
|
||||
db_session = get_db_session()
|
||||
user = db_session.query(User).filter(User.id == current_user.id).first()
|
||||
|
||||
if not user:
|
||||
db_session.close()
|
||||
return jsonify({"error": "Benutzer nicht gefunden"}), 404
|
||||
|
||||
# Einstellungen JSON aktualisieren
|
||||
current_settings = user.settings or {}
|
||||
if isinstance(current_settings, str):
|
||||
try:
|
||||
current_settings = json.loads(current_settings)
|
||||
except json.JSONDecodeError:
|
||||
current_settings = {}
|
||||
|
||||
# Neue Einstellungen hinzufügen/aktualisieren
|
||||
for key, value in data.items():
|
||||
current_settings[key] = value
|
||||
|
||||
user.settings = json.dumps(current_settings)
|
||||
user.updated_at = datetime.now()
|
||||
db_session.commit()
|
||||
|
||||
user_logger.info(f"Einstellungen aktualisiert für Benutzer {user.username}")
|
||||
|
||||
db_session.close()
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"message": "Einstellungen erfolgreich aktualisiert"
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
user_logger.error(f"Fehler beim Aktualisieren der Einstellungen: {str(e)}")
|
||||
return jsonify({"error": "Fehler beim Aktualisieren der Einstellungen"}), 500
|
||||
|
||||
@user_blueprint.route("/update-settings", methods=["POST"])
|
||||
@login_required
|
||||
def update_settings():
|
||||
"""Benutzereinstellungen aktualisieren (Form-basiert)"""
|
||||
try:
|
||||
db_session = get_db_session()
|
||||
user = db_session.query(User).filter(User.id == current_user.id).first()
|
||||
|
||||
if not user:
|
||||
db_session.close()
|
||||
flash("Benutzer nicht gefunden", "error")
|
||||
return redirect(url_for('user.settings'))
|
||||
|
||||
# Einstellungen aus dem Formular sammeln
|
||||
settings = {}
|
||||
|
||||
# Theme-Einstellungen
|
||||
settings['theme'] = request.form.get('theme', 'light')
|
||||
settings['language'] = request.form.get('language', 'de')
|
||||
|
||||
# Benachrichtigungseinstellungen
|
||||
settings['email_notifications'] = request.form.get('email_notifications') == 'on'
|
||||
settings['push_notifications'] = request.form.get('push_notifications') == 'on'
|
||||
settings['job_completion_notifications'] = request.form.get('job_completion_notifications') == 'on'
|
||||
settings['printer_error_notifications'] = request.form.get('printer_error_notifications') == 'on'
|
||||
|
||||
# Dashboard-Einstellungen
|
||||
settings['default_dashboard_view'] = request.form.get('default_dashboard_view', 'overview')
|
||||
settings['auto_refresh_interval'] = int(request.form.get('auto_refresh_interval', 30))
|
||||
|
||||
# Privacy-Einstellungen
|
||||
settings['show_profile_publicly'] = request.form.get('show_profile_publicly') == 'on'
|
||||
settings['allow_job_sharing'] = request.form.get('allow_job_sharing') == 'on'
|
||||
|
||||
user.settings = json.dumps(settings)
|
||||
user.updated_at = datetime.now()
|
||||
db_session.commit()
|
||||
|
||||
user_logger.info(f"Einstellungen aktualisiert für Benutzer {user.username}")
|
||||
flash("Einstellungen erfolgreich aktualisiert", "success")
|
||||
|
||||
db_session.close()
|
||||
return redirect(url_for('user.settings'))
|
||||
|
||||
except Exception as e:
|
||||
user_logger.error(f"Fehler beim Aktualisieren der Einstellungen: {str(e)}")
|
||||
flash("Fehler beim Aktualisieren der Einstellungen", "error")
|
||||
return redirect(url_for('user.settings'))
|
||||
|
||||
@user_blueprint.route("/change-password", methods=["POST"])
|
||||
@login_required
|
||||
def change_password():
|
||||
"""Passwort ändern"""
|
||||
try:
|
||||
# Daten aus Form oder JSON extrahieren
|
||||
if request.is_json:
|
||||
data = request.get_json()
|
||||
current_password = data.get('current_password')
|
||||
new_password = data.get('new_password')
|
||||
confirm_password = data.get('confirm_password')
|
||||
else:
|
||||
current_password = request.form.get('current_password')
|
||||
new_password = request.form.get('new_password')
|
||||
confirm_password = request.form.get('confirm_password')
|
||||
|
||||
# Validierung
|
||||
if not all([current_password, new_password, confirm_password]):
|
||||
error_msg = "Alle Passwort-Felder sind erforderlich"
|
||||
if request.is_json:
|
||||
return jsonify({"error": error_msg}), 400
|
||||
flash(error_msg, "error")
|
||||
return redirect(url_for('user.settings'))
|
||||
|
||||
if new_password != confirm_password:
|
||||
error_msg = "Neue Passwörter stimmen nicht überein"
|
||||
if request.is_json:
|
||||
return jsonify({"error": error_msg}), 400
|
||||
flash(error_msg, "error")
|
||||
return redirect(url_for('user.settings'))
|
||||
|
||||
if len(new_password) < 8:
|
||||
error_msg = "Das neue Passwort muss mindestens 8 Zeichen lang sein"
|
||||
if request.is_json:
|
||||
return jsonify({"error": error_msg}), 400
|
||||
flash(error_msg, "error")
|
||||
return redirect(url_for('user.settings'))
|
||||
|
||||
db_session = get_db_session()
|
||||
user = db_session.query(User).filter(User.id == current_user.id).first()
|
||||
|
||||
if not user:
|
||||
db_session.close()
|
||||
error_msg = "Benutzer nicht gefunden"
|
||||
if request.is_json:
|
||||
return jsonify({"error": error_msg}), 404
|
||||
flash(error_msg, "error")
|
||||
return redirect(url_for('user.settings'))
|
||||
|
||||
# Aktuelles Passwort überprüfen
|
||||
if not user.check_password(current_password):
|
||||
db_session.close()
|
||||
error_msg = "Aktuelles Passwort ist falsch"
|
||||
if request.is_json:
|
||||
return jsonify({"error": error_msg}), 401
|
||||
flash(error_msg, "error")
|
||||
return redirect(url_for('user.settings'))
|
||||
|
||||
# Neues Passwort setzen
|
||||
user.set_password(new_password)
|
||||
user.updated_at = datetime.now()
|
||||
db_session.commit()
|
||||
|
||||
user_logger.info(f"Passwort geändert für Benutzer {user.username}")
|
||||
|
||||
db_session.close()
|
||||
|
||||
success_msg = "Passwort erfolgreich geändert"
|
||||
if request.is_json:
|
||||
return jsonify({"success": True, "message": success_msg})
|
||||
flash(success_msg, "success")
|
||||
return redirect(url_for('user.settings'))
|
||||
|
||||
except Exception as e:
|
||||
user_logger.error(f"Fehler beim Ändern des Passworts: {str(e)}")
|
||||
error_msg = "Fehler beim Ändern des Passworts"
|
||||
if request.is_json:
|
||||
return jsonify({"error": error_msg}), 500
|
||||
flash(error_msg, "error")
|
||||
return redirect(url_for('user.settings'))
|
||||
|
||||
@user_blueprint.route("/export", methods=["GET"])
|
||||
@login_required
|
||||
def export_data():
|
||||
"""Benutzerdaten exportieren (DSGVO-Compliance)"""
|
||||
try:
|
||||
db_session = get_db_session()
|
||||
user = db_session.query(User).filter(User.id == current_user.id).first()
|
||||
|
||||
if not user:
|
||||
db_session.close()
|
||||
flash("Benutzer nicht gefunden", "error")
|
||||
return redirect(url_for('user.settings'))
|
||||
|
||||
# Benutzerdaten sammeln
|
||||
user_data = {
|
||||
"personal_information": {
|
||||
"id": user.id,
|
||||
"username": user.username,
|
||||
"email": user.email,
|
||||
"name": user.name,
|
||||
"department": user.department,
|
||||
"position": user.position,
|
||||
"phone": user.phone,
|
||||
"bio": user.bio,
|
||||
"role": user.role,
|
||||
"created_at": user.created_at.isoformat() if user.created_at else None,
|
||||
"last_login": user.last_login.isoformat() if user.last_login else None,
|
||||
"updated_at": user.updated_at.isoformat() if user.updated_at else None,
|
||||
"last_activity": user.last_activity.isoformat() if user.last_activity else None
|
||||
},
|
||||
"settings": json.loads(user.settings) if user.settings else {},
|
||||
"jobs": [],
|
||||
"export_date": datetime.now().isoformat(),
|
||||
"export_note": "Dies ist ein Export Ihrer persönlichen Daten gemäß DSGVO Art. 20"
|
||||
}
|
||||
|
||||
# Benutzer-Jobs sammeln (falls verfügbar)
|
||||
try:
|
||||
from models import Job
|
||||
user_jobs = db_session.query(Job).filter(Job.user_id == user.id).all()
|
||||
for job in user_jobs:
|
||||
user_data["jobs"].append({
|
||||
"id": job.id,
|
||||
"filename": job.filename,
|
||||
"status": job.status,
|
||||
"created_at": job.created_at.isoformat() if job.created_at else None,
|
||||
"estimated_duration": job.estimated_duration,
|
||||
"material_used": job.material_used,
|
||||
"notes": job.notes
|
||||
})
|
||||
except Exception as job_error:
|
||||
user_logger.warning(f"Fehler beim Sammeln der Job-Daten: {str(job_error)}")
|
||||
|
||||
db_session.close()
|
||||
|
||||
# JSON-Response erstellen
|
||||
response = make_response(jsonify(user_data))
|
||||
response.headers['Content-Disposition'] = f'attachment; filename=user_data_{user.username}_{datetime.now().strftime("%Y%m%d_%H%M%S")}.json'
|
||||
response.headers['Content-Type'] = 'application/json'
|
||||
|
||||
user_logger.info(f"Datenexport erstellt für Benutzer {user.username}")
|
||||
|
||||
return response
|
||||
|
||||
except Exception as e:
|
||||
user_logger.error(f"Fehler beim Datenexport: {str(e)}")
|
||||
flash("Fehler beim Erstellen des Datenexports", "error")
|
||||
return redirect(url_for('user.settings'))
|
||||
|
||||
@user_blueprint.route("/profile", methods=["PUT"])
|
||||
@login_required
|
||||
def update_profile_api():
|
||||
"""API-Endpunkt für Profil-Updates"""
|
||||
try:
|
||||
data = request.get_json()
|
||||
|
||||
db_session = get_db_session()
|
||||
user = db_session.query(User).filter(User.id == current_user.id).first()
|
||||
|
||||
if not user:
|
||||
db_session.close()
|
||||
return jsonify({"error": "Benutzer nicht gefunden"}), 404
|
||||
|
||||
# Aktualisierbare Felder (ohne sensitive Daten)
|
||||
updatable_fields = ['name', 'email', 'department', 'position', 'phone', 'bio']
|
||||
|
||||
for field in updatable_fields:
|
||||
if field in data:
|
||||
setattr(user, field, data[field])
|
||||
|
||||
user.updated_at = datetime.now()
|
||||
db_session.commit()
|
||||
|
||||
user_logger.info(f"Profil über API aktualisiert für Benutzer {user.username}")
|
||||
|
||||
# Aktuelle Benutzerdaten zurückgeben
|
||||
user_data = {
|
||||
"id": user.id,
|
||||
"username": user.username,
|
||||
"email": user.email,
|
||||
"name": user.name,
|
||||
"department": user.department,
|
||||
"position": user.position,
|
||||
"phone": user.phone,
|
||||
"bio": user.bio,
|
||||
"role": user.role,
|
||||
"updated_at": user.updated_at.isoformat()
|
||||
}
|
||||
|
||||
db_session.close()
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"message": "Profil erfolgreich aktualisiert",
|
||||
"user": user_data
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
user_logger.error(f"Fehler beim API-Profil-Update: {str(e)}")
|
||||
return jsonify({"error": "Fehler beim Aktualisieren des Profils"}), 500
|
168
backend/blueprints/deprecated/users.py
Normal file
168
backend/blueprints/deprecated/users.py
Normal file
@@ -0,0 +1,168 @@
|
||||
from flask import Blueprint, render_template, request, jsonify, redirect, url_for, abort
|
||||
from flask_login import current_user, login_required
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
from functools import wraps
|
||||
|
||||
from models import User, UserPermission, get_cached_session
|
||||
from utils.logging_config import get_logger
|
||||
|
||||
users_blueprint = Blueprint('users', __name__)
|
||||
logger = get_logger("users")
|
||||
|
||||
def users_admin_required(f):
|
||||
"""Decorator zur Prüfung der Admin-Berechtigung für Users Blueprint."""
|
||||
@wraps(f)
|
||||
@login_required
|
||||
def users_decorated_function(*args, **kwargs):
|
||||
if not current_user.is_admin:
|
||||
abort(403, "Nur Administratoren haben Zugriff auf diese Seite")
|
||||
return f(*args, **kwargs)
|
||||
return users_decorated_function
|
||||
|
||||
@users_blueprint.route('/admin/users/<int:user_id>/permissions', methods=['GET'])
|
||||
@users_admin_required
|
||||
def admin_user_permissions(user_id):
|
||||
"""Benutzerberechtigungen anzeigen und bearbeiten."""
|
||||
with get_cached_session() as db_session:
|
||||
user = db_session.query(User).filter_by(id=user_id).first()
|
||||
if not user:
|
||||
abort(404, "Benutzer nicht gefunden")
|
||||
|
||||
# Berechtigungen laden oder erstellen, falls nicht vorhanden
|
||||
permission = db_session.query(UserPermission).filter_by(user_id=user_id).first()
|
||||
if not permission:
|
||||
permission = UserPermission(user_id=user_id)
|
||||
db_session.add(permission)
|
||||
db_session.commit()
|
||||
|
||||
return render_template('admin_user_permissions.html', user=user, permission=permission)
|
||||
|
||||
@users_blueprint.route('/api/users/<int:user_id>/permissions', methods=['GET'])
|
||||
@login_required
|
||||
def api_get_user_permissions(user_id):
|
||||
"""Benutzerberechtigungen als JSON zurückgeben."""
|
||||
# Nur Admins oder der Benutzer selbst darf seine Berechtigungen sehen
|
||||
if not current_user.is_admin and current_user.id != user_id:
|
||||
return jsonify({"error": "Keine Berechtigung"}), 403
|
||||
|
||||
try:
|
||||
with get_cached_session() as db_session:
|
||||
permission = db_session.query(UserPermission).filter_by(user_id=user_id).first()
|
||||
|
||||
if not permission:
|
||||
# Falls keine Berechtigungen existieren, Standard-Werte zurückgeben
|
||||
return jsonify({
|
||||
"user_id": user_id,
|
||||
"can_start_jobs": False,
|
||||
"needs_approval": True,
|
||||
"can_approve_jobs": False
|
||||
})
|
||||
|
||||
return jsonify(permission.to_dict())
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Fehler beim Abrufen der Benutzerberechtigungen: {str(e)}")
|
||||
return jsonify({"error": "Fehler beim Verarbeiten der Anfrage"}), 500
|
||||
|
||||
@users_blueprint.route('/api/users/<int:user_id>/permissions', methods=['PUT'])
|
||||
@users_admin_required
|
||||
def api_update_user_permissions(user_id):
|
||||
"""Benutzerberechtigungen aktualisieren."""
|
||||
try:
|
||||
data = request.get_json()
|
||||
if not data:
|
||||
return jsonify({"error": "Keine Daten erhalten"}), 400
|
||||
|
||||
with get_cached_session() as db_session:
|
||||
# Benutzer prüfen
|
||||
user = db_session.query(User).filter_by(id=user_id).first()
|
||||
if not user:
|
||||
return jsonify({"error": "Benutzer nicht gefunden"}), 404
|
||||
|
||||
# Berechtigungen laden oder erstellen
|
||||
permission = db_session.query(UserPermission).filter_by(user_id=user_id).first()
|
||||
if not permission:
|
||||
permission = UserPermission(user_id=user_id)
|
||||
db_session.add(permission)
|
||||
|
||||
# Berechtigungen aktualisieren
|
||||
if 'can_start_jobs' in data:
|
||||
permission.can_start_jobs = bool(data['can_start_jobs'])
|
||||
|
||||
if 'needs_approval' in data:
|
||||
permission.needs_approval = bool(data['needs_approval'])
|
||||
|
||||
if 'can_approve_jobs' in data:
|
||||
permission.can_approve_jobs = bool(data['can_approve_jobs'])
|
||||
|
||||
db_session.commit()
|
||||
|
||||
logger.info(f"Berechtigungen für Benutzer {user_id} aktualisiert durch Admin {current_user.id}")
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"permissions": permission.to_dict()
|
||||
})
|
||||
|
||||
except SQLAlchemyError as e:
|
||||
logger.error(f"Datenbankfehler beim Aktualisieren der Benutzerberechtigungen: {str(e)}")
|
||||
return jsonify({"error": "Datenbankfehler beim Verarbeiten der Anfrage"}), 500
|
||||
except Exception as e:
|
||||
logger.error(f"Fehler beim Aktualisieren der Benutzerberechtigungen: {str(e)}")
|
||||
return jsonify({"error": "Fehler beim Verarbeiten der Anfrage"}), 500
|
||||
|
||||
@users_blueprint.route('/admin/users/<int:user_id>/permissions/update', methods=['POST'])
|
||||
@users_admin_required
|
||||
def admin_update_user_permissions(user_id):
|
||||
"""Benutzerberechtigungen über Formular aktualisieren."""
|
||||
try:
|
||||
# Formularfelder auslesen
|
||||
can_start_jobs = request.form.get('can_start_jobs') == 'on'
|
||||
needs_approval = request.form.get('needs_approval') == 'on'
|
||||
can_approve_jobs = request.form.get('can_approve_jobs') == 'on'
|
||||
|
||||
with get_cached_session() as db_session:
|
||||
# Benutzer prüfen
|
||||
user = db_session.query(User).filter_by(id=user_id).first()
|
||||
if not user:
|
||||
abort(404, "Benutzer nicht gefunden")
|
||||
|
||||
# Berechtigungen laden oder erstellen
|
||||
permission = db_session.query(UserPermission).filter_by(user_id=user_id).first()
|
||||
if not permission:
|
||||
permission = UserPermission(user_id=user_id)
|
||||
db_session.add(permission)
|
||||
|
||||
# Berechtigungen aktualisieren
|
||||
permission.can_start_jobs = can_start_jobs
|
||||
permission.needs_approval = needs_approval
|
||||
permission.can_approve_jobs = can_approve_jobs
|
||||
|
||||
db_session.commit()
|
||||
|
||||
logger.info(f"Berechtigungen für Benutzer {user_id} aktualisiert durch Admin {current_user.id} (Formular)")
|
||||
|
||||
return redirect(url_for('users.admin_user_permissions', user_id=user_id))
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Fehler beim Aktualisieren der Benutzerberechtigungen: {str(e)}")
|
||||
abort(500, "Fehler beim Verarbeiten der Anfrage")
|
||||
|
||||
# Erweiterung des bestehenden Benutzer-Bearbeitungsformulars
|
||||
@users_blueprint.route('/admin/users/<int:user_id>/edit/permissions', methods=['GET'])
|
||||
@users_admin_required
|
||||
def admin_edit_user_permissions_section(user_id):
|
||||
"""Rendert nur den Berechtigungsteil für das Benutzer-Edit-Formular."""
|
||||
with get_cached_session() as db_session:
|
||||
user = db_session.query(User).filter_by(id=user_id).first()
|
||||
if not user:
|
||||
abort(404, "Benutzer nicht gefunden")
|
||||
|
||||
# Berechtigungen laden oder erstellen, falls nicht vorhanden
|
||||
permission = db_session.query(UserPermission).filter_by(user_id=user_id).first()
|
||||
if not permission:
|
||||
permission = UserPermission(user_id=user_id)
|
||||
db_session.add(permission)
|
||||
db_session.commit()
|
||||
|
||||
return render_template('_user_permissions_form.html', user=user, permission=permission)
|
Reference in New Issue
Block a user