aboutsummaryrefslogtreecommitdiff
path: root/plugins/carddav/routes.go
diff options
context:
space:
mode:
authorSimon Ser <contact@emersion.fr>2020-02-12 21:13:51 +0100
committerSimon Ser <contact@emersion.fr>2020-02-12 21:14:18 +0100
commitc4ff33e64522f9662f5356d96b3d68f17764b84a (patch)
tree01c3eeb0b311373841bdf8c996c976d6a4f3eb5f /plugins/carddav/routes.go
parente24e20e528faa4a80c3281811f004b0388f4500b (diff)
downloadalps-c4ff33e64522f9662f5356d96b3d68f17764b84a.tar.gz
alps-c4ff33e64522f9662f5356d96b3d68f17764b84a.zip
plugins/carddav: add page to create new contact
Diffstat (limited to 'plugins/carddav/routes.go')
-rw-r--r--plugins/carddav/routes.go67
1 files changed, 67 insertions, 0 deletions
diff --git a/plugins/carddav/routes.go b/plugins/carddav/routes.go
index 45a6237..e05f32d 100644
--- a/plugins/carddav/routes.go
+++ b/plugins/carddav/routes.go
@@ -3,10 +3,13 @@ package koushincarddav
import (
"fmt"
"net/http"
+ "path"
+ "strings"
"git.sr.ht/~emersion/koushin"
"github.com/emersion/go-vcard"
"github.com/emersion/go-webdav/carddav"
+ "github.com/google/uuid"
)
type AddressBookRenderData struct {
@@ -21,6 +24,12 @@ type AddressObjectRenderData struct {
AddressObject *carddav.AddressObject
}
+type UpdateAddressObjectRenderData struct {
+ koushin.BaseRenderData
+ AddressObject *carddav.AddressObject // nil if creating a new contact
+ Card vcard.Card
+}
+
func registerRoutes(p *plugin) {
p.GET("/contacts", func(ctx *koushin.Context) error {
queryText := ctx.QueryParam("query")
@@ -107,4 +116,62 @@ func registerRoutes(p *plugin) {
AddressObject: addr,
})
})
+
+ createContact := func(ctx *koushin.Context) error {
+ card := make(vcard.Card)
+
+ if ctx.Request().Method == "POST" {
+ fn := ctx.FormValue("fn")
+ emails := strings.Split(ctx.FormValue("emails"), ",")
+
+ // Some CardDAV servers (e.g. Google) don't support vCard 4.0
+ // TODO: get supported formats from server, use highest version
+ if _, ok := card[vcard.FieldVersion]; !ok {
+ card.SetValue(vcard.FieldVersion, "3.0")
+ }
+
+ if field := card.Preferred(vcard.FieldFormattedName); field != nil {
+ field.Value = fn
+ } else {
+ card.Add(vcard.FieldFormattedName, &vcard.Field{Value: fn})
+ }
+
+ // TODO: Google wants a "N" field, fails with a 400 otherwise
+
+ // TODO: params are lost here
+ var emailFields []*vcard.Field
+ for _, email := range emails {
+ emailFields = append(emailFields, &vcard.Field{
+ Value: strings.TrimSpace(email),
+ })
+ }
+ card[vcard.FieldEmail] = emailFields
+
+ id := uuid.New()
+ if _, ok := card[vcard.FieldUID]; !ok {
+ card.SetValue(vcard.FieldUID, id.URN())
+ }
+
+ c, addressBook, err := p.clientWithAddressBook(ctx.Session)
+ if err != nil {
+ return err
+ }
+
+ p := path.Join(addressBook.Path, id.String() + ".vcf")
+ _, err = c.PutAddressObject(p, card)
+ if err != nil {
+ return fmt.Errorf("failed to put address object: %v", err)
+ }
+ // TODO: check if the returned AddressObject's path matches, if not
+ // fetch the new UID (the server may mutate it)
+
+ return ctx.Redirect(http.StatusFound, "/contacts/" + card.Value(vcard.FieldUID))
+ }
+
+ return ctx.Render(http.StatusOK, "update-address-object.html", &UpdateAddressObjectRenderData{
+ BaseRenderData: *koushin.NewBaseRenderData(ctx),
+ })
+ }
+ p.GET("/contacts/create", createContact)
+ p.POST("/contacts/create", createContact)
}