groupware: add endpoints to patch addressbooks, contacts, calendars, events

This commit is contained in:
Pascal Bleser
2026-04-13 16:53:52 +02:00
parent 0efbebe8be
commit 18d4522d31
5 changed files with 128 additions and 6 deletions

View File

@@ -158,3 +158,32 @@ func (g *Groupware) DeleteAddressBook(w http.ResponseWriter, r *http.Request) {
return req.noContent(accountId, sessionState, AddressBookResponseObjectType, state)
})
}
func (g *Groupware) ModifyAddressBook(w http.ResponseWriter, r *http.Request) {
g.respond(w, r, func(req Request) Response {
ok, accountId, resp := req.needContactWithAccount()
if !ok {
return resp
}
l := req.logger.With().Str(accountId, log.SafeString(accountId))
id, err := req.PathParamDoc(UriParamAddressBookId, "The unique identifier of the AddressBook to modify")
if err != nil {
return req.error(accountId, err)
}
l.Str(UriParamAddressBookId, log.SafeString(id))
var change jmap.AddressBookChange
err = req.body(&change)
if err != nil {
return req.error(accountId, err)
}
logger := log.From(l)
ctx := req.ctx.WithLogger(logger)
updated, sessionState, state, lang, jerr := g.jmap.UpdateAddressBook(accountId, id, change, ctx)
if jerr != nil {
return req.jmapError(accountId, jerr, sessionState, lang)
}
return req.respond(accountId, updated, sessionState, AddressBookResponseObjectType, state)
})
}

View File

