"feat: Integrate printer monitor for enhanced logging in backend"

This commit is contained in:
2025-05-29 22:35:00 +02:00
parent 81c2b2ab88
commit 482e04723d
2 changed files with 556 additions and 8 deletions

View File

@@ -4344,4 +4344,536 @@ if __name__ == "__main__":
stop_queue_manager()
except:
pass
sys.exit(1)
sys.exit(1)
# ===== FILE-UPLOAD-ROUTEN =====
@app.route('/api/upload/job', methods=['POST'])
@login_required
def upload_job_file():
"""
Lädt eine Datei für einen Druckjob hoch
Form Data:
file: Die hochzuladende Datei
job_name: Name des Jobs (optional)
"""
try:
if 'file' not in request.files:
return jsonify({'error': 'Keine Datei ausgewählt'}), 400
file = request.files['file']
job_name = request.form.get('job_name', '')
if file.filename == '':
return jsonify({'error': 'Keine Datei ausgewählt'}), 400
# Metadaten für die Datei
metadata = {
'uploader_id': current_user.id,
'uploader_name': current_user.username,
'job_name': job_name
}
# Datei speichern
result = save_job_file(file, current_user.id, metadata)
if result:
relative_path, absolute_path, file_metadata = result
app_logger.info(f"Job-Datei hochgeladen: {file_metadata['original_filename']} von User {current_user.id}")
return jsonify({
'success': True,
'message': 'Datei erfolgreich hochgeladen',
'file_path': relative_path,
'filename': file_metadata['original_filename'],
'unique_filename': file_metadata['unique_filename'],
'file_size': file_metadata['file_size'],
'metadata': file_metadata
})
else:
return jsonify({'error': 'Fehler beim Speichern der Datei'}), 500
except Exception as e:
app_logger.error(f"Fehler beim Hochladen der Job-Datei: {str(e)}")
return jsonify({'error': f'Fehler beim Hochladen: {str(e)}'}), 500
@app.route('/api/upload/guest', methods=['POST'])
def upload_guest_file():
"""
Lädt eine Datei für einen Gastauftrag hoch
Form Data:
file: Die hochzuladende Datei
guest_name: Name des Gasts (optional)
guest_email: E-Mail des Gasts (optional)
"""
try:
if 'file' not in request.files:
return jsonify({'error': 'Keine Datei ausgewählt'}), 400
file = request.files['file']
guest_name = request.form.get('guest_name', '')
guest_email = request.form.get('guest_email', '')
if file.filename == '':
return jsonify({'error': 'Keine Datei ausgewählt'}), 400
# Metadaten für die Datei
metadata = {
'guest_name': guest_name,
'guest_email': guest_email
}
# Datei speichern
result = save_guest_file(file, metadata)
if result:
relative_path, absolute_path, file_metadata = result
app_logger.info(f"Gast-Datei hochgeladen: {file_metadata['original_filename']} für {guest_name or 'Unbekannt'}")
return jsonify({
'success': True,
'message': 'Datei erfolgreich hochgeladen',
'file_path': relative_path,
'filename': file_metadata['original_filename'],
'unique_filename': file_metadata['unique_filename'],
'file_size': file_metadata['file_size'],
'metadata': file_metadata
})
else:
return jsonify({'error': 'Fehler beim Speichern der Datei'}), 500
except Exception as e:
app_logger.error(f"Fehler beim Hochladen der Gast-Datei: {str(e)}")
return jsonify({'error': f'Fehler beim Hochladen: {str(e)}'}), 500
@app.route('/api/upload/avatar', methods=['POST'])
@login_required
def upload_avatar():
"""
Lädt ein Avatar-Bild für den aktuellen Benutzer hoch
Form Data:
file: Das Avatar-Bild
"""
try:
if 'file' not in request.files:
return jsonify({'error': 'Keine Datei ausgewählt'}), 400
file = request.files['file']
if file.filename == '':
return jsonify({'error': 'Keine Datei ausgewählt'}), 400
# Nur Bilder erlauben
allowed_extensions = {'png', 'jpg', 'jpeg', 'gif', 'webp'}
if not file.filename or '.' not in file.filename:
return jsonify({'error': 'Ungültiger Dateityp'}), 400
file_ext = file.filename.rsplit('.', 1)[1].lower()
if file_ext not in allowed_extensions:
return jsonify({'error': 'Nur Bilddateien sind erlaubt (PNG, JPG, JPEG, GIF, WebP)'}), 400
# Alte Avatar-Datei löschen falls vorhanden
db_session = get_db_session()
user = db_session.query(User).get(current_user.id)
if user and user.avatar_path:
delete_file_safe(user.avatar_path)
# Neue Avatar-Datei speichern
result = save_avatar_file(file, current_user.id)
if result:
relative_path, absolute_path, file_metadata = result
# Avatar-Pfad in der Datenbank aktualisieren
user.avatar_path = relative_path
db_session.commit()
db_session.close()
app_logger.info(f"Avatar hochgeladen für User {current_user.id}")
return jsonify({
'success': True,
'message': 'Avatar erfolgreich hochgeladen',
'file_path': relative_path,
'filename': file_metadata['original_filename'],
'unique_filename': file_metadata['unique_filename'],
'file_size': file_metadata['file_size']
})
else:
db_session.close()
return jsonify({'error': 'Fehler beim Speichern des Avatars'}), 500
except Exception as e:
app_logger.error(f"Fehler beim Hochladen des Avatars: {str(e)}")
return jsonify({'error': f'Fehler beim Hochladen: {str(e)}'}), 500
@app.route('/api/upload/asset', methods=['POST'])
@login_required
@admin_required
def upload_asset():
"""
Lädt ein statisches Asset hoch (nur für Administratoren)
Form Data:
file: Die Asset-Datei
asset_name: Name des Assets (optional)
"""
try:
if 'file' not in request.files:
return jsonify({'error': 'Keine Datei ausgewählt'}), 400
file = request.files['file']
asset_name = request.form.get('asset_name', '')
if file.filename == '':
return jsonify({'error': 'Keine Datei ausgewählt'}), 400
# Metadaten für die Datei
metadata = {
'uploader_id': current_user.id,
'uploader_name': current_user.username,
'asset_name': asset_name
}
# Datei speichern
result = file_manager.save_file(file, 'assets', current_user.id, 'asset', metadata)
if result:
relative_path, absolute_path, file_metadata = result
app_logger.info(f"Asset hochgeladen: {file_metadata['original_filename']} von Admin {current_user.id}")
return jsonify({
'success': True,
'message': 'Asset erfolgreich hochgeladen',
'file_path': relative_path,
'filename': file_metadata['original_filename'],
'unique_filename': file_metadata['unique_filename'],
'file_size': file_metadata['file_size'],
'metadata': file_metadata
})
else:
return jsonify({'error': 'Fehler beim Speichern des Assets'}), 500
except Exception as e:
app_logger.error(f"Fehler beim Hochladen des Assets: {str(e)}")
return jsonify({'error': f'Fehler beim Hochladen: {str(e)}'}), 500
@app.route('/api/upload/log', methods=['POST'])
@login_required
@admin_required
def upload_log():
"""
Lädt eine Log-Datei hoch (nur für Administratoren)
Form Data:
file: Die Log-Datei
log_type: Typ des Logs (optional)
"""
try:
if 'file' not in request.files:
return jsonify({'error': 'Keine Datei ausgewählt'}), 400
file = request.files['file']
log_type = request.form.get('log_type', 'allgemein')
if file.filename == '':
return jsonify({'error': 'Keine Datei ausgewählt'}), 400
# Metadaten für die Datei
metadata = {
'uploader_id': current_user.id,
'uploader_name': current_user.username,
'log_type': log_type
}
# Datei speichern
result = file_manager.save_file(file, 'logs', current_user.id, 'log', metadata)
if result:
relative_path, absolute_path, file_metadata = result
app_logger.info(f"Log-Datei hochgeladen: {file_metadata['original_filename']} von Admin {current_user.id}")
return jsonify({
'success': True,
'message': 'Log-Datei erfolgreich hochgeladen',
'file_path': relative_path,
'filename': file_metadata['original_filename'],
'unique_filename': file_metadata['unique_filename'],
'file_size': file_metadata['file_size'],
'metadata': file_metadata
})
else:
return jsonify({'error': 'Fehler beim Speichern der Log-Datei'}), 500
except Exception as e:
app_logger.error(f"Fehler beim Hochladen der Log-Datei: {str(e)}")
return jsonify({'error': f'Fehler beim Hochladen: {str(e)}'}), 500
@app.route('/api/upload/backup', methods=['POST'])
@login_required
@admin_required
def upload_backup():
"""
Lädt eine Backup-Datei hoch (nur für Administratoren)
Form Data:
file: Die Backup-Datei
backup_type: Typ des Backups (optional)
"""
try:
if 'file' not in request.files:
return jsonify({'error': 'Keine Datei ausgewählt'}), 400
file = request.files['file']
backup_type = request.form.get('backup_type', 'allgemein')
if file.filename == '':
return jsonify({'error': 'Keine Datei ausgewählt'}), 400
# Metadaten für die Datei
metadata = {
'uploader_id': current_user.id,
'uploader_name': current_user.username,
'backup_type': backup_type
}
# Datei speichern
result = file_manager.save_file(file, 'backups', current_user.id, 'backup', metadata)
if result:
relative_path, absolute_path, file_metadata = result
app_logger.info(f"Backup-Datei hochgeladen: {file_metadata['original_filename']} von Admin {current_user.id}")
return jsonify({
'success': True,
'message': 'Backup-Datei erfolgreich hochgeladen',
'file_path': relative_path,
'filename': file_metadata['original_filename'],
'unique_filename': file_metadata['unique_filename'],
'file_size': file_metadata['file_size'],
'metadata': file_metadata
})
else:
return jsonify({'error': 'Fehler beim Speichern der Backup-Datei'}), 500
except Exception as e:
app_logger.error(f"Fehler beim Hochladen der Backup-Datei: {str(e)}")
return jsonify({'error': f'Fehler beim Hochladen: {str(e)}'}), 500
@app.route('/api/upload/temp', methods=['POST'])
@login_required
def upload_temp_file():
"""
Lädt eine temporäre Datei hoch
Form Data:
file: Die temporäre Datei
purpose: Verwendungszweck (optional)
"""
try:
if 'file' not in request.files:
return jsonify({'error': 'Keine Datei ausgewählt'}), 400
file = request.files['file']
purpose = request.form.get('purpose', '')
if file.filename == '':
return jsonify({'error': 'Keine Datei ausgewählt'}), 400
# Metadaten für die Datei
metadata = {
'uploader_id': current_user.id,
'uploader_name': current_user.username,
'purpose': purpose
}
# Datei speichern
result = file_manager.save_file(file, 'temp', current_user.id, 'temp', metadata)
if result:
relative_path, absolute_path, file_metadata = result
app_logger.info(f"Temporäre Datei hochgeladen: {file_metadata['original_filename']} von User {current_user.id}")
return jsonify({
'success': True,
'message': 'Temporäre Datei erfolgreich hochgeladen',
'file_path': relative_path,
'filename': file_metadata['original_filename'],
'unique_filename': file_metadata['unique_filename'],
'file_size': file_metadata['file_size'],
'metadata': file_metadata
})
else:
return jsonify({'error': 'Fehler beim Speichern der temporären Datei'}), 500
except Exception as e:
app_logger.error(f"Fehler beim Hochladen der temporären Datei: {str(e)}")
return jsonify({'error': f'Fehler beim Hochladen: {str(e)}'}), 500
@app.route('/api/files/<path:file_path>', methods=['GET'])
@login_required
def serve_uploaded_file(file_path):
"""
Stellt hochgeladene Dateien bereit (mit Zugriffskontrolle)
"""
try:
# Datei-Info abrufen
file_info = file_manager.get_file_info(file_path)
if not file_info:
return jsonify({'error': 'Datei nicht gefunden'}), 404
# Zugriffskontrolle basierend auf Dateikategorie
if file_path.startswith('jobs/'):
# Job-Dateien: Nur Besitzer und Admins
if not current_user.is_admin:
# Prüfen ob Benutzer der Besitzer ist
if f"user_{current_user.id}" not in file_path:
return jsonify({'error': 'Zugriff verweigert'}), 403
elif file_path.startswith('guests/'):
# Gast-Dateien: Nur Admins
if not current_user.is_admin:
return jsonify({'error': 'Zugriff verweigert'}), 403
elif file_path.startswith('avatars/'):
# Avatar-Dateien: Öffentlich zugänglich für angemeldete Benutzer
pass
elif file_path.startswith('temp/'):
# Temporäre Dateien: Nur Besitzer und Admins
if not current_user.is_admin:
# Prüfen ob Benutzer der Besitzer ist
if f"user_{current_user.id}" not in file_path:
return jsonify({'error': 'Zugriff verweigert'}), 403
else:
# Andere Dateien (assets, logs, backups): Nur Admins
if not current_user.is_admin:
return jsonify({'error': 'Zugriff verweigert'}), 403
# Datei bereitstellen
return send_file(file_info['absolute_path'], as_attachment=False)
except Exception as e:
app_logger.error(f"Fehler beim Bereitstellen der Datei {file_path}: {str(e)}")
return jsonify({'error': 'Fehler beim Laden der Datei'}), 500
@app.route('/api/files/<path:file_path>', methods=['DELETE'])
@login_required
def delete_uploaded_file(file_path):
"""
Löscht eine hochgeladene Datei (mit Zugriffskontrolle)
"""
try:
# Datei-Info abrufen
file_info = file_manager.get_file_info(file_path)
if not file_info:
return jsonify({'error': 'Datei nicht gefunden'}), 404
# Zugriffskontrolle basierend auf Dateikategorie
if file_path.startswith('jobs/'):
# Job-Dateien: Nur Besitzer und Admins
if not current_user.is_admin:
# Prüfen ob Benutzer der Besitzer ist
if f"user_{current_user.id}" not in file_path:
return jsonify({'error': 'Zugriff verweigert'}), 403
elif file_path.startswith('guests/'):
# Gast-Dateien: Nur Admins
if not current_user.is_admin:
return jsonify({'error': 'Zugriff verweigert'}), 403
elif file_path.startswith('avatars/'):
# Avatar-Dateien: Nur Besitzer und Admins
if not current_user.is_admin:
# Prüfen ob Benutzer der Besitzer ist
if f"user_{current_user.id}" not in file_path:
return jsonify({'error': 'Zugriff verweigert'}), 403
elif file_path.startswith('temp/'):
# Temporäre Dateien: Nur Besitzer und Admins
if not current_user.is_admin:
# Prüfen ob Benutzer der Besitzer ist
if f"user_{current_user.id}" not in file_path:
return jsonify({'error': 'Zugriff verweigert'}), 403
else:
# Andere Dateien (assets, logs, backups): Nur Admins
if not current_user.is_admin:
return jsonify({'error': 'Zugriff verweigert'}), 403
# Datei löschen
if delete_file_safe(file_path):
app_logger.info(f"Datei gelöscht: {file_path} von User {current_user.id}")
return jsonify({'success': True, 'message': 'Datei erfolgreich gelöscht'})
else:
return jsonify({'error': 'Fehler beim Löschen der Datei'}), 500
except Exception as e:
app_logger.error(f"Fehler beim Löschen der Datei {file_path}: {str(e)}")
return jsonify({'error': f'Fehler beim Löschen der Datei: {str(e)}'}), 500
@app.route('/api/admin/files/stats', methods=['GET'])
@login_required
@admin_required
def get_file_stats():
"""
Gibt Statistiken zu allen Dateien zurück (nur für Administratoren)
"""
try:
stats = file_manager.get_category_stats()
# Gesamtstatistiken berechnen
total_files = sum(category.get('file_count', 0) for category in stats.values())
total_size = sum(category.get('total_size', 0) for category in stats.values())
return jsonify({
'success': True,
'categories': stats,
'totals': {
'file_count': total_files,
'total_size': total_size,
'total_size_mb': round(total_size / (1024 * 1024), 2)
}
})
except Exception as e:
app_logger.error(f"Fehler beim Abrufen der Datei-Statistiken: {str(e)}")
return jsonify({'error': f'Fehler beim Abrufen der Statistiken: {str(e)}'}), 500
@app.route('/api/admin/files/cleanup', methods=['POST'])
@login_required
@admin_required
def cleanup_temp_files():
"""
Räumt temporäre Dateien auf (nur für Administratoren)
"""
try:
data = request.get_json() or {}
max_age_hours = data.get('max_age_hours', 24)
# Temporäre Dateien aufräumen
deleted_count = file_manager.cleanup_temp_files(max_age_hours)
app_logger.info(f"Temporäre Dateien aufgeräumt: {deleted_count} Dateien gelöscht")
return jsonify({
'success': True,
'message': f'{deleted_count} temporäre Dateien erfolgreich gelöscht',
'deleted_count': deleted_count
})
except Exception as e:
app_logger.error(f"Fehler beim Aufräumen temporärer Dateien: {str(e)}")
return jsonify({'error': f'Fehler beim Aufräumen: {str(e)}'}), 500