diff --git a/services/graph/pkg/service/v0/users_filter.go b/services/graph/pkg/service/v0/users_filter.go index a836f5378..8448a5605 100644 --- a/services/graph/pkg/service/v0/users_filter.go +++ b/services/graph/pkg/service/v0/users_filter.go @@ -50,6 +50,12 @@ func (g Graph) applyFilterLogical(ctx context.Context, req *godata.GoDataRequest return users, invalidFilterError() } return g.applyFilterLogicalAnd(ctx, req, root.Children[0], root.Children[1]) + case "or": + // 'or' needs 2 operands + if len(root.Children) != 2 { + return users, invalidFilterError() + } + return g.applyFilterLogicalOr(ctx, req, root.Children[0], root.Children[1]) } logger.Debug().Str("Token", root.Token.Value).Msg("unsupported logical filter") return users, unsupportedFilterError() @@ -109,6 +115,32 @@ func (g Graph) applyFilterLogicalAnd(ctx context.Context, req *godata.GoDataRequ return filteredUsers, nil } +func (g Graph) applyFilterLogicalOr(ctx context.Context, req *godata.GoDataRequest, operand1 *godata.ParseNode, operand2 *godata.ParseNode) (users []*libregraph.User, err error) { + // logger := g.logger.SubloggerWithRequestID(ctx) + var res1, res2 []*libregraph.User + + res1, err = g.applyUserFilter(ctx, req, operand1) + if err != nil { + return []*libregraph.User{}, err + } + + res2, err = g.applyUserFilter(ctx, req, operand2) + if err != nil { + return []*libregraph.User{}, err + } + + // We now have two slices with results of the subfilters. Now turn one of them + // into a map for efficiently getting the union of both slices + userSet := userSliceToMap(res1) + filteredUsers := make([]*libregraph.User, 0, len(res1)+len(res2)) + filteredUsers = append(filteredUsers, res1...) + for _, user := range res2 { + if _, found := userSet[user.GetId()]; !found { + filteredUsers = append(filteredUsers, user) + } + } + return filteredUsers, nil +} func (g Graph) applyFilterLambda(ctx context.Context, req *godata.GoDataRequest, nodes []*godata.ParseNode) (users []*libregraph.User, err error) { logger := g.logger.SubloggerWithRequestID(ctx) if len(nodes) != 2 { diff --git a/services/graph/pkg/service/v0/users_test.go b/services/graph/pkg/service/v0/users_test.go index b020ef207..a6f342fa0 100644 --- a/services/graph/pkg/service/v0/users_test.go +++ b/services/graph/pkg/service/v0/users_test.go @@ -378,9 +378,12 @@ var _ = Describe("Users", func() { Entry("with memberOf lambda filter with UUID", "memberOf/any(n:n/id eq 25cb7bc0-3168-4a0c-adbe-396f478ad494)", http.StatusOK), Entry("with memberOf lambda filter with UUID string", "memberOf/any(n:n/id eq '25cb7bc0-3168-4a0c-adbe-396f478ad494')", http.StatusOK), Entry("with appRoleAssignments lambda filter with appRoleId", "appRoleAssignments/any(n:n/appRoleId eq 'some-appRole-ID')", http.StatusOK), - Entry("with two memberOf lambda filters", + Entry("with two memberOf lambda filters combined with and", "memberOf/any(n:n/id eq 25cb7bc0-3168-4a0c-adbe-396f478ad494) and memberOf/any(n:n/id eq 2713f1d5-6822-42bd-ad56-9f6c55a3a8fa)", http.StatusOK), + Entry("with two memberOf lambda filters combined with or", + "memberOf/any(n:n/id eq 25cb7bc0-3168-4a0c-adbe-396f478ad494) or memberOf/any(n:n/id eq 2713f1d5-6822-42bd-ad56-9f6c55a3a8fa)", + http.StatusOK), Entry("with supported appRoleAssignments lambda filter property", "appRoleAssignments/any(n:n/appRoleId eq 'some-appRoleAssignment-ID') and memberOf/any(n:n/id eq 2713f1d5-6822-42bd-ad56-9f6c55a3a8fa)", http.StatusOK),