diff --git a/app.py b/app.py index 653d914..8217e59 100644 --- a/app.py +++ b/app.py @@ -1951,7 +1951,66 @@ def download_agent_file(agent_key, filename): if not os.path.isfile(filepath): return jsonify({'error': 'Datei nicht gefunden'}), 404 - return send_from_directory(work_dir, filename, as_attachment=False) + # Force download wenn download=1 Parameter + as_attachment = request.args.get('download') == '1' + return send_from_directory(work_dir, filename, as_attachment=as_attachment) + + +@app.route('/files/agent//view/') +def view_agent_file(agent_key, filename): + """Gibt Inhalt einer Agent-Datei als JSON zurück.""" + if agent_key not in AGENTS: + return jsonify({'error': 'Agent nicht gefunden'}), 404 + + dirs = ensure_agent_structure(agent_key) + work_dir = dirs['work_dir'] + filepath = os.path.join(work_dir, filename) + + # Security: Stelle sicher, dass die Datei im work_dir ist + if not os.path.abspath(filepath).startswith(os.path.abspath(work_dir)): + return jsonify({'error': 'Zugriff verweigert'}), 403 + + if not os.path.isfile(filepath): + return jsonify({'error': 'Datei nicht gefunden'}), 404 + + try: + with open(filepath, 'r', encoding='utf-8') as f: + content = f.read() + + if request.args.get('json'): + return jsonify({'content': content}) + return content + except Exception as e: + return jsonify({'error': str(e)}), 500 + + +@app.route('/files/agent//delete/') +def delete_agent_file(agent_key, filename): + """Löscht eine Datei aus dem Work-Ordner eines Agenten.""" + if agent_key not in AGENTS: + flash('Agent nicht gefunden', 'danger') + return redirect(url_for('files_page')) + + dirs = ensure_agent_structure(agent_key) + work_dir = dirs['work_dir'] + filepath = os.path.join(work_dir, filename) + + # Security: Stelle sicher, dass die Datei im work_dir ist + if not os.path.abspath(filepath).startswith(os.path.abspath(work_dir)): + flash('Zugriff verweigert', 'danger') + return redirect(url_for('files_page')) + + if not os.path.isfile(filepath): + flash('Datei nicht gefunden', 'warning') + return redirect(url_for('files_page')) + + try: + os.remove(filepath) + flash(f'Agent-Datei "{filename}" gelöscht', 'success') + except Exception as e: + flash(f'Fehler beim Löschen: {str(e)}', 'danger') + + return redirect(url_for('files_page')) @app.route('/files/email/view/') @@ -2032,6 +2091,57 @@ def view_project_file(filename): return jsonify({'error': str(e)}), 500 +@app.route('/files/project/') +def download_project_file(filename): + """Liefert eine Projektdatei zum Download.""" + base_dir = os.path.dirname(__file__) + filepath = os.path.join(base_dir, filename) + + # Security: stay in base dir + if os.path.dirname(os.path.abspath(filepath)) != os.path.abspath(base_dir): + return jsonify({'error': 'Zugriff verweigert'}), 403 + + allowed_ext = ('.md', '.txt', '.docx') + if not filename.lower().endswith(allowed_ext): + return jsonify({'error': 'Dateityp nicht unterstützt'}), 400 + + if not os.path.isfile(filepath): + return jsonify({'error': 'Datei nicht gefunden'}), 404 + + # Force download wenn download=1 Parameter + as_attachment = request.args.get('download') == '1' + return send_from_directory(base_dir, filename, as_attachment=as_attachment) + + +@app.route('/files/project/delete/') +def delete_project_file(filename): + """Löscht eine Projektdatei.""" + base_dir = os.path.dirname(__file__) + filepath = os.path.join(base_dir, filename) + + # Security: stay in base dir + if os.path.dirname(os.path.abspath(filepath)) != os.path.abspath(base_dir): + flash('Zugriff verweigert', 'danger') + return redirect(url_for('files_page')) + + allowed_ext = ('.md', '.txt', '.docx') + if not filename.lower().endswith(allowed_ext): + flash('Dateityp nicht unterstützt', 'warning') + return redirect(url_for('files_page')) + + if not os.path.isfile(filepath): + flash('Datei nicht gefunden', 'warning') + return redirect(url_for('files_page')) + + try: + os.remove(filepath) + flash(f'Projektdokument "{filename}" gelöscht', 'success') + except Exception as e: + flash(f'Fehler beim Löschen: {str(e)}', 'danger') + + return redirect(url_for('files_page')) + + @app.route('/emails', methods=['GET', 'POST']) def emails(): """Email Management Interface""" diff --git a/templates/files.html b/templates/files.html index f27fbee..a5dfcfd 100644 --- a/templates/files.html +++ b/templates/files.html @@ -137,6 +137,9 @@
+ +
{% endfor %} @@ -165,7 +168,11 @@
{{ (file.size / 1024)|round(1) }} KB · {{ file.modified[:10] }}
- + + +
{% endfor %} @@ -245,6 +252,11 @@ function viewProjectFile(event, name) { openFileModal(name, '/files/project/view/' + encodeURIComponent(name) + '?json=1'); } +function viewAgentFile(event, agentKey, name) { + event.preventDefault(); + openFileModal(`${agentKey}/${name}`, `/files/agent/${agentKey}/view/${encodeURIComponent(name)}?json=1`); +} + function editEmailFile(name) { currentEditFile = name; document.getElementById('editModalFilename').textContent = name;