Commit Graph
100 Commits
Author SHA1 Message Date
Stefan HackerandClaude Opus 4.6 e7f469f477 fix: CalDAV HEAD auf Events + PROPPATCH auf Kalender
* GET-Route akzeptiert jetzt auch HEAD - manche Clients pruefen
  Existenz einer Ressource via HEAD bevor sie GET senden.
* Neue PROPPATCH-Route auf der Kalender-Collection: erkennt
  calendar-color + displayname und persistiert beides. Andere
  Properties werden als "angewendet" bestaetigt, damit DAVx5
  und Apple Calendar nicht enttaeuscht sind.

Damit sollten die 500-Fehler beim Sync verschwinden. Falls nicht,
bitte Server- oder DAVx5-Log posten.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 14:18:53 +02:00
Stefan HackerandClaude Opus 4.6 189aa18be8 fix: PROPFIND-Response-Href stimmt mit Anfrage-URL ueberein
Bisher war der href in der Response immer /dav/, auch wenn DAVx5
einen PROPFIND auf / oder /.well-known/caldav gemacht hat. Das
kann Clients verwirren - die erwarten, dass der Response-Pfad zum
angefragten Pfad passt. current-user-principal zeigt weiterhin
korrekt auf /dav/Adam/.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 14:09:01 +02:00
Stefan HackerandClaude Opus 4.6 39e68eee6a fix: PROPFIND/OPTIONS auf / (Root) akzeptieren - DAVx5 startet dort
DAVx5 macht beim Account-Setup zuerst PROPFIND auf / bevor es
/.well-known/caldav probiert. Der Server antwortete mit 405
Method Not Allowed (weil / nur fuer SPA-GET registriert war),
woraufhin DAVx5 den gesamten Server als "kein DAV" verwirft.

Jetzt: PROPFIND und OPTIONS auf / werden an die DAV-Handler
delegiert (gleiches Verhalten wie auf /dav/). GET/HEAD auf /
laeuft unveraendert zur SPA.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 14:04:38 +02:00
Stefan HackerandClaude Opus 4.6 3c762e1476 fix: Well-Known DAV - OPTIONS liefert jetzt korrekt DAV-Header
Flask hat trotz expliziter OPTIONS-Route Auto-OPTIONS generiert,
wodurch der DAV-Header fehlte. DAVx5 sieht so keinen Calendar-
Access und lehnt den Server ab.

Konsolidiert zu einem Handler mit method-basiertem Dispatch und
provide_automatic_options=False, damit Flask nicht dazwischenfunkt.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 13:53:24 +02:00
Stefan HackerandClaude Opus 4.6 3f0d823dbf fix: CalDAV fuer DAVx5 - Well-Known intern dispatchen, mehr Properties
Aenderungen fuer besseren DAVx5-Support:

* /.well-known/caldav reagiert jetzt direkt auf PROPFIND/OPTIONS
  ohne Redirect-Zickerei. GET/HEAD redirecten weiterhin auf /dav/
  als visuelle Fallback.
* strict_slashes app-weit aus: /dav und /dav/ sind gleichwertig,
  ebenso die Unterpfade. DAVx5 nutzt beides gemischt.
* Jede DAV-Response traegt jetzt den DAV-Header (1, 2, 3,
  calendar-access), nicht nur OPTIONS.
* Kalender-Response enthaelt jetzt supported-report-set mit
  calendar-query + calendar-multiget (DAVx5 prueft das).
* current-user-privilege-set wird mit konkreten Privilegien gefuellt
  (read, write, write-properties, write-content, bind, unbind)
  statt leer.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 13:50:50 +02:00
Stefan HackerandClaude Opus 4.6 c4b381c5e9 fix: CalDAV Autodiscovery - XML war doppelt verschachtelt
Property-Elemente wurden unter einem Container mit demselben Tag
erzeugt, z.B.:
  <current-user-principal>
    <current-user-principal>    <!-- falsch, doppelt -->
      <href>/dav/adam/</href>
    </current-user-principal>
  </current-user-principal>

Clients wie DAVx5 und Thunderbird erkennen dadurch den Principal
nicht und melden "Kein CalDAV-Dienst gefunden". XML-Generierung
umgebaut - Response-Helfer bekommen jetzt eine populate_prop-
Callback, die die tatsaechlichen Property-Children direkt ins
<prop>-Element setzt.

Zusaetzlich:
* /.well-known/caldav und /carddav akzeptieren jetzt auch PROPFIND,
  OPTIONS, HEAD (einige Clients halten die Methode beim ersten
  Aufruf bei).
* Kalender-Response enthaelt current-user-privilege-set (leer, als
  Signal dass der Client nicht ACL-abhaengig pruefen muss).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 13:44:44 +02:00
Stefan HackerandClaude Opus 4.6 e85338761d feat: Persoenliche Farbe fuer freigegebene Kalender
CalendarShare bekommt color-Spalte. Im Kalender-Menue kann jeder
Benutzer eine eigene Anzeigefarbe fuer einen mit ihm geteilten
Kalender setzen, ohne dass sich dadurch die Farbe beim
Eigentuemer oder anderen Share-Empfaengern aendert.

* Owner: Farbe aendert den Kalender direkt (wie bisher).
* Share-Empfaenger: Farbe landet in CalendarShare.color und wird
  nur fuer ihn ausgeliefert (list_calendars injiziert sie in
  'color', Owner-Farbe bleibt in 'owner_color' als Referenz).

Neuer Endpoint: PUT /calendars/<id>/my-color.
UI-Hinweis: "Nur fuer deine Ansicht - <Owner> behaelt seine Farbe".

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 13:14:45 +02:00
Stefan HackerandClaude Opus 4.6 2170f4a7b1 feat: Kalender-Ansicht aktualisiert sich live via SSE
Backend:
Neuer Event-Typ 'calendar' im Broadcaster. Wird bei Event-CRUD,
Serien-Ausnahmen, Freigaben hinzufuegen/entfernen und beim
Loeschen ganzer Kalender emittiert. Empfaenger: Eigentuemer +
alle User mit CalendarShare auf dem jeweiligen Kalender.

Frontend:
CalendarView oeffnet beim Mount eine EventSource zu
/api/sync/events und reloaded Kalenderliste + Events bei jedem
'calendar'-Event (300ms debounced). Damit sehen beteiligte
Nutzer Aenderungen in praktisch Echtzeit - kein F5 mehr noetig.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 13:10:54 +02:00
Stefan HackerandClaude Opus 4.6 ce4faedd88 feat: CalDAV-URLs im Kalender-Menue anzeigen
Im Drei-Punkte-Menue jedes Kalenders wird jetzt ein Info-Block mit
den CalDAV-URLs angezeigt:

* Auto-Discovery URL fuer Thunderbird / DAVx5 / Apple Calendar
* Direkt-URL fuer diesen speziellen Kalender (z.B. Outlook
  CalDAV-Synchronizer)
* Kurz-Hinweis welcher Client welche URL nimmt

