"feat: Added debug server and related components for improved development experience"
This commit is contained in:
346
backend/frontend_v2_routes.py
Normal file
346
backend/frontend_v2_routes.py
Normal file
@@ -0,0 +1,346 @@
|
||||
"""
|
||||
Routing-Modul für die neue Frontend V2-Implementierung.
|
||||
Stellt die notwendigen Endpunkte bereit, während die Original-API-Endpunkte intakt bleiben.
|
||||
"""
|
||||
|
||||
from flask import Blueprint, render_template, redirect, url_for, request, flash, jsonify, g, session
|
||||
import datetime
|
||||
import os
|
||||
from functools import wraps
|
||||
import logging
|
||||
import jwt
|
||||
|
||||
# Blueprint für Frontend V2 erstellen
|
||||
frontend_v2 = Blueprint('frontend_v2', __name__, template_folder='frontend_v2/templates')
|
||||
|
||||
# Logger konfigurieren
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Importiere Funktionen aus dem Hauptmodul
|
||||
# Diese werden während der Registrierung des Blueprints übergeben,
|
||||
# um zirkuläre Importe zu vermeiden
|
||||
get_current_user = None
|
||||
get_user_by_id = None
|
||||
get_socket_by_id = None
|
||||
get_job_by_id = None
|
||||
get_all_sockets = None
|
||||
get_all_users = None
|
||||
get_all_jobs = None
|
||||
get_jobs_by_user = None
|
||||
login_required = None
|
||||
admin_required = None
|
||||
delete_session = None
|
||||
socket_to_dict = None
|
||||
job_to_dict = None
|
||||
user_to_dict = None
|
||||
|
||||
def set_app_functions(app_functions):
|
||||
"""
|
||||
Setzt die importierten Funktionen aus dem Hauptmodul.
|
||||
|
||||
Args:
|
||||
app_functions: Ein Dictionary mit Funktionen aus dem Hauptmodul
|
||||
"""
|
||||
global get_current_user, get_user_by_id, get_socket_by_id, get_job_by_id
|
||||
global get_all_sockets, get_all_users, get_all_jobs, get_jobs_by_user
|
||||
global login_required, admin_required, delete_session
|
||||
global socket_to_dict, job_to_dict, user_to_dict
|
||||
|
||||
get_current_user = app_functions.get('get_current_user')
|
||||
get_user_by_id = app_functions.get('get_user_by_id')
|
||||
get_socket_by_id = app_functions.get('get_socket_by_id')
|
||||
get_job_by_id = app_functions.get('get_job_by_id')
|
||||
get_all_sockets = app_functions.get('get_all_sockets')
|
||||
get_all_users = app_functions.get('get_all_users')
|
||||
get_all_jobs = app_functions.get('get_all_jobs')
|
||||
get_jobs_by_user = app_functions.get('get_jobs_by_user')
|
||||
login_required = app_functions.get('login_required')
|
||||
admin_required = app_functions.get('admin_required')
|
||||
delete_session = app_functions.get('delete_session')
|
||||
socket_to_dict = app_functions.get('socket_to_dict')
|
||||
job_to_dict = app_functions.get('job_to_dict')
|
||||
user_to_dict = app_functions.get('user_to_dict')
|
||||
|
||||
# Wrapper für Login-Erfordernis im Frontend
|
||||
def frontend_login_required(f):
|
||||
@wraps(f)
|
||||
def decorated(*args, **kwargs):
|
||||
user = get_current_user()
|
||||
if not user:
|
||||
flash('Bitte melden Sie sich an, um diese Seite zu besuchen.', 'error')
|
||||
return redirect(url_for('frontend_v2.login'))
|
||||
|
||||
g.current_user = user
|
||||
return f(*args, **kwargs)
|
||||
|
||||
return decorated
|
||||
|
||||
# Wrapper für Admin-Erfordernis im Frontend
|
||||
def frontend_admin_required(f):
|
||||
@wraps(f)
|
||||
def decorated(*args, **kwargs):
|
||||
if not g.get('current_user') or g.current_user['role'] != 'admin':
|
||||
flash('Sie benötigen Administrator-Rechte, um diese Seite zu besuchen.', 'error')
|
||||
return redirect(url_for('frontend_v2.dashboard'))
|
||||
return f(*args, **kwargs)
|
||||
|
||||
return decorated
|
||||
|
||||
# Öffentliche Routen
|
||||
@frontend_v2.route('/')
|
||||
def index():
|
||||
current_user = get_current_user()
|
||||
if current_user:
|
||||
return redirect(url_for('frontend_v2.dashboard'))
|
||||
return redirect(url_for('frontend_v2.login'))
|
||||
|
||||
@frontend_v2.route('/login')
|
||||
def login():
|
||||
current_user = get_current_user()
|
||||
if current_user:
|
||||
return redirect(url_for('frontend_v2.dashboard'))
|
||||
return render_template('login.html', current_user=None, active_page='login')
|
||||
|
||||
@frontend_v2.route('/register')
|
||||
def register():
|
||||
current_user = get_current_user()
|
||||
if current_user:
|
||||
return redirect(url_for('frontend_v2.dashboard'))
|
||||
return render_template('register.html', current_user=None, active_page='register')
|
||||
|
||||
@frontend_v2.route('/logout')
|
||||
def logout():
|
||||
session_id = session.get('session_id')
|
||||
if session_id:
|
||||
delete_session(session_id)
|
||||
session.pop('session_id', None)
|
||||
|
||||
flash('Sie wurden erfolgreich abgemeldet.', 'success')
|
||||
return redirect(url_for('frontend_v2.login'))
|
||||
|
||||
# Geschützte Routen
|
||||
@frontend_v2.route('/dashboard')
|
||||
@frontend_login_required
|
||||
def dashboard():
|
||||
current_user = g.current_user
|
||||
current_year = datetime.datetime.now().year
|
||||
return render_template('dashboard.html',
|
||||
current_user=user_to_dict(current_user),
|
||||
current_year=current_year,
|
||||
active_page='dashboard')
|
||||
|
||||
@frontend_v2.route('/jobs')
|
||||
@frontend_login_required
|
||||
def jobs():
|
||||
current_user = g.current_user
|
||||
|
||||
# Admins sehen alle Jobs, normale Benutzer nur ihre eigenen
|
||||
if current_user['role'] == 'admin':
|
||||
all_jobs = get_all_jobs()
|
||||
else:
|
||||
all_jobs = get_jobs_by_user(current_user['id'])
|
||||
|
||||
jobs_list = [job_to_dict(job) for job in all_jobs]
|
||||
|
||||
# Sortiere Jobs nach Startzeit (neueste zuerst)
|
||||
jobs_list.sort(key=lambda x: x['startAt'], reverse=True)
|
||||
|
||||
# Gruppiere Jobs nach Status (aktiv, abgebrochen, abgeschlossen)
|
||||
active_jobs = [job for job in jobs_list if job['remainingMinutes'] > 0 and not job['aborted']]
|
||||
completed_jobs = [job for job in jobs_list if job['remainingMinutes'] == 0 and not job['aborted']]
|
||||
aborted_jobs = [job for job in jobs_list if job['aborted']]
|
||||
|
||||
return render_template('jobs.html',
|
||||
current_user=user_to_dict(current_user),
|
||||
active_jobs=active_jobs,
|
||||
completed_jobs=completed_jobs,
|
||||
aborted_jobs=aborted_jobs,
|
||||
active_page='jobs')
|
||||
|
||||
@frontend_v2.route('/job/<job_id>')
|
||||
@frontend_login_required
|
||||
def job_details(job_id):
|
||||
current_user = g.current_user
|
||||
|
||||
job = get_job_by_id(job_id)
|
||||
if not job:
|
||||
flash('Der angeforderte Job wurde nicht gefunden.', 'error')
|
||||
return redirect(url_for('frontend_v2.jobs'))
|
||||
|
||||
# Benutzer können nur ihre eigenen Jobs sehen, es sei denn, sie sind Admins
|
||||
if current_user['role'] != 'admin' and job['user_id'] != current_user['id']:
|
||||
flash('Sie haben keine Berechtigung, diesen Job anzusehen.', 'error')
|
||||
return redirect(url_for('frontend_v2.jobs'))
|
||||
|
||||
job_data = job_to_dict(job)
|
||||
|
||||
# Holen Sie sich die Drucker-Informationen
|
||||
printer = get_socket_by_id(job['socket_id'])
|
||||
printer_data = socket_to_dict(printer) if printer else None
|
||||
|
||||
# Benutzerinformationen abrufen
|
||||
job_user = get_user_by_id(job['user_id'])
|
||||
job_user_data = user_to_dict(job_user) if job_user else None
|
||||
|
||||
return render_template('job_details.html',
|
||||
current_user=user_to_dict(current_user),
|
||||
job=job_data,
|
||||
printer=printer_data,
|
||||
job_user=job_user_data,
|
||||
active_page='jobs')
|
||||
|
||||
@frontend_v2.route('/profile')
|
||||
@frontend_login_required
|
||||
def profile():
|
||||
current_user = g.current_user
|
||||
|
||||
# Benutzer-Jobs abrufen
|
||||
user_jobs = get_jobs_by_user(current_user['id'])
|
||||
jobs_list = [job_to_dict(job) for job in user_jobs]
|
||||
|
||||
# Jobs nach Startzeit sortieren (neueste zuerst)
|
||||
jobs_list.sort(key=lambda x: x['startAt'], reverse=True)
|
||||
|
||||
# Gruppiere Jobs nach Status (aktiv, abgebrochen, abgeschlossen)
|
||||
active_jobs = [job for job in jobs_list if job['remainingMinutes'] > 0 and not job['aborted']]
|
||||
recent_jobs = jobs_list[:5] # Die 5 neuesten Jobs
|
||||
|
||||
# Nutzungsstatistiken berechnen
|
||||
total_jobs = len(jobs_list)
|
||||
total_minutes_used = sum(job['durationInMinutes'] for job in jobs_list if not job['aborted'])
|
||||
avg_duration = total_minutes_used // total_jobs if total_jobs > 0 else 0
|
||||
|
||||
return render_template('profile.html',
|
||||
current_user=user_to_dict(current_user),
|
||||
active_jobs=active_jobs,
|
||||
recent_jobs=recent_jobs,
|
||||
total_jobs=total_jobs,
|
||||
total_minutes_used=total_minutes_used,
|
||||
avg_duration=avg_duration,
|
||||
active_page='profile')
|
||||
|
||||
# Admin-Routen
|
||||
@frontend_v2.route('/printers')
|
||||
@frontend_login_required
|
||||
@frontend_admin_required
|
||||
def printers():
|
||||
current_user = g.current_user
|
||||
|
||||
# Alle Drucker abrufen
|
||||
all_sockets = get_all_sockets()
|
||||
printers_list = [socket_to_dict(socket) for socket in all_sockets]
|
||||
|
||||
return render_template('printers.html',
|
||||
current_user=user_to_dict(current_user),
|
||||
printers=printers_list,
|
||||
active_page='printers')
|
||||
|
||||
@frontend_v2.route('/printer/<printer_id>')
|
||||
@frontend_login_required
|
||||
@frontend_admin_required
|
||||
def printer_details(printer_id):
|
||||
current_user = g.current_user
|
||||
|
||||
printer = get_socket_by_id(printer_id)
|
||||
if not printer:
|
||||
flash('Der angeforderte Drucker wurde nicht gefunden.', 'error')
|
||||
return redirect(url_for('frontend_v2.printers'))
|
||||
|
||||
printer_data = socket_to_dict(printer)
|
||||
|
||||
return render_template('printer_details.html',
|
||||
current_user=user_to_dict(current_user),
|
||||
printer=printer_data,
|
||||
active_page='printers')
|
||||
|
||||
@frontend_v2.route('/users')
|
||||
@frontend_login_required
|
||||
@frontend_admin_required
|
||||
def users():
|
||||
current_user = g.current_user
|
||||
|
||||
# Alle Benutzer abrufen
|
||||
all_users = get_all_users()
|
||||
users_list = [user_to_dict(user) for user in all_users]
|
||||
|
||||
return render_template('users.html',
|
||||
current_user=user_to_dict(current_user),
|
||||
users=users_list,
|
||||
active_page='users')
|
||||
|
||||
@frontend_v2.route('/user/<user_id>')
|
||||
@frontend_login_required
|
||||
@frontend_admin_required
|
||||
def user_details(user_id):
|
||||
current_user = g.current_user
|
||||
|
||||
user = get_user_by_id(user_id)
|
||||
if not user:
|
||||
flash('Der angeforderte Benutzer wurde nicht gefunden.', 'error')
|
||||
return redirect(url_for('frontend_v2.users'))
|
||||
|
||||
user_data = user_to_dict(user)
|
||||
|
||||
# Benutzer-Jobs abrufen
|
||||
user_jobs = get_jobs_by_user(user_id)
|
||||
jobs_list = [job_to_dict(job) for job in user_jobs]
|
||||
|
||||
# Jobs nach Startzeit sortieren (neueste zuerst)
|
||||
jobs_list.sort(key=lambda x: x['startAt'], reverse=True)
|
||||
|
||||
# Gruppiere Jobs nach Status
|
||||
active_jobs = [job for job in jobs_list if job['remainingMinutes'] > 0 and not job['aborted']]
|
||||
completed_jobs = [job for job in jobs_list if job['remainingMinutes'] == 0 and not job['aborted']]
|
||||
aborted_jobs = [job for job in jobs_list if job['aborted']]
|
||||
|
||||
# Nutzungsstatistiken berechnen
|
||||
total_jobs = len(jobs_list)
|
||||
total_minutes_used = sum(job['durationInMinutes'] for job in jobs_list if not job['aborted'])
|
||||
avg_duration = total_minutes_used // total_jobs if total_jobs > 0 else 0
|
||||
|
||||
return render_template('user_details.html',
|
||||
current_user=user_to_dict(current_user),
|
||||
user=user_data,
|
||||
active_jobs=active_jobs,
|
||||
completed_jobs=completed_jobs,
|
||||
aborted_jobs=aborted_jobs,
|
||||
total_jobs=total_jobs,
|
||||
total_minutes_used=total_minutes_used,
|
||||
avg_duration=avg_duration,
|
||||
active_page='users')
|
||||
|
||||
@frontend_v2.route('/statistics')
|
||||
@frontend_login_required
|
||||
@frontend_admin_required
|
||||
def statistics():
|
||||
current_user = g.current_user
|
||||
|
||||
return render_template('statistics.html',
|
||||
current_user=user_to_dict(current_user),
|
||||
active_page='statistics')
|
||||
|
||||
# Fehlerbehandlung
|
||||
@frontend_v2.errorhandler(404)
|
||||
def page_not_found(e):
|
||||
current_user = get_current_user()
|
||||
return render_template('error.html',
|
||||
current_user=user_to_dict(current_user) if current_user else None,
|
||||
error_code=404,
|
||||
error_message='Die angeforderte Seite wurde nicht gefunden.'), 404
|
||||
|
||||
@frontend_v2.errorhandler(403)
|
||||
def forbidden(e):
|
||||
current_user = get_current_user()
|
||||
return render_template('error.html',
|
||||
current_user=user_to_dict(current_user) if current_user else None,
|
||||
error_code=403,
|
||||
error_message='Sie haben keine Berechtigung, auf diese Seite zuzugreifen.'), 403
|
||||
|
||||
@frontend_v2.errorhandler(500)
|
||||
def server_error(e):
|
||||
current_user = get_current_user()
|
||||
logger.error(f'Serverfehler: {e}')
|
||||
return render_template('error.html',
|
||||
current_user=user_to_dict(current_user) if current_user else None,
|
||||
error_code=500,
|
||||
error_message='Ein interner Serverfehler ist aufgetreten.'), 500
|
Reference in New Issue
Block a user