1package admin
2
3import (
4 "context"
5 "strings"
6
7 "tug/internal/storage"
8)
9
10func split(users []storage.User) (enabled, disabled []storage.User) {
11 for _, u := range users {
12 if u.Disabled {
13 disabled = append(disabled, u)
14 } else {
15 enabled = append(enabled, u)
16 }
17 }
18 return enabled, disabled
19}
20
21func membersOf(users []storage.User) []Member {
22 out := make([]Member, 0, len(users))
23 for _, u := range users {
24 out = append(out, Member{ID: u.ID, Username: u.Username, DisplayName: u.DisplayName})
25 }
26 return out
27}
28
29func (s *Service) GroupCandidates(ctx context.Context, groupID, query string) ([]Member, error) {
30 g, err := s.store.GroupByID(ctx, groupID)
31 if err != nil {
32 return nil, target("read group", err)
33 }
34 needle := strings.ToLower(strings.TrimSpace(query))
35 if needle == "" || g.Name == s.primaryGroup {
36 return nil, nil
37 }
38 members, err := s.members(ctx, g)
39 if err != nil {
40 return nil, err
41 }
42 in := make(map[string]bool, len(members))
43 for _, u := range members {
44 in[u.ID] = true
45 }
46 users, err := s.store.ListUsers(ctx)
47 if err != nil {
48 return nil, failed("list users", err)
49 }
50 var found []storage.User
51 for _, u := range users {
52 if !in[u.ID] && matches(u, needle) {
53 found = append(found, u)
54 if len(found) == CandidatesShown {
55 break
56 }
57 }
58 }
59 return membersOf(found), nil
60}