feat(calendar): Phase 1 – CalDAV lesend und schreibend, ein Kalender pro Nutzer
Neues, eigenständiges Modul internal/calendar: implementiert caldav.Backend (emersion/go-webdav) gegen zwei neue Tabellen (cal_calendars, cal_objects). Endpunkt /caldav/ mit eigener Basic Auth (nur App-Passwörter, wie /dav), plus /.well-known/caldav für die automatische Einrichtung nach RFC 6764. Gegen echte Container getestet (nicht nur go build): Discovery-Kette Principal -> Home-Set -> automatisch angelegter Standardkalender, PUT/GET/DELETE eines Termins, REPORT mit Zeitraumfilter (Treffer und Nicht-Treffer), If-Match/If-None-Match-Vorbedingungen (412), und dass ein fremder Nutzer auf einen Kalender-Pfad mit 404 statt 403 abgewiesen wird. Zwei Fallen unterwegs gefunden und dokumentiert: - go-webdav vergleicht von CurrentUserPrincipal/CalendarHomeSetPath zurückgegebene Pfade direkt gegen r.URL.Path (inklusive Prefix) und bestimmt den Ressourcentyp allein an der Segmentzahl dahinter – der Nutzername beim Principal steht deshalb in einem Segment (principals-max), nicht als Unterpfad. - chi kennt REPORT/MKCALENDAR nicht von Haus aus (nur PROPFIND & Co. waren für /dav bereits registriert) und hätte sie sonst mit 405 abgewiesen, bevor der CalDAV-Handler überhaupt lief. Migration 000021 nur mit CREATE TABLE IF NOT EXISTS, wie in kalender-plan.md festgelegt. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
e44bed0a34
commit
87788817f8
11 files changed
+819
-1
No files matched your search
@@ -0,0 +1,41 @@
|
||||
// Package calendar ist ein eigenständiges Modul, kein Kernbestandteil:
|
||||
// CalDAV für Termine und Aufgaben. Es importiert nichts aus files, sharing
|
||||
// oder admin – nur auth und acl, wie jeder andere Bereich auch. Ist es
|
||||
// abgeschaltet, gibt es keine Route und keinen Menüpunkt; die Tabellen
|
||||
// bleiben dann einfach ungenutzt liegen. Siehe kalender-plan.md.
|
||||
package calendar
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// Calendar ist eine Sammlung von Terminen/Aufgaben – das, was ein Client als
|
||||
// einen Kalender in seiner Liste zeigt.
|
||||
type Calendar struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
OwnerID uuid.UUID `json:"owner_id"`
|
||||
Name string `json:"name"`
|
||||
Color string `json:"color"`
|
||||
Description string `json:"description"`
|
||||
SupportsTodo bool `json:"supports_todo"`
|
||||
CTag int64 `json:"ctag"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
// Object ist ein einzelner Termin oder eine Aufgabe. Data ist die
|
||||
// vollständige .ics-Datei, unverändert wie vom Client geschickt – siehe
|
||||
// kalender-plan.md, Abschnitt "Felder".
|
||||
type Object struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
CalendarID uuid.UUID `json:"calendar_id"`
|
||||
UID string `json:"uid"`
|
||||
Component string `json:"component"` // "VEVENT" | "VTODO"
|
||||
Data string `json:"-"`
|
||||
ETag string `json:"etag"`
|
||||
DTStart *time.Time `json:"dtstart,omitempty"`
|
||||
DTEnd *time.Time `json:"dtend,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
Reference in new issue
Block a user