mirror of
https://github.com/zitadel/zitadel.git
synced 2025-12-06 17:32:17 +00:00
# Which Problems Are Solved As requested by @adlerhurst in https://github.com/zitadel/zitadel/pull/10415#discussion_r2298087711 , I am moving the refactoring of v2 user converter methods to a separate PR # How the Problems Are Solved Cherry-pick648c234caf# Additional Context Parent of https://github.com/zitadel/zitadel/pull/10415 (cherry picked from commitb604615cab)
1026 lines
23 KiB
Go
1026 lines
23 KiB
Go
package convert
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/muhlemmer/gu"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"google.golang.org/protobuf/types/known/timestamppb"
|
|
|
|
"github.com/zitadel/zitadel/internal/domain"
|
|
"github.com/zitadel/zitadel/internal/query"
|
|
"github.com/zitadel/zitadel/pkg/grpc/filter/v2"
|
|
metadata "github.com/zitadel/zitadel/pkg/grpc/metadata/v2"
|
|
"github.com/zitadel/zitadel/pkg/grpc/object/v2"
|
|
"github.com/zitadel/zitadel/pkg/grpc/user/v2"
|
|
)
|
|
|
|
func Test_userQueryToQuery(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tt := []struct {
|
|
name string
|
|
input *user.SearchQuery
|
|
level uint8
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "UserNameQuery",
|
|
input: &user.SearchQuery{
|
|
Query: &user.SearchQuery_UserNameQuery{
|
|
UserNameQuery: &user.UserNameQuery{
|
|
UserName: "testuser",
|
|
Method: object.TextQueryMethod_TEXT_QUERY_METHOD_EQUALS,
|
|
},
|
|
},
|
|
},
|
|
level: 0,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "FirstNameQuery",
|
|
input: &user.SearchQuery{
|
|
Query: &user.SearchQuery_FirstNameQuery{
|
|
FirstNameQuery: &user.FirstNameQuery{
|
|
FirstName: "John",
|
|
Method: object.TextQueryMethod_TEXT_QUERY_METHOD_EQUALS,
|
|
},
|
|
},
|
|
},
|
|
level: 0,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "LastNameQuery",
|
|
input: &user.SearchQuery{
|
|
Query: &user.SearchQuery_LastNameQuery{
|
|
LastNameQuery: &user.LastNameQuery{
|
|
LastName: "Doe",
|
|
Method: object.TextQueryMethod_TEXT_QUERY_METHOD_EQUALS,
|
|
},
|
|
},
|
|
},
|
|
level: 0,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "NickNameQuery",
|
|
input: &user.SearchQuery{
|
|
Query: &user.SearchQuery_NickNameQuery{
|
|
NickNameQuery: &user.NickNameQuery{
|
|
NickName: "JD",
|
|
Method: object.TextQueryMethod_TEXT_QUERY_METHOD_EQUALS,
|
|
},
|
|
},
|
|
},
|
|
level: 0,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "DisplayNameQuery",
|
|
input: &user.SearchQuery{
|
|
Query: &user.SearchQuery_DisplayNameQuery{
|
|
DisplayNameQuery: &user.DisplayNameQuery{
|
|
DisplayName: "John Doe",
|
|
Method: object.TextQueryMethod_TEXT_QUERY_METHOD_EQUALS,
|
|
},
|
|
},
|
|
},
|
|
level: 0,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "EmailQuery",
|
|
input: &user.SearchQuery{
|
|
Query: &user.SearchQuery_EmailQuery{
|
|
EmailQuery: &user.EmailQuery{
|
|
EmailAddress: "john@doe.com",
|
|
Method: object.TextQueryMethod_TEXT_QUERY_METHOD_EQUALS,
|
|
},
|
|
},
|
|
},
|
|
level: 0,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "PhoneQuery",
|
|
input: &user.SearchQuery{
|
|
Query: &user.SearchQuery_PhoneQuery{
|
|
PhoneQuery: &user.PhoneQuery{
|
|
Number: "123456789",
|
|
Method: object.TextQueryMethod_TEXT_QUERY_METHOD_EQUALS,
|
|
},
|
|
},
|
|
},
|
|
level: 0,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "StateQuery",
|
|
input: &user.SearchQuery{
|
|
Query: &user.SearchQuery_StateQuery{
|
|
StateQuery: &user.StateQuery{
|
|
State: user.UserState_USER_STATE_ACTIVE,
|
|
},
|
|
},
|
|
},
|
|
level: 0,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "TypeQuery",
|
|
input: &user.SearchQuery{
|
|
Query: &user.SearchQuery_TypeQuery{
|
|
TypeQuery: &user.TypeQuery{
|
|
Type: user.Type_TYPE_HUMAN,
|
|
},
|
|
},
|
|
},
|
|
level: 0,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "LoginNameQuery",
|
|
input: &user.SearchQuery{
|
|
Query: &user.SearchQuery_LoginNameQuery{
|
|
LoginNameQuery: &user.LoginNameQuery{
|
|
LoginName: "login",
|
|
Method: object.TextQueryMethod_TEXT_QUERY_METHOD_EQUALS,
|
|
},
|
|
},
|
|
},
|
|
level: 0,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "OrganizationIdQuery",
|
|
input: &user.SearchQuery{
|
|
Query: &user.SearchQuery_OrganizationIdQuery{
|
|
OrganizationIdQuery: &user.OrganizationIdQuery{
|
|
OrganizationId: "org1",
|
|
},
|
|
},
|
|
},
|
|
level: 0,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "InUserIdsQuery",
|
|
input: &user.SearchQuery{
|
|
Query: &user.SearchQuery_InUserIdsQuery{
|
|
InUserIdsQuery: &user.InUserIDQuery{
|
|
UserIds: []string{"id1", "id2"},
|
|
},
|
|
},
|
|
},
|
|
level: 0,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "OrQuery",
|
|
input: &user.SearchQuery{
|
|
Query: &user.SearchQuery_OrQuery{
|
|
OrQuery: &user.OrQuery{
|
|
Queries: []*user.SearchQuery{
|
|
{
|
|
Query: &user.SearchQuery_UserNameQuery{
|
|
UserNameQuery: &user.UserNameQuery{
|
|
UserName: "testuser",
|
|
Method: object.TextQueryMethod_TEXT_QUERY_METHOD_EQUALS,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
level: 0,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "AndQuery",
|
|
input: &user.SearchQuery{
|
|
Query: &user.SearchQuery_AndQuery{
|
|
AndQuery: &user.AndQuery{
|
|
Queries: []*user.SearchQuery{
|
|
{
|
|
Query: &user.SearchQuery_UserNameQuery{
|
|
UserNameQuery: &user.UserNameQuery{
|
|
UserName: "testuser",
|
|
Method: object.TextQueryMethod_TEXT_QUERY_METHOD_EQUALS,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
level: 0,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "NotQuery",
|
|
input: &user.SearchQuery{
|
|
Query: &user.SearchQuery_NotQuery{
|
|
NotQuery: &user.NotQuery{
|
|
Query: &user.SearchQuery{
|
|
Query: &user.SearchQuery_UserNameQuery{
|
|
UserNameQuery: &user.UserNameQuery{
|
|
UserName: "testuser",
|
|
Method: object.TextQueryMethod_TEXT_QUERY_METHOD_EQUALS,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
level: 0,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "InUserEmailsQuery",
|
|
input: &user.SearchQuery{
|
|
Query: &user.SearchQuery_InUserEmailsQuery{
|
|
InUserEmailsQuery: &user.InUserEmailsQuery{
|
|
UserEmails: []string{"john@doe.com", "jane@doe.com"},
|
|
},
|
|
},
|
|
},
|
|
level: 0,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "MetadataKeyFilter",
|
|
input: &user.SearchQuery{
|
|
Query: &user.SearchQuery_MetadataKeyFilter{
|
|
MetadataKeyFilter: &metadata.MetadataKeyFilter{
|
|
Key: "key1",
|
|
Method: filter.TextFilterMethod_TEXT_FILTER_METHOD_EQUALS,
|
|
},
|
|
},
|
|
},
|
|
level: 0,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "MetadataValueFilter",
|
|
input: &user.SearchQuery{
|
|
Query: &user.SearchQuery_MetadataValueFilter{
|
|
MetadataValueFilter: &metadata.MetadataValueFilter{
|
|
Value: []byte("value1"),
|
|
Method: filter.ByteFilterMethod_BYTE_FILTER_METHOD_EQUALS,
|
|
},
|
|
},
|
|
},
|
|
level: 0,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "TooManyNestingLevels",
|
|
input: &user.SearchQuery{
|
|
Query: &user.SearchQuery_UserNameQuery{
|
|
UserNameQuery: &user.UserNameQuery{
|
|
UserName: "testuser",
|
|
Method: object.TextQueryMethod_TEXT_QUERY_METHOD_EQUALS,
|
|
},
|
|
},
|
|
},
|
|
level: 21,
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "InvalidQueryType",
|
|
input: &user.SearchQuery{
|
|
Query: nil,
|
|
},
|
|
level: 0,
|
|
wantErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tc := range tt {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
got, err := userQueryToQuery(tc.input, tc.level)
|
|
if tc.wantErr {
|
|
assert.Error(t, err)
|
|
assert.Nil(t, got)
|
|
} else {
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, got)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_userQueriesToQuery(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tt := []struct {
|
|
name string
|
|
queries []*user.SearchQuery
|
|
level uint8
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "single valid query",
|
|
queries: []*user.SearchQuery{
|
|
{
|
|
Query: &user.SearchQuery_UserNameQuery{
|
|
UserNameQuery: &user.UserNameQuery{
|
|
UserName: "testuser",
|
|
Method: object.TextQueryMethod_TEXT_QUERY_METHOD_EQUALS,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
level: 0,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "multiple valid queries",
|
|
queries: []*user.SearchQuery{
|
|
{
|
|
Query: &user.SearchQuery_UserNameQuery{
|
|
UserNameQuery: &user.UserNameQuery{
|
|
UserName: "user1",
|
|
Method: object.TextQueryMethod_TEXT_QUERY_METHOD_EQUALS,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Query: &user.SearchQuery_EmailQuery{
|
|
EmailQuery: &user.EmailQuery{
|
|
EmailAddress: "user1@example.com",
|
|
Method: object.TextQueryMethod_TEXT_QUERY_METHOD_EQUALS,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
level: 0,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "empty queries slice",
|
|
queries: []*user.SearchQuery{},
|
|
level: 0,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "query with error (too many nesting levels)",
|
|
queries: []*user.SearchQuery{
|
|
{
|
|
Query: &user.SearchQuery_UserNameQuery{
|
|
UserNameQuery: &user.UserNameQuery{
|
|
UserName: "testuser",
|
|
Method: object.TextQueryMethod_TEXT_QUERY_METHOD_EQUALS,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
level: 21,
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "query with invalid type",
|
|
queries: []*user.SearchQuery{
|
|
{
|
|
Query: nil,
|
|
},
|
|
},
|
|
level: 0,
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "mixed valid and invalid queries",
|
|
queries: []*user.SearchQuery{
|
|
{
|
|
Query: &user.SearchQuery_UserNameQuery{
|
|
UserNameQuery: &user.UserNameQuery{
|
|
UserName: "testuser",
|
|
Method: object.TextQueryMethod_TEXT_QUERY_METHOD_EQUALS,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Query: nil,
|
|
},
|
|
},
|
|
level: 0,
|
|
wantErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tc := range tt {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
got, err := userQueriesToQuery(tc.queries, tc.level)
|
|
if tc.wantErr {
|
|
assert.Error(t, err)
|
|
assert.Nil(t, got)
|
|
} else {
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, got)
|
|
assert.Equal(t, len(tc.queries), len(got))
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_userFieldNameToSortingColumn(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
type testCase struct {
|
|
name string
|
|
input user.UserFieldName
|
|
expected query.Column
|
|
}
|
|
|
|
tt := []testCase{
|
|
{
|
|
name: "EMAIL",
|
|
input: user.UserFieldName_USER_FIELD_NAME_EMAIL,
|
|
expected: query.HumanEmailCol,
|
|
},
|
|
{
|
|
name: "FIRST_NAME",
|
|
input: user.UserFieldName_USER_FIELD_NAME_FIRST_NAME,
|
|
expected: query.HumanFirstNameCol,
|
|
},
|
|
{
|
|
name: "LAST_NAME",
|
|
input: user.UserFieldName_USER_FIELD_NAME_LAST_NAME,
|
|
expected: query.HumanLastNameCol,
|
|
},
|
|
{
|
|
name: "DISPLAY_NAME",
|
|
input: user.UserFieldName_USER_FIELD_NAME_DISPLAY_NAME,
|
|
expected: query.HumanDisplayNameCol,
|
|
},
|
|
{
|
|
name: "USER_NAME",
|
|
input: user.UserFieldName_USER_FIELD_NAME_USER_NAME,
|
|
expected: query.UserUsernameCol,
|
|
},
|
|
{
|
|
name: "STATE",
|
|
input: user.UserFieldName_USER_FIELD_NAME_STATE,
|
|
expected: query.UserStateCol,
|
|
},
|
|
{
|
|
name: "TYPE",
|
|
input: user.UserFieldName_USER_FIELD_NAME_TYPE,
|
|
expected: query.UserTypeCol,
|
|
},
|
|
{
|
|
name: "NICK_NAME",
|
|
input: user.UserFieldName_USER_FIELD_NAME_NICK_NAME,
|
|
expected: query.HumanNickNameCol,
|
|
},
|
|
{
|
|
name: "CREATION_DATE",
|
|
input: user.UserFieldName_USER_FIELD_NAME_CREATION_DATE,
|
|
expected: query.UserCreationDateCol,
|
|
},
|
|
{
|
|
name: "UNSPECIFIED",
|
|
input: user.UserFieldName_USER_FIELD_NAME_UNSPECIFIED,
|
|
expected: query.UserIDCol,
|
|
},
|
|
{
|
|
name: "Unknown value (default)",
|
|
input: user.UserFieldName(999),
|
|
expected: query.UserIDCol,
|
|
},
|
|
}
|
|
|
|
for _, tc := range tt {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
got := userFieldNameToSortingColumn(tc.input)
|
|
assert.Equal(t, tc.expected, got)
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_userStateToPb(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
type testCase struct {
|
|
name string
|
|
input domain.UserState
|
|
expected user.UserState
|
|
}
|
|
|
|
tt := []testCase{
|
|
{
|
|
name: "Active",
|
|
input: domain.UserStateActive,
|
|
expected: user.UserState_USER_STATE_ACTIVE,
|
|
},
|
|
{
|
|
name: "Inactive",
|
|
input: domain.UserStateInactive,
|
|
expected: user.UserState_USER_STATE_INACTIVE,
|
|
},
|
|
{
|
|
name: "Deleted",
|
|
input: domain.UserStateDeleted,
|
|
expected: user.UserState_USER_STATE_DELETED,
|
|
},
|
|
{
|
|
name: "Initial",
|
|
input: domain.UserStateInitial,
|
|
expected: user.UserState_USER_STATE_INITIAL,
|
|
},
|
|
{
|
|
name: "Locked",
|
|
input: domain.UserStateLocked,
|
|
expected: user.UserState_USER_STATE_LOCKED,
|
|
},
|
|
{
|
|
name: "Unspecified",
|
|
input: domain.UserStateUnspecified,
|
|
expected: user.UserState_USER_STATE_UNSPECIFIED,
|
|
},
|
|
{
|
|
name: "Suspend",
|
|
input: domain.UserStateSuspend,
|
|
expected: user.UserState_USER_STATE_UNSPECIFIED,
|
|
},
|
|
{
|
|
name: "Unknown value (default)",
|
|
input: domain.UserState(999),
|
|
expected: user.UserState_USER_STATE_UNSPECIFIED,
|
|
},
|
|
}
|
|
|
|
for _, tc := range tt {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
got := userStateToPb(tc.input)
|
|
assert.Equal(t, tc.expected, got)
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_userTypeToPb(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tt := []struct {
|
|
testName string
|
|
inputQueryUser *query.User
|
|
expectedUserType user.UserType
|
|
}{
|
|
{
|
|
testName: "when query user is nil should return nil",
|
|
expectedUserType: nil,
|
|
},
|
|
{
|
|
testName: "when query user is human should return usertype human",
|
|
inputQueryUser: &query.User{Human: &query.Human{}},
|
|
expectedUserType: &user.User_Human{
|
|
Human: &user.HumanUser{
|
|
Profile: &user.HumanProfile{
|
|
NickName: new(string),
|
|
DisplayName: new(string),
|
|
PreferredLanguage: gu.Ptr("und"),
|
|
Gender: gu.Ptr(user.Gender_GENDER_UNSPECIFIED),
|
|
},
|
|
Email: &user.HumanEmail{},
|
|
Phone: &user.HumanPhone{},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
testName: "when query user is machine should return usertype machine",
|
|
inputQueryUser: &query.User{Machine: &query.Machine{}},
|
|
expectedUserType: &user.User_Machine{
|
|
Machine: &user.MachineUser{},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tc := range tt {
|
|
t.Run(tc.testName, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
res := userTypeToPb(tc.inputQueryUser, "asset")
|
|
|
|
assert.Equal(t, tc.expectedUserType, res)
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_UserToPb(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
now := time.Now().UTC()
|
|
|
|
type args struct {
|
|
userQ *query.User
|
|
assetPrefix string
|
|
}
|
|
tt := []struct {
|
|
name string
|
|
args args
|
|
want *user.User
|
|
}{
|
|
{
|
|
name: "nil userQ returns nil",
|
|
args: args{
|
|
userQ: nil,
|
|
assetPrefix: "prefix",
|
|
},
|
|
want: nil,
|
|
},
|
|
{
|
|
name: "basic user with human type",
|
|
args: args{
|
|
userQ: &query.User{
|
|
ID: "user-id",
|
|
Sequence: 1,
|
|
ChangeDate: now,
|
|
ResourceOwner: "owner",
|
|
CreationDate: now,
|
|
State: domain.UserStateActive,
|
|
Username: "username",
|
|
LoginNames: []string{"login1", "login2"},
|
|
PreferredLoginName: "preferred",
|
|
Human: &query.Human{},
|
|
},
|
|
assetPrefix: "prefix",
|
|
},
|
|
want: &user.User{
|
|
UserId: "user-id",
|
|
Details: &object.Details{
|
|
Sequence: 1,
|
|
ChangeDate: timestamppb.New(now),
|
|
ResourceOwner: "owner",
|
|
CreationDate: timestamppb.New(now),
|
|
},
|
|
State: user.UserState_USER_STATE_ACTIVE,
|
|
Username: "username",
|
|
LoginNames: []string{"login1", "login2"},
|
|
PreferredLoginName: "preferred",
|
|
Type: &user.User_Human{
|
|
Human: humanToPb(&query.Human{}, "prefix", "owner"),
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "basic user with machine type",
|
|
args: args{
|
|
userQ: &query.User{
|
|
ID: "user-id2",
|
|
Sequence: 2,
|
|
ChangeDate: now,
|
|
ResourceOwner: "owner2",
|
|
CreationDate: now,
|
|
State: domain.UserStateInactive,
|
|
Username: "machineuser",
|
|
LoginNames: []string{"machine1"},
|
|
PreferredLoginName: "machinepreferred",
|
|
Machine: &query.Machine{},
|
|
},
|
|
assetPrefix: "prefix2",
|
|
},
|
|
want: &user.User{
|
|
UserId: "user-id2",
|
|
Details: &object.Details{
|
|
Sequence: 2,
|
|
ChangeDate: timestamppb.New(now),
|
|
ResourceOwner: "owner2",
|
|
CreationDate: timestamppb.New(now),
|
|
},
|
|
State: user.UserState_USER_STATE_INACTIVE,
|
|
Username: "machineuser",
|
|
LoginNames: []string{"machine1"},
|
|
PreferredLoginName: "machinepreferred",
|
|
Type: &user.User_Machine{
|
|
Machine: machineToPb(&query.Machine{}),
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "user with no type returns nil Type",
|
|
args: args{
|
|
userQ: &query.User{
|
|
ID: "user-id3",
|
|
Sequence: 3,
|
|
ChangeDate: now,
|
|
ResourceOwner: "owner3",
|
|
CreationDate: now,
|
|
State: domain.UserStateDeleted,
|
|
Username: "notypeuser",
|
|
LoginNames: []string{"notype1"},
|
|
PreferredLoginName: "notypepreferred",
|
|
},
|
|
assetPrefix: "prefix3",
|
|
},
|
|
want: &user.User{
|
|
UserId: "user-id3",
|
|
Details: &object.Details{
|
|
Sequence: 3,
|
|
ChangeDate: timestamppb.New(now),
|
|
ResourceOwner: "owner3",
|
|
CreationDate: timestamppb.New(now),
|
|
},
|
|
State: user.UserState_USER_STATE_DELETED,
|
|
Username: "notypeuser",
|
|
LoginNames: []string{"notype1"},
|
|
PreferredLoginName: "notypepreferred",
|
|
Type: nil,
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tc := range tt {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
got := UserToPb(tc.args.userQ, tc.args.assetPrefix)
|
|
assert.Equal(t, tc.want, got)
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_UsersToPb(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
now := time.Now().UTC()
|
|
|
|
type args struct {
|
|
users []*query.User
|
|
assetPrefix string
|
|
}
|
|
tt := []struct {
|
|
name string
|
|
args args
|
|
want []*user.User
|
|
}{
|
|
{
|
|
name: "nil slice returns nils",
|
|
args: args{
|
|
users: nil,
|
|
assetPrefix: "prefix",
|
|
},
|
|
want: []*user.User{},
|
|
},
|
|
{
|
|
name: "empty slice returns empty slice",
|
|
args: args{
|
|
users: []*query.User{},
|
|
assetPrefix: "prefix",
|
|
},
|
|
want: []*user.User{},
|
|
},
|
|
{
|
|
name: "slice with nil user returns slice with nil",
|
|
args: args{
|
|
users: []*query.User{nil},
|
|
assetPrefix: "prefix",
|
|
},
|
|
want: []*user.User{nil},
|
|
},
|
|
{
|
|
name: "slice with one human user",
|
|
args: args{
|
|
users: []*query.User{
|
|
{
|
|
ID: "user-id",
|
|
Sequence: 1,
|
|
ChangeDate: now,
|
|
ResourceOwner: "owner",
|
|
CreationDate: now,
|
|
State: domain.UserStateActive,
|
|
Username: "username",
|
|
LoginNames: []string{"login1", "login2"},
|
|
PreferredLoginName: "preferred",
|
|
Human: &query.Human{},
|
|
},
|
|
},
|
|
assetPrefix: "prefix",
|
|
},
|
|
want: []*user.User{
|
|
{
|
|
UserId: "user-id",
|
|
Details: &object.Details{
|
|
Sequence: 1,
|
|
ChangeDate: timestamppb.New(now),
|
|
ResourceOwner: "owner",
|
|
CreationDate: timestamppb.New(now),
|
|
},
|
|
State: user.UserState_USER_STATE_ACTIVE,
|
|
Username: "username",
|
|
LoginNames: []string{"login1", "login2"},
|
|
PreferredLoginName: "preferred",
|
|
Type: &user.User_Human{
|
|
Human: humanToPb(&query.Human{}, "prefix", "owner"),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "slice with one machine user",
|
|
args: args{
|
|
users: []*query.User{
|
|
{
|
|
ID: "user-id2",
|
|
Sequence: 2,
|
|
ChangeDate: now,
|
|
ResourceOwner: "owner2",
|
|
CreationDate: now,
|
|
State: domain.UserStateInactive,
|
|
Username: "machineuser",
|
|
LoginNames: []string{"machine1"},
|
|
PreferredLoginName: "machinepreferred",
|
|
Machine: &query.Machine{},
|
|
},
|
|
},
|
|
assetPrefix: "prefix2",
|
|
},
|
|
want: []*user.User{
|
|
{
|
|
UserId: "user-id2",
|
|
Details: &object.Details{
|
|
Sequence: 2,
|
|
ChangeDate: timestamppb.New(now),
|
|
ResourceOwner: "owner2",
|
|
CreationDate: timestamppb.New(now),
|
|
},
|
|
State: user.UserState_USER_STATE_INACTIVE,
|
|
Username: "machineuser",
|
|
LoginNames: []string{"machine1"},
|
|
PreferredLoginName: "machinepreferred",
|
|
Type: &user.User_Machine{
|
|
Machine: machineToPb(&query.Machine{}),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "slice with mixed users",
|
|
args: args{
|
|
users: []*query.User{
|
|
nil,
|
|
{
|
|
ID: "user-id3",
|
|
Sequence: 3,
|
|
ChangeDate: now,
|
|
ResourceOwner: "owner3",
|
|
CreationDate: now,
|
|
State: domain.UserStateDeleted,
|
|
Username: "notypeuser",
|
|
LoginNames: []string{"notype1"},
|
|
PreferredLoginName: "notypepreferred",
|
|
},
|
|
},
|
|
assetPrefix: "prefix3",
|
|
},
|
|
want: []*user.User{
|
|
nil,
|
|
{
|
|
UserId: "user-id3",
|
|
Details: &object.Details{
|
|
Sequence: 3,
|
|
ChangeDate: timestamppb.New(now),
|
|
ResourceOwner: "owner3",
|
|
CreationDate: timestamppb.New(now),
|
|
},
|
|
State: user.UserState_USER_STATE_DELETED,
|
|
Username: "notypeuser",
|
|
LoginNames: []string{"notype1"},
|
|
PreferredLoginName: "notypepreferred",
|
|
Type: nil,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tc := range tt {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
got := UsersToPb(tc.args.users, tc.args.assetPrefix)
|
|
assert.Equal(t, tc.want, got)
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_ListUsersRequestToModel(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
firstNameQuery, err := query.NewUserFirstNameSearchQuery("first name", query.TextEquals)
|
|
require.Nil(t, err)
|
|
|
|
type args struct {
|
|
req *user.ListUsersRequest
|
|
}
|
|
tt := []struct {
|
|
name string
|
|
args args
|
|
want *query.UserSearchQueries
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "valid request with one query",
|
|
args: args{
|
|
req: &user.ListUsersRequest{
|
|
Query: &object.ListQuery{
|
|
Offset: 10,
|
|
Limit: 5,
|
|
Asc: true,
|
|
},
|
|
SortingColumn: user.UserFieldName_USER_FIELD_NAME_EMAIL,
|
|
Queries: []*user.SearchQuery{
|
|
{
|
|
Query: &user.SearchQuery_FirstNameQuery{
|
|
FirstNameQuery: &user.FirstNameQuery{
|
|
FirstName: "first name",
|
|
Method: object.TextQueryMethod_TEXT_QUERY_METHOD_EQUALS,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
want: &query.UserSearchQueries{
|
|
SearchRequest: query.SearchRequest{
|
|
Offset: 10,
|
|
Limit: 5,
|
|
Asc: true,
|
|
SortingColumn: query.HumanEmailCol,
|
|
},
|
|
Queries: []query.SearchQuery{firstNameQuery},
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "valid request with no queries",
|
|
args: args{
|
|
req: &user.ListUsersRequest{
|
|
Query: &object.ListQuery{Offset: 0, Limit: 0, Asc: false},
|
|
SortingColumn: user.UserFieldName_USER_FIELD_NAME_UNSPECIFIED,
|
|
Queries: []*user.SearchQuery{},
|
|
},
|
|
},
|
|
want: &query.UserSearchQueries{
|
|
SearchRequest: query.SearchRequest{
|
|
Offset: 0,
|
|
Limit: 0,
|
|
Asc: false,
|
|
SortingColumn: query.UserIDCol,
|
|
},
|
|
Queries: []query.SearchQuery{},
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "invalid query type returns error",
|
|
args: args{
|
|
req: &user.ListUsersRequest{
|
|
Query: &object.ListQuery{Offset: 0, Limit: 0, Asc: false},
|
|
SortingColumn: user.UserFieldName_USER_FIELD_NAME_EMAIL,
|
|
Queries: []*user.SearchQuery{
|
|
{Query: nil},
|
|
},
|
|
},
|
|
},
|
|
want: nil,
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "nil request returns zero values",
|
|
args: args{
|
|
req: nil,
|
|
},
|
|
want: &query.UserSearchQueries{
|
|
SearchRequest: query.SearchRequest{
|
|
Offset: 0,
|
|
Limit: 0,
|
|
Asc: false,
|
|
SortingColumn: query.UserIDCol,
|
|
},
|
|
Queries: []query.SearchQuery{},
|
|
},
|
|
wantErr: false,
|
|
},
|
|
}
|
|
|
|
for _, tc := range tt {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
got, err := ListUsersRequestToModel(tc.args.req)
|
|
if tc.wantErr {
|
|
assert.Error(t, err)
|
|
assert.Nil(t, got)
|
|
} else {
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, tc.want, got)
|
|
}
|
|
})
|
|
}
|
|
}
|