mirror of
https://github.com/warmbly/warmbly.git
synced 2026-09-13 08:05:05 +00:00
62 lines
2.1 KiB
Go
62 lines
2.1 KiB
Go
package contact
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/warmbly/warmbly/internal/errx"
|
|
"github.com/warmbly/warmbly/internal/models"
|
|
)
|
|
|
|
// ResolveSelection turns a bulk action's selection into the contact ids it
|
|
// applies to. An explicit list passes through untouched; a "select all
|
|
// matching" resolves the same search the list ran, minus the rows unticked
|
|
// afterwards, so the action covers exactly what the user saw selected.
|
|
//
|
|
// The resolved set is capped: past models.MaxContactBulkSelection the action
|
|
// is refused rather than truncated, since acting on an arbitrary prefix of a
|
|
// selection is worse than acting on none of it.
|
|
func (s *contactService) ResolveSelection(ctx context.Context, orgID uuid.UUID, sel models.ContactSelection) ([]string, *errx.Error) {
|
|
if !sel.All {
|
|
return sel.Contacts, nil
|
|
}
|
|
if sel.Filters == nil {
|
|
return nil, errx.New(errx.BadRequest, "a select-all request must carry the filters it applies to")
|
|
}
|
|
|
|
ids, xerr := s.contactRepository.SearchIDs(ctx, orgID.String(), *sel.Filters, models.MaxContactBulkSelection)
|
|
if xerr != nil {
|
|
return nil, xerr
|
|
}
|
|
if len(ids) > models.MaxContactBulkSelection {
|
|
return nil, errx.NewWithIdentifier(errx.BadRequest, "selection_too_large",
|
|
fmt.Sprintf("that selection matches more than %d contacts; narrow it with a filter and try again", models.MaxContactBulkSelection))
|
|
}
|
|
|
|
// The cap above bounds the resolved set, not the request body: an
|
|
// exclusion list is caller-supplied and sized before anything is read.
|
|
if len(sel.Exclude) > models.MaxContactBulkSelection {
|
|
return nil, errx.NewWithIdentifier(errx.BadRequest, "too_many_contacts",
|
|
fmt.Sprintf("too many exclusions, maximum is %d", models.MaxContactBulkSelection))
|
|
}
|
|
excluded := make(map[uuid.UUID]struct{}, len(sel.Exclude))
|
|
for _, raw := range sel.Exclude {
|
|
id, err := uuid.Parse(strings.TrimSpace(raw))
|
|
if err != nil {
|
|
return nil, errx.ErrUuid
|
|
}
|
|
excluded[id] = struct{}{}
|
|
}
|
|
|
|
out := make([]string, 0, len(ids))
|
|
for _, id := range ids {
|
|
if _, skip := excluded[id]; skip {
|
|
continue
|
|
}
|
|
out = append(out, id.String())
|
|
}
|
|
return out, nil
|
|
}
|