mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 20:37:30 +00:00
feat: get multiple users by id (#6210)
* feat: introduce InTextQuery, and the ability to get multiple users by id * added in query tests * remove append call * fix lints
This commit is contained in:
@@ -40,6 +40,8 @@ func UserQueryToQuery(query *user_pb.SearchQuery) (query.SearchQuery, error) {
|
|||||||
return LoginNameQueryToQuery(q.LoginNameQuery)
|
return LoginNameQueryToQuery(q.LoginNameQuery)
|
||||||
case *user_pb.SearchQuery_ResourceOwner:
|
case *user_pb.SearchQuery_ResourceOwner:
|
||||||
return ResourceOwnerQueryToQuery(q.ResourceOwner)
|
return ResourceOwnerQueryToQuery(q.ResourceOwner)
|
||||||
|
case *user_pb.SearchQuery_InUserIdsQuery:
|
||||||
|
return InUserIdsQueryToQuery(q.InUserIdsQuery)
|
||||||
default:
|
default:
|
||||||
return nil, errors.ThrowInvalidArgument(nil, "GRPC-vR9nC", "List.Query.Invalid")
|
return nil, errors.ThrowInvalidArgument(nil, "GRPC-vR9nC", "List.Query.Invalid")
|
||||||
}
|
}
|
||||||
@@ -84,3 +86,7 @@ func LoginNameQueryToQuery(q *user_pb.LoginNameQuery) (query.SearchQuery, error)
|
|||||||
func ResourceOwnerQueryToQuery(q *user_pb.ResourceOwnerQuery) (query.SearchQuery, error) {
|
func ResourceOwnerQueryToQuery(q *user_pb.ResourceOwnerQuery) (query.SearchQuery, error) {
|
||||||
return query.NewUserResourceOwnerSearchQuery(q.OrgID, query.TextEquals)
|
return query.NewUserResourceOwnerSearchQuery(q.OrgID, query.TextEquals)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func InUserIdsQueryToQuery(q *user_pb.InUserIDQuery) (query.SearchQuery, error) {
|
||||||
|
return query.NewUserInUserIdsSearchQuery(q.UserIds)
|
||||||
|
}
|
||||||
|
@@ -156,6 +156,10 @@ const (
|
|||||||
columnCompareMax
|
columnCompareMax
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type InTextQuery struct {
|
||||||
|
Column Column
|
||||||
|
Values []string
|
||||||
|
}
|
||||||
type TextQuery struct {
|
type TextQuery struct {
|
||||||
Column Column
|
Column Column
|
||||||
Text string
|
Text string
|
||||||
@@ -167,8 +171,22 @@ var (
|
|||||||
ErrInvalidCompare = errors.New("invalid compare")
|
ErrInvalidCompare = errors.New("invalid compare")
|
||||||
ErrMissingColumn = errors.New("missing column")
|
ErrMissingColumn = errors.New("missing column")
|
||||||
ErrInvalidNumber = errors.New("value is no number")
|
ErrInvalidNumber = errors.New("value is no number")
|
||||||
|
ErrEmptyValues = errors.New("values array must not be empty")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func NewInTextQuery(col Column, values []string) (*InTextQuery, error) {
|
||||||
|
if len(values) == 0 {
|
||||||
|
return nil, ErrEmptyValues
|
||||||
|
}
|
||||||
|
if col.isZero() {
|
||||||
|
return nil, ErrMissingColumn
|
||||||
|
}
|
||||||
|
return &InTextQuery{
|
||||||
|
Column: col,
|
||||||
|
Values: values,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func NewTextQuery(col Column, value string, compare TextComparison) (*TextQuery, error) {
|
func NewTextQuery(col Column, value string, compare TextComparison) (*TextQuery, error) {
|
||||||
if compare < 0 || compare >= textCompareMax {
|
if compare < 0 || compare >= textCompareMax {
|
||||||
return nil, ErrInvalidCompare
|
return nil, ErrInvalidCompare
|
||||||
@@ -183,6 +201,15 @@ func NewTextQuery(col Column, value string, compare TextComparison) (*TextQuery,
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (q *InTextQuery) toQuery(query sq.SelectBuilder) sq.SelectBuilder {
|
||||||
|
return query.Where(q.comp())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *InTextQuery) comp() sq.Sqlizer {
|
||||||
|
// This translates to an IN query
|
||||||
|
return sq.Eq{s.Column.identifier(): s.Values}
|
||||||
|
}
|
||||||
|
|
||||||
func (q *TextQuery) toQuery(query sq.SelectBuilder) sq.SelectBuilder {
|
func (q *TextQuery) toQuery(query sq.SelectBuilder) sq.SelectBuilder {
|
||||||
return query.Where(q.comp())
|
return query.Where(q.comp())
|
||||||
}
|
}
|
||||||
@@ -269,7 +296,7 @@ func NewNumberQuery(c Column, value interface{}, compare NumberComparison) (*Num
|
|||||||
}
|
}
|
||||||
switch reflect.TypeOf(value).Kind() {
|
switch reflect.TypeOf(value).Kind() {
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64:
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64:
|
||||||
//everything fine
|
// everything fine
|
||||||
default:
|
default:
|
||||||
return nil, ErrInvalidNumber
|
return nil, ErrInvalidNumber
|
||||||
}
|
}
|
||||||
|
@@ -1382,3 +1382,118 @@ func TestNumberComparisonFromMethod(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNewInTextQuery(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
column Column
|
||||||
|
value []string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want *InTextQuery
|
||||||
|
wantErr func(error) bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "empty values",
|
||||||
|
args: args{
|
||||||
|
column: testCol,
|
||||||
|
value: []string{},
|
||||||
|
},
|
||||||
|
wantErr: func(err error) bool {
|
||||||
|
return errors.Is(err, ErrEmptyValues)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "no column",
|
||||||
|
args: args{
|
||||||
|
column: Column{},
|
||||||
|
value: []string{"adler", "hurst"},
|
||||||
|
},
|
||||||
|
wantErr: func(err error) bool {
|
||||||
|
return errors.Is(err, ErrMissingColumn)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "no column name",
|
||||||
|
args: args{
|
||||||
|
column: testNoCol,
|
||||||
|
value: []string{"adler", "hurst"},
|
||||||
|
},
|
||||||
|
wantErr: func(err error) bool {
|
||||||
|
return errors.Is(err, ErrMissingColumn)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "correct",
|
||||||
|
args: args{
|
||||||
|
column: testCol,
|
||||||
|
value: []string{"adler", "hurst"},
|
||||||
|
},
|
||||||
|
want: &InTextQuery{
|
||||||
|
Column: testCol,
|
||||||
|
Values: []string{"adler", "hurst"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got, err := NewInTextQuery(tt.args.column, tt.args.value)
|
||||||
|
if err != nil && tt.wantErr == nil {
|
||||||
|
t.Errorf("NewTextQuery() no error expected got %v", err)
|
||||||
|
return
|
||||||
|
} else if tt.wantErr != nil && !tt.wantErr(err) {
|
||||||
|
t.Errorf("NewTextQuery() unexpeted error = %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("NewTextQuery() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInTextQuery_comp(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
Column Column
|
||||||
|
Values []string
|
||||||
|
}
|
||||||
|
type want struct {
|
||||||
|
query interface{}
|
||||||
|
isNil bool
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
want want
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "equals",
|
||||||
|
fields: fields{
|
||||||
|
Column: testCol,
|
||||||
|
Values: []string{"Adler", "Hurst"},
|
||||||
|
},
|
||||||
|
want: want{
|
||||||
|
query: sq.Eq{"test_table.test_col": []string{"Adler", "Hurst"}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
s := &InTextQuery{
|
||||||
|
Column: tt.fields.Column,
|
||||||
|
Values: tt.fields.Values,
|
||||||
|
}
|
||||||
|
query := s.comp()
|
||||||
|
if query == nil && tt.want.isNil {
|
||||||
|
return
|
||||||
|
} else if tt.want.isNil && query != nil {
|
||||||
|
t.Error("query should not be nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(query, tt.want.query) {
|
||||||
|
t.Errorf("wrong query: want: %v, (%T), got: %v, (%T)", tt.want.query, tt.want.query, query, query)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -605,6 +605,10 @@ func (r *UserSearchQueries) AppendMyResourceOwnerQuery(orgID string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewUserInUserIdsSearchQuery(values []string) (SearchQuery, error) {
|
||||||
|
return NewInTextQuery(UserIDCol, values)
|
||||||
|
}
|
||||||
|
|
||||||
func NewUserResourceOwnerSearchQuery(value string, comparison TextComparison) (SearchQuery, error) {
|
func NewUserResourceOwnerSearchQuery(value string, comparison TextComparison) (SearchQuery, error) {
|
||||||
return NewTextQuery(UserResourceOwnerCol, value, comparison)
|
return NewTextQuery(UserResourceOwnerCol, value, comparison)
|
||||||
}
|
}
|
||||||
|
@@ -184,9 +184,19 @@ message SearchQuery {
|
|||||||
StateQuery state_query = 7;
|
StateQuery state_query = 7;
|
||||||
TypeQuery type_query = 8;
|
TypeQuery type_query = 8;
|
||||||
LoginNameQuery login_name_query = 9;
|
LoginNameQuery login_name_query = 9;
|
||||||
|
InUserIDQuery in_user_ids_query = 10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message InUserIDQuery {
|
||||||
|
repeated string user_ids = 1 [
|
||||||
|
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||||
|
description: "the ids of the users to include"
|
||||||
|
example: "[\"69629023906488334\",\"69622366012355662\"]";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
message UserNameQuery {
|
message UserNameQuery {
|
||||||
string user_name = 1 [
|
string user_name = 1 [
|
||||||
(validate.rules).string = {max_len: 200},
|
(validate.rules).string = {max_len: 200},
|
||||||
|
Reference in New Issue
Block a user