mirror of
https://github.com/1f349/go-webdav.git
synced 2024-12-22 08:14:15 +00:00
carddav: support address book creation/deletion
Now that the handling for multiple address books is in place, this commit adds initial support for creation and deletion of address books. These operations obviously require support from the backend, so the interface gains two new methods. All properties of the address book passed to `CreateAddressBook()` may be unset (e.g. when a client sends a MKCOL request without a body), except for the path, which is always set. It is up to the backend to put any desired default values in place.
This commit is contained in:
parent
80d77a977a
commit
71bd967b43
@ -68,6 +68,14 @@ func (b *testBackend) GetAddressBook(ctx context.Context, path string) (*Address
|
|||||||
return nil, webdav.NewHTTPError(404, fmt.Errorf("Not found"))
|
return nil, webdav.NewHTTPError(404, fmt.Errorf("Not found"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (*testBackend) CreateAddressBook(ctx context.Context, ab AddressBook) error {
|
||||||
|
panic("TODO: implement")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*testBackend) DeleteAddressBook(ctx context.Context, path string) error {
|
||||||
|
panic("TODO: implement")
|
||||||
|
}
|
||||||
|
|
||||||
func (*testBackend) GetAddressObject(ctx context.Context, path string, req *AddressDataRequest) (*AddressObject, error) {
|
func (*testBackend) GetAddressObject(ctx context.Context, path string, req *AddressDataRequest) (*AddressObject, error) {
|
||||||
if path == alicePath {
|
if path == alicePath {
|
||||||
card, err := vcard.NewDecoder(strings.NewReader(aliceData)).Decode()
|
card, err := vcard.NewDecoder(strings.NewReader(aliceData)).Decode()
|
||||||
|
@ -211,3 +211,11 @@ func (r *reportReq) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
|||||||
|
|
||||||
return d.DecodeElement(v, &start)
|
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"`
|
||||||
|
Description addressbookDescription `xml:"set>prop>addressbook-description"`
|
||||||
|
// TODO this could theoretically contain all addressbook properties?
|
||||||
|
}
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"mime"
|
"mime"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path"
|
"path"
|
||||||
@ -30,6 +31,8 @@ type Backend interface {
|
|||||||
AddressBookHomeSetPath(ctx context.Context) (string, error)
|
AddressBookHomeSetPath(ctx context.Context) (string, error)
|
||||||
ListAddressBooks(ctx context.Context) ([]AddressBook, error)
|
ListAddressBooks(ctx context.Context) ([]AddressBook, error)
|
||||||
GetAddressBook(ctx context.Context, path string) (*AddressBook, error)
|
GetAddressBook(ctx context.Context, path string) (*AddressBook, error)
|
||||||
|
CreateAddressBook(ctx context.Context, addressBook AddressBook) error
|
||||||
|
DeleteAddressBook(ctx context.Context, path string) error
|
||||||
GetAddressObject(ctx context.Context, path string, req *AddressDataRequest) (*AddressObject, error)
|
GetAddressObject(ctx context.Context, path string, req *AddressDataRequest) (*AddressObject, error)
|
||||||
ListAddressObjects(ctx context.Context, path string, req *AddressDataRequest) ([]AddressObject, error)
|
ListAddressObjects(ctx context.Context, path string, req *AddressDataRequest) ([]AddressObject, error)
|
||||||
QueryAddressObjects(ctx context.Context, path string, query *AddressBookQuery) ([]AddressObject, error)
|
QueryAddressObjects(ctx context.Context, path string, query *AddressBookQuery) ([]AddressObject, error)
|
||||||
@ -682,11 +685,44 @@ func (b *backend) Put(r *http.Request) (*internal.Href, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *backend) Delete(r *http.Request) error {
|
func (b *backend) Delete(r *http.Request) error {
|
||||||
|
switch b.resourceTypeAtPath(r.URL.Path) {
|
||||||
|
case resourceTypeAddressBook:
|
||||||
|
return b.Backend.DeleteAddressBook(r.Context(), r.URL.Path)
|
||||||
|
case resourceTypeAddressObject:
|
||||||
return b.Backend.DeleteAddressObject(r.Context(), r.URL.Path)
|
return b.Backend.DeleteAddressObject(r.Context(), r.URL.Path)
|
||||||
}
|
}
|
||||||
|
return internal.HTTPErrorf(http.StatusForbidden, "carddav: cannot delete resource at given location")
|
||||||
|
}
|
||||||
|
|
||||||
func (b *backend) Mkcol(r *http.Request) error {
|
func (b *backend) Mkcol(r *http.Request) error {
|
||||||
return internal.HTTPErrorf(http.StatusForbidden, "carddav: address book creation unsupported")
|
if b.resourceTypeAtPath(r.URL.Path) != resourceTypeAddressBook {
|
||||||
|
return internal.HTTPErrorf(http.StatusForbidden, "carddav: address book creation not allowed at given location")
|
||||||
|
}
|
||||||
|
|
||||||
|
ab := AddressBook{
|
||||||
|
Path: r.URL.Path,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if a request body was sent
|
||||||
|
_, err := r.Body.Read(nil)
|
||||||
|
if err != nil && err != io.EOF {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
// Not EOF, body is present
|
||||||
|
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(addressBookName) {
|
||||||
|
return internal.HTTPErrorf(http.StatusBadRequest, "carddav: unexpected resource type")
|
||||||
|
}
|
||||||
|
ab.Name = m.DisplayName
|
||||||
|
ab.Description = m.Description.Description
|
||||||
|
// TODO ...
|
||||||
|
}
|
||||||
|
return b.Backend.CreateAddressBook(r.Context(), ab)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *backend) Copy(r *http.Request, dest *internal.Href, recursive, overwrite bool) (created bool, err error) {
|
func (b *backend) Copy(r *http.Request, dest *internal.Href, recursive, overwrite bool) (created bool, err error) {
|
||||||
|
Loading…
Reference in New Issue
Block a user