From 0ea114ec795a19dea210f374da3aa8b7bd7669e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= <1005065+DeepDiver1975@users.noreply.github.com> Date: Thu, 8 Feb 2024 17:08:41 +0100 Subject: [PATCH] caldav: add MKCOL support --- caldav/elements.go | 7 +++++++ caldav/server.go | 26 +++++++++++++++++++++++++- caldav/server_test.go | 4 ++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/caldav/elements.go b/caldav/elements.go index 255ab7a..5759f31 100644 --- a/caldav/elements.go +++ b/caldav/elements.go @@ -228,3 +228,10 @@ func (r *reportReq) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { return d.DecodeElement(v, &start) } + +type mkcolReq struct { + XMLName xml.Name `xml:"DAV: mkcol"` + ResourceType internal.ResourceType `xml:"set>prop>resourcetype"` + DisplayName string `xml:"set>prop>displayname"` + // TODO this could theoretically contain all addressbook properties? +} diff --git a/caldav/server.go b/caldav/server.go index b1ce9ad..f69a0bd 100644 --- a/caldav/server.go +++ b/caldav/server.go @@ -30,8 +30,11 @@ type PutCalendarObjectOptions struct { // Backend is a CalDAV server backend. type Backend interface { CalendarHomeSetPath(ctx context.Context) (string, error) + + CreateCalendar(ctx context.Context, calendar *Calendar) error ListCalendars(ctx context.Context) ([]Calendar, error) GetCalendar(ctx context.Context, path string) (*Calendar, error) + GetCalendarObject(ctx context.Context, path string, req *CalendarCompRequest) (*CalendarObject, error) ListCalendarObjects(ctx context.Context, path string, req *CalendarCompRequest) ([]CalendarObject, error) QueryCalendarObjects(ctx context.Context, path string, query *CalendarQuery) ([]CalendarObject, error) @@ -702,7 +705,28 @@ func (b *backend) Delete(r *http.Request) error { } func (b *backend) Mkcol(r *http.Request) error { - return internal.HTTPErrorf(http.StatusNotImplemented, "caldav: Mkcol not implemented") + if b.resourceTypeAtPath(r.URL.Path) != resourceTypeCalendar { + return internal.HTTPErrorf(http.StatusForbidden, "caldav: calendar creation not allowed at given location") + } + + cal := Calendar{ + Path: r.URL.Path, + } + + if !internal.IsRequestBodyEmpty(r) { + var m mkcolReq + if err := internal.DecodeXMLRequest(r, &m); err != nil { + return internal.HTTPErrorf(http.StatusBadRequest, "carddav: error parsing mkcol request: %s", err.Error()) + } + + if !m.ResourceType.Is(internal.CollectionName) || !m.ResourceType.Is(calendarName) { + return internal.HTTPErrorf(http.StatusBadRequest, "carddav: unexpected resource type") + } + cal.Name = m.DisplayName + // TODO ... + } + + return b.Backend.CreateCalendar(r.Context(), &cal) } func (b *backend) Copy(r *http.Request, dest *internal.Href, recursive, overwrite bool) (created bool, err error) { diff --git a/caldav/server_test.go b/caldav/server_test.go index 26acd56..3d1e63c 100644 --- a/caldav/server_test.go +++ b/caldav/server_test.go @@ -182,6 +182,10 @@ type testBackend struct { objectMap map[string][]CalendarObject } +func (t testBackend) CreateCalendar(ctx context.Context, calendar *Calendar) error { + return nil +} + func (t testBackend) ListCalendars(ctx context.Context) ([]Calendar, error) { return t.calendars, nil }