fix: ZIP-Download, Share-Status live aktualisieren, Ordner-ZIP bei Share-Links

ZIP-Download fix:
- window.location.href statt a.download fuer API-Downloads
  (a.download funktioniert nicht mit authentifizierten API-Routen)

Share-Status live:
- Dateiliste wird nach jeder Share-Aenderung automatisch neu geladen
  (Link erstellen, Link loeschen, Benutzer-Freigabe setzen/entfernen)
- Gruenes Share-Icon aktualisiert sich sofort ohne F5

Ordner-ZIP bei Share-Links:
- "Ganzen Ordner als ZIP herunterladen" Button bei read/write Ordner-Shares
- Backend: GET /share/<token>/download-zip mit Passwort + Ablauf-Check
- Benachrichtigung an Ersteller bei ZIP-Download

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Stefan Hacker
2026-04-11 20:35:30 +02:00
parent 1a831bfb04
commit 4b487974c6
3 changed files with 52 additions and 6 deletions
+34
View File
@@ -652,6 +652,40 @@ def share_download_file(token, file_id):
download_name=target_file.name)
@api_bp.route('/share/<token>/download-zip', methods=['GET'])
def share_download_zip(token):
"""Download the entire shared folder as ZIP."""
link = ShareLink.query.filter_by(token=token).first()
if not link:
return jsonify({'error': 'Link nicht gefunden'}), 404
if link.is_expired():
return jsonify({'error': 'Link abgelaufen'}), 410
if link.permission not in ('read', 'write'):
return jsonify({'error': 'Download nicht erlaubt'}), 403
if link.password_hash:
password = request.args.get('password', '') or request.headers.get('X-Share-Password', '')
if not bcrypt.check_password_hash(link.password_hash, password):
return jsonify({'error': 'Passwort erforderlich'}), 401
f = db.session.get(File, link.file_id)
if not f.is_folder:
return jsonify({'error': 'Kein Ordner'}), 400
link.download_count += 1
db.session.commit()
try:
from app.services.system_mail import notify_share_link_accessed
notify_share_link_accessed(link, f.name, request.remote_addr)
except Exception:
pass
return _download_folder_as_zip(f)
@api_bp.route('/share/<token>/files/<int:file_id>', methods=['DELETE'])
def share_delete_file(token, file_id):
"""Delete a file from a shared folder (write permission required)."""