mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-01-22 12:59:23 -05:00
groupware: add Object-Type and Account-Id response headers
* implement Request.AllAccountIds() to generalize the fetching (and uniqifying) of all account IDs, which will allow us to implement things such as "subscribed" accounts, or limiting the number of accounts in one request * add Account-Id response header * add Object-Type response header
This commit is contained in:
@@ -29,11 +29,11 @@ type SwaggerGetAccountResponse struct {
|
||||
// 500: ErrorResponse500
|
||||
func (g *Groupware) GetAccount(w http.ResponseWriter, r *http.Request) {
|
||||
g.respond(w, r, func(req Request) Response {
|
||||
account, err := req.GetAccountForMail()
|
||||
accountId, account, err := req.GetAccountForMail()
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
return response(account, req.session.State, "")
|
||||
return etagResponse(accountId, account, req.session.State, AccountResponseObjectType, jmap.State(req.session.State), "")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -66,16 +66,16 @@ func (g *Groupware) GetAccounts(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
// sort on accountId to have a stable order that remains the same with every query
|
||||
slices.SortFunc(list, func(a, b AccountWithId) int { return strings.Compare(a.AccountId, b.AccountId) })
|
||||
return response(list, req.session.State, "")
|
||||
return etagResponse(joinAccountIds(structs.Map(list, func(a AccountWithId) string { return a.AccountId })), list, req.session.State, AccountResponseObjectType, jmap.State(req.session.State), "")
|
||||
})
|
||||
}
|
||||
|
||||
func (g *Groupware) GetAccountsWithTheirIdentities(w http.ResponseWriter, r *http.Request) {
|
||||
g.respond(w, r, func(req Request) Response {
|
||||
uniqueAccountIds := structs.Uniq(structs.Keys(req.session.Accounts))
|
||||
resp, sessionState, state, lang, err := g.jmap.GetIdentitiesForAllAccounts(uniqueAccountIds, req.session, req.ctx, req.logger, req.language())
|
||||
allAccountIds := req.AllAccountIds()
|
||||
resp, sessionState, state, lang, err := g.jmap.GetIdentitiesForAllAccounts(allAccountIds, req.session, req.ctx, req.logger, req.language())
|
||||
if err != nil {
|
||||
return req.errorResponseFromJmap(err)
|
||||
return req.errorResponseFromJmap(joinAccountIds(allAccountIds), err)
|
||||
}
|
||||
list := make([]AccountWithIdAndIdentities, len(req.session.Accounts))
|
||||
i := 0
|
||||
@@ -94,7 +94,7 @@ func (g *Groupware) GetAccountsWithTheirIdentities(w http.ResponseWriter, r *htt
|
||||
}
|
||||
// sort on accountId to have a stable order that remains the same with every query
|
||||
slices.SortFunc(list, func(a, b AccountWithIdAndIdentities) int { return strings.Compare(a.AccountId, b.AccountId) })
|
||||
return etagResponse(list, sessionState, state, lang)
|
||||
return etagResponse(joinAccountIds(structs.Map(list, func(a AccountWithIdAndIdentities) string { return a.AccountId })), list, sessionState, AccountResponseObjectType, state, lang)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -16,26 +16,29 @@ const (
|
||||
|
||||
func (g *Groupware) GetBlobMeta(w http.ResponseWriter, r *http.Request) {
|
||||
g.respond(w, r, func(req Request) Response {
|
||||
blobId := chi.URLParam(req.r, UriParamBlobId)
|
||||
if blobId == "" {
|
||||
return req.parameterErrorResponse(UriParamBlobId, fmt.Sprintf("Invalid value for path parameter '%v': empty", UriParamBlobId))
|
||||
}
|
||||
|
||||
accountId, err := req.GetAccountIdForBlob()
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
logger := log.From(req.logger.With().Str(logAccountId, accountId))
|
||||
l := req.logger.With().Str(logAccountId, accountId)
|
||||
|
||||
blobId := chi.URLParam(req.r, UriParamBlobId)
|
||||
if blobId == "" {
|
||||
return req.parameterErrorResponse(accountId, UriParamBlobId, fmt.Sprintf("Invalid value for path parameter '%v': empty", UriParamBlobId))
|
||||
}
|
||||
l = l.Str(UriParamBlobId, blobId)
|
||||
|
||||
logger := log.From(l)
|
||||
|
||||
res, sessionState, state, lang, jerr := g.jmap.GetBlobMetadata(accountId, req.session, req.ctx, logger, req.language(), blobId)
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
blob := res
|
||||
if blob == nil {
|
||||
return notFoundResponse(sessionState)
|
||||
return notFoundResponse(accountId, sessionState)
|
||||
}
|
||||
return etagResponse(res, sessionState, state, lang)
|
||||
return etagResponse(accountId, res, sessionState, BlobResponseObjectType, state, lang)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -54,16 +57,16 @@ func (g *Groupware) UploadBlob(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
accountId, err := req.GetAccountIdForBlob()
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
logger := log.From(req.logger.With().Str(logAccountId, accountId))
|
||||
|
||||
resp, lang, jerr := g.jmap.UploadBlobStream(accountId, req.session, req.ctx, logger, req.language(), contentType, body)
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
|
||||
return response(resp, req.session.State, lang)
|
||||
return response(accountId, resp, req.session.State, lang)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -78,7 +81,7 @@ func (g *Groupware) DownloadBlob(w http.ResponseWriter, r *http.Request) {
|
||||
if gwerr != nil {
|
||||
return gwerr
|
||||
}
|
||||
logger := log.From(req.logger.With().Str(logAccountId, accountId))
|
||||
logger := log.From(req.logger.With().Str(logAccountId, accountId).Str(UriParamBlobId, blobId))
|
||||
|
||||
return req.serveBlob(blobId, name, typ, logger, accountId, w)
|
||||
})
|
||||
|
||||
@@ -34,10 +34,10 @@ func (g *Groupware) GetCalendars(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
calendars, sessionState, state, lang, jerr := g.jmap.GetCalendars(accountId, req.session, req.ctx, req.logger, req.language(), nil)
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
|
||||
return etagResponse(calendars, sessionState, state, lang)
|
||||
return etagResponse(accountId, calendars, sessionState, CalendarResponseObjectType, state, lang)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -74,13 +74,13 @@ func (g *Groupware) GetCalendarById(w http.ResponseWriter, r *http.Request) {
|
||||
logger := log.From(l)
|
||||
calendars, sessionState, state, lang, jerr := g.jmap.GetCalendars(accountId, req.session, req.ctx, logger, req.language(), []string{calendarId})
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
|
||||
if len(calendars.NotFound) > 0 {
|
||||
return notFoundResponse(sessionState)
|
||||
return notFoundResponse(accountId, sessionState)
|
||||
} else {
|
||||
return etagResponse(calendars.Calendars[0], sessionState, state, lang)
|
||||
return etagResponse(accountId, calendars.Calendars[0], sessionState, CalendarResponseObjectType, state, lang)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -115,7 +115,7 @@ func (g *Groupware) GetEventsInCalendar(w http.ResponseWriter, r *http.Request)
|
||||
|
||||
offset, ok, err := req.parseUIntParam(QueryParamOffset, 0)
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
if ok {
|
||||
l = l.Uint(QueryParamOffset, offset)
|
||||
@@ -123,7 +123,7 @@ func (g *Groupware) GetEventsInCalendar(w http.ResponseWriter, r *http.Request)
|
||||
|
||||
limit, ok, err := req.parseUIntParam(QueryParamLimit, g.defaultContactLimit)
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
if ok {
|
||||
l = l.Uint(QueryParamLimit, limit)
|
||||
@@ -137,13 +137,13 @@ func (g *Groupware) GetEventsInCalendar(w http.ResponseWriter, r *http.Request)
|
||||
logger := log.From(l)
|
||||
eventsByAccountId, sessionState, state, lang, jerr := g.jmap.QueryCalendarEvents([]string{accountId}, req.session, req.ctx, logger, req.language(), filter, sortBy, offset, limit)
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
|
||||
if events, ok := eventsByAccountId[accountId]; ok {
|
||||
return etagResponse(events, sessionState, state, lang)
|
||||
return etagResponse(accountId, events, sessionState, EventResponseObjectType, state, lang)
|
||||
} else {
|
||||
return notFoundResponse(sessionState)
|
||||
return notFoundResponse(accountId, sessionState)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -163,15 +163,15 @@ func (g *Groupware) CreateCalendarEvent(w http.ResponseWriter, r *http.Request)
|
||||
var create jmap.CalendarEvent
|
||||
err := req.body(&create)
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
|
||||
logger := log.From(l)
|
||||
created, sessionState, state, lang, jerr := g.jmap.CreateCalendarEvent(accountId, req.session, req.ctx, logger, req.language(), create)
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
return etagResponse(created, sessionState, state, lang)
|
||||
return etagResponse(accountId, created, sessionState, EventResponseObjectType, state, lang)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -191,25 +191,25 @@ func (g *Groupware) DeleteCalendarEvent(w http.ResponseWriter, r *http.Request)
|
||||
|
||||
deleted, sessionState, state, _, jerr := g.jmap.DeleteCalendarEvent(accountId, []string{eventId}, req.session, req.ctx, logger, req.language())
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
|
||||
for _, e := range deleted {
|
||||
desc := e.Description
|
||||
if desc != "" {
|
||||
return errorResponseWithSessionState(apiError(
|
||||
return errorResponseWithSessionState(accountId, apiError(
|
||||
req.errorId(),
|
||||
ErrorFailedToDeleteContact,
|
||||
withDetail(e.Description),
|
||||
), sessionState)
|
||||
} else {
|
||||
return errorResponseWithSessionState(apiError(
|
||||
return errorResponseWithSessionState(accountId, apiError(
|
||||
req.errorId(),
|
||||
ErrorFailedToDeleteContact,
|
||||
), sessionState)
|
||||
}
|
||||
}
|
||||
return noContentResponseWithEtag(sessionState, state)
|
||||
return noContentResponseWithEtag(accountId, sessionState, EventResponseObjectType, state)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -217,7 +217,7 @@ func (g *Groupware) ParseIcalBlob(w http.ResponseWriter, r *http.Request) {
|
||||
g.respond(w, r, func(req Request) Response {
|
||||
accountId, err := req.GetAccountIdForBlob()
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
|
||||
blobId := chi.URLParam(r, UriParamBlobId)
|
||||
@@ -228,8 +228,8 @@ func (g *Groupware) ParseIcalBlob(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
resp, sessionState, state, lang, jerr := g.jmap.ParseICalendarBlob(accountId, req.session, req.ctx, logger, req.language(), blobIds)
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
return etagResponse(resp, sessionState, state, lang)
|
||||
return etagResponse(accountId, resp, sessionState, EventResponseObjectType, state, lang)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -34,10 +34,10 @@ func (g *Groupware) GetAddressbooks(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
addressbooks, sessionState, state, lang, jerr := g.jmap.GetAddressbooks(accountId, req.session, req.ctx, req.logger, req.language(), nil)
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
|
||||
return etagResponse(addressbooks, sessionState, state, lang)
|
||||
return etagResponse(accountId, addressbooks, sessionState, AddressBookResponseObjectType, state, lang)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -74,13 +74,13 @@ func (g *Groupware) GetAddressbook(w http.ResponseWriter, r *http.Request) {
|
||||
logger := log.From(l)
|
||||
addressbooks, sessionState, state, lang, jerr := g.jmap.GetAddressbooks(accountId, req.session, req.ctx, logger, req.language(), []string{addressBookId})
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
|
||||
if len(addressbooks.NotFound) > 0 {
|
||||
return notFoundResponse(sessionState)
|
||||
return notFoundResponse(accountId, sessionState)
|
||||
} else {
|
||||
return etagResponse(addressbooks, sessionState, state, lang)
|
||||
return etagResponse(accountId, addressbooks, sessionState, AddressBookResponseObjectType, state, lang)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -115,7 +115,7 @@ func (g *Groupware) GetContactsInAddressbook(w http.ResponseWriter, r *http.Requ
|
||||
|
||||
offset, ok, err := req.parseUIntParam(QueryParamOffset, 0)
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
if ok {
|
||||
l = l.Uint(QueryParamOffset, offset)
|
||||
@@ -123,7 +123,7 @@ func (g *Groupware) GetContactsInAddressbook(w http.ResponseWriter, r *http.Requ
|
||||
|
||||
limit, ok, err := req.parseUIntParam(QueryParamLimit, g.defaultContactLimit)
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
if ok {
|
||||
l = l.Uint(QueryParamLimit, limit)
|
||||
@@ -137,13 +137,13 @@ func (g *Groupware) GetContactsInAddressbook(w http.ResponseWriter, r *http.Requ
|
||||
logger := log.From(l)
|
||||
contactsByAccountId, sessionState, state, lang, jerr := g.jmap.QueryContactCards([]string{accountId}, req.session, req.ctx, logger, req.language(), filter, sortBy, offset, limit)
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
|
||||
if contacts, ok := contactsByAccountId[accountId]; ok {
|
||||
return etagResponse(contacts, sessionState, state, lang)
|
||||
return etagResponse(accountId, contacts, sessionState, ContactResponseObjectType, state, lang)
|
||||
} else {
|
||||
return notFoundResponse(sessionState)
|
||||
return etagNotFoundResponse(accountId, sessionState, ContactResponseObjectType, state, lang)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -163,13 +163,13 @@ func (g *Groupware) GetContactById(w http.ResponseWriter, r *http.Request) {
|
||||
logger := log.From(l)
|
||||
contactsById, sessionState, state, lang, jerr := g.jmap.GetContactCardsById(accountId, req.session, req.ctx, logger, req.language(), []string{contactId})
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
|
||||
if contact, ok := contactsById[contactId]; ok {
|
||||
return etagResponse(contact, sessionState, state, lang)
|
||||
return etagResponse(accountId, contact, sessionState, ContactResponseObjectType, state, lang)
|
||||
} else {
|
||||
return notFoundResponse(sessionState)
|
||||
return etagNotFoundResponse(accountId, sessionState, ContactResponseObjectType, state, lang)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -189,15 +189,15 @@ func (g *Groupware) CreateContact(w http.ResponseWriter, r *http.Request) {
|
||||
var create jscontact.ContactCard
|
||||
err := req.body(&create)
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
|
||||
logger := log.From(l)
|
||||
created, sessionState, state, lang, jerr := g.jmap.CreateContactCard(accountId, req.session, req.ctx, logger, req.language(), create)
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
return etagResponse(created, sessionState, state, lang)
|
||||
return etagResponse(accountId, created, sessionState, ContactResponseObjectType, state, lang)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -216,24 +216,24 @@ func (g *Groupware) DeleteContact(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
deleted, sessionState, state, _, jerr := g.jmap.DeleteContactCard(accountId, []string{contactId}, req.session, req.ctx, logger, req.language())
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
|
||||
for _, e := range deleted {
|
||||
desc := e.Description
|
||||
if desc != "" {
|
||||
return errorResponseWithSessionState(apiError(
|
||||
return errorResponseWithSessionState(accountId, apiError(
|
||||
req.errorId(),
|
||||
ErrorFailedToDeleteContact,
|
||||
withDetail(e.Description),
|
||||
), sessionState)
|
||||
} else {
|
||||
return errorResponseWithSessionState(apiError(
|
||||
return errorResponseWithSessionState(accountId, apiError(
|
||||
req.errorId(),
|
||||
ErrorFailedToDeleteContact,
|
||||
), sessionState)
|
||||
}
|
||||
}
|
||||
return noContentResponseWithEtag(sessionState, state)
|
||||
return noContentResponseWithEtag(accountId, sessionState, ContactResponseObjectType, state)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -68,33 +68,41 @@ func (g *Groupware) GetAllEmailsInMailbox(w http.ResponseWriter, r *http.Request
|
||||
// ... then it's a completely different operation
|
||||
maxChanges := uint(0)
|
||||
g.respond(w, r, func(req Request) Response {
|
||||
if mailboxId == "" {
|
||||
return req.parameterErrorResponse(UriParamMailboxId, fmt.Sprintf("Missing required mailbox ID path parameter '%v'", UriParamMailboxId))
|
||||
}
|
||||
|
||||
accountId, err := req.GetAccountIdForMail()
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
|
||||
if mailboxId == "" {
|
||||
return req.parameterErrorResponse(accountId, UriParamMailboxId, fmt.Sprintf("Missing required mailbox ID path parameter '%v'", UriParamMailboxId))
|
||||
}
|
||||
|
||||
logger := log.From(req.logger.With().Str(HeaderSince, log.SafeString(since)).Str(logAccountId, log.SafeString(accountId)))
|
||||
|
||||
changes, sessionState, state, lang, jerr := g.jmap.GetMailboxChanges(accountId, req.session, req.ctx, logger, req.language(), mailboxId, since, true, g.maxBodyValueBytes, maxChanges)
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
|
||||
return etagResponse(changes, sessionState, state, lang)
|
||||
return etagResponse(accountId, changes, sessionState, EmailResponseObjectType, state, lang)
|
||||
})
|
||||
} else {
|
||||
g.respond(w, r, func(req Request) Response {
|
||||
l := req.logger.With()
|
||||
if mailboxId == "" {
|
||||
return req.parameterErrorResponse(UriParamMailboxId, fmt.Sprintf("Missing required mailbox ID path parameter '%v'", UriParamMailboxId))
|
||||
|
||||
accountId, err := req.GetAccountIdForMail()
|
||||
if err != nil {
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
l = l.Str(logAccountId, accountId)
|
||||
|
||||
if mailboxId == "" {
|
||||
return req.parameterErrorResponse(accountId, UriParamMailboxId, fmt.Sprintf("Missing required mailbox ID path parameter '%v'", UriParamMailboxId))
|
||||
}
|
||||
|
||||
offset, ok, err := req.parseUIntParam(QueryParamOffset, 0)
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
if ok {
|
||||
l = l.Uint(QueryParamOffset, offset)
|
||||
@@ -102,28 +110,22 @@ func (g *Groupware) GetAllEmailsInMailbox(w http.ResponseWriter, r *http.Request
|
||||
|
||||
limit, ok, err := req.parseUIntParam(QueryParamLimit, g.defaultEmailLimit)
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
if ok {
|
||||
l = l.Uint(QueryParamLimit, limit)
|
||||
}
|
||||
|
||||
accountId, err := req.GetAccountIdForMail()
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
}
|
||||
l = l.Str(logAccountId, accountId)
|
||||
|
||||
logger := log.From(l)
|
||||
|
||||
emails, sessionState, state, lang, jerr := g.jmap.GetAllEmailsInMailbox(accountId, req.session, req.ctx, logger, req.language(), mailboxId, offset, limit, false, true, g.maxBodyValueBytes, true)
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
|
||||
sanitized, err := req.sanitizeEmails(emails.Emails)
|
||||
if err != nil {
|
||||
return errorResponseWithSessionState(err, sessionState)
|
||||
return errorResponseWithSessionState(accountId, err, sessionState)
|
||||
}
|
||||
|
||||
safe := jmap.Emails{
|
||||
@@ -133,7 +135,7 @@ func (g *Groupware) GetAllEmailsInMailbox(w http.ResponseWriter, r *http.Request
|
||||
Offset: emails.Offset,
|
||||
}
|
||||
|
||||
return etagResponse(safe, sessionState, state, lang)
|
||||
return etagResponse(accountId, safe, sessionState, EmailResponseObjectType, state, lang)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -182,19 +184,19 @@ func (g *Groupware) GetEmailsById(w http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
} else {
|
||||
g.respond(w, r, func(req Request) Response {
|
||||
if len(ids) < 1 {
|
||||
return req.parameterErrorResponse(UriParamEmailId, fmt.Sprintf("Invalid value for path parameter '%v': '%s': %s", UriParamEmailId, log.SafeString(id), "empty list of mail ids"))
|
||||
}
|
||||
|
||||
accountId, err := req.GetAccountIdForMail()
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
l := req.logger.With().Str(logAccountId, log.SafeString(accountId))
|
||||
|
||||
if len(ids) < 1 {
|
||||
return req.parameterErrorResponse(accountId, UriParamEmailId, fmt.Sprintf("Invalid value for path parameter '%v': '%s': %s", UriParamEmailId, log.SafeString(id), "empty list of mail ids"))
|
||||
}
|
||||
|
||||
markAsSeen, ok, err := req.parseBoolParam(QueryParamMarkAsSeen, false)
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
if ok {
|
||||
l = l.Bool(QueryParamMarkAsSeen, markAsSeen)
|
||||
@@ -205,32 +207,32 @@ func (g *Groupware) GetEmailsById(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
emails, sessionState, state, lang, jerr := g.jmap.GetEmails(accountId, req.session, req.ctx, logger, req.language(), ids, true, g.maxBodyValueBytes, markAsSeen, true)
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
if len(emails) < 1 {
|
||||
return notFoundResponse(sessionState)
|
||||
return notFoundResponse(accountId, sessionState)
|
||||
} else {
|
||||
sanitized, err := req.sanitizeEmail(emails[0])
|
||||
if err != nil {
|
||||
return errorResponseWithSessionState(err, sessionState)
|
||||
return errorResponseWithSessionState(accountId, err, sessionState)
|
||||
}
|
||||
return etagResponse(sanitized, sessionState, state, lang)
|
||||
return etagResponse(accountId, sanitized, sessionState, EmailResponseObjectType, state, lang)
|
||||
}
|
||||
} else {
|
||||
logger := log.From(l.Array("ids", log.SafeStringArray(ids)))
|
||||
|
||||
emails, sessionState, state, lang, jerr := g.jmap.GetEmails(accountId, req.session, req.ctx, logger, req.language(), ids, true, g.maxBodyValueBytes, markAsSeen, false)
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
if len(emails) < 1 {
|
||||
return notFoundResponse(sessionState)
|
||||
return notFoundResponse(accountId, sessionState)
|
||||
} else {
|
||||
sanitized, err := req.sanitizeEmails(emails)
|
||||
if err != nil {
|
||||
return errorResponseWithSessionState(err, sessionState)
|
||||
return errorResponseWithSessionState(accountId, err, sessionState)
|
||||
}
|
||||
return etagResponse(sanitized, sessionState, state, lang)
|
||||
return etagResponse(accountId, sanitized, sessionState, EmailResponseObjectType, state, lang)
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -265,22 +267,22 @@ func (g *Groupware) GetEmailAttachments(w http.ResponseWriter, r *http.Request)
|
||||
g.respond(w, r, func(req Request) Response {
|
||||
accountId, err := req.GetAccountIdForMail()
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
l := req.logger.With().Str(logAccountId, log.SafeString(accountId))
|
||||
logger := log.From(l)
|
||||
emails, sessionState, state, lang, jerr := g.jmap.GetEmails(accountId, req.session, req.ctx, logger, req.language(), []string{id}, false, 0, false, false)
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
if len(emails) < 1 {
|
||||
return notFoundResponse(sessionState)
|
||||
return notFoundResponse(accountId, sessionState)
|
||||
}
|
||||
email, err := req.sanitizeEmail(emails[0])
|
||||
if err != nil {
|
||||
return errorResponseWithSessionState(err, sessionState)
|
||||
return errorResponseWithSessionState(accountId, err, sessionState)
|
||||
}
|
||||
return etagResponse(email.Attachments, sessionState, state, lang)
|
||||
return etagResponse(accountId, email.Attachments, sessionState, EmailResponseObjectType, state, lang)
|
||||
})
|
||||
} else {
|
||||
g.stream(w, r, func(req Request, w http.ResponseWriter) *Error {
|
||||
@@ -365,28 +367,29 @@ func (g *Groupware) GetEmailAttachments(w http.ResponseWriter, r *http.Request)
|
||||
func (g *Groupware) getEmailsSince(w http.ResponseWriter, r *http.Request, since string) {
|
||||
g.respond(w, r, func(req Request) Response {
|
||||
l := req.logger.With().Str(QueryParamSince, log.SafeString(since))
|
||||
|
||||
accountId, err := req.GetAccountIdForMail()
|
||||
if err != nil {
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
l = l.Str(logAccountId, log.SafeString(accountId))
|
||||
|
||||
maxChanges, ok, err := req.parseUIntParam(QueryParamMaxChanges, 0)
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
if ok {
|
||||
l = l.Uint(QueryParamMaxChanges, maxChanges)
|
||||
}
|
||||
|
||||
accountId, err := req.GetAccountIdForMail()
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
}
|
||||
l = l.Str(logAccountId, log.SafeString(accountId))
|
||||
|
||||
logger := log.From(l)
|
||||
|
||||
changes, sessionState, state, lang, jerr := g.jmap.GetEmailsSince(accountId, req.session, req.ctx, logger, req.language(), since, true, g.maxBodyValueBytes, maxChanges)
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
|
||||
return etagResponse(changes, sessionState, state, lang)
|
||||
return etagResponse(accountId, changes, sessionState, EmailResponseObjectType, state, lang)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -577,10 +580,16 @@ func (g *Groupware) buildFilter(req Request) (bool, jmap.EmailFilterElement, boo
|
||||
|
||||
func (g *Groupware) searchEmails(w http.ResponseWriter, r *http.Request) {
|
||||
g.respond(w, r, func(req Request) Response {
|
||||
accountId, err := req.GetAccountIdForMail()
|
||||
if err != nil {
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
|
||||
ok, filter, makesSnippets, offset, limit, logger, err := g.buildFilter(req)
|
||||
if !ok {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
logger = log.From(req.logger.With().Str(logAccountId, log.SafeString(accountId)))
|
||||
|
||||
if !filter.IsNotEmpty() {
|
||||
filter = nil
|
||||
@@ -588,7 +597,7 @@ func (g *Groupware) searchEmails(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
fetchEmails, ok, err := req.parseBoolParam(QueryParamSearchFetchEmails, false)
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
if ok {
|
||||
logger = log.From(logger.With().Bool(QueryParamSearchFetchEmails, fetchEmails))
|
||||
@@ -597,21 +606,15 @@ func (g *Groupware) searchEmails(w http.ResponseWriter, r *http.Request) {
|
||||
if fetchEmails {
|
||||
fetchBodies, ok, err := req.parseBoolParam(QueryParamSearchFetchBodies, false)
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
if ok {
|
||||
logger = log.From(logger.With().Bool(QueryParamSearchFetchBodies, fetchBodies))
|
||||
}
|
||||
|
||||
accountId, err := req.GetAccountIdForMail()
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
}
|
||||
logger = log.From(logger.With().Str(logAccountId, log.SafeString(accountId)))
|
||||
|
||||
resultsByAccount, sessionState, state, lang, jerr := g.jmap.QueryEmailsWithSnippets([]string{accountId}, filter, req.session, req.ctx, logger, req.language(), offset, limit, fetchBodies, g.maxBodyValueBytes)
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
|
||||
if results, ok := resultsByAccount[accountId]; ok {
|
||||
@@ -631,7 +634,7 @@ func (g *Groupware) searchEmails(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
sanitized, err := req.sanitizeEmail(result.Email)
|
||||
if err != nil {
|
||||
return errorResponseWithSessionState(err, sessionState)
|
||||
return errorResponseWithSessionState(accountId, err, sessionState)
|
||||
}
|
||||
flattened[i] = EmailWithSnippets{
|
||||
// AccountId: accountId,
|
||||
@@ -640,36 +643,30 @@ func (g *Groupware) searchEmails(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
return etagResponse(EmailWithSnippetsSearchResults{
|
||||
return etagResponse(accountId, EmailWithSnippetsSearchResults{
|
||||
Results: flattened,
|
||||
Total: results.Total,
|
||||
Limit: results.Limit,
|
||||
QueryState: results.QueryState,
|
||||
}, sessionState, state, lang)
|
||||
}, sessionState, EmailResponseObjectType, state, lang)
|
||||
} else {
|
||||
return notFoundResponse(sessionState)
|
||||
return notFoundResponse(accountId, sessionState)
|
||||
}
|
||||
} else {
|
||||
accountId, err := req.GetAccountIdForMail()
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
}
|
||||
logger = log.From(logger.With().Str(logAccountId, log.SafeString(accountId)))
|
||||
|
||||
resultsByAccountId, sessionState, state, lang, jerr := g.jmap.QueryEmailSnippets([]string{accountId}, filter, req.session, req.ctx, logger, req.language(), offset, limit)
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
|
||||
if results, ok := resultsByAccountId[accountId]; ok {
|
||||
return etagResponse(EmailSearchSnippetsResults{
|
||||
return etagResponse(accountId, EmailSearchSnippetsResults{
|
||||
Results: structs.Map(results.Snippets, func(s jmap.SearchSnippetWithMeta) Snippet { return Snippet{SearchSnippetWithMeta: s} }),
|
||||
Total: results.Total,
|
||||
Limit: results.Limit,
|
||||
QueryState: results.QueryState,
|
||||
}, sessionState, state, lang)
|
||||
}, sessionState, EmailResponseObjectType, state, lang)
|
||||
} else {
|
||||
return notFoundResponse(sessionState)
|
||||
return notFoundResponse(accountId, sessionState)
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -692,10 +689,13 @@ func (g *Groupware) GetEmails(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (g *Groupware) GetEmailsForAllAccounts(w http.ResponseWriter, r *http.Request) {
|
||||
g.respond(w, r, func(req Request) Response {
|
||||
allAccountIds := req.AllAccountIds()
|
||||
|
||||
ok, filter, makesSnippets, offset, limit, logger, err := g.buildFilter(req)
|
||||
if !ok {
|
||||
return errorResponse(err)
|
||||
return errorResponse(joinAccountIds(allAccountIds), err)
|
||||
}
|
||||
logger = log.From(req.logger.With().Array(logAccountId, log.SafeStringArray(allAccountIds)))
|
||||
|
||||
if !filter.IsNotEmpty() {
|
||||
filter = nil
|
||||
@@ -703,19 +703,16 @@ func (g *Groupware) GetEmailsForAllAccounts(w http.ResponseWriter, r *http.Reque
|
||||
|
||||
fetchEmails, ok, err := req.parseBoolParam(QueryParamSearchFetchEmails, false)
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(joinAccountIds(allAccountIds), err)
|
||||
}
|
||||
if ok {
|
||||
logger = log.From(logger.With().Bool(QueryParamSearchFetchEmails, fetchEmails))
|
||||
}
|
||||
|
||||
allAccountIds := structs.Keys(req.session.Accounts) // TODO(pbleser-oc) do we need a limit for a maximum amount of accounts to query at once?
|
||||
logger = log.From(logger.With().Array(logAccountId, log.SafeStringArray(allAccountIds)))
|
||||
|
||||
if fetchEmails {
|
||||
fetchBodies, ok, err := req.parseBoolParam(QueryParamSearchFetchBodies, false)
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(joinAccountIds(allAccountIds), err)
|
||||
}
|
||||
if ok {
|
||||
logger = log.From(logger.With().Bool(QueryParamSearchFetchBodies, fetchBodies))
|
||||
@@ -724,7 +721,7 @@ func (g *Groupware) GetEmailsForAllAccounts(w http.ResponseWriter, r *http.Reque
|
||||
if makesSnippets {
|
||||
resultsByAccountId, sessionState, state, lang, jerr := g.jmap.QueryEmailsWithSnippets(allAccountIds, filter, req.session, req.ctx, logger, req.language(), offset, limit, fetchBodies, g.maxBodyValueBytes)
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(joinAccountIds(allAccountIds), jerr)
|
||||
}
|
||||
|
||||
flattenedByAccountId := make(map[string][]EmailWithSnippets, len(resultsByAccountId))
|
||||
@@ -747,7 +744,7 @@ func (g *Groupware) GetEmailsForAllAccounts(w http.ResponseWriter, r *http.Reque
|
||||
|
||||
sanitized, err := req.sanitizeEmail(result.Email)
|
||||
if err != nil {
|
||||
return errorResponseWithSessionState(err, sessionState)
|
||||
return errorResponseWithSessionState(accountId, err, sessionState)
|
||||
}
|
||||
flattened[i] = EmailWithSnippets{
|
||||
AccountId: accountId,
|
||||
@@ -774,16 +771,16 @@ func (g *Groupware) GetEmailsForAllAccounts(w http.ResponseWriter, r *http.Reque
|
||||
|
||||
// TODO offset and limit over the aggregated results by account
|
||||
|
||||
return etagResponse(EmailWithSnippetsSearchResults{
|
||||
return etagResponse(joinAccountIds(allAccountIds), EmailWithSnippetsSearchResults{
|
||||
Results: flattened,
|
||||
Total: totalOverAllAccounts,
|
||||
Limit: limit,
|
||||
QueryState: state,
|
||||
}, sessionState, state, lang)
|
||||
}, sessionState, EmailResponseObjectType, state, lang)
|
||||
} else {
|
||||
resultsByAccountId, sessionState, state, lang, jerr := g.jmap.QueryEmails(allAccountIds, filter, req.session, req.ctx, logger, req.language(), offset, limit, fetchBodies, g.maxBodyValueBytes)
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(joinAccountIds(allAccountIds), jerr)
|
||||
}
|
||||
|
||||
total := 0
|
||||
@@ -800,7 +797,7 @@ func (g *Groupware) GetEmailsForAllAccounts(w http.ResponseWriter, r *http.Reque
|
||||
for _, e := range list.Emails {
|
||||
sanitized, err := req.sanitizeEmail(e)
|
||||
if err != nil {
|
||||
return errorResponseWithSessionState(err, sessionState)
|
||||
return errorResponseWithSessionState(joinAccountIds(allAccountIds), err, sessionState)
|
||||
}
|
||||
flattened[i] = sanitized
|
||||
i++
|
||||
@@ -812,18 +809,18 @@ func (g *Groupware) GetEmailsForAllAccounts(w http.ResponseWriter, r *http.Reque
|
||||
|
||||
// TODO offset and limit over the aggregated results by account
|
||||
|
||||
return etagResponse(EmailSearchResults{
|
||||
return etagResponse(joinAccountIds(allAccountIds), EmailSearchResults{
|
||||
Results: flattened,
|
||||
Total: totalOverAllAccounts,
|
||||
Limit: limit,
|
||||
QueryState: state,
|
||||
}, sessionState, state, lang)
|
||||
}, sessionState, EmailResponseObjectType, state, lang)
|
||||
}
|
||||
} else {
|
||||
if makesSnippets {
|
||||
resultsByAccountId, sessionState, state, lang, jerr := g.jmap.QueryEmailSnippets(allAccountIds, filter, req.session, req.ctx, logger, req.language(), offset, limit)
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(joinAccountIds(allAccountIds), jerr)
|
||||
}
|
||||
|
||||
var totalOverAllAccounts uint = 0
|
||||
@@ -850,12 +847,12 @@ func (g *Groupware) GetEmailsForAllAccounts(w http.ResponseWriter, r *http.Reque
|
||||
|
||||
// TODO offset and limit over the aggregated results by account
|
||||
|
||||
return etagResponse(EmailSearchSnippetsResults{
|
||||
return etagResponse(joinAccountIds(allAccountIds), EmailSearchSnippetsResults{
|
||||
Results: flattened,
|
||||
Total: totalOverAllAccounts,
|
||||
Limit: limit,
|
||||
QueryState: state,
|
||||
}, sessionState, state, lang)
|
||||
}, sessionState, EmailResponseObjectType, state, lang)
|
||||
} else {
|
||||
// TODO implement search without email bodies (only retrieve a few chosen properties?) + without snippets
|
||||
return notImplementesResponse()
|
||||
@@ -864,41 +861,28 @@ func (g *Groupware) GetEmailsForAllAccounts(w http.ResponseWriter, r *http.Reque
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
type EmailCreation struct {
|
||||
MailboxIds []string `json:"mailboxIds,omitempty"`
|
||||
Keywords []string `json:"keywords,omitempty"`
|
||||
From []jmap.EmailAddress `json:"from,omitempty"`
|
||||
Subject string `json:"subject,omitempty"`
|
||||
ReceivedAt time.Time `json:"receivedAt,omitzero"`
|
||||
SentAt time.Time `json:"sentAt,omitzero"` // huh?
|
||||
BodyStructure jmap.EmailBodyStructure `json:"bodyStructure"`
|
||||
BodyValues map[string]jmap.EmailBodyValue `json:"bodyValues,omitempty"`
|
||||
}
|
||||
*/
|
||||
|
||||
func (g *Groupware) CreateEmail(w http.ResponseWriter, r *http.Request) {
|
||||
g.respond(w, r, func(req Request) Response {
|
||||
logger := req.logger
|
||||
|
||||
accountId, gwerr := req.GetAccountIdForMail()
|
||||
if gwerr != nil {
|
||||
return errorResponse(gwerr)
|
||||
return errorResponse(accountId, gwerr)
|
||||
}
|
||||
logger = log.From(logger.With().Str(logAccountId, log.SafeString(accountId)))
|
||||
|
||||
var body jmap.EmailCreate
|
||||
err := req.body(&body)
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
|
||||
created, sessionState, state, lang, jerr := g.jmap.CreateEmail(accountId, body, "", req.session, req.ctx, logger, req.language())
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
|
||||
return etagResponse(created, sessionState, state, lang)
|
||||
return etagResponse(accountId, created, sessionState, EmailResponseObjectType, state, lang)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -908,7 +892,7 @@ func (g *Groupware) ReplaceEmail(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
accountId, gwerr := req.GetAccountIdForMail()
|
||||
if gwerr != nil {
|
||||
return errorResponse(gwerr)
|
||||
return errorResponse(accountId, gwerr)
|
||||
}
|
||||
|
||||
replaceId := chi.URLParam(r, UriParamEmailId)
|
||||
@@ -918,15 +902,15 @@ func (g *Groupware) ReplaceEmail(w http.ResponseWriter, r *http.Request) {
|
||||
var body jmap.EmailCreate
|
||||
err := req.body(&body)
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
|
||||
created, sessionState, state, lang, jerr := g.jmap.CreateEmail(accountId, body, replaceId, req.session, req.ctx, logger, req.language())
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
|
||||
return etagResponse(created, sessionState, state, lang)
|
||||
return etagResponse(accountId, created, sessionState, EmailResponseObjectType, state, lang)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -947,7 +931,7 @@ func (g *Groupware) UpdateEmail(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
accountId, gwerr := req.GetAccountIdForMail()
|
||||
if gwerr != nil {
|
||||
return errorResponse(gwerr)
|
||||
return errorResponse(accountId, gwerr)
|
||||
}
|
||||
l.Str(logAccountId, accountId)
|
||||
|
||||
@@ -956,7 +940,7 @@ func (g *Groupware) UpdateEmail(w http.ResponseWriter, r *http.Request) {
|
||||
var body map[string]any
|
||||
err := req.body(&body)
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
|
||||
updates := map[string]jmap.EmailUpdate{
|
||||
@@ -965,20 +949,20 @@ func (g *Groupware) UpdateEmail(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
result, sessionState, state, lang, jerr := g.jmap.UpdateEmails(accountId, updates, req.session, req.ctx, logger, req.language())
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
|
||||
if result == nil {
|
||||
return errorResponse(apiError(req.errorId(), ErrorApiInconsistency, withTitle("API Inconsistency: Missing Email Update Response",
|
||||
return errorResponse(accountId, apiError(req.errorId(), ErrorApiInconsistency, withTitle("API Inconsistency: Missing Email Update Response",
|
||||
"An internal API behaved unexpectedly: missing Email update response from JMAP endpoint")))
|
||||
}
|
||||
updatedEmail, ok := result[emailId]
|
||||
if !ok {
|
||||
return errorResponse(apiError(req.errorId(), ErrorApiInconsistency, withTitle("API Inconsistency: Wrong Email Update Response ID",
|
||||
return errorResponse(accountId, apiError(req.errorId(), ErrorApiInconsistency, withTitle("API Inconsistency: Wrong Email Update Response ID",
|
||||
"An internal API behaved unexpectedly: wrong Email update ID response from JMAP endpoint")))
|
||||
}
|
||||
|
||||
return etagResponse(updatedEmail, sessionState, state, lang)
|
||||
return etagResponse(accountId, updatedEmail, sessionState, EmailResponseObjectType, state, lang)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1000,7 +984,7 @@ func (g *Groupware) UpdateEmailKeywords(w http.ResponseWriter, r *http.Request)
|
||||
|
||||
accountId, gwerr := req.GetAccountIdForMail()
|
||||
if gwerr != nil {
|
||||
return errorResponse(gwerr)
|
||||
return errorResponse(accountId, gwerr)
|
||||
}
|
||||
l.Str(logAccountId, accountId)
|
||||
|
||||
@@ -1009,11 +993,11 @@ func (g *Groupware) UpdateEmailKeywords(w http.ResponseWriter, r *http.Request)
|
||||
var body emailKeywordUpdates
|
||||
err := req.body(&body)
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
|
||||
if body.IsEmpty() {
|
||||
return noContentResponse(req.session.State)
|
||||
return noContentResponse(accountId, req.session.State)
|
||||
}
|
||||
|
||||
patch := jmap.EmailUpdate{}
|
||||
@@ -1029,20 +1013,20 @@ func (g *Groupware) UpdateEmailKeywords(w http.ResponseWriter, r *http.Request)
|
||||
|
||||
result, sessionState, state, lang, jerr := g.jmap.UpdateEmails(accountId, patches, req.session, req.ctx, logger, req.language())
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
|
||||
if result == nil {
|
||||
return errorResponse(apiError(req.errorId(), ErrorApiInconsistency, withTitle("API Inconsistency: Missing Email Update Response",
|
||||
return errorResponse(accountId, apiError(req.errorId(), ErrorApiInconsistency, withTitle("API Inconsistency: Missing Email Update Response",
|
||||
"An internal API behaved unexpectedly: missing Email update response from JMAP endpoint")))
|
||||
}
|
||||
updatedEmail, ok := result[emailId]
|
||||
if !ok {
|
||||
return errorResponse(apiError(req.errorId(), ErrorApiInconsistency, withTitle("API Inconsistency: Wrong Email Update Response ID",
|
||||
return errorResponse(accountId, apiError(req.errorId(), ErrorApiInconsistency, withTitle("API Inconsistency: Wrong Email Update Response ID",
|
||||
"An internal API behaved unexpectedly: wrong Email update ID response from JMAP endpoint")))
|
||||
}
|
||||
|
||||
return etagResponse(updatedEmail, sessionState, state, lang)
|
||||
return etagResponse(accountId, updatedEmail, sessionState, EmailResponseObjectType, state, lang)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1064,7 +1048,7 @@ func (g *Groupware) AddEmailKeywords(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
accountId, gwerr := req.GetAccountIdForMail()
|
||||
if gwerr != nil {
|
||||
return errorResponse(gwerr)
|
||||
return errorResponse(accountId, gwerr)
|
||||
}
|
||||
l.Str(logAccountId, accountId)
|
||||
|
||||
@@ -1073,11 +1057,11 @@ func (g *Groupware) AddEmailKeywords(w http.ResponseWriter, r *http.Request) {
|
||||
var body []string
|
||||
err := req.body(&body)
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
|
||||
if len(body) < 1 {
|
||||
return noContentResponse(req.session.State)
|
||||
return noContentResponse(accountId, req.session.State)
|
||||
}
|
||||
|
||||
patch := jmap.EmailUpdate{}
|
||||
@@ -1090,23 +1074,23 @@ func (g *Groupware) AddEmailKeywords(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
result, sessionState, state, lang, jerr := g.jmap.UpdateEmails(accountId, patches, req.session, req.ctx, logger, req.language())
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
|
||||
if result == nil {
|
||||
return errorResponse(apiError(req.errorId(), ErrorApiInconsistency, withTitle("API Inconsistency: Missing Email Update Response",
|
||||
return errorResponse(accountId, apiError(req.errorId(), ErrorApiInconsistency, withTitle("API Inconsistency: Missing Email Update Response",
|
||||
"An internal API behaved unexpectedly: missing Email update response from JMAP endpoint")))
|
||||
}
|
||||
updatedEmail, ok := result[emailId]
|
||||
if !ok {
|
||||
return errorResponse(apiError(req.errorId(), ErrorApiInconsistency, withTitle("API Inconsistency: Wrong Email Update Response ID",
|
||||
return errorResponse(accountId, apiError(req.errorId(), ErrorApiInconsistency, withTitle("API Inconsistency: Wrong Email Update Response ID",
|
||||
"An internal API behaved unexpectedly: wrong Email update ID response from JMAP endpoint")))
|
||||
}
|
||||
|
||||
if updatedEmail == nil {
|
||||
return noContentResponseWithEtag(sessionState, state)
|
||||
return noContentResponseWithEtag(accountId, sessionState, EmailResponseObjectType, state)
|
||||
} else {
|
||||
return etagResponse(updatedEmail, sessionState, state, lang)
|
||||
return etagResponse(accountId, updatedEmail, sessionState, EmailResponseObjectType, state, lang)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1129,7 +1113,7 @@ func (g *Groupware) RemoveEmailKeywords(w http.ResponseWriter, r *http.Request)
|
||||
|
||||
accountId, gwerr := req.GetAccountIdForMail()
|
||||
if gwerr != nil {
|
||||
return errorResponse(gwerr)
|
||||
return errorResponse(accountId, gwerr)
|
||||
}
|
||||
l.Str(logAccountId, accountId)
|
||||
|
||||
@@ -1138,11 +1122,11 @@ func (g *Groupware) RemoveEmailKeywords(w http.ResponseWriter, r *http.Request)
|
||||
var body []string
|
||||
err := req.body(&body)
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
|
||||
if len(body) < 1 {
|
||||
return noContentResponse(req.session.State)
|
||||
return noContentResponse(accountId, req.session.State)
|
||||
}
|
||||
|
||||
patch := jmap.EmailUpdate{}
|
||||
@@ -1155,23 +1139,23 @@ func (g *Groupware) RemoveEmailKeywords(w http.ResponseWriter, r *http.Request)
|
||||
|
||||
result, sessionState, state, lang, jerr := g.jmap.UpdateEmails(accountId, patches, req.session, req.ctx, logger, req.language())
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
|
||||
if result == nil {
|
||||
return errorResponse(apiError(req.errorId(), ErrorApiInconsistency, withTitle("API Inconsistency: Missing Email Update Response",
|
||||
return errorResponse(accountId, apiError(req.errorId(), ErrorApiInconsistency, withTitle("API Inconsistency: Missing Email Update Response",
|
||||
"An internal API behaved unexpectedly: missing Email update response from JMAP endpoint")))
|
||||
}
|
||||
updatedEmail, ok := result[emailId]
|
||||
if !ok {
|
||||
return errorResponse(apiError(req.errorId(), ErrorApiInconsistency, withTitle("API Inconsistency: Wrong Email Update Response ID",
|
||||
return errorResponse(accountId, apiError(req.errorId(), ErrorApiInconsistency, withTitle("API Inconsistency: Wrong Email Update Response ID",
|
||||
"An internal API behaved unexpectedly: wrong Email update ID response from JMAP endpoint")))
|
||||
}
|
||||
|
||||
if updatedEmail == nil {
|
||||
return noContentResponseWithEtag(sessionState, state)
|
||||
return noContentResponseWithEtag(accountId, sessionState, EmailResponseObjectType, state)
|
||||
} else {
|
||||
return etagResponse(updatedEmail, sessionState, state, lang)
|
||||
return etagResponse(accountId, updatedEmail, sessionState, EmailResponseObjectType, state, lang)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1194,7 +1178,7 @@ func (g *Groupware) DeleteEmail(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
accountId, gwerr := req.GetAccountIdForMail()
|
||||
if gwerr != nil {
|
||||
return errorResponse(gwerr)
|
||||
return errorResponse(accountId, gwerr)
|
||||
}
|
||||
l.Str(logAccountId, accountId)
|
||||
|
||||
@@ -1202,25 +1186,25 @@ func (g *Groupware) DeleteEmail(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
resp, sessionState, state, _, jerr := g.jmap.DeleteEmails(accountId, []string{emailId}, req.session, req.ctx, logger, req.language())
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
|
||||
for _, e := range resp {
|
||||
desc := e.Description
|
||||
if desc != "" {
|
||||
return errorResponseWithSessionState(apiError(
|
||||
return errorResponseWithSessionState(accountId, apiError(
|
||||
req.errorId(),
|
||||
ErrorFailedToDeleteEmail,
|
||||
withDetail(e.Description),
|
||||
), sessionState)
|
||||
} else {
|
||||
return errorResponseWithSessionState(apiError(
|
||||
return errorResponseWithSessionState(accountId, apiError(
|
||||
req.errorId(),
|
||||
ErrorFailedToDeleteEmail,
|
||||
), sessionState)
|
||||
}
|
||||
}
|
||||
return noContentResponseWithEtag(sessionState, state)
|
||||
return noContentResponseWithEtag(accountId, sessionState, EmailResponseObjectType, state)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1246,26 +1230,27 @@ type SwaggerDeleteEmailsBody struct {
|
||||
// 500: ErrorResponse500
|
||||
func (g *Groupware) DeleteEmails(w http.ResponseWriter, r *http.Request) {
|
||||
g.respond(w, r, func(req Request) Response {
|
||||
var emailIds []string
|
||||
err := req.body(&emailIds)
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
}
|
||||
|
||||
l := req.logger.With()
|
||||
l.Array("emailIds", log.SafeStringArray(emailIds))
|
||||
|
||||
accountId, gwerr := req.GetAccountIdForMail()
|
||||
if gwerr != nil {
|
||||
return errorResponse(gwerr)
|
||||
return errorResponse(accountId, gwerr)
|
||||
}
|
||||
l.Str(logAccountId, accountId)
|
||||
|
||||
var emailIds []string
|
||||
err := req.body(&emailIds)
|
||||
if err != nil {
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
|
||||
l.Array("emailIds", log.SafeStringArray(emailIds))
|
||||
|
||||
logger := log.From(l)
|
||||
|
||||
resp, sessionState, state, _, jerr := g.jmap.DeleteEmails(accountId, emailIds, req.session, req.ctx, logger, req.language())
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
|
||||
if len(resp) > 0 {
|
||||
@@ -1273,26 +1258,32 @@ func (g *Groupware) DeleteEmails(w http.ResponseWriter, r *http.Request) {
|
||||
for emailId, e := range resp {
|
||||
meta[emailId] = e.Description
|
||||
}
|
||||
return errorResponseWithSessionState(apiError(
|
||||
return errorResponseWithSessionState(accountId, apiError(
|
||||
req.errorId(),
|
||||
ErrorFailedToDeleteEmail,
|
||||
withMeta(meta),
|
||||
), sessionState)
|
||||
}
|
||||
return noContentResponseWithEtag(sessionState, state)
|
||||
return noContentResponseWithEtag(accountId, sessionState, EmailResponseObjectType, state)
|
||||
})
|
||||
}
|
||||
|
||||
func (g *Groupware) SendEmail(w http.ResponseWriter, r *http.Request) {
|
||||
g.respond(w, r, func(req Request) Response {
|
||||
emailId := chi.URLParam(r, UriParamEmailId)
|
||||
|
||||
l := req.logger.With()
|
||||
|
||||
accountId, gwerr := req.GetAccountIdForMail()
|
||||
if gwerr != nil {
|
||||
return errorResponse(accountId, gwerr)
|
||||
}
|
||||
l.Str(logAccountId, accountId)
|
||||
|
||||
emailId := chi.URLParam(r, UriParamEmailId)
|
||||
l.Str(UriParamEmailId, log.SafeString(emailId))
|
||||
|
||||
identityId, err := req.getMandatoryStringParam(QueryParamIdentityId)
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
l.Str(QueryParamIdentityId, log.SafeString(identityId))
|
||||
|
||||
@@ -1312,26 +1303,20 @@ func (g *Groupware) SendEmail(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
// only one is set
|
||||
msg := fmt.Sprintf("Missing required value for query parameter '%v'", missing)
|
||||
return errorResponse(req.observedParameterError(ErrorMissingMandatoryRequestParameter,
|
||||
return errorResponse(accountId, req.observedParameterError(ErrorMissingMandatoryRequestParameter,
|
||||
withDetail(msg),
|
||||
withSource(&ErrorSource{Parameter: missing})))
|
||||
}
|
||||
}
|
||||
|
||||
accountId, gwerr := req.GetAccountIdForMail()
|
||||
if gwerr != nil {
|
||||
return errorResponse(gwerr)
|
||||
}
|
||||
l.Str(logAccountId, accountId)
|
||||
|
||||
logger := log.From(l)
|
||||
|
||||
resp, sessionState, state, lang, jerr := g.jmap.SubmitEmail(accountId, identityId, emailId, move, req.session, req.ctx, logger, req.language())
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
|
||||
return etagResponse(resp, sessionState, state, lang)
|
||||
return etagResponse(accountId, resp, sessionState, EmailResponseObjectType, state, lang)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1391,9 +1376,15 @@ func (g *Groupware) RelatedToEmail(w http.ResponseWriter, r *http.Request) {
|
||||
g.respond(w, r, func(req Request) Response {
|
||||
l := req.logger.With().Str(logEmailId, log.SafeString(id))
|
||||
|
||||
accountId, gwerr := req.GetAccountIdForMail()
|
||||
if gwerr != nil {
|
||||
return errorResponse(accountId, gwerr)
|
||||
}
|
||||
l = l.Str(logAccountId, log.SafeString(accountId))
|
||||
|
||||
limit, ok, err := req.parseUIntParam(QueryParamLimit, 10) // TODO configurable default limit
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
if ok {
|
||||
l = l.Uint("limit", limit)
|
||||
@@ -1401,18 +1392,12 @@ func (g *Groupware) RelatedToEmail(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
days, ok, err := req.parseUIntParam(QueryParamDays, 5) // TODO configurable default days
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
if ok {
|
||||
l = l.Uint("days", days)
|
||||
}
|
||||
|
||||
accountId, gwerr := req.GetAccountIdForMail()
|
||||
if gwerr != nil {
|
||||
return errorResponse(gwerr)
|
||||
}
|
||||
l = l.Str(logAccountId, log.SafeString(accountId))
|
||||
|
||||
logger := log.From(l)
|
||||
|
||||
reqId := req.GetRequestId()
|
||||
@@ -1420,13 +1405,13 @@ func (g *Groupware) RelatedToEmail(w http.ResponseWriter, r *http.Request) {
|
||||
emails, sessionState, state, lang, jerr := g.jmap.GetEmails(accountId, req.session, req.ctx, logger, req.language(), []string{id}, true, g.maxBodyValueBytes, false, false)
|
||||
getEmailsDuration := time.Since(getEmailsBefore)
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
|
||||
if len(emails) < 1 {
|
||||
req.observe(g.metrics.EmailByIdDuration.WithLabelValues(req.session.JmapEndpoint, metrics.Values.Result.NotFound), getEmailsDuration.Seconds())
|
||||
logger.Trace().Msg("failed to find any emails matching id") // the id is already in the log field
|
||||
return notFoundResponse(sessionState)
|
||||
return notFoundResponse(accountId, sessionState)
|
||||
} else {
|
||||
req.observe(g.metrics.EmailByIdDuration.WithLabelValues(req.session.JmapEndpoint, metrics.Values.Result.Found), getEmailsDuration.Seconds())
|
||||
}
|
||||
@@ -1482,12 +1467,12 @@ func (g *Groupware) RelatedToEmail(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
sanitized, err := req.sanitizeEmail(email)
|
||||
if err != nil {
|
||||
return errorResponseWithSessionState(err, sessionState)
|
||||
return errorResponseWithSessionState(accountId, err, sessionState)
|
||||
}
|
||||
return etagResponse(AboutEmailResponse{
|
||||
return etagResponse(accountId, AboutEmailResponse{
|
||||
Email: sanitized,
|
||||
RequestId: reqId,
|
||||
}, sessionState, state, lang)
|
||||
}, sessionState, EmailResponseObjectType, state, lang)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1751,9 +1736,13 @@ type EmailSummaries struct {
|
||||
func (g *Groupware) GetLatestEmailsSummaryForAllAccounts(w http.ResponseWriter, r *http.Request) {
|
||||
g.respond(w, r, func(req Request) Response {
|
||||
l := req.logger.With()
|
||||
|
||||
allAccountIds := req.AllAccountIds()
|
||||
l.Array(logAccountId, log.SafeStringArray(allAccountIds))
|
||||
|
||||
limit, ok, err := req.parseUIntParam(QueryParamLimit, 10) // TODO from configuration
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(joinAccountIds(allAccountIds), err)
|
||||
}
|
||||
if ok {
|
||||
l = l.Uint(QueryParamLimit, limit)
|
||||
@@ -1761,7 +1750,7 @@ func (g *Groupware) GetLatestEmailsSummaryForAllAccounts(w http.ResponseWriter,
|
||||
|
||||
offset, ok, err := req.parseUIntParam(QueryParamOffset, 0)
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(joinAccountIds(allAccountIds), err)
|
||||
}
|
||||
if offset > 0 {
|
||||
return notImplementesResponse()
|
||||
@@ -1772,7 +1761,7 @@ func (g *Groupware) GetLatestEmailsSummaryForAllAccounts(w http.ResponseWriter,
|
||||
|
||||
seen, ok, err := req.parseBoolParam(QueryParamSeen, false)
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(joinAccountIds(allAccountIds), err)
|
||||
}
|
||||
if ok {
|
||||
l = l.Bool(QueryParamSeen, seen)
|
||||
@@ -1780,7 +1769,7 @@ func (g *Groupware) GetLatestEmailsSummaryForAllAccounts(w http.ResponseWriter,
|
||||
|
||||
undesirable, ok, err := req.parseBoolParam(QueryParamUndesirable, false)
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(joinAccountIds(allAccountIds), err)
|
||||
}
|
||||
if ok {
|
||||
l = l.Bool(QueryParamUndesirable, undesirable)
|
||||
@@ -1798,14 +1787,11 @@ func (g *Groupware) GetLatestEmailsSummaryForAllAccounts(w http.ResponseWriter,
|
||||
filter = filterFromNotKeywords(notKeywords)
|
||||
}
|
||||
|
||||
allAccountIds := structs.Keys(req.session.Accounts) // TODO(pbleser-oc) do we need a limit for a maximum amount of accounts to query at once?
|
||||
l.Array(logAccountId, log.SafeStringArray(allAccountIds))
|
||||
|
||||
logger := log.From(l)
|
||||
|
||||
emailsSummariesByAccount, sessionState, state, lang, jerr := g.jmap.QueryEmailSummaries(allAccountIds, req.session, req.ctx, logger, req.language(), filter, limit, true)
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(joinAccountIds(allAccountIds), jerr)
|
||||
}
|
||||
|
||||
// sort in memory to respect the overall limit
|
||||
@@ -1829,12 +1815,12 @@ func (g *Groupware) GetLatestEmailsSummaryForAllAccounts(w http.ResponseWriter,
|
||||
summaries[i] = summarizeEmail(all[i].accountId, all[i].email)
|
||||
}
|
||||
|
||||
return etagResponse(EmailSummaries{
|
||||
return etagResponse(joinAccountIds(allAccountIds), EmailSummaries{
|
||||
Emails: summaries,
|
||||
Total: total,
|
||||
Limit: limit,
|
||||
Offset: offset,
|
||||
}, sessionState, state, lang)
|
||||
}, sessionState, EmailResponseObjectType, state, lang)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -31,14 +31,14 @@ func (g *Groupware) GetIdentities(w http.ResponseWriter, r *http.Request) {
|
||||
g.respond(w, r, func(req Request) Response {
|
||||
accountId, err := req.GetAccountIdForMail()
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
logger := log.From(req.logger.With().Str(logAccountId, accountId))
|
||||
res, sessionState, state, lang, jerr := g.jmap.GetAllIdentities(accountId, req.session, req.ctx, logger, req.language())
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
return etagResponse(res, sessionState, state, lang)
|
||||
return etagResponse(accountId, res, sessionState, IdentityResponseObjectType, state, lang)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -46,18 +46,18 @@ func (g *Groupware) GetIdentityById(w http.ResponseWriter, r *http.Request) {
|
||||
g.respond(w, r, func(req Request) Response {
|
||||
accountId, err := req.GetAccountIdForMail()
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
id := chi.URLParam(r, UriParamIdentityId)
|
||||
logger := log.From(req.logger.With().Str(logAccountId, accountId).Str(logIdentityId, id))
|
||||
res, sessionState, state, lang, jerr := g.jmap.GetIdentities(accountId, req.session, req.ctx, logger, req.language(), []string{id})
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
if len(res) < 1 {
|
||||
return notFoundResponse(sessionState)
|
||||
return notFoundResponse(accountId, sessionState)
|
||||
}
|
||||
return etagResponse(res[0], sessionState, state, lang)
|
||||
return etagResponse(accountId, res[0], sessionState, IdentityResponseObjectType, state, lang)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -65,21 +65,21 @@ func (g *Groupware) AddIdentity(w http.ResponseWriter, r *http.Request) {
|
||||
g.respond(w, r, func(req Request) Response {
|
||||
accountId, err := req.GetAccountIdForMail()
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
logger := log.From(req.logger.With().Str(logAccountId, accountId))
|
||||
|
||||
var identity jmap.Identity
|
||||
err = req.body(&identity)
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
|
||||
created, sessionState, state, lang, jerr := g.jmap.CreateIdentity(accountId, req.session, req.ctx, logger, req.language(), identity)
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
return etagResponse(created, sessionState, state, lang)
|
||||
return etagResponse(accountId, created, sessionState, IdentityResponseObjectType, state, lang)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -87,21 +87,21 @@ func (g *Groupware) ModifyIdentity(w http.ResponseWriter, r *http.Request) {
|
||||
g.respond(w, r, func(req Request) Response {
|
||||
accountId, err := req.GetAccountIdForMail()
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
logger := log.From(req.logger.With().Str(logAccountId, accountId))
|
||||
|
||||
var identity jmap.Identity
|
||||
err = req.body(&identity)
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
|
||||
updated, sessionState, state, lang, jerr := g.jmap.UpdateIdentity(accountId, req.session, req.ctx, logger, req.language(), identity)
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
return etagResponse(updated, sessionState, state, lang)
|
||||
return etagResponse(accountId, updated, sessionState, IdentityResponseObjectType, state, lang)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -109,27 +109,27 @@ func (g *Groupware) DeleteIdentity(w http.ResponseWriter, r *http.Request) {
|
||||
g.respond(w, r, func(req Request) Response {
|
||||
accountId, err := req.GetAccountIdForMail()
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
logger := log.From(req.logger.With().Str(logAccountId, accountId))
|
||||
|
||||
id := chi.URLParam(r, UriParamIdentityId)
|
||||
ids := strings.Split(id, ",")
|
||||
if len(ids) < 1 {
|
||||
return req.parameterErrorResponse(UriParamEmailId, fmt.Sprintf("Invalid value for path parameter '%v': '%s': %s", UriParamIdentityId, log.SafeString(id), "empty list of identity ids"))
|
||||
return req.parameterErrorResponse(accountId, UriParamEmailId, fmt.Sprintf("Invalid value for path parameter '%v': '%s': %s", UriParamIdentityId, log.SafeString(id), "empty list of identity ids"))
|
||||
}
|
||||
|
||||
deletion, sessionState, state, _, jerr := g.jmap.DeleteIdentity(accountId, req.session, req.ctx, logger, req.language(), ids)
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
|
||||
notDeletedIds := structs.Missing(ids, deletion)
|
||||
if len(notDeletedIds) == 0 {
|
||||
return noContentResponseWithEtag(sessionState, state)
|
||||
return noContentResponseWithEtag(accountId, sessionState, IdentityResponseObjectType, state)
|
||||
} else {
|
||||
logger.Error().Array("not-deleted", log.SafeStringArray(notDeletedIds)).Msgf("failed to delete %d identities", len(notDeletedIds))
|
||||
return errorResponseWithSessionState(req.apiError(&ErrorFailedToDeleteSomeIdentities,
|
||||
return errorResponseWithSessionState(accountId, req.apiError(&ErrorFailedToDeleteSomeIdentities,
|
||||
withMeta(map[string]any{"ids": notDeletedIds})), sessionState)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/opencloud-eu/opencloud/pkg/jmap"
|
||||
"github.com/opencloud-eu/opencloud/pkg/structs"
|
||||
)
|
||||
|
||||
type IndexLimits struct {
|
||||
@@ -160,20 +159,20 @@ type SwaggerIndexResponse struct {
|
||||
// 200: IndexResponse
|
||||
func (g *Groupware) Index(w http.ResponseWriter, r *http.Request) {
|
||||
g.respond(w, r, func(req Request) Response {
|
||||
accountIds := structs.Keys(req.session.Accounts)
|
||||
accountIds := req.AllAccountIds()
|
||||
|
||||
boot, sessionState, state, lang, err := g.jmap.GetBootstrap(accountIds, req.session, req.ctx, req.logger, req.language())
|
||||
if err != nil {
|
||||
return req.errorResponseFromJmap(err)
|
||||
return req.errorResponseFromJmap(joinAccountIds(accountIds), err)
|
||||
}
|
||||
|
||||
return etagResponse(IndexResponse{
|
||||
return etagResponse(joinAccountIds(accountIds), IndexResponse{
|
||||
Version: Version,
|
||||
Capabilities: Capabilities,
|
||||
Limits: buildIndexLimits(req.session),
|
||||
Accounts: buildIndexAccounts(req.session, boot),
|
||||
PrimaryAccounts: buildIndexPrimaryAccounts(req.session),
|
||||
}, sessionState, state, lang)
|
||||
}, sessionState, IndexResponseObjectType, state, lang)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
|
||||
"github.com/opencloud-eu/opencloud/pkg/jmap"
|
||||
"github.com/opencloud-eu/opencloud/pkg/log"
|
||||
"github.com/opencloud-eu/opencloud/pkg/structs"
|
||||
)
|
||||
|
||||
// When the request succeeds.
|
||||
@@ -40,18 +39,18 @@ func (g *Groupware) GetMailbox(w http.ResponseWriter, r *http.Request) {
|
||||
g.respond(w, r, func(req Request) Response {
|
||||
accountId, err := req.GetAccountIdForMail()
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
|
||||
mailboxes, sessionState, state, lang, jerr := g.jmap.GetMailbox(accountId, req.session, req.ctx, req.logger, req.language(), []string{mailboxId})
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
|
||||
if len(mailboxes.Mailboxes) == 1 {
|
||||
return etagResponse(mailboxes.Mailboxes[0], sessionState, state, lang)
|
||||
return etagResponse(accountId, mailboxes.Mailboxes[0], sessionState, MailboxResponseObjectType, state, lang)
|
||||
} else {
|
||||
return notFoundResponse(sessionState)
|
||||
return notFoundResponse(accountId, sessionState)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -109,41 +108,42 @@ func (g *Groupware) GetMailboxes(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
g.respond(w, r, func(req Request) Response {
|
||||
accountId, err := req.GetAccountIdForMail()
|
||||
if err != nil {
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
|
||||
subscribed, set, err := req.parseBoolParam(QueryParamMailboxSearchSubscribed, false)
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
if set {
|
||||
filter.IsSubscribed = &subscribed
|
||||
hasCriteria = true
|
||||
}
|
||||
|
||||
accountId, err := req.GetAccountIdForMail()
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
}
|
||||
logger := log.From(req.logger.With().Str(logAccountId, accountId))
|
||||
|
||||
if hasCriteria {
|
||||
mailboxesByAccountId, sessionState, state, lang, err := g.jmap.SearchMailboxes([]string{accountId}, req.session, req.ctx, logger, req.language(), filter)
|
||||
if err != nil {
|
||||
return req.errorResponseFromJmap(err)
|
||||
return req.errorResponseFromJmap(accountId, err)
|
||||
}
|
||||
|
||||
if mailboxes, ok := mailboxesByAccountId[accountId]; ok {
|
||||
return etagResponse(sortMailboxSlice(mailboxes), sessionState, state, lang)
|
||||
return etagResponse(accountId, sortMailboxSlice(mailboxes), sessionState, MailboxResponseObjectType, state, lang)
|
||||
} else {
|
||||
return notFoundResponse(sessionState)
|
||||
return notFoundResponse(accountId, sessionState)
|
||||
}
|
||||
} else {
|
||||
mailboxesByAccountId, sessionState, state, lang, err := g.jmap.GetAllMailboxes([]string{accountId}, req.session, req.ctx, logger, req.language())
|
||||
if err != nil {
|
||||
return req.errorResponseFromJmap(err)
|
||||
return req.errorResponseFromJmap(accountId, err)
|
||||
}
|
||||
if mailboxes, ok := mailboxesByAccountId[accountId]; ok {
|
||||
return etagResponse(sortMailboxSlice(mailboxes), sessionState, state, lang)
|
||||
return etagResponse(accountId, sortMailboxSlice(mailboxes), sessionState, MailboxResponseObjectType, state, lang)
|
||||
} else {
|
||||
return notFoundResponse(sessionState)
|
||||
return notFoundResponse(accountId, sessionState)
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -177,33 +177,33 @@ func (g *Groupware) GetMailboxesForAllAccounts(w http.ResponseWriter, r *http.Re
|
||||
}
|
||||
|
||||
g.respond(w, r, func(req Request) Response {
|
||||
accountIds := req.AllAccountIds()
|
||||
if len(accountIds) < 1 {
|
||||
return noContentResponse("", "")
|
||||
}
|
||||
logger := log.From(req.logger.With().Array(logAccountId, log.SafeStringArray(accountIds)))
|
||||
|
||||
subscribed, set, err := req.parseBoolParam(QueryParamMailboxSearchSubscribed, false)
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(joinAccountIds(accountIds), err)
|
||||
}
|
||||
if set {
|
||||
filter.IsSubscribed = &subscribed
|
||||
hasCriteria = true
|
||||
}
|
||||
|
||||
accountIds := structs.Keys(req.session.Accounts)
|
||||
if len(accountIds) < 1 {
|
||||
return noContentResponse("")
|
||||
}
|
||||
logger := log.From(req.logger.With().Array(logAccountId, log.SafeStringArray(accountIds)))
|
||||
|
||||
if hasCriteria {
|
||||
mailboxesByAccountId, sessionState, state, lang, err := g.jmap.SearchMailboxes(accountIds, req.session, req.ctx, logger, req.language(), filter)
|
||||
if err != nil {
|
||||
return req.errorResponseFromJmap(err)
|
||||
return req.errorResponseFromJmap(joinAccountIds(accountIds), err)
|
||||
}
|
||||
return etagResponse(sortMailboxesMap(mailboxesByAccountId), sessionState, state, lang)
|
||||
return etagResponse(joinAccountIds(accountIds), sortMailboxesMap(mailboxesByAccountId), sessionState, MailboxResponseObjectType, state, lang)
|
||||
} else {
|
||||
mailboxesByAccountId, sessionState, state, lang, err := g.jmap.GetAllMailboxes(accountIds, req.session, req.ctx, logger, req.language())
|
||||
if err != nil {
|
||||
return req.errorResponseFromJmap(err)
|
||||
return req.errorResponseFromJmap(joinAccountIds(accountIds), err)
|
||||
}
|
||||
return etagResponse(sortMailboxesMap(mailboxesByAccountId), sessionState, state, lang)
|
||||
return etagResponse(joinAccountIds(accountIds), sortMailboxesMap(mailboxesByAccountId), sessionState, MailboxResponseObjectType, state, lang)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -211,9 +211,9 @@ func (g *Groupware) GetMailboxesForAllAccounts(w http.ResponseWriter, r *http.Re
|
||||
func (g *Groupware) GetMailboxByRoleForAllAccounts(w http.ResponseWriter, r *http.Request) {
|
||||
role := chi.URLParam(r, UriParamRole)
|
||||
g.respond(w, r, func(req Request) Response {
|
||||
accountIds := structs.Keys(req.session.Accounts)
|
||||
accountIds := req.AllAccountIds()
|
||||
if len(accountIds) < 1 {
|
||||
return noContentResponse("")
|
||||
return noContentResponse("", "")
|
||||
}
|
||||
logger := log.From(req.logger.With().Array(logAccountId, log.SafeStringArray(accountIds)).Str("role", role))
|
||||
|
||||
@@ -223,9 +223,9 @@ func (g *Groupware) GetMailboxByRoleForAllAccounts(w http.ResponseWriter, r *htt
|
||||
|
||||
mailboxesByAccountId, sessionState, state, lang, err := g.jmap.SearchMailboxes(accountIds, req.session, req.ctx, logger, req.language(), filter)
|
||||
if err != nil {
|
||||
return req.errorResponseFromJmap(err)
|
||||
return req.errorResponseFromJmap(joinAccountIds(accountIds), err)
|
||||
}
|
||||
return etagResponse(sortMailboxesMap(mailboxesByAccountId), sessionState, state, lang)
|
||||
return etagResponse(joinAccountIds(accountIds), sortMailboxesMap(mailboxesByAccountId), sessionState, MailboxResponseObjectType, state, lang)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -251,28 +251,28 @@ func (g *Groupware) GetMailboxChanges(w http.ResponseWriter, r *http.Request) {
|
||||
g.respond(w, r, func(req Request) Response {
|
||||
l := req.logger.With().Str(HeaderSince, sinceState)
|
||||
|
||||
accountId, err := req.GetAccountIdForMail()
|
||||
if err != nil {
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
l = l.Str(logAccountId, accountId)
|
||||
|
||||
maxChanges, ok, err := req.parseUIntParam(QueryParamMaxChanges, 0)
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
if ok {
|
||||
l = l.Uint(QueryParamMaxChanges, maxChanges)
|
||||
}
|
||||
|
||||
accountId, err := req.GetAccountIdForMail()
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
}
|
||||
l = l.Str(logAccountId, accountId)
|
||||
|
||||
logger := log.From(l)
|
||||
|
||||
changes, sessionState, state, lang, jerr := g.jmap.GetMailboxChanges(accountId, req.session, req.ctx, logger, req.language(), mailboxId, sinceState, true, g.maxBodyValueBytes, maxChanges)
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
|
||||
return etagResponse(changes, sessionState, state, lang)
|
||||
return etagResponse(accountId, changes, sessionState, MailboxResponseObjectType, state, lang)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -295,9 +295,12 @@ func (g *Groupware) GetMailboxChangesForAllAccounts(w http.ResponseWriter, r *ht
|
||||
g.respond(w, r, func(req Request) Response {
|
||||
l := req.logger.With()
|
||||
|
||||
allAccountIds := req.AllAccountIds()
|
||||
l.Array(logAccountId, log.SafeStringArray(allAccountIds))
|
||||
|
||||
sinceStateMap, ok, err := req.parseMapParam(QueryParamSince)
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(joinAccountIds(allAccountIds), err)
|
||||
}
|
||||
if ok {
|
||||
dict := zerolog.Dict()
|
||||
@@ -309,39 +312,36 @@ func (g *Groupware) GetMailboxChangesForAllAccounts(w http.ResponseWriter, r *ht
|
||||
|
||||
maxChanges, ok, err := req.parseUIntParam(QueryParamMaxChanges, 0)
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(joinAccountIds(allAccountIds), err)
|
||||
}
|
||||
if ok {
|
||||
l = l.Uint(QueryParamMaxChanges, maxChanges)
|
||||
}
|
||||
|
||||
allAccountIds := structs.Keys(req.session.Accounts) // TODO(pbleser-oc) do we need a limit for a maximum amount of accounts to query at once?
|
||||
l.Array(logAccountId, log.SafeStringArray(allAccountIds))
|
||||
|
||||
logger := log.From(l)
|
||||
|
||||
changesByAccountId, sessionState, state, lang, jerr := g.jmap.GetMailboxChangesForMultipleAccounts(allAccountIds, req.session, req.ctx, logger, req.language(), sinceStateMap, true, g.maxBodyValueBytes, maxChanges)
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(joinAccountIds(allAccountIds), jerr)
|
||||
}
|
||||
|
||||
return etagResponse(changesByAccountId, sessionState, state, lang)
|
||||
return etagResponse(joinAccountIds(allAccountIds), changesByAccountId, sessionState, MailboxResponseObjectType, state, lang)
|
||||
})
|
||||
}
|
||||
|
||||
func (g *Groupware) GetMailboxRoles(w http.ResponseWriter, r *http.Request) {
|
||||
g.respond(w, r, func(req Request) Response {
|
||||
l := req.logger.With()
|
||||
allAccountIds := structs.Keys(req.session.Accounts) // TODO(pbleser-oc) do we need a limit for a maximum amount of accounts to query at once?
|
||||
allAccountIds := req.AllAccountIds()
|
||||
l.Array(logAccountId, log.SafeStringArray(allAccountIds))
|
||||
logger := log.From(l)
|
||||
|
||||
rolesByAccountId, sessionState, state, lang, jerr := g.jmap.GetMailboxRolesForMultipleAccounts(allAccountIds, req.session, req.ctx, logger, req.language())
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(joinAccountIds(allAccountIds), jerr)
|
||||
}
|
||||
|
||||
return etagResponse(rolesByAccountId, sessionState, state, lang)
|
||||
return etagResponse(joinAccountIds(allAccountIds), rolesByAccountId, sessionState, MailboxResponseObjectType, state, lang)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -353,23 +353,23 @@ func (g *Groupware) UpdateMailbox(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
accountId, err := req.GetAccountIdForMail()
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
l = l.Str(logAccountId, accountId)
|
||||
|
||||
var body jmap.MailboxChange
|
||||
err = req.body(&body)
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
logger := log.From(l)
|
||||
|
||||
updated, sessionState, state, lang, jerr := g.jmap.UpdateMailbox(accountId, req.session, req.ctx, logger, req.language(), mailboxId, "", body)
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
|
||||
return etagResponse(updated, sessionState, state, lang)
|
||||
return etagResponse(accountId, updated, sessionState, MailboxResponseObjectType, state, lang)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -378,23 +378,23 @@ func (g *Groupware) CreateMailbox(w http.ResponseWriter, r *http.Request) {
|
||||
l := req.logger.With()
|
||||
accountId, err := req.GetAccountIdForMail()
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
l = l.Str(logAccountId, accountId)
|
||||
|
||||
var body jmap.MailboxChange
|
||||
err = req.body(&body)
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
logger := log.From(l)
|
||||
|
||||
created, sessionState, state, lang, jerr := g.jmap.CreateMailbox(accountId, req.session, req.ctx, logger, req.language(), "", body)
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
|
||||
return etagResponse(created, sessionState, state, lang)
|
||||
return etagResponse(accountId, created, sessionState, MailboxResponseObjectType, state, lang)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -403,25 +403,26 @@ func (g *Groupware) DeleteMailbox(w http.ResponseWriter, r *http.Request) {
|
||||
mailboxIds := strings.Split(mailboxId, ",")
|
||||
|
||||
g.respond(w, r, func(req Request) Response {
|
||||
if len(mailboxIds) < 1 {
|
||||
return noContentResponse(req.session.State)
|
||||
}
|
||||
|
||||
l := req.logger.With()
|
||||
accountId, err := req.GetAccountIdForMail()
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
l = l.Str(logAccountId, accountId)
|
||||
|
||||
if len(mailboxIds) < 1 {
|
||||
return noContentResponse(accountId, req.session.State)
|
||||
}
|
||||
|
||||
l = l.Array(UriParamMailboxId, log.SafeStringArray(mailboxIds))
|
||||
logger := log.From(l)
|
||||
|
||||
deleted, sessionState, state, lang, jerr := g.jmap.DeleteMailboxes(accountId, req.session, req.ctx, logger, req.language(), "", mailboxIds)
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
|
||||
return etagResponse(deleted, sessionState, state, lang)
|
||||
return etagResponse(accountId, deleted, sessionState, MailboxResponseObjectType, state, lang)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
|
||||
"github.com/opencloud-eu/opencloud/pkg/jmap"
|
||||
"github.com/opencloud-eu/opencloud/pkg/log"
|
||||
"github.com/opencloud-eu/opencloud/pkg/structs"
|
||||
)
|
||||
|
||||
// When the request succeeds.
|
||||
@@ -27,18 +26,18 @@ func (g *Groupware) GetQuota(w http.ResponseWriter, r *http.Request) {
|
||||
g.respond(w, r, func(req Request) Response {
|
||||
accountId, err := req.GetAccountIdForQuota()
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
logger := log.From(req.logger.With().Str(logAccountId, accountId))
|
||||
|
||||
res, sessionState, state, lang, jerr := g.jmap.GetQuotas([]string{accountId}, req.session, req.ctx, logger, req.language())
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
for _, v := range res {
|
||||
return etagResponse(v.List, sessionState, state, lang)
|
||||
return etagResponse(accountId, v.List, sessionState, QuotaResponseObjectType, state, lang)
|
||||
}
|
||||
return notFoundResponse(sessionState)
|
||||
return notFoundResponse(accountId, sessionState)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -64,15 +63,15 @@ type SwaggerGetQuotaForAllAccountsResponse200 struct {
|
||||
// 500: ErrorResponse500
|
||||
func (g *Groupware) GetQuotaForAllAccounts(w http.ResponseWriter, r *http.Request) {
|
||||
g.respond(w, r, func(req Request) Response {
|
||||
accountIds := structs.Keys(req.session.Accounts)
|
||||
accountIds := req.AllAccountIds()
|
||||
if len(accountIds) < 1 {
|
||||
return noContentResponse("")
|
||||
return noContentResponse(joinAccountIds(accountIds), "")
|
||||
}
|
||||
logger := log.From(req.logger.With().Array(logAccountId, log.SafeStringArray(accountIds)))
|
||||
|
||||
res, sessionState, state, lang, jerr := g.jmap.GetQuotas(accountIds, req.session, req.ctx, logger, req.language())
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(joinAccountIds(accountIds), jerr)
|
||||
}
|
||||
|
||||
result := make(map[string]AccountQuota, len(res))
|
||||
@@ -82,6 +81,6 @@ func (g *Groupware) GetQuotaForAllAccounts(w http.ResponseWriter, r *http.Reques
|
||||
Quotas: accountQuotas.List,
|
||||
}
|
||||
}
|
||||
return etagResponse(result, sessionState, state, lang)
|
||||
return etagResponse(joinAccountIds(accountIds), result, sessionState, QuotaResponseObjectType, state, lang)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ func (g *Groupware) GetTaskLists(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
var _ string = accountId
|
||||
|
||||
return response(AllTaskLists, req.session.State, "")
|
||||
return etagResponse(accountId, AllTaskLists, req.session.State, TaskListResponseObjectType, TaskListsState, "")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -65,10 +65,10 @@ func (g *Groupware) GetTaskListById(w http.ResponseWriter, r *http.Request) {
|
||||
// TODO replace with proper implementation
|
||||
for _, tasklist := range AllTaskLists {
|
||||
if tasklist.Id == tasklistId {
|
||||
return response(tasklist, req.session.State, "")
|
||||
return response(accountId, tasklist, req.session.State, "")
|
||||
}
|
||||
}
|
||||
return notFoundResponse(req.session.State)
|
||||
return etagNotFoundResponse(accountId, req.session.State, TaskListResponseObjectType, TaskListsState, "")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -100,8 +100,8 @@ func (g *Groupware) GetTasksInTaskList(w http.ResponseWriter, r *http.Request) {
|
||||
// TODO replace with proper implementation
|
||||
tasks, ok := TaskMapByTaskListId[tasklistId]
|
||||
if !ok {
|
||||
return notFoundResponse(req.session.State)
|
||||
return notFoundResponse(accountId, req.session.State)
|
||||
}
|
||||
return response(tasks, req.session.State, "")
|
||||
return etagResponse(accountId, tasks, req.session.State, TaskResponseObjectType, TaskState, "")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -33,15 +33,15 @@ func (g *Groupware) GetVacation(w http.ResponseWriter, r *http.Request) {
|
||||
g.respond(w, r, func(req Request) Response {
|
||||
accountId, err := req.GetAccountIdForVacationResponse()
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
logger := log.From(req.logger.With().Str(logAccountId, accountId))
|
||||
|
||||
res, sessionState, state, lang, jerr := g.jmap.GetVacationResponse(accountId, req.session, req.ctx, logger, req.language())
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
return etagResponse(res, sessionState, state, lang)
|
||||
return etagResponse(accountId, res, sessionState, VacationResponseResponseObjectType, state, lang)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -67,23 +67,23 @@ type SwaggerSetVacationResponse200 struct {
|
||||
// 500: ErrorResponse500
|
||||
func (g *Groupware) SetVacation(w http.ResponseWriter, r *http.Request) {
|
||||
g.respond(w, r, func(req Request) Response {
|
||||
var body jmap.VacationResponsePayload
|
||||
err := req.body(&body)
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
}
|
||||
|
||||
accountId, err := req.GetAccountIdForVacationResponse()
|
||||
if err != nil {
|
||||
return errorResponse(err)
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
logger := log.From(req.logger.With().Str(logAccountId, accountId))
|
||||
|
||||
res, sessionState, state, lang, jerr := g.jmap.SetVacationResponse(accountId, body, req.session, req.ctx, logger, req.language())
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(jerr)
|
||||
var body jmap.VacationResponsePayload
|
||||
err = req.body(&body)
|
||||
if err != nil {
|
||||
return errorResponse(accountId, err)
|
||||
}
|
||||
|
||||
return etagResponse(res, sessionState, state, lang)
|
||||
res, sessionState, state, lang, jerr := g.jmap.SetVacationResponse(accountId, body, req.session, req.ctx, logger, req.language())
|
||||
if jerr != nil {
|
||||
return req.errorResponseFromJmap(accountId, jerr)
|
||||
}
|
||||
|
||||
return etagResponse(accountId, res, sessionState, VacationResponseResponseObjectType, state, lang)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -629,6 +629,6 @@ func errorResponses(errors ...Error) ErrorResponse {
|
||||
return ErrorResponse{Errors: errors}
|
||||
}
|
||||
|
||||
func (r Request) errorResponseFromJmap(err jmap.Error) Response {
|
||||
return errorResponse(r.apiErrorFromJmap(r.observeJmapError(err)))
|
||||
func (r Request) errorResponseFromJmap(accountId string, err jmap.Error) Response {
|
||||
return errorResponse(accountId, r.apiErrorFromJmap(r.observeJmapError(err)))
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"slices"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
@@ -564,6 +566,13 @@ func (g *Groupware) withSession(w http.ResponseWriter, r *http.Request, handler
|
||||
return response, time.Time{}, true
|
||||
}
|
||||
|
||||
const (
|
||||
SessionStateResponseHeader = "Session-State"
|
||||
StateResponseHeader = "State"
|
||||
ObjectTypeResponseHeader = "Object-Type"
|
||||
AccountIdResponseHeader = "Account-Id"
|
||||
)
|
||||
|
||||
func (g *Groupware) sendResponse(w http.ResponseWriter, r *http.Request, response Response) {
|
||||
if response.err != nil {
|
||||
g.log(response.err)
|
||||
@@ -573,22 +582,8 @@ func (g *Groupware) sendResponse(w http.ResponseWriter, r *http.Request, respons
|
||||
return
|
||||
}
|
||||
|
||||
etag := ""
|
||||
sessionState := ""
|
||||
|
||||
if response.etag != "" {
|
||||
etag = string(response.etag)
|
||||
}
|
||||
|
||||
if response.sessionState != "" {
|
||||
sessionState = string(response.sessionState)
|
||||
if etag == "" {
|
||||
etag = sessionState
|
||||
}
|
||||
}
|
||||
|
||||
if sessionState != "" {
|
||||
w.Header().Add("Session-State", string(sessionState))
|
||||
w.Header().Add(SessionStateResponseHeader, string(response.sessionState))
|
||||
}
|
||||
|
||||
if response.contentLanguage != "" {
|
||||
@@ -596,11 +591,24 @@ func (g *Groupware) sendResponse(w http.ResponseWriter, r *http.Request, respons
|
||||
}
|
||||
|
||||
notModified := false
|
||||
if etag != "" {
|
||||
challenge := r.Header.Get("if-none-match")
|
||||
quotedEtag := "\"" + etag + "\""
|
||||
notModified = challenge != "" && (challenge == etag || challenge == quotedEtag)
|
||||
w.Header().Add("ETag", quotedEtag)
|
||||
{
|
||||
etag := string(response.etag)
|
||||
if etag != "" {
|
||||
challenge := r.Header.Get("if-none-match")
|
||||
quotedEtag := "\"" + etag + "\""
|
||||
notModified = challenge != "" && (challenge == etag || challenge == quotedEtag)
|
||||
w.Header().Add("ETag", quotedEtag)
|
||||
w.Header().Add(StateResponseHeader, etag)
|
||||
}
|
||||
}
|
||||
{
|
||||
ot := string(response.objectType)
|
||||
if ot != "" {
|
||||
w.Header().Add(ObjectTypeResponseHeader, ot)
|
||||
}
|
||||
}
|
||||
if response.accountId != "" {
|
||||
w.Header().Add(AccountIdResponseHeader, response.accountId)
|
||||
}
|
||||
|
||||
if notModified {
|
||||
@@ -699,3 +707,17 @@ func (g *Groupware) MethodNotAllowed(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Add("Unsupported-Method", r.Method) // TODO possibly remove this in production for security reasons?
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
}
|
||||
|
||||
func joinAccountIds(accountIds []string) string {
|
||||
switch len(accountIds) {
|
||||
case 0:
|
||||
return ""
|
||||
case 1:
|
||||
return accountIds[0]
|
||||
default:
|
||||
c := make([]string, len(accountIds))
|
||||
copy(c, accountIds)
|
||||
slices.Sort(c)
|
||||
return strings.Join(c, ",")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,12 +199,16 @@ var T1 = jmap.Task{
|
||||
|
||||
var AllTaskLists = []jmap.TaskList{TL1}
|
||||
|
||||
var TaskListsState = jmap.State("mock")
|
||||
|
||||
var TaskMapByTaskListId = map[string][]jmap.Task{
|
||||
TL1.Id: {
|
||||
T1,
|
||||
},
|
||||
}
|
||||
|
||||
var TaskState = jmap.State("mock")
|
||||
|
||||
func mustParseTime(text string) time.Time {
|
||||
t, err := time.Parse(time.RFC3339, text)
|
||||
if err != nil {
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
|
||||
"github.com/opencloud-eu/opencloud/pkg/jmap"
|
||||
"github.com/opencloud-eu/opencloud/pkg/log"
|
||||
"github.com/opencloud-eu/opencloud/pkg/structs"
|
||||
|
||||
"github.com/opencloud-eu/opencloud/services/groupware/pkg/metrics"
|
||||
groupwaremiddleware "github.com/opencloud-eu/opencloud/services/groupware/pkg/middleware"
|
||||
@@ -75,6 +76,11 @@ var (
|
||||
// errNoPrimaryAccountForWebsocket = errors.New("no primary account for websocket")
|
||||
)
|
||||
|
||||
func (r Request) AllAccountIds() []string {
|
||||
// TODO potentially filter on "subscribed" accounts?
|
||||
return structs.Uniq(structs.Keys(r.session.Accounts))
|
||||
}
|
||||
|
||||
func (r Request) GetAccountIdWithoutFallback() (string, *Error) {
|
||||
accountId := chi.URLParam(r.r, UriParamAccountId)
|
||||
if accountId == "" || isDefaultAccountid(accountId) {
|
||||
@@ -140,22 +146,22 @@ func (r Request) GetAccountIdForContact() (string, *Error) {
|
||||
return r.GetAccountIdForMail()
|
||||
}
|
||||
|
||||
func (r Request) GetAccountForMail() (jmap.Account, *Error) {
|
||||
func (r Request) GetAccountForMail() (string, jmap.Account, *Error) {
|
||||
accountId, err := r.GetAccountIdForMail()
|
||||
if err != nil {
|
||||
return jmap.Account{}, err
|
||||
return "", jmap.Account{}, err
|
||||
}
|
||||
|
||||
account, ok := r.session.Accounts[accountId]
|
||||
if !ok {
|
||||
r.logger.Debug().Msgf("failed to find account '%v'", accountId)
|
||||
// TODO metric for inexistent accounts
|
||||
return jmap.Account{}, apiError(r.errorId(), ErrorNonExistingAccount,
|
||||
return accountId, jmap.Account{}, apiError(r.errorId(), ErrorNonExistingAccount,
|
||||
withDetail(fmt.Sprintf("The account '%v' does not exist", log.SafeString(accountId))),
|
||||
withSource(&ErrorSource{Parameter: UriParamAccountId}),
|
||||
)
|
||||
}
|
||||
return account, nil
|
||||
return accountId, account, nil
|
||||
}
|
||||
|
||||
func (r Request) parameterError(param string, detail string) *Error {
|
||||
@@ -164,8 +170,8 @@ func (r Request) parameterError(param string, detail string) *Error {
|
||||
withSource(&ErrorSource{Parameter: param}))
|
||||
}
|
||||
|
||||
func (r Request) parameterErrorResponse(param string, detail string) Response {
|
||||
return errorResponse(r.parameterError(param, detail))
|
||||
func (r Request) parameterErrorResponse(accountId string, param string, detail string) Response {
|
||||
return errorResponse(accountId, r.parameterError(param, detail))
|
||||
}
|
||||
|
||||
func (r Request) getStringParam(param string, defaultValue string) (string, bool) {
|
||||
@@ -346,26 +352,26 @@ func (r Request) observeJmapError(jerr jmap.Error) jmap.Error {
|
||||
return jerr
|
||||
}
|
||||
|
||||
func (r Request) needTask() (bool, Response) {
|
||||
func (r Request) needTask(accountId string) (bool, Response) {
|
||||
if !IgnoreSessionCapabilityChecks {
|
||||
if r.session.Capabilities.Tasks == nil {
|
||||
return false, errorResponseWithSessionState(r.apiError(&ErrorMissingTasksSessionCapability), r.session.State)
|
||||
return false, errorResponseWithSessionState(accountId, r.apiError(&ErrorMissingTasksSessionCapability), r.session.State)
|
||||
}
|
||||
}
|
||||
return true, Response{}
|
||||
}
|
||||
|
||||
func (r Request) needTaskForAccount(accountId string) (bool, Response) {
|
||||
if ok, resp := r.needTask(); !ok {
|
||||
if ok, resp := r.needTask(accountId); !ok {
|
||||
return ok, resp
|
||||
}
|
||||
account, ok := r.session.Accounts[accountId]
|
||||
if !ok {
|
||||
return false, errorResponseWithSessionState(r.apiError(&ErrorAccountNotFound), r.session.State)
|
||||
return false, errorResponseWithSessionState(accountId, r.apiError(&ErrorAccountNotFound), r.session.State)
|
||||
}
|
||||
if !IgnoreSessionCapabilityChecks {
|
||||
if account.AccountCapabilities.Tasks == nil {
|
||||
return false, errorResponseWithSessionState(r.apiError(&ErrorMissingTasksAccountCapability), r.session.State)
|
||||
return false, errorResponseWithSessionState(accountId, r.apiError(&ErrorMissingTasksAccountCapability), r.session.State)
|
||||
}
|
||||
}
|
||||
return true, Response{}
|
||||
@@ -374,7 +380,7 @@ func (r Request) needTaskForAccount(accountId string) (bool, Response) {
|
||||
func (r Request) needTaskWithAccount() (bool, string, Response) {
|
||||
accountId, err := r.GetAccountIdForTask()
|
||||
if err != nil {
|
||||
return false, "", errorResponse(err)
|
||||
return false, "", errorResponse(accountId, err)
|
||||
}
|
||||
if !IgnoreSessionCapabilityChecks {
|
||||
if ok, resp := r.needTaskForAccount(accountId); !ok {
|
||||
@@ -384,26 +390,26 @@ func (r Request) needTaskWithAccount() (bool, string, Response) {
|
||||
return true, accountId, Response{}
|
||||
}
|
||||
|
||||
func (r Request) needCalendar() (bool, Response) {
|
||||
func (r Request) needCalendar(accountId string) (bool, Response) {
|
||||
if !IgnoreSessionCapabilityChecks {
|
||||
if r.session.Capabilities.Calendars == nil {
|
||||
return false, errorResponseWithSessionState(r.apiError(&ErrorMissingCalendarsSessionCapability), r.session.State)
|
||||
return false, errorResponseWithSessionState(accountId, r.apiError(&ErrorMissingCalendarsSessionCapability), r.session.State)
|
||||
}
|
||||
}
|
||||
return true, Response{}
|
||||
}
|
||||
|
||||
func (r Request) needCalendarForAccount(accountId string) (bool, Response) {
|
||||
if ok, resp := r.needCalendar(); !ok {
|
||||
if ok, resp := r.needCalendar(accountId); !ok {
|
||||
return ok, resp
|
||||
}
|
||||
account, ok := r.session.Accounts[accountId]
|
||||
if !ok {
|
||||
return false, errorResponseWithSessionState(r.apiError(&ErrorAccountNotFound), r.session.State)
|
||||
return false, errorResponseWithSessionState(accountId, r.apiError(&ErrorAccountNotFound), r.session.State)
|
||||
}
|
||||
if !IgnoreSessionCapabilityChecks {
|
||||
if account.AccountCapabilities.Calendars == nil {
|
||||
return false, errorResponseWithSessionState(r.apiError(&ErrorMissingCalendarsAccountCapability), r.session.State)
|
||||
return false, errorResponseWithSessionState(accountId, r.apiError(&ErrorMissingCalendarsAccountCapability), r.session.State)
|
||||
}
|
||||
}
|
||||
return true, Response{}
|
||||
@@ -412,7 +418,7 @@ func (r Request) needCalendarForAccount(accountId string) (bool, Response) {
|
||||
func (r Request) needCalendarWithAccount() (bool, string, Response) {
|
||||
accountId, err := r.GetAccountIdForCalendar()
|
||||
if err != nil {
|
||||
return false, "", errorResponse(err)
|
||||
return false, "", errorResponse(accountId, err)
|
||||
}
|
||||
if !IgnoreSessionCapabilityChecks {
|
||||
if ok, resp := r.needCalendarForAccount(accountId); !ok {
|
||||
@@ -422,23 +428,23 @@ func (r Request) needCalendarWithAccount() (bool, string, Response) {
|
||||
return true, accountId, Response{}
|
||||
}
|
||||
|
||||
func (r Request) needContact() (bool, Response) {
|
||||
func (r Request) needContact(accountId string) (bool, Response) {
|
||||
if r.session.Capabilities.Contacts == nil {
|
||||
return false, errorResponseWithSessionState(r.apiError(&ErrorMissingContactsSessionCapability), r.session.State)
|
||||
return false, errorResponseWithSessionState(accountId, r.apiError(&ErrorMissingContactsSessionCapability), r.session.State)
|
||||
}
|
||||
return true, Response{}
|
||||
}
|
||||
|
||||
func (r Request) needContactForAccount(accountId string) (bool, Response) {
|
||||
if ok, resp := r.needContact(); !ok {
|
||||
if ok, resp := r.needContact(accountId); !ok {
|
||||
return ok, resp
|
||||
}
|
||||
account, ok := r.session.Accounts[accountId]
|
||||
if !ok {
|
||||
return false, errorResponseWithSessionState(r.apiError(&ErrorAccountNotFound), r.session.State)
|
||||
return false, errorResponseWithSessionState(accountId, r.apiError(&ErrorAccountNotFound), r.session.State)
|
||||
}
|
||||
if account.AccountCapabilities.Contacts == nil {
|
||||
return false, errorResponseWithSessionState(r.apiError(&ErrorMissingContactsAccountCapability), r.session.State)
|
||||
return false, errorResponseWithSessionState(accountId, r.apiError(&ErrorMissingContactsAccountCapability), r.session.State)
|
||||
}
|
||||
return true, Response{}
|
||||
}
|
||||
@@ -446,7 +452,7 @@ func (r Request) needContactForAccount(accountId string) (bool, Response) {
|
||||
func (r Request) needContactWithAccount() (bool, string, Response) {
|
||||
accountId, err := r.GetAccountIdForContact()
|
||||
if err != nil {
|
||||
return false, "", errorResponse(err)
|
||||
return false, "", errorResponse(accountId, err)
|
||||
}
|
||||
if ok, resp := r.needContactForAccount(accountId); !ok {
|
||||
return false, accountId, resp
|
||||
|
||||
@@ -6,17 +6,39 @@ import (
|
||||
"github.com/opencloud-eu/opencloud/pkg/jmap"
|
||||
)
|
||||
|
||||
type ResponseObjectType string
|
||||
|
||||
const (
|
||||
IndexResponseObjectType = ResponseObjectType("index")
|
||||
AccountResponseObjectType = ResponseObjectType("account")
|
||||
IdentityResponseObjectType = ResponseObjectType("identity")
|
||||
BlobResponseObjectType = ResponseObjectType("blob")
|
||||
CalendarResponseObjectType = ResponseObjectType("calendar")
|
||||
EventResponseObjectType = ResponseObjectType("event")
|
||||
AddressBookResponseObjectType = ResponseObjectType("addressbook")
|
||||
ContactResponseObjectType = ResponseObjectType("contact")
|
||||
EmailResponseObjectType = ResponseObjectType("email")
|
||||
MailboxResponseObjectType = ResponseObjectType("mailbox")
|
||||
QuotaResponseObjectType = ResponseObjectType("quota")
|
||||
TaskListResponseObjectType = ResponseObjectType("tasklist")
|
||||
TaskResponseObjectType = ResponseObjectType("task")
|
||||
VacationResponseResponseObjectType = ResponseObjectType("vacationresponse")
|
||||
)
|
||||
|
||||
type Response struct {
|
||||
body any
|
||||
status int
|
||||
err *Error
|
||||
etag jmap.State
|
||||
objectType ResponseObjectType
|
||||
accountId string
|
||||
sessionState jmap.SessionState
|
||||
contentLanguage jmap.Language
|
||||
}
|
||||
|
||||
func errorResponse(err *Error) Response {
|
||||
func errorResponse(accountId string, err *Error) Response {
|
||||
return Response{
|
||||
accountId: accountId,
|
||||
body: nil,
|
||||
err: err,
|
||||
etag: "",
|
||||
@@ -24,8 +46,9 @@ func errorResponse(err *Error) Response {
|
||||
}
|
||||
}
|
||||
|
||||
func errorResponseWithSessionState(err *Error, sessionState jmap.SessionState) Response {
|
||||
func errorResponseWithSessionState(accountId string, err *Error, sessionState jmap.SessionState) Response {
|
||||
return Response{
|
||||
accountId: accountId,
|
||||
body: nil,
|
||||
err: err,
|
||||
etag: "",
|
||||
@@ -33,8 +56,9 @@ func errorResponseWithSessionState(err *Error, sessionState jmap.SessionState) R
|
||||
}
|
||||
}
|
||||
|
||||
func response(body any, sessionState jmap.SessionState, contentLanguage jmap.Language) Response {
|
||||
func response(accountId string, body any, sessionState jmap.SessionState, contentLanguage jmap.Language) Response {
|
||||
return Response{
|
||||
accountId: accountId,
|
||||
body: body,
|
||||
err: nil,
|
||||
etag: jmap.State(sessionState),
|
||||
@@ -43,28 +67,34 @@ func response(body any, sessionState jmap.SessionState, contentLanguage jmap.Lan
|
||||
}
|
||||
}
|
||||
|
||||
func etagResponse(body any, sessionState jmap.SessionState, etag jmap.State, contentLanguage jmap.Language) Response {
|
||||
func etagResponse(accountId string, body any, sessionState jmap.SessionState, objectType ResponseObjectType, etag jmap.State, contentLanguage jmap.Language) Response {
|
||||
return Response{
|
||||
accountId: accountId,
|
||||
body: body,
|
||||
err: nil,
|
||||
etag: etag,
|
||||
objectType: objectType,
|
||||
sessionState: sessionState,
|
||||
contentLanguage: contentLanguage,
|
||||
}
|
||||
}
|
||||
|
||||
func etagOnlyResponse(body any, etag jmap.State, contentLanguage jmap.Language) Response {
|
||||
/*
|
||||
func etagOnlyResponse(body any, etag jmap.State, objectType ResponseObjectType, contentLanguage jmap.Language) Response {
|
||||
return Response{
|
||||
body: body,
|
||||
err: nil,
|
||||
etag: etag,
|
||||
objectType: objectType,
|
||||
sessionState: "",
|
||||
contentLanguage: contentLanguage,
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
func noContentResponse(sessionState jmap.SessionState) Response {
|
||||
func noContentResponse(accountId string, sessionState jmap.SessionState) Response {
|
||||
return Response{
|
||||
accountId: accountId,
|
||||
body: nil,
|
||||
status: http.StatusNoContent,
|
||||
err: nil,
|
||||
@@ -73,12 +103,14 @@ func noContentResponse(sessionState jmap.SessionState) Response {
|
||||
}
|
||||
}
|
||||
|
||||
func noContentResponseWithEtag(sessionState jmap.SessionState, etag jmap.State) Response {
|
||||
func noContentResponseWithEtag(accountId string, sessionState jmap.SessionState, objectType ResponseObjectType, etag jmap.State) Response {
|
||||
return Response{
|
||||
accountId: accountId,
|
||||
body: nil,
|
||||
status: http.StatusNoContent,
|
||||
err: nil,
|
||||
etag: etag,
|
||||
objectType: objectType,
|
||||
sessionState: sessionState,
|
||||
}
|
||||
}
|
||||
@@ -107,16 +139,30 @@ func timeoutResponse(sessionState jmap.SessionState) Response {
|
||||
}
|
||||
*/
|
||||
|
||||
func notFoundResponse(sessionState jmap.SessionState) Response {
|
||||
func notFoundResponse(accountId string, sessionState jmap.SessionState) Response {
|
||||
return Response{
|
||||
accountId: accountId,
|
||||
body: nil,
|
||||
status: http.StatusNotFound,
|
||||
err: nil,
|
||||
etag: jmap.State(sessionState),
|
||||
etag: "",
|
||||
sessionState: sessionState,
|
||||
}
|
||||
}
|
||||
|
||||
func etagNotFoundResponse(accountId string, sessionState jmap.SessionState, objectType ResponseObjectType, etag jmap.State, contentLanguage jmap.Language) Response {
|
||||
return Response{
|
||||
accountId: accountId,
|
||||
body: nil,
|
||||
status: http.StatusNotFound,
|
||||
err: nil,
|
||||
etag: etag,
|
||||
objectType: objectType,
|
||||
sessionState: sessionState,
|
||||
contentLanguage: contentLanguage,
|
||||
}
|
||||
}
|
||||
|
||||
func notImplementesResponse() Response {
|
||||
return Response{
|
||||
body: nil,
|
||||
|
||||
Reference in New Issue
Block a user