Commit Graph

16 Commits

Author SHA1 Message Date
Stefan Hacker 4d67819cac feat: Vor-/Nachname, geteilte Listen zeigen Eigentuemer
Backend:
- User.first_name / User.last_name (nullable, Auto-Migrate fuegt sie an)
  full_name/display_name als Properties + in to_dict
- TaskList.owner-Relationship ergaenzt (fehlte, daher wurden geteilte
  Listen beim Empfaenger nicht korrekt aufgeloest)
- /auth/me GET + PUT (Profil bearbeiten: Vorname, Nachname, E-Mail)
- /users/search findet jetzt auch nach Vor-/Nachname und liefert
  full_name/display_name mit
- list_tasklists/list_calendars/list_addressbooks liefern
  owner_full_name und owner_display_name

Frontend:
- Sidebars bei Kontakten/Kalender/Aufgaben: "(geteilt von <Voller Name>)"
  mit Fallback auf Username
- User-Search-Popup zeigt vollen Namen neben Username
- SettingsView: Vorname/Nachname/E-Mail bearbeiten

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 15:34:22 +02:00
Stefan Hacker ba3e619963 feat: Aufgaben (Tasks) mit CalDAV VTODO-Sync
Neuer Menuepunkt "Aufgaben" unterhalb Kontakte.

Backend:
- TaskList + Task + TaskListShare Models
- REST-API: CRUD, Teilen, my-color, Import/Export (.ics mit VTODO, CSV)
- CalDAV: Task-Listen tauchen als Calendar-Collection mit
  supported-calendar-component-set=VTODO im autodiscovery auf
- PROPFIND/REPORT/GET/PUT/DELETE/PROPPATCH/MKCOL fuer /dav/<user>/tl-<id>/
- SSE-Notifications bei Aenderungen

Frontend:
- TasksView mit Listen-Sidebar, Suche, "Erledigte ausblenden"
- Mehrfachauswahl + Bulk-Loeschen, Status-Toggle per Checkbox
- Editor mit Titel/Beschreibung/Faellig/Prioritaet/Status/Fortschritt
- Teilen, Farbe persoenlich anpassen, Import/Export

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 15:07:06 +02:00
Stefan Hacker 9c102823e4 feat: Kontakte mit Outlook-Feldern + CardDAV-Server + Sharing
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>
2026-04-12 15:16:01 +02:00
Stefan Hacker 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 Hacker 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 Hacker 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 Hacker 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 Hacker 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 Hacker 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 Hacker 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 Hacker 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 Hacker 82f3091f2e feat: Papierkorb + Bestaetigungsdialoge bei allen Loeschaktionen
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>
2026-04-11 20:50:19 +02:00
Stefan Hacker 116c33a7dc feat: Share-Links mit Berechtigungen (Lesen / Lesen+Schreiben)
Share-Links haben jetzt ein permission-Feld (read/write):

- read (Standard): Nur Download erlaubt, kein Upload, kein Aendern
- write: Download + Upload in Ordner erlaubt

Backend-Absicherung:
- POST /share/<token>/upload prueft permission == 'write', gibt 403
  bei read-only Links zurueck
- GET /share/<token>/info gibt permission + upload_allowed zurueck
- ShareLink-Model hat neues permission-Feld (default: 'read')

Frontend Share-Dialog:
- Dropdown "Berechtigung" beim Erstellen von Links
  (Nur Lesen / Lesen+Hochladen)
- Bestehende Links zeigen Berechtigungslevel an

Frontend ShareView:
- Upload-Zone nur sichtbar wenn upload_allowed == true
- Bei read-only Links: kein Drag & Drop, kein Upload-Button

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 18:39:38 +02:00
Stefan Hacker d42d6d5d96 feat: SFTP-Backup mit Scheduler, Versionierung und Multi-Target
Mehrere SFTP-Backup-Ziele konfigurierbar mit:
- Host, Port, Benutzername, Passwort, Remote-Pfad
- Konfigurierbares Intervall (15 Min. bis woechentlich oder deaktiviert)
- Maximale Anzahl aufbewahrter Versionen (aeltere werden automatisch geloescht)
- Aktiv/Inaktiv-Toggle pro Ziel

Features:
- Automatischer Hintergrund-Scheduler prueft alle 60 Sekunden ob
  Backups faellig sind und fuehrt sie aus
- Manuelles Backup per Klick ("Jetzt sichern")
- SFTP-Verbindungstest-Button
- Versionen-Dialog: Alle Backup-Versionen auf dem SFTP-Server auflisten
  mit Groesse und Datum
- Restore direkt von SFTP: Version auswaehlen -> wird heruntergeladen
  und ueber die bestehende DB-Merge-Logik wiederhergestellt
- Chunked Upload zum SFTP in 16MB-Bloecken (fuer grosse Backups)
- Status-Anzeige: Letztes Backup, Erfolg/Fehler, Nachricht

Backend: BackupTarget Model, SFTP-Service (paramiko), Backup-Scheduler
API: /admin/backup/targets CRUD, /test, /run, /versions, /restore

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 18:07:28 +02:00
Stefan Hacker 35099de2c5 feat: Share-Dialog Fix, User-Sharing, Admin-Benutzerverwaltung, Registrierungs-Toggle
- Fix: Share-Dialog oeffnet sich jetzt auch bei bereits geteilten Dateien
- Neu: Dateien/Ordner direkt mit anderen Benutzern teilen (Lesen/Schreiben/Admin)
- Neu: Benutzersuche im Share-Dialog, bestehende Freigaben anzeigen/entfernen
- Neu: Admin kann Benutzer ueber die Weboberflaeche anlegen
- Neu: Admin kann Benutzer bearbeiten (Rolle, Quota, aktiv/inaktiv) und loeschen
- Neu: Schieberegler fuer oeffentliche Registrierung in den Admin-Einstellungen
- Neu: Register-Link auf Login-Seite nur sichtbar wenn Registrierung erlaubt
- Neu: Register-Seite leitet um wenn Registrierung deaktiviert
- Neu: AppSettings-Model fuer persistente App-Konfiguration
- Neu: /api/users/search Endpunkt fuer Benutzersuche in Share-Dialogen

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 15:26:04 +02:00
Stefan Hacker 62f550c373 feat: Mini-Cloud Plattform - komplette Implementierung Phase 0-8
Selbstgehostete Web-Cloud mit Dateiverwaltung, Kalender, Kontakte,
Email-Webclient, Office-Viewer und Passwort-Manager.

Backend (Flask/Python):
- JWT-Auth mit Access/Refresh Tokens, Benutzerverwaltung
- Dateien: Upload/Download, Ordner, Berechtigungen, Share-Links
- Kalender: CRUD, Teilen, iCal-Export, CalDAV well-known URLs
- Kontakte: Adressbuecher, vCard-Export, Teilen
- Email: IMAP/SMTP-Proxy, Multi-Account
- Office-Viewer: DOCX/XLSX/PPTX/PDF Vorschau
- Passwort-Manager: AES-256-GCM clientseitig, KeePass-Import
- Sync-API fuer Desktop/Mobile-Clients
- SQLite mit WAL-Modus

Frontend (Vue 3 + PrimeVue):
- Datei-Explorer mit Breadcrumbs und Share-Dialogen
- Monatskalender mit Event-Verwaltung
- Kontaktliste mit Adressbuch-Sidebar
- Email-Client mit 3-Spalten-Layout
- Passwort-Manager mit TOTP und Passwort-Generator
- Admin-Panel, Settings, oeffentliche Share-Seite

Docker: Multi-Stage Build, Bind Mounts (keine Volumes)

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