groupware: fix query objects in a container with multiple suppliers

* by adding a predicate that can analyze a filter and inform the
   template methods whether the filter is applicable for that supplier
   or not

 * this fixed /groupware/accounts/.../addressbooks/.../contacts
This commit is contained in:
Pascal Bleser
2026-06-24 15:42:09 +02:00
parent 0e71922282
commit 7ed065ddfe
3 changed files with 22 additions and 0 deletions

View File

@@ -86,6 +86,17 @@ func (g *Groupware) contacts(accountIds []jmap.AccountId, qps QueryParamsSupplie
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,
func(supplier QuerySupplier[jmap.ContactCard, *jmap.ContactCardSearchResults, jmap.ContactCardFilterElement, jmap.ContactCardComparator], filter jmap.ContactCardFilterElement) bool {
switch c := filter.(type) {
case jmap.ContactCardFilterCondition:
if c.InAddressBook != "" {
if !supplier.IsMine(c.InAddressBook) {
return false
}
}
}
return true
},
func(a, b jmap.ContactCard) int { return a.Created.Compare(b.Created) },
func(canCalculateChanges jmap.ChangeCalculation, position, limit, total *uint, results []jmap.ContactCard) *jmap.ContactCardSearchResults {
return &jmap.ContactCardSearchResults{

View File

@@ -13,6 +13,8 @@ import (
type SupplierId string
const EmptySupplierId = ""
type Supplier[T jmap.Foo] interface {
GetId() SupplierId
IsMine(id string) bool
@@ -171,6 +173,7 @@ func fillMissingAccounts(qps QueryParamsSupplier, supplierId SupplierId, account
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 []jmap.AccountId, qps QueryParamsSupplier, limit *uint, filter F, sortBy []C,
calculateTotal bool, ctx jmap.Context,
filterSupplierPredicate func(supplier S, filter F) bool,
sorter func(T, T) int,
searchResultCtor func(canCalculateChanges jmap.ChangeCalculation, position *uint, limit *uint, total *uint, results []T) R) (
jmap.Result[R], NextToken, error,
@@ -296,6 +299,11 @@ func squery[T jmap.Idable, R jmap.SearchResults[T], S QuerySupplier[T, R, F, C],
lang := jmap.NoLanguage
durations := make([][]time.Duration, len(suppliers))
for i, supplier := range suppliers {
if !filterSupplierPredicate(supplier, filter) {
// the filter is not applicable for this supplier => skip
continue
}
// we are not injecting id prefixes here for all the objects, as each supplier is responsible for doing that if necessary
if result, err := supplier.Query(accountIds, qps, limit, filter, sortBy, calculateTotal, ctx); err != nil {
return jmap.ZeroResult[R](result.Durations), NoNextToken, err

View File

@@ -101,6 +101,9 @@ func pets(
calculateTotal bool,
ctx jmap.Context) (jmap.Result[*PetSearchResults], NextToken, error) {
return squery(suppliers, accountIds, qps, limit, filter, sortBy, calculateTotal, ctx,
func(supplier QuerySupplier[Pet, *PetSearchResults, PetFilterElement, PetComparator], filter PetFilterElement) bool {
return true
},
func(a, b Pet) int { return strings.Compare(a.name, b.name) },
func(canCalculateChanges jmap.ChangeCalculation, position, limit, total *uint, results []Pet) *PetSearchResults {
return &PetSearchResults{