Jede URL hat ein Kopier-Icon. Ergaenzt den bestehenden iCal-Link
um die bidirektionale Sync-Moeglichkeit ueber CalDAV.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 13:08:11 +02:00
Stefan HackerandClaude Opus 4.6 fda9e685a9 feat: Kalender-Freigaben per Stift-Button bearbeiten
Analog zu den Datei-Freigaben: Stift neben der Muelltonne in der
Share-Liste macht die Zeile zur Inline-Edit-Zeile mit Permission-
Dropdown + Check/X. Speichern nutzt denselben POST /share-
Endpoint, der auch das initiale Teilen erledigt - er erkennt den
existierenden User und aktualisiert nur die Berechtigung.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 13:04:48 +02:00
Stefan HackerandClaude Opus 4.6 c73be6fac5 fix: Startup-Crash - doppelt definierte Calendar.owner-Relation entfernt
User.calendars hat bereits backref='owner', mein zusaetzlich
hinzugefuegtes Calendar.owner kollidierte damit und SQLAlchemy
weigerte sich, die Mappers zu initialisieren ("Error creating
backref 'owner'..."). Damit waren alle Auth-Endpoints tot.

Jetzt nur noch Kommentar, die backref uebernimmt die Aufgabe.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 13:00:00 +02:00
Stefan HackerandClaude Opus 4.6 a143325bbe feat: Kalender - Autocomplete + Privat-Flag + Share-Liste + Bugfix
Sharing-Fix:
Calendar-Model hatte keine owner-Relation zu User - list_calendars
stuerzte beim Listen geteilter Kalender ab (c.owner.username ->
AttributeError). Jetzt mit explizitem foreign_keys Relationship.

Benutzer-Autocomplete:
"Kalender teilen" nutzt jetzt /users/search wie bei Dateien.
Tippt man 2+ Zeichen, erscheint ein Dropdown mit passenden
Benutzernamen. Klick uebernimmt den Namen.

Bestehende Freigaben werden im Menue angezeigt mit Muelleimer
zum Entfernen.

Privat-Flag fuer Termine:
CalendarEvent bekommt is_private-Spalte. Checkbox im Termin-
Dialog "🔒 Privat (Teilnehmer sehen nur den Zeitblock)".

Redaction greift an drei Stellen:
* GET /events: Nicht-Owner sehen summary="Privat", description
  und location = null. Zeitfenster bleibt voll sichtbar.
* iCal-Export (/ical/<token>): Privat-Events werden mit
  CLASS:PRIVATE ausgegeben und SUMMARY/DESCRIPTION/LOCATION
  werden gestrippt.
* CalDAV: aktuell werden eh nur eigene Kalender exportiert,
  also keine Redaction noetig. Kommt bei Share-Support rein.

Der Eigentuemer sieht natuerlich in seiner eigenen Ansicht alle
Details seines privaten Termins.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 12:56:25 +02:00
Stefan HackerandClaude Opus 4.6 5797a7b738 feat: CalDAV-Server (RFC 4791 Subset) fuer native Client-Sync
Vollstaendige CalDAV-Implementierung unter /dav/ - Thunderbird,
DAVx5, Apple Calendar und Outlook (CalDAV-Synchronizer) koennen
sich einfach ueber HTTP-Basic-Auth mit ihrem Mini-Cloud-Account
anmelden und ihre Kalender synchronisieren.

Unterstuetzte Methoden:
* OPTIONS      - DAV-Capabilities
* PROPFIND     - Discovery, Principal, Calendar-Home, Kalender,
                 Termin-Listings (Depth 0/1 beachtet)
* REPORT       - calendar-query + calendar-multiget mit
                 optionalem Zeitraumfilter (<time-range>)
* GET          - einzelner Termin als VCALENDAR
* PUT          - Termin erstellen/aktualisieren (mit ETag-Check
                 via If-Match + If-None-Match)
* DELETE       - Termin oder ganzer Kalender
* MKCALENDAR   - neuen Kalender vom Client aus anlegen

iCal-Parser verarbeitet SUMMARY, DESCRIPTION, LOCATION, DTSTART,
DTEND, RRULE, EXDATE - inklusive Line-Folding (RFC 5545).
Ganztages-Termine (VALUE=DATE) werden korrekt erkannt.

ETags basieren auf updated_at-Zeitstempel und werden pro
PUT-Response zurueckgegeben, damit Clients Konflikte erkennen.

nginx.example.conf: /dav/ mit proxy_request_buffering off fuer
groessere PUTs und Weiterleitung der .well-known-URLs.

README: eigener "CalDAV-Zugriff"-Block mit Tabelle pro Client.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 12:51:21 +02:00
Stefan HackerandClaude Opus 4.6 cbb2786130 fix: Kalender - Termine immer als Balken statt Punkt+Zeit
eventDisplay: 'block' zwingt FullCalendar dazu, auch zeitlich
terminierte Termine in der Monatsansicht als farbige Balken
anzuzeigen statt als Punkt mit Uhrzeit-Label. Damit sieht ein
per "Neuer Termin"-Button angelegter Termin genauso aus wie einer,
der per Klick auf den Tag erstellt wurde.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 12:44:28 +02:00
Stefan HackerandClaude Opus 4.6 c1b05e2525 feat: Serientermin-Bearbeitung: Nur diesen Termin oder Serie
Klick auf einen wiederkehrenden Termin oeffnet zuerst einen Dialog:
"Nur diesen Termin" oder "Ganze Serie".

* Serie: bearbeitet den Master wie bisher
* Nur dieser: fuegt EXDATE fuer das geklickte Datum zum Master
  hinzu und legt einen eigenstaendigen Ersatz-Termin mit den
  bearbeiteten Daten an

Backend:
* CalendarEvent.exdates speichert Ausnahmedaten kommasepariert
* POST /events/<id>/exception fuegt EXDATE hinzu, erstellt
  optional das Replacement-Event mit frischer UID
* _build_vevent schreibt jetzt EXDATE-Zeilen in die ical_data,
  sodass CalDAV-Clients die Ausnahmen auch sehen werden

Frontend:
* FullCalendar rrule-Plugin bekommt die exdate-Liste und blendet
  die uebersprungenen Tage aus
* Drag & Drop verschiebt weiterhin die ganze Serie (Shortcut -
  fuer Einzelverschiebung Termin anklicken und bearbeiten)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 12:41:35 +02:00
Stefan HackerandClaude Opus 4.6 ddd8f57e69 feat: Kalender-Termine zeigen Icons + Start-Ende-Uhrzeit
* 📅-Icon bei ganztaegigen Terminen
* 🔁-Icon bei wiederkehrenden Terminen
* Anzeige "09:00-10:30" statt nur "09:00" in Woche/Tag-Ansicht
* Mouseover-Tooltip mit allen Termin-Infos inklusive Ort und
  Beschreibung

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 12:38:44 +02:00
Stefan HackerandClaude Opus 4.6 c5284f57e0 feat: Kalender mit FullCalendar - Woche/Monat/Tag, Drag&Drop, Wiederholungen
Kalender-UI komplett neu aufgesetzt mit FullCalendar:
* Drei Ansichten: Monat, Woche, Tag - ueber Toolbar wechselbar
* Drag & Drop: Termine zwischen Tagen verschieben
* Resize: Termindauer direkt am Rand ziehen
* Sidebar mit aktiven Kalendern (Checkbox fuers Ein-/Ausblenden)
* Deutsch lokalisiert, Woche startet Mo, Wochennummern
* Heute-Marker + Jetzt-Linie in Woche/Tag

Terminbearbeitung:
* Titel, Ort, Beschreibung, Zeitraum (oder ganztaegig)
* Wiederholungs-Editor: taeglich, woechentlich (mit Wochentagen),
  monatlich (auch "jeden 2. Mittwoch"), jaehrlich - jeweils mit
  Intervall, Enddatum oder Wiederholungsanzahl
* RRULE-Feld (RFC 5545) wird generiert und vom rrule-Plugin fuer
  die Anzeige im Kalender gerendert

Backend:
* CalendarEvent: description + location Spalten ergaenzt
* Calendar: ical_password_hash fuer passwortgeschuetzte Abo-Links
* /calendars/<id>/ical-link unterstuetzt password + clear_password
* DELETE /calendars/<id>/ical-link zum Zurueckziehen
* ical_export erzwingt HTTP Basic Auth wenn Passwort gesetzt -
  DAVx5, Apple Cal, Thunderbird verstehen das out-of-the-box

Frontend-Deps: @fullcalendar/{core,daygrid,timegrid,interaction,
rrule,vue3}, rrule - ca. 150KB Bundle-Overhead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 12:32:59 +02:00
Stefan HackerandClaude Opus 4.6 04bc3f80ec feat: Bestehende Benutzerfreigaben per Stift-Button bearbeiten
Neben der Muelltonne jetzt ein Stift-Icon im Share-Dialog:
Klick macht die Zeile zur Inline-Edit-Zeile mit Permission-
Dropdown + Weiterteilen-Checkbox + Speichern/Abbrechen-Buttons.
Speichern ruft POST /permissions mit user_id auf - Backend
erkennt die bestehende Freigabe und aktualisiert sie, statt
loeschen + neu anlegen zu muessen.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 12:14:03 +02:00
Stefan HackerandClaude Opus 4.6 9b135e42b7 feat: Freigaben-Aenderung live + "Ordner nicht mehr verfuegbar"-Handling
Backend:
set_permission und remove_permission feuern jetzt ein SSE-Event vom
Typ 'permission' an Target-User + Owner + weitere Share-Empfaenger.
Damit aktualisieren sich die Dateilisten aller Beteiligten in
Echtzeit - auch beim Betroffenen, der gerade seinen Zugriff
verliert.

Frontend:
FilesView wrapped loadFiles in safeLoadCurrentFolder(). Bei
403/404 erscheint ein Toast "Dieser Ordner wurde geloescht oder
die Freigabe wurde entfernt" und nach 600ms wird zurueck zum
Root navigiert. Greift beim Direktaufruf, beim Ordnerwechsel und
bei durch SSE ausgeloesten Auto-Reloads.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 12:00:15 +02:00
Stefan HackerandClaude Opus 4.6 9369c851a0 feat: Benutzerfreigabe - Weiterteilen-Recht + Lesezugriff wird erzwungen
Neues Berechtigungs-Modell fuer Benutzerfreigaben:

* FilePermission bekommt zwei neue Spalten:
  - can_reshare (bool): darf dieser Nutzer die Freigabe weiterverteilen?
  - granted_by (user_id): wer hat diese Freigabe erstellt?

* set_permission / create_share_link erlauben jetzt auch Nicht-Owner,
  sofern sie can_reshare haben. Dabei gilt:
  - Lesend + reshare -> kann nur lesend weiterteilen
  - Schreibend + reshare -> kann lesend ODER schreibend weiterteilen
  - Admin kann nur der Eigentuemer vergeben
  - Jeder Re-Sharer kann wiederum can_reshare weitergeben

* remove_permission: Owner kann alle Freigaben entfernen; Re-Sharer
  nur die von ihnen selbst erstellten.

* get_permissions: Owner sieht alle; Re-Sharer nur selbst-erstellte.

* list_files liefert my_permission + my_can_reshare pro Eintrag -
  Frontend kann Rename/Delete/Share-Buttons gezielt ein- und
  ausblenden statt blind alle anzuzeigen.

Frontend:
* Rename/Delete-Buttons nur fuer Write-Zugriff
* Share-Button nur fuer Owner oder Re-Sharer
* "darf weiterteilen" Checkbox neben Permission-Dropdown im Dialog
* Dropdown-Optionen nach eigenem Level gefiltert (Re-Sharer sieht
  keine hoeheren Stufen als seine eigene)
* Hinweis-Text "Du hast X - du kannst maximal X weiterteilen"

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 11:54:36 +02:00
Stefan HackerandClaude Opus 4.6 035923834b docs: README erklaert Reichweite des File Locks in Alltagssprache
Neuer Abschnitt "Was das Lock wirklich kann (und was nicht)" mit
Tabelle + Beispielszenario Adam/Anna. Zeigt Laien, dass das Lock
Web-GUI, Client und Upload schuetzt, aber nicht den Windows-
Explorer - und dass die Konflikt-Kopie das Sicherheitsnetz ist.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 11:36:07 +02:00
Stefan HackerandClaude Opus 4.6 23563622f8 feat: Lock-Badge + smartes Kontextmenue in lokaler Client-Ansicht
Die lokale Dateiliste im Client zeigt jetzt pro Datei ein 🔒-Badge
mit Nutzername wenn ausgecheckt (wie Server-Ansicht + Web-GUI).
browse_sync_folder zieht den Server-Tree bei jedem Aufruf und
korreliert via Journal-Lookup (oder .cloud-Metadaten) die lokale
Datei mit dem File-Lock-Status.

Rechtsklick-Menue reagiert jetzt auf den Lock-Status:
- Frei              -> "Auschecken (sperren)"
- Eigener/fremder   -> "Entsperren (einchecken)"
Neuer Tauri-Command lock_file_cmd fuer reines Sperren ohne Oeffnen.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 11:32:01 +02:00
Stefan HackerandClaude Opus 4.6 5afb87c9cd fix: SSE-Reload in FilesView etwas robuster
Beim Verbindungsaufbau (open-Event) wird jetzt ein initialer Reload
ausgeloest, damit eventuelle Changes in der Zeit zwischen letzter
Anzeige und SSE-Verbindung nicht verloren gehen. Gilt fuer eigene
und freigegebene Ordner gleichermassen (selbe FilesView-Komponente).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 11:21:10 +02:00
Stefan HackerandClaude Opus 4.6 8c7a14c38f fix: Server-Ansicht aktualisiert Lock-Status sofort via SSE
Die Server-Dateiliste im Client wartete bisher auf einen abgeschlossenen
Sync-Durchlauf, bevor Lock-Aenderungen anderer Nutzer sichtbar wurden.
Ausloeser von Events ohne Datei-Download (reine Lock/Unlock-Events)
landeten teils gar nicht in der UI.

Frontend hoert jetzt direkt auf das sse-event vom Backend und ruft
loadFileTree + loadLocalFiles auf - damit Lock-Icons im Server-Tree
in Echtzeit erscheinen/verschwinden.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 11:18:34 +02:00
Stefan HackerandClaude Opus 4.6 6c9daa5783 feat: Offline-Dateien werden beim erneuten Oeffnen wieder ausgecheckt
Bisher hat der Client nur beim ersten Oeffnen (.cloud-Platzhalter ->
Download) gesperrt. Nach dem Einchecken und erneutem Doppelklick
blieb die Datei ungesperrt, weil der Open-Pfad fehlte.

Neuer Tauri-Command open_offline_file loest die Server-Datei-ID
ueber das Sync-Journal auf, sperrt auf dem Server und oeffnet
lokal mit der Standard-App. Im lokalen Dateibrowser:
- Doppelklick auf eine bereits offline vorhandene Datei checkt sie
  nun aus und oeffnet sie (vorher: keine Reaktion)
- Rechtsklick-Menue hat "Oeffnen (auschecken)" fuer Offline-Dateien

Das Lock triggert wie gehabt notify_file_change -> SSE -> Web-UI
aktualisiert den Lock-Status sofort.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 11:09:06 +02:00
Stefan HackerandClaude Opus 4.6 88ab3c9b8d fix: Save-Endpoints feuern SSE-Event - Web-Edits synchronisieren sich
/files/<id>/save (Text/HTML/Spreadsheet) und der OnlyOffice-
Callback aktualisierten Inhalt + Checksum, riefen aber
notify_file_change nicht auf. Der Client bekam dadurch keinen
SSE-Trigger und merkte die neue Server-Version erst beim naechsten
30s-Fallback-Sync - wenn ueberhaupt.

Jetzt: beide Endpoints emittieren 'updated' an Owner + Share-
Empfaenger, Desktop- und Web-Clients reagieren sofort.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 10:56:51 +02:00
Stefan HackerandClaude Opus 4.6 e3cf7b1b64 fix: SSE-Broadcaster nur 1 Worker - sonst Events zwischen Prozessen verloren
Mit 2 Gunicorn-Workern laeuft der In-Memory-Broadcaster in zwei
voneinander getrennten Prozessen. Landet ein Lock-Request auf
Worker A und die SSE-Verbindung des Empfaengers auf Worker B, kommt
das Event nie beim Client an - genau deshalb klappte der Live-
Refresh bei freigegebenen Ordnern nicht zuverlaessig.

Jetzt: 1 Worker mit 32 Threads. Threads teilen Memory, der
Broadcaster ist fuer alle Verbindungen derselbe. Fuer mehr Durchsatz
waere Redis Pub/Sub noetig - hier reicht aber Single-Process-Modus.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 10:51:49 +02:00
Stefan HackerandClaude Opus 4.6 3af2bc3312 fix: SSE blockiert gunicorn-Worker - auf gthread umstellen
Mit 4 synchronen Workern hielt jede SSE-Verbindung dauerhaft einen
ganzen Worker besetzt. 4 offene Browser-Tabs -> alle anderen
Requests blockiert -> "Dateien laden dauert ewig".

Loesung: gthread worker-class mit 2 Workern x 16 Threads = 32
gleichzeitige Slots. Lang laufende SSE-Streams belegen nur je
einen Thread, regulaere Requests laufen unbeeintraechtigt.

nginx.example.conf: separater Location-Block fuer /api/sync/events
mit proxy_buffering off und 24h Read-Timeout, damit die Events
sofort durchkommen und die Verbindung nicht abbricht.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 10:33:02 +02:00
Stefan HackerandClaude Opus 4.6 5f905b4925 fix: Sync-Fehler "error decoding response body" + Server-Edits
Drei Probleme in einem:

1. create_folder/get_sync_tree parsten die Response auch bei HTTP-
   Fehlern als JSON. Bei 401/409/etc. kam "error decoding response
   body" statt der eigentlichen Fehlermeldung. Status wird jetzt
   zuerst geprueft, Body-Text wird bei Fehlern zurueckgegeben.

2. Ohne Journal-Eintrag und unterschiedlichen Hashes wurde vorher
   eine Konflikt-Kopie erstellt. Fuer Server-Edits aus dem Web-UI
   (wo der Client die Datei gar nie mit Journal erfasst hatte) war
   das falsch. Nextcloud-Ansatz: beim Erstkontakt Server
   autoritativ - Download statt Konflikt-Kopie.

3. run_sync_now uebernimmt neu konfigurierte sync_paths aus dem
   State, damit manuelle Syncs auch nach add_sync_path greifen.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 10:25:01 +02:00
Stefan HackerandClaude Opus 4.6 28fb1c47c2 feat: Web-GUI Live-Refresh via SSE
FilesView abonniert beim Mount die SSE-Events des Backends. Lock/
Unlock, Create, Update oder Delete durch andere Clients loest einen
debounced Reload der aktuellen Ordner-Ansicht aus. EventSource
reconnected automatisch; wird beim Unmount sauber geschlossen.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 10:21:00 +02:00
Stefan HackerandClaude Opus 4.6 b33e66cad9 fix: Freigegebene Ordner zeigen Dateien auch an
list_files filterte Kinder-Dateien nach owner_id=current_user, wodurch
in einem freigegebenen Ordner (der einem anderen User gehoert) keine
Dateien angezeigt wurden. Jetzt wird beim Betreten eines Ordners die
Zugriffsberechtigung geprueft; bei eigenem Ordner wie gehabt, bei
freigegebenem Ordner werden alle Kinder-Dateien gelistet.

_check_file_access laeuft jetzt auch den Ordner-Baum hoch, damit
eine Permission auf einem Vorfahren-Ordner automatisch Zugriff auf
alle Nachkommen gewaehrt.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 10:13:35 +02:00
Stefan HackerandClaude Opus 4.6 c63a52629d fix: Lock/Unlock-Buttons in FilesView - doppelter /api-Prefix
apiClient hat baseURL '/api' - die URL darf nicht nochmal mit /api
anfangen, sonst wird daraus /api/api/... und der Request geht ins
Leere.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 10:01:43 +02:00
Stefan HackerandClaude Opus 4.6 5ba007ef51 fix: Borrow-Checker in Background-Sync-Thread
Temporary-Drop-Order: MutexGuard hielt Referenz auf State-Binding,
das am Block-Ende schon fallen gelassen wurde. Zwischenvariable
erzwingt Drop der MutexGuard vor dem Binding.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 09:57:06 +02:00
Stefan HackerandClaude Opus 4.6 6aad986d78 fix: PDFs im Preview-iframe statt neuem Tab
Download-Endpoint unterstuetzt jetzt ?inline=1, wodurch
Content-Disposition auf inline statt attachment gesetzt wird.
PDF- und Bild-Preview nutzen diesen Parameter, damit der
Browser das PDF im Preview-Iframe rendert statt einen Download
auszuloesen. Normale Download-Buttons bleiben unveraendert.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 09:55:40 +02:00
Stefan HackerandClaude Opus 4.6 50385faa02 feat: Echtzeit-Sync via SSE + Journal-basierter 3-Wege-Vergleich
Desktop-Client komplett ueberarbeitet nach Nextcloud-Vorbild:
- Persistentes SQLite-Journal (journal.rs) speichert letzten bekannten
  Stand pro Datei - ueberlebt Client-Neustarts (Hauptbug behoben).
- Engine.rs neu: 3-Wege-Vergleich Local <-> Journal <-> Server mit
  sauberer Konflikt-Kopie (inkl. Username + Zeitstempel).
- Loesch-Propagation: Lokal geloeschte Dateien landen im Server-
  Papierkorb des Owners (auch bei Freigaben). Auf dem Server
  geloeschte Dateien werden lokal entfernt.
- Lock-Flow repariert: frischer Token bei jedem Call, Fehler-Feedback.

Echtzeit-Sync:
- Backend: SSE-Endpoint /api/sync/events mit In-Memory-Broadcaster.
  Events bei Create/Update/Delete/Lock/Unlock, Zustellung an Owner
  plus alle User mit Share-Permission.
- Client: persistente SSE-Verbindung mit Auto-Reconnect. Events
  triggern sofortigen Sync (<100ms). 30s-Polling bleibt als
  Fallback fuer Netzwerk-Aussetzer.

Weitere Fixes:
- /api/sync/tree filtert is_trashed=False (Papierkorb wird nicht
  mehr an Clients gesynct).
- Web-GUI: Lock/Unlock-Buttons pro Datei, Admin darf fremde Locks
  zwangsweise loesen. Rename/Delete disabled bei fremdem Lock.
- Lock-Check im Backend bei PUT/DELETE (423 Locked Response).
- Background-Sync nur noch einmal pro Prozess gestartet, liest
  sync_paths pro Iteration neu - add/remove wirkt sofort, kein
  Client-Neustart mehr noetig.
- Watcher werden pro Sync-Pfad individuell verwaltet.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 09:50:44 +02:00
Stefan HackerandClaude Opus 4.6 e65d330d1d docs: README File Locking Tabelle aktualisiert
- Feature-Beschreibung angepasst (manuelles Entsperren, auto-unlock)
- Neue File Locking Tabelle mit allen Szenarien
  (oeffnen, entsperren, vergessen, client beenden, admin)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 03:06:40 +02:00
Stefan HackerandClaude Opus 4.6 2bd8a2e1b5 feat: Heartbeat fuer Locks - vergessene Locks laufen nach 15 Min ab
Wenn jemand vergisst zu entsperren:
- Client laeuft -> Heartbeat alle 60s -> Lock bleibt aktiv
- Client geschlossen -> kein Heartbeat -> Lock laeuft nach 15 Min ab
- Laptop zugeklappt -> gleicher Effekt -> 15 Min -> frei

Tracking: locked_files Vec merkt sich welche Dateien wir gesperrt haben.
Heartbeat laeuft im Token-Refresh Thread mit (alle 60s Heartbeat,
alle 10 Min Token-Refresh).

Lock wird beim Oeffnen getrackt, beim Entsperren/Unmark-Offline entfernt.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 03:04:28 +02:00
Stefan HackerandClaude Opus 4.6 597dafc461 feat: File Lock beim Oeffnen + Entsperren per Rechtsklick
Beim Oeffnen einer .cloud-Datei:
- Download + Datei bleibt lokal (wie bisher)
- Lock wird auf dem Server gesetzt (andere sehen "gesperrt von X")
- Kein Auto-Unlock - Datei bleibt gesperrt bis manuell entsperrt

Rechtsklick im Datei-Browser auf Offline-Dateien:
- "Entsperren (Freigeben fuer andere)" - hebt den Lock auf
- "Nicht mehr offline" - .cloud zurueck + automatisch unlock

So bleiben Dateien gesperrt solange man daran arbeitet.
Wenn fertig: Rechtsklick -> Entsperren. Einfach und explizit.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 03:03:01 +02:00
Stefan HackerandClaude Opus 4.6 0845659c84 refactor: Auto-Close komplett entfernt - Nextcloud-Ansatz
.cloud oeffnen = Download + Datei bleibt als echte Datei (wie Nextcloud).
Aenderungen werden automatisch vom Watcher gesynct.
"Nicht mehr offline" per Rechtsklick im Datei-Browser -> .cloud zurueck.

Entfernt:
- Auto-Close Detection (is_file_in_use, OpenedFile tracking,
  Heartbeat, Lock/Unlock beim Oeffnen)
- Lock-Kommandos (lock_file_cmd, unlock_file_cmd)
- opened_files HashMap, locked_files Vec
- is_file_in_use Funktion
- ~100 Zeilen Code weniger

Beibehalten:
- Token-Refresh Thread (alle 10 Min)
- File-Locking API im Backend (wird vom Web-UI weiterhin genutzt)
- Watcher + Sofort-Sync
- mark_offline / unmark_offline Kommandos

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 03:01:02 +02:00
Stefan HackerandClaude Opus 4.6 763fd4d563 fix: Auto-Close erkennt Datei-Aktivitaet statt nur File-Lock
Problem: Notepad und die meisten Editoren halten keinen File-Lock.
is_file_in_use() fand sofort "nicht in Benutzung" und raeumte die
Datei auf bevor der User sie bearbeiten konnte.

Neuer Ansatz - drei Bedingungen muessen erfuellt sein:
1. Mindestens 30 Sekunden seit dem Oeffnen (Schutzzeit)
2. Kein File-Lock UND Dateigroesse unveraendert
3. Mindestens 2 Minuten seit der letzten Aenderung/Lock

Datei-Aktivitaet wird getrackt:
- Groesse aendert sich -> Timer zuruecksetzen
- File-Lock aktiv (Office) -> Timer zuruecksetzen
- Erst nach 2 Minuten Inaktivitaet -> Auto-Close

So funktioniert es fuer alle Programme:
- Office (haelt Lock): Lock verschwindet -> 2 Min warten -> Close
- Notepad (kein Lock): Letzte Groessenaenderung -> 2 Min -> Close
- Schnell oeffnen+schliessen: 30s Schutzzeit verhindert sofortiges Close

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 02:57:12 +02:00
Stefan HackerandClaude Opus 4.6 0714d96668 fix: .cloud Platzhalter werden bei Server-Aenderung aktualisiert
Vorher: Platzhalter wurde nur erstellt wenn er nicht existierte.
Wenn sich die Datei auf dem Server aenderte (neue Groesse, neuer
Checksum), blieb der Platzhalter mit den alten Metadaten.

Jetzt: Bei jedem Sync wird der Checksum im Platzhalter mit dem
Server-Checksum verglichen. Bei Unterschied -> Platzhalter neu
schreiben mit aktueller Groesse, Checksum und Datum.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 02:43:09 +02:00
Stefan HackerandClaude Opus 4.6 b6afc05148 fix: .cloud Oeffnen - besseres Error-Handling + Fallback-Dateiname
- Dateiname: Erst aus JSON "name" Feld, Fallback: .cloud von Dateiname strippen
- Alle Fehler werden jetzt gemeldet statt verschluckt (download, lock, open)
- open::that Fehler wird zurueckgegeben statt ignoriert
- Ausfuehrliches Logging: Pfade, Groesse, Lock-Status
- Pruefung ob Download-Datei existiert bevor geoeffnet wird

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 02:41:58 +02:00
Stefan HackerandClaude Opus 4.6 f71103185c fix: Borrow-Checker - sync_paths klonen vor der Iteration
Kann nicht &self.sync_paths iterieren und gleichzeitig &mut self
Methoden aufrufen. Clone der Liste loest den Konflikt.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 02:21:51 +02:00
Stefan HackerandClaude Opus 4.6 eb49a034ed fix: &self -> &mut self fuer Methoden die known_checksums aendern
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 02:19:09 +02:00
Stefan HackerandClaude Opus 4.6 2428dabed7 docs: README Sync-Logik Tabelle + aktualisierte Features
- Sync-Logik Tabelle: Checksum-Tracking erklaert (wer hat sich geaendert)
- Features aktualisiert: Intelligenter Sync, Konflikt-Erkennung,
  Auto-Unlock, Minimiert starten, .cloud Handler

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 02:17:59 +02:00
Stefan HackerandClaude Opus 4.6 9ede2d6bdb fix: Sync-Richtung korrekt - Checksum-Tracking statt Timestamps
Problem: Timestamps waren unzuverlaessig fuer die Sync-Richtung
(Download setzt lokale mtime auf 'jetzt', Timezone-Differenzen).
Offline-markierte Dateien wurden nie vom Server aktualisiert.

Loesung: known_checksums HashMap trackt den Server-Checksum
beim letzten Sync. Bei unterschiedlichen Checksums:

| Lokal geaendert | Server geaendert | Aktion |
|-----------------|------------------|--------|
| Nein | Ja | Server->Lokal (Download) |
| Ja | Nein | Lokal->Server (Upload) |
| Ja | Ja | KONFLIKT (lokale Kopie umbenennen, Server runterladen) |

Erster Sync (kein known_checksum): Server gewinnt immer (Download).
Danach wird jeder Server-Checksum gespeichert.

Betrifft: sync_virtual, sync_upload_new, sync_full_upload

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 02:15:53 +02:00
Stefan HackerandClaude Opus 4.6 b3da50e6ce fix: Server->Client Sync + File Locking repariert
Server->Client Sync:
- Server sendet Timestamps ohne Timezone (2026-04-11T12:49:24.735436)
- parse_from_rfc3339 braucht Timezone -> schlug still fehl
- Client dachte IMMER er sei neuer -> Upload statt Download
- Fix: parse_server_time() akzeptiert beides (mit/ohne Timezone)
- Probiert RFC3339, dann NaiveDateTime mit Microseconds, dann ohne

File Locking:
- open_cloud_file nutzte API-Clone vom SyncEngine (evtl. alter Token)
- Jetzt direkt state.api (immer aktueller Token nach Refresh)
- Lock wird zuverlaessig gesetzt beim Oeffnen von .cloud Dateien

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 02:05:10 +02:00
Stefan HackerandClaude Opus 4.6 a445256d86 fix: Alle Rust-Warnings bereinigt
- unused variables: Underscore-Prefix (_real_path, _had_changes, _file_id)
- dead_code: #[allow(dead_code)] fuer zukuenftige Methoden
  (open_cloud_file, close_cloud_file, get_changes, LockResponse, SyncChangesResponse)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 02:02:53 +02:00
Stefan HackerandClaude Opus 4.6 0d1fc67287 fix: use std::path::Path Import fuer is_file_in_use
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 01:55:56 +02:00
Stefan HackerandClaude Opus 4.6 b606ec9a4a docs: CHANGELOG.md - komplette Projekthistorie
Von der ersten Zeile Code bis zum Desktop Sync Client.
9 Versionen, 70+ Commits, alles an einem Tag.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 01:52:43 +02:00
Stefan HackerandClaude Opus 4.6 86545ca405 feat: Minimiert starten + kein Fenster-Popup bei .cloud Oeffnung
- .cloud Doppelklick oeffnet Datei im Hintergrund ohne das Client-
  Fenster aufzupoppen (war nervig)
- Neue Einstellung "Minimiert starten (direkt im System-Tray)"
  als Checkbox im Einstellungen-Bereich
- Wird in config.json gespeichert, bleibt bei Updates erhalten
- Bei aktiviertem Haken: Client startet unsichtbar im Tray,
  Sync laeuft im Hintergrund, Fenster nur per Tray-Doppelklick

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 01:50:09 +02:00
Stefan HackerandClaude Opus 4.6 e9638cc6ed fix: Lock verschwindet nicht mehr - Token-Refresh + laengerer Timeout
Problem: Lock verschwand nach 5 Minuten weil:
1. JWT-Token nach 15 Min ablief -> Heartbeat schlug still fehl
2. Server gab Lock nach 5 Min ohne Heartbeat frei

Fix Client:
- Token-Refresh alle 10 Minuten (vor dem 15-Min-Ablauf)
- Aktualisiert den Token in der shared API-Instanz
- Heartbeat nutzt immer den aktuellen Token

Fix Backend:
- Lock-Timeout von 5 auf 15 Minuten erhoeht
- Genug Puffer fuer Netzwerk-Probleme oder kurze Unterbrechungen

Timeline:
  0s    -> Lock + Heartbeat alle 10s
  600s  -> Token-Refresh
  900s  -> Lock wuerde erst jetzt ablaufen (15 Min ohne Heartbeat)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 01:45:52 +02:00
Stefan HackerandClaude Opus 4.6 b937351556 feat: Auto-Unlock wenn Datei geschlossen wird
Problem: Nach Oeffnen einer .cloud-Datei blieb die Sperre auf dem
Server bestehen, auch wenn Word/Excel geschlossen wurde.

Loesung: Hintergrund-Thread prueft alle 10 Sekunden ob geoeffnete
Dateien noch von einem Prozess benutzt werden:

Windows: Versucht exklusiven Schreibzugriff - wenn erfolgreich ist
  die Datei nicht mehr in Benutzung (Office gibt den Lock frei)
Linux/Mac: lsof prueft ob ein Prozess die Datei offen hat

Wenn Datei geschlossen:
1. Aenderungen werden zum Server hochgeladen
2. Server-Lock wird aufgehoben
3. .cloud Platzhalter wird neu erstellt (mit aktuellem Checksum)
4. Lokale Kopie wird geloescht
5. UI zeigt "Geschlossen + entsperrt: datei.cloud"

Tracking: opened_files HashMap speichert file_id -> Pfad + Cloud-Name
fuer alle via .cloud geoeffneten Dateien.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 01:44:40 +02:00
Stefan HackerandClaude Opus 4.6 4673423e2f fix: Sync vergleicht Timestamps - Server-Aenderungen nicht ueberschreiben
Problem: Wenn eine Datei auf dem Server geaendert wurde, hat der
Client sie trotzdem mit der lokalen (alten) Version ueberschrieben.
Der Sync hat nur Checksums verglichen aber nicht geprueft wer neuer ist.

Fix: Bei unterschiedlichen Checksums wird jetzt der Timestamp verglichen:
- Server neuer (updated_at > lokales modified) -> Download vom Server
- Lokal neuer (modified > Server updated_at) -> Upload zum Server
- Log zeigt "Server->Lokal" oder "Lokal->Server" statt nur "Aktualisiert"

Betrifft alle drei Sync-Methoden:
- sync_virtual (Offline-markierte Dateien)
- sync_upload_new (Virtual Mode Upload)
- sync_full_upload (Full Sync Upload)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 01:42:46 +02:00
Stefan HackerandClaude Opus 4.6 11fd11aa45 docs: README Desktop Sync Client komplett dokumentiert
- Features-Liste (Virtual Files, Multi-Sync, Offline, Locking, Tray etc.)
- Terminalserver-Tabelle (pro User eigene Instanz)
- Virtual Files vs. Full Sync Vergleichstabelle
- Einstellungen-Pfade pro OS
- Config bleibt bei Updates erhalten

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 01:30:08 +02:00
Stefan HackerandClaude Opus 4.6 b653f9657a fix: Single-Instance per User (Terminalserver-kompatibel)
Lock-File liegt in %APPDATA% (Windows) bzw ~/.config (Linux) -
das ist pro User verschieden. Auf Terminalservern kann jeder
User seine eigene Instanz haben.

Verbesserungen:
- Prueft ob der Prozess aus dem Lock-File noch lebt (PID-Check)
  statt nur ob die Datei existiert
- Windows: tasklist /FI "PID eq X"
- Linux: /proc/PID existiert?
- Stale Lock-Files (Prozess abgestuerzt) werden ueberschrieben
- Ohne .cloud Argument + andere Instanz laeuft -> sofort beenden
- Mit .cloud Argument + andere Instanz -> delegieren und beenden

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 01:28:39 +02:00
Stefan HackerandClaude Opus 4.6 4cc8de8a1a fix: Settings persistent (kein Keyring) + Single-Instance
Config-Persistenz:
- Passwort wird base64-kodiert in config.json gespeichert
  (statt OS-Keyring der beim Cross-Compile nicht funktioniert)
- Config-Pfad wird beim Laden/Speichern geloggt fuer Debugging
- Keyring-Dependency entfernt, base64 hinzugefuegt

Single-Instance:
- Lock-File in Config-Dir verhindert doppelte Instanz
- Wenn .cloud Datei doppelgeklickt wird und Client laeuft:
  Pfad wird in open_request.txt geschrieben und 2. Instanz beendet sich
- Laufende Instanz pollt open_request.txt und oeffnet die Datei
- Fenster wird automatisch in den Vordergrund geholt

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 01:27:03 +02:00
Stefan HackerandClaude Opus 4.6 c354682905 fix: Tray-Icon API kompatibel (kein Image::from_bytes)
Nutzt default_window_icon() statt Image::from_bytes das in
dieser Tauri-Version nicht existiert.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 01:15:02 +02:00
Stefan HackerandClaude Opus 4.6 ac5a0a3367 feat: Settings persistent + Auto-Login + Installer Update-Modus
Settings-Persistenz:
- Config wird in OS-AppData gespeichert
  (Windows: %APPDATA%/MiniCloud Sync/config.json,
   Linux: ~/.config/MiniCloud Sync/config.json,
   Mac: ~/Library/Application Support/MiniCloud Sync/config.json)
- Gespeichert werden: Server-URL, Username, Sync-Pfade
- Passwort wird im OS-Keychain gespeichert (Windows Credential Manager,
  macOS Keychain, Linux Secret Service) - nicht in der Config-Datei

Auto-Login:
- Beim Start wird gespeicherte Config geladen
- Wenn Credentials im Keychain vorhanden: automatischer Login
- Wenn Sync-Pfade konfiguriert: Sync startet sofort automatisch
- Bei Fehler: Login-Screen mit vorausgefuellten Feldern

Config ueberlebt Updates:
- Config liegt ausserhalb des Installationsverzeichnisses
- NSIS-Installer ueberschreibt nur App-Dateien, nicht AppData
- installMode: "both" erlaubt per-User und per-Machine Installation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 01:11:42 +02:00
Stefan HackerandClaude Opus 4.6 81574c8991 fix: Virtual Mode laedt neue lokale Dateien jetzt hoch
Problem: Im Virtual Mode wurden nur .cloud Platzhalter fuer
Server-Dateien erstellt, aber neue lokale Dateien wurden nie
hochgeladen. Der Watcher hat die Aenderung erkannt aber der
Sync hat sie ignoriert.

Fix: sync_upload_new() wird jetzt auch im Virtual Mode aufgerufen.
Scannt den lokalen Ordner nach Dateien die auf dem Server nicht
existieren und laedt sie hoch. Auch geaenderte lokale Dateien
(Checksum-Vergleich) werden aktualisiert. Gesperrte Dateien
werden zurueckgehalten.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 01:04:03 +02:00
Stefan HackerandClaude Opus 4.6 607d18a7e2 feat: Lokaler Datei-Browser mit Offline-Markierung + Kontextmenue
Datei-Browser im Client:
- Zeigt lokalen Sync-Ordner mit allen Dateien an
- Ordner navigierbar mit Breadcrumb
- Status pro Datei: ☁ Cloud (Platzhalter) / 📄 Offline (echte Datei)
- Badges: blaues "Cloud" oder gruenes "Offline"
- Cloud-Dateien zeigen Originalgroesse aus .cloud-Metadaten
- Aktualisiert sich automatisch nach jedem Sync

Rechtsklick-Kontextmenue:
- .cloud Datei: "Oeffnen (herunterladen)" + "Offline verfuegbar machen"
- Echte Datei: "Nicht mehr offline (Platzhalter)"
- Doppelklick auf Ordner = navigieren
- Doppelklick auf .cloud = herunterladen + oeffnen

Rust-Backend:
- browse_sync_folder: Listet lokale Dateien mit Status auf
  (is_cloud, is_offline, cloud_size aus JSON-Metadaten)
- Sortierung: Ordner zuerst, dann alphabetisch

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 01:02:21 +02:00
Stefan HackerandClaude Opus 4.6 adaa19a1ef fix: Durchsuchen-Button, Tray-Icon, Minimize statt Close, .cloud Handler
1. Durchsuchen-Button: dialog:allow-open Permission in capabilities
2. Tray-Icon: Nutzt das App-Icon (32x32.png) statt leer
3. Close = Minimize: Fenster wird versteckt statt App beendet,
   Doppelklick auf Tray-Icon oeffnet wieder
4. .cloud Datei-Handler:
   - fileAssociations in tauri.conf.json registriert .cloud Extension
   - NSIS-Installer registriert den Handler automatisch
   - Doppelklick auf .cloud -> App startet, laedt Datei runter,
     oeffnet mit Standard-App (Word/Excel/etc.)
   - Wenn App laeuft: Event wird emitted, Frontend verarbeitet es

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 00:57:18 +02:00
Stefan HackerandClaude Opus 4.6 505545f26c feat: Watcher triggert sofort Sync + Offline-Markierung pro Datei
Sofort-Sync statt 30s-Polling:
- Filesystem-Watcher erkennt lokale Aenderungen sofort
- 3 Sekunden Debounce (wartet ob noch mehr kommt)
- Dann sofortiger Sync-Trigger statt auf den naechsten 30s-Zyklus zu warten
- .cloud-Dateien werden vom Watcher ignoriert (kein Loop)
- Fallback: alle 60s Sync auch ohne Aenderungen (Server-Aenderungen holen)
- UI zeigt "→ Sync ausgeloest" bei Watcher-Trigger

Offline-Markierung:
- mark_offline: .cloud -> echte Datei runterladen, bleibt permanent lokal
- unmark_offline: echte Datei -> zurueck zu .cloud Platzhalter
- Offline-Dateien werden bei jedem Sync automatisch aktualisiert
  (Checksum-Vergleich in sync_virtual)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 00:44:57 +02:00
Stefan HackerandClaude Opus 4.6 e32a64ba83 fix: fehlende npm-Dependencies fuer Tauri-Plugins (dialog, notification)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 00:40:25 +02:00
Stefan HackerandClaude Opus 4.6 16d514f7f1 feat: Virtual Files, Multi-Sync-Pfade, Full Sync, Ordner-Dialog
Virtual Files System:
- .cloud Platzhalter-Dateien (JSON mit ID, Name, Groesse, Checksum)
- 0 Bytes Speicherverbrauch pro Datei
- Doppelklick auf .cloud -> Download + Oeffnen mit Standard-App + Lock
- Nach Schliessen: Sync zurueck, lokale Kopie entfernen, .cloud neu
- Offline-Markierung: Echte Dateien bleiben lokal (kein .cloud)
- Server-Dateien loeschen -> .cloud wird automatisch entfernt

Multi-Sync-Pfade (wie Nextcloud):
- Beliebig viele Server-Ordner auf lokale Ordner mappen
- z.B. /Projekte/2026 -> ~/Projekte oder /Shared/Team -> ~/Team
- Freigegebene Ordner von anderen Benutzern sync-bar
- Jeder Pfad hat eigenen Modus (Virtual oder Full)
- Hinzufuegen/Entfernen/Modus wechseln in der UI

Full Sync:
- Pro Sync-Pfad waehlbar: Virtual oder Full
- Full = alle Dateien lokal spiegeln (bidirektional)
- Virtual = .cloud Platzhalter (Standard)
- Klick auf Modus-Badge zum Umschalten

Ordner-Dialog:
- "Durchsuchen..." Button oeffnet nativen Ordner-Auswahl-Dialog
- Server-Ordner per Dropdown aus Dateibaum waehlen
- Ordner werden automatisch erstellt wenn noetig

UI:
- Sync-Pfade als Karten: ☁ /Server/Pfad → 📁 /Lokaler/Pfad
- Modus-Badge (Virtual/Full) mit Klick zum Wechseln
- Tray-Menue: "Jetzt synchronisieren" Eintrag

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 00:34:03 +02:00
Stefan HackerandClaude Opus 4.6 4662286959 fix: Windows Build laedt Setup-Installer hoch statt nackte .exe
Die nackte .exe braucht WebView2 separat installiert.
Der NSIS-Setup-Installer (nsis/*setup*.exe) installiert WebView2
automatisch mit. Jetzt wird der Setup bevorzugt hochgeladen.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 00:09:32 +02:00
Stefan HackerandClaude Opus 4.6 ba7e541260 docs: Docker aufraeumen - Speicher freigeben Anleitung
docker system prune, image prune, builder prune, system df

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 00:02:54 +02:00
Stefan HackerandClaude Opus 4.6 60e9f2699e docs: Docker-Cache loeschen Anleitung in README
build --no-cache, Image loeschen, Browser-Cache Hinweis

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 00:01:02 +02:00
Stefan HackerandClaude Opus 4.6 96d82967fc fix: build.sh zeigt klare Fehlermeldung bei falschem Upload-Token
403 -> Erklaerung dass BUILD_UPLOAD_TOKEN der SECRET_KEY vom Server sein muss
000 -> Server nicht erreichbar
Sonstige -> HTTP-Code + Response-Body

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 00:00:33 +02:00
Stefan HackerandClaude Opus 4.6 29cc00e284 fix: Client-Upload akzeptiert SECRET_KEY oder JWT_SECRET_KEY + Download in Settings
Upload-Auth:
- Akzeptiert jetzt sowohl SECRET_KEY als auch JWT_SECRET_KEY
  (BUILD_UPLOAD_TOKEN in Entwicklungs-.env kann einer von beiden sein)

Settings-View:
- Zeigt verfuegbare Desktop/Mobile Clients zum Download an
  (nur wenn mindestens ein Client vorhanden)
- Pro Client: Name, Dateiname, Download-Button

.env.example:
- Klarere Kommentare: "SECRET_KEY oder JWT_SECRET_KEY des Zielservers"

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 23:58:54 +02:00
Stefan HackerandClaude Opus 4.6 9391a58683 fix: build-output/ in .gitignore + aus Git entfernt
Binaries gehoeren nicht ins Repository.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 23:55:09 +02:00
Stefan HackerandClaude Opus 4.6 714ce1ae53 feat: Desktop-Client komplett - Auto-Sync, Watcher, Locking, Tray
Alles eingebunden was vorher nur als unused code existierte:

Auto-Sync:
- Nach erstem Sync laeuft alle 30s ein Delta-Sync im Hintergrund
- Status-Badge zeigt live: Synchronisiert / Synchronisiere... / Fehler
- Sync-Protokoll mit Timestamps

File-Watcher:
- Ueberwacht den Sync-Ordner auf lokale Aenderungen (Erstellt/Geaendert/Geloescht)
- Aenderungen werden im UI unter "Lokale Aenderungen" angezeigt
- Filtert temp/hidden files automatisch

File-Locking:
- lock_file_cmd / unlock_file_cmd Tauri-Kommandos
- Heartbeat-Thread sendet alle 60s Heartbeat fuer gesperrte Dateien
- locked_files Liste im State

System-Tray:
- Tray-Icon mit "Mini-Cloud Sync" Tooltip
- Rechtsklick-Menue: Oeffnen / Beenden
- "Oeffnen" zeigt das Hauptfenster

UI:
- Status-Badge mit Farbe (gruen=synced, orange=syncing, rot=error)
- Spinning-Icon waehrend Sync
- "Auto-Sync aktiv" Hinweis nach erstem Sync
- Sync-Ordner wird nach Start gesperrt (nicht mehr aenderbar)
- Lokale Aenderungen und Sync-Log mit Timestamps

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 23:54:54 +02:00
Stefan HackerandClaude Opus 4.6 8342cbfa17 fix: main.rs lib-Name auf minicloud_sync_lib korrigiert
War noch tauri_app_lib vom Template, muss minicloud_sync_lib heissen
(wie in Cargo.toml definiert).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 23:47:18 +02:00
Stefan HackerandClaude Opus 4.6 10e6211820 fix: Rust MutexGuard ueber await - delta_sync Send-Fehler
MutexGuard wird jetzt vor dem .await gedroppt (take + put back),
damit der Future Send-kompatibel ist wie Tauri es erfordert.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 23:42:28 +02:00
Stefan HackerandClaude Opus 4.6 ec3d4866e0 refactor: Build-Upload nutzt SECRET_KEY + Doku klargestellt
- Backend: Upload-Auth prueft SECRET_KEY statt eigenen Token
  (ein Token weniger zu verwalten)
- BUILD_UPLOAD_TOKEN in Entwicklungs-.env = SECRET_KEY vom Server
- .env.example: Klarer Kommentar dass CLOUD_URL + BUILD_UPLOAD_TOKEN
  NUR auf der Entwicklungsmaschine gesetzt werden, nicht auf dem Server
- README: Desktop Sync Client Abschnitt mit Build-Anleitung und
  Auto-Upload-Erklaerung

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 23:41:22 +02:00
Stefan HackerandClaude Opus 4.6 9a6aa7aadc feat: Client-Download-System + Auto-Upload nach Build
Backend:
- GET /api/clients - Verfuegbare Clients auflisten (oeffentlich)
- GET /api/clients/<platform>/download - Client herunterladen (oeffentlich)
- POST /api/clients/<platform>/upload - Build hochladen (BUILD_UPLOAD_TOKEN)
- Alte Version wird automatisch bei neuem Upload ersetzt
- Plattformen: linux, windows, mac, android, ios

Frontend:
- /clients - Download-Seite mit Grid aller verfuegbaren Clients
- Login-Seite zeigt "Desktop & Mobile Clients herunterladen" Link
  wenn mindestens ein Client verfuegbar ist

build.sh:
- Nach jedem Build wird der Client automatisch auf CLOUD_URL
  hochgeladen (wenn CLOUD_URL + BUILD_UPLOAD_TOKEN in .env gesetzt)
- Bestes Format pro Plattform: AppImage > .deb > Binary (Linux),
  .msi > .exe (Windows), .dmg (Mac), .apk (Android), .ipa (iOS)

.env.example:
- CLOUD_URL: Oeffentliche URL der Cloud-Instanz
- BUILD_UPLOAD_TOKEN: Auth-Token fuer Build-Upload

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 23:39:51 +02:00
Stefan HackerandClaude Opus 4.6 3ed5adc1e8 fix: sudo vor allen docker-Befehlen im build.sh
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 23:31:30 +02:00
Stefan HackerandClaude Opus 4.6 48a46cbc79 feat: Build-Script + Docker-Build fuer alle Plattformen
build.sh - baut Clients via Docker (kein lokales Setup noetig):
  ./build.sh linux        # Linux Desktop (.deb + .AppImage)
  ./build.sh windows      # Windows Desktop (.msi + .exe) Cross-Compile
  ./build.sh mac          # macOS Desktop (.dmg) - nur auf macOS
  ./build.sh android      # Android App (.apk) via Docker
  ./build.sh ios          # iOS App (.ipa) - nur auf macOS
  ./build.sh all-desktop  # Linux + Windows zusammen
  ./build.sh clean        # Build-Cache loeschen

Dockerfile.build: Multi-stage Container mit Rust, Node.js, Tauri-Deps,
  Windows Cross-Compile Tools (mingw-w64)

Output landet in build-output/ (gitignored)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 23:29:58 +02:00
Stefan HackerandClaude Opus 4.6 06ad65dbb3 feat: Desktop Sync Client (Tauri) - Grundgeruest
Tauri 2 Desktop-Client mit:

Rust-Backend:
- MiniCloudApi: Login, Token-Refresh, Upload, Download, Sync-Tree,
  Sync-Changes, File-Locking (Lock/Unlock/Heartbeat)
- SyncEngine: Full-Sync (Server-Tree vs. lokales Dateisystem),
  Delta-Sync (nur Aenderungen seit letztem Sync), bidirektionaler
  Abgleich mit SHA-256 Checksummen, Ordner-Erstellung,
  Lock-Status-Pruefung vor Upload, Konflikt-Erkennung
- FileWatcher: Filesystem-Watcher (notify crate) fuer Echtzeit-
  Erkennung lokaler Aenderungen, filtert temp/hidden files

Vue-Frontend:
- Login-Screen: Server-URL, Benutzername, Passwort
- Main-Screen: Sync-Ordner setzen, Sync starten, Dateiliste mit
  Lock-Status, Sync-Protokoll
- Dark-Mode Support

Tauri-Kommandos: login, set_sync_dir, start_sync, delta_sync,
  get_status, get_file_tree

Zum Bauen (Linux):
  sudo apt install libwebkit2gtk-4.1-dev libgtk-3-dev
  cd clients/desktop && npm install && npm run tauri build

Windows/Mac: Tauri Voraussetzungen installieren, dann gleicher Befehl

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 23:26:57 +02:00
Stefan HackerandClaude Opus 4.6 748537b9f5 feat: File Locking System (Ein-/Auschecken) + Konflikt-Email
Backend - FileLock Model + API:
- POST /files/<id>/lock - Datei auschecken (sperren)
- POST /files/<id>/unlock - Datei einchecken (entsperren)
- POST /files/<id>/heartbeat - "Datei noch offen" (alle 60s)
- GET /files/<id>/lock-status - Sperrstatus abfragen
- GET /files/locks - Alle aktiven Sperren auflisten
- Auto-Unlock: Kein Heartbeat seit 5 Min -> Sperre wird freigegeben
- 423 Locked wenn bereits von anderem User gesperrt
- Admin kann fremde Sperren aufheben

Dateiliste + Sync-API:
- Lock-Info (locked, locked_by, locked_at) pro Datei mitgeliefert
- Sync-Tree enthaelt Lock-Status fuer Desktop/Mobile-Clients

Web-UI:
- Schloss-Icon mit Benutzername bei gesperrten Dateien
- Tooltip: "Ausgecheckt von Adam seit 14:30"
- Gesperrte Dateien: "Oeffnen nicht moeglich" Toast-Meldung
  (eigene Sperren sind erlaubt)

Konflikt-Email an Admin:
- Wer hat die Konflikt-Kopie erstellt (Name + Email)
- Welche Datei (Name + Ordnerpfad)
- Name der Konflikt-Kopie
- Von wem gesperrt (Name + Email + seit wann)
- Erklaerungstext was passiert ist

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 23:20:55 +02:00
Stefan HackerandClaude Opus 4.6 33156f9431 feat: OnlyOffice Force-Save bei Ctrl+S + private IP erlauben
- forcesavetype in Editor-Config: Ctrl+S speichert sofort zurueck
  zum Server (statt erst beim Schliessen des Dokuments)
- ALLOW_PRIVATE_IP_ADDRESS + ALLOW_META_IP_ADDRESS fuer OnlyOffice
  damit Callbacks an interne Docker-IPs funktionieren

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 22:54:31 +02:00
Stefan HackerandClaude Opus 4.6 5f79ebe9b0 fix: OnlyOffice/Preview zeigt immer aktuelle Version (kein Cache)
Drei Cache-Ebenen gefixt:
- Vue Router: :key=fullPath erzwingt Komponenten-Neuaufbau bei
  jeder Navigation (kein Wiederverwenden alter Instanzen)
- Frontend: Cache-Bust Parameter an Preview + OnlyOffice API-Calls
- Backend: No-Cache Headers (Cache-Control, Pragma) auf Preview-Endpunkt

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 22:50:33 +02:00
Stefan HackerandClaude Opus 4.6 916971fc1b fix: OnlyOffice Cache - jedes Oeffnen laedt frische Version
Document-Key nutzt jetzt Timestamp statt Checksum, damit OnlyOffice
bei jedem Oeffnen die aktuelle Version vom Server laedt statt eine
gecachte alte Version anzuzeigen.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 22:47:17 +02:00
Stefan HackerandClaude Opus 4.6 bb73a8130a fix: Doppelter Route-Dekorator auf oo_download entfernt
Der @api_bp.route('/files/onlyoffice-callback') Dekorator war
versehentlich auf oo_download statt onlyoffice_callback gelandet.
Flask routete dadurch alle Callback-POSTs an oo_download, die dann
mit 'missing access_key argument' crashte (500 Error).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 22:41:35 +02:00
Stefan HackerandClaude Opus 4.6 9d138ecf1d fix: OnlyOffice Callback komplett neu - robust gegen 500 Errors
- Gesamter Callback in try/except gewrapped (gibt immer error:0
  zurueck, damit OnlyOffice nicht endlos retryt)
- JWT Body-Decoding mit graceful fallback auf Raw-Daten
- JWT-Header-Validierung entfernt (verursachte den 500 Crash)
- Download ohne extra JWT-Header (OnlyOffice-interne URLs
  brauchen das nicht)
- Ausfuehrliches Logging: Status, Key, Dateiname, Groesse
- Saubere Imports am Anfang der Funktion

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 22:34:24 +02:00
Stefan HackerandClaude Opus 4.6 9d1f4e117c fix: OnlyOffice Callback JWT-Validierung + Speichern
Problem: OnlyOffice sendete JWT-Token im Callback-Request und im
Body, unser Endpoint hat das ignoriert -> Speichern schlug fehl.

Fix:
- Callback validiert OnlyOffice JWT aus Authorization-Header
- Callback entpackt JWT-wrapped Body (OnlyOffice wraps den Body
  in einen JWT-Token wenn JWT_ENABLED=true)
- Download der gespeicherten Datei sendet JWT-Header mit
- Besseres Error-Logging mit Traceback

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 22:28:34 +02:00
Stefan HackerandClaude Opus 4.6 1f9b87900c fix: Dedizierter OnlyOffice Download-Endpunkt ohne JWT-Auth
Problem: OnlyOffice konnte Dateien nicht herunterladen weil unser
token_required-Decorator den Request ablehnte - OnlyOffice sendet
eigene Header die mit unserem JWT-System kollidieren.

Loesung: Eigener Endpunkt GET /files/oo-download/<access_key>
- Kein JWT noetig, stattdessen Einmal-Schluessel
- Schluessel wird beim Oeffnen des Editors generiert und in der DB gespeichert
- Schluessel enthaelt file_id + user_id, wird beim Download validiert
- OnlyOffice ruft diesen Endpunkt intern auf (http://minicloud:5000)
- Kein Token in der URL, keine JWT-Konflikte

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 22:24:09 +02:00
Stefan HackerandClaude Opus 4.6 c3c0610750 fix: OnlyOffice nutzt internes Docker-Netzwerk + langlebigen Token
Problem: OnlyOffice versuchte Dateien ueber die oeffentliche URL
herunterzuladen (http://selftestcloud...) und bekam 401 weil der
Access-Token nach 15 Min. ablief.

Fix:
- Download-URL und Callback-URL nutzen jetzt die interne Docker-URL
  (http://minicloud:5000) statt die oeffentliche URL
- Eigener 24h-Token fuer OnlyOffice Datei-Zugriff (statt des
  kurzlebigen User-Access-Tokens)
- ONLYOFFICE_INTERNAL_URL konfigurierbar (Default: http://minicloud:5000)

So bleibt der gesamte Dateizugriff zwischen OnlyOffice und Mini-Cloud
im Docker-Netzwerk - schneller und kein externer Roundtrip.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 22:19:30 +02:00
Stefan HackerandClaude Opus 4.6 35fddbfcbc docs: README OnlyOffice-Abschnitt aktualisiert
- Kein ONLYOFFICE_JWT_SECRET mehr, nutzt JWT_SECRET_KEY automatisch
- Nur noch ONLYOFFICE_URL in .env setzen
- Eigene Subdomain mit HTTPS als Pflicht beschrieben
- Schritte vereinfacht (4 statt 5)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 22:10:54 +02:00
Stefan HackerandClaude Opus 4.6 15211509a6 simplify: OnlyOffice nutzt JWT_SECRET_KEY, kein extra Secret
- OnlyOffice und Mini-Cloud teilen sich den gleichen JWT_SECRET_KEY
- ONLYOFFICE_JWT_SECRET komplett entfernt (aus .env, docker-compose, Backend, Frontend)
- docker-compose: OnlyOffice liest JWT_SECRET=${JWT_SECRET_KEY}
- In .env nur noch ONLYOFFICE_URL setzen, fertig
- Admin-GUI zeigt: URL + "JWT nutzt JWT_SECRET_KEY aus .env"

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 22:10:06 +02:00
Stefan HackerandClaude Opus 4.6 0dbeef7cd9 refactor: OnlyOffice Konfiguration nur ueber .env, nicht Admin-GUI
OnlyOffice URL und JWT Secret kommen jetzt ausschliesslich aus der
.env Datei (Umgebungsvariablen), nicht mehr aus der Admin-GUI:
- ONLYOFFICE_URL und ONLYOFFICE_JWT_SECRET in .env setzen
- docker-compose liest das gleiche Secret fuer den OnlyOffice-Container
- Eine Quelle der Wahrheit, kein Sync zwischen .env und DB noetig

Admin-GUI zeigt jetzt nur noch den Status an:
- Konfiguriert / Nicht konfiguriert (Tag)
- Aktuelle URL
- JWT Secret gesetzt / Fehlt (Tag)
- Setup-Anleitung mit .env Beispiel

Behebt: "Sicherheitstoken nicht korrekt" wenn OnlyOffice laeuft
aber JWT Secret nicht uebereinstimmt

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 22:08:07 +02:00
Stefan HackerandClaude Opus 4.6 5bf98302e3 fix: DATABASE_PATH und UPLOAD_PATH aus .env entfernt
Pfade werden jetzt automatisch gesetzt und nicht mehr in .env
ueberschrieben, was den Bug verursacht hatte:
- Docker: Dockerfile setzt /app/data/ als ENV-Default
- Entwicklung: Config nutzt CWD/data/ als Default

.env.example erklaert das mit Kommentar.
Optionale manuelle Pfade bleiben als auskommentierte Zeilen.

Auf dem Server: DATABASE_PATH und UPLOAD_PATH aus .env loeschen
(oder auskommentieren), dann docker-compose up --build -d

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 21:58:58 +02:00
Stefan HackerandClaude Opus 4.6 97cb4c7748 fix: Datenbank-Pfad in Docker - relative Pfade aus .env falsch aufgeloest
Problem: Nach Umstellung auf env_file in docker-compose wurden die
relativen Pfade (./data/minicloud.db) aus .env falsch aufgeloest.
basedir zeigte auf / statt /app, dadurch wurde eine neue leere DB
unter /data/ erstellt statt die bestehende unter /app/data/ zu nutzen.
Ergebnis: Alle User weg, Login unmoeglich.

Fix:
- config.py: _resolve_path nutzt Path.cwd() fuer relative Pfade
  (in Docker CWD=/app, in Dev CWD=backend/)
- .env.example: Absolute Docker-Pfade als Default
  (/app/data/minicloud.db statt ./data/minicloud.db)
  mit Kommentar fuer Entwicklungsumgebung

Auf dem Server muss die .env angepasst werden:
  DATABASE_PATH=/app/data/minicloud.db
  UPLOAD_PATH=/app/data/files

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 21:53:43 +02:00
Stefan HackerandClaude Opus 4.6 c23205d2a6 feat: OnlyOffice in docker-compose aktiviert
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 21:43:37 +02:00
Stefan HackerandClaude Opus 4.6 67790af95e fix: OnlyOffice Port-Mapping 8080:80 in docker-compose ergaenzt
nginx braucht Zugriff auf den OnlyOffice-Container um ihn per
HTTPS nach aussen weiterzuleiten (proxy_pass http://127.0.0.1:8080).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 21:42:16 +02:00
Stefan HackerandClaude Opus 4.6 3185b2d41c docs: .env.example + docker-compose + README komplett aktualisiert
- .env.example: OnlyOffice-Variablen (URL + JWT_SECRET) hinzugefuegt,
  FRONTEND_URL auf HTTPS-Beispiel geaendert
- docker-compose.yml: Nutzt env_file statt einzelner Variablen,
  alle Secrets kommen aus .env (eine Quelle der Wahrheit)
- README.md komplett ueberarbeitet:
  - Alle Features dokumentiert (Papierkorb, Share-Link-Typen,
    Drag&Drop, OnlyOffice, SFTP-Backup, Benachrichtigungen etc.)
  - Docker + nginx Reverse-Proxy Beispiel mit Let's Encrypt
  - OnlyOffice Setup-Anleitung (docker-compose + nginx + .env)
  - Alle Verwendungs-Abschnitte aktualisiert
  - Administration dokumentiert

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 21:27:13 +02:00
Stefan HackerandClaude Opus 4.6 fca2bc2d47 fix: OnlyOffice Docker-Setup ohne Port-Mapping + nginx-Beispielconfig
- docker-compose.yml: Kein ports-Mapping fuer OnlyOffice mehr
  (Zugriff nur ueber nginx mit HTTPS, nicht direkt ueber Port 8080)
- nginx.example.conf: Komplette Beispielkonfiguration fuer
  cloud.example.com + office.example.com mit Let's Encrypt
  - Unbegrenztes Upload-Limit (client_max_body_size 0)
  - CalDAV/CardDAV spezielle Location
  - WebSocket-Support vorbereitet
  - HTTP->HTTPS Redirect
- Admin-UI: Setup-Anleitung aktualisiert - erklaert nginx + HTTPS +
  Let's Encrypt Schritte, Hinweis dass die oeffentliche HTTPS-URL
  eingetragen werden muss (nicht die interne Docker-URL)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 21:23:31 +02:00
Stefan HackerandClaude Opus 4.6 216445d41b feat: OnlyOffice Document Server Integration + Preview ohne neuen Tab
OnlyOffice Integration:
- DOCX, XLSX, PPTX nativ im Browser bearbeiten (wie Google Docs)
- Automatische Erkennung: Wenn OnlyOffice konfiguriert ist, wird der
  vollwertige Editor geladen, sonst die einfache Vorschau als Fallback
- Backend: WOPI-aehnliche Endpunkte
  - GET /files/<id>/onlyoffice-config - Editor-Konfiguration
  - POST /files/onlyoffice-callback - Speicher-Callback von OnlyOffice
  - GET /files/onlyoffice-status - Verfuegbarkeits-Check
- JWT-Signierung fuer sichere Kommunikation mit OnlyOffice
- Dokument-Key basiert auf file_id + checksum (Cache-Invalidierung)

Admin-Einstellungen:
- OnlyOffice URL + JWT Secret konfigurierbar
- Setup-Anleitung direkt in der UI (docker-compose auskommentieren)

docker-compose.yml:
- OnlyOffice Document Server als optionaler Service (auskommentiert)
- Einfach auskommentieren fuer volle Office-Bearbeitung

Preview:
- Oeffnet sich jetzt innerhalb der App (kein neuer Tab)
- Zurueck-Button in der Toolbar

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 21:19:17 +02:00
Stefan HackerandClaude Opus 4.6 a2ded7f97c feat: Office-Preview im neuen Tab + DOCX/XLSX/Text bearbeitbar
Preview-System komplett ueberarbeitet:
- Neuer Tab: Doppelklick oder Auge-Icon oeffnet Vorschau im neuen Tab
- Dedizierte PreviewView mit Toolbar (Zurueck, Bearbeiten, Speichern, Download)
- Token wird als Query-Parameter an Preview/Download-URLs angehaengt (kein 404 mehr)

Unterstuetzte Formate:
- PDF: Inline-Anzeige im iFrame
- Bilder: Zentrierte Anzeige mit Schatten
- DOCX: HTML-Darstellung mit Formatierung (Headings, Bold, Italic, Tabellen)
- XLSX: Tabellen-Ansicht mit Sheet-Tabs
- PPTX: Folien-Navigation (vor/zurueck)
- Text/Code: Monospace mit Syntax

Bearbeitung (neu!):
- DOCX: ContentEditable-Editor, Bold/Italic/Headings bleiben erhalten,
  Speichern schreibt zurueck als .docx (python-docx)
- XLSX: Direkt in der Tabelle bearbeiten (Zellen anklicken),
  Speichern schreibt zurueck als .xlsx (openpyxl)
- Text/Code: Textarea-Editor, Speichern als UTF-8

Backend: POST /files/<id>/save mit type-spezifischer Konvertierung
- html -> DOCX (Headings, Bold/Italic/Underline erhalten)
- spreadsheet -> XLSX (Zahlen werden automatisch konvertiert)
- text -> direkt als Datei

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 21:07:59 +02:00
Stefan HackerandClaude Opus 4.6 67118a34fd fix: Share-View Loeschen nutzt jetzt Papierkorb statt hartem Delete
- share_delete_file nutzt _trash_recursive() statt db.session.delete()
- Geloeschte Dateien aus Share-Links landen im Papierkorb des Eigentümers
- Share-Dateiliste filtert getrashte Dateien aus (is_trashed=False)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 20:53:47 +02:00