Skip to content

Commit b3b8bf0

Browse files
salmonumbrellaPeter Steinberger
authored andcommitted
fix(groups): add required labels filter for list query
1 parent a2f001e commit b3b8bf0

3 files changed

Lines changed: 48 additions & 1 deletion

File tree

internal/cmd/execute_groups_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@ func TestExecute_GroupsList_JSON(t *testing.T) {
1818

1919
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
2020
if strings.Contains(r.URL.Path, "groups/-/memberships:searchTransitiveGroups") && r.Method == http.MethodGet {
21+
query := r.URL.Query().Get("query")
22+
if !strings.Contains(query, "'"+groupLabelDiscussionForum+"' in labels") {
23+
t.Fatalf("missing discussion label filter in query: %q", query)
24+
}
25+
if !strings.Contains(query, "member_key_id == 'a@b.com'") {
26+
t.Fatalf("missing member_key_id filter in query: %q", query)
27+
}
2128
w.Header().Set("Content-Type", "application/json")
2229
_ = json.NewEncoder(w).Encode(map[string]any{
2330
"memberships": []map[string]any{
@@ -159,6 +166,13 @@ func TestExecute_GroupsList_Text(t *testing.T) {
159166

160167
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
161168
if strings.Contains(r.URL.Path, "groups/-/memberships:searchTransitiveGroups") && r.Method == http.MethodGet {
169+
query := r.URL.Query().Get("query")
170+
if !strings.Contains(query, "'"+groupLabelDiscussionForum+"' in labels") {
171+
t.Fatalf("missing discussion label filter in query: %q", query)
172+
}
173+
if !strings.Contains(query, "member_key_id == 'a@b.com'") {
174+
t.Fatalf("missing member_key_id filter in query: %q", query)
175+
}
162176
w.Header().Set("Content-Type", "application/json")
163177
_ = json.NewEncoder(w).Encode(map[string]any{
164178
"memberships": []map[string]any{

internal/cmd/groups.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ const (
2121
groupRoleOwner = "OWNER"
2222
groupRoleManager = "MANAGER"
2323
groupRoleMember = "MEMBER"
24+
25+
groupLabelDiscussionForum = "cloudidentity.googleapis.com/groups.discussion_forum"
26+
groupLabelDynamic = "cloudidentity.googleapis.com/groups.dynamic"
2427
)
2528

2629
type GroupsCmd struct {
@@ -51,7 +54,7 @@ func (c *GroupsListCmd) Run(ctx context.Context, flags *RootFlags) error {
5154
// Using "groups/-" as parent searches across all groups
5255
fetch := func(pageToken string) ([]*cloudidentity.GroupRelation, string, error) {
5356
call := svc.Groups.Memberships.SearchTransitiveGroups("groups/-").
54-
Query("member_key_id == '" + account + "'").
57+
Query(searchTransitiveGroupsQuery(account)).
5558
PageSize(c.Max).
5659
Context(ctx)
5760
if strings.TrimSpace(pageToken) != "" {
@@ -148,6 +151,16 @@ func wrapCloudIdentityError(err error, account string) error {
148151
return err
149152
}
150153

154+
func searchTransitiveGroupsQuery(memberKeyID string) string {
155+
memberKeyID = strings.ReplaceAll(strings.TrimSpace(memberKeyID), "'", "\\'")
156+
return fmt.Sprintf(
157+
"member_key_id == '%s' && ('%s' in labels || '%s' in labels)",
158+
memberKeyID,
159+
groupLabelDiscussionForum,
160+
groupLabelDynamic,
161+
)
162+
}
163+
151164
// getRelationType returns a human-readable relation type.
152165
func getRelationType(relationType string) string {
153166
switch relationType {

internal/cmd/groups_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,23 @@ func TestTruncate(t *testing.T) {
7474
t.Fatalf("unexpected truncate: %q", got)
7575
}
7676
}
77+
78+
func TestSearchTransitiveGroupsQuery(t *testing.T) {
79+
got := searchTransitiveGroupsQuery("person@example.com")
80+
if !strings.Contains(got, "member_key_id == 'person@example.com'") {
81+
t.Fatalf("missing member_key_id clause: %q", got)
82+
}
83+
if !strings.Contains(got, "'"+groupLabelDiscussionForum+"' in labels") {
84+
t.Fatalf("missing discussion label clause: %q", got)
85+
}
86+
if !strings.Contains(got, "'"+groupLabelDynamic+"' in labels") {
87+
t.Fatalf("missing dynamic label clause: %q", got)
88+
}
89+
}
90+
91+
func TestSearchTransitiveGroupsQuery_EscapesSingleQuote(t *testing.T) {
92+
got := searchTransitiveGroupsQuery("o'connor@example.com")
93+
if !strings.Contains(got, "member_key_id == 'o\\'connor@example.com'") {
94+
t.Fatalf("expected escaped single quote: %q", got)
95+
}
96+
}

0 commit comments

Comments
 (0)