mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-06-16 20:08:59 -04:00
groupware: add strongly typed aliases for AccountId, PrincipalId and SupplierId
Purpose is to make APIs and parameters easier to understand, since plain strings are used all over the place for all sorts of identifiers.
This commit is contained in:
@@ -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}
|
||||
|
||||
@@ -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
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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{},
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -244,4 +244,3 @@ The alternative would be to have different APIs depending on what each endpoint
|
||||
|
||||
* endpoint with multiple backends or multiple accounts:<br>same as above with `?first=...` and `?next=...`
|
||||
* endpoint with a single backend and a single account:<br>`?position=...&anchor=...&offset=...&limit=...`
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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{}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user