diff --git a/caldav/server.go b/caldav/server.go
index a3b9289..bb86925 100644
--- a/caldav/server.go
+++ b/caldav/server.go
@@ -371,6 +371,12 @@ func (b *backend) PropFind(r *http.Request, propfind *internal.PropFind, depth i
var resps []internal.Response
switch resType {
+ case resourceTypeRoot:
+ resp, err := b.propFindRoot(r.Context(), propfind)
+ if err != nil {
+ return nil, err
+ }
+ resps = append(resps, *resp)
case resourceTypeUserPrincipal:
principalPath, err := b.Backend.CurrentUserPrincipal(r.Context())
if err != nil {
@@ -453,6 +459,23 @@ func (b *backend) PropFind(r *http.Request, propfind *internal.PropFind, depth i
return internal.NewMultiStatus(resps...), nil
}
+func (b *backend) propFindRoot(ctx context.Context, propfind *internal.PropFind) (*internal.Response, error) {
+ principalPath, err := b.Backend.CurrentUserPrincipal(ctx)
+ if err != nil {
+ return nil, err
+ }
+
+ props := map[xml.Name]internal.PropFindFunc{
+ internal.CurrentUserPrincipalName: func(*internal.RawXMLValue) (interface{}, error) {
+ return &internal.CurrentUserPrincipal{Href: internal.Href{Path: principalPath}}, nil
+ },
+ internal.ResourceTypeName: func(*internal.RawXMLValue) (interface{}, error) {
+ return internal.NewResourceType(internal.CollectionName), nil
+ },
+ }
+ return internal.NewPropFindResponse(principalPath, propfind, props)
+}
+
func (b *backend) propFindUserPrincipal(ctx context.Context, propfind *internal.PropFind) (*internal.Response, error) {
principalPath, err := b.Backend.CurrentUserPrincipal(ctx)
if err != nil {
diff --git a/caldav/server_test.go b/caldav/server_test.go
index 0ee5fbd..c063871 100644
--- a/caldav/server_test.go
+++ b/caldav/server_test.go
@@ -50,6 +50,37 @@ func TestPropFindSupportedCalendarComponent(t *testing.T) {
}
}
+var propFindUserPrincipal = `
+
+
+
+
+
+
+
+
+`
+
+func TestPropFindRoot(t *testing.T) {
+ req := httptest.NewRequest("PROPFIND", "/", strings.NewReader(propFindUserPrincipal))
+ req.Header.Set("Content-Type", "application/xml")
+ w := httptest.NewRecorder()
+ calendar := &Calendar{}
+ handler := Handler{Backend: testBackend{calendar: calendar}}
+ handler.ServeHTTP(w, req)
+
+ res := w.Result()
+ defer res.Body.Close()
+ data, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ t.Error(err)
+ }
+ resp := string(data)
+ if !strings.Contains(resp, `/user/`) {
+ t.Errorf("No user-principal returned when doing a PROPFIND against root, response:\n%s", resp)
+ }
+}
+
type testBackend struct {
calendar *Calendar
}
@@ -59,11 +90,11 @@ func (t testBackend) Calendar(ctx context.Context) (*Calendar, error) {
}
func (t testBackend) CalendarHomeSetPath(ctx context.Context) (string, error) {
- return "", nil
+ return "/user/calendars/", nil
}
func (t testBackend) CurrentUserPrincipal(ctx context.Context) (string, error) {
- return "", nil
+ return "/user/", nil
}
func (t testBackend) DeleteCalendarObject(ctx context.Context, path string) error {