Stift-Icon neben Freigabe oeffnet Inline-Editor mit Select "Lesen" /
"Lesen+Schreiben" (analog zu Kontakten/Kalender).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Analog zu Kontakten/Kalender: ab 2 Zeichen werden Vorschlaege per
/users/search eingeblendet.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- /api/settings gibt zusaetzlich timezone, timezone_abbr, server_time,
ntp_server zurueck (alle read-only, aus Config/ENV).
- AdminView zeigt neuen Abschnitt "System-Zeit" mit Zeitzone, aktueller
Server-Zeit und NTP-Server samt Hinweis "wird in der .env festgelegt".
- .env.example: Liste gaengiger TZ-Werte mit Link zur IANA-Vollliste.
- README.md: neuer Abschnitt "Zeitzone & NTP" mit Werte-Tabelle.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Kontakte:
- Mehrfachauswahl in der Liste (Checkbox-Spalte) mit Bulk-Loeschen
- Export als Sammel-vCard (.vcf), als ZIP mit Einzel-vCards oder als CSV
- Import aus vCard (mehrere im File moeglich) oder CSV; Match per UID,
bestehende Kontakte werden aktualisiert
Kalender:
- Export als iCalendar (.ics) oder CSV
- Import aus .ics oder CSV; bestehende Termine via UID aktualisiert
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Browser/Kalender-App fragen sonst nach Benutzername+Passwort - der
Benutzername muss leer bleiben.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Checkbox-Spalte plus Header-Checkbox "Alle". Bulk-Aktion mit
Bestaetigung loescht ausgewaehlte Termine; Read-Only-Eintraege
werden uebersprungen.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Titel reagiert reaktiv auf Login/Logout. Favicon ist die Wolke aus
der Sidebar (pi-cloud-Style).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Anrede: Herr/Frau/Divers (fest), Titel: Dr./Prof./Dipl.-Ing./... (editierbar).
Beim Speichern werden beide zu vCard-PREFIX zusammengesetzt, beim Laden
wieder aufgesplittet.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Anrede/Suffix/PLZ etc. hatten max-width-Container, das InputText darin
behielt aber die Default-Breite und ueberlief. Globale CSS-Regel sorgt
nun dafuer, dass jedes Input/Select seinen Field-Container ausfuellt.
field-row wrappt auf schmalen Dialogen.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- caldav.py sendet SSE-Notifications bei Event-PUT/DELETE und Kalender-Loeschung,
damit das Web-UI auch auf Aenderungen aus DAVx5 sofort reagiert.
- FullCalendar navLinks: Klick auf Tagesnummer im Monatsraster wechselt in
die Tagesansicht.
- Neue Listen-Ansicht mit Volltext-Suche, Datumsbereich, Kalender-Filter,
Sortierung nach Datum/Titel und Loeschen-Button pro Zeile.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Checkbox pro Eintrag, "Alle auswaehlen" oben und roter Loesch-Button mit
Anzahl. Sicherheitsabfrage vor dem Loeschen.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Kalender und Adressbuecher teilten sich den gleichen Home-Set
(/dav/<user>/). DAVx5 hat bei Depth-1-PROPFIND beide Collection-
Typen angezeigt und mangels bekanntem Resourcetype als
"DEFAULT_TASK_CALENDAR_NAME"-Kacheln gelistet.
Loesung:
* calendar-home-set zeigt auf /dav/<user>/calendars/
* addressbook-home-set zeigt auf /dav/<user>/addressbooks/
* Beide Pfade sind eigene Container-Collections - PROPFIND Depth 1
liefert nur den jeweils passenden Typ
* /dav/<user>/ selbst gibt bei Depth 1 keine Kinder mehr zurueck,
Clients folgen den Home-Sets
* Die konkreten URLs cal-<id> / ab-<id> liegen weiterhin unter
/dav/<user>/ (keine Breaking Change fuer existierende Clients;
nur die Discovery-URL aendert sich)
Frontend:
CalendarView + ContactsView zeigen als Auto-Discovery-URL nur
noch den Hostname - PROPFIND auf / funktioniert ja jetzt. Die
Direkt-URL bleibt vollstaendig mit /dav/<user>/cal-<id> bzw.
ab-<id> fuer Clients die das brauchen.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Komplette Kontakte-Ueberarbeitung analog zum Kalender-Ausbau.
Backend-Model:
* AddressBook: color (pro Buch), ausserdem Per-User-Color via
AddressBookShare.color wie bei CalendarShare.
* Contact: volle Outlook-artige Struktur - prefix/first/middle/
last/suffix, display_name, nickname, organization, department,
job_title, birthday, anniversary, notes, photo sowie JSON-
Spalten fuer mehrfach vorhandene Felder (emails, phones,
addresses mit allen Adressteilen, websites, impp, categories).
Backend-API:
* REST CRUD uebernimmt die neuen Felder und generiert vCard 3.0
als Source of Truth fuer CardDAV. Voller vCard-Parser +
-Builder mit Escape/Unescape, TYPE-Parametern, Line-Folding.
* Neuer Endpoint PUT /addressbooks/<id>/my-color - persoenliche
Farbe pro Buch ohne den Besitzer zu beeinflussen.
* SSE-Events vom Typ 'addressbook' an Besitzer + alle Share-
Empfaenger bei jeder Aenderung.
CardDAV-Server (backend/app/dav/carddav.py):
* Volle Discovery via principal - addressbook-home-set wird
neben calendar-home-set annonciert.
* PROPFIND/REPORT/GET/PUT/DELETE/MKCOL fuer
/dav/<user>/ab-<id>/ und /<...>/{uid}.vcf
* addressbook-query + addressbook-multiget REPORTs
* ETag-basierte Konfliktpruefung via If-Match/If-None-Match
Frontend (ContactsView.vue):
* Komplett neuer Editor mit vier Tabs: Allgemein (Name, Org),
Kommunikation (Emails/Phones/Websites/IMPP dynamisch),
Adressen (mehrere mit allen Teilen), Details (Geburtstag,
Jahrestag, Kategorien, Notizen).
* Avatar mit Fotoauswahl oder Initialen-Farbkreis.
* Kalender-Sharing-Flow 1:1 uebernommen: Autocomplete fuer
Benutzersuche, Share-Liste mit Stift zum Bearbeiten, Muelleimer
zum Entfernen, Per-User-Farbe, CardDAV-URL-Info-Block pro
Adressbuch, Live-Refresh via SSE.
* Suche durchsucht Displayname, E-Mail und Firma.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>
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>
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>
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>
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>
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>
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>
* 📅-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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
- 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>
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>
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>
Papierkorb:
- Dateien/Ordner werden beim Loeschen in den Papierkorb verschoben
(Soft-Delete) statt sofort geloescht
- Papierkorb-Seite in der Sidebar mit Tabelle aller geloeschten Elemente
- Pro Element: Wiederherstellen (am Originalort) oder endgueltig loeschen
- "Papierkorb leeren" Button loescht alles unwiderruflich
- Backend: is_trashed, trashed_at, original_parent_id Felder im File-Model
- Getrashte Dateien erscheinen nicht in der normalen Dateiliste
Bestaetigungsdialoge (vorher fehlend):
- Kontakte: "Moechtest du XY wirklich loeschen?"
- Kalender Events: Bestaetigung vor dem Loeschen
- Kalender: Bestaetigung vor dem Loeschen (mit Hinweis auf Events)
- E-Mail Nachrichten: Bestaetigung mit Betreff-Vorschau
- Share-Link Dateien: Bestaetigung beim Loeschen aus geteiltem Ordner
- Admin SFTP-Backup-Ziele: Bestaetigung
- Admin Email-Konten: Bestaetigung
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Problem: window.location.href sendet keinen Authorization-Header,
daher scheiterten alle direkten Downloads (Dateien + Ordner-ZIP)
mit 'Token fehlt'.
Loesung:
- Backend: token_required akzeptiert jetzt auch ?token=... als
Query-Parameter (Fallback wenn kein Authorization-Header)
- Frontend: downloadUrl() haengt den Access-Token automatisch als
Query-Parameter an die Download-URL an
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
pi-file-zip gibt es in PrimeIcons nicht, daher wurde kein Icon
angezeigt. Ersetzt durch pi-box in Datei-Browser und Share-View.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>
Ordner-Download:
- Ordner koennen jetzt als ZIP heruntergeladen werden (rekursiv
mit allen Unterordnern und Dateien)
- ZIP-Icon statt Download-Icon bei Ordnern in der Dateiliste
- Backend erstellt ZIP mit ZIP_DEFLATED und allowZip64 fuer grosse Ordner
Share-Status visuell:
- Share-Button zeigt gruenes Personen-Icon (pi-users) wenn die Datei/
der Ordner bereits Freigaben hat (Links oder Benutzer-Berechtigungen)
- Normales Share-Icon (pi-share-alt) wenn keine Freigaben existieren
- Backend liefert has_shares und has_permissions pro Datei mit
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Geteilte Ordner koennen jetzt komplett durchnavigiert werden:
- Klick auf einen Unterordner oeffnet dessen Inhalt
- Breadcrumb-Navigation: Root > Unterordner > Unter-Unterordner
mit Klick zurueck auf jede Ebene
- Ordner-Zeilen haben Hover-Effekt und Cursor-Pointer
Backend:
- GET /share/<token>/files?parent_id=X - Unterordner auflisten
- Sicherheitspruefung: parent_id muss innerhalb des geteilten
Ordners liegen (_is_inside_shared_folder traversiert den Baum)
- Breadcrumb wird serverseitig berechnet
- Download + Delete erlauben jetzt Dateien in jeder Tiefe
(nicht nur direkte Kinder)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Share-Links fuer Ordner verhalten sich jetzt je nach Berechtigung:
read (Nur Lesen):
- Zeigt alle Dateien im Ordner mit Name, Groesse, Typ
- Download-Button pro Datei
- Kein Upload, kein Loeschen
write (Lesen+Schreiben):
- Zeigt alle Dateien im Ordner
- Download-Button pro Datei
- Loeschen-Button pro Datei
- Upload-Zone (Drag & Drop + Button)
- Nach Upload wird Dateiliste automatisch aktualisiert
upload_only (Nur Upload):
- Kein Dateilisting, kein Ordnername sichtbar
- Nur Upload-Zone
Backend-Endpunkte:
- GET /share/<token>/files - Dateien im geteilten Ordner auflisten
- GET /share/<token>/files/<id>/download - Einzeldatei herunterladen
- DELETE /share/<token>/files/<id> - Datei loeschen (nur write)
- Alle Endpunkte pruefen Passwort, Ablaufdatum und Berechtigung
- Dateien muessen direkte Kinder des geteilten Ordners sein (kein Ausbruch)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Alle Buttons in der Datei-Tabelle haben jetzt @click.stop
(Download, Teilen, Umbenennen, Loeschen) damit die DataTable
den Click nicht verschluckt
- Debug-Logging in createShare() um Frontend-Fehler sichtbar zu machen
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>