mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-04-13 11:57:33 -04:00
groupware: refactoring: pass object type instead of namespaces
* make the JMAP internal API a bit more future-proof by passing ObjectType objects instead of the JMAP namespaces * remove the new attempt to contain operations even further using the Factory objects * move CalendarEvent operations to its own file, like everything else * fix email tests * ignore WS error when closing an already closed connection
This commit is contained in:
@@ -3,7 +3,7 @@ package jmap
|
||||
var NS_ADDRESSBOOKS = ns(JmapContacts)
|
||||
|
||||
func (j *Client) GetAddressbooks(accountId string, ids []string, ctx Context) (AddressBookGetResponse, SessionState, State, Language, Error) {
|
||||
return get(j, "GetAddressbooks", NS_ADDRESSBOOKS,
|
||||
return get(j, "GetAddressbooks", MailboxType,
|
||||
func(accountId string, ids []string) AddressBookGetCommand {
|
||||
return AddressBookGetCommand{AccountId: accountId, Ids: ids}
|
||||
},
|
||||
@@ -19,7 +19,7 @@ type AddressBookChanges = ChangesTemplate[AddressBook]
|
||||
// Retrieve Address Book changes since a given state.
|
||||
// @apidoc addressbook,changes
|
||||
func (j *Client) GetAddressbookChanges(accountId string, sinceState State, maxChanges uint, ctx Context) (AddressBookChanges, SessionState, State, Language, Error) {
|
||||
return changesA(j, "GetAddressbookChanges", NS_ADDRESSBOOKS,
|
||||
return changesA(j, "GetAddressbookChanges", MailboxType,
|
||||
func() AddressBookChangesCommand {
|
||||
return AddressBookChangesCommand{AccountId: accountId, SinceState: sinceState, MaxChanges: uintPtr(maxChanges)}
|
||||
},
|
||||
@@ -50,7 +50,7 @@ func (j *Client) GetAddressbookChanges(accountId string, sinceState State, maxCh
|
||||
}
|
||||
|
||||
func (j *Client) CreateAddressBook(accountId string, addressbook AddressBookChange, ctx Context) (*AddressBook, SessionState, State, Language, Error) {
|
||||
return create(j, "CreateAddressBook", NS_ADDRESSBOOKS,
|
||||
return create(j, "CreateAddressBook", MailboxType,
|
||||
func(accountId string, create map[string]AddressBookChange) AddressBookSetCommand {
|
||||
return AddressBookSetCommand{AccountId: accountId, Create: create}
|
||||
},
|
||||
@@ -69,7 +69,7 @@ func (j *Client) CreateAddressBook(accountId string, addressbook AddressBookChan
|
||||
}
|
||||
|
||||
func (j *Client) DeleteAddressBook(accountId string, destroyIds []string, ctx Context) (map[string]SetError, SessionState, State, Language, Error) {
|
||||
return destroy(j, "DeleteAddressBook", NS_ADDRESSBOOKS,
|
||||
return destroy(j, "DeleteAddressBook", MailboxType,
|
||||
func(accountId string, destroy []string) AddressBookSetCommand {
|
||||
return AddressBookSetCommand{AccountId: accountId, Destroy: destroy}
|
||||
},
|
||||
@@ -80,7 +80,7 @@ func (j *Client) DeleteAddressBook(accountId string, destroyIds []string, ctx Co
|
||||
}
|
||||
|
||||
func (j *Client) UpdateAddressBook(accountId string, id string, changes AddressBookChange, ctx Context) (AddressBook, SessionState, State, Language, Error) {
|
||||
return update(j, "UpdateAddressBook", NS_ADDRESSBOOKS,
|
||||
return update(j, "UpdateAddressBook", MailboxType,
|
||||
func(update map[string]PatchObject) AddressBookSetCommand {
|
||||
return AddressBookSetCommand{AccountId: accountId, Update: update}
|
||||
},
|
||||
|
||||
@@ -24,7 +24,7 @@ func (j *Client) ParseICalendarBlob(accountId string, blobIds []string, ctx Cont
|
||||
}
|
||||
|
||||
func (j *Client) GetCalendars(accountId string, ids []string, ctx Context) (CalendarGetResponse, SessionState, State, Language, Error) {
|
||||
return get(j, "GetCalendars", NS_CALENDARS,
|
||||
return get(j, "GetCalendars", CalendarType,
|
||||
func(accountId string, ids []string) CalendarGetCommand {
|
||||
return CalendarGetCommand{AccountId: accountId, Ids: ids}
|
||||
},
|
||||
@@ -40,7 +40,7 @@ type CalendarChanges = ChangesTemplate[Calendar]
|
||||
// Retrieve Calendar changes since a given state.
|
||||
// @apidoc calendar,changes
|
||||
func (j *Client) GetCalendarChanges(accountId string, sinceState State, maxChanges uint, ctx Context) (CalendarChanges, SessionState, State, Language, Error) {
|
||||
return changes(j, "GetCalendarChanges", NS_CALENDARS,
|
||||
return changes(j, "GetCalendarChanges", CalendarType,
|
||||
func() CalendarChangesCommand {
|
||||
return CalendarChangesCommand{AccountId: accountId, SinceState: sinceState, MaxChanges: uintPtr(maxChanges)}
|
||||
},
|
||||
@@ -70,110 +70,8 @@ func (j *Client) GetCalendarChanges(accountId string, sinceState State, maxChang
|
||||
)
|
||||
}
|
||||
|
||||
type CalendarEventSearchResults SearchResultsTemplate[CalendarEvent]
|
||||
|
||||
var _ SearchResults[CalendarEvent] = CalendarEventSearchResults{}
|
||||
|
||||
func (r CalendarEventSearchResults) GetResults() []CalendarEvent { return r.Results }
|
||||
func (r CalendarEventSearchResults) GetCanCalculateChanges() bool { return r.CanCalculateChanges }
|
||||
func (r CalendarEventSearchResults) GetPosition() uint { return r.Position }
|
||||
func (r CalendarEventSearchResults) GetLimit() uint { return r.Limit }
|
||||
func (r CalendarEventSearchResults) GetTotal() *uint { return r.Total }
|
||||
|
||||
func (j *Client) QueryCalendarEvents(accountIds []string, //NOSONAR
|
||||
filter CalendarEventFilterElement, sortBy []CalendarEventComparator,
|
||||
position int, limit uint, calculateTotal bool,
|
||||
ctx Context) (map[string]CalendarEventSearchResults, SessionState, State, Language, Error) {
|
||||
return queryN(j, "QueryCalendarEvents", NS_CALENDARS,
|
||||
[]CalendarEventComparator{{Property: CalendarEventPropertyStart, IsAscending: false}},
|
||||
func(accountId string, filter CalendarEventFilterElement, sortBy []CalendarEventComparator, position int, limit uint) CalendarEventQueryCommand {
|
||||
return CalendarEventQueryCommand{AccountId: accountId, Filter: filter, Sort: sortBy, Position: position, Limit: uintPtr(limit), CalculateTotal: calculateTotal}
|
||||
},
|
||||
func(accountId string, cmd Command, path string, rof string) CalendarEventGetRefCommand {
|
||||
return CalendarEventGetRefCommand{AccountId: accountId, IdsRef: &ResultReference{Name: cmd, Path: path, ResultOf: rof}}
|
||||
},
|
||||
func(query CalendarEventQueryResponse, get CalendarEventGetResponse) CalendarEventSearchResults {
|
||||
return CalendarEventSearchResults{
|
||||
Results: get.List,
|
||||
CanCalculateChanges: query.CanCalculateChanges,
|
||||
Position: query.Position,
|
||||
Total: uintPtrIf(query.Total, calculateTotal),
|
||||
Limit: query.Limit,
|
||||
}
|
||||
},
|
||||
accountIds,
|
||||
filter, sortBy, limit, position, ctx,
|
||||
)
|
||||
}
|
||||
|
||||
type CalendarEventChanges = ChangesTemplate[CalendarEvent]
|
||||
|
||||
// Retrieve the changes in Calendar Events since a given State.
|
||||
// @api:tags event,changes
|
||||
func (j *Client) GetCalendarEventChanges(accountId string, sinceState State, maxChanges uint,
|
||||
ctx Context) (CalendarEventChanges, SessionState, State, Language, Error) {
|
||||
return changes(j, "GetCalendarEventChanges", NS_CALENDARS,
|
||||
func() CalendarEventChangesCommand {
|
||||
return CalendarEventChangesCommand{AccountId: accountId, SinceState: sinceState, MaxChanges: uintPtr(maxChanges)}
|
||||
},
|
||||
CalendarEventChangesResponse{},
|
||||
func(path string, rof string) CalendarEventGetRefCommand {
|
||||
return CalendarEventGetRefCommand{
|
||||
AccountId: accountId,
|
||||
IdsRef: &ResultReference{
|
||||
Name: CommandCalendarEventChanges,
|
||||
Path: path,
|
||||
ResultOf: rof,
|
||||
},
|
||||
}
|
||||
},
|
||||
func(resp CalendarEventGetResponse) []CalendarEvent { return resp.List },
|
||||
func(oldState, newState State, hasMoreChanges bool, created, updated []CalendarEvent, destroyed []string) CalendarEventChanges {
|
||||
return CalendarEventChanges{
|
||||
OldState: oldState,
|
||||
NewState: newState,
|
||||
HasMoreChanges: hasMoreChanges,
|
||||
Created: created,
|
||||
Updated: updated,
|
||||
Destroyed: destroyed,
|
||||
}
|
||||
},
|
||||
ctx,
|
||||
)
|
||||
}
|
||||
|
||||
func (j *Client) CreateCalendarEvent(accountId string, event CalendarEvent, ctx Context) (*CalendarEvent, SessionState, State, Language, Error) {
|
||||
return create(j, "CreateCalendarEvent", NS_CALENDARS,
|
||||
func(accountId string, create map[string]CalendarEvent) CalendarEventSetCommand {
|
||||
return CalendarEventSetCommand{AccountId: accountId, Create: create}
|
||||
},
|
||||
func(accountId string, ref string) CalendarEventGetCommand {
|
||||
return CalendarEventGetCommand{AccountId: accountId, Ids: []string{ref}}
|
||||
},
|
||||
func(resp CalendarEventSetResponse) map[string]*CalendarEvent {
|
||||
return resp.Created
|
||||
},
|
||||
func(resp CalendarEventGetResponse) []CalendarEvent {
|
||||
return resp.List
|
||||
},
|
||||
accountId, event,
|
||||
ctx,
|
||||
)
|
||||
}
|
||||
|
||||
func (j *Client) DeleteCalendarEvent(accountId string, destroyIds []string, ctx Context) (map[string]SetError, SessionState, State, Language, Error) {
|
||||
return destroy(j, "DeleteCalendarEvent", NS_CALENDARS,
|
||||
func(accountId string, destroy []string) CalendarEventSetCommand {
|
||||
return CalendarEventSetCommand{AccountId: accountId, Destroy: destroy}
|
||||
},
|
||||
CalendarEventSetResponse{},
|
||||
accountId, destroyIds,
|
||||
ctx,
|
||||
)
|
||||
}
|
||||
|
||||
func (j *Client) CreateCalendar(accountId string, calendar CalendarChange, ctx Context) (*Calendar, SessionState, State, Language, Error) {
|
||||
return create(j, "CreateCalendar", NS_CALENDARS,
|
||||
return create(j, "CreateCalendar", CalendarEventType,
|
||||
func(accountId string, create map[string]CalendarChange) CalendarSetCommand {
|
||||
return CalendarSetCommand{AccountId: accountId, Create: create}
|
||||
},
|
||||
@@ -192,7 +90,7 @@ func (j *Client) CreateCalendar(accountId string, calendar CalendarChange, ctx C
|
||||
}
|
||||
|
||||
func (j *Client) DeleteCalendar(accountId string, destroyIds []string, ctx Context) (map[string]SetError, SessionState, State, Language, Error) {
|
||||
return destroy(j, "DeleteCalendar", NS_CALENDARS,
|
||||
return destroy(j, "DeleteCalendar", CalendarEventType,
|
||||
func(accountId string, destroy []string) CalendarSetCommand {
|
||||
return CalendarSetCommand{AccountId: accountId, Destroy: destroy}
|
||||
},
|
||||
@@ -203,7 +101,7 @@ func (j *Client) DeleteCalendar(accountId string, destroyIds []string, ctx Conte
|
||||
}
|
||||
|
||||
func (j *Client) UpdateCalendar(accountId string, id string, changes CalendarChange, ctx Context) (Calendar, SessionState, State, Language, Error) {
|
||||
return update(j, "UpdateCalendar", NS_CALENDARS,
|
||||
return update(j, "UpdateCalendar", CalendarEventType,
|
||||
func(update map[string]PatchObject) CalendarSetCommand {
|
||||
return CalendarSetCommand{AccountId: accountId, Update: update}
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@ package jmap
|
||||
var NS_CONTACTS = ns(JmapContacts)
|
||||
|
||||
func (j *Client) GetContactCards(accountId string, contactIds []string, ctx Context) (ContactCardGetResponse, SessionState, State, Language, Error) {
|
||||
return get(j, "GetContactCards", NS_CONTACTS,
|
||||
return get(j, "GetContactCards", ContactCardType,
|
||||
func(accountId string, ids []string) ContactCardGetCommand {
|
||||
return ContactCardGetCommand{AccountId: accountId, Ids: contactIds}
|
||||
},
|
||||
@@ -19,7 +19,7 @@ type ContactCardChanges = ChangesTemplate[ContactCard]
|
||||
// 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) (ContactCardChanges, SessionState, State, Language, Error) {
|
||||
return changes(j, "GetContactCardChanges", NS_CONTACTS,
|
||||
return changes(j, "GetContactCardChanges", ContactCardType,
|
||||
func() ContactCardChangesCommand {
|
||||
return ContactCardChangesCommand{AccountId: accountId, SinceState: sinceState, MaxChanges: uintPtr(maxChanges)}
|
||||
},
|
||||
@@ -63,7 +63,7 @@ func (j *Client) QueryContactCards(accountIds []string,
|
||||
filter ContactCardFilterElement, sortBy []ContactCardComparator,
|
||||
position int, limit uint, calculateTotal bool,
|
||||
ctx Context) (map[string]ContactCardSearchResults, SessionState, State, Language, Error) {
|
||||
return queryN(j, "QueryContactCards", NS_CONTACTS,
|
||||
return queryN(j, "QueryContactCards", ContactCardType,
|
||||
[]ContactCardComparator{{Property: ContactCardPropertyUpdated, IsAscending: false}},
|
||||
func(accountId string, filter ContactCardFilterElement, sortBy []ContactCardComparator, position int, limit uint) ContactCardQueryCommand {
|
||||
return ContactCardQueryCommand{AccountId: accountId, Filter: filter, Sort: sortBy, Position: position, Limit: uintPtr(limit), CalculateTotal: calculateTotal}
|
||||
@@ -86,7 +86,7 @@ func (j *Client) QueryContactCards(accountIds []string,
|
||||
}
|
||||
|
||||
func (j *Client) CreateContactCard(accountId string, contact ContactCard, ctx Context) (*ContactCard, SessionState, State, Language, Error) {
|
||||
return create(j, "CreateContactCard", NS_CONTACTS,
|
||||
return create(j, "CreateContactCard", ContactCardType,
|
||||
func(accountId string, create map[string]ContactCard) ContactCardSetCommand {
|
||||
return ContactCardSetCommand{AccountId: accountId, Create: create}
|
||||
},
|
||||
@@ -105,7 +105,7 @@ func (j *Client) CreateContactCard(accountId string, contact ContactCard, ctx Co
|
||||
}
|
||||
|
||||
func (j *Client) DeleteContactCard(accountId string, destroyIds []string, ctx Context) (map[string]SetError, SessionState, State, Language, Error) {
|
||||
return destroy(j, "DeleteContactCard", NS_CONTACTS,
|
||||
return destroy(j, "DeleteContactCard", ContactCardType,
|
||||
func(accountId string, destroy []string) ContactCardSetCommand {
|
||||
return ContactCardSetCommand{AccountId: accountId, Destroy: destroy}
|
||||
},
|
||||
|
||||
@@ -13,13 +13,6 @@ import (
|
||||
var NS_MAIL = ns(JmapMail)
|
||||
var NS_MAIL_SUBMISSION = ns(JmapMail, JmapSubmission)
|
||||
|
||||
type Emails struct {
|
||||
Emails []Email `json:"emails,omitempty"`
|
||||
Total uint `json:"total,omitzero"`
|
||||
Limit uint `json:"limit,omitzero"`
|
||||
Offset uint `json:"offset,omitzero"`
|
||||
}
|
||||
|
||||
type getEmailsResult struct {
|
||||
emails []Email
|
||||
notFound []string
|
||||
@@ -32,23 +25,25 @@ func (j *Client) GetEmails(accountId string, ids []string, //NOSONAR
|
||||
logger := j.logger("GetEmails", ctx)
|
||||
ctx = ctx.WithLogger(logger)
|
||||
|
||||
get := EmailGetCommand{AccountId: accountId, Ids: ids, FetchAllBodyValues: fetchBodies}
|
||||
getEmails := EmailGetCommand{AccountId: accountId, Ids: ids, FetchAllBodyValues: fetchBodies}
|
||||
if maxBodyValueBytes > 0 {
|
||||
get.MaxBodyValueBytes = maxBodyValueBytes
|
||||
getEmails.MaxBodyValueBytes = maxBodyValueBytes
|
||||
}
|
||||
invokeGet := invocation(get, "1")
|
||||
invokeGet := invocation(getEmails, "1")
|
||||
|
||||
methodCalls := []Invocation{invokeGet}
|
||||
var markEmails EmailSetCommand
|
||||
if markAsSeen {
|
||||
updates := make(map[string]EmailUpdate, len(ids))
|
||||
for _, id := range ids {
|
||||
updates[id] = EmailUpdate{EmailPropertyKeywords + "/" + JmapKeywordSeen: true}
|
||||
}
|
||||
mark := EmailSetCommand{AccountId: accountId, Update: updates}
|
||||
methodCalls = []Invocation{invocation(mark, "0"), invokeGet}
|
||||
markEmails = EmailSetCommand{AccountId: accountId, Update: updates}
|
||||
methodCalls = []Invocation{invocation(markEmails, "0"), invokeGet}
|
||||
}
|
||||
var getThreads ThreadGetRefCommand
|
||||
if withThreads {
|
||||
threads := ThreadGetRefCommand{
|
||||
getThreads = ThreadGetRefCommand{
|
||||
AccountId: accountId,
|
||||
IdsRef: &ResultReference{
|
||||
ResultOf: "1",
|
||||
@@ -56,7 +51,7 @@ func (j *Client) GetEmails(accountId string, ids []string, //NOSONAR
|
||||
Path: "/list/*/" + EmailPropertyThreadId, //NOSONAR
|
||||
},
|
||||
}
|
||||
methodCalls = append(methodCalls, invocation(threads, "2"))
|
||||
methodCalls = append(methodCalls, invocation(getThreads, "2"))
|
||||
}
|
||||
|
||||
cmd, err := j.request(ctx, NS_MAIL, methodCalls...)
|
||||
@@ -66,7 +61,7 @@ func (j *Client) GetEmails(accountId string, ids []string, //NOSONAR
|
||||
result, sessionState, state, language, gwerr := command(j, ctx, cmd, func(body *Response) (getEmailsResult, State, Error) {
|
||||
if markAsSeen {
|
||||
var markResponse EmailSetResponse
|
||||
err = retrieveResponseMatchParameters(ctx, body, CommandEmailSet, "0", &markResponse)
|
||||
err = retrieveSet(ctx, body, markEmails, "0", &markResponse)
|
||||
if err != nil {
|
||||
return getEmailsResult{}, "", err
|
||||
}
|
||||
@@ -76,13 +71,13 @@ func (j *Client) GetEmails(accountId string, ids []string, //NOSONAR
|
||||
}
|
||||
}
|
||||
var response EmailGetResponse
|
||||
err = retrieveResponseMatchParameters(ctx, body, CommandEmailGet, "1", &response)
|
||||
err = retrieveGet(ctx, body, getEmails, "1", &response)
|
||||
if err != nil {
|
||||
return getEmailsResult{}, "", err
|
||||
}
|
||||
if withThreads {
|
||||
var threads ThreadGetResponse
|
||||
err = retrieveResponseMatchParameters(ctx, body, CommandThreadGet, "2", &threads)
|
||||
err = retrieveGet(ctx, body, getThreads, "2", &threads)
|
||||
if err != nil {
|
||||
return getEmailsResult{}, "", err
|
||||
}
|
||||
@@ -116,10 +111,12 @@ func (j *Client) GetEmailBlobId(accountId string, id string, ctx Context) (strin
|
||||
})
|
||||
}
|
||||
|
||||
type EmailSearchResults = SearchResultsTemplate[Email]
|
||||
|
||||
// Retrieve all the Emails in a given Mailbox by its id.
|
||||
func (j *Client) GetAllEmailsInMailbox(accountId string, mailboxId string, //NOSONAR
|
||||
offset int, limit uint, collapseThreads bool, fetchBodies bool, maxBodyValueBytes uint, withThreads bool,
|
||||
ctx Context) (Emails, SessionState, State, Language, Error) {
|
||||
ctx Context) (EmailSearchResults, SessionState, State, Language, Error) {
|
||||
logger := j.loggerParams("GetAllEmailsInMailbox", ctx, func(z zerolog.Context) zerolog.Context {
|
||||
return z.Bool(logFetchBodies, fetchBodies).Int(logOffset, offset).Uint(logLimit, limit)
|
||||
})
|
||||
@@ -168,36 +165,37 @@ func (j *Client) GetAllEmailsInMailbox(accountId string, mailboxId string, //NOS
|
||||
|
||||
cmd, err := j.request(ctx, NS_MAIL, invocations...)
|
||||
if err != nil {
|
||||
return Emails{}, "", "", "", err
|
||||
return EmailSearchResults{}, "", "", "", err
|
||||
}
|
||||
|
||||
return command(j, ctx, cmd, func(body *Response) (Emails, State, Error) {
|
||||
return command(j, ctx, cmd, func(body *Response) (EmailSearchResults, State, Error) {
|
||||
var queryResponse EmailQueryResponse
|
||||
err = retrieveQuery(ctx, body, query, "0", &queryResponse)
|
||||
if err != nil {
|
||||
return Emails{}, "", err
|
||||
return EmailSearchResults{}, "", err
|
||||
}
|
||||
var getResponse EmailGetResponse
|
||||
err = retrieveGet(ctx, body, get, "1", &getResponse)
|
||||
if err != nil {
|
||||
logger.Error().Err(err).Send()
|
||||
return Emails{}, "", err
|
||||
return EmailSearchResults{}, "", err
|
||||
}
|
||||
|
||||
if withThreads {
|
||||
var thread ThreadGetResponse
|
||||
err = retrieveGet(ctx, body, threads, "2", &thread)
|
||||
if err != nil {
|
||||
return Emails{}, "", err
|
||||
return EmailSearchResults{}, "", err
|
||||
}
|
||||
setThreadSize(&thread, getResponse.List)
|
||||
}
|
||||
|
||||
return Emails{
|
||||
Emails: getResponse.List,
|
||||
Total: queryResponse.Total,
|
||||
Limit: queryResponse.Limit,
|
||||
Offset: queryResponse.Position,
|
||||
return EmailSearchResults{
|
||||
Results: getResponse.List,
|
||||
CanCalculateChanges: queryResponse.CanCalculateChanges,
|
||||
Position: queryResponse.Position,
|
||||
Limit: queryResponse.Limit,
|
||||
Total: uintPtr(queryResponse.Total),
|
||||
}, queryResponse.QueryState, nil
|
||||
})
|
||||
}
|
||||
@@ -293,17 +291,11 @@ type SearchSnippetWithMeta struct {
|
||||
SearchSnippet
|
||||
}
|
||||
|
||||
type EmailSnippetQueryResult struct {
|
||||
Snippets []SearchSnippetWithMeta `json:"snippets,omitempty"`
|
||||
Total uint `json:"total"`
|
||||
Limit uint `json:"limit,omitzero"`
|
||||
Position uint `json:"position,omitzero"`
|
||||
QueryState State `json:"queryState"`
|
||||
}
|
||||
type EmailSnippetSearchResults SearchResultsTemplate[SearchSnippetWithMeta]
|
||||
|
||||
func (j *Client) QueryEmailSnippets(accountIds []string, //NOSONAR
|
||||
filter EmailFilterElement, offset int, limit uint,
|
||||
ctx Context) (map[string]EmailSnippetQueryResult, SessionState, State, Language, Error) {
|
||||
ctx Context) (map[string]EmailSnippetSearchResults, SessionState, State, Language, Error) {
|
||||
logger := j.loggerParams("QueryEmailSnippets", ctx, func(z zerolog.Context) zerolog.Context {
|
||||
return z.Uint(logLimit, limit).Int(logOffset, offset)
|
||||
})
|
||||
@@ -358,8 +350,9 @@ func (j *Client) QueryEmailSnippets(accountIds []string, //NOSONAR
|
||||
return nil, "", "", "", err
|
||||
}
|
||||
|
||||
return command(j, ctx, cmd, func(body *Response) (map[string]EmailSnippetQueryResult, State, Error) {
|
||||
results := make(map[string]EmailSnippetQueryResult, len(uniqueAccountIds))
|
||||
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))
|
||||
for _, accountId := range uniqueAccountIds {
|
||||
var queryResponse EmailQueryResponse
|
||||
err = retrieveResponseMatchParameters(ctx, body, CommandEmailQuery, mcid(accountId, "0"), &queryResponse)
|
||||
@@ -400,15 +393,17 @@ func (j *Client) QueryEmailSnippets(accountIds []string, //NOSONAR
|
||||
i++
|
||||
}
|
||||
|
||||
results[accountId] = EmailSnippetQueryResult{
|
||||
Snippets: snippets,
|
||||
Total: queryResponse.Total,
|
||||
Limit: queryResponse.Limit,
|
||||
Position: queryResponse.Position,
|
||||
QueryState: queryResponse.QueryState,
|
||||
states[accountId] = queryResponse.QueryState
|
||||
|
||||
results[accountId] = EmailSnippetSearchResults{
|
||||
Results: snippets,
|
||||
CanCalculateChanges: queryResponse.CanCalculateChanges,
|
||||
Total: uintPtr(queryResponse.Total),
|
||||
Limit: queryResponse.Limit,
|
||||
Position: queryResponse.Position,
|
||||
}
|
||||
}
|
||||
return results, squashStateFunc(results, func(r EmailSnippetQueryResult) State { return r.QueryState }), nil
|
||||
return results, squashState(states), nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -775,24 +770,15 @@ func (j *Client) UpdateEmails(accountId string, updates map[string]EmailUpdate,
|
||||
})
|
||||
}
|
||||
|
||||
func (j *Client) DeleteEmails(accountId string, destroy []string, ctx Context) (map[string]SetError, SessionState, State, Language, Error) {
|
||||
set := EmailSetCommand{
|
||||
AccountId: accountId,
|
||||
Destroy: destroy,
|
||||
}
|
||||
cmd, err := j.request(ctx, NS_MAIL, invocation(set, "0"))
|
||||
if err != nil {
|
||||
return nil, "", "", "", err
|
||||
}
|
||||
|
||||
return command(j, ctx, cmd, func(body *Response) (map[string]SetError, State, Error) {
|
||||
var setResponse EmailSetResponse
|
||||
err = retrieveSet(ctx, body, set, "0", &setResponse)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return setResponse.NotDestroyed, setResponse.NewState, nil
|
||||
})
|
||||
func (j *Client) DeleteEmails(accountId string, destroyIds []string, ctx Context) (map[string]SetError, SessionState, State, Language, Error) {
|
||||
return destroy(j, "DeleteEmails", EmailType,
|
||||
func(accountId string, destroy []string) EmailSetCommand {
|
||||
return EmailSetCommand{AccountId: accountId, Destroy: destroy}
|
||||
},
|
||||
EmailSetResponse{},
|
||||
accountId, destroyIds,
|
||||
ctx,
|
||||
)
|
||||
}
|
||||
|
||||
type SubmittedEmail struct {
|
||||
@@ -1109,7 +1095,7 @@ type EmailSubmissionChanges = ChangesTemplate[EmailSubmission]
|
||||
// @api:tags email,changes
|
||||
func (j *Client) GetEmailSubmissionChanges(accountId string, sinceState State, maxChanges uint,
|
||||
ctx Context) (EmailSubmissionChanges, SessionState, State, Language, Error) {
|
||||
return changes(j, "GetEmailSubmissionChanges", NS_MAIL_SUBMISSION,
|
||||
return changes(j, "GetEmailSubmissionChanges", EmailSubmissionType,
|
||||
func() EmailSubmissionChangesCommand {
|
||||
return EmailSubmissionChangesCommand{AccountId: accountId, SinceState: sinceState, MaxChanges: uintPtr(maxChanges)}
|
||||
},
|
||||
|
||||
105
pkg/jmap/api_event.go
Normal file
105
pkg/jmap/api_event.go
Normal file
@@ -0,0 +1,105 @@
|
||||
package jmap
|
||||
|
||||
var NS_CALENDAR_EVENTS = ns(JmapCalendars)
|
||||
|
||||
type CalendarEventSearchResults SearchResultsTemplate[CalendarEvent]
|
||||
|
||||
var _ SearchResults[CalendarEvent] = CalendarEventSearchResults{}
|
||||
|
||||
func (r CalendarEventSearchResults) GetResults() []CalendarEvent { return r.Results }
|
||||
func (r CalendarEventSearchResults) GetCanCalculateChanges() bool { return r.CanCalculateChanges }
|
||||
func (r CalendarEventSearchResults) GetPosition() uint { return r.Position }
|
||||
func (r CalendarEventSearchResults) GetLimit() uint { return r.Limit }
|
||||
func (r CalendarEventSearchResults) GetTotal() *uint { return r.Total }
|
||||
|
||||
func (j *Client) QueryCalendarEvents(accountIds []string, //NOSONAR
|
||||
filter CalendarEventFilterElement, sortBy []CalendarEventComparator,
|
||||
position int, limit uint, calculateTotal bool,
|
||||
ctx Context) (map[string]CalendarEventSearchResults, SessionState, State, Language, Error) {
|
||||
return queryN(j, "QueryCalendarEvents", CalendarEventType,
|
||||
[]CalendarEventComparator{{Property: CalendarEventPropertyStart, IsAscending: false}},
|
||||
func(accountId string, filter CalendarEventFilterElement, sortBy []CalendarEventComparator, position int, limit uint) CalendarEventQueryCommand {
|
||||
return CalendarEventQueryCommand{AccountId: accountId, Filter: filter, Sort: sortBy, Position: position, Limit: uintPtr(limit), CalculateTotal: calculateTotal}
|
||||
},
|
||||
func(accountId string, cmd Command, path string, rof string) CalendarEventGetRefCommand {
|
||||
return CalendarEventGetRefCommand{AccountId: accountId, IdsRef: &ResultReference{Name: cmd, Path: path, ResultOf: rof}}
|
||||
},
|
||||
func(query CalendarEventQueryResponse, get CalendarEventGetResponse) CalendarEventSearchResults {
|
||||
return CalendarEventSearchResults{
|
||||
Results: get.List,
|
||||
CanCalculateChanges: query.CanCalculateChanges,
|
||||
Position: query.Position,
|
||||
Total: uintPtrIf(query.Total, calculateTotal),
|
||||
Limit: query.Limit,
|
||||
}
|
||||
},
|
||||
accountIds,
|
||||
filter, sortBy, limit, position, ctx,
|
||||
)
|
||||
}
|
||||
|
||||
type CalendarEventChanges = ChangesTemplate[CalendarEvent]
|
||||
|
||||
// Retrieve the changes in Calendar Events since a given State.
|
||||
// @api:tags event,changes
|
||||
func (j *Client) GetCalendarEventChanges(accountId string, sinceState State, maxChanges uint,
|
||||
ctx Context) (CalendarEventChanges, SessionState, State, Language, Error) {
|
||||
return changes(j, "GetCalendarEventChanges", CalendarEventType,
|
||||
func() CalendarEventChangesCommand {
|
||||
return CalendarEventChangesCommand{AccountId: accountId, SinceState: sinceState, MaxChanges: uintPtr(maxChanges)}
|
||||
},
|
||||
CalendarEventChangesResponse{},
|
||||
func(path string, rof string) CalendarEventGetRefCommand {
|
||||
return CalendarEventGetRefCommand{
|
||||
AccountId: accountId,
|
||||
IdsRef: &ResultReference{
|
||||
Name: CommandCalendarEventChanges,
|
||||
Path: path,
|
||||
ResultOf: rof,
|
||||
},
|
||||
}
|
||||
},
|
||||
func(resp CalendarEventGetResponse) []CalendarEvent { return resp.List },
|
||||
func(oldState, newState State, hasMoreChanges bool, created, updated []CalendarEvent, destroyed []string) CalendarEventChanges {
|
||||
return CalendarEventChanges{
|
||||
OldState: oldState,
|
||||
NewState: newState,
|
||||
HasMoreChanges: hasMoreChanges,
|
||||
Created: created,
|
||||
Updated: updated,
|
||||
Destroyed: destroyed,
|
||||
}
|
||||
},
|
||||
ctx,
|
||||
)
|
||||
}
|
||||
|
||||
func (j *Client) CreateCalendarEvent(accountId string, event CalendarEvent, ctx Context) (*CalendarEvent, SessionState, State, Language, Error) {
|
||||
return create(j, "CreateCalendarEvent", CalendarEventType,
|
||||
func(accountId string, create map[string]CalendarEvent) CalendarEventSetCommand {
|
||||
return CalendarEventSetCommand{AccountId: accountId, Create: create}
|
||||
},
|
||||
func(accountId string, ref string) CalendarEventGetCommand {
|
||||
return CalendarEventGetCommand{AccountId: accountId, Ids: []string{ref}}
|
||||
},
|
||||
func(resp CalendarEventSetResponse) map[string]*CalendarEvent {
|
||||
return resp.Created
|
||||
},
|
||||
func(resp CalendarEventGetResponse) []CalendarEvent {
|
||||
return resp.List
|
||||
},
|
||||
accountId, event,
|
||||
ctx,
|
||||
)
|
||||
}
|
||||
|
||||
func (j *Client) DeleteCalendarEvent(accountId string, destroyIds []string, ctx Context) (map[string]SetError, SessionState, State, Language, Error) {
|
||||
return destroy(j, "DeleteCalendarEvent", CalendarEventType,
|
||||
func(accountId string, destroy []string) CalendarEventSetCommand {
|
||||
return CalendarEventSetCommand{AccountId: accountId, Destroy: destroy}
|
||||
},
|
||||
CalendarEventSetResponse{},
|
||||
accountId, destroyIds,
|
||||
ctx,
|
||||
)
|
||||
}
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
var NS_IDENTITY = ns(JmapMail)
|
||||
|
||||
func (j *Client) GetAllIdentities(accountId string, ctx Context) ([]Identity, SessionState, State, Language, Error) {
|
||||
return getA(j, "GetAllIdentities", NS_IDENTITY,
|
||||
return getA(j, "GetAllIdentities", IdentityType,
|
||||
func(accountId string, ids []string) IdentityGetCommand {
|
||||
return IdentityGetCommand{AccountId: accountId}
|
||||
},
|
||||
@@ -20,7 +20,7 @@ func (j *Client) GetAllIdentities(accountId string, ctx Context) ([]Identity, Se
|
||||
}
|
||||
|
||||
func (j *Client) GetIdentities(accountId string, identityIds []string, ctx Context) ([]Identity, SessionState, State, Language, Error) {
|
||||
return getA(j, "GetIdentities", NS_IDENTITY,
|
||||
return getA(j, "GetIdentities", IdentityType,
|
||||
func(accountId string, ids []string) IdentityGetCommand {
|
||||
return IdentityGetCommand{AccountId: accountId, Ids: ids}
|
||||
},
|
||||
@@ -31,7 +31,7 @@ func (j *Client) GetIdentities(accountId string, identityIds []string, ctx Conte
|
||||
}
|
||||
|
||||
func (j *Client) GetIdentitiesForAllAccounts(accountIds []string, ctx Context) (map[string][]Identity, SessionState, State, Language, Error) {
|
||||
return getN(j, "GetIdentitiesForAllAccounts", NS_IDENTITY,
|
||||
return getN(j, "GetIdentitiesForAllAccounts", IdentityType,
|
||||
func(accountId string, ids []string) IdentityGetCommand {
|
||||
return IdentityGetCommand{AccountId: accountId}
|
||||
},
|
||||
@@ -96,7 +96,7 @@ func (j *Client) GetIdentitiesAndMailboxes(mailboxAccountId string, accountIds [
|
||||
}
|
||||
|
||||
func (j *Client) CreateIdentity(accountId string, identity IdentityChange, ctx Context) (*Identity, SessionState, State, Language, Error) {
|
||||
return create(j, "CreateIdentity", NS_IDENTITY,
|
||||
return create(j, "CreateIdentity", IdentityType,
|
||||
func(accountId string, create map[string]IdentityChange) IdentitySetCommand {
|
||||
return IdentitySetCommand{AccountId: accountId, Create: create}
|
||||
},
|
||||
@@ -115,7 +115,7 @@ func (j *Client) CreateIdentity(accountId string, identity IdentityChange, ctx C
|
||||
}
|
||||
|
||||
func (j *Client) UpdateIdentity(accountId string, id string, changes IdentityChange, ctx Context) (Identity, SessionState, State, Language, Error) {
|
||||
return update(j, "UpdateIdentity", NS_IDENTITY,
|
||||
return update(j, "UpdateIdentity", IdentityType,
|
||||
func(update map[string]PatchObject) IdentitySetCommand {
|
||||
return IdentitySetCommand{AccountId: accountId, Update: update}
|
||||
},
|
||||
@@ -130,7 +130,7 @@ func (j *Client) UpdateIdentity(accountId string, id string, changes IdentityCha
|
||||
}
|
||||
|
||||
func (j *Client) DeleteIdentity(accountId string, destroyIds []string, ctx Context) (map[string]SetError, SessionState, State, Language, Error) {
|
||||
return destroy(j, "DeleteIdentity", NS_IDENTITY,
|
||||
return destroy(j, "DeleteIdentity", IdentityType,
|
||||
func(accountId string, destroy []string) IdentitySetCommand {
|
||||
return IdentitySetCommand{AccountId: accountId, Destroy: destroyIds}
|
||||
},
|
||||
@@ -146,7 +146,7 @@ type IdentityChanges = ChangesTemplate[Identity]
|
||||
// @api:tags email,changes
|
||||
func (j *Client) GetIdentityChanges(accountId string, sinceState State, maxChanges uint,
|
||||
ctx Context) (IdentityChanges, SessionState, State, Language, Error) {
|
||||
return changes(j, "GetIdentityChanges", NS_IDENTITY,
|
||||
return changes(j, "GetIdentityChanges", IdentityType,
|
||||
func() IdentityChangesCommand {
|
||||
return IdentityChangesCommand{AccountId: accountId, SinceState: sinceState, MaxChanges: uintPtr(maxChanges)}
|
||||
},
|
||||
|
||||
@@ -9,32 +9,27 @@ import (
|
||||
var NS_MAILBOX = ns(JmapMail)
|
||||
|
||||
func (j *Client) GetMailbox(accountId string, ids []string, ctx Context) (MailboxGetResponse, SessionState, State, Language, Error) {
|
||||
/*
|
||||
return get(j, "GetMailbox", NS_MAILBOX,
|
||||
func(accountId string, ids []string) MailboxGetCommand {
|
||||
return MailboxGetCommand{AccountId: accountId, Ids: ids}
|
||||
},
|
||||
MailboxGetResponse{},
|
||||
identity1,
|
||||
accountId, session, ctx, logger, acceptLanguage, ids,
|
||||
)
|
||||
*/
|
||||
|
||||
return fget[Mailboxes](MAILBOX, j, "GetMailbox", accountId, ids, ctx)
|
||||
return get(j, "GetMailbox", MailboxType,
|
||||
func(accountId string, ids []string) MailboxGetCommand {
|
||||
return MailboxGetCommand{AccountId: accountId, Ids: ids}
|
||||
},
|
||||
MailboxGetResponse{},
|
||||
identity1,
|
||||
accountId, ids,
|
||||
ctx,
|
||||
)
|
||||
}
|
||||
|
||||
func (j *Client) GetAllMailboxes(accountIds []string, ctx Context) (map[string][]Mailbox, SessionState, State, Language, Error) {
|
||||
/*
|
||||
return getAN(j, "GetAllMailboxes", NS_MAILBOX,
|
||||
func(accountId string, ids []string) MailboxGetCommand {
|
||||
return MailboxGetCommand{AccountId: accountId}
|
||||
},
|
||||
MailboxGetResponse{},
|
||||
identity1,
|
||||
accountIds, session, ctx, logger, acceptLanguage, []string{},
|
||||
)
|
||||
*/
|
||||
return fgetAN[Mailboxes](MAILBOX, j, "GetAllMailboxes", identity1, accountIds, []string{}, ctx)
|
||||
return getAN(j, "GetAllMailboxes", MailboxType,
|
||||
func(accountId string, ids []string) MailboxGetCommand {
|
||||
return MailboxGetCommand{AccountId: accountId}
|
||||
},
|
||||
MailboxGetResponse{},
|
||||
identity1,
|
||||
accountIds, []string{},
|
||||
ctx,
|
||||
)
|
||||
}
|
||||
|
||||
func (j *Client) SearchMailboxes(accountIds []string, filter MailboxFilterElement, ctx Context) (map[string][]Mailbox, SessionState, State, Language, Error) {
|
||||
@@ -135,7 +130,7 @@ func newMailboxChanges(oldState, newState State, hasMoreChanges bool, created, u
|
||||
// @apidoc mailboxes,changes
|
||||
func (j *Client) GetMailboxChanges(accountId string, sinceState State, maxChanges uint,
|
||||
ctx Context) (MailboxChanges, SessionState, State, Language, Error) {
|
||||
return changesA(j, "GetMailboxChanges", NS_MAILBOX,
|
||||
return changesA(j, "GetMailboxChanges", MailboxType,
|
||||
func() MailboxChangesCommand {
|
||||
return MailboxChangesCommand{AccountId: accountId, SinceState: sinceState, MaxChanges: uintPtr(maxChanges)}
|
||||
},
|
||||
@@ -161,7 +156,7 @@ func (j *Client) GetMailboxChanges(accountId string, sinceState State, maxChange
|
||||
func (j *Client) GetMailboxChangesForMultipleAccounts(accountIds []string, //NOSONAR
|
||||
sinceStateMap map[string]State, maxChanges uint,
|
||||
ctx Context) (map[string]MailboxChanges, SessionState, State, Language, Error) {
|
||||
return changesN(j, "GetMailboxChangesForMultipleAccounts", NS_MAILBOX,
|
||||
return changesN(j, "GetMailboxChangesForMultipleAccounts", MailboxType,
|
||||
accountIds, sinceStateMap,
|
||||
func(accountId string, state State) MailboxChangesCommand {
|
||||
return MailboxChangesCommand{AccountId: accountId, SinceState: state, MaxChanges: uintPtr(maxChanges)}
|
||||
@@ -179,59 +174,22 @@ func (j *Client) GetMailboxChangesForMultipleAccounts(accountIds []string, //NOS
|
||||
}
|
||||
|
||||
func (j *Client) GetMailboxRolesForMultipleAccounts(accountIds []string, ctx Context) (map[string][]string, SessionState, State, Language, Error) {
|
||||
logger := j.logger("GetMailboxRolesForMultipleAccounts", ctx)
|
||||
ctx = ctx.WithLogger(logger)
|
||||
|
||||
uniqueAccountIds := structs.Uniq(accountIds)
|
||||
n := len(uniqueAccountIds)
|
||||
if n < 1 {
|
||||
return nil, "", "", "", nil
|
||||
}
|
||||
|
||||
t := true
|
||||
|
||||
invocations := make([]Invocation, n*2)
|
||||
for i, accountId := range uniqueAccountIds {
|
||||
invocations[i*2+0] = invocation(MailboxQueryCommand{
|
||||
AccountId: accountId,
|
||||
Filter: MailboxFilterCondition{
|
||||
HasAnyRole: &t,
|
||||
},
|
||||
}, mcid(accountId, "0"))
|
||||
invocations[i*2+1] = invocation(MailboxGetRefCommand{
|
||||
AccountId: accountId,
|
||||
IdsRef: &ResultReference{
|
||||
ResultOf: mcid(accountId, "0"),
|
||||
Name: CommandMailboxQuery,
|
||||
Path: "/ids",
|
||||
},
|
||||
}, mcid(accountId, "1"))
|
||||
}
|
||||
|
||||
cmd, err := j.request(ctx, NS_MAILBOX, invocations...)
|
||||
if err != nil {
|
||||
return nil, "", "", "", 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)
|
||||
for _, accountId := range uniqueAccountIds {
|
||||
var getResponse MailboxGetResponse
|
||||
err = retrieveResponseMatchParameters(ctx, body, CommandMailboxGet, mcid(accountId, "1"), &getResponse)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
roles := make([]string, len(getResponse.List))
|
||||
for i, mailbox := range getResponse.List {
|
||||
roles[i] = mailbox.Role
|
||||
}
|
||||
return queryN(j, "GetMailboxRolesForMultipleAccounts", MailboxType,
|
||||
[]MailboxComparator{{Property: MailboxPropertySortOrder, IsAscending: true}},
|
||||
func(accountId string, filter MailboxFilterCondition, sortBy []MailboxComparator, _ int, _ uint) MailboxQueryCommand {
|
||||
return MailboxQueryCommand{AccountId: accountId, Filter: filter, Sort: sortBy, SortAsTree: false, FilterAsTree: false, Position: 0, Limit: nil, CalculateTotal: false}
|
||||
},
|
||||
func(accountId string, cmd Command, path, rof string) MailboxGetRefCommand {
|
||||
return MailboxGetRefCommand{AccountId: accountId, IdsRef: &ResultReference{Name: cmd, Path: path, ResultOf: rof}}
|
||||
},
|
||||
func(_ MailboxQueryResponse, get MailboxGetResponse) []string {
|
||||
roles := structs.Map(get.List, func(m Mailbox) string { return m.Role })
|
||||
slices.Sort(roles)
|
||||
resp[accountId] = roles
|
||||
stateByAccountId[accountId] = getResponse.State
|
||||
}
|
||||
return resp, squashState(stateByAccountId), nil
|
||||
})
|
||||
return roles
|
||||
},
|
||||
accountIds, MailboxFilterCondition{HasAnyRole: boolPtr(true)}, nil, 0, 0,
|
||||
ctx,
|
||||
)
|
||||
}
|
||||
|
||||
func (j *Client) GetInboxNameForMultipleAccounts(accountIds []string, ctx Context) (map[string]string, SessionState, State, Language, Error) {
|
||||
@@ -286,7 +244,7 @@ func (j *Client) GetInboxNameForMultipleAccounts(accountIds []string, ctx Contex
|
||||
|
||||
func (j *Client) UpdateMailbox(accountId string, mailboxId string, change MailboxChange, //NOSONAR
|
||||
ctx Context) (Mailbox, SessionState, State, Language, Error) {
|
||||
return update(j, "UpdateMailbox", NS_MAILBOX,
|
||||
return update(j, "UpdateMailbox", MailboxType,
|
||||
func(update map[string]PatchObject) MailboxSetCommand {
|
||||
return MailboxSetCommand{AccountId: accountId, Update: update}
|
||||
},
|
||||
@@ -301,7 +259,7 @@ func (j *Client) UpdateMailbox(accountId string, mailboxId string, change Mailbo
|
||||
}
|
||||
|
||||
func (j *Client) CreateMailbox(accountId string, mailbox MailboxChange, ctx Context) (*Mailbox, SessionState, State, Language, Error) {
|
||||
return create(j, "CreateMailbox", NS_MAILBOX,
|
||||
return create(j, "CreateMailbox", MailboxType,
|
||||
func(accountId string, create map[string]MailboxChange) MailboxSetCommand {
|
||||
return MailboxSetCommand{AccountId: accountId, Create: create}
|
||||
},
|
||||
@@ -320,7 +278,7 @@ func (j *Client) CreateMailbox(accountId string, mailbox MailboxChange, ctx Cont
|
||||
}
|
||||
|
||||
func (j *Client) DeleteMailboxes(accountId string, destroyIds []string, ctx Context) (map[string]SetError, SessionState, State, Language, Error) {
|
||||
return destroy(j, "DeleteMailboxes", NS_MAILBOX,
|
||||
return destroy(j, "DeleteMailboxes", MailboxType,
|
||||
func(accountId string, destroy []string) MailboxSetCommand {
|
||||
return MailboxSetCommand{AccountId: accountId, Destroy: destroyIds}
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@ package jmap
|
||||
var NS_PRINCIPALS = ns(JmapPrincipals)
|
||||
|
||||
func (j *Client) GetPrincipals(accountId string, ids []string, ctx Context) (PrincipalGetResponse, SessionState, State, Language, Error) {
|
||||
return get(j, "GetPrincipals", NS_PRINCIPALS,
|
||||
return get(j, "GetPrincipals", PrincipalType,
|
||||
func(accountId string, ids []string) PrincipalGetCommand {
|
||||
return PrincipalGetCommand{AccountId: accountId, Ids: ids}
|
||||
},
|
||||
@@ -28,7 +28,7 @@ func (j *Client) QueryPrincipals(accountId string,
|
||||
filter PrincipalFilterElement, sortBy []PrincipalComparator,
|
||||
position uint, limit uint, calculateTotal bool,
|
||||
ctx Context) (PrincipalSearchResults, SessionState, State, Language, Error) {
|
||||
return query(j, "QueryPrincipals", NS_PRINCIPALS,
|
||||
return query(j, "QueryPrincipals", PrincipalType,
|
||||
[]PrincipalComparator{{Property: PrincipalPropertyName, IsAscending: true}},
|
||||
func(filter PrincipalFilterElement, sortBy []PrincipalComparator, position uint, limit uint) PrincipalQueryCommand {
|
||||
return PrincipalQueryCommand{AccountId: accountId, Filter: filter, Sort: sortBy, Position: position, Limit: limit, CalculateTotal: calculateTotal}
|
||||
|
||||
@@ -3,7 +3,7 @@ package jmap
|
||||
var NS_QUOTA = ns(JmapQuota)
|
||||
|
||||
func (j *Client) GetQuotas(accountIds []string, ctx Context) (map[string]QuotaGetResponse, SessionState, State, Language, Error) {
|
||||
return getN(j, "GetQuotas", NS_QUOTA,
|
||||
return getN(j, "GetQuotas", QuotaType,
|
||||
func(accountId string, ids []string) QuotaGetCommand {
|
||||
return QuotaGetCommand{AccountId: accountId}
|
||||
},
|
||||
@@ -21,7 +21,7 @@ type QuotaChanges = ChangesTemplate[Quota]
|
||||
// @api:tags quota,changes
|
||||
func (j *Client) GetQuotaChanges(accountId string, sinceState State, maxChanges uint,
|
||||
ctx Context) (QuotaChanges, SessionState, State, Language, Error) {
|
||||
return changesA(j, "GetQuotaChanges", NS_QUOTA,
|
||||
return changesA(j, "GetQuotaChanges", QuotaType,
|
||||
func() QuotaChangesCommand {
|
||||
return QuotaChangesCommand{AccountId: accountId, SinceState: sinceState, MaxChanges: uintPtr(maxChanges)}
|
||||
},
|
||||
@@ -53,7 +53,7 @@ func (j *Client) GetQuotaChanges(accountId string, sinceState State, maxChanges
|
||||
|
||||
func (j *Client) GetQuotaUsageChanges(accountId string, sinceState State, maxChanges uint,
|
||||
ctx Context) (QuotaChanges, SessionState, State, Language, Error) {
|
||||
return updates(j, "GetQuotaUsageChanges", NS_QUOTA,
|
||||
return updates(j, "GetQuotaUsageChanges", QuotaType,
|
||||
func() QuotaChangesCommand {
|
||||
return QuotaChangesCommand{AccountId: accountId, SinceState: sinceState, MaxChanges: uintPtr(maxChanges)}
|
||||
},
|
||||
|
||||
@@ -12,7 +12,7 @@ const (
|
||||
)
|
||||
|
||||
func (j *Client) GetVacationResponse(accountId string, ctx Context) (VacationResponseGetResponse, SessionState, State, Language, Error) {
|
||||
return get(j, "GetVacationResponse", NS_VACATION,
|
||||
return get(j, "GetVacationResponse", VacationResponseType,
|
||||
func(accountId string, ids []string) VacationResponseGetCommand {
|
||||
return VacationResponseGetCommand{AccountId: accountId}
|
||||
},
|
||||
|
||||
@@ -6,12 +6,35 @@ import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"iter"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/tools/go/packages"
|
||||
)
|
||||
|
||||
func valuesOf(p *packages.Package) iter.Seq[*ast.ValueSpec] { //NOSONAR
|
||||
return func(yield func(*ast.ValueSpec) bool) {
|
||||
for _, syn := range p.Syntax {
|
||||
for _, decl := range syn.Decls {
|
||||
g, ok := decl.(*ast.GenDecl)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
for _, s := range g.Specs {
|
||||
e, ok := s.(*ast.ValueSpec)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if !yield(e) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func parseConsts(pkgID string, suffix string, typeName string) (map[string]string, error) { //NOSONAR
|
||||
result := map[string]string{}
|
||||
{
|
||||
@@ -31,29 +54,19 @@ func parseConsts(pkgID string, suffix string, typeName string) (map[string]strin
|
||||
if p.ID != pkgID {
|
||||
continue
|
||||
}
|
||||
for _, syn := range p.Syntax {
|
||||
for _, decl := range syn.Decls {
|
||||
switch g := decl.(type) {
|
||||
case *ast.GenDecl:
|
||||
for _, s := range g.Specs {
|
||||
switch e := s.(type) {
|
||||
case *ast.ValueSpec:
|
||||
for i, ident := range e.Names {
|
||||
if ident != nil && strings.HasSuffix(ident.Name, suffix) {
|
||||
value := e.Values[i]
|
||||
switch c := value.(type) {
|
||||
case *ast.CallExpr:
|
||||
switch f := c.Fun.(type) {
|
||||
case *ast.Ident:
|
||||
if f.Name == typeName {
|
||||
switch a := c.Args[0].(type) {
|
||||
case *ast.BasicLit:
|
||||
if a.Kind == token.STRING {
|
||||
result[ident.Name] = strings.Trim(a.Value, `"`)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for v := range valuesOf(p) {
|
||||
for i, ident := range v.Names {
|
||||
if ident != nil && strings.HasSuffix(ident.Name, suffix) {
|
||||
value := v.Values[i]
|
||||
switch c := value.(type) {
|
||||
case *ast.CallExpr:
|
||||
switch f := c.Fun.(type) {
|
||||
case *ast.Ident:
|
||||
if f.Name == typeName {
|
||||
switch a := c.Args[0].(type) {
|
||||
case *ast.BasicLit:
|
||||
if a.Kind == token.STRING {
|
||||
result[ident.Name] = strings.Trim(a.Value, `"`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
@@ -577,7 +578,7 @@ type HttpWsClient struct {
|
||||
func (w *HttpWsClient) readPump() { //NOSONAR
|
||||
logger := log.From(w.logger.With().Str("username", w.username))
|
||||
defer func() {
|
||||
if err := w.c.Close(); err != nil {
|
||||
if err := w.c.Close(); err != nil && !errors.Is(err, net.ErrClosed) {
|
||||
logger.Warn().Err(err).Msg("failed to close websocket connection")
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -126,7 +126,7 @@ func TestEvents(t *testing.T) {
|
||||
results := m[accountId]
|
||||
require.Equal(len(results.Results), int(page))
|
||||
require.Equal(limit, results.Limit)
|
||||
require.Equal(position, results.Position)
|
||||
require.Equal(uint(position), results.Position)
|
||||
require.Equal(true, results.CanCalculateChanges)
|
||||
require.NotNil(results.Total)
|
||||
require.Equal(count, *results.Total)
|
||||
@@ -107,7 +107,8 @@ func TestContacts(t *testing.T) {
|
||||
require.Len(results.Results, int(count))
|
||||
require.Equal(uint(0), results.Limit)
|
||||
require.Equal(uint(0), results.Position)
|
||||
require.Equal(uint(0), results.Total)
|
||||
require.NotNil(results.Total)
|
||||
require.Equal(count, *results.Total)
|
||||
require.Equal(true, results.CanCalculateChanges)
|
||||
|
||||
for _, actual := range results.Results {
|
||||
|
||||
@@ -85,8 +85,8 @@ func TestEmails(t *testing.T) {
|
||||
require.NoError(err)
|
||||
require.Equal(session.State, sessionState)
|
||||
|
||||
require.Equalf(threads, len(resp.Emails), "the number of collapsed emails in the inbox is expected to be %v, but is actually %v", threads, len(resp.Emails))
|
||||
for _, e := range resp.Emails {
|
||||
require.Equalf(threads, len(resp.Results), "the number of collapsed emails in the inbox is expected to be %v, but is actually %v", threads, len(resp.Results))
|
||||
for _, e := range resp.Results {
|
||||
require.Len(e.MessageId, 1)
|
||||
expectation, ok := mailsByMessageId[e.MessageId[0]]
|
||||
require.True(ok)
|
||||
@@ -99,8 +99,8 @@ func TestEmails(t *testing.T) {
|
||||
require.NoError(err)
|
||||
require.Equal(session.State, sessionState)
|
||||
|
||||
require.Equalf(count, len(resp.Emails), "the number of emails in the inbox is expected to be %v, but is actually %v", count, len(resp.Emails))
|
||||
for _, e := range resp.Emails {
|
||||
require.Equalf(count, len(resp.Results), "the number of emails in the inbox is expected to be %v, but is actually %v", count, len(resp.Results))
|
||||
for _, e := range resp.Results {
|
||||
require.Len(e.MessageId, 1)
|
||||
expectation, ok := mailsByMessageId[e.MessageId[0]]
|
||||
require.True(ok)
|
||||
@@ -168,7 +168,13 @@ func TestSendingEmails(t *testing.T) {
|
||||
accountId string
|
||||
session *Session
|
||||
}{{toAccountId, toSession}, {ccAccountId, ccSession}} {
|
||||
mailboxes, _, _, _, err := s.client.GetAllMailboxes([]string{u.accountId}, ctx)
|
||||
uctx := Context{
|
||||
Session: u.session,
|
||||
Context: ctx.Context,
|
||||
Logger: ctx.Logger,
|
||||
AcceptLanguage: ctx.AcceptLanguage,
|
||||
}
|
||||
mailboxes, _, _, _, err := s.client.GetAllMailboxes([]string{u.accountId}, uctx)
|
||||
require.NoError(err)
|
||||
for _, mailbox := range mailboxes[u.accountId] {
|
||||
require.Equal(0, mailbox.TotalEmails)
|
||||
@@ -288,7 +294,13 @@ func TestSendingEmails(t *testing.T) {
|
||||
accountId string
|
||||
session *Session
|
||||
}{{to, toAccountId, toSession}, {cc, ccAccountId, ccSession}} {
|
||||
mailboxes, _, _, _, err := s.client.GetAllMailboxes([]string{r.accountId}, ctx)
|
||||
rctx := Context{
|
||||
Session: r.session,
|
||||
Context: ctx.Context,
|
||||
Logger: ctx.Logger,
|
||||
AcceptLanguage: ctx.AcceptLanguage,
|
||||
}
|
||||
mailboxes, _, _, _, err := s.client.GetAllMailboxes([]string{r.accountId}, rctx)
|
||||
require.NoError(err)
|
||||
inboxId := ""
|
||||
for _, mailbox := range mailboxes[r.accountId] {
|
||||
@@ -299,7 +311,7 @@ func TestSendingEmails(t *testing.T) {
|
||||
}
|
||||
require.NotEmpty(inboxId, "failed to find the Mailbox with the 'inbox' role for %v", r.user.name)
|
||||
|
||||
emails, _, _, _, err := s.client.QueryEmails([]string{r.accountId}, EmailFilterCondition{InMailbox: inboxId}, 0, 0, true, 0, ctx)
|
||||
emails, _, _, _, err := s.client.QueryEmails([]string{r.accountId}, EmailFilterCondition{InMailbox: inboxId}, 0, 0, true, 0, rctx)
|
||||
require.NoError(err)
|
||||
require.Contains(emails, r.accountId)
|
||||
require.Len(emails[r.accountId].Emails, 1)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package jmap
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
@@ -223,7 +224,15 @@ func TestWs(t *testing.T) {
|
||||
require.Equal(state, changes.NewState)
|
||||
require.Empty(changes.Created)
|
||||
require.Len(changes.Destroyed, 2)
|
||||
require.EqualValues(emailIds, changes.Destroyed)
|
||||
{
|
||||
a := make([]string, len(emailIds))
|
||||
copy(a, emailIds)
|
||||
slices.Sort(emailIds)
|
||||
b := make([]string, len(changes.Destroyed))
|
||||
copy(b, changes.Destroyed)
|
||||
slices.Sort(changes.Destroyed)
|
||||
require.EqualValues(a, b)
|
||||
}
|
||||
require.Empty(changes.Updated)
|
||||
lastState = state
|
||||
}
|
||||
|
||||
@@ -1564,6 +1564,34 @@ var _ Idable = &Mailbox{}
|
||||
func (f Mailbox) GetObjectType() ObjectType { return MailboxType }
|
||||
func (f Mailbox) GetId() string { return f.Id }
|
||||
|
||||
const (
|
||||
MailboxPropertyId = "id"
|
||||
MailboxPropertyName = "name"
|
||||
MailboxPropertyParentId = "parentId"
|
||||
MailboxPropertyRole = "role"
|
||||
MailboxPropertySortOrder = "sortOrder"
|
||||
MailboxPropertyTotalEmails = "totalEmails"
|
||||
MailboxPropertyUnreadEmails = "unreadEmails"
|
||||
MailboxPropertyTotalThreads = "totalThreads"
|
||||
MailboxPropertyUnreadThreads = "unreadThreads"
|
||||
MailboxPropertyMyRights = "myRights"
|
||||
MailboxPropertyIsSubscribed = "isSubscribed"
|
||||
)
|
||||
|
||||
var MailboxProperties = []string{
|
||||
MailboxPropertyId,
|
||||
MailboxPropertyName,
|
||||
MailboxPropertyParentId,
|
||||
MailboxPropertyRole,
|
||||
MailboxPropertySortOrder,
|
||||
MailboxPropertyTotalEmails,
|
||||
MailboxPropertyUnreadEmails,
|
||||
MailboxPropertyTotalThreads,
|
||||
MailboxPropertyUnreadThreads,
|
||||
MailboxPropertyMyRights,
|
||||
MailboxPropertyIsSubscribed,
|
||||
}
|
||||
|
||||
type MailboxChange struct {
|
||||
// User-visible name for the Mailbox, e.g., “Inbox”.
|
||||
//
|
||||
@@ -1750,6 +1778,49 @@ type MailboxQueryCommand struct {
|
||||
Sort []MailboxComparator `json:"sort,omitempty"`
|
||||
SortAsTree bool `json:"sortAsTree,omitempty"`
|
||||
FilterAsTree bool `json:"filterAsTree,omitempty"`
|
||||
|
||||
// The zero-based index of the first id in the full list of results to return.
|
||||
//
|
||||
// If a negative value is given, it is an offset from the end of the list.
|
||||
// Specifically, the negative value MUST be added to the total number of results given
|
||||
// the filter, and if still negative, it’s clamped to 0. This is now the zero-based
|
||||
// index of the first id to return.
|
||||
//
|
||||
// If the index is greater than or equal to the total number of objects in the results
|
||||
// list, then the ids array in the response will be empty, but this is not an error.
|
||||
Position int `json:"position,omitempty"`
|
||||
|
||||
// An Email id.
|
||||
//
|
||||
// If supplied, the position argument is ignored.
|
||||
// The index of this id in the results will be used in combination with the anchorOffset
|
||||
// argument to determine the index of the first result to return.
|
||||
Anchor string `json:"anchor,omitempty"`
|
||||
|
||||
// The index of the first result to return relative to the index of the anchor,
|
||||
// if an anchor is given.
|
||||
//
|
||||
// This MAY be negative.
|
||||
//
|
||||
// For example, -1 means the object immediately preceding the anchor is the first result in
|
||||
// the list returned.
|
||||
AnchorOffset int `json:"anchorOffset,omitzero" doc:"opt" default:"0"`
|
||||
|
||||
// The maximum number of results to return.
|
||||
//
|
||||
// If null, no limit presumed.
|
||||
// The server MAY choose to enforce a maximum limit argument.
|
||||
// In this case, if a greater value is given (or if it is null), the limit is clamped
|
||||
// to the maximum; the new limit is returned with the response so the client is aware.
|
||||
//
|
||||
// If a negative value is given, the call MUST be rejected with an invalidArguments error.
|
||||
Limit *uint `json:"limit,omitempty"`
|
||||
|
||||
// Does the client wish to know the total number of results in the query?
|
||||
//
|
||||
// This may be slow and expensive for servers to calculate, particularly with complex filters,
|
||||
// so clients should take care to only request the total when needed.
|
||||
CalculateTotal bool `json:"calculateTotal,omitempty"`
|
||||
}
|
||||
|
||||
var _ QueryCommand[Mailbox] = &MailboxQueryCommand{}
|
||||
@@ -3673,6 +3744,7 @@ var _ GetResponse[Thread] = &ThreadGetResponse{}
|
||||
func (r ThreadGetResponse) GetState() State { return r.State }
|
||||
func (r ThreadGetResponse) GetNotFound() []string { return r.NotFound }
|
||||
func (r ThreadGetResponse) GetList() []Thread { return r.List }
|
||||
func (r ThreadGetResponse) GetMarker() Thread { return Thread{} }
|
||||
|
||||
type IdentityGetCommand struct {
|
||||
AccountId string `json:"accountId"`
|
||||
|
||||
@@ -806,12 +806,13 @@ func (e Exemplar) EmailBodyPart() EmailBodyPart {
|
||||
}
|
||||
}
|
||||
|
||||
func (e Exemplar) Emails() Emails {
|
||||
return Emails{
|
||||
Emails: []Email{e.Email()},
|
||||
Total: 132,
|
||||
Limit: 1,
|
||||
Offset: 5,
|
||||
func (e Exemplar) Emails() EmailSearchResults {
|
||||
return EmailSearchResults{
|
||||
Results: []Email{e.Email()},
|
||||
Total: uintPtr(132),
|
||||
Limit: 1,
|
||||
Position: 5,
|
||||
CanCalculateChanges: true,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -820,7 +821,7 @@ func (e Exemplar) EmailGetResponse() EmailGetResponse {
|
||||
AccountId: e.AccountId,
|
||||
State: "aesh2ahj",
|
||||
NotFound: []string{"ahx"},
|
||||
List: e.Emails().Emails,
|
||||
List: e.Emails().Results,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,72 +8,8 @@ import (
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
type Factory[T Foo, GETREQ GetCommand[T], GETRESP GetResponse[T], CHANGES any] interface {
|
||||
Namespaces() []JmapNamespace
|
||||
CreateGetCommand(accountId string, ids []string) GETREQ
|
||||
CreateGetResponse() GETRESP
|
||||
MapChanges(oldState, newState State, hasMoreChanges bool, created, updated []T, destroyed []string) CHANGES
|
||||
}
|
||||
|
||||
type Mailboxes string
|
||||
|
||||
const MAILBOX = Mailboxes("MAILBOX")
|
||||
|
||||
var _ Factory[Mailbox, MailboxGetCommand, MailboxGetResponse, MailboxChanges] = MAILBOX
|
||||
|
||||
func (f Mailboxes) Namespaces() []JmapNamespace {
|
||||
return NS_MAILBOX
|
||||
}
|
||||
|
||||
func (f Mailboxes) CreateGetCommand(accountId string, ids []string) MailboxGetCommand {
|
||||
return MailboxGetCommand{AccountId: accountId, Ids: ids}
|
||||
}
|
||||
|
||||
func (f Mailboxes) CreateGetResponse() MailboxGetResponse {
|
||||
return MailboxGetResponse{}
|
||||
}
|
||||
|
||||
func (f Mailboxes) MapChanges(oldState, newState State, hasMoreChanges bool, created, updated []Mailbox, destroyed []string) MailboxChanges {
|
||||
return MailboxChanges{
|
||||
OldState: oldState,
|
||||
NewState: newState,
|
||||
HasMoreChanges: hasMoreChanges,
|
||||
Created: created,
|
||||
Updated: updated,
|
||||
Destroyed: destroyed,
|
||||
}
|
||||
}
|
||||
|
||||
func fget[F Factory[T, GETREQ, GETRESP, CHANGES], T Foo, GETREQ GetCommand[T], GETRESP GetResponse[T], CHANGES any](f Factory[T, GETREQ, GETRESP, CHANGES], //NOSONAR
|
||||
client *Client, name string,
|
||||
accountId string, ids []string,
|
||||
ctx Context) (GETRESP, SessionState, State, Language, Error) {
|
||||
var getresp GETRESP
|
||||
return get(client, name, f.Namespaces(),
|
||||
f.CreateGetCommand,
|
||||
getresp,
|
||||
identity1,
|
||||
accountId, ids,
|
||||
ctx,
|
||||
)
|
||||
}
|
||||
|
||||
func fgetA[F Factory[T, GETREQ, GETRESP, CHANGES], T Foo, GETREQ GetCommand[T], GETRESP GetResponse[T], CHANGES any](f Factory[T, GETREQ, GETRESP, CHANGES], //NOSONAR
|
||||
client *Client, name string,
|
||||
accountId string, ids []string,
|
||||
ctx Context) ([]T, SessionState, State, Language, Error) {
|
||||
var getresp GETRESP
|
||||
return getA(client, name, f.Namespaces(),
|
||||
f.CreateGetCommand,
|
||||
getresp,
|
||||
accountId,
|
||||
ids,
|
||||
ctx,
|
||||
)
|
||||
}
|
||||
|
||||
func get[T Foo, GETREQ GetCommand[T], GETRESP GetResponse[T], RESP any]( //NOSONAR
|
||||
client *Client, name string, using []JmapNamespace,
|
||||
client *Client, name string, objType ObjectType,
|
||||
getCommandFactory func(string, []string) GETREQ,
|
||||
_ GETRESP,
|
||||
mapper func(GETRESP) RESP,
|
||||
@@ -83,7 +19,7 @@ func get[T Foo, GETREQ GetCommand[T], GETRESP GetResponse[T], RESP any]( //NOSON
|
||||
var zero RESP
|
||||
|
||||
get := getCommandFactory(accountId, ids)
|
||||
cmd, err := client.request(ctx, using, invocation(get, "0"))
|
||||
cmd, err := client.request(ctx, objType.Namespaces, invocation(get, "0"))
|
||||
if err != nil {
|
||||
return zero, "", "", "", err
|
||||
}
|
||||
@@ -100,35 +36,20 @@ func get[T Foo, GETREQ GetCommand[T], GETRESP GetResponse[T], RESP any]( //NOSON
|
||||
}
|
||||
|
||||
func getA[T Foo, GETREQ GetCommand[T], GETRESP GetResponse[T]]( //NOSONAR
|
||||
client *Client, name string, using []JmapNamespace,
|
||||
client *Client, name string, objType ObjectType,
|
||||
getCommandFactory func(string, []string) GETREQ,
|
||||
resp GETRESP,
|
||||
accountId string, ids []string, ctx Context) ([]T, SessionState, State, Language, Error) {
|
||||
return get(client, name, using, getCommandFactory, resp, func(r GETRESP) []T { return r.GetList() }, accountId, ids, ctx)
|
||||
}
|
||||
|
||||
func fgetAN[F Factory[T, GETREQ, GETRESP, CHANGES], T Foo, GETREQ GetCommand[T], GETRESP GetResponse[T], RESP any, CHANGES any](f Factory[T, GETREQ, GETRESP, CHANGES], //NOSONAR
|
||||
client *Client, name string,
|
||||
respMapper func(map[string][]T) RESP,
|
||||
accountIds []string, ids []string,
|
||||
ctx Context) (RESP, SessionState, State, Language, Error) {
|
||||
var getresp GETRESP
|
||||
return getAN(client, name, f.Namespaces(),
|
||||
f.CreateGetCommand,
|
||||
getresp,
|
||||
respMapper,
|
||||
accountIds, ids,
|
||||
ctx,
|
||||
)
|
||||
return get(client, name, objType, getCommandFactory, resp, func(r GETRESP) []T { return r.GetList() }, accountId, ids, ctx)
|
||||
}
|
||||
|
||||
func getAN[T Foo, GETREQ GetCommand[T], GETRESP GetResponse[T], RESP any]( //NOSONAR
|
||||
client *Client, name string, using []JmapNamespace,
|
||||
client *Client, name string, objType ObjectType,
|
||||
getCommandFactory func(string, []string) GETREQ,
|
||||
resp GETRESP,
|
||||
respMapper func(map[string][]T) RESP,
|
||||
accountIds []string, ids []string, ctx Context) (RESP, SessionState, State, Language, Error) {
|
||||
return getN(client, name, using, getCommandFactory, resp,
|
||||
return getN(client, name, objType, getCommandFactory, resp,
|
||||
func(r GETRESP) []T { return r.GetList() },
|
||||
respMapper,
|
||||
accountIds, ids,
|
||||
@@ -137,7 +58,7 @@ 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
|
||||
client *Client, name string, using []JmapNamespace,
|
||||
client *Client, name string, objType ObjectType,
|
||||
getCommandFactory func(string, []string) GETREQ,
|
||||
_ GETRESP,
|
||||
itemMapper func(GETRESP) ITEM,
|
||||
@@ -158,7 +79,7 @@ func getN[T Foo, ITEM any, GETREQ GetCommand[T], GETRESP GetResponse[T], RESP an
|
||||
invocations[i] = invocation(get, mcid(accountId, "0"))
|
||||
}
|
||||
|
||||
cmd, err := client.request(ctx, using, invocations...)
|
||||
cmd, err := client.request(ctx, objType.Namespaces, invocations...)
|
||||
if err != nil {
|
||||
return zero, "", "", "", err
|
||||
}
|
||||
@@ -180,7 +101,7 @@ 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, using []JmapNamespace,
|
||||
client *Client, name string, objType ObjectType,
|
||||
setCommandFactory func(string, map[string]C) SETREQ,
|
||||
getCommandFactory func(string, string) GETREQ,
|
||||
createdMapper func(SETRESP) map[string]*T,
|
||||
@@ -193,7 +114,7 @@ func create[T Foo, C any, SETREQ SetCommand[T], GETREQ GetCommand[T], SETRESP Se
|
||||
createMap := map[string]C{"c": create}
|
||||
get := getCommandFactory(accountId, "#c")
|
||||
set := setCommandFactory(accountId, createMap)
|
||||
cmd, err := client.request(ctx, using,
|
||||
cmd, err := client.request(ctx, objType.Namespaces,
|
||||
invocation(set, "0"),
|
||||
invocation(get, "1"),
|
||||
)
|
||||
@@ -240,14 +161,14 @@ 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, using []JmapNamespace, //NOSONAR
|
||||
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) (map[string]SetError, SessionState, State, Language, Error) {
|
||||
logger := client.logger(name, ctx)
|
||||
ctx = ctx.WithLogger(logger)
|
||||
|
||||
set := setCommandFactory(accountId, destroy)
|
||||
cmd, err := client.request(ctx, using,
|
||||
cmd, err := client.request(ctx, objType.Namespaces,
|
||||
invocation(set, "0"),
|
||||
)
|
||||
if err != nil {
|
||||
@@ -265,7 +186,7 @@ func destroy[T Foo, REQ SetCommand[T], RESP SetResponse[T]](client *Client, name
|
||||
}
|
||||
|
||||
func changesA[T Foo, CHANGESREQ ChangesCommand[T], GETREQ GetCommand[T], CHANGESRESP ChangesResponse[T], GETRESP GetResponse[T], RESP any]( //NOSONAR
|
||||
client *Client, name string, using []JmapNamespace,
|
||||
client *Client, name string, objType ObjectType,
|
||||
changesCommandFactory func() CHANGESREQ,
|
||||
changesResp CHANGESRESP,
|
||||
_ GETRESP,
|
||||
@@ -273,7 +194,7 @@ func changesA[T Foo, CHANGESREQ ChangesCommand[T], GETREQ GetCommand[T], CHANGES
|
||||
respMapper func(State, State, bool, []T, []T, []string) RESP,
|
||||
ctx Context) (RESP, SessionState, State, Language, Error) {
|
||||
|
||||
return changes(client, name, using, changesCommandFactory, changesResp, getCommandFactory,
|
||||
return changes(client, name, objType, changesCommandFactory, changesResp, getCommandFactory,
|
||||
func(r GETRESP) []T { return r.GetList() },
|
||||
respMapper,
|
||||
ctx,
|
||||
@@ -281,7 +202,7 @@ func changesA[T Foo, CHANGESREQ ChangesCommand[T], GETREQ GetCommand[T], CHANGES
|
||||
}
|
||||
|
||||
func changes[T Foo, CHANGESREQ ChangesCommand[T], GETREQ GetCommand[T], CHANGESRESP ChangesResponse[T], GETRESP GetResponse[T], ITEM any, RESP any]( //NOSONAR
|
||||
client *Client, name string, using []JmapNamespace,
|
||||
client *Client, name string, objType ObjectType,
|
||||
changesCommandFactory func() CHANGESREQ,
|
||||
_ CHANGESRESP,
|
||||
getCommandFactory func(string, string) GETREQ,
|
||||
@@ -295,7 +216,7 @@ func changes[T Foo, CHANGESREQ ChangesCommand[T], GETREQ GetCommand[T], CHANGESR
|
||||
getCreated := getCommandFactory("/created", "0") //NOSONAR
|
||||
getUpdated := getCommandFactory("/updated", "0") //NOSONAR
|
||||
|
||||
cmd, err := client.request(ctx.WithLogger(logger), using,
|
||||
cmd, err := client.request(ctx.WithLogger(logger), objType.Namespaces,
|
||||
invocation(changes, "0"),
|
||||
invocation(getCreated, "1"),
|
||||
invocation(getUpdated, "2"),
|
||||
@@ -335,7 +256,7 @@ 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, using []JmapNamespace,
|
||||
client *Client, name string, objType ObjectType,
|
||||
accountIds []string, sinceStateMap map[string]State,
|
||||
changesCommandFactory func(string, State) CHANGESREQ,
|
||||
_ CHANGESRESP,
|
||||
@@ -362,8 +283,9 @@ func changesN[T Foo, CHANGESREQ ChangesCommand[T], GETREQ GetCommand[T], CHANGES
|
||||
}
|
||||
|
||||
invocations := make([]Invocation, n*3)
|
||||
getCommand := Command("")
|
||||
changesCommand := Command("")
|
||||
var ch CHANGESREQ
|
||||
var gc GETREQ
|
||||
var gu GETREQ
|
||||
for i, accountId := range uniqueAccountIds {
|
||||
sinceState, ok := sinceStateMap[accountId]
|
||||
if !ok {
|
||||
@@ -379,13 +301,14 @@ func changesN[T Foo, CHANGESREQ ChangesCommand[T], GETREQ GetCommand[T], CHANGES
|
||||
invocations[i*3+1] = invocation(getCreated, mcid(accountId, "1"))
|
||||
invocations[i*3+2] = invocation(getUpdated, mcid(accountId, "2"))
|
||||
|
||||
changesCommand = changes.GetCommand()
|
||||
getCommand = getCreated.GetCommand()
|
||||
ch = changes
|
||||
gc = getCreated
|
||||
gu = getUpdated
|
||||
}
|
||||
|
||||
ctx = ctx.WithLogger(logger)
|
||||
|
||||
cmd, err := client.request(ctx, using, invocations...)
|
||||
cmd, err := client.request(ctx, objType.Namespaces, invocations...)
|
||||
if err != nil {
|
||||
return zero, "", "", "", err
|
||||
}
|
||||
@@ -395,19 +318,19 @@ func changesN[T Foo, CHANGESREQ ChangesCommand[T], GETREQ GetCommand[T], CHANGES
|
||||
stateByAccountId := make(map[string]State, n)
|
||||
for _, accountId := range uniqueAccountIds {
|
||||
var changesResponse CHANGESRESP
|
||||
err = retrieveResponseMatchParameters(ctx, body, changesCommand, mcid(accountId, "0"), &changesResponse)
|
||||
err = retrieveChanges(ctx, body, ch, mcid(accountId, "0"), &changesResponse)
|
||||
if err != nil {
|
||||
return zero, "", err
|
||||
}
|
||||
|
||||
var createdResponse GETRESP
|
||||
err = retrieveResponseMatchParameters(ctx, body, getCommand, mcid(accountId, "1"), &createdResponse)
|
||||
err = retrieveGet(ctx, body, gc, mcid(accountId, "1"), &createdResponse)
|
||||
if err != nil {
|
||||
return zero, "", err
|
||||
}
|
||||
|
||||
var updatedResponse GETRESP
|
||||
err = retrieveResponseMatchParameters(ctx, body, getCommand, mcid(accountId, "2"), &updatedResponse)
|
||||
err = retrieveGet(ctx, body, gu, mcid(accountId, "2"), &updatedResponse)
|
||||
if err != nil {
|
||||
return zero, "", err
|
||||
}
|
||||
@@ -422,7 +345,7 @@ func changesN[T Foo, CHANGESREQ ChangesCommand[T], GETREQ GetCommand[T], CHANGES
|
||||
}
|
||||
|
||||
func updates[T Foo, CHANGESREQ ChangesCommand[T], GETREQ GetCommand[T], CHANGESRESP ChangesResponse[T], GETRESP GetResponse[T], ITEM any, RESP any]( //NOSONAR
|
||||
client *Client, name string, using []JmapNamespace,
|
||||
client *Client, name string, objType ObjectType,
|
||||
changesCommandFactory func() CHANGESREQ,
|
||||
_ CHANGESRESP,
|
||||
getCommandFactory func(string, string) GETREQ,
|
||||
@@ -435,7 +358,7 @@ func updates[T Foo, CHANGESREQ ChangesCommand[T], GETREQ GetCommand[T], CHANGESR
|
||||
|
||||
changes := changesCommandFactory()
|
||||
getUpdated := getCommandFactory("/updated", "0") //NOSONAR
|
||||
cmd, err := client.request(ctx, using,
|
||||
cmd, err := client.request(ctx, objType.Namespaces,
|
||||
invocation(changes, "0"),
|
||||
invocation(getUpdated, "1"),
|
||||
)
|
||||
@@ -464,7 +387,8 @@ func updates[T Foo, CHANGESREQ ChangesCommand[T], GETREQ GetCommand[T], CHANGESR
|
||||
})
|
||||
}
|
||||
|
||||
func update[T Foo, CHANGES Change, SET SetCommand[T], GET GetCommand[T], RESP any, SETRESP SetResponse[T], GETRESP GetResponse[T]](client *Client, name string, using []JmapNamespace, //NOSONAR
|
||||
func update[T Foo, CHANGES Change, SET SetCommand[T], GET GetCommand[T], RESP any, SETRESP SetResponse[T], GETRESP GetResponse[T]]( //NOSONAR
|
||||
client *Client, name string, objType ObjectType,
|
||||
setCommandFactory func(map[string]PatchObject) SET,
|
||||
getCommandFactory func(string) GET,
|
||||
notUpdatedExtractor func(SETRESP) map[string]SetError,
|
||||
@@ -473,9 +397,10 @@ func update[T Foo, CHANGES Change, SET SetCommand[T], GET GetCommand[T], RESP an
|
||||
ctx Context) (RESP, SessionState, State, Language, Error) {
|
||||
logger := client.logger(name, ctx)
|
||||
ctx = ctx.WithLogger(logger)
|
||||
|
||||
update := setCommandFactory(map[string]PatchObject{id: changes.AsPatch()})
|
||||
get := getCommandFactory(id)
|
||||
cmd, err := client.request(ctx, using, invocation(update, "0"), invocation(get, "1"))
|
||||
cmd, err := client.request(ctx, objType.Namespaces, invocation(update, "0"), invocation(get, "1"))
|
||||
var zero RESP
|
||||
if err != nil {
|
||||
return zero, "", "", "", err
|
||||
@@ -503,7 +428,7 @@ func update[T Foo, CHANGES Change, SET SetCommand[T], GET GetCommand[T], RESP an
|
||||
}
|
||||
|
||||
func query[T Foo, FILTER any, SORT any, QUERY QueryCommand[T], GET GetCommand[T], QUERYRESP QueryResponse[T], GETRESP GetResponse[T], RESP any]( //NOSONAR
|
||||
client *Client, name string, using []JmapNamespace,
|
||||
client *Client, name string, objType ObjectType,
|
||||
defaultSortBy []SORT,
|
||||
queryCommandFactory func(filter FILTER, sortBy []SORT, limit uint, position uint) QUERY,
|
||||
getCommandFactory func(cmd Command, path string, rof string) GET,
|
||||
@@ -523,7 +448,7 @@ func query[T Foo, FILTER any, SORT any, QUERY QueryCommand[T], GET GetCommand[T]
|
||||
|
||||
var zero RESP
|
||||
|
||||
cmd, err := client.request(ctx, using, invocation(query, "0"), invocation(get, "1"))
|
||||
cmd, err := client.request(ctx, objType.Namespaces, invocation(query, "0"), invocation(get, "1"))
|
||||
if err != nil {
|
||||
return zero, "", "", "", err
|
||||
}
|
||||
@@ -544,7 +469,7 @@ 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], GET GetCommand[T], QUERYRESP QueryResponse[T], GETRESP GetResponse[T], RESP any]( //NOSONAR
|
||||
client *Client, name string, using []JmapNamespace,
|
||||
client *Client, name string, objType ObjectType,
|
||||
defaultSortBy []SORT,
|
||||
queryCommandFactory func(accountId string, filter FILTER, sortBy []SORT, position int, limit uint) QUERY,
|
||||
getCommandFactory func(accountId string, cmd Command, path string, rof string) GET,
|
||||
@@ -552,6 +477,9 @@ func queryN[T Foo, FILTER any, SORT any, QUERY QueryCommand[T], GET GetCommand[T
|
||||
accountIds []string,
|
||||
filter FILTER, sortBy []SORT, limit uint, position int,
|
||||
ctx Context) (map[string]RESP, SessionState, State, Language, Error) {
|
||||
logger := client.logger(name, ctx)
|
||||
ctx = ctx.WithLogger(logger)
|
||||
|
||||
uniqueAccountIds := structs.Uniq(accountIds)
|
||||
|
||||
if sortBy == nil {
|
||||
@@ -570,7 +498,7 @@ func queryN[T Foo, FILTER any, SORT any, QUERY QueryCommand[T], GET GetCommand[T
|
||||
g = get
|
||||
}
|
||||
|
||||
cmd, err := client.request(ctx, NS_CALENDARS, invocations...)
|
||||
cmd, err := client.request(ctx, objType.Namespaces, invocations...)
|
||||
if err != nil {
|
||||
return nil, "", "", "", err
|
||||
}
|
||||
|
||||
@@ -109,16 +109,17 @@ func (g *Groupware) GetAllEmailsInMailbox(w http.ResponseWriter, r *http.Request
|
||||
return req.jmapError(accountId, jerr, sessionState, lang)
|
||||
}
|
||||
|
||||
sanitized, err := req.sanitizeEmails(emails.Emails)
|
||||
sanitized, err := req.sanitizeEmails(emails.Results)
|
||||
if err != nil {
|
||||
return req.error(accountId, err)
|
||||
}
|
||||
|
||||
safe := jmap.Emails{
|
||||
Emails: sanitized,
|
||||
Total: emails.Total,
|
||||
Limit: emails.Limit,
|
||||
Offset: emails.Offset,
|
||||
safe := jmap.EmailSearchResults{
|
||||
Results: sanitized,
|
||||
Total: emails.Total,
|
||||
Limit: emails.Limit,
|
||||
Position: emails.Position,
|
||||
CanCalculateChanges: emails.CanCalculateChanges,
|
||||
}
|
||||
|
||||
return req.respond(accountId, safe, sessionState, EmailResponseObjectType, state)
|
||||
@@ -689,15 +690,17 @@ func (g *Groupware) GetEmailsForAllAccounts(w http.ResponseWriter, r *http.Reque
|
||||
var totalOverAllAccounts uint = 0
|
||||
total := 0
|
||||
for _, results := range resultsByAccountId {
|
||||
totalOverAllAccounts += results.Total
|
||||
total += len(results.Snippets)
|
||||
if results.Total != nil {
|
||||
totalOverAllAccounts += *results.Total
|
||||
}
|
||||
total += len(results.Results)
|
||||
}
|
||||
|
||||
flattened := make([]Snippet, total)
|
||||
{
|
||||
i := 0
|
||||
for accountId, results := range resultsByAccountId {
|
||||
for _, result := range results.Snippets {
|
||||
for _, result := range results.Results {
|
||||
flattened[i] = Snippet{
|
||||
AccountId: accountId,
|
||||
SearchSnippetWithMeta: result,
|
||||
|
||||
Reference in New Issue
Block a user