diff --git a/pkg/jmap/api_addressbook.go b/pkg/jmap/api_addressbook.go
index 4294ebce55..71fd606263 100644
--- a/pkg/jmap/api_addressbook.go
+++ b/pkg/jmap/api_addressbook.go
@@ -2,9 +2,9 @@ package jmap
var NS_ADDRESSBOOKS = ns(JmapContacts)
-func (j *Client) GetAddressbooks(accountId string, ids []string, ctx Context) (Result[AddressBookGetResponse], error) {
+func (j *Client) GetAddressbooks(accountId AccountId, ids []string, ctx Context) (Result[AddressBookGetResponse], error) {
return get(j, "GetAddressbooks", MailboxType,
- func(accountId string, ids []string) AddressBookGetCommand {
+ func(accountId AccountId, ids []string) AddressBookGetCommand {
return AddressBookGetCommand{AccountId: accountId, Ids: ids}
},
AddressBookGetResponse{},
@@ -27,7 +27,7 @@ func (c AddressBookChanges) GetDestroyed() []string { return c.Destroyed }
// Retrieve Address Book changes since a given state.
// @apidoc addressbook,changes
-func (j *Client) GetAddressbookChanges(accountId string, sinceState State, maxChanges uint, ctx Context) (Result[AddressBookChanges], error) {
+func (j *Client) GetAddressbookChanges(accountId AccountId, sinceState State, maxChanges uint, ctx Context) (Result[AddressBookChanges], error) {
return changesA(j, "GetAddressbookChanges", MailboxType,
func() AddressBookChangesCommand {
return AddressBookChangesCommand{AccountId: accountId, SinceState: sinceState, MaxChanges: uintPtr(maxChanges)}
@@ -58,12 +58,12 @@ func (j *Client) GetAddressbookChanges(accountId string, sinceState State, maxCh
)
}
-func (j *Client) CreateAddressBook(accountId string, addressbook AddressBookChange, ctx Context) (Result[*AddressBook], error) {
+func (j *Client) CreateAddressBook(accountId AccountId, addressbook AddressBookChange, ctx Context) (Result[*AddressBook], error) {
return create(j, "CreateAddressBook", MailboxType,
- func(accountId string, create map[string]AddressBookChange) AddressBookSetCommand {
+ func(accountId AccountId, create map[string]AddressBookChange) AddressBookSetCommand {
return AddressBookSetCommand{AccountId: accountId, Create: create}
},
- func(accountId string, ids string) AddressBookGetCommand {
+ func(accountId AccountId, ids string) AddressBookGetCommand {
return AddressBookGetCommand{AccountId: accountId, Ids: []string{ids}}
},
func(resp AddressBookSetResponse) map[string]*AddressBook {
@@ -77,9 +77,9 @@ func (j *Client) CreateAddressBook(accountId string, addressbook AddressBookChan
)
}
-func (j *Client) DeleteAddressBook(accountId string, destroyIds []string, ctx Context) (Result[map[string]SetError], error) {
+func (j *Client) DeleteAddressBook(accountId AccountId, destroyIds []string, ctx Context) (Result[map[string]SetError], error) {
return destroy(j, "DeleteAddressBook", MailboxType,
- func(accountId string, destroy []string) AddressBookSetCommand {
+ func(accountId AccountId, destroy []string) AddressBookSetCommand {
return AddressBookSetCommand{AccountId: accountId, Destroy: destroy}
},
AddressBookSetResponse{},
@@ -88,7 +88,7 @@ func (j *Client) DeleteAddressBook(accountId string, destroyIds []string, ctx Co
)
}
-func (j *Client) UpdateAddressBook(accountId string, id string, changes AddressBookChange, ctx Context) (Result[AddressBook], error) {
+func (j *Client) UpdateAddressBook(accountId AccountId, id string, changes AddressBookChange, ctx Context) (Result[AddressBook], error) {
return update(j, "UpdateAddressBook", MailboxType,
func(update map[string]PatchObject) AddressBookSetCommand {
return AddressBookSetCommand{AccountId: accountId, Update: update}
diff --git a/pkg/jmap/api_blob.go b/pkg/jmap/api_blob.go
index c094e254e2..7cf1037da1 100644
--- a/pkg/jmap/api_blob.go
+++ b/pkg/jmap/api_blob.go
@@ -10,7 +10,7 @@ import (
var NS_BLOB = ns(JmapBlob)
-func (j *Client) GetBlobMetadata(accountId string, ids []string, ctx Context) (Result[BlobGetResponse], error) {
+func (j *Client) GetBlobMetadata(accountId AccountId, ids []string, ctx Context) (Result[BlobGetResponse], error) {
get := BlobGetCommand{
AccountId: accountId,
Ids: ids,
@@ -41,20 +41,20 @@ type UploadedBlobWithHash struct {
Sha512 string `json:"sha:512,omitempty"`
}
-func (j *Client) UploadBlobStream(accountId string, contentType string, body io.Reader, ctx Context) (UploadedBlob, Language, error) {
+func (j *Client) UploadBlobStream(accountId AccountId, contentType string, body io.Reader, ctx Context) (UploadedBlob, Language, error) {
logger := log.From(ctx.Logger.With().Str(logEndpoint, ctx.Session.UploadEndpoint))
ctx = ctx.WithLogger(logger)
// TODO(pbleser-oc) use a library for proper URL template parsing
- uploadUrl := strings.ReplaceAll(ctx.Session.UploadUrlTemplate, "{accountId}", accountId)
+ uploadUrl := strings.ReplaceAll(ctx.Session.UploadUrlTemplate, "{accountId}", string(accountId))
return j.blob.UploadBinary(uploadUrl, ctx.Session.UploadEndpoint, contentType, body, ctx)
}
-func (j *Client) DownloadBlobStream(accountId string, blobId string, name string, typ string, ctx Context) (*BlobDownload, Language, error) { //NOSONAR
+func (j *Client) DownloadBlobStream(accountId AccountId, blobId string, name string, typ string, ctx Context) (*BlobDownload, Language, error) { //NOSONAR
logger := log.From(ctx.Logger.With().Str(logEndpoint, ctx.Session.DownloadEndpoint))
ctx = ctx.WithLogger(logger)
// TODO(pbleser-oc) use a library for proper URL template parsing
downloadUrl := ctx.Session.DownloadUrlTemplate
- downloadUrl = strings.ReplaceAll(downloadUrl, "{accountId}", accountId)
+ downloadUrl = strings.ReplaceAll(downloadUrl, "{accountId}", string(accountId))
downloadUrl = strings.ReplaceAll(downloadUrl, "{blobId}", blobId)
downloadUrl = strings.ReplaceAll(downloadUrl, "{name}", name)
downloadUrl = strings.ReplaceAll(downloadUrl, "{type}", typ)
@@ -62,7 +62,7 @@ func (j *Client) DownloadBlobStream(accountId string, blobId string, name string
return j.blob.DownloadBinary(downloadUrl, ctx.Session.DownloadEndpoint, ctx)
}
-func (j *Client) UploadBlob(accountId string, data []byte, contentType string, ctx Context) (Result[UploadedBlobWithHash], error) {
+func (j *Client) UploadBlob(accountId AccountId, data []byte, contentType string, ctx Context) (Result[UploadedBlobWithHash], error) {
encoded := base64.StdEncoding.EncodeToString(data)
upload := BlobUploadCommand{
@@ -131,5 +131,4 @@ func (j *Client) UploadBlob(accountId string, data []byte, contentType string, c
Sha512: get.DigestSha512,
}, getResponse.State, nil
})
-
}
diff --git a/pkg/jmap/api_bootstrap.go b/pkg/jmap/api_bootstrap.go
index ae373703aa..cf2c69af64 100644
--- a/pkg/jmap/api_bootstrap.go
+++ b/pkg/jmap/api_bootstrap.go
@@ -11,7 +11,7 @@ type AccountBootstrapResult struct {
var NS_MAIL_QUOTA = ns(JmapMail, JmapQuota)
-func (j *Client) GetBootstrap(accountIds []string, ctx Context) (Result[map[string]AccountBootstrapResult], error) { //NOSONAR
+func (j *Client) GetBootstrap(accountIds []AccountId, ctx Context) (Result[map[AccountId]AccountBootstrapResult], error) { //NOSONAR
uniqueAccountIds := structs.Uniq(accountIds)
logger := j.logger("GetBootstrap", ctx)
@@ -25,13 +25,13 @@ func (j *Client) GetBootstrap(accountIds []string, ctx Context) (Result[map[stri
cmd, err := j.request(ctx, NS_MAIL_QUOTA, calls...)
if err != nil {
- return ZeroResult[map[string]AccountBootstrapResult](), err
+ return ZeroResult[map[AccountId]AccountBootstrapResult](), err
}
- return command(j, ctx, cmd, func(body *Response) (map[string]AccountBootstrapResult, State, Error) {
- identityPerAccount := map[string][]Identity{}
- quotaPerAccount := map[string][]Quota{}
- identityStatesPerAccount := map[string]State{}
- quotaStatesPerAccount := map[string]State{}
+ return command(j, ctx, cmd, func(body *Response) (map[AccountId]AccountBootstrapResult, State, Error) {
+ identityPerAccount := map[AccountId][]Identity{}
+ quotaPerAccount := map[AccountId][]Quota{}
+ identityStatesPerAccount := map[AccountId]State{}
+ quotaStatesPerAccount := map[AccountId]State{}
for _, accountId := range uniqueAccountIds {
var identityResponse IdentityGetResponse
err = retrieveResponseMatchParameters(ctx, body, CommandIdentityGet, mcid(accountId, "I"), &identityResponse)
@@ -52,7 +52,7 @@ func (j *Client) GetBootstrap(accountIds []string, ctx Context) (Result[map[stri
}
}
- result := map[string]AccountBootstrapResult{}
+ result := map[AccountId]AccountBootstrapResult{}
for accountId, value := range identityPerAccount {
r, ok := result[accountId]
if !ok {
diff --git a/pkg/jmap/api_calendar.go b/pkg/jmap/api_calendar.go
index 1727501ca0..774541dd46 100644
--- a/pkg/jmap/api_calendar.go
+++ b/pkg/jmap/api_calendar.go
@@ -2,7 +2,7 @@ package jmap
var NS_CALENDARS = ns(JmapCalendars)
-func (j *Client) ParseICalendarBlob(accountId string, blobIds []string, ctx Context) (Result[CalendarEventParseResponse], error) {
+func (j *Client) ParseICalendarBlob(accountId AccountId, blobIds []string, ctx Context) (Result[CalendarEventParseResponse], error) {
logger := j.logger("ParseICalendarBlob", ctx)
parse := CalendarEventParseCommand{AccountId: accountId, BlobIds: blobIds}
@@ -23,9 +23,9 @@ func (j *Client) ParseICalendarBlob(accountId string, blobIds []string, ctx Cont
})
}
-func (j *Client) GetCalendars(accountId string, ids []string, ctx Context) (Result[CalendarGetResponse], error) {
+func (j *Client) GetCalendars(accountId AccountId, ids []string, ctx Context) (Result[CalendarGetResponse], error) {
return get(j, "GetCalendars", CalendarType,
- func(accountId string, ids []string) CalendarGetCommand {
+ func(accountId AccountId, ids []string) CalendarGetCommand {
return CalendarGetCommand{AccountId: accountId, Ids: ids}
},
CalendarGetResponse{},
@@ -48,7 +48,7 @@ func (c CalendarChanges) GetDestroyed() []string { return c.Destroyed }
// Retrieve Calendar changes since a given state.
// @apidoc calendar,changes
-func (j *Client) GetCalendarChanges(accountId string, sinceState State, maxChanges uint, ctx Context) (Result[CalendarChanges], error) {
+func (j *Client) GetCalendarChanges(accountId AccountId, sinceState State, maxChanges uint, ctx Context) (Result[CalendarChanges], error) {
return changes(j, "GetCalendarChanges", CalendarType,
func() CalendarChangesCommand {
return CalendarChangesCommand{AccountId: accountId, SinceState: sinceState, MaxChanges: uintPtr(maxChanges)}
@@ -79,12 +79,12 @@ func (j *Client) GetCalendarChanges(accountId string, sinceState State, maxChang
)
}
-func (j *Client) CreateCalendar(accountId string, calendar CalendarChange, ctx Context) (Result[*Calendar], error) {
+func (j *Client) CreateCalendar(accountId AccountId, calendar CalendarChange, ctx Context) (Result[*Calendar], error) {
return create(j, "CreateCalendar", CalendarEventType,
- func(accountId string, create map[string]CalendarChange) CalendarSetCommand {
+ func(accountId AccountId, create map[string]CalendarChange) CalendarSetCommand {
return CalendarSetCommand{AccountId: accountId, Create: create}
},
- func(accountId string, ref string) CalendarGetCommand {
+ func(accountId AccountId, ref string) CalendarGetCommand {
return CalendarGetCommand{AccountId: accountId, Ids: []string{ref}}
},
func(resp CalendarSetResponse) map[string]*Calendar {
@@ -98,9 +98,9 @@ func (j *Client) CreateCalendar(accountId string, calendar CalendarChange, ctx C
)
}
-func (j *Client) DeleteCalendar(accountId string, destroyIds []string, ctx Context) (Result[map[string]SetError], error) {
+func (j *Client) DeleteCalendar(accountId AccountId, destroyIds []string, ctx Context) (Result[map[string]SetError], error) {
return destroy(j, "DeleteCalendar", CalendarEventType,
- func(accountId string, destroy []string) CalendarSetCommand {
+ func(accountId AccountId, destroy []string) CalendarSetCommand {
return CalendarSetCommand{AccountId: accountId, Destroy: destroy}
},
CalendarSetResponse{},
@@ -109,7 +109,7 @@ func (j *Client) DeleteCalendar(accountId string, destroyIds []string, ctx Conte
)
}
-func (j *Client) UpdateCalendar(accountId string, id string, changes CalendarChange, ctx Context) (Result[Calendar], error) {
+func (j *Client) UpdateCalendar(accountId AccountId, id string, changes CalendarChange, ctx Context) (Result[Calendar], error) {
return update(j, "UpdateCalendar", CalendarEventType,
func(update map[string]PatchObject) CalendarSetCommand {
return CalendarSetCommand{AccountId: accountId, Update: update}
diff --git a/pkg/jmap/api_changes.go b/pkg/jmap/api_changes.go
index 7cc455b687..df54d549e3 100644
--- a/pkg/jmap/api_changes.go
+++ b/pkg/jmap/api_changes.go
@@ -74,7 +74,7 @@ func (s StateMap) MarshalZerologObject(e *zerolog.Event) {
// Retrieve the changes in any type of objects at once since a given State.
// @api:tags changes
-func (j *Client) GetChanges(accountId string, stateMap StateMap, maxChanges uint, ctx Context) (Result[ObjectChanges], error) { //NOSONAR
+func (j *Client) GetChanges(accountId AccountId, stateMap StateMap, maxChanges uint, ctx Context) (Result[ObjectChanges], error) { //NOSONAR
logger := log.From(j.logger("GetChanges", ctx).With().Object("state", stateMap).Uint("maxChanges", maxChanges))
ctx = ctx.WithLogger(logger)
diff --git a/pkg/jmap/api_contact.go b/pkg/jmap/api_contact.go
index d7172eb5c0..4a5ee283b4 100644
--- a/pkg/jmap/api_contact.go
+++ b/pkg/jmap/api_contact.go
@@ -6,9 +6,9 @@ var NS_CONTACTS = ns(JmapContacts)
var DEFAULT_CONTACT_CARD_VERSION = jscontact.JSContactVersion_1_0
-func (j *Client) GetContactCards(accountId string, contactIds []string, ctx Context) (Result[ContactCardGetResponse], error) {
+func (j *Client) GetContactCards(accountId AccountId, contactIds []string, ctx Context) (Result[ContactCardGetResponse], error) {
return get(j, "GetContactCards", ContactCardType,
- func(accountId string, ids []string) ContactCardGetCommand {
+ func(accountId AccountId, ids []string) ContactCardGetCommand {
return ContactCardGetCommand{AccountId: accountId, Ids: contactIds}
},
ContactCardGetResponse{},
@@ -31,7 +31,7 @@ func (c ContactCardChanges) GetDestroyed() []string { return c.Destroyed }
// Retrieve the changes in Contact Cards since a given State.
// @api:tags contact,changes
-func (j *Client) GetContactCardChanges(accountId string, sinceState State, maxChanges uint, ctx Context) (Result[ContactCardChanges], error) {
+func (j *Client) GetContactCardChanges(accountId AccountId, sinceState State, maxChanges uint, ctx Context) (Result[ContactCardChanges], error) {
return changes(j, "GetContactCardChanges", ContactCardType,
func() ContactCardChangesCommand {
return ContactCardChangesCommand{AccountId: accountId, SinceState: sinceState, MaxChanges: uintPtr(maxChanges)}
@@ -77,19 +77,19 @@ func (r *ContactCardSearchResults) RemoveResults() { r.Results = nil
func (r *ContactCardSearchResults) SetLimit(limit *uint) { r.Limit = limit }
func (r *ContactCardSearchResults) SetPosition(position *uint) { r.Position = position }
-func (j *Client) QueryContactCards(accountIds map[string]QueryParams, //NOSONAR
+func (j *Client) QueryContactCards(accountIds map[AccountId]QueryParams, //NOSONAR
limit *uint, filter ContactCardFilterElement, sortBy []ContactCardComparator, calculateTotal bool,
- ctx Context) (Result[map[string]*ContactCardSearchResults], error) {
+ ctx Context) (Result[map[AccountId]*ContactCardSearchResults], error) {
return queryN(j, "QueryContactCards", ContactCardType,
[]ContactCardComparator{{Property: ContactCardPropertyUpdated, IsAscending: false}},
- func(accountId string, qp QueryParams, limit *uint, filter ContactCardFilterElement, sortBy []ContactCardComparator) ContactCardQueryCommand {
+ func(accountId AccountId, qp QueryParams, limit *uint, filter ContactCardFilterElement, sortBy []ContactCardComparator) ContactCardQueryCommand {
if qp.Anchor != "" {
return ContactCardQueryCommand{AccountId: accountId, Filter: filter, Sort: sortBy, Anchor: qp.Anchor, AnchorOffset: qp.AnchorOffset, Limit: limit, CalculateTotal: calculateTotal}
} else {
return ContactCardQueryCommand{AccountId: accountId, Filter: filter, Sort: sortBy, Position: qp.Position, Limit: limit, CalculateTotal: calculateTotal}
}
},
- func(accountId string, cmd Command, path string, rof string) ContactCardGetRefCommand {
+ func(accountId AccountId, cmd Command, path string, rof string) ContactCardGetRefCommand {
return ContactCardGetRefCommand{AccountId: accountId, IdsRef: &ResultReference{Name: cmd, Path: path, ResultOf: rof}}
},
func(query ContactCardQueryResponse, queryParams QueryParams, limit *uint) *ContactCardSearchResults {
@@ -116,15 +116,15 @@ func (j *Client) QueryContactCards(accountIds map[string]QueryParams, //NOSONAR
}
// @api:example create
-func (j *Client) CreateContactCard(accountId string, contact ContactCardChange, ctx Context) (Result[*ContactCard], error) {
+func (j *Client) CreateContactCard(accountId AccountId, contact ContactCardChange, ctx Context) (Result[*ContactCard], error) {
if contact.Version == nil {
contact.Version = &DEFAULT_CONTACT_CARD_VERSION
}
return create(j, "CreateContactCard", ContactCardType,
- func(accountId string, create map[string]ContactCardChange) ContactCardSetCommand {
+ func(accountId AccountId, create map[string]ContactCardChange) ContactCardSetCommand {
return ContactCardSetCommand{AccountId: accountId, Create: create}
},
- func(accountId string, ids string) ContactCardGetCommand {
+ func(accountId AccountId, ids string) ContactCardGetCommand {
return ContactCardGetCommand{AccountId: accountId, Ids: []string{ids}}
},
func(resp ContactCardSetResponse) map[string]*ContactCard {
@@ -138,9 +138,9 @@ func (j *Client) CreateContactCard(accountId string, contact ContactCardChange,
)
}
-func (j *Client) DeleteContactCard(accountId string, destroyIds []string, ctx Context) (Result[map[string]SetError], error) {
+func (j *Client) DeleteContactCard(accountId AccountId, destroyIds []string, ctx Context) (Result[map[string]SetError], error) {
return destroy(j, "DeleteContactCard", ContactCardType,
- func(accountId string, destroy []string) ContactCardSetCommand {
+ func(accountId AccountId, destroy []string) ContactCardSetCommand {
return ContactCardSetCommand{AccountId: accountId, Destroy: destroy}
},
ContactCardSetResponse{},
@@ -150,7 +150,7 @@ func (j *Client) DeleteContactCard(accountId string, destroyIds []string, ctx Co
}
// @api:example update
-func (j *Client) UpdateContactCard(accountId string, id string, changes ContactCardChange, ctx Context) (Result[ContactCard], error) {
+func (j *Client) UpdateContactCard(accountId AccountId, id string, changes ContactCardChange, ctx Context) (Result[ContactCard], error) {
return update(j, "UpdateContactCard", ContactCardType,
func(update map[string]PatchObject) ContactCardSetCommand {
return ContactCardSetCommand{AccountId: accountId, Update: update}
diff --git a/pkg/jmap/api_email.go b/pkg/jmap/api_email.go
index 41ef7c4f24..7eca1a0cab 100644
--- a/pkg/jmap/api_email.go
+++ b/pkg/jmap/api_email.go
@@ -14,7 +14,7 @@ var NS_MAIL = ns(JmapMail)
var NS_MAIL_SUBMISSION = ns(JmapMail, JmapSubmission)
// Retrieve specific Emails by their id.
-func (j *Client) GetEmails(accountId string, ids []string, //NOSONAR
+func (j *Client) GetEmails(accountId AccountId, ids []string, //NOSONAR
fetchBodies bool, maxBodyValueBytes uint, markAsSeen bool, withThreads bool,
ctx Context) (Result[EmailGetResponse], error) {
logger := j.logger("GetEmails", ctx)
@@ -82,7 +82,7 @@ func (j *Client) GetEmails(accountId string, ids []string, //NOSONAR
})
}
-func (j *Client) GetEmailBlobId(accountId string, id string, ctx Context) (Result[string], error) {
+func (j *Client) GetEmailBlobId(accountId AccountId, id string, ctx Context) (Result[string], error) {
logger := j.logger("GetEmailBlobId", ctx)
ctx = ctx.WithLogger(logger)
@@ -119,7 +119,7 @@ func (r *EmailSearchResults) SetLimit(limit *uint) { r.Limi
func (r *EmailSearchResults) SetPosition(position *uint) { r.Position = position }
// Retrieve all the Emails in a given Mailbox by its id.
-func (j *Client) GetAllEmailsInMailbox(accountId string, mailboxId string, //NOSONAR
+func (j *Client) GetAllEmailsInMailbox(accountId AccountId, mailboxId string, //NOSONAR
qp QueryParams, limit *uint, collapseThreads bool, fetchBodies bool, maxBodyValueBytes uint, withThreads bool,
ctx Context) (Result[*EmailSearchResults], error) {
logger := j.loggerParams("GetAllEmailsInMailbox", ctx, func(z zerolog.Context) zerolog.Context {
@@ -220,7 +220,7 @@ func (c EmailChanges) GetDestroyed() []string { return c.Destroyed }
// Retrieve the changes in Emails since a given State.
// @api:tags email,changes
-func (j *Client) GetEmailChanges(accountId string,
+func (j *Client) GetEmailChanges(accountId AccountId,
sinceState State, fetchBodies bool, maxBodyValueBytes uint, maxChanges uint,
ctx Context) (Result[EmailChanges], error) { //NOSONAR
logger := j.loggerParams("GetEmailChanges", ctx, func(z zerolog.Context) zerolog.Context {
@@ -302,9 +302,9 @@ type SearchSnippetWithMeta struct {
type EmailSnippetSearchResults SearchResultsTemplate[SearchSnippetWithMeta]
-func (j *Client) QueryEmailSnippets(accountIds []string, //NOSONAR
+func (j *Client) QueryEmailSnippets(accountIds []AccountId, //NOSONAR
filter EmailFilterElement, position int, anchor string, anchorOffset *int, limit *uint,
- ctx Context) (Result[map[string]EmailSnippetSearchResults], error) {
+ ctx Context) (Result[map[AccountId]EmailSnippetSearchResults], error) {
logger := j.loggerParams("QueryEmailSnippets", ctx, func(z zerolog.Context) zerolog.Context {
l := z.Int(logPosition, position)
if limit != nil {
@@ -358,12 +358,12 @@ func (j *Client) QueryEmailSnippets(accountIds []string, //NOSONAR
cmd, err := j.request(ctx, NS_MAIL, invocations...)
if err != nil {
- return ZeroResult[map[string]EmailSnippetSearchResults](), err
+ return ZeroResult[map[AccountId]EmailSnippetSearchResults](), err
}
- return command(j, ctx, cmd, func(body *Response) (map[string]EmailSnippetSearchResults, State, Error) {
- results := make(map[string]EmailSnippetSearchResults, len(uniqueAccountIds))
- states := make(map[string]State, len(uniqueAccountIds))
+ return command(j, ctx, cmd, func(body *Response) (map[AccountId]EmailSnippetSearchResults, State, Error) {
+ results := make(map[AccountId]EmailSnippetSearchResults, len(uniqueAccountIds))
+ states := make(map[AccountId]State, len(uniqueAccountIds))
for _, accountId := range uniqueAccountIds {
var queryResponse EmailQueryResponse
err = retrieveResponseMatchParameters(ctx, body, CommandEmailQuery, mcid(accountId, "0"), &queryResponse)
@@ -428,9 +428,9 @@ type EmailQueryResult struct {
}
*/
-func (j *Client) QueryEmails(accountIds []string,
+func (j *Client) QueryEmails(accountIds []AccountId,
filter EmailFilterElement, position int, limit uint, fetchBodies bool, maxBodyValueBytes uint,
- ctx Context) (Result[map[string]EmailSearchResults], error) { //NOSONAR
+ ctx Context) (Result[map[AccountId]EmailSearchResults], error) { //NOSONAR
logger := j.loggerParams("QueryEmails", ctx, func(z zerolog.Context) zerolog.Context {
return z.Bool(logFetchBodies, fetchBodies)
})
@@ -470,12 +470,12 @@ func (j *Client) QueryEmails(accountIds []string,
cmd, err := j.request(ctx, NS_MAIL, invocations...)
if err != nil {
- return ZeroResult[map[string]EmailSearchResults](), err
+ return ZeroResult[map[AccountId]EmailSearchResults](), err
}
- return command(j, ctx, cmd, func(body *Response) (map[string]EmailSearchResults, State, Error) {
- results := make(map[string]EmailSearchResults, len(uniqueAccountIds))
- queryStates := map[string]State{}
+ return command(j, ctx, cmd, func(body *Response) (map[AccountId]EmailSearchResults, State, Error) {
+ results := make(map[AccountId]EmailSearchResults, len(uniqueAccountIds))
+ queryStates := map[AccountId]State{}
for _, accountId := range uniqueAccountIds {
var queryResponse EmailQueryResponse
err = retrieveResponseMatchParameters(ctx, body, CommandEmailQuery, mcid(accountId, "0"), &queryResponse)
@@ -515,9 +515,9 @@ type EmailQueryWithSnippetsResult struct {
QueryState State `json:"queryState"`
}
-func (j *Client) QueryEmailsWithSnippets(accountIds []string, //NOSONAR
+func (j *Client) QueryEmailsWithSnippets(accountIds []AccountId, //NOSONAR
filter EmailFilterElement, position int, anchor string, anchorOffset *int, limit *uint, collapseThreads bool, calculateTotal bool, fetchBodies bool, maxBodyValueBytes uint,
- ctx Context) (Result[map[string]EmailQueryWithSnippetsResult], error) {
+ ctx Context) (Result[map[AccountId]EmailQueryWithSnippetsResult], error) {
logger := j.loggerParams("QueryEmailsWithSnippets", ctx, func(z zerolog.Context) zerolog.Context {
return z.Bool(logFetchBodies, fetchBodies)
})
@@ -565,11 +565,11 @@ func (j *Client) QueryEmailsWithSnippets(accountIds []string, //NOSONAR
cmd, err := j.request(ctx, NS_MAIL, invocations...)
if err != nil {
- return ZeroResult[map[string]EmailQueryWithSnippetsResult](), err
+ return ZeroResult[map[AccountId]EmailQueryWithSnippetsResult](), err
}
- return command(j, ctx, cmd, func(body *Response) (map[string]EmailQueryWithSnippetsResult, State, Error) {
- result := make(map[string]EmailQueryWithSnippetsResult, len(uniqueAccountIds))
+ return command(j, ctx, cmd, func(body *Response) (map[AccountId]EmailQueryWithSnippetsResult, State, Error) {
+ result := make(map[AccountId]EmailQueryWithSnippetsResult, len(uniqueAccountIds))
for _, accountId := range uniqueAccountIds {
var queryResponse EmailQueryResponse
err = retrieveResponseMatchParameters(ctx, body, CommandEmailQuery, mcid(accountId, "0"), &queryResponse)
@@ -629,7 +629,7 @@ type UploadedEmail struct {
Sha512 string `json:"sha:512"`
}
-func (j *Client) ImportEmail(accountId string, data []byte, ctx Context) (Result[UploadedEmail], error) {
+func (j *Client) ImportEmail(accountId AccountId, data []byte, ctx Context) (Result[UploadedEmail], error) {
encoded := base64.StdEncoding.EncodeToString(data)
upload := BlobUploadCommand{
@@ -702,7 +702,7 @@ func (j *Client) ImportEmail(accountId string, data []byte, ctx Context) (Result
}
-func (j *Client) CreateEmail(accountId string, email EmailChange, replaceId string, ctx Context) (Result[*Email], error) {
+func (j *Client) CreateEmail(accountId AccountId, email EmailChange, replaceId string, ctx Context) (Result[*Email], error) {
set := EmailSetCommand{
AccountId: accountId,
Create: map[string]EmailChange{
@@ -757,7 +757,7 @@ func (j *Client) CreateEmail(accountId string, email EmailChange, replaceId stri
// To create drafts, use the CreateEmail function instead.
//
// To delete mails, use the DeleteEmails function instead.
-func (j *Client) UpdateEmails(accountId string, updates map[string]PatchObject, ctx Context) (Result[map[string]*Email], error) {
+func (j *Client) UpdateEmails(accountId AccountId, updates map[string]PatchObject, ctx Context) (Result[map[string]*Email], error) {
set := EmailSetCommand{
AccountId: accountId,
Update: updates,
@@ -783,7 +783,7 @@ func (j *Client) UpdateEmails(accountId string, updates map[string]PatchObject,
})
}
-func (j *Client) UpdateEmail(accountId string, id string, changes EmailChange, ctx Context) (Result[Email], error) {
+func (j *Client) UpdateEmail(accountId AccountId, id string, changes EmailChange, ctx Context) (Result[Email], error) {
return update(j, "UpdateEmail", EmailType,
func(update map[string]PatchObject) EmailSetCommand {
return EmailSetCommand{AccountId: accountId, Update: update}
@@ -798,9 +798,9 @@ func (j *Client) UpdateEmail(accountId string, id string, changes EmailChange, c
)
}
-func (j *Client) DeleteEmails(accountId string, destroyIds []string, ctx Context) (Result[map[string]SetError], error) {
+func (j *Client) DeleteEmails(accountId AccountId, destroyIds []string, ctx Context) (Result[map[string]SetError], error) {
return destroy(j, "DeleteEmails", EmailType,
- func(accountId string, destroy []string) EmailSetCommand {
+ func(accountId AccountId, destroy []string) EmailSetCommand {
return EmailSetCommand{AccountId: accountId, Destroy: destroy}
},
EmailSetResponse{},
@@ -838,7 +838,7 @@ type MoveMail struct {
ToMailboxId string
}
-func (j *Client) SubmitEmail(accountId string, identityId string, emailId string, move *MoveMail, //NOSONAR
+func (j *Client) SubmitEmail(accountId AccountId, identityId string, emailId string, move *MoveMail, //NOSONAR
ctx Context) (Result[EmailSubmission], error) {
logger := j.logger("SubmitEmail", ctx)
ctx = ctx.WithLogger(logger)
@@ -926,7 +926,7 @@ func (j *Client) SubmitEmail(accountId string, identityId string, emailId string
})
}
-func (j *Client) GetEmailSubmissionStatus(accountId string, submissionIds []string, ctx Context) (Result[EmailSubmissionGetResponse], error) {
+func (j *Client) GetEmailSubmissionStatus(accountId AccountId, submissionIds []string, ctx Context) (Result[EmailSubmissionGetResponse], error) {
logger := j.logger("GetEmailSubmissionStatus", ctx)
ctx = ctx.WithLogger(logger)
@@ -949,7 +949,7 @@ func (j *Client) GetEmailSubmissionStatus(accountId string, submissionIds []stri
})
}
-func (j *Client) EmailsInThread(accountId string, threadId string,
+func (j *Client) EmailsInThread(accountId AccountId, threadId string,
fetchBodies bool, maxBodyValueBytes uint,
ctx Context) (Result[[]Email], Error) { //NOSONAR
logger := j.loggerParams("EmailsInThread", ctx, func(z zerolog.Context) zerolog.Context {
@@ -1018,9 +1018,9 @@ var EmailSummaryProperties = []string{
EmailPropertyPreview,
}
-func (j *Client) QueryEmailSummaries(accountIds []string, //NOSONAR
+func (j *Client) QueryEmailSummaries(accountIds []AccountId, //NOSONAR
filter EmailFilterElement, position int, anchor string, anchorOffset *int, limit *uint, withThreads bool, calculateTotal bool,
- ctx Context) (Result[map[string]EmailsSummary], error) {
+ ctx Context) (Result[map[AccountId]EmailsSummary], error) {
logger := j.logger("QueryEmailSummaries", ctx)
ctx = ctx.WithLogger(logger)
@@ -1067,11 +1067,11 @@ func (j *Client) QueryEmailSummaries(accountIds []string, //NOSONAR
}
cmd, err := j.request(ctx, NS_MAIL, invocations...)
if err != nil {
- return ZeroResult[map[string]EmailsSummary](), err
+ return ZeroResult[map[AccountId]EmailsSummary](), err
}
- return command(j, ctx, cmd, func(body *Response) (map[string]EmailsSummary, State, Error) {
- resp := map[string]EmailsSummary{}
+ return command(j, ctx, cmd, func(body *Response) (map[AccountId]EmailsSummary, State, Error) {
+ resp := map[AccountId]EmailsSummary{}
for _, accountId := range uniqueAccountIds {
var queryResponse EmailQueryResponse
err = retrieveResponseMatchParameters(ctx, body, CommandEmailQuery, mcid(accountId, "0"), &queryResponse)
@@ -1112,7 +1112,7 @@ type EmailSubmissionChanges = ChangesTemplate[EmailSubmission]
// Retrieve the changes in Email Submissions since a given State.
// @api:tags email,changes
-func (j *Client) GetEmailSubmissionChanges(accountId string, sinceState State, maxChanges uint,
+func (j *Client) GetEmailSubmissionChanges(accountId AccountId, sinceState State, maxChanges uint,
ctx Context) (Result[EmailSubmissionChanges], error) {
return changes(j, "GetEmailSubmissionChanges", EmailSubmissionType,
func() EmailSubmissionChangesCommand {
diff --git a/pkg/jmap/api_event.go b/pkg/jmap/api_event.go
index 8e7d8469d1..374cf5d295 100644
--- a/pkg/jmap/api_event.go
+++ b/pkg/jmap/api_event.go
@@ -17,9 +17,9 @@ func (r *CalendarEventSearchResults) RemoveResults() { r.Results = n
func (r *CalendarEventSearchResults) SetLimit(limit *uint) { r.Limit = limit }
func (r *CalendarEventSearchResults) SetPosition(position *uint) { r.Position = position }
-func (j *Client) GetCalendarEvents(accountId string, eventIds []string, ctx Context) (Result[CalendarEventGetResponse], error) {
+func (j *Client) GetCalendarEvents(accountId AccountId, eventIds []string, ctx Context) (Result[CalendarEventGetResponse], error) {
return get(j, "GetCalendarEvents", CalendarEventType,
- func(accountId string, ids []string) CalendarEventGetCommand {
+ func(accountId AccountId, ids []string) CalendarEventGetCommand {
return CalendarEventGetCommand{AccountId: accountId, Ids: eventIds}
},
CalendarEventGetResponse{},
@@ -29,15 +29,15 @@ func (j *Client) GetCalendarEvents(accountId string, eventIds []string, ctx Cont
)
}
-func (j *Client) QueryCalendarEvents(accountIds map[string]QueryParams, limit *uint, //NOSONAR
+func (j *Client) QueryCalendarEvents(accountIds map[AccountId]QueryParams, limit *uint, //NOSONAR
filter CalendarEventFilterElement, sortBy []CalendarEventComparator, calculateTotal bool,
- ctx Context) (Result[map[string]*CalendarEventSearchResults], error) {
+ ctx Context) (Result[map[AccountId]*CalendarEventSearchResults], error) {
return queryN(j, "QueryCalendarEvents", CalendarEventType,
[]CalendarEventComparator{{Property: CalendarEventPropertyStart, IsAscending: false}},
- func(accountId string, queryParams QueryParams, limit *uint, filter CalendarEventFilterElement, sortBy []CalendarEventComparator) CalendarEventQueryCommand {
+ func(accountId AccountId, queryParams QueryParams, limit *uint, filter CalendarEventFilterElement, sortBy []CalendarEventComparator) CalendarEventQueryCommand {
return CalendarEventQueryCommand{AccountId: accountId, Filter: filter, Sort: sortBy, Position: queryParams.Position, Anchor: queryParams.Anchor, AnchorOffset: queryParams.AnchorOffset, Limit: limit, CalculateTotal: calculateTotal}
},
- func(accountId string, cmd Command, path string, rof string) CalendarEventGetRefCommand {
+ func(accountId AccountId, cmd Command, path string, rof string) CalendarEventGetRefCommand {
return CalendarEventGetRefCommand{AccountId: accountId, IdsRef: &ResultReference{Name: cmd, Path: path, ResultOf: rof}}
},
func(query CalendarEventQueryResponse, queryParams QueryParams, limit *uint) *CalendarEventSearchResults {
@@ -76,7 +76,7 @@ func (c CalendarEventChanges) GetDestroyed() []string { return c.Destroyed
// Retrieve the changes in Calendar Events since a given State.
// @api:tags event,changes
-func (j *Client) GetCalendarEventChanges(accountId string, sinceState State, maxChanges uint,
+func (j *Client) GetCalendarEventChanges(accountId AccountId, sinceState State, maxChanges uint,
ctx Context) (Result[CalendarEventChanges], error) {
return changes(j, "GetCalendarEventChanges", CalendarEventType,
func() CalendarEventChangesCommand {
@@ -108,12 +108,12 @@ func (j *Client) GetCalendarEventChanges(accountId string, sinceState State, max
)
}
-func (j *Client) CreateCalendarEvent(accountId string, event CalendarEventChange, ctx Context) (Result[*CalendarEvent], error) {
+func (j *Client) CreateCalendarEvent(accountId AccountId, event CalendarEventChange, ctx Context) (Result[*CalendarEvent], error) {
return create(j, "CreateCalendarEvent", CalendarEventType,
- func(accountId string, create map[string]CalendarEventChange) CalendarEventSetCommand {
+ func(accountId AccountId, create map[string]CalendarEventChange) CalendarEventSetCommand {
return CalendarEventSetCommand{AccountId: accountId, Create: create}
},
- func(accountId string, ref string) CalendarEventGetCommand {
+ func(accountId AccountId, ref string) CalendarEventGetCommand {
return CalendarEventGetCommand{AccountId: accountId, Ids: []string{ref}}
},
func(resp CalendarEventSetResponse) map[string]*CalendarEvent {
@@ -127,9 +127,9 @@ func (j *Client) CreateCalendarEvent(accountId string, event CalendarEventChange
)
}
-func (j *Client) DeleteCalendarEvent(accountId string, destroyIds []string, ctx Context) (Result[map[string]SetError], error) {
+func (j *Client) DeleteCalendarEvent(accountId AccountId, destroyIds []string, ctx Context) (Result[map[string]SetError], error) {
return destroy(j, "DeleteCalendarEvent", CalendarEventType,
- func(accountId string, destroy []string) CalendarEventSetCommand {
+ func(accountId AccountId, destroy []string) CalendarEventSetCommand {
return CalendarEventSetCommand{AccountId: accountId, Destroy: destroy}
},
CalendarEventSetResponse{},
@@ -138,7 +138,7 @@ func (j *Client) DeleteCalendarEvent(accountId string, destroyIds []string, ctx
)
}
-func (j *Client) UpdateCalendarEvent(accountId string, id string, changes CalendarEventChange, ctx Context) (Result[CalendarEvent], error) {
+func (j *Client) UpdateCalendarEvent(accountId AccountId, id string, changes CalendarEventChange, ctx Context) (Result[CalendarEvent], error) {
return update(j, "UpdateCalendarEvent", CalendarEventType,
func(update map[string]PatchObject) CalendarEventSetCommand {
return CalendarEventSetCommand{AccountId: accountId, Update: update}
diff --git a/pkg/jmap/api_identity.go b/pkg/jmap/api_identity.go
index da13c549a3..d3bf5bda14 100644
--- a/pkg/jmap/api_identity.go
+++ b/pkg/jmap/api_identity.go
@@ -8,9 +8,9 @@ import (
var NS_IDENTITY = ns(JmapMail)
-func (j *Client) GetIdentities(accountId string, identityIds []string, ctx Context) (Result[IdentityGetResponse], error) {
+func (j *Client) GetIdentities(accountId AccountId, identityIds []string, ctx Context) (Result[IdentityGetResponse], error) {
return get(j, "GetIdentities", IdentityType,
- func(accountId string, ids []string) IdentityGetCommand {
+ func(accountId AccountId, ids []string) IdentityGetCommand {
return IdentityGetCommand{AccountId: accountId, Ids: ids}
},
IdentityGetResponse{},
@@ -20,9 +20,9 @@ func (j *Client) GetIdentities(accountId string, identityIds []string, ctx Conte
)
}
-func (j *Client) GetIdentitiesForAllAccounts(accountIds []string, ctx Context) (Result[map[string][]Identity], error) {
+func (j *Client) GetIdentitiesForAllAccounts(accountIds []AccountId, ctx Context) (Result[map[AccountId][]Identity], error) {
return getN(j, "GetIdentitiesForAllAccounts", IdentityType,
- func(accountId string, ids []string) IdentityGetCommand {
+ func(accountId AccountId, ids []string) IdentityGetCommand {
return IdentityGetCommand{AccountId: accountId}
},
IdentityGetResponse{},
@@ -34,12 +34,12 @@ func (j *Client) GetIdentitiesForAllAccounts(accountIds []string, ctx Context) (
}
type IdentitiesAndMailboxesGetResponse struct {
- Identities map[string][]Identity `json:"identities,omitempty"`
- NotFound []string `json:"notFound,omitempty"`
- Mailboxes []Mailbox `json:"mailboxes"`
+ Identities map[AccountId][]Identity `json:"identities,omitempty"`
+ NotFound []string `json:"notFound,omitempty"`
+ Mailboxes []Mailbox `json:"mailboxes"`
}
-func (j *Client) GetIdentitiesAndMailboxes(mailboxAccountId string, accountIds []string, ctx Context) (Result[IdentitiesAndMailboxesGetResponse], error) {
+func (j *Client) GetIdentitiesAndMailboxes(mailboxAccountId AccountId, accountIds []AccountId, ctx Context) (Result[IdentitiesAndMailboxesGetResponse], error) {
uniqueAccountIds := structs.Uniq(accountIds)
logger := j.logger("GetIdentitiesAndMailboxes", ctx)
@@ -56,8 +56,8 @@ func (j *Client) GetIdentitiesAndMailboxes(mailboxAccountId string, accountIds [
return ZeroResult[IdentitiesAndMailboxesGetResponse](), err
}
return command(j, ctx, cmd, func(body *Response) (IdentitiesAndMailboxesGetResponse, State, Error) {
- identities := make(map[string][]Identity, len(uniqueAccountIds))
- stateByAccountId := make(map[string]State, len(uniqueAccountIds))
+ identities := make(map[AccountId][]Identity, len(uniqueAccountIds))
+ stateByAccountId := make(map[AccountId]State, len(uniqueAccountIds))
notFound := []string{}
for i, accountId := range uniqueAccountIds {
var response IdentityGetResponse
@@ -85,12 +85,12 @@ func (j *Client) GetIdentitiesAndMailboxes(mailboxAccountId string, accountIds [
})
}
-func (j *Client) CreateIdentity(accountId string, identity IdentityChange, ctx Context) (Result[*Identity], error) {
+func (j *Client) CreateIdentity(accountId AccountId, identity IdentityChange, ctx Context) (Result[*Identity], error) {
return create(j, "CreateIdentity", IdentityType,
- func(accountId string, create map[string]IdentityChange) IdentitySetCommand {
+ func(accountId AccountId, create map[string]IdentityChange) IdentitySetCommand {
return IdentitySetCommand{AccountId: accountId, Create: create}
},
- func(accountId string, ids string) IdentityGetCommand {
+ func(accountId AccountId, ids string) IdentityGetCommand {
return IdentityGetCommand{AccountId: accountId, Ids: []string{ids}}
},
func(resp IdentitySetResponse) map[string]*Identity {
@@ -104,7 +104,7 @@ func (j *Client) CreateIdentity(accountId string, identity IdentityChange, ctx C
)
}
-func (j *Client) UpdateIdentity(accountId string, id string, changes IdentityChange, ctx Context) (Result[Identity], error) {
+func (j *Client) UpdateIdentity(accountId AccountId, id string, changes IdentityChange, ctx Context) (Result[Identity], error) {
return update(j, "UpdateIdentity", IdentityType,
func(update map[string]PatchObject) IdentitySetCommand {
return IdentitySetCommand{AccountId: accountId, Update: update}
@@ -119,9 +119,9 @@ func (j *Client) UpdateIdentity(accountId string, id string, changes IdentityCha
)
}
-func (j *Client) DeleteIdentity(accountId string, destroyIds []string, ctx Context) (Result[map[string]SetError], error) {
+func (j *Client) DeleteIdentity(accountId AccountId, destroyIds []string, ctx Context) (Result[map[string]SetError], error) {
return destroy(j, "DeleteIdentity", IdentityType,
- func(accountId string, destroy []string) IdentitySetCommand {
+ func(accountId AccountId, destroy []string) IdentitySetCommand {
return IdentitySetCommand{AccountId: accountId, Destroy: destroyIds}
},
IdentitySetResponse{},
@@ -143,7 +143,7 @@ func (c IdentityChanges) GetDestroyed() []string { return c.Destroyed }
// Retrieve the changes in Email Identities since a given State.
// @api:tags email,changes
-func (j *Client) GetIdentityChanges(accountId string, sinceState State, maxChanges uint,
+func (j *Client) GetIdentityChanges(accountId AccountId, sinceState State, maxChanges uint,
ctx Context) (Result[IdentityChanges], error) {
return changes(j, "GetIdentityChanges", IdentityType,
func() IdentityChangesCommand {
diff --git a/pkg/jmap/api_mailbox.go b/pkg/jmap/api_mailbox.go
index 7e5fb72393..48447b74bb 100644
--- a/pkg/jmap/api_mailbox.go
+++ b/pkg/jmap/api_mailbox.go
@@ -8,9 +8,9 @@ import (
var NS_MAILBOX = ns(JmapMail)
-func (j *Client) GetMailbox(accountId string, ids []string, ctx Context) (Result[MailboxGetResponse], error) {
+func (j *Client) GetMailbox(accountId AccountId, ids []string, ctx Context) (Result[MailboxGetResponse], error) {
return get(j, "GetMailbox", MailboxType,
- func(accountId string, ids []string) MailboxGetCommand {
+ func(accountId AccountId, ids []string) MailboxGetCommand {
return MailboxGetCommand{AccountId: accountId, Ids: ids}
},
MailboxGetResponse{},
@@ -20,9 +20,9 @@ func (j *Client) GetMailbox(accountId string, ids []string, ctx Context) (Result
)
}
-func (j *Client) GetAllMailboxes(accountIds []string, ctx Context) (Result[map[string][]Mailbox], error) {
+func (j *Client) GetAllMailboxes(accountIds []AccountId, ctx Context) (Result[map[AccountId][]Mailbox], error) {
return getAN(j, "GetAllMailboxes", MailboxType,
- func(accountId string, ids []string) MailboxGetCommand {
+ func(accountId AccountId, ids []string) MailboxGetCommand {
return MailboxGetCommand{AccountId: accountId}
},
MailboxGetResponse{},
@@ -32,7 +32,7 @@ func (j *Client) GetAllMailboxes(accountIds []string, ctx Context) (Result[map[s
)
}
-func (j *Client) SearchMailboxes(accountIds []string, filter MailboxFilterElement, ctx Context) (Result[map[string][]Mailbox], error) {
+func (j *Client) SearchMailboxes(accountIds []AccountId, filter MailboxFilterElement, ctx Context) (Result[map[AccountId][]Mailbox], error) {
logger := j.logger("SearchMailboxes", ctx)
ctx = ctx.WithLogger(logger)
@@ -52,12 +52,12 @@ func (j *Client) SearchMailboxes(accountIds []string, filter MailboxFilterElemen
}
cmd, err := j.request(ctx, NS_MAILBOX, invocations...)
if err != nil {
- return ZeroResult[map[string][]Mailbox](), err
+ return ZeroResult[map[AccountId][]Mailbox](), err
}
- return command(j, ctx, cmd, func(body *Response) (map[string][]Mailbox, State, Error) {
- resp := map[string][]Mailbox{}
- stateByAccountid := map[string]State{}
+ return command(j, ctx, cmd, func(body *Response) (map[AccountId][]Mailbox, State, Error) {
+ resp := map[AccountId][]Mailbox{}
+ stateByAccountid := map[AccountId]State{}
for _, accountId := range uniqueAccountIds {
var response MailboxGetResponse
err = retrieveResponseMatchParameters(ctx, body, CommandMailboxGet, mcid(accountId, "1"), &response)
@@ -72,7 +72,7 @@ func (j *Client) SearchMailboxes(accountIds []string, filter MailboxFilterElemen
})
}
-func (j *Client) SearchMailboxIdsPerRole(accountIds []string, roles []string, ctx Context) (Result[map[string]map[string]string], error) { //NOSONAR
+func (j *Client) SearchMailboxIdsPerRole(accountIds []AccountId, roles []string, ctx Context) (Result[map[AccountId]map[string]string], error) { //NOSONAR
logger := j.logger("SearchMailboxIdsPerRole", ctx)
ctx = ctx.WithLogger(logger)
@@ -86,12 +86,12 @@ func (j *Client) SearchMailboxIdsPerRole(accountIds []string, roles []string, ct
}
cmd, err := j.request(ctx, NS_MAILBOX, invocations...)
if err != nil {
- return ZeroResult[map[string]map[string]string](), err
+ return ZeroResult[map[AccountId]map[string]string](), err
}
- return command(j, ctx, cmd, func(body *Response) (map[string]map[string]string, State, Error) {
- resp := map[string]map[string]string{}
- stateByAccountid := map[string]State{}
+ return command(j, ctx, cmd, func(body *Response) (map[AccountId]map[string]string, State, Error) {
+ resp := map[AccountId]map[string]string{}
+ stateByAccountid := map[AccountId]State{}
for _, accountId := range uniqueAccountIds {
mailboxIdsByRole := map[string]string{}
for _, role := range roles {
@@ -137,7 +137,7 @@ func newMailboxChanges(oldState, newState State, hasMoreChanges bool, created, u
// Retrieve Mailbox changes since a given state.
// @apidoc mailboxes,changes
-func (j *Client) GetMailboxChanges(accountId string, sinceState State, maxChanges uint, ctx Context) (Result[MailboxChanges], error) {
+func (j *Client) GetMailboxChanges(accountId AccountId, sinceState State, maxChanges uint, ctx Context) (Result[MailboxChanges], error) {
return changesA(j, "GetMailboxChanges", MailboxType,
func() MailboxChangesCommand {
return MailboxChangesCommand{AccountId: accountId, SinceState: sinceState, MaxChanges: uintPtr(maxChanges)}
@@ -161,16 +161,16 @@ func (j *Client) GetMailboxChanges(accountId string, sinceState State, maxChange
// Retrieve Mailbox changes of multiple Accounts.
// @api:tags email,changes
-func (j *Client) GetMailboxChangesForMultipleAccounts(accountIds []string, //NOSONAR
- sinceStateMap map[string]State, maxChanges uint,
- ctx Context) (Result[map[string]MailboxChanges], error) {
+func (j *Client) GetMailboxChangesForMultipleAccounts(accountIds []AccountId, //NOSONAR
+ sinceStateMap map[AccountId]State, maxChanges uint,
+ ctx Context) (Result[map[AccountId]MailboxChanges], error) {
return changesN(j, "GetMailboxChangesForMultipleAccounts", MailboxType,
accountIds, sinceStateMap,
- func(accountId string, state State) MailboxChangesCommand {
+ func(accountId AccountId, state State) MailboxChangesCommand {
return MailboxChangesCommand{AccountId: accountId, SinceState: state, MaxChanges: uintPtr(maxChanges)}
},
MailboxChangesResponse{},
- func(accountId string, path string, ref string) MailboxGetRefCommand {
+ func(accountId AccountId, path string, ref string) MailboxGetRefCommand {
return MailboxGetRefCommand{AccountId: accountId, IdsRef: &ResultReference{Name: CommandMailboxChanges, Path: path, ResultOf: ref}}
},
func(resp MailboxGetResponse) []Mailbox { return resp.List },
@@ -181,13 +181,13 @@ func (j *Client) GetMailboxChangesForMultipleAccounts(accountIds []string, //NOS
)
}
-func (j *Client) GetMailboxRolesForMultipleAccounts(accountIds []string, ctx Context) (Result[map[string]*[]string], error) {
+func (j *Client) GetMailboxRolesForMultipleAccounts(accountIds []AccountId, ctx Context) (Result[map[AccountId]*[]string], error) {
return queryN(j, "GetMailboxRolesForMultipleAccounts", MailboxType,
[]MailboxComparator{{Property: MailboxPropertySortOrder, IsAscending: true}},
- func(accountId string, _ QueryParams, _ *uint, filter MailboxFilterCondition, sortBy []MailboxComparator) MailboxQueryCommand {
+ func(accountId AccountId, _ QueryParams, _ *uint, filter MailboxFilterCondition, sortBy []MailboxComparator) MailboxQueryCommand {
return MailboxQueryCommand{AccountId: accountId, Filter: filter, Sort: sortBy, SortAsTree: false, FilterAsTree: false, Position: 0, Anchor: "", AnchorOffset: nil, Limit: nil, CalculateTotal: false}
},
- func(accountId string, cmd Command, path, rof string) MailboxGetRefCommand {
+ func(accountId AccountId, cmd Command, path, rof string) MailboxGetRefCommand {
return MailboxGetRefCommand{AccountId: accountId, IdsRef: &ResultReference{Name: cmd, Path: path, ResultOf: rof}}
},
func(_ MailboxQueryResponse, _ QueryParams, _ *uint) *[]string {
@@ -203,14 +203,14 @@ func (j *Client) GetMailboxRolesForMultipleAccounts(accountIds []string, ctx Con
)
}
-func (j *Client) GetInboxNameForMultipleAccounts(accountIds []string, ctx Context) (Result[map[string]string], error) {
+func (j *Client) GetInboxNameForMultipleAccounts(accountIds []AccountId, ctx Context) (Result[map[AccountId]string], error) {
logger := j.logger("GetInboxNameForMultipleAccounts", ctx)
ctx = ctx.WithLogger(logger)
uniqueAccountIds := structs.Uniq(accountIds)
n := len(uniqueAccountIds)
if n < 1 {
- return ZeroResult[map[string]string](), nil
+ return ZeroResult[map[AccountId]string](), nil
}
invocations := make([]Invocation, n*2)
@@ -225,12 +225,12 @@ func (j *Client) GetInboxNameForMultipleAccounts(accountIds []string, ctx Contex
cmd, err := j.request(ctx, NS_MAILBOX, invocations...)
if err != nil {
- return ZeroResult[map[string]string](), err
+ return ZeroResult[map[AccountId]string](), err
}
- return command(j, ctx, cmd, func(body *Response) (map[string]string, State, Error) {
- resp := make(map[string]string, n)
- stateByAccountId := make(map[string]State, n)
+ return command(j, ctx, cmd, func(body *Response) (map[AccountId]string, State, Error) {
+ resp := make(map[AccountId]string, n)
+ stateByAccountId := make(map[AccountId]State, n)
for _, accountId := range uniqueAccountIds {
var r MailboxQueryResponse
err = retrieveResponseMatchParameters(ctx, body, CommandMailboxGet, mcid(accountId, "0"), &r)
@@ -253,7 +253,7 @@ func (j *Client) GetInboxNameForMultipleAccounts(accountIds []string, ctx Contex
})
}
-func (j *Client) UpdateMailbox(accountId string, mailboxId string, change MailboxChange, //NOSONAR
+func (j *Client) UpdateMailbox(accountId AccountId, mailboxId string, change MailboxChange, //NOSONAR
ctx Context) (Result[Mailbox], error) {
return update(j, "UpdateMailbox", MailboxType,
func(update map[string]PatchObject) MailboxSetCommand {
@@ -269,12 +269,12 @@ func (j *Client) UpdateMailbox(accountId string, mailboxId string, change Mailbo
)
}
-func (j *Client) CreateMailbox(accountId string, mailbox MailboxChange, ctx Context) (Result[*Mailbox], error) {
+func (j *Client) CreateMailbox(accountId AccountId, mailbox MailboxChange, ctx Context) (Result[*Mailbox], error) {
return create(j, "CreateMailbox", MailboxType,
- func(accountId string, create map[string]MailboxChange) MailboxSetCommand {
+ func(accountId AccountId, create map[string]MailboxChange) MailboxSetCommand {
return MailboxSetCommand{AccountId: accountId, Create: create}
},
- func(accountId string, ids string) MailboxGetCommand {
+ func(accountId AccountId, ids string) MailboxGetCommand {
return MailboxGetCommand{AccountId: accountId, Ids: []string{ids}}
},
func(resp MailboxSetResponse) map[string]*Mailbox {
@@ -288,9 +288,9 @@ func (j *Client) CreateMailbox(accountId string, mailbox MailboxChange, ctx Cont
)
}
-func (j *Client) DeleteMailboxes(accountId string, destroyIds []string, ctx Context) (Result[map[string]SetError], error) {
+func (j *Client) DeleteMailboxes(accountId AccountId, destroyIds []string, ctx Context) (Result[map[string]SetError], error) {
return destroy(j, "DeleteMailboxes", MailboxType,
- func(accountId string, destroy []string) MailboxSetCommand {
+ func(accountId AccountId, destroy []string) MailboxSetCommand {
return MailboxSetCommand{AccountId: accountId, Destroy: destroyIds}
},
MailboxSetResponse{},
diff --git a/pkg/jmap/api_objects.go b/pkg/jmap/api_objects.go
index 401523e110..14820a84a2 100644
--- a/pkg/jmap/api_objects.go
+++ b/pkg/jmap/api_objects.go
@@ -20,7 +20,7 @@ type Objects struct {
// Retrieve objects of all types by their identifiers in a single batch.
// @api:tags changes
-func (j *Client) GetObjects(accountId string, //NOSONAR
+func (j *Client) GetObjects(accountId AccountId, //NOSONAR
mailboxIds []string, emailIds []string,
addressbookIds []string, contactIds []string,
calendarIds []string, eventIds []string,
diff --git a/pkg/jmap/api_principal.go b/pkg/jmap/api_principal.go
index 9f3470bcdb..6cf66fc4a6 100644
--- a/pkg/jmap/api_principal.go
+++ b/pkg/jmap/api_principal.go
@@ -2,9 +2,9 @@ package jmap
var NS_PRINCIPALS = ns(JmapPrincipals)
-func (j *Client) GetPrincipals(accountId string, ids []string, ctx Context) (Result[PrincipalGetResponse], error) {
+func (j *Client) GetPrincipals(accountId AccountId, ids []PrincipalId, ctx Context) (Result[PrincipalGetResponse], error) {
return get(j, "GetPrincipals", PrincipalType,
- func(accountId string, ids []string) PrincipalGetCommand {
+ func(accountId AccountId, ids []PrincipalId) PrincipalGetCommand {
return PrincipalGetCommand{AccountId: accountId, Ids: ids}
},
PrincipalGetResponse{},
@@ -29,15 +29,15 @@ func (r *PrincipalSearchResults) RemoveResults() { r.Results = nil }
func (r *PrincipalSearchResults) SetLimit(limit *uint) { r.Limit = limit }
func (r *PrincipalSearchResults) SetPosition(position *uint) { r.Position = position }
-func (j *Client) QueryPrincipals(accountIds map[string]QueryParams, limit *uint, //NOSONAR
+func (j *Client) QueryPrincipals(accountIds map[AccountId]QueryParams, limit *uint, //NOSONAR
filter PrincipalFilterElement, sortBy []PrincipalComparator, calculateTotal bool,
- ctx Context) (Result[map[string]*PrincipalSearchResults], error) {
+ ctx Context) (Result[map[AccountId]*PrincipalSearchResults], error) {
return queryN(j, "QueryPrincipals", PrincipalType,
[]PrincipalComparator{{Property: PrincipalPropertyName, IsAscending: true}},
- func(accountId string, p QueryParams, limit *uint, filter PrincipalFilterElement, sortBy []PrincipalComparator) PrincipalQueryCommand {
+ func(accountId AccountId, p QueryParams, limit *uint, filter PrincipalFilterElement, sortBy []PrincipalComparator) PrincipalQueryCommand {
return PrincipalQueryCommand{AccountId: accountId, Filter: filter, Sort: sortBy, Position: p.Position, Anchor: p.Anchor, AnchorOffset: p.AnchorOffset, Limit: limit, CalculateTotal: calculateTotal}
},
- func(accountId string, cmd Command, path, rof string) PrincipalGetRefCommand {
+ func(accountId AccountId, cmd Command, path, rof string) PrincipalGetRefCommand {
return PrincipalGetRefCommand{AccountId: accountId, IdsRef: &ResultReference{Name: cmd, Path: path, ResultOf: rof}}
},
func(query PrincipalQueryResponse, queryParams QueryParams, limit *uint) *PrincipalSearchResults {
diff --git a/pkg/jmap/api_quota.go b/pkg/jmap/api_quota.go
index 3950402c7d..4fbb6e34f8 100644
--- a/pkg/jmap/api_quota.go
+++ b/pkg/jmap/api_quota.go
@@ -2,9 +2,9 @@ package jmap
var NS_QUOTA = ns(JmapQuota)
-func (j *Client) GetQuotas(accountIds []string, ctx Context) (Result[map[string]QuotaGetResponse], error) {
+func (j *Client) GetQuotas(accountIds []AccountId, ctx Context) (Result[map[AccountId]QuotaGetResponse], error) {
return getN(j, "GetQuotas", QuotaType,
- func(accountId string, ids []string) QuotaGetCommand {
+ func(accountId AccountId, ids []string) QuotaGetCommand {
return QuotaGetCommand{AccountId: accountId}
},
QuotaGetResponse{},
@@ -28,7 +28,7 @@ func (c QuotaChanges) GetDestroyed() []string { return c.Destroyed }
// Retrieve the changes in Quotas since a given State.
// @api:tags quota,changes
-func (j *Client) GetQuotaChanges(accountId string, sinceState State, maxChanges uint,
+func (j *Client) GetQuotaChanges(accountId AccountId, sinceState State, maxChanges uint,
ctx Context) (Result[QuotaChanges], error) {
return changesA(j, "GetQuotaChanges", QuotaType,
func() QuotaChangesCommand {
@@ -60,7 +60,7 @@ func (j *Client) GetQuotaChanges(accountId string, sinceState State, maxChanges
)
}
-func (j *Client) GetQuotaUsageChanges(accountId string, sinceState State, maxChanges uint,
+func (j *Client) GetQuotaUsageChanges(accountId AccountId, sinceState State, maxChanges uint,
ctx Context) (Result[QuotaChanges], error) {
return updates(j, "GetQuotaUsageChanges", QuotaType,
func() QuotaChangesCommand {
diff --git a/pkg/jmap/api_vacation.go b/pkg/jmap/api_vacation.go
index 21eb6ad1ce..eab5d50b78 100644
--- a/pkg/jmap/api_vacation.go
+++ b/pkg/jmap/api_vacation.go
@@ -11,9 +11,9 @@ const (
vacationResponseId = "singleton"
)
-func (j *Client) GetVacationResponse(accountId string, ctx Context) (Result[VacationResponseGetResponse], error) {
+func (j *Client) GetVacationResponse(accountId AccountId, ctx Context) (Result[VacationResponseGetResponse], error) {
return get(j, "GetVacationResponse", VacationResponseType,
- func(accountId string, ids []string) VacationResponseGetCommand {
+ func(accountId AccountId, ids []string) VacationResponseGetCommand {
return VacationResponseGetCommand{AccountId: accountId}
},
VacationResponseGetResponse{},
@@ -64,7 +64,7 @@ func (c VacationResponseChanges) GetCreated() []VacationResponse { return c.Crea
func (c VacationResponseChanges) GetUpdated() []VacationResponse { return c.Updated }
func (c VacationResponseChanges) GetDestroyed() []string { return c.Destroyed }
-func (j *Client) SetVacationResponse(accountId string, vacation VacationResponseChange,
+func (j *Client) SetVacationResponse(accountId AccountId, vacation VacationResponseChange,
ctx Context) (Result[VacationResponse], error) {
logger := j.logger("SetVacationResponse", ctx)
ctx = ctx.WithLogger(logger)
diff --git a/pkg/jmap/export_integration_test.go b/pkg/jmap/export_integration_test.go
index 3d8dc02721..ae596bbfd1 100644
--- a/pkg/jmap/export_integration_test.go
+++ b/pkg/jmap/export_integration_test.go
@@ -584,8 +584,8 @@ type uploadedBlob struct {
Sha512 string `json:"sha:512"`
}
-func (j *TestJmapClient) uploadBlob(accountId string, data []byte, mimetype string) (uploadedBlob, error) { //NOSONAR
- uploadUrl := strings.ReplaceAll(j.session.UploadUrl, "{accountId}", accountId)
+func (j *TestJmapClient) uploadBlob(accountId AccountId, data []byte, mimetype string) (uploadedBlob, error) { //NOSONAR
+ uploadUrl := strings.ReplaceAll(j.session.UploadUrl, "{accountId}", string(accountId))
req, err := http.NewRequest(http.MethodPost, uploadUrl, bytes.NewReader(data))
if err != nil {
return uploadedBlob{}, err
@@ -707,7 +707,7 @@ func (c Commander[T]) command(body map[string]any) (T, error) {
return c.closure(methodResponses)
}
-func (j *TestJmapClient) objectsById(accountId string, objectType ObjectType) (map[string]map[string]any, error) {
+func (j *TestJmapClient) objectsById(accountId AccountId, objectType ObjectType) (map[string]map[string]any, error) {
m := map[string]map[string]any{}
{
body := map[string]any{
@@ -1154,13 +1154,13 @@ func deepEqual[T any](t *testing.T, expected, actual T) {
}
func containerTest[OBJ Idable, RESP GetResponse[OBJ], BOXES any, CHANGE Change](t *testing.T, //NOSONAR
- acc func(session *Session) string,
+ acc func(session *Session) AccountId,
obj func(RESP) []OBJ,
id func(OBJ) string,
- get func(s *StalwartTest, accountId string, ids []string, ctx Context) (Result[RESP], error),
- update func(s *StalwartTest, accountId string, id string, change CHANGE, ctx Context) (Result[OBJ], error),
- destroy func(s *StalwartTest, accountId string, ids []string, ctx Context) (Result[map[string]SetError], error),
- fill func(s *StalwartTest, t *testing.T, accountId string, count uint, ctx Context, _ User, principalIds []string) (BOXES, []OBJ, SessionState, State, error),
+ get func(s *StalwartTest, accountId AccountId, ids []string, ctx Context) (Result[RESP], error),
+ update func(s *StalwartTest, accountId AccountId, id string, change CHANGE, ctx Context) (Result[OBJ], error),
+ destroy func(s *StalwartTest, accountId AccountId, ids []string, ctx Context) (Result[map[string]SetError], error),
+ fill func(s *StalwartTest, t *testing.T, accountId AccountId, count uint, ctx Context, _ User, principalIds []PrincipalId) (BOXES, []OBJ, SessionState, State, error),
change func(OBJ) CHANGE,
checkChanged func(t *testing.T, orig OBJ, change CHANGE, changed OBJ),
) {
@@ -1177,12 +1177,12 @@ func containerTest[OBJ Idable, RESP GetResponse[OBJ], BOXES any, CHANGE Change](
accountId := acc(session)
// we first need to retrieve the list of all the Principals in order to be able to use and test sharing
- principalIds := []string{}
+ principalIds := []PrincipalId{}
{
- result, err := s.client.GetPrincipals(accountId, []string{}, ctx)
+ result, err := s.client.GetPrincipals(accountId, []PrincipalId{}, ctx)
require.NoError(err)
require.NotEmpty(result.Payload.List)
- principalIds = structs.Map(result.Payload.List, func(p Principal) string { return p.Id })
+ principalIds = structs.Map(result.Payload.List, func(p Principal) PrincipalId { return PrincipalId(p.Id) })
}
ss := EmptySessionState
diff --git a/pkg/jmap/integration_addressbook_test.go b/pkg/jmap/integration_addressbook_test.go
index 50261d59cd..97428cc78e 100644
--- a/pkg/jmap/integration_addressbook_test.go
+++ b/pkg/jmap/integration_addressbook_test.go
@@ -42,19 +42,19 @@ func TestAddressBooks(t *testing.T) {
}
containerTest(t,
- func(session *Session) string { return session.PrimaryAccounts.Contacts },
+ func(session *Session) AccountId { return session.PrimaryAccounts.Contacts },
list,
getid,
- func(s *StalwartTest, accountId string, ids []string, ctx Context) (Result[AddressBookGetResponse], error) {
+ func(s *StalwartTest, accountId AccountId, ids []string, ctx Context) (Result[AddressBookGetResponse], error) {
return s.client.GetAddressbooks(accountId, ids, ctx)
},
- func(s *StalwartTest, accountId string, id string, change AddressBookChange, ctx Context) (Result[AddressBook], error) { //NOSONAR
+ func(s *StalwartTest, accountId AccountId, id string, change AddressBookChange, ctx Context) (Result[AddressBook], error) { //NOSONAR
return s.client.UpdateAddressBook(accountId, id, change, ctx)
},
- func(s *StalwartTest, accountId string, ids []string, ctx Context) (Result[map[string]SetError], error) { //NOSONAR
+ func(s *StalwartTest, accountId AccountId, ids []string, ctx Context) (Result[map[string]SetError], error) { //NOSONAR
return s.client.DeleteAddressBook(accountId, ids, ctx)
},
- func(s *StalwartTest, t *testing.T, accountId string, count uint, ctx Context, user User, principalIds []string) (AddressBookBoxes, []AddressBook, SessionState, State, error) {
+ func(s *StalwartTest, t *testing.T, accountId AccountId, count uint, ctx Context, user User, principalIds []PrincipalId) (AddressBookBoxes, []AddressBook, SessionState, State, error) {
return s.fillAddressBook(t, accountId, count, ctx, user, principalIds)
},
func(orig AddressBook) AddressBookChange {
@@ -104,7 +104,7 @@ func TestContacts(t *testing.T) {
ss := EmptySessionState
os := EmptyState
{
- result, err := s.client.QueryContactCards(toNullQueryParams([]string{accountId}), nil, filter, sortBy, true, ctx)
+ result, err := s.client.QueryContactCards(toNullQueryParams([]AccountId{accountId}), nil, filter, sortBy, true, ctx)
require.NoError(err)
require.Len(result.Payload, 1)
@@ -161,7 +161,7 @@ func TestContacts(t *testing.T) {
for i := range slices {
position := int(i * limit)
page := min(remainder, limit)
- result, err := s.client.QueryContactCards(map[string]QueryParams{accountId: {Position: position}}, &limit, filter, sortBy, true, ctx)
+ result, err := s.client.QueryContactCards(map[AccountId]QueryParams{accountId: {Position: position}}, &limit, filter, sortBy, true, ctx)
require.NoError(err)
require.Len(result.Payload, 1)
require.Contains(result.Payload, accountId)
@@ -186,7 +186,7 @@ func TestContacts(t *testing.T) {
offset := 0
i := 0
for chunk := range slices.Chunk(results.Results, chunkSize) {
- result, err := s.client.QueryContactCards(map[string]QueryParams{accountId: {Anchor: anchor, AnchorOffset: &offset}}, uintPtr(chunkSize), filter, sortBy, true, ctx)
+ result, err := s.client.QueryContactCards(map[AccountId]QueryParams{accountId: {Anchor: anchor, AnchorOffset: &offset}}, uintPtr(chunkSize), filter, sortBy, true, ctx)
require.Equal(ss, result.GetSessionState())
require.NoError(err)
require.Len(result.Payload, 1)
@@ -236,7 +236,7 @@ func TestContacts(t *testing.T) {
os = result.GetState()
}
{
- result, err := s.client.QueryContactCards(toNullQueryParams([]string{accountId}), nil, filter, sortBy, true, ctx)
+ result, err := s.client.QueryContactCards(toNullQueryParams([]AccountId{accountId}), nil, filter, sortBy, true, ctx)
require.NoError(err)
require.Contains(result.Payload, accountId)
resp := result.Payload[accountId]
@@ -278,11 +278,11 @@ var streetNumberRegex = regexp.MustCompile(`^(\d+)\s+(.+)$`)
func (s *StalwartTest) fillAddressBook( //NOSONAR
t *testing.T,
- accountId string,
+ accountId AccountId,
count uint,
ctx Context,
_ User,
- principalIds []string,
+ principalIds []PrincipalId,
) (AddressBookBoxes, []AddressBook, SessionState, State, error) {
require := require.New(t)
@@ -322,7 +322,7 @@ func (s *StalwartTest) fillAddressBook( //NOSONAR
}
if sharing != nil {
numPrincipals := 1 + rand.Intn(len(principalIds)-1)
- m := make(map[string]AddressBookRights, numPrincipals)
+ m := make(map[PrincipalId]AddressBookRights, numPrincipals)
for _, p := range pickRandomN(numPrincipals, principalIds...) {
m[p] = *sharing
}
@@ -357,7 +357,7 @@ func (s *StalwartTest) fillContacts( //NOSONAR
session *Session,
ctx Context,
user User,
-) (string, string, map[string]ContactCard, ContactsBoxes, error) {
+) (AccountId, string, map[string]ContactCard, ContactsBoxes, error) {
require := require.New(t)
c, err := NewTestJmapClient(session, user.name, user.password, true, true)
require.NoError(err)
diff --git a/pkg/jmap/integration_calendar_test.go b/pkg/jmap/integration_calendar_test.go
index 4978097851..53aaf24976 100644
--- a/pkg/jmap/integration_calendar_test.go
+++ b/pkg/jmap/integration_calendar_test.go
@@ -32,19 +32,19 @@ func TestCalendars(t *testing.T) { //NOSONAR
}
containerTest(t,
- func(session *Session) string { return session.PrimaryAccounts.Calendars },
+ func(session *Session) AccountId { return session.PrimaryAccounts.Calendars },
func(resp CalendarGetResponse) []Calendar { return resp.List },
func(obj Calendar) string { return obj.Id },
- func(s *StalwartTest, accountId string, ids []string, ctx Context) (Result[CalendarGetResponse], error) {
+ func(s *StalwartTest, accountId AccountId, ids []string, ctx Context) (Result[CalendarGetResponse], error) {
return s.client.GetCalendars(accountId, ids, ctx)
},
- func(s *StalwartTest, accountId string, id string, change CalendarChange, ctx Context) (Result[Calendar], error) { //NOSONAR
+ func(s *StalwartTest, accountId AccountId, id string, change CalendarChange, ctx Context) (Result[Calendar], error) { //NOSONAR
return s.client.UpdateCalendar(accountId, id, change, ctx)
},
- func(s *StalwartTest, accountId string, ids []string, ctx Context) (Result[map[string]SetError], error) { //NOSONAR
+ func(s *StalwartTest, accountId AccountId, ids []string, ctx Context) (Result[map[string]SetError], error) { //NOSONAR
return s.client.DeleteCalendar(accountId, ids, ctx)
},
- func(s *StalwartTest, t *testing.T, accountId string, count uint, ctx Context, user User, principalIds []string) (CalendarBoxes, []Calendar, SessionState, State, error) {
+ func(s *StalwartTest, t *testing.T, accountId AccountId, count uint, ctx Context, user User, principalIds []PrincipalId) (CalendarBoxes, []Calendar, SessionState, State, error) {
return s.fillCalendar(t, accountId, count, ctx, user, principalIds)
},
func(orig Calendar) CalendarChange {
@@ -94,7 +94,7 @@ func TestEvents(t *testing.T) {
os := EmptyState
var results *CalendarEventSearchResults
{
- result, err := s.client.QueryCalendarEvents(toNullQueryParams([]string{accountId}), nil, filter, sortBy, true, ctx)
+ result, err := s.client.QueryCalendarEvents(toNullQueryParams([]AccountId{accountId}), nil, filter, sortBy, true, ctx)
require.NoError(err)
require.Len(result.Payload, 1)
@@ -127,7 +127,7 @@ func TestEvents(t *testing.T) {
for i := range slices {
position := int(i * limit)
page := min(remainder, limit)
- result, err := s.client.QueryCalendarEvents(map[string]QueryParams{accountId: {Position: position}}, &limit, filter, sortBy, true, ctx)
+ result, err := s.client.QueryCalendarEvents(map[AccountId]QueryParams{accountId: {Position: position}}, &limit, filter, sortBy, true, ctx)
require.NoError(err)
require.Len(result.Payload, 1)
require.Contains(result.Payload, accountId)
@@ -152,7 +152,7 @@ func TestEvents(t *testing.T) {
offset := 0
i := 0
for chunk := range slices.Chunk(results.Results, chunkSize) {
- result, err := s.client.QueryCalendarEvents(map[string]QueryParams{accountId: {Anchor: anchor, AnchorOffset: &offset}}, uintPtr(chunkSize), filter, sortBy, true, ctx)
+ result, err := s.client.QueryCalendarEvents(map[AccountId]QueryParams{accountId: {Anchor: anchor, AnchorOffset: &offset}}, uintPtr(chunkSize), filter, sortBy, true, ctx)
require.Equal(ss, result.GetSessionState())
require.NoError(err)
require.Len(result.Payload, 1)
@@ -207,7 +207,7 @@ func TestEvents(t *testing.T) {
}
{
- result, err := s.client.QueryCalendarEvents(toNullQueryParams([]string{accountId}), nil, filter, sortBy, true, ctx)
+ result, err := s.client.QueryCalendarEvents(toNullQueryParams([]AccountId{accountId}), nil, filter, sortBy, true, ctx)
require.NoError(err)
require.Contains(result.Payload, accountId)
resp := result.Payload[accountId]
@@ -239,11 +239,11 @@ type CalendarBoxes struct {
func (s *StalwartTest) fillCalendar( //NOSONAR
t *testing.T,
- accountId string,
+ accountId AccountId,
count uint,
ctx Context,
_ User,
- principalIds []string,
+ principalIds []PrincipalId,
) (CalendarBoxes, []Calendar, SessionState, State, error) {
require := require.New(t)
@@ -340,7 +340,7 @@ func (s *StalwartTest) fillCalendar( //NOSONAR
}
if sharing != nil {
numPrincipals := 1 + rand.Intn(len(principalIds)-1)
- m := make(map[string]CalendarRights, numPrincipals)
+ m := make(map[PrincipalId]CalendarRights, numPrincipals)
for _, p := range pickRandomN(numPrincipals, principalIds...) {
m[p] = *sharing
}
@@ -380,7 +380,7 @@ func (s *StalwartTest) fillEvents( //NOSONAR
count uint,
ctx Context,
user User,
-) (string, string, map[string]CalendarEvent, EventsBoxes, error) {
+) (AccountId, string, map[string]CalendarEvent, EventsBoxes, error) {
require := require.New(t)
c, err := NewTestJmapClient(ctx.Session, user.name, user.password, true, true)
require.NoError(err)
diff --git a/pkg/jmap/integration_email_test.go b/pkg/jmap/integration_email_test.go
index b85dfa3b0a..d7b1e1389f 100644
--- a/pkg/jmap/integration_email_test.go
+++ b/pkg/jmap/integration_email_test.go
@@ -65,7 +65,7 @@ func TestEmails(t *testing.T) {
}
{
- result, err := s.client.GetAllMailboxes([]string{accountId}, ctx)
+ result, err := s.client.GetAllMailboxes([]AccountId{accountId}, ctx)
require.NoError(err)
require.Equal(session.State, result.GetSessionState())
require.Len(result.Payload, 1)
@@ -144,7 +144,7 @@ func TestSendingEmails(t *testing.T) {
var mailboxPerRole map[string]Mailbox
{
- result, err := s.client.GetAllMailboxes([]string{accountId}, ctx)
+ result, err := s.client.GetAllMailboxes([]AccountId{accountId}, ctx)
require.NoError(err)
mailboxPerRole = structs.Index(result.Payload[accountId], func(m Mailbox) string { return m.Role })
require.Contains(mailboxPerRole, JmapMailboxRoleInbox)
@@ -154,7 +154,7 @@ func TestSendingEmails(t *testing.T) {
}
{
roles := []string{JmapMailboxRoleDrafts, JmapMailboxRoleSent, JmapMailboxRoleInbox}
- result, err := s.client.SearchMailboxIdsPerRole([]string{accountId}, roles, ctx)
+ result, err := s.client.SearchMailboxIdsPerRole([]AccountId{accountId}, roles, ctx)
require.NoError(err)
require.Contains(result.Payload, accountId)
a := result.Payload[accountId]
@@ -165,7 +165,7 @@ func TestSendingEmails(t *testing.T) {
// let's ensure that the recipients have zero emails in their mailboxes before we send them any
for _, u := range []struct {
- accountId string
+ accountId AccountId
session *Session
}{{toAccountId, toSession}, {ccAccountId, ccSession}} {
uctx := Context{
@@ -174,7 +174,7 @@ func TestSendingEmails(t *testing.T) {
Logger: ctx.Logger,
AcceptLanguage: ctx.AcceptLanguage,
}
- result, err := s.client.GetAllMailboxes([]string{u.accountId}, uctx)
+ result, err := s.client.GetAllMailboxes([]AccountId{u.accountId}, uctx)
require.NoError(err)
for _, mailbox := range result.Payload[u.accountId] {
require.Equal(0, mailbox.TotalEmails)
@@ -306,7 +306,7 @@ func TestSendingEmails(t *testing.T) {
for _, r := range []struct {
user User
- accountId string
+ accountId AccountId
session *Session
}{{to, toAccountId, toSession}, {cc, ccAccountId, ccSession}} {
rctx := Context{
@@ -317,7 +317,7 @@ func TestSendingEmails(t *testing.T) {
}
inboxId := ""
{
- result, err := s.client.GetAllMailboxes([]string{r.accountId}, rctx)
+ result, err := s.client.GetAllMailboxes([]AccountId{r.accountId}, rctx)
require.NoError(err)
for _, mailbox := range result.Payload[r.accountId] {
if mailbox.Role == JmapMailboxRoleInbox {
@@ -328,7 +328,7 @@ func TestSendingEmails(t *testing.T) {
require.NotEmpty(inboxId, "failed to find the Mailbox with the 'inbox' role for %v", r.user.name)
}
- result, err := s.client.QueryEmails([]string{r.accountId}, EmailFilterCondition{InMailbox: inboxId}, 0, 0, true, 0, rctx)
+ result, err := s.client.QueryEmails([]AccountId{r.accountId}, EmailFilterCondition{InMailbox: inboxId}, 0, 0, true, 0, rctx)
require.NoError(err)
require.Contains(result.Payload, r.accountId)
require.Len(result.Payload[r.accountId].Results, 1)
@@ -385,9 +385,9 @@ func matchEmail(t *testing.T, actual Email, expected filledMail, hasBodies bool)
}
}
-func (s *StalwartTest) findInbox(t *testing.T, accountId string, ctx Context) (string, string) {
+func (s *StalwartTest) findInbox(t *testing.T, accountId AccountId, ctx Context) (string, string) {
require := require.New(t)
- result, err := s.client.GetAllMailboxes([]string{accountId}, ctx)
+ result, err := s.client.GetAllMailboxes([]AccountId{accountId}, ctx)
require.NoError(err)
require.Equal(ctx.Session.State, result.GetSessionState())
require.Len(result.Payload, 1)
diff --git a/pkg/jmap/integration_ws_test.go b/pkg/jmap/integration_ws_test.go
index 499141038b..8bcd0b35e3 100644
--- a/pkg/jmap/integration_ws_test.go
+++ b/pkg/jmap/integration_ws_test.go
@@ -17,7 +17,7 @@ type testWsPushListener struct {
t *testing.T
logger *log.Logger
username string
- mailAccountId string
+ mailAccountId AccountId
calls atomic.Uint32
m sync.Mutex
emailStates []string
@@ -46,7 +46,7 @@ func (l *testWsPushListener) OnNotification(username string, pushState StateChan
unsupportedKeys := structs.Filter(structs.Keys(changed), func(o ObjectTypeName) bool { return o != EmailName && o != ThreadName && o != MailboxName })
assert.Empty(l.t, unsupportedKeys)
}
- unsupportedAccounts := structs.Filter(structs.Keys(pushState.Changed), func(s string) bool { return s != l.mailAccountId })
+ unsupportedAccounts := structs.Filter(structs.Keys(pushState.Changed), func(s AccountId) bool { return s != l.mailAccountId })
assert.Empty(l.t, unsupportedAccounts)
}
diff --git a/pkg/jmap/model.go b/pkg/jmap/model.go
index 9dfe499a6f..1ec63cc164 100644
--- a/pkg/jmap/model.go
+++ b/pkg/jmap/model.go
@@ -445,6 +445,10 @@ var (
}
)
+type AccountId string
+
+type PrincipalId string
+
type SessionMailAccountCapabilities struct {
// The maximum number of Mailboxes that can be can assigned to a single Email object.
//
@@ -683,16 +687,16 @@ type SessionTasksCustomTimezonesAccountCapabilities struct {
type SessionPrincipalsAccountCapabilities struct {
// The id of the principal in this account that corresponds to the user fetching this object, if any.
- CurrentUserPrincipalId string `json:"currentUserPrincipalId,omitempty"`
+ CurrentUserPrincipalId PrincipalId `json:"currentUserPrincipalId,omitempty"`
}
type SessionPrincipalsOwnerAccountCapabilities struct {
// The id of an account with the `urn:ietf:params:jmap:principals` capability that contains the
// corresponding `Principal` object.
- AccountIdForPrincipal string `json:"accountIdForPrincipal,omitempty"`
+ AccountIdForPrincipal AccountId `json:"accountIdForPrincipal,omitempty"`
// The id of the `Principal` that owns this account.
- PrincipalId string `json:"principalId,omitempty"`
+ PrincipalId PrincipalId `json:"principalId,omitempty"`
}
type SessionPrincipalAvailabilityAccountCapabilities struct {
@@ -821,7 +825,7 @@ type SessionPrincipalCapabilities struct {
//
// The corresponding Account object can be found in the Principal's "accounts" property, as
// per Section 2 of [RFC9670](https://www.rfc-editor.org/rfc/rfc9670.html).
- AccountId string `json:"accountId,omitempty"`
+ AccountId AccountId `json:"accountId,omitempty"`
// If true, the user may call the "Principal/getAvailability" method with this Principal.
MayGetAvailability *bool `json:"mayGetAvailability,omitzero"`
@@ -916,19 +920,19 @@ type SessionCapabilities struct {
}
type SessionPrimaryAccounts struct {
- Core string `json:"urn:ietf:params:jmap:core,omitempty"`
- Mail string `json:"urn:ietf:params:jmap:mail,omitempty"`
- Submission string `json:"urn:ietf:params:jmap:submission,omitempty"`
- VacationResponse string `json:"urn:ietf:params:jmap:vacationresponse,omitempty"`
- Sieve string `json:"urn:ietf:params:jmap:sieve,omitempty"`
- Blob string `json:"urn:ietf:params:jmap:blob,omitempty"`
- Quota string `json:"urn:ietf:params:jmap:quota,omitempty"`
- Websocket string `json:"urn:ietf:params:jmap:websocket,omitempty"`
- Task string `json:"urn:ietf:params:jmap:task,omitempty"`
- Calendars string `json:"urn:ietf:params:jmap:calendars,omitempty"`
- CalendarsParse string `json:"urn:ietf:params:jmap:calendars:parse,omitempty"`
- Contacts string `json:"urn:ietf:params:jmap:contacts,omitempty"`
- ContactsParse string `json:"urn:ietf:params:jmap:contacts:parse,omitempty"`
+ Core AccountId `json:"urn:ietf:params:jmap:core,omitempty"`
+ Mail AccountId `json:"urn:ietf:params:jmap:mail,omitempty"`
+ Submission AccountId `json:"urn:ietf:params:jmap:submission,omitempty"`
+ VacationResponse AccountId `json:"urn:ietf:params:jmap:vacationresponse,omitempty"`
+ Sieve AccountId `json:"urn:ietf:params:jmap:sieve,omitempty"`
+ Blob AccountId `json:"urn:ietf:params:jmap:blob,omitempty"`
+ Quota AccountId `json:"urn:ietf:params:jmap:quota,omitempty"`
+ Websocket AccountId `json:"urn:ietf:params:jmap:websocket,omitempty"`
+ Task AccountId `json:"urn:ietf:params:jmap:task,omitempty"`
+ Calendars AccountId `json:"urn:ietf:params:jmap:calendars,omitempty"`
+ CalendarsParse AccountId `json:"urn:ietf:params:jmap:calendars:parse,omitempty"`
+ Contacts AccountId `json:"urn:ietf:params:jmap:contacts,omitempty"`
+ ContactsParse AccountId `json:"urn:ietf:params:jmap:contacts:parse,omitempty"`
}
type SessionState string
@@ -946,7 +950,7 @@ const NoLanguage = Language("")
type SessionResponse struct {
Capabilities SessionCapabilities `json:"capabilities"`
- Accounts map[string]Account `json:"accounts,omitempty"`
+ Accounts map[AccountId]Account `json:"accounts,omitempty"`
// A map of capability URIs (as found in accountCapabilities) to the account id that is considered to be the user’s main or default
// account for data pertaining to that capability.
@@ -1164,6 +1168,8 @@ type SetError struct {
type Command string
+const NoCommand = Command("")
+
type Invocation struct {
Command Command
Parameters any
@@ -1179,7 +1185,7 @@ func invocation(parameters JmapCommand, tag string) Invocation {
}
func skipInvocation() Invocation {
- return Invocation{Command: ""}
+ return Invocation{Command: NoCommand}
}
type TypeOfRequest string
@@ -1239,10 +1245,12 @@ type Response struct {
RequestId string `json:"requestId,omitempty"`
}
+// A JMAP object.
type Foo interface {
GetObjectType() ObjectType
}
+// A JMAP object that also has an identifier.
type Idable interface {
GetId() string
Foo
@@ -1384,6 +1392,7 @@ type ChangesResponse[T Foo] interface {
type QueryCommand[T Foo, SELF QueryCommand[T, SELF]] interface {
JmapCommand
GetResponse() QueryResponse[T]
+ // Wither that creates a new object of the same type, keeping all the same values except for the limit that is specified as parameter.
WithLimit(limit *uint) SELF
}
@@ -1436,8 +1445,8 @@ type QueryParams struct {
var NullQueryParams = QueryParams{Position: 0, Anchor: "", AnchorOffset: nil}
-func toNullQueryParams(accountIds []string) map[string]QueryParams {
- return structs.ToMap(accountIds, func(k string) (string, QueryParams) { return k, NullQueryParams })
+func toNullQueryParams(accountIds []AccountId) map[AccountId]QueryParams {
+ return structs.ToMap(accountIds, func(k AccountId) (AccountId, QueryParams) { return k, NullQueryParams })
}
type FilterElement[T Foo] interface {
@@ -1751,8 +1760,8 @@ func (m MailboxChange) AsPatch() (PatchObject, error) {
}
type MailboxGetCommand struct {
- AccountId string `json:"accountId"`
- Ids []string `json:"ids,omitempty"`
+ AccountId AccountId `json:"accountId"`
+ Ids []string `json:"ids,omitempty"`
}
var _ GetCommand[Mailbox] = &MailboxGetCommand{}
@@ -1762,7 +1771,7 @@ func (c MailboxGetCommand) GetObjectType() ObjectType { return MailboxTy
func (c MailboxGetCommand) GetResponse() GetResponse[Mailbox] { return MailboxGetResponse{} }
type MailboxGetRefCommand struct {
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
IdsRef *ResultReference `json:"#ids,omitempty"`
}
@@ -1773,8 +1782,8 @@ func (c MailboxGetRefCommand) GetObjectType() ObjectType { return Mailbo
func (c MailboxGetRefCommand) GetResponse() GetResponse[Mailbox] { return MailboxGetResponse{} }
type MailboxSetCommand struct {
- AccountId string `json:"accountId"`
- IfInState string `json:"ifInState,omitempty"`
+ AccountId AccountId `json:"accountId"`
+ IfInState State `json:"ifInState,omitempty"`
Create map[string]MailboxChange `json:"create,omitempty"`
Update map[string]PatchObject `json:"update,omitempty"`
Destroy []string `json:"destroy,omitempty"`
@@ -1787,7 +1796,7 @@ func (c MailboxSetCommand) GetObjectType() ObjectType { return MailboxTy
func (c MailboxSetCommand) GetResponse() SetResponse[Mailbox] { return MailboxSetResponse{} }
type MailboxSetResponse struct {
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
OldState State `json:"oldState,omitempty"`
NewState State `json:"newState,omitempty"`
Created map[string]*Mailbox `json:"created,omitempty"`
@@ -1853,7 +1862,7 @@ var _ Comparator[Mailbox] = &MailboxComparator{}
func (c MailboxComparator) GetMarker() Mailbox { return Mailbox{} }
type MailboxQueryCommand struct {
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
Filter MailboxFilterElement `json:"filter,omitempty"`
Sort []MailboxComparator `json:"sort,omitempty"`
SortAsTree bool `json:"sortAsTree,omitempty"`
@@ -2157,7 +2166,7 @@ func (c EmailComparator) GetMarker() Email { return Email{} }
// A client can use anchor instead of position to find the index of an id within a large set of results.
type EmailQueryCommand struct {
// The id of the account to use.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// Determines the set of Emails returned in the results.
//
@@ -2250,7 +2259,7 @@ type EmailGetCommand struct {
Ids []string `json:"ids,omitempty"`
// The id of the account to use.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// If supplied, only the properties listed in the array are returned for each Email object.
//
@@ -2316,7 +2325,7 @@ type EmailGetRefCommand struct {
IdsRef *ResultReference `json:"#ids,omitempty"`
// The id of the account to use.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// If supplied, only the properties listed in the array are returned for each Email object.
//
@@ -2372,7 +2381,7 @@ func (c EmailGetRefCommand) GetResponse() GetResponse[Email] { return EmailGetRe
type EmailChangesCommand struct {
// The id of the account to use.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// The current state of the client.
//
@@ -2634,7 +2643,7 @@ type Email struct {
// The account ID this email belongs to.
// Note that this is not part of the JMAP specification, and is only contained in all-account operations.
- AccountId string `json:"accountId,omitempty"`
+ AccountId AccountId `json:"accountId,omitempty"`
// The set of Mailbox ids this Email belongs to.
//
@@ -2998,7 +3007,7 @@ func (f EmailSubmission) GetId() string { return f.Id }
type EmailSubmissionGetCommand struct {
// The id of the account to use.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// The ids of the EmailSubmission objects to return.
//
@@ -3024,7 +3033,7 @@ func (c EmailSubmissionGetCommand) GetResponse() GetResponse[EmailSubmission] {
type EmailSubmissionGetRefCommand struct {
// The id of the account to use.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// The ids of the EmailSubmission objects to return.
//
@@ -3050,7 +3059,7 @@ func (c EmailSubmissionGetRefCommand) GetResponse() GetResponse[EmailSubmission]
type EmailSubmissionGetResponse struct {
// The id of the account used for the call.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// A (preferably short) string representing the state on the server for all the data
// of this type in the account (not just the objects returned in this call).
@@ -3089,7 +3098,7 @@ func (r EmailSubmissionGetResponse) GetList() []EmailSubmission { return r.List
type EmailSubmissionChangesCommand struct {
// The id of the account to use.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// The current state of the client.
//
@@ -3120,7 +3129,7 @@ func (c EmailSubmissionChangesCommand) GetResponse() ChangesResponse[EmailSubmis
type EmailSubmissionChangesResponse struct {
// The id of the account used for the call.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// This is the sinceState argument echoed back; it’s the state from which the server is returning changes.
OldState State `json:"oldState"`
@@ -3169,7 +3178,7 @@ type EmailSubmissionCreate struct {
}
type EmailSubmissionSetCommand struct {
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
Create map[string]EmailSubmissionCreate `json:"create,omitempty"`
OldState State `json:"oldState,omitempty"`
NewState State `json:"newState,omitempty"`
@@ -3203,7 +3212,7 @@ type CreatedEmailSubmission struct {
type EmailSubmissionSetResponse struct {
// The id of the account used for the call.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// This is the sinceState argument echoed back; it’s the state from which the server is returning changes.
OldState State `json:"oldState"`
@@ -3239,7 +3248,7 @@ func (r EmailSubmissionSetResponse) GetMarker() EmailSubmission { retu
type EmailQueryResponse struct {
// The id of the account used for the call.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// A string encoding the current state of the query on the server.
//
@@ -3294,7 +3303,7 @@ func (r EmailQueryResponse) GetMarker() Email { return Email{} }
type EmailGetResponse struct {
// The id of the account used for the call.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// A (preferably short) string representing the state on the server for all the data of this type
// in the account (not just the objects returned in this call).
@@ -3328,7 +3337,7 @@ func (r EmailGetResponse) GetMarker() Email { return Email{} }
type EmailChangesResponse struct {
// The id of the account used for the call.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// This is the sinceState argument echoed back; it’s the state from which the server is returning changes.
OldState State `json:"oldState"`
@@ -3362,7 +3371,7 @@ func (r EmailChangesResponse) GetMarker() Email { return Email{} }
type MailboxGetResponse struct {
// The id of the account used for the call.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// A (preferably short) string representing the state on the server for all the data of this type in the account
// (not just the objects returned in this call).
@@ -3393,7 +3402,7 @@ func (r MailboxGetResponse) GetList() []Mailbox { return r.List }
type MailboxChangesCommand struct {
// The id of the account to use.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// The current state of the client.
//
@@ -3424,7 +3433,7 @@ func (c MailboxChangesCommand) GetResponse() ChangesResponse[Mailbox] {
type MailboxChangesResponse struct {
// The id of the account used for the call.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// This is the sinceState argument echoed back; it’s the state from which the server is returning changes.
OldState State `json:"oldState"`
@@ -3465,7 +3474,7 @@ func (r MailboxChangesResponse) GetMarker() Mailbox { return Mailbox{} }
type MailboxQueryResponse struct {
// The id of the account used for the call.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// A string encoding the current state of the query on the server.
//
@@ -3625,7 +3634,7 @@ func (e EmailChange) AsPatch() (PatchObject, error) {
type EmailSetCommand struct {
// The id of the account to use.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// This is a state string as returned by the `Email/get` method.
//
@@ -3633,7 +3642,7 @@ type EmailSetCommand struct {
// `stateMismatch` error returned.
//
// If null, any changes will be applied to the current state.
- IfInState string `json:"ifInState,omitempty"`
+ IfInState State `json:"ifInState,omitempty"`
// A map of a creation id (a temporary id set by the client) to Email objects,
// or null if no objects are to be created.
@@ -3684,7 +3693,7 @@ func (c EmailSetCommand) GetResponse() SetResponse[Email] { return EmailSetRespo
type EmailSetResponse struct {
// The id of the account used for the call.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// The state string that would have been returned by Email/get before making the
// requested changes, or null if the server doesn’t know what the previous state
@@ -3760,7 +3769,7 @@ type EmailImport struct {
}
type EmailImportCommand struct {
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// This is a state string as returned by the Email/get method.
//
@@ -3769,7 +3778,7 @@ type EmailImportCommand struct {
// error returned.
//
// If null, any changes will be applied to the current state.
- IfInState string `json:"ifInState,omitempty"`
+ IfInState State `json:"ifInState,omitempty"`
// A map of creation id (client specified) to EmailImport objects.
Emails map[string]EmailImport `json:"emails"`
@@ -3792,7 +3801,7 @@ type ImportedEmail struct {
type EmailImportResponse struct {
// The id of the account used for this call.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// The state string that would have been returned by Email/get on this account
// before making the requested changes, or null if the server doesn’t know
@@ -3834,8 +3843,8 @@ func (f Thread) GetObjectType() ObjectType { return ThreadType }
func (f Thread) GetId() string { return f.Id }
type ThreadGetCommand struct {
- AccountId string `json:"accountId"`
- Ids []string `json:"ids,omitempty"`
+ AccountId AccountId `json:"accountId"`
+ Ids []string `json:"ids,omitempty"`
}
var _ GetCommand[Thread] = &ThreadGetCommand{}
@@ -3845,7 +3854,7 @@ func (c ThreadGetCommand) GetObjectType() ObjectType { return ThreadType
func (c ThreadGetCommand) GetResponse() GetResponse[Thread] { return ThreadGetResponse{} }
type ThreadGetRefCommand struct {
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
IdsRef *ResultReference `json:"#ids,omitempty"`
}
@@ -3856,7 +3865,7 @@ func (c ThreadGetRefCommand) GetObjectType() ObjectType { return ThreadTy
func (c ThreadGetRefCommand) GetResponse() GetResponse[Thread] { return ThreadGetResponse{} }
type ThreadGetResponse struct {
- AccountId string
+ AccountId AccountId
State State
List []Thread
NotFound []string
@@ -3870,8 +3879,8 @@ func (r ThreadGetResponse) GetList() []Thread { return r.List }
func (r ThreadGetResponse) GetMarker() Thread { return Thread{} }
type IdentityGetCommand struct {
- AccountId string `json:"accountId"`
- Ids []string `json:"ids,omitempty"`
+ AccountId AccountId `json:"accountId"`
+ Ids []string `json:"ids,omitempty"`
}
var _ GetCommand[Identity] = &IdentityGetCommand{}
@@ -3881,7 +3890,7 @@ func (c IdentityGetCommand) GetObjectType() ObjectType { return Identit
func (c IdentityGetCommand) GetResponse() GetResponse[Identity] { return IdentityGetResponse{} }
type IdentityGetRefCommand struct {
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
IdsRef *ResultReference `json:"#ids,omitempty"`
PropertiesRef *ResultReference `json:"#properties,omitempty"`
}
@@ -3894,7 +3903,7 @@ func (c IdentityGetRefCommand) GetResponse() GetResponse[Identity] { return Iden
type IdentityChangesCommand struct {
// The id of the account to use.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// The current state of the client.
//
@@ -3925,7 +3934,7 @@ func (c IdentityChangesCommand) GetResponse() ChangesResponse[Identity] {
type IdentityChangesResponse struct {
// The id of the account used for the call.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// This is the sinceState argument echoed back; it’s the state from which the server is returning changes.
OldState State `json:"oldState"`
@@ -3959,8 +3968,8 @@ func (r IdentityChangesResponse) GetDestroyed() []string { return r.Destroyed }
func (r IdentityChangesResponse) GetMarker() Identity { return Identity{} }
type IdentitySetCommand struct {
- AccountId string `json:"accountId"`
- IfInState string `json:"ifInState,omitempty"`
+ AccountId AccountId `json:"accountId"`
+ IfInState State `json:"ifInState,omitempty"`
Create map[string]IdentityChange `json:"create,omitempty"`
Update map[string]PatchObject `json:"update,omitempty"`
Destroy []string `json:"destroy,omitempty"`
@@ -3973,7 +3982,7 @@ func (c IdentitySetCommand) GetObjectType() ObjectType { return Identit
func (c IdentitySetCommand) GetResponse() SetResponse[Identity] { return IdentitySetResponse{} }
type IdentitySetResponse struct {
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
OldState State `json:"oldState,omitempty"`
NewState State `json:"newState,omitempty"`
Created map[string]*Identity `json:"created,omitempty"`
@@ -4081,7 +4090,7 @@ func (i IdentityChange) AsPatch() (PatchObject, error) {
}
type IdentityGetResponse struct {
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
State State `json:"state"`
List []Identity `json:"list,omitempty"`
NotFound []string `json:"notFound,omitempty"`
@@ -4095,7 +4104,7 @@ func (r IdentityGetResponse) GetNotFound() []string { return r.NotFound }
func (r IdentityGetResponse) GetList() []Identity { return r.List }
type VacationResponseGetCommand struct {
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
}
var _ GetCommand[VacationResponse] = &VacationResponseGetCommand{}
@@ -4156,7 +4165,7 @@ func (f VacationResponse) GetId() string { return f.Id }
type VacationResponseGetResponse struct {
// The identifier of the account this response pertains to.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// A string representing the state on the server for all the data of this type in the account
// (not just the objects returned in this call).
@@ -4180,7 +4189,7 @@ func (r VacationResponseGetResponse) GetNotFound() []string { return r.Not
func (r VacationResponseGetResponse) GetList() []VacationResponse { return r.List }
type VacationResponseSetCommand struct {
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
IfInState string `json:"ifInState,omitempty"`
Create map[string]VacationResponse `json:"create,omitempty"`
Update map[string]PatchObject `json:"update,omitempty"`
@@ -4196,7 +4205,7 @@ func (c VacationResponseSetCommand) GetResponse() SetResponse[VacationResponse]
}
type VacationResponseSetResponse struct {
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
OldState State `json:"oldState,omitempty"`
NewState State `json:"newState,omitempty"`
Created map[string]VacationResponse `json:"created,omitempty"`
@@ -4228,7 +4237,7 @@ type UploadObject struct {
}
type BlobUploadCommand struct {
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
Create map[string]UploadObject `json:"create"`
}
@@ -4245,7 +4254,7 @@ type BlobUploadCreateResult struct {
}
type BlobUploadResponse struct {
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
Created map[string]BlobUploadCreateResult `json:"created"`
}
@@ -4341,11 +4350,11 @@ func (c BlobChanges) GetUpdated() []Blob { return c.Updated }
func (c BlobChanges) GetDestroyed() []string { return c.Destroyed }
type BlobGetCommand struct {
- AccountId string `json:"accountId"`
- Ids []string `json:"ids,omitempty"`
- Properties []string `json:"properties,omitempty"`
- Position int `json:"position,omitzero"`
- Length int `json:"length,omitzero"`
+ AccountId AccountId `json:"accountId"`
+ Ids []string `json:"ids,omitempty"`
+ Properties []string `json:"properties,omitempty"`
+ Position int `json:"position,omitzero"`
+ Length int `json:"length,omitzero"`
}
var _ GetCommand[Blob] = &BlobGetCommand{}
@@ -4355,7 +4364,7 @@ func (c BlobGetCommand) GetObjectType() ObjectType { return BlobType }
func (c BlobGetCommand) GetResponse() GetResponse[Blob] { return BlobGetResponse{} }
type BlobGetRefCommand struct {
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
IdRef *ResultReference `json:"#ids,omitempty"`
Properties []string `json:"properties,omitempty"`
Position int `json:"position,omitzero"`
@@ -4370,7 +4379,7 @@ func (c BlobGetRefCommand) GetResponse() GetResponse[Blob] { return BlobGetRespo
type BlobGetResponse struct {
// The id of the account used for the call.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// A string representing the state on the server for all the data of this type in the
// account (not just the objects returned in this call).
@@ -4461,7 +4470,7 @@ func (f SearchSnippet) GetObjectType() ObjectType { return SearchSnippetType }
type SearchSnippetGetRefCommand struct {
// The id of the account to use.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// The same filter as passed to Email/query.
Filter EmailFilterElement `json:"filter,omitempty"`
@@ -4476,7 +4485,7 @@ func (c SearchSnippetGetRefCommand) GetCommand() Command { return CommandS
func (c SearchSnippetGetRefCommand) GetObjectType() ObjectType { return SearchSnippetType }
type SearchSnippetGetResponse struct {
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
List []SearchSnippet `json:"list,omitempty"`
NotFound []string `json:"notFound,omitempty"`
}
@@ -4503,7 +4512,7 @@ type StateChange struct {
// The client can compare the new state strings with its current values to see whether
// it has the current data for these types. If not, the changes can then be efficiently
// fetched in a single standard API request (using the /changes type methods).
- Changed map[string]map[ObjectTypeName]string `json:"changed"`
+ Changed map[AccountId]map[ObjectTypeName]string `json:"changed"`
// A (preferably short) string that encodes the entire server state visible to the user
// (not just the objects returned in this call).
@@ -4586,7 +4595,7 @@ type AddressBook struct {
//
// The account id for the principals may be found in the urn:ietf:params:jmap:principals:owner capability
// of the Account to which the AddressBook belongs.
- ShareWith map[string]AddressBookRights `json:"shareWith,omitempty"`
+ ShareWith map[PrincipalId]AddressBookRights `json:"shareWith,omitempty"`
// The set of access rights the user has in relation to this AddressBook (server-set).
MyRights AddressBookRights `json:"myRights"`
@@ -5337,7 +5346,7 @@ type Calendar struct {
//
// The account id for the principals may be found in the `urn:ietf:params:jmap:principals:owner`
// capability of the `Account` to which the calendar belongs.
- ShareWith map[string]CalendarRights `json:"shareWith,omitempty"`
+ ShareWith map[PrincipalId]CalendarRights `json:"shareWith,omitempty"`
// The set of access rights the user has in relation to this Calendar.
//
@@ -5468,7 +5477,7 @@ type CalendarChange struct {
//
// The account id for the principals may be found in the `urn:ietf:params:jmap:principals:owner`
// capability of the `Account` to which the calendar belongs.
- ShareWith map[string]CalendarRights `json:"shareWith,omitempty"`
+ ShareWith map[PrincipalId]CalendarRights `json:"shareWith,omitempty"`
// The set of access rights the user has in relation to this Calendar.
//
@@ -5790,7 +5799,7 @@ type CalendarAlert struct {
Type TypeOfCalendarAlert `json:"@type,omitempty"`
// The account id for the calendar in which the alert triggered.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// The CalendarEvent id for the alert that triggered.
//
@@ -5818,7 +5827,7 @@ type Person struct {
// The id of the `Principal` corresponding to the person who made the change, if any.
//
// This will be null if the change was due to receving an iTIP message.
- PrincipalId string `json:"principalId,omitempty"`
+ PrincipalId PrincipalId `json:"principalId,omitempty"`
// The `scheduleId` URI of the person who made the change, if any.
//
@@ -6052,7 +6061,7 @@ type TaskList struct {
//
// The account id for the principals may be found in the `urn:ietf:params:jmap:principals:owner` capability
// of the `Account` to which the task list belongs.
- ShareWith map[string]TaskRights `json:"shareWith,omitempty"`
+ ShareWith map[PrincipalId]TaskRights `json:"shareWith,omitempty"`
// The set of access rights the user has in relation to this `TaskList`.
//
@@ -6366,7 +6375,7 @@ type Principal struct {
// A map of account id to `Account` object for each JMAP Account containing data for
// this principal that the user has access to, or null if none.
- Accounts map[string]Account `json:"accounts,omitempty"`
+ Accounts map[AccountId]Account `json:"accounts,omitempty"`
}
var _ Idable = &Principal{}
@@ -6598,7 +6607,7 @@ type MDN struct {
type SendMDN struct {
// The id of the account to use.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// The id of the `Identity` to associate with these MDNs.
//
@@ -6616,8 +6625,8 @@ type SendMDN struct {
}
type QuotaGetCommand struct {
- AccountId string `json:"accountId"`
- Ids []string `json:"ids,omitempty"`
+ AccountId AccountId `json:"accountId"`
+ Ids []string `json:"ids,omitempty"`
}
var _ GetCommand[Quota] = &QuotaGetCommand{}
@@ -6627,7 +6636,7 @@ func (c QuotaGetCommand) GetObjectType() ObjectType { return QuotaType }
func (c QuotaGetCommand) GetResponse() GetResponse[Quota] { return QuotaGetResponse{} }
type QuotaGetRefCommand struct {
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
IdsRef *ResultReference `json:"#ids,omitempty"`
PropertiesRef *ResultReference `json:"#properties,omitempty"`
}
@@ -6639,10 +6648,10 @@ func (c QuotaGetRefCommand) GetObjectType() ObjectType { return QuotaType
func (c QuotaGetRefCommand) GetResponse() GetResponse[Quota] { return QuotaGetResponse{} }
type QuotaGetResponse struct {
- AccountId string `json:"accountId"`
- State State `json:"state,omitempty"`
- List []Quota `json:"list,omitempty"`
- NotFound []string `json:"notFound,omitempty"`
+ AccountId AccountId `json:"accountId"`
+ State State `json:"state,omitempty"`
+ List []Quota `json:"list,omitempty"`
+ NotFound []string `json:"notFound,omitempty"`
}
var _ GetResponse[Quota] = &QuotaGetResponse{}
@@ -6654,7 +6663,7 @@ func (r QuotaGetResponse) GetList() []Quota { return r.List }
type QuotaChangesCommand struct {
// The id of the account to use.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// The current state of the client.
// This is the string that was returned as the "state" argument in the "Quota/get" response.
@@ -6682,7 +6691,7 @@ func (c QuotaChangesCommand) GetResponse() ChangesResponse[Quota] { return Quota
type QuotaChangesResponse struct {
// The id of the account used for the call.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// This is the "sinceState" argument echoed back; it's the state from which the server is returning changes.
OldState State `json:"oldState"`
@@ -6715,8 +6724,8 @@ func (r QuotaChangesResponse) GetDestroyed() []string { return r.Destroyed }
func (r QuotaChangesResponse) GetMarker() Quota { return Quota{} }
type AddressBookGetCommand struct {
- AccountId string `json:"accountId"`
- Ids []string `json:"ids,omitempty"`
+ AccountId AccountId `json:"accountId"`
+ Ids []string `json:"ids,omitempty"`
}
var _ GetCommand[AddressBook] = &AddressBookGetCommand{}
@@ -6728,7 +6737,7 @@ func (c AddressBookGetCommand) GetResponse() GetResponse[AddressBook] {
}
type AddressBookGetRefCommand struct {
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
IdsRef *ResultReference `json:"#ids,omitempty"`
}
@@ -6741,7 +6750,7 @@ func (c AddressBookGetRefCommand) GetResponse() GetResponse[AddressBook] {
}
type AddressBookGetResponse struct {
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
State State `json:"state,omitempty"`
List []AddressBook `json:"list,omitempty"`
NotFound []string `json:"notFound,omitempty"`
@@ -6795,7 +6804,7 @@ type AddressBookChange struct {
//
// The account id for the principals may be found in the urn:ietf:params:jmap:principals:owner capability
// of the Account to which the AddressBook belongs.
- ShareWith map[string]AddressBookRights `json:"shareWith,omitempty"`
+ ShareWith map[PrincipalId]AddressBookRights `json:"shareWith,omitempty"`
}
var _ Change = AddressBookChange{}
@@ -6805,8 +6814,8 @@ func (a AddressBookChange) AsPatch() (PatchObject, error) {
}
type AddressBookSetCommand struct {
- AccountId string `json:"accountId"`
- IfInState string `json:"ifInState,omitempty"`
+ AccountId AccountId `json:"accountId"`
+ IfInState State `json:"ifInState,omitempty"`
Create map[string]AddressBookChange `json:"create,omitempty"`
Update map[string]PatchObject `json:"update,omitempty"`
Destroy []string `json:"destroy,omitempty"`
@@ -6822,7 +6831,7 @@ func (c AddressBookSetCommand) GetResponse() SetResponse[AddressBook] {
type AddressBookSetResponse struct {
// The id of the account used for the call.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// The state string that would have been returned by AddressBook/get before making the
// requested changes, or null if the server doesn’t know what the previous state
@@ -6878,7 +6887,7 @@ func (r AddressBookSetResponse) GetMarker() AddressBook { return A
type AddressBookChangesCommand struct {
// The id of the account to use.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// The current state of the client.
//
@@ -6909,7 +6918,7 @@ func (c AddressBookChangesCommand) GetResponse() ChangesResponse[AddressBook] {
type AddressBookChangesResponse struct {
// The id of the account used for the call.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// This is the sinceState argument echoed back; it’s the state from which the server is returning changes.
OldState State `json:"oldState"`
@@ -7144,7 +7153,7 @@ func (o ContactCardFilterOperator) IsNotEmpty() bool {
}
type ContactCardQueryCommand struct {
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
Filter ContactCardFilterElement `json:"filter,omitempty"`
@@ -7216,7 +7225,7 @@ func (c ContactCardQueryCommand) WithLimit(limit *uint) ContactCardQueryCommand
type ContactCardQueryResponse struct {
// The id of the account used for the call.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// A string encoding the current state of the query on the server.
//
@@ -7277,7 +7286,7 @@ type ContactCardGetCommand struct {
Ids []string `json:"ids,omitempty"`
// The id of the account to use.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// If supplied, only the properties listed in the array are returned for each ContactCard object.
//
@@ -7303,7 +7312,7 @@ type ContactCardGetRefCommand struct {
IdsRef *ResultReference `json:"#ids,omitempty"`
// The id of the account to use.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// If supplied, only the properties listed in the array are returned for each ContactCard object.
//
@@ -7323,7 +7332,7 @@ func (c ContactCardGetRefCommand) GetResponse() GetResponse[ContactCard] {
type ContactCardGetResponse struct {
// The id of the account used for the call.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// A (preferably short) string representing the state on the server for all the data of this type
// in the account (not just the objects returned in this call).
@@ -7357,7 +7366,7 @@ func (r ContactCardGetResponse) GetList() []ContactCard { return r.List }
type ContactCardChangesCommand struct {
// The id of the account to use.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// The current state of the client.
// This is the string that was returned as the "state" argument in the "ContactCard/get" response.
@@ -7382,7 +7391,7 @@ func (c ContactCardChangesCommand) GetResponse() ChangesResponse[ContactCard] {
type ContactCardChangesResponse struct {
// The id of the account used for the call.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// This is the "sinceState" argument echoed back; it's the state from which the server is returning changes.
OldState State `json:"oldState"`
@@ -7416,7 +7425,7 @@ func (r ContactCardChangesResponse) GetMarker() ContactCard { return ContactCar
type ContactCardSetCommand struct {
// The id of the account to use.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// This is a state string as returned by the `ContactCard/get` method.
//
@@ -7424,7 +7433,7 @@ type ContactCardSetCommand struct {
// `stateMismatch` error returned.
//
// If null, any changes will be applied to the current state.
- IfInState string `json:"ifInState,omitempty"`
+ IfInState State `json:"ifInState,omitempty"`
// A map of a creation id (a temporary id set by the client) to ContactCard objects,
// or null if no objects are to be created.
@@ -7477,7 +7486,7 @@ func (c ContactCardSetCommand) GetResponse() SetResponse[ContactCard] {
type ContactCardSetResponse struct {
// The id of the account used for the call.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// The state string that would have been returned by ContactCard/get before making the
// requested changes, or null if the server doesn’t know what the previous state
@@ -7533,7 +7542,7 @@ func (r ContactCardSetResponse) GetMarker() ContactCard { return C
type CalendarEventParseCommand struct {
// The id of the account to use.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// The ids of the blobs to parse
BlobIds []string `json:"blobIds,omitempty"`
@@ -7554,7 +7563,7 @@ func (c CalendarEventParseCommand) GetResponse() ParseResponse[CalendarEvent] {
type CalendarEventParseResponse struct {
// The id of the account used for the call.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// A map of blob ids to parsed CalendarEvent objects representations for each successfully
// parsed blob, or null if none.
@@ -7573,8 +7582,8 @@ var _ ParseResponse[CalendarEvent] = &CalendarEventParseResponse{}
func (r CalendarEventParseResponse) GetMarker() CalendarEvent { return CalendarEvent{} }
type CalendarGetCommand struct {
- AccountId string `json:"accountId"`
- Ids []string `json:"ids,omitempty"`
+ AccountId AccountId `json:"accountId"`
+ Ids []string `json:"ids,omitempty"`
}
var _ GetCommand[Calendar] = &CalendarGetCommand{}
@@ -7584,7 +7593,7 @@ func (c CalendarGetCommand) GetObjectType() ObjectType { return Calenda
func (c CalendarGetCommand) GetResponse() GetResponse[Calendar] { return CalendarGetResponse{} }
type CalendarGetRefCommand struct {
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
IdsRef *ResultReference `json:"#ids,omitempty"`
}
@@ -7595,7 +7604,7 @@ func (c CalendarGetRefCommand) GetObjectType() ObjectType { return Cale
func (c CalendarGetRefCommand) GetResponse() GetResponse[Calendar] { return CalendarGetResponse{} }
type CalendarGetResponse struct {
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
State State `json:"state,omitempty"`
List []Calendar `json:"list,omitempty"`
NotFound []string `json:"notFound,omitempty"`
@@ -7609,8 +7618,8 @@ func (r CalendarGetResponse) GetNotFound() []string { return r.NotFound }
func (r CalendarGetResponse) GetList() []Calendar { return r.List }
type CalendarSetCommand struct {
- AccountId string `json:"accountId"`
- IfInState string `json:"ifInState,omitempty"`
+ AccountId AccountId `json:"accountId"`
+ IfInState State `json:"ifInState,omitempty"`
Create map[string]CalendarChange `json:"create,omitempty"`
Update map[string]PatchObject `json:"update,omitempty"`
Destroy []string `json:"destroy,omitempty"`
@@ -7626,7 +7635,7 @@ func (c CalendarSetCommand) GetResponse() SetResponse[Calendar] {
type CalendarSetResponse struct {
// The id of the account used for the call.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// The state string that would have been returned by Calendar/get before making the
// requested changes, or null if the server doesn’t know what the previous state
@@ -7682,7 +7691,7 @@ func (r CalendarSetResponse) GetMarker() Calendar { return Cale
type CalendarChangesCommand struct {
// The id of the account to use.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// The current state of the client.
//
@@ -7713,7 +7722,7 @@ func (c CalendarChangesCommand) GetResponse() ChangesResponse[Calendar] {
type CalendarChangesResponse struct {
// The id of the account used for the call.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// This is the "sinceState" argument echoed back; it's the state from which the server is returning changes.
OldState State `json:"oldState"`
@@ -7893,7 +7902,7 @@ func (o CalendarEventFilterOperator) IsNotEmpty() bool {
var _ CalendarEventFilterElement = &CalendarEventFilterOperator{}
type CalendarEventQueryCommand struct {
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
Filter CalendarEventFilterElement `json:"filter,omitempty"`
@@ -7965,7 +7974,7 @@ func (c CalendarEventQueryCommand) WithLimit(limit *uint) CalendarEventQueryComm
type CalendarEventQueryResponse struct {
// The id of the account used for the call.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// A string encoding the current state of the query on the server.
//
@@ -8026,7 +8035,7 @@ type CalendarEventGetCommand struct {
Ids []string `json:"ids,omitempty"`
// The id of the account to use.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// If supplied, only the properties listed in the array are returned for each CalendarEvent object.
//
@@ -8052,7 +8061,7 @@ type CalendarEventGetRefCommand struct {
IdsRef *ResultReference `json:"#ids,omitempty"`
// The id of the account to use.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// If supplied, only the properties listed in the array are returned for each CalendarEvent object.
//
@@ -8072,7 +8081,7 @@ func (c CalendarEventGetRefCommand) GetResponse() GetResponse[CalendarEvent] {
type CalendarEventGetResponse struct {
// The id of the account used for the call.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// A (preferably short) string representing the state on the server for all the data of this type
// in the account (not just the objects returned in this call).
@@ -8106,7 +8115,7 @@ func (r CalendarEventGetResponse) GetList() []CalendarEvent { return r.List }
type CalendarEventChangesCommand struct {
// The id of the account to use.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// The current state of the client.
//
@@ -8137,7 +8146,7 @@ func (c CalendarEventChangesCommand) GetResponse() ChangesResponse[CalendarEvent
type CalendarEventChangesResponse struct {
// The id of the account used for the call.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// This is the "sinceState" argument echoed back; it's the state from which the server is returning changes.
OldState State `json:"oldState"`
@@ -8171,7 +8180,7 @@ func (r CalendarEventChangesResponse) GetMarker() CalendarEvent { return Calenda
type CalendarEventSetCommand struct {
// The id of the account to use.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// This is a state string as returned by the `CalendarEvent/get` method.
//
@@ -8179,7 +8188,7 @@ type CalendarEventSetCommand struct {
// `stateMismatch` error returned.
//
// If null, any changes will be applied to the current state.
- IfInState string `json:"ifInState,omitempty"`
+ IfInState State `json:"ifInState,omitempty"`
// A map of a creation id (a temporary id set by the client) to CalendarEvent objects,
// or null if no objects are to be created.
@@ -8232,7 +8241,7 @@ func (c CalendarEventSetCommand) GetResponse() SetResponse[CalendarEvent] {
type CalendarEventSetResponse struct {
// The id of the account used for the call.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// The state string that would have been returned by CalendarEvent/get before making the
// requested changes, or null if the server doesn’t know what the previous state
@@ -8287,8 +8296,8 @@ func (r CalendarEventSetResponse) GetNotDestroyed() map[string]SetError { return
func (r CalendarEventSetResponse) GetMarker() CalendarEvent { return CalendarEvent{} }
type PrincipalGetCommand struct {
- AccountId string `json:"accountId"`
- Ids []string `json:"ids,omitempty"`
+ AccountId AccountId `json:"accountId"`
+ Ids []PrincipalId `json:"ids,omitempty"`
}
var _ GetCommand[Principal] = &PrincipalGetCommand{}
@@ -8298,7 +8307,7 @@ func (c PrincipalGetCommand) GetObjectType() ObjectType { return Princ
func (c PrincipalGetCommand) GetResponse() GetResponse[Principal] { return PrincipalGetResponse{} }
type PrincipalGetRefCommand struct {
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
IdsRef *ResultReference `json:"#ids,omitempty"`
}
@@ -8310,7 +8319,7 @@ func (c PrincipalGetRefCommand) GetResponse() GetResponse[Principal] { return Pr
type PrincipalGetResponse struct {
// The id of the account used for the call.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// A (preferably short) string representing the state on the server for all the data of this type in the account
// (not just the objects returned in this call).
@@ -8346,7 +8355,7 @@ type PrincipalFilterElement interface {
type PrincipalFilterCondition struct {
// A list of Account ids.
// The Principal matches if any of the ids in this list are keys in the Principal's "accounts" property (i.e., if any of the Account ids belong to the Principal).
- AccountIds []string `json:"accountIds,omitempty"`
+ AccountIds []AccountId `json:"accountIds,omitempty"`
// The email property of the Principal contains the given string.
Email string `json:"email,omitempty"`
// The name property of the Principal contains the given string.
@@ -8394,7 +8403,7 @@ var _ Comparator[Principal] = &PrincipalComparator{}
func (c PrincipalComparator) GetMarker() Principal { return Principal{} }
type PrincipalQueryCommand struct {
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
Filter PrincipalFilterElement `json:"filter,omitempty"`
Sort []PrincipalComparator `json:"sort,omitempty"`
@@ -8464,7 +8473,7 @@ func (c PrincipalQueryCommand) WithLimit(limit *uint) PrincipalQueryCommand {
type PrincipalQueryResponse struct {
// The id of the account used for the call.
- AccountId string `json:"accountId"`
+ AccountId AccountId `json:"accountId"`
// A string encoding the current state of the query on the server.
//
diff --git a/pkg/jmap/model_examples.go b/pkg/jmap/model_examples.go
index 1c763bcabd..2585ca15bc 100644
--- a/pkg/jmap/model_examples.go
+++ b/pkg/jmap/model_examples.go
@@ -124,8 +124,8 @@ func SerializeExamples(e any) { //NOSONAR
}
type Exemplar struct {
- AccountId string
- SharedAccountId string
+ AccountId AccountId
+ SharedAccountId AccountId
IdentityId string
IdentityName string
EmailAddress string
@@ -331,9 +331,9 @@ func (e Exemplar) SessionCalendarsParseAccountCapabilities() SessionCalendarsPar
return SessionCalendarsParseAccountCapabilities{}
}
-func (e Exemplar) sessionPrincipalsAccountCapabilities(accountId string) SessionPrincipalsAccountCapabilities {
+func (e Exemplar) sessionPrincipalsAccountCapabilities(accountId AccountId) SessionPrincipalsAccountCapabilities {
return SessionPrincipalsAccountCapabilities{
- CurrentUserPrincipalId: accountId,
+ CurrentUserPrincipalId: PrincipalId(accountId),
}
}
@@ -380,7 +380,7 @@ func (e Exemplar) SessionTasksCustomTimezonesAccountCapabilities() SessionTasksC
func (e Exemplar) SessionPrincipalsOwnerAccountCapabilities() SessionPrincipalsOwnerAccountCapabilities {
return SessionPrincipalsOwnerAccountCapabilities{
AccountIdForPrincipal: e.AccountId,
- PrincipalId: e.AccountId,
+ PrincipalId: PrincipalId(e.AccountId),
}
}
@@ -392,7 +392,7 @@ func (e Exemplar) SessionAccountCapabilities() SessionAccountCapabilities {
return e.sessionAccountCapabilities(e.AccountId)
}
-func (e Exemplar) sessionAccountCapabilities(accountId string) SessionAccountCapabilities {
+func (e Exemplar) sessionAccountCapabilities(accountId AccountId) SessionAccountCapabilities {
mail := e.SessionMailAccountCapabilities()
submission := e.SessionSubmissionAccountCapabilities()
vacationResponse := e.SessionVacationResponseAccountCapabilities()
@@ -446,7 +446,7 @@ func (e Exemplar) Account() (Account, string) {
func (e Exemplar) SharedAccount() (Account, string, string) {
return Account{
- Name: e.SharedAccountId,
+ Name: string(e.SharedAccountId),
IsPersonal: false,
IsReadOnly: true,
AccountCapabilities: e.sessionAccountCapabilities(e.SharedAccountId),
@@ -489,7 +489,7 @@ func (e Exemplar) Quotas() []Quota {
Scope: "account",
Used: 29102918,
HardLimit: 50000000000,
- Name: e.SharedAccountId,
+ Name: string(e.SharedAccountId),
Types: []ObjectTypeName{
EmailName,
SieveScriptName,
diff --git a/pkg/jmap/templates.go b/pkg/jmap/templates.go
index fc8ba115be..fffeda7ca1 100644
--- a/pkg/jmap/templates.go
+++ b/pkg/jmap/templates.go
@@ -8,12 +8,12 @@ import (
"github.com/rs/zerolog"
)
-func get[T Foo, GETREQ GetCommand[T], GETRESP GetResponse[T], RESP any]( //NOSONAR
+func get[T Foo, GETREQ GetCommand[T], GETRESP GetResponse[T], ID any, RESP any]( //NOSONAR
client *Client, name string, objType ObjectType,
- getCommandFactory func(string, []string) GETREQ,
+ getCommandFactory func(AccountId, []ID) GETREQ,
_ GETRESP,
mapper func(GETRESP) RESP,
- accountId string, ids []string, ctx Context) (Result[RESP], Error) {
+ accountId AccountId, ids []ID, ctx Context) (Result[RESP], Error) {
ctx = ctx.WithLogger(client.logger(name, ctx))
get := getCommandFactory(accountId, ids)
@@ -34,12 +34,12 @@ func get[T Foo, GETREQ GetCommand[T], GETRESP GetResponse[T], RESP any]( //NOSON
})
}
-func getAN[T Foo, GETREQ GetCommand[T], GETRESP GetResponse[T], RESP any]( //NOSONAR
+func getAN[T Foo, GETREQ GetCommand[T], GETRESP GetResponse[T], ID any, RESP any]( //NOSONAR
client *Client, name string, objType ObjectType,
- getCommandFactory func(string, []string) GETREQ,
+ getCommandFactory func(AccountId, []ID) GETREQ,
resp GETRESP,
- respMapper func(map[string][]T) RESP,
- accountIds []string, ids []string, ctx Context) (Result[RESP], Error) {
+ respMapper func(map[AccountId][]T) RESP,
+ accountIds []AccountId, ids []ID, ctx Context) (Result[RESP], Error) {
return getN(client, name, objType, getCommandFactory, resp,
func(r GETRESP) []T { return r.GetList() },
respMapper,
@@ -48,13 +48,13 @@ func getAN[T Foo, GETREQ GetCommand[T], GETRESP GetResponse[T], RESP any]( //NOS
)
}
-func getN[T Foo, ITEM any, GETREQ GetCommand[T], GETRESP GetResponse[T], RESP any]( //NOSONAR
+func getN[T Foo, ITEM any, GETREQ GetCommand[T], GETRESP GetResponse[T], ID any, RESP any]( //NOSONAR
client *Client, name string, objType ObjectType,
- getCommandFactory func(string, []string) GETREQ,
+ getCommandFactory func(AccountId, []ID) GETREQ,
_ GETRESP,
itemMapper func(GETRESP) ITEM,
- respMapper func(map[string]ITEM) RESP,
- accountIds []string, ids []string, ctx Context) (Result[RESP], Error) {
+ respMapper func(map[AccountId]ITEM) RESP,
+ accountIds []AccountId, ids []ID, ctx Context) (Result[RESP], Error) {
logger := client.logger(name, ctx)
ctx = ctx.WithLogger(logger)
@@ -74,8 +74,8 @@ func getN[T Foo, ITEM any, GETREQ GetCommand[T], GETRESP GetResponse[T], RESP an
}
return command(client, ctx, cmd, func(body *Response) (RESP, State, Error) {
- result := map[string]ITEM{}
- responses := map[string]GETRESP{}
+ result := map[AccountId]ITEM{}
+ responses := map[AccountId]GETRESP{}
for _, accountId := range uniqueAccountIds {
var resp GETRESP
err = retrieveResponseMatchParameters(ctx, body, c, mcid(accountId, "0"), &resp)
@@ -92,11 +92,11 @@ func getN[T Foo, ITEM any, GETREQ GetCommand[T], GETRESP GetResponse[T], RESP an
func create[T Foo, C any, SETREQ SetCommand[T], GETREQ GetCommand[T], SETRESP SetResponse[T], GETRESP GetResponse[T]]( //NOSONAR
client *Client, name string, objType ObjectType,
- setCommandFactory func(string, map[string]C) SETREQ,
- getCommandFactory func(string, string) GETREQ,
+ setCommandFactory func(AccountId, map[string]C) SETREQ,
+ getCommandFactory func(AccountId, string) GETREQ,
createdMapper func(SETRESP) map[string]*T,
listMapper func(GETRESP) []T,
- accountId string, create C,
+ accountId AccountId, create C,
ctx Context) (Result[*T], Error) {
logger := client.logger(name, ctx)
ctx = ctx.WithLogger(logger)
@@ -152,8 +152,8 @@ func create[T Foo, C any, SETREQ SetCommand[T], GETREQ GetCommand[T], SETRESP Se
}
func destroy[T Foo, REQ SetCommand[T], RESP SetResponse[T]](client *Client, name string, objType ObjectType, //NOSONAR
- setCommandFactory func(string, []string) REQ, _ RESP,
- accountId string, destroy []string, ctx Context) (Result[map[string]SetError], Error) {
+ setCommandFactory func(AccountId, []string) REQ, _ RESP,
+ accountId AccountId, destroy []string, ctx Context) (Result[map[string]SetError], Error) {
logger := client.logger(name, ctx)
ctx = ctx.WithLogger(logger)
@@ -248,19 +248,19 @@ func changes[T Foo, CHANGESREQ ChangesCommand[T], GETREQ GetCommand[T], CHANGESR
func changesN[T Foo, CHANGESREQ ChangesCommand[T], GETREQ GetCommand[T], CHANGESRESP ChangesResponse[T], GETRESP GetResponse[T], ITEM any, CHANGESITEM any, RESP any]( //NOSONAR
client *Client, name string, objType ObjectType,
- accountIds []string, sinceStateMap map[string]State,
- changesCommandFactory func(string, State) CHANGESREQ,
+ accountIds []AccountId, sinceStateMap map[AccountId]State,
+ changesCommandFactory func(AccountId, State) CHANGESREQ,
_ CHANGESRESP,
- getCommandFactory func(string, string, string) GETREQ,
+ getCommandFactory func(AccountId, string, string) GETREQ,
getMapper func(GETRESP) []ITEM,
changesItemMapper func(State, State, bool, []ITEM, []ITEM, []string) CHANGESITEM,
- respMapper func(map[string]CHANGESITEM) RESP,
+ respMapper func(map[AccountId]CHANGESITEM) RESP,
stateMapper func(GETRESP) State,
ctx Context) (Result[RESP], Error) {
logger := client.loggerParams(name, ctx, func(z zerolog.Context) zerolog.Context {
sinceStateLogDict := zerolog.Dict()
for k, v := range sinceStateMap {
- sinceStateLogDict.Str(log.SafeString(k), log.SafeString(string(v)))
+ sinceStateLogDict.Str(log.SafeString(string(k)), log.SafeString(string(v)))
}
return z.Dict(logSinceState, sinceStateLogDict)
})
@@ -303,8 +303,8 @@ func changesN[T Foo, CHANGESREQ ChangesCommand[T], GETREQ GetCommand[T], CHANGES
}
return command(client, ctx, cmd, func(body *Response) (RESP, State, Error) {
- changesItemByAccount := make(map[string]CHANGESITEM, n)
- stateByAccountId := make(map[string]State, n)
+ changesItemByAccount := make(map[AccountId]CHANGESITEM, n)
+ stateByAccountId := make(map[AccountId]State, n)
for _, accountId := range uniqueAccountIds {
var changesResponse CHANGESRESP
err = retrieveChanges(ctx, body, ch, mcid(accountId, "0"), &changesResponse)
@@ -488,13 +488,13 @@ func query[T Foo, FILTER any, SORT any, QUERY QueryCommand[T], GET GetCommand[T]
func queryN[T Foo, FILTER any, SORT any, QUERY QueryCommand[T, QUERY], GET GetCommand[T], QUERYRESP QueryResponse[T], GETRESP GetResponse[T], RESP any]( //NOSONAR
client *Client, name string, objType ObjectType,
defaultSortBy []SORT,
- queryCommandFactory func(accountId string, queryParams QueryParams, limit *uint, filter FILTER, sortBy []SORT) QUERY,
- getCommandFactory func(accountId string, cmd Command, path string, rof string) GET,
+ queryCommandFactory func(accountId AccountId, queryParams QueryParams, limit *uint, filter FILTER, sortBy []SORT) QUERY,
+ getCommandFactory func(accountId AccountId, cmd Command, path string, rof string) GET,
respMapper0 func(query QUERYRESP, queryParams QueryParams, limit *uint) *RESP,
respMapper func(query QUERYRESP, get GETRESP, queryParams QueryParams, limit *uint) *RESP,
- accountIds map[string]QueryParams,
+ accountIds map[AccountId]QueryParams,
limit *uint, filter FILTER, sortBy []SORT,
- ctx Context) (Result[map[string]*RESP], Error) {
+ ctx Context) (Result[map[AccountId]*RESP], Error) {
logger := client.logger(name, ctx)
ctx = ctx.WithLogger(logger)
@@ -525,12 +525,12 @@ func queryN[T Foo, FILTER any, SORT any, QUERY QueryCommand[T, QUERY], GET GetCo
cmd, err := client.request(ctx, objType.Namespaces, invocations...)
if err != nil {
- return ZeroResult[map[string]*RESP](), err
+ return ZeroResult[map[AccountId]*RESP](), err
}
- return command(client, ctx, cmd, func(body *Response) (map[string]*RESP, State, Error) {
- resp := map[string]*RESP{}
- stateByAccountId := map[string]State{}
+ return command(client, ctx, cmd, func(body *Response) (map[AccountId]*RESP, State, Error) {
+ resp := map[AccountId]*RESP{}
+ stateByAccountId := map[AccountId]State{}
for accountId, queryParams := range accountIds {
var queryResponse QUERYRESP
err = retrieveQuery(ctx, body, q, mcid(accountId, "0"), &queryResponse)
diff --git a/pkg/jmap/tools.go b/pkg/jmap/tools.go
index 3956aa3673..e00bef9bcc 100644
--- a/pkg/jmap/tools.go
+++ b/pkg/jmap/tools.go
@@ -44,13 +44,13 @@ func newEventListeners[T any]() *eventListeners[T] {
// Create an identifier to use as a method call ID, from the specified accountId and additional
// tag, to make something unique within that API request.
-func mcid(accountId string, tag string) string {
+func mcid(accountId AccountId, tag string) string {
// https://jmap.io/spec-core.html#the-invocation-data-type
// May be any string of data:
// An arbitrary string from the client to be echoed back with the responses emitted by that method
// call (a method may return 1 or more responses, as it may make implicit calls to other methods;
// all responses initiated by this method call get the same method call id in the response).
- return accountId + ":" + tag
+ return string(accountId) + ":" + tag
}
type Cmdr interface {
@@ -308,7 +308,7 @@ func (i *Invocation) UnmarshalJSON(bs []byte) error {
return nil
}
-func squashState(all map[string]State) State {
+func squashState[K ~string](all map[K]State) State {
return squashStateFunc(all, func(s State) State { return s })
}
@@ -318,11 +318,11 @@ func squashStates(states ...State) State {
}
*/
-func squashKeyedStates(m map[string]State) State {
+func squashKeyedStates[K ~string](m map[K]State) State {
return squashStateFunc(m, identity1)
}
-func squashStateFunc[V any](all map[string]V, mapper func(V) State) State {
+func squashStateFunc[K ~string, V any](all map[K]V, mapper func(V) State) State {
n := len(all)
if n == 0 {
return State("")
@@ -334,7 +334,7 @@ func squashStateFunc[V any](all map[string]V, mapper func(V) State) State {
}
parts := make([]string, n)
- sortedKeys := make([]string, n)
+ sortedKeys := make([]K, n)
i := 0
for k := range all {
sortedKeys[i] = k
@@ -343,15 +343,15 @@ func squashStateFunc[V any](all map[string]V, mapper func(V) State) State {
slices.Sort(sortedKeys)
for i, k := range sortedKeys {
if v, ok := all[k]; ok {
- parts[i] = k + ":" + string(mapper(v))
+ parts[i] = string(k) + ":" + string(mapper(v))
} else {
- parts[i] = k + ":"
+ parts[i] = string(k) + ":"
}
}
return State(strings.Join(parts, ","))
}
-func squashStateMaps(first map[string]State, second map[string]State) State {
+func squashStateMaps(first map[AccountId]State, second map[AccountId]State) State {
return squashStateFunc(mapPairs(first, second), func(p pair[State, State]) State {
if p.left != nil {
if p.right != nil {
diff --git a/pkg/log/log_safely.go b/pkg/log/log_safely.go
index 67c4df9dd6..686a2d67e2 100644
--- a/pkg/log/log_safely.go
+++ b/pkg/log/log_safely.go
@@ -9,11 +9,12 @@ const (
// Safely caps a string to a given size to avoid log bombing.
// Use this function to wrap strings that are user input (HTTP headers, path parameters, URI parameters, HTTP body, ...).
-func SafeString(text string) string {
- runes := []rune(text)
+func SafeString[S ~string](text S) string {
+ t := string(text)
+ runes := []rune(t)
if len(runes) <= logMaxStrLength {
- return text
+ return t
} else {
return string(runes[0:logMaxStrLength-1]) + `\u2026` // hellip
}
diff --git a/pkg/structs/structs.go b/pkg/structs/structs.go
index ff7cc3cdaf..ce997ea7ce 100644
--- a/pkg/structs/structs.go
+++ b/pkg/structs/structs.go
@@ -95,6 +95,10 @@ func Set[V comparable](source []V) map[V]struct{} {
return result
}
+func ToStrings[A ~string](s []A) []string {
+ return Map(s, func(a A) string { return string(a) })
+}
+
// Creates a slice from a slice, putting each value from the source slice through the
// mapper function to determine the value to store into the resulting slice.
func Map[E any, R any](source []E, mapper func(E) R) []R {
@@ -156,6 +160,16 @@ func MapO[E any, R any](source []E, indexer func(E) (R, bool)) []R {
return result
}
+// Created a map from a map, mapping both the key and the value using the mapper function.
+func MapMap[A comparable, B any, X comparable, Y any](m map[A]B, mapper func(A, B) (X, Y)) map[X]Y {
+ r := make(map[X]Y, len(m))
+ for a, b := range m {
+ x, y := mapper(a, b)
+ r[x] = y
+ }
+ return r
+}
+
// Creates a map from a map, keeping each key as-is, and using the mapper
// function to determine the value to store into the resulting map.
func MapValues[K comparable, S any, T any](m map[K]S, mapper func(S) T) map[K]T {
diff --git a/pkg/structs/structs_test.go b/pkg/structs/structs_test.go
index 82ca9034a4..c4eac27285 100644
--- a/pkg/structs/structs_test.go
+++ b/pkg/structs/structs_test.go
@@ -122,6 +122,24 @@ func TestIndex(t *testing.T) {
}
}
+func TestMapMap(t *testing.T) {
+ {
+ m := map[string]int{
+ "un": 1,
+ "deux": 2,
+ "trois": 3,
+ }
+ n := MapMap(m, func(a string, b int) (string, int) { return strings.ToUpper(a), b + 100 })
+ assert.Len(t, n, 3)
+ assert.Contains(t, n, "UN")
+ assert.Equal(t, 1001, n["UN"])
+ assert.Contains(t, n, "DEUX")
+ assert.Equal(t, 1002, n["DEUX"])
+ assert.Contains(t, n, "TROIS")
+ assert.Equal(t, 1003, n["TROIS"])
+ }
+}
+
func TestMap(t *testing.T) {
tests := []struct {
input []string
diff --git a/services/groupware/QueryPagination.md b/services/groupware/QueryPagination.md
index d65a203046..0f64bad7d9 100644
--- a/services/groupware/QueryPagination.md
+++ b/services/groupware/QueryPagination.md
@@ -244,4 +244,3 @@ The alternative would be to have different APIs depending on what each endpoint
* endpoint with multiple backends or multiple accounts:
same as above with `?first=...` and `?next=...`
* endpoint with a single backend and a single account:
`?position=...&anchor=...&offset=...&limit=...`
-
diff --git a/services/groupware/pkg/groupware/address_book_supplier_jmap.go b/services/groupware/pkg/groupware/address_book_supplier_jmap.go
index 25e1d962f4..7dd86b3183 100644
--- a/services/groupware/pkg/groupware/address_book_supplier_jmap.go
+++ b/services/groupware/pkg/groupware/address_book_supplier_jmap.go
@@ -17,18 +17,20 @@ func newJmapContactCardSupplier(client *jmap.Client) *JmapContactCardSupplier {
return &JmapContactCardSupplier{client: client}
}
-func (c *JmapContactCardSupplier) GetId() string {
- return "jmap"
+const jmapContactCardSupplierid = SupplierId("jmap")
+
+func (c *JmapContactCardSupplier) GetId() SupplierId {
+ return jmapContactCardSupplierid
}
func (c *JmapContactCardSupplier) IsMine(id string) bool {
return id != "" && !strings.Contains(id, ":")
}
-func (c *JmapContactCardSupplier) GetAll(accountId string, ids []string, ctx jmap.Context) (jmap.Result[jmap.AddressBookGetResponse], error) {
+func (c *JmapContactCardSupplier) GetAll(accountId jmap.AccountId, ids []string, ctx jmap.Context) (jmap.Result[jmap.AddressBookGetResponse], error) {
return c.client.GetAddressbooks(accountId, ids, ctx)
}
-func (c *JmapContactCardSupplier) Query(accountIds []string, qps QueryParamsSupplier, limit *uint, filter jmap.ContactCardFilterElement, sortBy []jmap.ContactCardComparator, calculateTotal bool, ctx jmap.Context) (jmap.Result[map[string]*jmap.ContactCardSearchResults], error) { //NOSONAR
+func (c *JmapContactCardSupplier) Query(accountIds []jmap.AccountId, qps QueryParamsSupplier, limit *uint, filter jmap.ContactCardFilterElement, sortBy []jmap.ContactCardComparator, calculateTotal bool, ctx jmap.Context) (jmap.Result[map[jmap.AccountId]*jmap.ContactCardSearchResults], error) { //NOSONAR
if m, err := mapQueryParams(c.GetId(), accountIds, qps); err != nil {
- return jmap.ZeroResult[map[string]*jmap.ContactCardSearchResults](), err
+ return jmap.ZeroResult[map[jmap.AccountId]*jmap.ContactCardSearchResults](), err
} else {
return c.client.QueryContactCards(m, limit, filter, sortBy, calculateTotal, ctx)
}
diff --git a/services/groupware/pkg/groupware/address_book_supplier_mock.go b/services/groupware/pkg/groupware/address_book_supplier_mock.go
index ca8f9ea441..ab10314123 100644
--- a/services/groupware/pkg/groupware/address_book_supplier_mock.go
+++ b/services/groupware/pkg/groupware/address_book_supplier_mock.go
@@ -64,13 +64,13 @@ func newMockContactCardSupplier() *MockContactCardSupplier {
return MockContactCardSupplierInstance
}
-func (c *MockContactCardSupplier) GetId() string {
- return "mock"
+func (c *MockContactCardSupplier) GetId() SupplierId {
+ return SupplierId("mock")
}
func (c *MockContactCardSupplier) IsMine(id string) bool {
return strings.HasPrefix(id, "mock:")
}
-func (c *MockContactCardSupplier) GetAll(accountId string, ids []string, ctx jmap.Context) (jmap.Result[jmap.AddressBookGetResponse], error) {
+func (c *MockContactCardSupplier) GetAll(accountId jmap.AccountId, ids []string, ctx jmap.Context) (jmap.Result[jmap.AddressBookGetResponse], error) {
abooks := []jmap.AddressBook{c.addressBook}
if len(ids) > 0 {
abooks = structs.Filter(abooks, func(a jmap.AddressBook) bool { return slices.Contains(ids, a.Id) })
@@ -86,14 +86,14 @@ func (c *MockContactCardSupplier) GetAll(accountId string, ids []string, ctx jma
},
}, nil
}
-func (c *MockContactCardSupplier) Query(accountIds []string, qps QueryParamsSupplier, limit *uint, filter jmap.ContactCardFilterElement, sortBy []jmap.ContactCardComparator, calculateTotal bool, ctx jmap.Context) (jmap.Result[map[string]*jmap.ContactCardSearchResults], error) { //NOSONAR
- payload := make(map[string]*jmap.ContactCardSearchResults, len(accountIds))
+func (c *MockContactCardSupplier) Query(accountIds []jmap.AccountId, qps QueryParamsSupplier, limit *uint, filter jmap.ContactCardFilterElement, sortBy []jmap.ContactCardComparator, calculateTotal bool, ctx jmap.Context) (jmap.Result[map[jmap.AccountId]*jmap.ContactCardSearchResults], error) { //NOSONAR
+ payload := make(map[jmap.AccountId]*jmap.ContactCardSearchResults, len(accountIds))
total := len(c.contacts)
for _, accountId := range accountIds {
all := []jmap.ContactCard{}
var qp jmap.QueryParams
if q, ok, err := qps.ForSupplier(c.GetId(), accountId); err != nil {
- return jmap.ZeroResult[map[string]*jmap.ContactCardSearchResults](), err
+ return jmap.ZeroResult[map[jmap.AccountId]*jmap.ContactCardSearchResults](), err
} else if ok {
qp = q
} else {
@@ -141,7 +141,7 @@ func (c *MockContactCardSupplier) Query(accountIds []string, qps QueryParamsSupp
payload[accountId] = res
}
- return jmap.Result[map[string]*jmap.ContactCardSearchResults]{
+ return jmap.Result[map[jmap.AccountId]*jmap.ContactCardSearchResults]{
Payload: payload,
SessionState: jmap.EmptySessionState,
State: jmap.EmptyState,
diff --git a/services/groupware/pkg/groupware/api_account.go b/services/groupware/pkg/groupware/api_account.go
index 92b6b7ef1d..dbcbeafe2a 100644
--- a/services/groupware/pkg/groupware/api_account.go
+++ b/services/groupware/pkg/groupware/api_account.go
@@ -34,9 +34,9 @@ func (g *Groupware) GetAccounts(w http.ResponseWriter, r *http.Request) {
i++
}
// 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) })
+ slices.SortFunc(list, func(a, b AccountWithId) int { return strings.Compare(string(a.AccountId), string(b.AccountId)) })
var RBODY []AccountWithId = list
- return req.respondN(structs.Map(list, func(a AccountWithId) string { return a.AccountId }), RBODY, AccountResponseObjectType, req.session)
+ return req.respondN(structs.Map(list, func(a AccountWithId) jmap.AccountId { return a.AccountId }), RBODY, AccountResponseObjectType, req.session)
})
}
@@ -64,19 +64,21 @@ func (g *Groupware) GetAccountsWithTheirIdentities(w http.ResponseWriter, r *htt
i++
}
// 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) })
+ slices.SortFunc(list, func(a, b AccountWithIdAndIdentities) int {
+ return strings.Compare(string(a.AccountId), string(b.AccountId))
+ })
var RBODY []AccountWithIdAndIdentities = list
- return req.respondN(structs.Map(list, func(a AccountWithIdAndIdentities) string { return a.AccountId }), RBODY, AccountResponseObjectType, resp)
+ return req.respondN(structs.Map(list, func(a AccountWithIdAndIdentities) jmap.AccountId { return a.AccountId }), RBODY, AccountResponseObjectType, resp)
})
}
type AccountWithId struct {
- AccountId string `json:"accountId,omitempty"`
+ AccountId jmap.AccountId `json:"accountId,omitempty"`
jmap.Account
}
type AccountWithIdAndIdentities struct {
- AccountId string `json:"accountId,omitempty"`
+ AccountId jmap.AccountId `json:"accountId,omitempty"`
Identities []jmap.Identity `json:"identities,omitempty"`
jmap.Account
}
diff --git a/services/groupware/pkg/groupware/api_addressbooks.go b/services/groupware/pkg/groupware/api_addressbooks.go
index 38f9a880d3..45621b2859 100644
--- a/services/groupware/pkg/groupware/api_addressbooks.go
+++ b/services/groupware/pkg/groupware/api_addressbooks.go
@@ -34,8 +34,8 @@ func (g *Groupware) ModifyAddressBook(w http.ResponseWriter, r *http.Request) {
modify(AddressBook, w, r, g, g.jmap.UpdateAddressBook)
}
-func (g *Groupware) addressbooks(accountId string, ids []string, ctx jmap.Context) (jmap.Result[jmap.AddressBookGetResponse], error) {
- return slist(g.addressBookListSuppliers, accountId, ids, ctx, func(accountId string, state jmap.State, notFound []string, list []jmap.AddressBook) jmap.AddressBookGetResponse {
+func (g *Groupware) addressbooks(accountId jmap.AccountId, ids []string, ctx jmap.Context) (jmap.Result[jmap.AddressBookGetResponse], error) {
+ return slist(g.addressBookListSuppliers, accountId, ids, ctx, func(accountId jmap.AccountId, state jmap.State, notFound []string, list []jmap.AddressBook) jmap.AddressBookGetResponse {
return jmap.AddressBookGetResponse{AccountId: accountId, State: state, NotFound: notFound, List: list}
})
}
diff --git a/services/groupware/pkg/groupware/api_blob.go b/services/groupware/pkg/groupware/api_blob.go
index 8d33ab78ee..e612247a1c 100644
--- a/services/groupware/pkg/groupware/api_blob.go
+++ b/services/groupware/pkg/groupware/api_blob.go
@@ -34,7 +34,7 @@ func (g *Groupware) UploadBlob(w http.ResponseWriter, r *http.Request) {
if err != nil {
return req.error(accountId, err)
}
- logger := log.From(req.logger.With().Str(logAccountId, accountId))
+ logger := log.From(req.logger.With().Str(logAccountId, log.SafeString(accountId)))
ctx := req.ctx.WithLogger(logger)
resp, _, jerr := g.jmap.UploadBlobStream(accountId, contentType, body, ctx)
if jerr != nil {
@@ -63,7 +63,7 @@ func (g *Groupware) DownloadBlob(w http.ResponseWriter, r *http.Request) {
}
typ, _ := req.getStringParam(QueryParamBlobType, "") // optionally, the Content-Type of the blob, which is then used in the response
- logger := log.From(req.logger.With().Str(logAccountId, accountId).Str(UriParamBlobId, blobId))
+ logger := log.From(req.logger.With().Str(logAccountId, log.SafeString(accountId)).Str(UriParamBlobId, blobId))
ctx := req.ctx.WithLogger(logger)
if err := req.serveBlob(blobId, name, typ, ctx, accountId, w); err != nil {
@@ -74,7 +74,7 @@ func (g *Groupware) DownloadBlob(w http.ResponseWriter, r *http.Request) {
})
}
-func (r *Request) serveBlob(blobId string, name string, typ string, ctx jmap.Context, accountId string, w http.ResponseWriter) *Error { //NOSONAR
+func (r *Request) serveBlob(blobId string, name string, typ string, ctx jmap.Context, accountId jmap.AccountId, w http.ResponseWriter) *Error { //NOSONAR
if typ == "" {
typ = DefaultBlobDownloadType
}
diff --git a/services/groupware/pkg/groupware/api_changes.go b/services/groupware/pkg/groupware/api_changes.go
index fa7ec29068..4650eeb91a 100644
--- a/services/groupware/pkg/groupware/api_changes.go
+++ b/services/groupware/pkg/groupware/api_changes.go
@@ -34,7 +34,7 @@ func (g *Groupware) GetChanges(w http.ResponseWriter, r *http.Request) { //NOSON
if err != nil {
return req.error(accountId, err)
}
- l = l.Str(logAccountId, accountId)
+ l = l.Str(logAccountId, log.SafeString(accountId))
var maxChanges uint = 0
if v, ok, err := req.parseUIntParam(QueryParamMaxChanges, 0); err != nil { // The maximum amount of changes to emit for each type of object.
diff --git a/services/groupware/pkg/groupware/api_contacts.go b/services/groupware/pkg/groupware/api_contacts.go
index e5ee8f2906..cfe96db940 100644
--- a/services/groupware/pkg/groupware/api_contacts.go
+++ b/services/groupware/pkg/groupware/api_contacts.go
@@ -82,7 +82,7 @@ func (g *Groupware) ModifyContact(w http.ResponseWriter, r *http.Request) {
modify(Contact, w, r, g, g.jmap.UpdateContactCard)
}
-func (g *Groupware) contacts(accountIds []string, qps QueryParamsSupplier, limit *uint, //NOSONAR
+func (g *Groupware) contacts(accountIds []jmap.AccountId, qps QueryParamsSupplier, limit *uint, //NOSONAR
filter jmap.ContactCardFilterElement, sortBy []jmap.ContactCardComparator, calculateTotal bool,
ctx jmap.Context) (jmap.Result[*jmap.ContactCardSearchResults], NextToken, error) {
return squery(g.contactCardQuerySuppliers, accountIds, qps, limit, filter, sortBy, calculateTotal, ctx,
diff --git a/services/groupware/pkg/groupware/api_emails.go b/services/groupware/pkg/groupware/api_emails.go
index 9e6f6d5eac..5582cac8c1 100644
--- a/services/groupware/pkg/groupware/api_emails.go
+++ b/services/groupware/pkg/groupware/api_emails.go
@@ -24,7 +24,7 @@ import (
// Get the changes tp Emails since a certain State.
// @api:tags email,changes
func (g *Groupware) GetEmailChanges(w http.ResponseWriter, r *http.Request) {
- changes(Email, w, r, g, func(accountId string, sinceState jmap.State, maxChanges uint, ctx jmap.Context) (jmap.Result[jmap.EmailChanges], error) {
+ changes(Email, w, r, g, func(accountId jmap.AccountId, sinceState jmap.State, maxChanges uint, ctx jmap.Context) (jmap.Result[jmap.EmailChanges], error) {
return g.jmap.GetEmailChanges(accountId, sinceState, true, g.config.maxBodyValueBytes, maxChanges, ctx)
})
}
@@ -42,7 +42,7 @@ func (g *Groupware) GetAllEmailsInMailbox(w http.ResponseWriter, r *http.Request
fetchBodies := false
withThreads := true
query(Email, w, r, g, g.defaults.emailLimit,
- func(req Request, accountId string, containerId string, qp jmap.QueryParams, limit *uint, ctx jmap.Context) (jmap.Result[*jmap.EmailSearchResults], error) { //NOSONAR
+ func(req Request, accountId jmap.AccountId, containerId string, qp jmap.QueryParams, limit *uint, ctx jmap.Context) (jmap.Result[*jmap.EmailSearchResults], error) { //NOSONAR
result, jerr := g.jmap.GetAllEmailsInMailbox(accountId, containerId, qp, limit, collapseThreads, fetchBodies, g.config.maxBodyValueBytes, withThreads, ctx)
if jerr != nil {
return jmap.ZeroResult[*jmap.EmailSearchResults](), jerr
@@ -348,13 +348,13 @@ func (g *Groupware) getEmailsSince(w http.ResponseWriter, r *http.Request, since
type EmailSearchSnippetsResults jmap.SearchResultsTemplate[Snippet]
type EmailWithSnippets struct {
- AccountId string `json:"accountId,omitempty"`
+ AccountId jmap.AccountId `json:"accountId,omitempty"`
Snippets []SnippetWithoutEmailId `json:"snippets,omitempty"`
jmap.Email
}
type Snippet struct {
- AccountId string `json:"accountId,omitempty"`
+ AccountId jmap.AccountId `json:"accountId,omitempty"`
jmap.SearchSnippetWithMeta
}
@@ -649,7 +649,7 @@ func (g *Groupware) GetEmailsForAllAccounts(w http.ResponseWriter, r *http.Reque
if !ok {
return req.errorN(allAccountIds, err)
}
- logger = log.From(req.logger.With().Array(logAccountId, log.SafeStringArray(allAccountIds)))
+ logger = log.From(req.logger.With().Array(logAccountId, log.SafeStringArray(structs.ToStrings(allAccountIds))))
ctx := req.ctx.WithLogger(logger)
if !filter.IsNotEmpty() {
@@ -758,7 +758,7 @@ var draftEmailAutoMailboxRolePrecedence = []string{
jmap.JmapMailboxRoleInbox, // but if there is none, we will use the Mailbox with the inbox role instead
}
-func findDraftsMailboxId(j *jmap.Client, accountId string, req Request, ctx jmap.Context) (string, Response) {
+func findDraftsMailboxId(j *jmap.Client, accountId jmap.AccountId, req Request, ctx jmap.Context) (string, Response) {
result, jerr := j.SearchMailboxIdsPerRole(single(accountId), draftEmailAutoMailboxRolePrecedence, ctx)
if jerr != nil {
return "", req.jmapError(accountId, jerr, result)
@@ -781,7 +781,7 @@ var sentEmailAutoMailboxRolePrecedence = []string{
var draftAndSentMailboxRoles = structs.Uniq(structs.Concat(draftEmailAutoMailboxRolePrecedence, sentEmailAutoMailboxRolePrecedence))
-func findSentMailboxId(j *jmap.Client, accountId string, req Request, ctx jmap.Context) (string, string, Response) { //NOSONAR
+func findSentMailboxId(j *jmap.Client, accountId jmap.AccountId, req Request, ctx jmap.Context) (string, string, Response) { //NOSONAR
result, jerr := j.SearchMailboxIdsPerRole(single(accountId), draftAndSentMailboxRoles, ctx)
if jerr != nil {
return "", "", req.jmapError(accountId, jerr, result)
@@ -812,7 +812,7 @@ func findSentMailboxId(j *jmap.Client, accountId string, req Request, ctx jmap.C
func (g *Groupware) CreateEmail(w http.ResponseWriter, r *http.Request) {
create(Email, w, r, g,
- func(r Request, accountId string, body *jmap.EmailChange, ctx jmap.Context) (bool, Response) {
+ func(r Request, accountId jmap.AccountId, body *jmap.EmailChange, ctx jmap.Context) (bool, Response) {
if len(body.MailboxIds) < 1 {
mailboxId, resp := findDraftsMailboxId(g.jmap, accountId, r, ctx)
if mailboxId != "" && body != nil {
@@ -826,7 +826,7 @@ func (g *Groupware) CreateEmail(w http.ResponseWriter, r *http.Request) {
}
return true, Response{}
},
- func(accountId string, body jmap.EmailChange, ctx jmap.Context) (jmap.Result[*jmap.Email], error) {
+ func(accountId jmap.AccountId, body jmap.EmailChange, ctx jmap.Context) (jmap.Result[*jmap.Email], error) {
return g.jmap.CreateEmail(accountId, body, "", ctx)
},
)
@@ -835,7 +835,7 @@ func (g *Groupware) CreateEmail(w http.ResponseWriter, r *http.Request) {
func (g *Groupware) ReplaceEmail(w http.ResponseWriter, r *http.Request) {
replaceId := ""
create(Email, w, r, g,
- func(r Request, accountId string, body *jmap.EmailChange, ctx jmap.Context) (bool, Response) {
+ func(r Request, accountId jmap.AccountId, body *jmap.EmailChange, ctx jmap.Context) (bool, Response) {
if len(body.MailboxIds) < 1 {
mailboxId, resp := findDraftsMailboxId(g.jmap, accountId, r, ctx)
if mailboxId != "" {
@@ -852,7 +852,7 @@ func (g *Groupware) ReplaceEmail(w http.ResponseWriter, r *http.Request) {
return true, Response{}
},
- func(accountId string, body jmap.EmailChange, ctx jmap.Context) (jmap.Result[*jmap.Email], error) {
+ func(accountId jmap.AccountId, body jmap.EmailChange, ctx jmap.Context) (jmap.Result[*jmap.Email], error) {
ctx = ctx.WithLogger(log.From(ctx.Logger.With().Str("replaceId", replaceId)))
return g.jmap.CreateEmail(accountId, body, replaceId, ctx)
},
@@ -883,7 +883,7 @@ func (g *Groupware) UpdateEmailKeywords(w http.ResponseWriter, r *http.Request)
if gwerr != nil {
return req.error(accountId, gwerr)
}
- l.Str(logAccountId, accountId)
+ l.Str(logAccountId, log.SafeString(accountId))
emailId, err := req.PathParam(UriParamEmailId)
if err != nil {
@@ -945,7 +945,7 @@ func (g *Groupware) AddEmailKeywords(w http.ResponseWriter, r *http.Request) { /
if gwerr != nil {
return req.error(accountId, gwerr)
}
- l.Str(logAccountId, accountId)
+ l.Str(logAccountId, log.SafeString(accountId))
emailId, err := req.PathParam(UriParamEmailId)
if err != nil {
@@ -1008,7 +1008,7 @@ func (g *Groupware) RemoveEmailKeywords(w http.ResponseWriter, r *http.Request)
if err != nil {
return req.error(accountId, err)
}
- l.Str(logAccountId, accountId)
+ l.Str(logAccountId, log.SafeString(accountId))
emailId, err := req.PathParam(UriParamEmailId)
if err != nil {
@@ -1082,7 +1082,7 @@ func (g *Groupware) SendEmail(w http.ResponseWriter, r *http.Request) { //NOSONA
if gwerr != nil {
return req.error(accountId, gwerr)
}
- l.Str(logAccountId, accountId)
+ l.Str(logAccountId, log.SafeString(accountId))
emailId, err := req.PathParam(UriParamEmailId)
if err != nil {
@@ -1309,7 +1309,7 @@ func (g *Groupware) RelatedToEmail(w http.ResponseWriter, r *http.Request) { //N
type EmailSummary struct {
// The id of the account this Email summary pertains to.
- AccountId string `json:"accountId,omitempty"`
+ AccountId jmap.AccountId `json:"accountId,omitempty"`
// The id of the Email object.
//
@@ -1450,7 +1450,7 @@ var _ jmap.Foo = EmailSummary{}
func (e EmailSummary) GetObjectType() jmap.ObjectType { return jmap.EmailType }
-func summarizeEmail(accountId string, email jmap.Email) EmailSummary {
+func summarizeEmail(accountId jmap.AccountId, email jmap.Email) EmailSummary {
return EmailSummary{
AccountId: accountId,
Id: email.Id,
@@ -1474,7 +1474,7 @@ func summarizeEmail(accountId string, email jmap.Email) EmailSummary {
}
type emailWithAccountId struct {
- accountId string
+ accountId jmap.AccountId
email jmap.Email
}
@@ -1495,7 +1495,7 @@ func (g *Groupware) GetLatestEmailsSummaryForAllAccounts(w http.ResponseWriter,
l := req.logger.With()
allAccountIds := req.AllAccountIds()
- l.Array(logAccountId, log.SafeStringArray(allAccountIds))
+ l.Array(logAccountId, log.SafeStringArray(structs.ToStrings(allAccountIds)))
limit, ok, err := req.parseUIntParam(QueryParamLimit, 10) // TODO from configuration
if err != nil {
diff --git a/services/groupware/pkg/groupware/api_index.go b/services/groupware/pkg/groupware/api_index.go
index db6efe5c17..7671d1ff13 100644
--- a/services/groupware/pkg/groupware/api_index.go
+++ b/services/groupware/pkg/groupware/api_index.go
@@ -90,7 +90,7 @@ type IndexAccountCapabilities struct {
}
type IndexAccount struct {
- AccountId string `json:"accountId"`
+ AccountId jmap.AccountId `json:"accountId"`
// A user-friendly string to show when presenting content from this Account,
// e.g., the email address representing the owner of the account.
@@ -116,11 +116,11 @@ type IndexAccount struct {
// Primary account identifiers per API usage type.
type IndexPrimaryAccounts struct {
- Mail string `json:"mail"`
- Submission string `json:"submission"`
- Blob string `json:"blob"`
- VacationResponse string `json:"vacationResponse"`
- Sieve string `json:"sieve"`
+ Mail jmap.AccountId `json:"mail"`
+ Submission jmap.AccountId `json:"submission"`
+ Blob jmap.AccountId `json:"blob"`
+ VacationResponse jmap.AccountId `json:"vacationResponse"`
+ Sieve jmap.AccountId `json:"sieve"`
}
type IndexResponse struct {
@@ -185,7 +185,7 @@ func buildIndexPrimaryAccounts(session *jmap.Session) IndexPrimaryAccounts {
}
}
-func buildIndexAccounts(session *jmap.Session, boot map[string]jmap.AccountBootstrapResult) []IndexAccount {
+func buildIndexAccounts(session *jmap.Session, boot map[jmap.AccountId]jmap.AccountBootstrapResult) []IndexAccount {
accounts := make([]IndexAccount, len(session.Accounts))
i := 0
for accountId, account := range session.Accounts {
@@ -206,7 +206,7 @@ func buildIndexAccounts(session *jmap.Session, boot map[string]jmap.AccountBoots
accounts[i] = indexAccount
i++
}
- slices.SortFunc(accounts, func(a, b IndexAccount) int { return strings.Compare(a.AccountId, b.AccountId) })
+ slices.SortFunc(accounts, func(a, b IndexAccount) int { return strings.Compare(string(a.AccountId), string(b.AccountId)) })
return accounts
}
diff --git a/services/groupware/pkg/groupware/api_mailbox.go b/services/groupware/pkg/groupware/api_mailbox.go
index f7b26cb0ac..8bcbf85978 100644
--- a/services/groupware/pkg/groupware/api_mailbox.go
+++ b/services/groupware/pkg/groupware/api_mailbox.go
@@ -71,7 +71,7 @@ func (g *Groupware) GetMailboxes(w http.ResponseWriter, r *http.Request) { //NOS
return resp
}
- logger := log.From(req.logger.With().Str(logAccountId, accountId))
+ logger := log.From(req.logger.With().Str(logAccountId, log.SafeString(accountId)))
ctx := req.ctx.WithLogger(logger)
if hasCriteria {
@@ -106,7 +106,7 @@ func (g *Groupware) GetMailboxesForAllAccounts(w http.ResponseWriter, r *http.Re
if len(accountIds) < 1 {
return req.noopN(nil) // when the user has no accounts
}
- logger := log.From(req.logger.With().Array(logAccountId, log.SafeStringArray(accountIds)))
+ logger := log.From(req.logger.With().Array(logAccountId, log.SafeStringArray(structs.ToStrings(accountIds))))
ctx := req.ctx.WithLogger(logger)
var filter jmap.MailboxFilterCondition
@@ -153,7 +153,7 @@ func (g *Groupware) GetMailboxByRoleForAllAccounts(w http.ResponseWriter, r *htt
return req.errorN(accountIds, err)
}
- logger := log.From(req.logger.With().Array(logAccountId, log.SafeStringArray(accountIds)).Str("role", role))
+ logger := log.From(req.logger.With().Array(logAccountId, log.SafeStringArray(structs.ToStrings(accountIds))).Str("role", role))
ctx := req.ctx.WithLogger(logger)
filter := jmap.MailboxFilterCondition{
@@ -180,7 +180,7 @@ func (g *Groupware) GetMailboxChangesForAllAccounts(w http.ResponseWriter, r *ht
l := req.logger.With()
allAccountIds := req.AllAccountIds()
- l.Array(logAccountId, log.SafeStringArray(allAccountIds))
+ l.Array(logAccountId, log.SafeStringArray(structs.ToStrings(allAccountIds)))
sinceStateStrMap, ok, err := req.parseMapParam(QueryParamSince)
if err != nil {
@@ -205,7 +205,7 @@ func (g *Groupware) GetMailboxChangesForAllAccounts(w http.ResponseWriter, r *ht
logger := log.From(l)
ctx := req.ctx.WithLogger(logger)
- sinceStateMap := structs.MapValues(sinceStateStrMap, toState)
+ sinceStateMap := structs.MapMap(sinceStateStrMap, toAccountIdState)
result, jerr := g.jmap.GetMailboxChangesForMultipleAccounts(allAccountIds, sinceStateMap, maxChanges, ctx)
if jerr != nil {
return req.jmapErrorN(allAccountIds, jerr, result)
@@ -221,7 +221,7 @@ func (g *Groupware) GetMailboxRoles(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))
+ l.Array(logAccountId, log.SafeStringArray(structs.ToStrings(allAccountIds)))
logger := log.From(l)
ctx := req.ctx.WithLogger(logger)
@@ -257,8 +257,8 @@ func scoreMailbox(m jmap.Mailbox) int {
return 1000
}
-func sortMailboxesMap(mailboxesByAccountId map[string][]jmap.Mailbox) map[string][]jmap.Mailbox {
- sortedByAccountId := make(map[string][]jmap.Mailbox, len(mailboxesByAccountId))
+func sortMailboxesMap(mailboxesByAccountId map[jmap.AccountId][]jmap.Mailbox) map[jmap.AccountId][]jmap.Mailbox {
+ sortedByAccountId := make(map[jmap.AccountId][]jmap.Mailbox, len(mailboxesByAccountId))
for accountId, unsorted := range mailboxesByAccountId {
mailboxes := make([]jmap.Mailbox, len(unsorted))
copy(mailboxes, unsorted)
diff --git a/services/groupware/pkg/groupware/api_objects.go b/services/groupware/pkg/groupware/api_objects.go
index be75e2b177..e377e8cf72 100644
--- a/services/groupware/pkg/groupware/api_objects.go
+++ b/services/groupware/pkg/groupware/api_objects.go
@@ -45,7 +45,7 @@ func (g *Groupware) GetObjects(w http.ResponseWriter, r *http.Request) { //NOSON
if err != nil {
return req.error(accountId, err)
}
- l = l.Str(logAccountId, accountId)
+ l = l.Str(logAccountId, log.SafeString(accountId))
mailboxIds := []string{}
emailIds := []string{}
diff --git a/services/groupware/pkg/groupware/api_quota.go b/services/groupware/pkg/groupware/api_quota.go
index a751a71b87..bac9727b49 100644
--- a/services/groupware/pkg/groupware/api_quota.go
+++ b/services/groupware/pkg/groupware/api_quota.go
@@ -5,6 +5,7 @@ import (
"github.com/opencloud-eu/opencloud/pkg/jmap"
"github.com/opencloud-eu/opencloud/pkg/log"
+ "github.com/opencloud-eu/opencloud/pkg/structs"
)
// Get quota limits.
@@ -13,7 +14,7 @@ import (
//
// Note that there may be multiple Quota objects for different resource types.
func (g *Groupware) GetQuota(w http.ResponseWriter, r *http.Request) {
- getFromMap(Quota, w, r, g, func(accountIds, _ []string, ctx jmap.Context) (jmap.Result[map[string]jmap.QuotaGetResponse], error) {
+ getFromMap(Quota, w, r, g, func(accountIds []jmap.AccountId, _ []string, ctx jmap.Context) (jmap.Result[map[jmap.AccountId]jmap.QuotaGetResponse], error) {
return g.jmap.GetQuotas(accountIds, ctx)
})
}
@@ -33,7 +34,7 @@ func (g *Groupware) GetQuotaForAllAccounts(w http.ResponseWriter, r *http.Reques
if len(accountIds) < 1 {
return req.noopN(accountIds) // user has no accounts
}
- logger := log.From(req.logger.With().Array(logAccountId, log.SafeStringArray(accountIds)))
+ logger := log.From(req.logger.With().Array(logAccountId, log.SafeStringArray(structs.ToStrings(accountIds))))
ctx := req.ctx.WithLogger(logger)
result, jerr := g.jmap.GetQuotas(accountIds, ctx)
@@ -41,7 +42,7 @@ func (g *Groupware) GetQuotaForAllAccounts(w http.ResponseWriter, r *http.Reques
return req.jmapErrorN(accountIds, jerr, result)
}
- body := make(map[string]AccountQuota, len(result.Payload))
+ body := make(map[jmap.AccountId]AccountQuota, len(result.Payload))
for accountId, accountQuotas := range result.Payload {
body[accountId] = AccountQuota{
State: accountQuotas.State,
diff --git a/services/groupware/pkg/groupware/api_tasklists.go b/services/groupware/pkg/groupware/api_tasklists.go
index fee45a857e..096318e069 100644
--- a/services/groupware/pkg/groupware/api_tasklists.go
+++ b/services/groupware/pkg/groupware/api_tasklists.go
@@ -13,7 +13,7 @@ func (g *Groupware) GetTaskLists(w http.ResponseWriter, r *http.Request) {
if !ok {
return resp
}
- var _ string = accountId
+ var _ jmap.AccountId = accountId
var body []jmap.TaskList = AllTaskLists
meta := TaskListsMeta{SessionState: req.session.State}
@@ -28,7 +28,7 @@ func (g *Groupware) GetTaskListById(w http.ResponseWriter, r *http.Request) {
if !ok {
return resp
}
- var _ string = accountId
+ var _ jmap.AccountId = accountId
tasklistId, err := req.PathParam(UriParamTaskListId)
if err != nil {
@@ -52,7 +52,7 @@ func (g *Groupware) GetTasksInTaskList(w http.ResponseWriter, r *http.Request) {
if !ok {
return resp
}
- var _ string = accountId
+ var _ jmap.AccountId = accountId
tasklistId, err := req.PathParam(UriParamTaskListId)
if err != nil {
diff --git a/services/groupware/pkg/groupware/api_vacation.go b/services/groupware/pkg/groupware/api_vacation.go
index 0f8f2c344e..04c58a3974 100644
--- a/services/groupware/pkg/groupware/api_vacation.go
+++ b/services/groupware/pkg/groupware/api_vacation.go
@@ -13,7 +13,7 @@ import (
//
// The VacationResponse object represents the state of vacation-response-related settings for an account.
func (g *Groupware) GetVacation(w http.ResponseWriter, r *http.Request) {
- get(VacationResponse, w, r, g, func(accountId string, ids []string, ctx jmap.Context) (jmap.Result[jmap.VacationResponseGetResponse], error) {
+ get(VacationResponse, w, r, g, func(accountId jmap.AccountId, ids []string, ctx jmap.Context) (jmap.Result[jmap.VacationResponseGetResponse], error) {
return g.jmap.GetVacationResponse(accountId, ctx)
})
}
@@ -23,7 +23,7 @@ func (g *Groupware) GetVacation(w http.ResponseWriter, r *http.Request) {
// A vacation response sends an automatic reply when a message is delivered to the mail store, informing the original
// sender that their message may not be read for some time.
func (g *Groupware) SetVacation(w http.ResponseWriter, r *http.Request) {
- modify(VacationResponse, w, r, g, func(accountId string, id string, change jmap.VacationResponseChange, ctx jmap.Context) (jmap.Result[jmap.VacationResponse], error) {
+ modify(VacationResponse, w, r, g, func(accountId jmap.AccountId, id string, change jmap.VacationResponseChange, ctx jmap.Context) (jmap.Result[jmap.VacationResponse], error) {
return g.jmap.SetVacationResponse(accountId, change, ctx)
})
}
diff --git a/services/groupware/pkg/groupware/error.go b/services/groupware/pkg/groupware/error.go
index e9de913a92..037e23d738 100644
--- a/services/groupware/pkg/groupware/error.go
+++ b/services/groupware/pkg/groupware/error.go
@@ -750,19 +750,19 @@ func errorResponses(errors ...Error) ErrorResponse {
return ErrorResponse{Errors: errors}
}
-func (r *Request) error(accountId string, err *Error) Response {
+func (r *Request) error(accountId jmap.AccountId, err *Error) Response {
return errorResponse(single(accountId), err, r.session.State, jmap.NoLanguage)
}
-func (r *Request) errorS(accountId string, err *Error, result jmap.ResultMetadata) Response {
+func (r *Request) errorS(accountId jmap.AccountId, err *Error, result jmap.ResultMetadata) Response {
return errorResponse(single(accountId), err, result.GetSessionState(), result.GetLanguage())
}
-func (r *Request) errorN(accountIds []string, err *Error) Response {
+func (r *Request) errorN(accountIds []jmap.AccountId, err *Error) Response {
return errorResponse(accountIds, err, r.session.State, jmap.NoLanguage)
}
-func (r *Request) jmapError(accountId string, err error, result jmap.ResultMetadata) Response {
+func (r *Request) jmapError(accountId jmap.AccountId, err error, result jmap.ResultMetadata) Response {
switch e := err.(type) {
case jmap.Error:
if result != nil {
@@ -779,7 +779,7 @@ func (r *Request) jmapError(accountId string, err error, result jmap.ResultMetad
}
}
-func (r *Request) jmapErrorN(accountIds []string, err error, result jmap.ResultMetadata) Response {
+func (r *Request) jmapErrorN(accountIds []jmap.AccountId, err error, result jmap.ResultMetadata) Response {
switch e := err.(type) {
case jmap.Error:
if result != nil {
diff --git a/services/groupware/pkg/groupware/examples_test.go b/services/groupware/pkg/groupware/examples_test.go
index 0867b6ee2c..d470faf054 100644
--- a/services/groupware/pkg/groupware/examples_test.go
+++ b/services/groupware/pkg/groupware/examples_test.go
@@ -27,8 +27,8 @@ func (e Exemplar) AccountQuota() AccountQuota {
}
}
-func (e Exemplar) AccountQuotaMap() map[string]AccountQuota {
- return map[string]AccountQuota{
+func (e Exemplar) AccountQuotaMap() map[jmap.AccountId]AccountQuota {
+ return map[jmap.AccountId]AccountQuota{
j.AccountId: e.AccountQuota(),
}
}
@@ -148,23 +148,23 @@ func (e Exemplar) ErrorResponse() ErrorResponse {
}
}
-func (e Exemplar) MailboxesByAccountId() (map[string][]jmap.Mailbox, string) {
+func (e Exemplar) MailboxesByAccountId() (map[jmap.AccountId][]jmap.Mailbox, string) {
j := jmap.ExemplarInstance
- return map[string][]jmap.Mailbox{
+ return map[jmap.AccountId][]jmap.Mailbox{
j.AccountId: j.Mailboxes(),
}, "All mailboxes for all accounts, without a role filter"
}
-func (e Exemplar) MailboxesByAccountIdFilteredOnInboxRole() (map[string][]jmap.Mailbox, string, string) {
+func (e Exemplar) MailboxesByAccountIdFilteredOnInboxRole() (map[jmap.AccountId][]jmap.Mailbox, string, string) {
j := jmap.ExemplarInstance
- return map[string][]jmap.Mailbox{
+ return map[jmap.AccountId][]jmap.Mailbox{
j.AccountId: structs.Filter(j.Mailboxes(), func(m jmap.Mailbox) bool { return m.Role == jmap.JmapMailboxRoleInbox }),
}, "All mailboxes for all accounts, filtered on the 'inbox' role", "inboxrole"
}
-func (e Exemplar) MailboxRolesByAccounts() (map[string][]string, string, string, string) {
+func (e Exemplar) MailboxRolesByAccounts() (map[jmap.AccountId][]string, string, string, string) {
j := jmap.ExemplarInstance
- return map[string][]string{
+ return map[jmap.AccountId][]string{
j.AccountId: jmap.JmapMailboxRoles,
j.SharedAccountId: jmap.JmapMailboxRoles,
}, "Roles of the Mailboxes of each Account", "", "mailboxrolesbyaccount"
diff --git a/services/groupware/pkg/groupware/framework.go b/services/groupware/pkg/groupware/framework.go
index 27074171fc..543268f750 100644
--- a/services/groupware/pkg/groupware/framework.go
+++ b/services/groupware/pkg/groupware/framework.go
@@ -25,6 +25,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/config"
"github.com/opencloud-eu/opencloud/services/groupware/pkg/metrics"
@@ -778,10 +779,9 @@ func (g *Groupware) sendResponse(w http.ResponseWriter, r *http.Request, respons
case 0:
break
case 1:
- w.Header().Add(AccountIdResponseHeader, response.accountIds[0])
+ w.Header().Add(AccountIdResponseHeader, string(response.accountIds[0]))
default:
- c := make([]string, len(response.accountIds))
- copy(c, response.accountIds)
+ c := structs.Map(response.accountIds, func(a jmap.AccountId) string { return string(a) })
slices.Sort(c)
value := strings.Join(c, ",")
w.Header().Add(AccountIdsResponseHeader, value)
@@ -890,12 +890,12 @@ func single[S any](s S) []S {
}
type QueryParamsSupplier interface {
- ForSupplier(supplierId string, accountId string) (jmap.QueryParams, bool, error)
- ForAccountId(accountId string) (jmap.QueryParams, bool, error)
+ ForSupplier(supplierId SupplierId, accountId jmap.AccountId) (jmap.QueryParams, bool, error)
+ ForAccountId(accountId jmap.AccountId) (jmap.QueryParams, bool, error)
}
-func mapQueryParams(supplierId string, accountIds []string, qps QueryParamsSupplier) (map[string]jmap.QueryParams, error) {
- m := map[string]jmap.QueryParams{}
+func mapQueryParams(supplierId SupplierId, accountIds []jmap.AccountId, qps QueryParamsSupplier) (map[jmap.AccountId]jmap.QueryParams, error) {
+ m := map[jmap.AccountId]jmap.QueryParams{}
if supplierId == "" {
for _, accountId := range accountIds {
if q, ok, err := qps.ForAccountId(accountId); err != nil {
@@ -920,11 +920,11 @@ type ErrorQueryParamsSupplier struct {
err error
}
-func (s ErrorQueryParamsSupplier) ForSupplier(supplierId string, accountId string) (jmap.QueryParams, bool, error) {
+func (s ErrorQueryParamsSupplier) ForSupplier(supplierId SupplierId, accountId jmap.AccountId) (jmap.QueryParams, bool, error) {
return jmap.NullQueryParams, false, s.err
}
-func (s ErrorQueryParamsSupplier) ForAccountId(accountId string) (jmap.QueryParams, bool, error) {
+func (s ErrorQueryParamsSupplier) ForAccountId(accountId jmap.AccountId) (jmap.QueryParams, bool, error) {
return jmap.NullQueryParams, false, s.err
}
@@ -933,11 +933,11 @@ var _ QueryParamsSupplier = ErrorQueryParamsSupplier{}
type FirstQueryParamsSupplier struct {
}
-func (s FirstQueryParamsSupplier) ForSupplier(supplierId string, accountId string) (jmap.QueryParams, bool, error) {
+func (s FirstQueryParamsSupplier) ForSupplier(supplierId SupplierId, accountId jmap.AccountId) (jmap.QueryParams, bool, error) {
return jmap.NullQueryParams, true, nil
}
-func (s FirstQueryParamsSupplier) ForAccountId(accountId string) (jmap.QueryParams, bool, error) {
+func (s FirstQueryParamsSupplier) ForAccountId(accountId jmap.AccountId) (jmap.QueryParams, bool, error) {
return jmap.NullQueryParams, true, nil
}
@@ -947,21 +947,21 @@ type StaticQueryParamsSupplier struct {
qp jmap.QueryParams
}
-func (s StaticQueryParamsSupplier) ForSupplier(supplierId string, accountId string) (jmap.QueryParams, bool, error) {
+func (s StaticQueryParamsSupplier) ForSupplier(supplierId SupplierId, accountId jmap.AccountId) (jmap.QueryParams, bool, error) {
return s.qp, true, nil
}
-func (s StaticQueryParamsSupplier) ForAccountId(accountId string) (jmap.QueryParams, bool, error) {
+func (s StaticQueryParamsSupplier) ForAccountId(accountId jmap.AccountId) (jmap.QueryParams, bool, error) {
return s.qp, true, nil
}
var _ QueryParamsSupplier = StaticQueryParamsSupplier{}
type MultiSupplierQueryParamsSupplier struct {
- m map[string]map[string]jmap.QueryParams
+ m map[SupplierId]map[jmap.AccountId]jmap.QueryParams
}
-func (s MultiSupplierQueryParamsSupplier) ForSupplier(supplierId string, accountId string) (jmap.QueryParams, bool, error) {
+func (s MultiSupplierQueryParamsSupplier) ForSupplier(supplierId SupplierId, accountId jmap.AccountId) (jmap.QueryParams, bool, error) {
if a, ok := s.m[supplierId]; ok {
if b, ok := a[accountId]; ok {
return b, true, nil
@@ -970,7 +970,7 @@ func (s MultiSupplierQueryParamsSupplier) ForSupplier(supplierId string, account
return jmap.NullQueryParams, false, nil
}
-func (s MultiSupplierQueryParamsSupplier) ForAccountId(accountId string) (jmap.QueryParams, bool, error) {
+func (s MultiSupplierQueryParamsSupplier) ForAccountId(accountId jmap.AccountId) (jmap.QueryParams, bool, error) {
switch len(s.m) {
case 1:
for _, v := range s.m {
@@ -989,14 +989,14 @@ func (s MultiSupplierQueryParamsSupplier) ForAccountId(accountId string) (jmap.Q
var _ QueryParamsSupplier = MultiSupplierQueryParamsSupplier{}
type SingleSupplierQueryParamsSupplier struct {
- m map[string]jmap.QueryParams
+ m map[jmap.AccountId]jmap.QueryParams
}
-func (s SingleSupplierQueryParamsSupplier) ForSupplier(supplierId string, accountId string) (jmap.QueryParams, bool, error) {
+func (s SingleSupplierQueryParamsSupplier) ForSupplier(supplierId SupplierId, accountId jmap.AccountId) (jmap.QueryParams, bool, error) {
return jmap.NullQueryParams, false, fmt.Errorf("unable to provide for supplier with single supplier token")
}
-func (s SingleSupplierQueryParamsSupplier) ForAccountId(accountId string) (jmap.QueryParams, bool, error) {
+func (s SingleSupplierQueryParamsSupplier) ForAccountId(accountId jmap.AccountId) (jmap.QueryParams, bool, error) {
if b, ok := s.m[accountId]; ok {
return b, true, nil
}
diff --git a/services/groupware/pkg/groupware/mock_tasks.go b/services/groupware/pkg/groupware/mock_tasks.go
index 5b91ce0028..d7e79f600c 100644
--- a/services/groupware/pkg/groupware/mock_tasks.go
+++ b/services/groupware/pkg/groupware/mock_tasks.go
@@ -26,8 +26,8 @@ var TL1 = jmap.TaskList{
WorkflowStatuses: []string{
"new", "todo", "in-progress", "done",
},
- ShareWith: map[string]jmap.TaskRights{
- "eefeeb4p": {
+ ShareWith: map[jmap.PrincipalId]jmap.TaskRights{
+ jmap.PrincipalId("eefeeb4p"): {
MayReadItems: true,
MayWriteAll: false,
MayWriteOwn: true,
diff --git a/services/groupware/pkg/groupware/next.go b/services/groupware/pkg/groupware/next.go
index c03b4cfcce..5eb3635904 100644
--- a/services/groupware/pkg/groupware/next.go
+++ b/services/groupware/pkg/groupware/next.go
@@ -13,7 +13,7 @@ type NextToken string
const NoNextToken = NextToken("")
-func nextSingle(m map[string]jmap.QueryParams) (NextToken, error) {
+func nextSingle(m map[jmap.AccountId]jmap.QueryParams) (NextToken, error) {
if b, err := json.Marshal(m); err != nil {
return NoNextToken, err
} else {
@@ -21,7 +21,7 @@ func nextSingle(m map[string]jmap.QueryParams) (NextToken, error) {
}
}
-func nextMulti(m map[string]map[string]jmap.QueryParams) (NextToken, error) {
+func nextMulti(m map[SupplierId]map[jmap.AccountId]jmap.QueryParams) (NextToken, error) {
if b, err := json.Marshal(m); err != nil {
return NoNextToken, err
} else {
@@ -42,7 +42,7 @@ func unnext(n NextToken) (QueryParamsSupplier, error) {
if b, err := DecodeBytesFromBase62(payload); err != nil {
return ErrorQueryParamsSupplier{err: err}, err
} else {
- var m map[string]jmap.QueryParams
+ var m map[jmap.AccountId]jmap.QueryParams
if err := json.Unmarshal(b, &m); err != nil {
return ErrorQueryParamsSupplier{err: err}, err
} else {
@@ -54,7 +54,7 @@ func unnext(n NextToken) (QueryParamsSupplier, error) {
if b, err := DecodeBytesFromBase62(payload); err != nil {
return ErrorQueryParamsSupplier{err: err}, err
} else {
- var m map[string]map[string]jmap.QueryParams
+ var m map[SupplierId]map[jmap.AccountId]jmap.QueryParams
if err := json.Unmarshal(b, &m); err != nil {
return ErrorQueryParamsSupplier{err: err}, err
} else {
@@ -68,11 +68,11 @@ func unnext(n NextToken) (QueryParamsSupplier, error) {
}
func curryNoNextMapQuery[SRES jmap.SearchResults[T], T jmap.Idable, FILTER any, COMP any](
- f func(accountIds map[string]jmap.QueryParams, limit *uint, filter FILTER, sortBy []COMP, calculateTotal bool, ctx jmap.Context) (jmap.Result[map[string]SRES], error),
+ f func(accountIds map[jmap.AccountId]jmap.QueryParams, limit *uint, filter FILTER, sortBy []COMP, calculateTotal bool, ctx jmap.Context) (jmap.Result[map[jmap.AccountId]SRES], error),
sorter func(a, b T) int,
searchResultCtor func(canCalculateChanges jmap.ChangeCalculation, position *uint, limit *uint, total *uint, results []T) SRES,
-) func(req Request, accountIds []string, qps QueryParamsSupplier, limit *uint, filter FILTER, sortBy []COMP, ctx jmap.Context) (jmap.Result[SRES], NextToken, error) {
- return func(_ Request, accountIds []string, qps QueryParamsSupplier, limit *uint, filter FILTER, sortBy []COMP, ctx jmap.Context) (jmap.Result[SRES], NextToken, error) { //NOSONAR
+) func(req Request, accountIds []jmap.AccountId, qps QueryParamsSupplier, limit *uint, filter FILTER, sortBy []COMP, ctx jmap.Context) (jmap.Result[SRES], NextToken, error) {
+ return func(_ Request, accountIds []jmap.AccountId, qps QueryParamsSupplier, limit *uint, filter FILTER, sortBy []COMP, ctx jmap.Context) (jmap.Result[SRES], NextToken, error) { //NOSONAR
if m, err := mapQueryParams("", accountIds, qps); err != nil {
return jmap.ZeroResult[SRES](), NoNextToken, err
} else {
@@ -80,7 +80,7 @@ func curryNoNextMapQuery[SRES jmap.SearchResults[T], T jmap.Idable, FILTER any,
if err != nil {
return jmap.ZeroResult[SRES](), NoNextToken, err
} else {
- singleAccountId := ""
+ var singleAccountId jmap.AccountId = ""
// TODO what about requests with zero accountIds, can these even happen at all?
if len(accountIds) == 1 {
// optimization: no need to combine the results of several accounts if the query was
@@ -91,14 +91,14 @@ func curryNoNextMapQuery[SRES jmap.SearchResults[T], T jmap.Idable, FILTER any,
// all accounts: let's first calculate the number of results we have for each account
totalByAccount := structs.MapValues(result.Payload, func(a SRES) int { return len(a.GetResults()) })
// and let's now pick out the accounts that do have results
- accountsWithResults := structs.FilterKeys(totalByAccount, func(_ string, total int) bool { return total > 0 })
+ accountsWithResults := structs.FilterKeys(totalByAccount, func(_ jmap.AccountId, total int) bool { return total > 0 })
if len(accountsWithResults) == 1 {
singleAccountId = accountsWithResults[0]
}
// TODO what if we don't have any results at all? (accountsWithResults == 0)
}
if singleAccountId != "" {
- r, err := jmap.RefineResultPayload(result, func(a map[string]SRES) (SRES, bool, error) {
+ r, err := jmap.RefineResultPayload(result, func(a map[jmap.AccountId]SRES) (SRES, bool, error) {
r, ok := a[accountIds[0]]
return r, ok, nil
})
@@ -113,10 +113,10 @@ func curryNoNextMapQuery[SRES jmap.SearchResults[T], T jmap.Idable, FILTER any,
}
func flattenMultipleAccounts[SRES jmap.SearchResults[T], T jmap.Idable](
- accountIds []string,
+ accountIds []jmap.AccountId,
qps QueryParamsSupplier,
limit *uint,
- result jmap.Result[map[string]SRES],
+ result jmap.Result[map[jmap.AccountId]SRES],
sorter func(a, b T) int,
searchResultCtor func(canCalculateChanges jmap.ChangeCalculation, position *uint, limit *uint, total *uint, results []T) SRES,
) (jmap.Result[SRES], NextToken, error) {
@@ -133,7 +133,7 @@ func flattenMultipleAccounts[SRES jmap.SearchResults[T], T jmap.Idable](
cc := true
total := uint(0)
- lastByAccountId := map[string]string{}
+ lastByAccountId := map[jmap.AccountId]string{}
for accountId, searchResult := range result.Payload {
if !searchResult.GetCanCalculateChanges() {
cc = false
@@ -150,7 +150,7 @@ func flattenMultipleAccounts[SRES jmap.SearchResults[T], T jmap.Idable](
// 4. we need to build the NextToken by taking the ID of the last item
// we kept after shrinking, but separately for each accountId
- n := map[string]jmap.QueryParams{}
+ n := map[jmap.AccountId]jmap.QueryParams{}
for accountId, lastId := range lastByAccountId {
n[accountId] = jmap.QueryParams{Anchor: lastId, AnchorOffset: ptr(1)}
}
@@ -160,7 +160,7 @@ func flattenMultipleAccounts[SRES jmap.SearchResults[T], T jmap.Idable](
if t, err := nextSingle(n); err != nil {
return jmap.ZeroResult[SRES](), NoNextToken, err
} else {
- if r, err := jmap.RefineResultPayload(result, func(a map[string]SRES) (SRES, bool, error) {
+ if r, err := jmap.RefineResultPayload(result, func(a map[jmap.AccountId]SRES) (SRES, bool, error) {
return searchResultCtor(jmap.ChangeCalculation(cc), nil, limit, &total, all), true, nil
}); err != nil {
return jmap.ZeroResult[SRES](), NoNextToken, err
@@ -184,7 +184,7 @@ func flattenMultipleAccounts[SRES jmap.SearchResults[T], T jmap.Idable](
// no need to compute a NextToken since there was no limit,
// which means that this Result contains all the elements,
// and thus there is no "next" to query for
- if r, err := jmap.RefineResultPayload(result, func(a map[string]SRES) (SRES, bool, error) {
+ if r, err := jmap.RefineResultPayload(result, func(a map[jmap.AccountId]SRES) (SRES, bool, error) {
return searchResultCtor(jmap.ChangeCalculation(cc), nil, limit, &total, all), true, nil
}); err != nil {
return jmap.ZeroResult[SRES](), NoNextToken, err
diff --git a/services/groupware/pkg/groupware/objtypes.go b/services/groupware/pkg/groupware/objtypes.go
index c52a61032a..8a51ad64ed 100644
--- a/services/groupware/pkg/groupware/objtypes.go
+++ b/services/groupware/pkg/groupware/objtypes.go
@@ -10,7 +10,7 @@ type ObjectType[T jmap.Foo, CH jmap.Change, CHS jmap.Changes[T]] struct {
responseType ResponseObjectType
uriParamName string
containerUriParamName string
- accountFunc func(r *Request) (bool, string, Response)
+ accountFunc func(r *Request) (bool, jmap.AccountId, Response)
failedToDeleteError GroupwareError
}
diff --git a/services/groupware/pkg/groupware/request.go b/services/groupware/pkg/groupware/request.go
index 3881c12c75..950c561c0b 100644
--- a/services/groupware/pkg/groupware/request.go
+++ b/services/groupware/pkg/groupware/request.go
@@ -45,8 +45,8 @@ type Request struct {
ctx jmap.Context
}
-func isDefaultAccountId(accountId string) bool {
- return slices.Contains(defaultAccountIds, accountId)
+func isDefaultAccountId(accountId jmap.AccountId) bool {
+ return slices.Contains(defaultAccountIds, string(accountId))
}
func (r *Request) push(typ string, event any) {
@@ -129,13 +129,13 @@ func (r *Request) PathListParamDoc(name string, _ string) ([]string, *Error) {
return strings.Split(value, ","), nil
}
-func (r *Request) AllAccountIds() []string {
+func (r *Request) AllAccountIds() []jmap.AccountId {
// 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)
+func (r *Request) GetAccountIdWithoutFallback() (jmap.AccountId, *Error) {
+ accountId := jmap.AccountId(chi.URLParam(r.r, UriParamAccountId))
if accountId == "" || isDefaultAccountId(accountId) {
r.logger.Error().Err(errNoPrimaryAccountFallback).Msg("failed to determine the accountId")
return "", apiError(r.errorId(), ErrorNonExistingAccount,
@@ -146,8 +146,8 @@ func (r *Request) GetAccountIdWithoutFallback() (string, *Error) {
return accountId, nil
}
-func (r *Request) getAccountId(fallback string, err error) (string, *Error) {
- accountId := chi.URLParam(r.r, UriParamAccountId)
+func (r *Request) getAccountId(fallback jmap.AccountId, err error) (jmap.AccountId, *Error) {
+ accountId := jmap.AccountId(chi.URLParam(r.r, UriParamAccountId))
if accountId == "" || isDefaultAccountId(accountId) {
accountId = fallback
}
@@ -161,45 +161,45 @@ func (r *Request) getAccountId(fallback string, err error) (string, *Error) {
return accountId, nil
}
-func (r *Request) GetAccountIdForMail() (string, *Error) {
+func (r *Request) GetAccountIdForMail() (jmap.AccountId, *Error) {
return r.getAccountId(r.session.PrimaryAccounts.Mail, errNoPrimaryAccountForMail)
}
-func (r *Request) GetAccountIdForBlob() (string, *Error) {
+func (r *Request) GetAccountIdForBlob() (jmap.AccountId, *Error) {
return r.getAccountId(r.session.PrimaryAccounts.Blob, errNoPrimaryAccountForBlob)
}
-func (r *Request) GetAccountIdForVacationResponse() (string, *Error) {
+func (r *Request) GetAccountIdForVacationResponse() (jmap.AccountId, *Error) {
return r.getAccountId(r.session.PrimaryAccounts.VacationResponse, errNoPrimaryAccountForVacationResponse)
}
-func (r *Request) GetAccountIdForQuota() (string, *Error) {
+func (r *Request) GetAccountIdForQuota() (jmap.AccountId, *Error) {
return r.getAccountId(r.session.PrimaryAccounts.Quota, errNoPrimaryAccountForQuota)
}
-func (r *Request) GetAccountIdForSubmission() (string, *Error) {
+func (r *Request) GetAccountIdForSubmission() (jmap.AccountId, *Error) {
return r.getAccountId(r.session.PrimaryAccounts.Blob, errNoPrimaryAccountForSubmission)
}
-func (r *Request) GetAccountIdForTask() (string, *Error) {
+func (r *Request) GetAccountIdForTask() (jmap.AccountId, *Error) {
// TODO we don't have these yet, not implemented in Stalwart
// return r.getAccountId(r.session.PrimaryAccounts.Task, errNoPrimaryAccountForTask)
return r.GetAccountIdForMail()
}
-func (r *Request) GetAccountIdForCalendar() (string, *Error) {
+func (r *Request) GetAccountIdForCalendar() (jmap.AccountId, *Error) {
// TODO we don't have these yet, not implemented in Stalwart
// return r.getAccountId(r.session.PrimaryAccounts.Calendar, errNoPrimaryAccountForCalendar)
return r.GetAccountIdForMail()
}
-func (r *Request) GetAccountIdForContact() (string, *Error) {
+func (r *Request) GetAccountIdForContact() (jmap.AccountId, *Error) {
// TODO we don't have these yet, not implemented in Stalwart
// return r.getAccountId(r.session.PrimaryAccounts.Contact, errNoPrimaryAccountForContact)
return r.GetAccountIdForMail()
}
-func (r *Request) GetAccountForMail() (string, jmap.Account, *Error) {
+func (r *Request) GetAccountForMail() (jmap.AccountId, jmap.Account, *Error) {
accountId, err := r.GetAccountIdForMail()
if err != nil {
return "", jmap.Account{}, err
@@ -210,7 +210,7 @@ func (r *Request) GetAccountForMail() (string, jmap.Account, *Error) {
r.logger.Debug().Msgf("failed to find account '%v'", accountId)
// TODO metric for inexistent accounts
return accountId, jmap.Account{}, apiError(r.errorId(), ErrorNonExistingAccount,
- withDetail(fmt.Sprintf("The account '%v' does not exist", log.SafeString(accountId))),
+ withDetail(fmt.Sprintf("The account '%v' does not exist", log.SafeString(string(accountId)))),
withSource(&ErrorSource{Parameter: UriParamAccountId}),
)
}
@@ -223,11 +223,11 @@ func (r *Request) parameterError(param string, detail string) *Error {
withSource(&ErrorSource{Parameter: param}))
}
-func (r *Request) parameterErrorResponse(accountId string, param string, detail string) Response {
+func (r *Request) parameterErrorResponse(accountId jmap.AccountId, param string, detail string) Response {
return r.error(accountId, r.parameterError(param, detail))
}
-func (r *Request) parameterErrorResponseN(accountIds []string, param string, detail string) Response {
+func (r *Request) parameterErrorResponseN(accountIds []jmap.AccountId, param string, detail string) Response {
return r.errorN(accountIds, r.parameterError(param, detail))
}
@@ -239,7 +239,7 @@ func toSupportedQueryParams(params ...string) supportedQueryParams {
var noSupportedQueryParams supportedQueryParams = toSupportedQueryParams()
-func (r *Request) unsupportedQueryParams(accountIds []string, allowed supportedQueryParams) (bool, Response) {
+func (r *Request) unsupportedQueryParams(accountIds []jmap.AccountId, allowed supportedQueryParams) (bool, Response) {
q := r.r.URL.Query()
for n := range q {
if _, ok := allowed[n]; !ok {
@@ -470,14 +470,14 @@ func (r *Request) observeJmapError(jerr jmap.Error) jmap.Error {
return jerr
}
-func (r *Request) needBlob(accountId string) (bool, Response) {
+func (r *Request) needBlob(accountId jmap.AccountId) (bool, Response) {
if r.session.Capabilities.Blob == nil {
return false, errorResponse(single(accountId), r.apiError(&ErrorMissingBlobSessionCapability), r.session.State, jmap.NoLanguage)
}
return true, Response{}
}
-func (r *Request) needBlobForAccount(accountId string) (bool, Response) {
+func (r *Request) needBlobForAccount(accountId jmap.AccountId) (bool, Response) {
if ok, resp := r.needBlob(accountId); !ok {
return ok, resp
}
@@ -491,7 +491,7 @@ func (r *Request) needBlobForAccount(accountId string) (bool, Response) {
return true, Response{}
}
-func (r *Request) needBloblWithAccount() (bool, string, Response) {
+func (r *Request) needBloblWithAccount() (bool, jmap.AccountId, Response) {
accountId, err := r.GetAccountIdForBlob()
if err != nil {
return false, "", r.error(accountId, err)
@@ -502,14 +502,14 @@ func (r *Request) needBloblWithAccount() (bool, string, Response) {
return true, accountId, Response{}
}
-func (r *Request) needMail(accountId string) (bool, Response) {
+func (r *Request) needMail(accountId jmap.AccountId) (bool, Response) {
if r.session.Capabilities.Mail == nil {
return false, errorResponse(single(accountId), r.apiError(&ErrorMissingMailsSessionCapability), r.session.State, jmap.NoLanguage)
}
return true, Response{}
}
-func (r *Request) needMailForAccount(accountId string) (bool, Response) {
+func (r *Request) needMailForAccount(accountId jmap.AccountId) (bool, Response) {
if ok, resp := r.needMail(accountId); !ok {
return ok, resp
}
@@ -523,7 +523,7 @@ func (r *Request) needMailForAccount(accountId string) (bool, Response) {
return true, Response{}
}
-func (r *Request) needMailWithAccount() (bool, string, Response) {
+func (r *Request) needMailWithAccount() (bool, jmap.AccountId, Response) {
accountId, err := r.GetAccountIdForMail()
if err != nil {
return false, "", r.error(accountId, err)
@@ -534,7 +534,7 @@ func (r *Request) needMailWithAccount() (bool, string, Response) {
return true, accountId, Response{}
}
-func (r *Request) needTask(accountId string) (bool, Response) {
+func (r *Request) needTask(accountId jmap.AccountId) (bool, Response) {
if !IgnoreSessionCapabilityChecksForTasks {
if r.session.Capabilities.Tasks == nil {
return false, errorResponse(single(accountId), r.apiError(&ErrorMissingTasksSessionCapability), r.session.State, jmap.Language(r.language()))
@@ -543,7 +543,7 @@ func (r *Request) needTask(accountId string) (bool, Response) {
return true, Response{}
}
-func (r *Request) needTaskForAccount(accountId string) (bool, Response) {
+func (r *Request) needTaskForAccount(accountId jmap.AccountId) (bool, Response) {
if ok, resp := r.needTask(accountId); !ok {
return ok, resp
}
@@ -557,7 +557,7 @@ func (r *Request) needTaskForAccount(accountId string) (bool, Response) {
return true, Response{}
}
-func (r *Request) needTaskWithAccount() (bool, string, Response) {
+func (r *Request) needTaskWithAccount() (bool, jmap.AccountId, Response) {
accountId, err := r.GetAccountIdForTask()
if err != nil {
return false, "", r.error(accountId, err)
@@ -568,14 +568,14 @@ func (r *Request) needTaskWithAccount() (bool, string, Response) {
return true, accountId, Response{}
}
-func (r *Request) needCalendar(accountId string) (bool, Response) {
+func (r *Request) needCalendar(accountId jmap.AccountId) (bool, Response) {
if r.session.Capabilities.Calendars == nil {
return false, errorResponse(single(accountId), r.apiError(&ErrorMissingCalendarsSessionCapability), r.session.State, jmap.NoLanguage)
}
return true, Response{}
}
-func (r *Request) needCalendarForAccount(accountId string) (bool, Response) {
+func (r *Request) needCalendarForAccount(accountId jmap.AccountId) (bool, Response) {
if ok, resp := r.needCalendar(accountId); !ok {
return ok, resp
}
@@ -589,7 +589,7 @@ func (r *Request) needCalendarForAccount(accountId string) (bool, Response) {
return true, Response{}
}
-func (r *Request) needCalendarWithAccount() (bool, string, Response) {
+func (r *Request) needCalendarWithAccount() (bool, jmap.AccountId, Response) {
accountId, err := r.GetAccountIdForCalendar()
if err != nil {
return false, "", r.error(accountId, err)
@@ -600,14 +600,14 @@ func (r *Request) needCalendarWithAccount() (bool, string, Response) {
return true, accountId, Response{}
}
-func (r *Request) needContact(accountId string) (bool, Response) {
+func (r *Request) needContact(accountId jmap.AccountId) (bool, Response) {
if r.session.Capabilities.Contacts == nil {
return false, errorResponse(single(accountId), r.apiError(&ErrorMissingContactsSessionCapability), r.session.State, jmap.NoLanguage)
}
return true, Response{}
}
-func (r *Request) needContactForAccount(accountId string) (bool, Response) {
+func (r *Request) needContactForAccount(accountId jmap.AccountId) (bool, Response) {
if ok, resp := r.needContact(accountId); !ok {
return ok, resp
}
@@ -621,7 +621,7 @@ func (r *Request) needContactForAccount(accountId string) (bool, Response) {
return true, Response{}
}
-func (r *Request) needContactWithAccount() (bool, string, Response) {
+func (r *Request) needContactWithAccount() (bool, jmap.AccountId, Response) {
accountId, err := r.GetAccountIdForContact()
if err != nil {
return false, "", r.error(accountId, err)
@@ -632,14 +632,14 @@ func (r *Request) needContactWithAccount() (bool, string, Response) {
return true, accountId, Response{}
}
-func (r *Request) needQuota(accountId string) (bool, Response) {
+func (r *Request) needQuota(accountId jmap.AccountId) (bool, Response) {
if r.session.Capabilities.Quota == nil {
return false, errorResponse(single(accountId), r.apiError(&ErrorMissingQuotaSessionCapability), r.session.State, jmap.NoLanguage)
}
return true, Response{}
}
-func (r *Request) needQuotaForAccount(accountId string) (bool, Response) {
+func (r *Request) needQuotaForAccount(accountId jmap.AccountId) (bool, Response) {
if ok, resp := r.needQuota(accountId); !ok {
return ok, resp
}
@@ -653,7 +653,7 @@ func (r *Request) needQuotaForAccount(accountId string) (bool, Response) {
return true, Response{}
}
-func (r *Request) needQuotaWithAccount() (bool, string, Response) {
+func (r *Request) needQuotaWithAccount() (bool, jmap.AccountId, Response) {
accountId, err := r.GetAccountIdForQuota()
if err != nil {
return false, "", r.error(accountId, err)
@@ -707,3 +707,7 @@ func (r *Request) parseSort(s string, props []string) ([]SortCrit, *Error) {
func toState(s string) jmap.State {
return jmap.State(s)
}
+
+func toAccountIdState(accountId string, state string) (jmap.AccountId, jmap.State) {
+ return jmap.AccountId(accountId), jmap.State(state)
+}
diff --git a/services/groupware/pkg/groupware/response.go b/services/groupware/pkg/groupware/response.go
index 196c2d19c3..973650998a 100644
--- a/services/groupware/pkg/groupware/response.go
+++ b/services/groupware/pkg/groupware/response.go
@@ -32,13 +32,13 @@ type Response struct {
err *Error
etag jmap.State
objectType ResponseObjectType
- accountIds []string
+ accountIds []jmap.AccountId
sessionState jmap.SessionState
contentLanguage jmap.Language
next NextToken
}
-func errorResponse(accountIds []string, err *Error, sessionState jmap.SessionState, contentLanguage jmap.Language) Response {
+func errorResponse(accountIds []jmap.AccountId, err *Error, sessionState jmap.SessionState, contentLanguage jmap.Language) Response {
return Response{
accountIds: accountIds,
body: nil,
@@ -50,7 +50,7 @@ func errorResponse(accountIds []string, err *Error, sessionState jmap.SessionSta
}
}
-func response(accountIds []string, body any, sessionState jmap.SessionState, contentLanguage jmap.Language) Response {
+func response(accountIds []jmap.AccountId, body any, sessionState jmap.SessionState, contentLanguage jmap.Language) Response {
return Response{
accountIds: accountIds,
body: body,
@@ -62,11 +62,11 @@ func response(accountIds []string, body any, sessionState jmap.SessionState, con
}
}
-func (r *Request) respondWithoutStatus(accountId string, body any) Response {
+func (r *Request) respondWithoutStatus(accountId jmap.AccountId, body any) Response {
return response(single(accountId), body, r.session.State, jmap.Language(r.language()))
}
-func etaggedResponse(accountIds []string, body any, sessionState jmap.SessionState, objectType ResponseObjectType, etag jmap.State, contentLanguage jmap.Language) Response {
+func etaggedResponse(accountIds []jmap.AccountId, body any, sessionState jmap.SessionState, objectType ResponseObjectType, etag jmap.State, contentLanguage jmap.Language) Response {
return Response{
accountIds: accountIds,
body: body,
@@ -79,15 +79,15 @@ func etaggedResponse(accountIds []string, body any, sessionState jmap.SessionSta
}
}
-func (r *Request) respond(accountId string, body any, objectType ResponseObjectType, result jmap.ResultMetadata) Response {
+func (r *Request) respond(accountId jmap.AccountId, body any, objectType ResponseObjectType, result jmap.ResultMetadata) Response {
return etaggedResponse(single(accountId), body, result.GetSessionState(), objectType, result.GetState(), result.GetLanguage())
}
-func (r *Request) respondN(accountIds []string, body any, objectType ResponseObjectType, result jmap.ResultMetadata) Response {
+func (r *Request) respondN(accountIds []jmap.AccountId, body any, objectType ResponseObjectType, result jmap.ResultMetadata) Response {
return etaggedResponse(accountIds, body, result.GetSessionState(), objectType, result.GetState(), result.GetLanguage())
}
-func etaggedNextResponse(accountIds []string, body any, sessionState jmap.SessionState, objectType ResponseObjectType, etag jmap.State, contentLanguage jmap.Language, next NextToken) Response {
+func etaggedNextResponse(accountIds []jmap.AccountId, body any, sessionState jmap.SessionState, objectType ResponseObjectType, etag jmap.State, contentLanguage jmap.Language, next NextToken) Response {
return Response{
accountIds: accountIds,
body: body,
@@ -100,7 +100,7 @@ func etaggedNextResponse(accountIds []string, body any, sessionState jmap.Sessio
}
}
-func (r *Request) respondNext(accountId string, body any, objectType ResponseObjectType, result jmap.ResultMetadata, next NextToken) Response {
+func (r *Request) respondNext(accountId jmap.AccountId, body any, objectType ResponseObjectType, result jmap.ResultMetadata, next NextToken) Response {
return etaggedNextResponse(single(accountId), body, result.GetSessionState(), objectType, result.GetState(), result.GetLanguage(), next)
}
@@ -117,7 +117,7 @@ func etagOnlyResponse(body any, etag jmap.State, objectType ResponseObjectType,
}
*/
-func noContentResponse(accountIds []string, sessionState jmap.SessionState) Response {
+func noContentResponse(accountIds []jmap.AccountId, sessionState jmap.SessionState) Response {
return Response{
accountIds: accountIds,
body: nil,
@@ -129,15 +129,15 @@ func noContentResponse(accountIds []string, sessionState jmap.SessionState) Resp
}
}
-func (r *Request) noop(accountId string) Response {
+func (r *Request) noop(accountId jmap.AccountId) Response {
return noContentResponse(single(accountId), r.session.State)
}
-func (r *Request) noopN(accountIds []string) Response {
+func (r *Request) noopN(accountIds []jmap.AccountId) Response {
return noContentResponse(accountIds, r.session.State)
}
-func noContentResponseWithEtag(accountIds []string, sessionState jmap.SessionState, objectType ResponseObjectType, etag jmap.State) Response {
+func noContentResponseWithEtag(accountIds []jmap.AccountId, sessionState jmap.SessionState, objectType ResponseObjectType, etag jmap.State) Response {
return Response{
accountIds: accountIds,
body: nil,
@@ -150,7 +150,7 @@ func noContentResponseWithEtag(accountIds []string, sessionState jmap.SessionSta
}
}
-func (r *Request) noContent(accountId string, objectType ResponseObjectType, result jmap.ResultMetadata) Response {
+func (r *Request) noContent(accountId jmap.AccountId, objectType ResponseObjectType, result jmap.ResultMetadata) Response {
return noContentResponseWithEtag(single(accountId), result.GetSessionState(), objectType, result.GetState())
}
@@ -178,7 +178,7 @@ func timeoutResponse(sessionState jmap.SessionState) Response {
}
*/
-func notFoundResponse(accountIds []string, sessionState jmap.SessionState, objectType ResponseObjectType, etag jmap.State) Response {
+func notFoundResponse(accountIds []jmap.AccountId, sessionState jmap.SessionState, objectType ResponseObjectType, etag jmap.State) Response {
return Response{
accountIds: accountIds,
body: nil,
@@ -191,11 +191,11 @@ func notFoundResponse(accountIds []string, sessionState jmap.SessionState, objec
}
}
-func (r *Request) notFound(accountId string, objectType ResponseObjectType, result jmap.ResultMetadata) Response {
+func (r *Request) notFound(accountId jmap.AccountId, objectType ResponseObjectType, result jmap.ResultMetadata) Response {
return notFoundResponse(single(accountId), result.GetSessionState(), objectType, result.GetState())
}
-func etaggedNotFoundResponse(accountIds []string, sessionState jmap.SessionState, objectType ResponseObjectType, etag jmap.State, contentLanguage jmap.Language) Response {
+func etaggedNotFoundResponse(accountIds []jmap.AccountId, sessionState jmap.SessionState, objectType ResponseObjectType, etag jmap.State, contentLanguage jmap.Language) Response {
return Response{
accountIds: accountIds,
body: nil,
@@ -209,11 +209,11 @@ func etaggedNotFoundResponse(accountIds []string, sessionState jmap.SessionState
}
}
-func (r *Request) etaggedNotFound(accountId string, sessionState jmap.SessionState, objectType ResponseObjectType, etag jmap.State) Response {
+func (r *Request) etaggedNotFound(accountId jmap.AccountId, sessionState jmap.SessionState, objectType ResponseObjectType, etag jmap.State) Response {
return etaggedNotFoundResponse(single(accountId), sessionState, objectType, etag, jmap.Language(r.language()))
}
-func notImplementedResponse(accountIds []string, sessionState jmap.SessionState, objectType ResponseObjectType) Response {
+func notImplementedResponse(accountIds []jmap.AccountId, sessionState jmap.SessionState, objectType ResponseObjectType) Response {
return Response{
accountIds: accountIds,
body: nil,
@@ -225,6 +225,6 @@ func notImplementedResponse(accountIds []string, sessionState jmap.SessionState,
}
}
-func (r *Request) notImplementedN(accountIds []string, objectType ResponseObjectType) Response {
+func (r *Request) notImplementedN(accountIds []jmap.AccountId, objectType ResponseObjectType) Response {
return notImplementedResponse(accountIds, r.session.State, objectType)
}
diff --git a/services/groupware/pkg/groupware/suppliers.go b/services/groupware/pkg/groupware/suppliers.go
index 91b706a865..4bf35fa302 100644
--- a/services/groupware/pkg/groupware/suppliers.go
+++ b/services/groupware/pkg/groupware/suppliers.go
@@ -11,26 +11,28 @@ import (
"github.com/opencloud-eu/opencloud/pkg/structs"
)
+type SupplierId string
+
type Supplier[T jmap.Foo] interface {
- GetId() string
+ GetId() SupplierId
IsMine(id string) bool
}
type ListSupplier[T jmap.Foo, G jmap.GetResponse[T]] interface {
- GetAll(accountId string, ids []string, ctx jmap.Context) (jmap.Result[G], error)
+ GetAll(accountId jmap.AccountId, ids []string, ctx jmap.Context) (jmap.Result[G], error)
Supplier[T]
}
type QuerySupplier[T jmap.Foo, R jmap.SearchResults[T], F jmap.FilterElement[T], C jmap.Comparator[T]] interface {
- Query(accountIds []string, qps QueryParamsSupplier, limit *uint, filter F, sortBy []C, calculateTotal bool, ctx jmap.Context) (jmap.Result[map[string]R], error)
+ Query(accountIds []jmap.AccountId, qps QueryParamsSupplier, limit *uint, filter F, sortBy []C, calculateTotal bool, ctx jmap.Context) (jmap.Result[map[jmap.AccountId]R], error)
Supplier[T]
}
// queryFunc func(req Request, accountIds []string, qps QueryParamsSupplier, limit *uint, filter FILTER, sortBy []COMP, ctx jmap.Context) (jmap.Result[SEARCHRESULTS], NextToken, error),
func curryQueryFunc[SRES jmap.SearchResults[T], T jmap.Foo, FILTER any, COMP any](
- f func(accountIds []string, qps QueryParamsSupplier, limit *uint, filter FILTER, sortBy []COMP, calculateTotal bool, ctx jmap.Context) (jmap.Result[SRES], NextToken, error),
-) func(req Request, accountIds []string, qps QueryParamsSupplier, limit *uint, filter FILTER, sortBy []COMP, ctx jmap.Context) (jmap.Result[SRES], NextToken, error) {
- return func(_ Request, accountIds []string, qps QueryParamsSupplier, limit *uint, filter FILTER, sortBy []COMP, ctx jmap.Context) (jmap.Result[SRES], NextToken, error) { //NOSONAR
+ f func(accountIds []jmap.AccountId, qps QueryParamsSupplier, limit *uint, filter FILTER, sortBy []COMP, calculateTotal bool, ctx jmap.Context) (jmap.Result[SRES], NextToken, error),
+) func(req Request, accountIds []jmap.AccountId, qps QueryParamsSupplier, limit *uint, filter FILTER, sortBy []COMP, ctx jmap.Context) (jmap.Result[SRES], NextToken, error) {
+ return func(_ Request, accountIds []jmap.AccountId, qps QueryParamsSupplier, limit *uint, filter FILTER, sortBy []COMP, ctx jmap.Context) (jmap.Result[SRES], NextToken, error) { //NOSONAR
result, next, err := f(accountIds, qps, limit, filter, sortBy, true, ctx)
if err != nil {
return jmap.ZeroResult[SRES](), next, err
@@ -40,8 +42,8 @@ func curryQueryFunc[SRES jmap.SearchResults[T], T jmap.Foo, FILTER any, COMP any
}
}
-func agg[T jmap.Idable, R jmap.GetResponse[T]](accountId string, supplierIds []string, responses []*R, //NOSONAR
- ctor func(accountId string, state jmap.State, notFound []string, list []T) R) (R, error) {
+func agg[T jmap.Idable, R jmap.GetResponse[T]](accountId jmap.AccountId, supplierIds []SupplierId, responses []*R, //NOSONAR
+ ctor func(accountId jmap.AccountId, state jmap.State, notFound []string, list []T) R) (R, error) {
if len(responses) < 1 {
var zero R
return zero, fmt.Errorf("requires at least one response")
@@ -54,7 +56,7 @@ func agg[T jmap.Idable, R jmap.GetResponse[T]](accountId string, supplierIds []s
return zero
}
})...)
- states, err := structs.MeshMap(supplierIds, responses, func(id string, e *R) (string, jmap.State, bool) {
+ states, err := structs.MeshMap(supplierIds, responses, func(id SupplierId, e *R) (SupplierId, jmap.State, bool) {
if e != nil {
state := (*e).GetState()
if state != jmap.EmptyState {
@@ -85,8 +87,8 @@ func agg[T jmap.Idable, R jmap.GetResponse[T]](accountId string, supplierIds []s
return ctor(accountId, state, notFounds, lists), nil
}
-func slist[T jmap.Idable, G jmap.GetResponse[T], S ListSupplier[T, G]](suppliers []S, accountId string, ids []string, ctx jmap.Context, //NOSONAR
- ctor func(accountId string, state jmap.State, notFound []string, list []T) G) (jmap.Result[G], error) {
+func slist[T jmap.Idable, G jmap.GetResponse[T], S ListSupplier[T, G]](suppliers []S, accountId jmap.AccountId, ids []string, ctx jmap.Context, //NOSONAR
+ ctor func(accountId jmap.AccountId, state jmap.State, notFound []string, list []T) G) (jmap.Result[G], error) {
switch len(suppliers) {
case 0:
return jmap.ZeroResult[G](), nil
@@ -94,7 +96,7 @@ func slist[T jmap.Idable, G jmap.GetResponse[T], S ListSupplier[T, G]](suppliers
return suppliers[0].GetAll(accountId, ids, ctx)
default:
results := make([]*jmap.Result[G], len(suppliers))
- supplierIds := make([]string, len(suppliers))
+ supplierIds := make([]SupplierId, len(suppliers))
for i, supplier := range suppliers {
supplierIds[i] = supplier.GetId()
localIds := []string{}
@@ -118,7 +120,7 @@ func slist[T jmap.Idable, G jmap.GetResponse[T], S ListSupplier[T, G]](suppliers
if err != nil {
return resp, jmap.EmptySessionState, jmap.EmptyState, jmap.NoLanguage, err
}
- m, err := structs.MeshMap(supplierIds, sessionStates, func(id string, state *jmap.SessionState) (string, jmap.SessionState, bool) {
+ m, err := structs.MeshMap(supplierIds, sessionStates, func(id SupplierId, state *jmap.SessionState) (SupplierId, jmap.SessionState, bool) {
if state != nil && *state != jmap.EmptySessionState {
return id, *state, true
} else {
@@ -141,7 +143,7 @@ func slist[T jmap.Idable, G jmap.GetResponse[T], S ListSupplier[T, G]](suppliers
}
}
-func fillMissingAccounts(qps QueryParamsSupplier, supplierId string, accountIds []string, n map[string]jmap.QueryParams) error {
+func fillMissingAccounts(qps QueryParamsSupplier, supplierId SupplierId, accountIds []jmap.AccountId, n map[jmap.AccountId]jmap.QueryParams) error {
for _, accountId := range accountIds {
if _, ok := n[accountId]; !ok {
// no result item was kept for this accountId
@@ -167,7 +169,7 @@ func fillMissingAccounts(qps QueryParamsSupplier, supplierId string, accountIds
}
func squery[T jmap.Idable, R jmap.SearchResults[T], S QuerySupplier[T, R, F, C], F jmap.FilterElement[T], C jmap.Comparator[T]]( //NOSONAR
- suppliers []S, accountIds []string, qps QueryParamsSupplier, limit *uint, filter F, sortBy []C,
+ suppliers []S, accountIds []jmap.AccountId, qps QueryParamsSupplier, limit *uint, filter F, sortBy []C,
calculateTotal bool, ctx jmap.Context,
sorter func(T, T) int,
searchResultCtor func(canCalculateChanges jmap.ChangeCalculation, position *uint, limit *uint, total *uint, results []T) R) (
@@ -190,7 +192,7 @@ func squery[T jmap.Idable, R jmap.SearchResults[T], S QuerySupplier[T, R, F, C],
// use anchor and anchorOffset and limit:
// the anchor for the next query is the ID of the last element in the results for this query
// using an anchor offset of +1
- n := map[string]jmap.QueryParams{}
+ n := map[jmap.AccountId]jmap.QueryParams{}
for accountId, payload := range result.Payload {
items := payload.GetResults()
last := items[len(items)-1]
@@ -199,7 +201,7 @@ func squery[T jmap.Idable, R jmap.SearchResults[T], S QuerySupplier[T, R, F, C],
if nextToken, err := nextSingle(n); err != nil {
return jmap.ZeroResult[R](), NoNextToken, err
} else {
- single, err := jmap.RefineResultPayload(result, func(m map[string]R) (R, bool, error) {
+ single, err := jmap.RefineResultPayload(result, func(m map[jmap.AccountId]R) (R, bool, error) {
if r, ok := m[accountId]; ok {
return r, true, nil
} else {
@@ -211,7 +213,7 @@ func squery[T jmap.Idable, R jmap.SearchResults[T], S QuerySupplier[T, R, F, C],
} else {
// multiple accountIds => we need to merge/flatten the results, and we must use anchor and offset for the next page
payloads := []T{}
- originals := map[string][]T{}
+ originals := map[jmap.AccountId][]T{}
cc := true
total := uint(0)
for accountId, searchResult := range result.Payload {
@@ -249,7 +251,7 @@ func squery[T jmap.Idable, R jmap.SearchResults[T], S QuerySupplier[T, R, F, C],
r = searchResultCtor(jmap.ChangeCalculation(cc), nil, limit, &total, payloads) // TODO can we determine the position here, instead of nil?
}
- lastIdByAccountId := map[string]string{}
+ lastIdByAccountId := map[jmap.AccountId]string{}
// not amazing, but since the accountId information is not attached to every single
// search result element (e.g. a ContactCard), we have to iterate over the original results that we
// have by accountId to find them again, in order to determine the "last ID"
@@ -263,7 +265,7 @@ func squery[T jmap.Idable, R jmap.SearchResults[T], S QuerySupplier[T, R, F, C],
}
}
- n := map[string]jmap.QueryParams{}
+ n := map[jmap.AccountId]jmap.QueryParams{}
for accountId, lastId := range lastIdByAccountId {
// the anchor for the next query is the ID of the last element in the results for this query
// using an anchor offset of +1
@@ -273,7 +275,7 @@ func squery[T jmap.Idable, R jmap.SearchResults[T], S QuerySupplier[T, R, F, C],
return jmap.ZeroResult[R](), NoNextToken, err
}
- nextBySupplier := map[string]map[string]jmap.QueryParams{supplier.GetId(): n}
+ nextBySupplier := map[SupplierId]map[jmap.AccountId]jmap.QueryParams{supplier.GetId(): n}
if nextToken, err := nextMulti(nextBySupplier); err != nil {
return jmap.ZeroResult[R](), NoNextToken, err
} else {
@@ -287,11 +289,11 @@ func squery[T jmap.Idable, R jmap.SearchResults[T], S QuerySupplier[T, R, F, C],
}
default:
payloads := []T{}
- originals := map[string]map[string][]T{}
+ originals := map[SupplierId]map[jmap.AccountId][]T{}
cc := true
total := uint(0)
sessionState := jmap.EmptySessionState
- states := map[string]jmap.State{}
+ states := map[SupplierId]jmap.State{}
lang := jmap.NoLanguage
for _, supplier := range suppliers {
// we are not injecting id prefixes here for all the objects, as each supplier is responsible for doing that if necessary
@@ -306,7 +308,7 @@ func squery[T jmap.Idable, R jmap.SearchResults[T], S QuerySupplier[T, R, F, C],
lang = result.GetLanguage()
}
// iterate over results by accountId and flatten everything into the 'payloads' array
- o := map[string][]T{}
+ o := map[jmap.AccountId][]T{}
for accountId, searchResult := range result.Payload {
o[accountId] = searchResult.GetResults()
if !searchResult.GetCanCalculateChanges() {
@@ -345,7 +347,7 @@ func squery[T jmap.Idable, R jmap.SearchResults[T], S QuerySupplier[T, R, F, C],
r = searchResultCtor(jmap.ChangeCalculation(cc), nil, limit, &total, payloads) // TODO cen we provide the position here instead of nil?
}
- lastIdBySupplierByAccountId := map[string]map[string]string{}
+ lastIdBySupplierByAccountId := map[SupplierId]map[jmap.AccountId]string{}
// not amazing, but since the accountId and supplier information is not attached to every single
// search result element (e.g. a ContactCard), we have to iterate over the original results that we
// kept by supplier and by accountId to find them again, in order to determine the "last ID"
@@ -356,7 +358,7 @@ func squery[T jmap.Idable, R jmap.SearchResults[T], S QuerySupplier[T, R, F, C],
for accountId, items := range o {
if slices.IndexFunc(items, func(t T) bool { return t.GetId() == item.GetId() }) >= 0 {
if _, ok := lastIdBySupplierByAccountId[supplierId]; !ok {
- lastIdBySupplierByAccountId[supplierId] = map[string]string{}
+ lastIdBySupplierByAccountId[supplierId] = map[jmap.AccountId]string{}
}
lastIdBySupplierByAccountId[supplierId][accountId] = item.GetId()
}
@@ -364,9 +366,9 @@ func squery[T jmap.Idable, R jmap.SearchResults[T], S QuerySupplier[T, R, F, C],
}
}
- nextBySupplier := map[string]map[string]jmap.QueryParams{}
+ nextBySupplier := map[SupplierId]map[jmap.AccountId]jmap.QueryParams{}
for supplierId, m := range lastIdBySupplierByAccountId {
- n := map[string]jmap.QueryParams{}
+ n := map[jmap.AccountId]jmap.QueryParams{}
for accountId, lastId := range m {
// the anchor for the next query is the ID of the last element in the results for this query
// using an anchor offset of +1
@@ -397,7 +399,7 @@ func squery[T jmap.Idable, R jmap.SearchResults[T], S QuerySupplier[T, R, F, C],
const combinedStateEncodingPrefix = "="
-func combineState[S jmap.State | jmap.SessionState](m map[string]S) (S, error) {
+func combineState[K ~string, S jmap.State | jmap.SessionState](m map[K]S) (S, error) {
if b, err := json.Marshal(m); err != nil {
return "", err
} else {
@@ -406,13 +408,13 @@ func combineState[S jmap.State | jmap.SessionState](m map[string]S) (S, error) {
}
}
-func splitState[S jmap.State | jmap.SessionState](state S) (map[string]S, error) {
+func splitState[K ~string, S jmap.State | jmap.SessionState](state S) (map[K]S, error) {
s := string(state)
if strings.HasPrefix(s, combinedStateEncodingPrefix) {
if b, err := base64.RawURLEncoding.DecodeString(s[len(combinedStateEncodingPrefix):]); err != nil {
return nil, err
} else {
- m := map[string]S{}
+ m := map[K]S{}
if err := json.Unmarshal(b, &m); err != nil {
return nil, err
} else {
@@ -420,6 +422,6 @@ func splitState[S jmap.State | jmap.SessionState](state S) (map[string]S, error)
}
}
} else {
- return map[string]S{"jmap": state}, nil
+ return map[K]S{K("jmap"): state}, nil
}
}
diff --git a/services/groupware/pkg/groupware/suppliers_test.go b/services/groupware/pkg/groupware/suppliers_test.go
index 5d2fa43ce5..e0ca3defe0 100644
--- a/services/groupware/pkg/groupware/suppliers_test.go
+++ b/services/groupware/pkg/groupware/suppliers_test.go
@@ -10,20 +10,20 @@ import (
)
type PetSupplier struct {
- id string
- petsByAccountId map[string][]Pet
+ id SupplierId
+ petsByAccountId map[jmap.AccountId][]Pet
}
// var _ ListSupplier[Pet, PetGetResponse] = &PetSupplier{}
var _ QuerySupplier[Pet, *PetSearchResults, PetFilterElement, PetComparator] = &PetSupplier{}
-func (s *PetSupplier) GetId() string {
+func (s *PetSupplier) GetId() SupplierId {
return s.id
}
func (s *PetSupplier) IsMine(id string) bool {
- return strings.HasPrefix(id, s.id+":")
+ return strings.HasPrefix(id, string(s.id)+":")
}
-func (s *PetSupplier) Query(accountIds []string, qps QueryParamsSupplier, limit *uint, filter PetFilterElement, sortBy []PetComparator, calculateTotal bool, ctx jmap.Context) (jmap.Result[map[string]*PetSearchResults], error) {
+func (s *PetSupplier) Query(accountIds []jmap.AccountId, qps QueryParamsSupplier, limit *uint, filter PetFilterElement, sortBy []PetComparator, calculateTotal bool, ctx jmap.Context) (jmap.Result[map[jmap.AccountId]*PetSearchResults], error) {
return inmemquery(s.id, s.petsByAccountId, accountIds, qps, limit, calculateTotal,
func(results []Pet, canCalculateChanges jmap.ChangeCalculation, position *uint, limit *uint, total *uint) *PetSearchResults {
return &PetSearchResults{Results: results, CanCalculateChanges: canCalculateChanges, Position: position, Limit: limit, Total: total}
@@ -32,18 +32,18 @@ func (s *PetSupplier) Query(accountIds []string, qps QueryParamsSupplier, limit
}
func inmemquery[T jmap.Idable, R jmap.SearchResults[T]](
- supplierId string,
- store map[string][]T,
- accountIds []string,
+ supplierId SupplierId,
+ store map[jmap.AccountId][]T,
+ accountIds []jmap.AccountId,
qps QueryParamsSupplier, limit *uint,
calculateTotal bool,
searchResultCtor func(results []T, canCalculateChanges jmap.ChangeCalculation, position *uint, limit *uint, total *uint) R,
-) (jmap.Result[map[string]R], error) {
- payload := make(map[string]R, len(accountIds))
+) (jmap.Result[map[jmap.AccountId]R], error) {
+ payload := make(map[jmap.AccountId]R, len(accountIds))
for _, accountId := range accountIds {
qp := jmap.NullQueryParams
if q, ok, err := qps.ForSupplier(supplierId, accountId); err != nil {
- return jmap.ZeroResult[map[string]R](), err
+ return jmap.ZeroResult[map[jmap.AccountId]R](), err
} else if ok {
qp = q
}
@@ -91,7 +91,7 @@ func inmemquery[T jmap.Idable, R jmap.SearchResults[T]](
payload[accountId] = res
}
- return jmap.Result[map[string]R]{
+ return jmap.Result[map[jmap.AccountId]R]{
Payload: payload,
SessionState: jmap.EmptySessionState,
State: jmap.EmptyState,
@@ -101,7 +101,7 @@ func inmemquery[T jmap.Idable, R jmap.SearchResults[T]](
func pets(
suppliers []QuerySupplier[Pet, *PetSearchResults, PetFilterElement, PetComparator],
- accountIds []string, qps QueryParamsSupplier, limit *uint,
+ accountIds []jmap.AccountId, qps QueryParamsSupplier, limit *uint,
filter PetFilterElement, sortBy []PetComparator,
calculateTotal bool,
ctx jmap.Context) (jmap.Result[*PetSearchResults], NextToken, error) {
@@ -125,7 +125,7 @@ func TestSquery(t *testing.T) {
suppliers := []QuerySupplier[Pet, *PetSearchResults, PetFilterElement, PetComparator]{
&PetSupplier{
id: "X",
- petsByAccountId: map[string][]Pet{
+ petsByAccountId: map[jmap.AccountId][]Pet{
"a": {
{id: "X:1", name: "ace"},
{id: "X:2", name: "bella"},
@@ -137,7 +137,7 @@ func TestSquery(t *testing.T) {
},
&PetSupplier{
id: "Y",
- petsByAccountId: map[string][]Pet{
+ petsByAccountId: map[jmap.AccountId][]Pet{
"a": {
{id: "Y:1", name: "cupcake"},
{id: "Y:2", name: "elvis"},
@@ -149,14 +149,14 @@ func TestSquery(t *testing.T) {
},
},
}
- f := func(accountIds []string, position int, anchor string, anchorOffset *int, limit *uint) (jmap.Result[*PetSearchResults], NextToken, error) {
+ f := func(accountIds []jmap.AccountId, position int, anchor string, anchorOffset *int, limit *uint) (jmap.Result[*PetSearchResults], NextToken, error) {
return pets(suppliers, accountIds,
StaticQueryParamsSupplier{qp: jmap.QueryParams{Position: position, Anchor: anchor, AnchorOffset: anchorOffset}}, limit,
PetFilterCondition{}, []PetComparator{{Property: "id", IsAscending: true}},
true, jmap.Context{},
)
}
- n := func(accountIds []string, nextToken NextToken, limit *uint) (jmap.Result[*PetSearchResults], NextToken, error) {
+ n := func(accountIds []jmap.AccountId, nextToken NextToken, limit *uint) (jmap.Result[*PetSearchResults], NextToken, error) {
if qps, err := unnext(nextToken); err != nil {
return jmap.ZeroResult[*PetSearchResults](), NoNextToken, err
} else {
@@ -165,7 +165,7 @@ func TestSquery(t *testing.T) {
}
{
- res, n, err := f([]string{"a", "b", "c"}, 0, "", nil, nil)
+ res, n, err := f([]jmap.AccountId{"a", "b", "c"}, 0, "", nil, nil)
require.NoError(err)
require.Len(res.Payload.Results, 7)
require.Equal(uint(len(res.Payload.Results)), *res.Payload.Total)
@@ -189,7 +189,7 @@ func TestSquery(t *testing.T) {
}
var nextToken NextToken
{
- res, n, err := f([]string{"a", "b", "c"}, 0, "", nil, uintPtr(4))
+ res, n, err := f([]jmap.AccountId{"a", "b", "c"}, 0, "", nil, uintPtr(4))
nextToken = n
require.NoError(err)
require.Len(res.Payload.Results, 4)
@@ -210,7 +210,7 @@ func TestSquery(t *testing.T) {
}
}
{
- res, _, err := n([]string{"a", "b", "c"}, nextToken, uintPtr(4))
+ res, _, err := n([]jmap.AccountId{"a", "b", "c"}, nextToken, uintPtr(4))
require.NoError(err)
require.Equal(uint(7), *res.Payload.Total)
require.Len(res.Payload.Results, 3)
diff --git a/services/groupware/pkg/groupware/templates.go b/services/groupware/pkg/groupware/templates.go
index 7cbeddd9f7..6d2c559c76 100644
--- a/services/groupware/pkg/groupware/templates.go
+++ b/services/groupware/pkg/groupware/templates.go
@@ -14,15 +14,15 @@ func create[T jmap.Foo, CHANGE jmap.Change, CHANGES jmap.Changes[T]]( //NOSONAR
o ObjectType[T, CHANGE, CHANGES],
w http.ResponseWriter, r *http.Request,
g *Groupware,
- bodyFunc func(r Request, accountId string, body *CHANGE, ctx jmap.Context) (bool, Response),
- createFunc func(accountId string, change CHANGE, ctx jmap.Context) (jmap.Result[*T], error),
+ bodyFunc func(r Request, accountId jmap.AccountId, body *CHANGE, ctx jmap.Context) (bool, Response),
+ createFunc func(accountId jmap.AccountId, change CHANGE, ctx jmap.Context) (jmap.Result[*T], error),
) {
g.respond(w, r, func(req Request) Response {
ok, accountId, resp := o.accountFunc(&req)
if !ok {
return resp
}
- l := req.logger.With().Str(accountId, log.SafeString(accountId))
+ l := req.logger.With().Str(logAccountId, log.SafeString(accountId))
if notok, resp := req.unsupportedQueryParams(single(accountId), noSupportedQueryParams); notok {
return resp
@@ -66,14 +66,14 @@ func getall[T jmap.Foo, CHANGE jmap.Change, CHANGES jmap.Changes[T], RESP jmap.G
o ObjectType[T, CHANGE, CHANGES],
w http.ResponseWriter, r *http.Request,
g *Groupware,
- getFunc func(accountId string, ids []string, ctx jmap.Context) (jmap.Result[RESP], error),
+ getFunc func(accountId jmap.AccountId, ids []string, ctx jmap.Context) (jmap.Result[RESP], error),
) {
g.respond(w, r, func(req Request) Response {
ok, accountId, resp := o.accountFunc(&req)
if !ok {
return resp
}
- l := req.logger.With().Str(accountId, log.SafeString(accountId))
+ l := req.logger.With().Str(logAccountId, log.SafeString(accountId))
if notok, resp := req.unsupportedQueryParams(single(accountId), noSupportedQueryParams); notok {
return resp
@@ -112,14 +112,14 @@ func getallpaged[T jmap.Foo, CHANGE jmap.Change, CHANGES jmap.Changes[T], FILTER
withContainerId bool,
filterFunc func(containerId string) FILTER,
sortBy []COMP,
- queryFunc func(req Request, accountIds []string, qps QueryParamsSupplier, limit *uint, filter FILTER, sortBy []COMP, ctx jmap.Context) (jmap.Result[SEARCHRESULTS], NextToken, error),
+ queryFunc func(req Request, accountIds []jmap.AccountId, qps QueryParamsSupplier, limit *uint, filter FILTER, sortBy []COMP, ctx jmap.Context) (jmap.Result[SEARCHRESULTS], NextToken, error),
) {
g.respond(w, r, func(req Request) Response {
ok, accountId, resp := o.accountFunc(&req)
if !ok {
return resp
}
- l := req.logger.With().Str(accountId, log.SafeString(accountId))
+ l := req.logger.With().Str(logAccountId, log.SafeString(accountId))
var limit *uint = nil
{
@@ -147,34 +147,6 @@ func getallpaged[T jmap.Foo, CHANGE jmap.Change, CHANGES jmap.Changes[T], FILTER
} else {
supportedQueryParams = firstQueryParams
qps = FirstQueryParamsSupplier{}
-
- /*
- position, ok, err := req.parseIntParam(QueryParamPosition, 0)
- if err != nil {
- return req.error(accountId, err)
- }
- if ok {
- l = l.Int(QueryParamPosition, position)
- }
-
- anchor, ok := req.getStringParam(QueryParamAnchor, "")
- if ok {
- l = l.Str(QueryParamAnchor, log.SafeString(anchor))
- }
-
- var anchorOffset *int = nil
- {
- v, ok, err := req.parseIntParam(QueryParamAnchorOffset, 0)
- if err != nil {
- return req.error(accountId, err)
- }
- if ok {
- l = l.Int(QueryParamAnchorOffset, v)
- anchorOffset = &v
- }
- }
- */
-
}
}
@@ -220,14 +192,14 @@ func query[T jmap.Foo, CHANGE jmap.Change, CHANGES jmap.Changes[T], SEARCHRESULT
w http.ResponseWriter, r *http.Request,
g *Groupware,
defaultLimit *uint,
- queryFunc func(req Request, accountId string, containerId string, qp jmap.QueryParams, limit *uint, ctx jmap.Context) (jmap.Result[SEARCHRESULTS], error),
+ queryFunc func(req Request, accountId jmap.AccountId, containerId string, qp jmap.QueryParams, limit *uint, ctx jmap.Context) (jmap.Result[SEARCHRESULTS], error),
) {
g.respond(w, r, func(req Request) Response {
ok, accountId, resp := o.accountFunc(&req)
if !ok {
return resp
}
- l := req.logger.With().Str(accountId, log.SafeString(accountId))
+ l := req.logger.With().Str(logAccountId, log.SafeString(accountId))
containerId := ""
if o.containerUriParamName != "" {
@@ -366,14 +338,14 @@ func get[T jmap.Foo, CHANGE jmap.Change, CHANGES jmap.Changes[T], RESP jmap.GetR
o ObjectType[T, CHANGE, CHANGES],
w http.ResponseWriter, r *http.Request,
g *Groupware,
- getFunc func(accountId string, ids []string, ctx jmap.Context) (jmap.Result[RESP], error),
+ getFunc func(accountId jmap.AccountId, ids []string, ctx jmap.Context) (jmap.Result[RESP], error),
) {
g.respond(w, r, func(req Request) Response {
ok, accountId, resp := o.accountFunc(&req)
if !ok {
return resp
}
- l := req.logger.With().Str(accountId, log.SafeString(accountId))
+ l := req.logger.With().Str(logAccountId, log.SafeString(accountId))
ids := []string{}
if o.uriParamName != "" {
id, err := req.PathParamDoc(o.uriParamName, "The unique identifier of the object to retrieve")
@@ -423,14 +395,14 @@ func getFromMap[T jmap.Foo, CHANGE jmap.Change, CHANGES jmap.Changes[T], RESP jm
o ObjectType[T, CHANGE, CHANGES],
w http.ResponseWriter, r *http.Request,
g *Groupware,
- getFunc func(accountIds []string, ids []string, ctx jmap.Context) (jmap.Result[map[string]RESP], error),
+ getFunc func(accountIds []jmap.AccountId, ids []string, ctx jmap.Context) (jmap.Result[map[jmap.AccountId]RESP], error),
) {
g.respond(w, r, func(req Request) Response {
ok, accountId, resp := o.accountFunc(&req)
if !ok {
return resp
}
- l := req.logger.With().Str(accountId, log.SafeString(accountId))
+ l := req.logger.With().Str(logAccountId, log.SafeString(accountId))
id, err := req.PathParamDoc(o.uriParamName, "The unique identifier of the object to retrieve")
if err != nil {
return req.error(accountId, err)
@@ -482,14 +454,14 @@ func changes[T jmap.Foo, CHANGE jmap.Change, CHANGES jmap.Changes[T]]( //NOSONAR
o ObjectType[T, CHANGE, CHANGES],
w http.ResponseWriter, r *http.Request,
g *Groupware,
- changesFunc func(accountId string, sinceState jmap.State, maxChanges uint, ctx jmap.Context) (jmap.Result[CHANGES], error),
+ changesFunc func(accountId jmap.AccountId, sinceState jmap.State, maxChanges uint, ctx jmap.Context) (jmap.Result[CHANGES], error),
) {
g.respond(w, r, func(req Request) Response {
ok, accountId, resp := o.accountFunc(&req)
if !ok {
return resp
}
- l := req.logger.With().Str(accountId, log.SafeString(accountId))
+ l := req.logger.With().Str(logAccountId, log.SafeString(accountId))
maxChanges, ok, err := req.parseUIntParam(QueryParamMaxChanges, 0)
if err != nil {
@@ -535,14 +507,14 @@ func delete[T jmap.Foo, CHANGE jmap.Change, CHANGES jmap.Changes[T]]( //NOSONAR
o ObjectType[T, CHANGE, CHANGES],
w http.ResponseWriter, r *http.Request,
g *Groupware,
- deleteFunc func(accountId string, ids []string, ctx jmap.Context) (jmap.Result[map[string]jmap.SetError], error),
+ deleteFunc func(accountId jmap.AccountId, ids []string, ctx jmap.Context) (jmap.Result[map[string]jmap.SetError], error),
) {
g.respond(w, r, func(req Request) Response {
ok, accountId, resp := o.accountFunc(&req)
if !ok {
return resp
}
- l := req.logger.With().Str(accountId, log.SafeString(accountId))
+ l := req.logger.With().Str(logAccountId, log.SafeString(accountId))
id, err := req.PathParamDoc(o.uriParamName, "The unique identifier of the object to delete")
if err != nil {
return req.error(accountId, err)
@@ -597,14 +569,14 @@ func deleteMany[T jmap.Foo, CHANGE jmap.Change, CHANGES jmap.Changes[T]]( //NOSO
o ObjectType[T, CHANGE, CHANGES],
w http.ResponseWriter, r *http.Request,
g *Groupware,
- deleteFunc func(accountId string, ids []string, ctx jmap.Context) (jmap.Result[map[string]jmap.SetError], error),
+ deleteFunc func(accountId jmap.AccountId, ids []string, ctx jmap.Context) (jmap.Result[map[string]jmap.SetError], error),
) {
g.respond(w, r, func(req Request) Response {
ok, accountId, resp := o.accountFunc(&req)
if !ok {
return resp
}
- l := req.logger.With().Str(accountId, log.SafeString(accountId))
+ l := req.logger.With().Str(logAccountId, log.SafeString(accountId))
ids := []string{}
if o.uriParamName != "" {
@@ -686,14 +658,14 @@ func modify[T jmap.Foo, CHANGE jmap.Change, CHANGES jmap.Changes[T]](
o ObjectType[T, CHANGE, CHANGES],
w http.ResponseWriter, r *http.Request,
g *Groupware,
- updateFunc func(accountId string, id string, change CHANGE, ctx jmap.Context) (jmap.Result[T], error),
+ updateFunc func(accountId jmap.AccountId, id string, change CHANGE, ctx jmap.Context) (jmap.Result[T], error),
) {
g.respond(w, r, func(req Request) Response {
ok, accountId, resp := o.accountFunc(&req)
if !ok {
return resp
}
- l := req.logger.With().Str(accountId, log.SafeString(accountId))
+ l := req.logger.With().Str(logAccountId, log.SafeString(accountId))
id, err := req.PathParamDoc(o.uriParamName, "The unique identifier of the object to modify")
if err != nil {
return req.error(accountId, err)