@@ -95,7 +95,7 @@ func (g *Groupware) GetCalendarChanges(w http.ResponseWriter, r *http.Request) {
func (g *Groupware) CreateCalendar(w http.ResponseWriter, r *http.Request) {
g.respond(w, r, func(req Request) Response {
ok, accountId, resp := req.needContactWithAccount()
ok, accountId, resp := req.needCalendarWithAccount()
if !ok {
return resp
}
@@ -120,7 +120,7 @@ func (g *Groupware) CreateCalendar(w http.ResponseWriter, r *http.Request) {
func (g *Groupware) DeleteCalendar(w http.ResponseWriter, r *http.Request) {
g.respond(w, r, func(req Request) Response {
ok, accountId, resp := req.needContactWithAccount()
ok, accountId, resp := req.needCalendarWithAccount()
if !ok {
return resp
}
@@ -157,3 +157,32 @@ func (g *Groupware) DeleteCalendar(w http.ResponseWriter, r *http.Request) {
return req.noContent(accountId, sessionState, CalendarResponseObjectType, state)
})
}
func (g *Groupware) ModifyCalendar(w http.ResponseWriter, r *http.Request) {
g.respond(w, r, func(req Request) Response {
ok, accountId, resp := req.needCalendarWithAccount()
if !ok {
return resp
}
l := req.logger.With().Str(accountId, log.SafeString(accountId))
id, err := req.PathParamDoc(UriParamCalendarId, "The unique identifier of the Calendar to modify")
if err != nil {
return req.error(accountId, err)
}
l.Str(UriParamCalendarId, log.SafeString(id))
var change jmap.CalendarChange
err = req.body(&change)
if err != nil {
return req.error(accountId, err)
}
logger := log.From(l)
ctx := req.ctx.WithLogger(logger)
updated, sessionState, state, lang, jerr := g.jmap.UpdateCalendar(accountId, id, change, ctx)
if jerr != nil {
return req.jmapError(accountId, jerr, sessionState, lang)
}
return req.respond(accountId, updated, sessionState, CalendarResponseObjectType, state)
})
}

View File

@@ -258,6 +258,35 @@ func (g *Groupware) DeleteContact(w http.ResponseWriter, r *http.Request) {
})
}
func (g *Groupware) ModifyContact(w http.ResponseWriter, r *http.Request) {
g.respond(w, r, func(req Request) Response {
ok, accountId, resp := req.needContactWithAccount()
if !ok {
return resp
}
l := req.logger.With().Str(accountId, log.SafeString(accountId))
id, err := req.PathParamDoc(UriParamContactId, "The unique identifier of the Contact to modify")
if err != nil {
return req.error(accountId, err)
}
l.Str(UriParamContactId, log.SafeString(id))
var change jmap.ContactCardChange
err = req.body(&change)
if err != nil {
return req.error(accountId, err)
}
logger := log.From(l)
ctx := req.ctx.WithLogger(logger)
updated, sessionState, state, lang, jerr := g.jmap.UpdateContactCard(accountId, id, change, ctx)
if jerr != nil {
return req.jmapError(accountId, jerr, sessionState, lang)
}
return req.respond(accountId, updated, sessionState, ContactResponseObjectType, state)
})
}
func mapContactCardSort(s SortCrit) jmap.ContactCardComparator {
attr := s.Attribute
if mapped, ok := ContactSortingPropertyMapping[s.Attribute]; ok {

View File

@@ -159,6 +159,35 @@ func (g *Groupware) DeleteCalendarEvent(w http.ResponseWriter, r *http.Request)
})
}
func (g *Groupware) ModifyCalendarEvent(w http.ResponseWriter, r *http.Request) {
g.respond(w, r, func(req Request) Response {
ok, accountId, resp := req.needCalendarWithAccount()
if !ok {
return resp
}
l := req.logger.With().Str(accountId, log.SafeString(accountId))
id, err := req.PathParamDoc(UriParamEventId, "The unique identifier of the Calendar Event to modify")
if err != nil {
return req.error(accountId, err)
}
l.Str(UriParamEventId, log.SafeString(id))
var change jmap.CalendarEventChange
err = req.body(&change)
if err != nil {
return req.error(accountId, err)
}
logger := log.From(l)
ctx := req.ctx.WithLogger(logger)
updated, sessionState, state, lang, jerr := g.jmap.UpdateCalendarEvent(accountId, id, change, ctx)
if jerr != nil {
return req.jmapError(accountId, jerr, sessionState, lang)
}
return req.respond(accountId, updated, sessionState, EventResponseObjectType, state)
})
}
// Parse a blob that contains an iCal file and return it as JSCalendar.
//
// @api:tags calendar,blob

View File

@@ -151,8 +151,9 @@ func (g *Groupware) Route(r chi.Router) {
r.Post("/", g.CreateAddressBook)
r.Route("/{addressbookid}", func(r chi.Router) {
r.Get("/", g.GetAddressbook)
r.Get("/contacts", g.GetContactsInAddressbook) //NOSONAR
r.Patch("/", g.ModifyAddressBook)
r.Delete("/", g.DeleteAddressBook)
r.Get("/contacts", g.GetContactsInAddressbook) //NOSONAR
})
})
r.Route("/contacts", func(r chi.Router) {
@@ -160,6 +161,7 @@ func (g *Groupware) Route(r chi.Router) {
r.Post("/", g.CreateContact)
r.Route("/{contactid}", func(r chi.Router) {
r.Get("/", g.GetContactById)
r.Patch("/", g.ModifyContact)
r.Delete("/", g.DeleteContact)
})
})
@@ -168,12 +170,14 @@ func (g *Groupware) Route(r chi.Router) {
r.Post("/", g.CreateCalendar)
r.Route("/{calendarid}", func(r chi.Router) {
r.Get("/", g.GetCalendarById)
r.Get("/events", g.GetEventsInCalendar) //NOSONAR
r.Patch("/", g.ModifyCalendar)
r.Delete("/", g.DeleteCalendar)
r.Get("/events", g.GetEventsInCalendar) //NOSONAR
})
})
r.Route("/events", func(r chi.Router) {
r.Post("/", g.CreateCalendarEvent)
r.Patch("/", g.ModifyCalendarEvent)
r.Delete("/{eventid}", g.DeleteCalendarEvent)
})
r.Route("/tasklists", func(r chi.Router) {
@@ -194,8 +198,10 @@ func (g *Groupware) Route(r chi.Router) {
// r.Get("/quotas", g.GetQuotaChanges)
r.Get("/identities", g.GetIdentityChanges)
})
r.Get("/objects", g.GetObjects)
r.Post("/objects", g.GetObjects)
r.Route("/objects", func(r chi.Router) {
r.Get("/", g.GetObjects)
r.Post("/", g.GetObjects) // this is actually a read-only operation
})
})
})