From 16906d2c2ce15462210029952304c5000f970190 Mon Sep 17 00:00:00 2001 From: Livio Spring Date: Tue, 23 Sep 2025 11:39:05 +0200 Subject: [PATCH] fix(export): add sorting when searching users to prevent error (#10777) # Which Problems Are Solved When exporting users, an error `QUERY-AG4gs` was returned. This was due to #10750, where the orderBy column was added to the query to prevent the exact same error. In case there was no sorting column specified, such as the export, the query would fail. # How the Problems Are Solved - Added a default sorting on `id` as we already have for the other APIs. # Additional Changes None # Additional Context - reported through support - relates to #10750, #10415 - backport to v4.x --- internal/query/user.go | 3 ++ internal/query/user_test.go | 84 +++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) diff --git a/internal/query/user.go b/internal/query/user.go index c9289ce7a84..a7ffff7d8b0 100644 --- a/internal/query/user.go +++ b/internal/query/user.go @@ -1271,6 +1271,9 @@ func prepareUserUniqueQuery() (sq.SelectBuilder, func(*sql.Row) (bool, error)) { } func prepareUsersQuery(orderBy Column) (sq.SelectBuilder, func(*sql.Rows) (*Users, error)) { + if orderBy.isZero() { + orderBy = UserIDCol + } return sq.Select( UserIDCol.identifier(), UserCreationDateCol.identifier(), diff --git a/internal/query/user_test.go b/internal/query/user_test.go index 809b778becb..c67eee286f4 100644 --- a/internal/query/user_test.go +++ b/internal/query/user_test.go @@ -1050,6 +1050,90 @@ func Test_UserPrepares(t *testing.T) { }, }, }, + { + name: "prepareUsersQuery one result, no sorting", + prepare: func() (sq.SelectBuilder, func(*sql.Rows) (*Users, error)) { + return prepareUsersQuery(Column{}) + }, + want: want{ + sqlExpectations: mockQueries( + regexp.QuoteMeta(usersQuery), + usersCols, + [][]driver.Value{ + { + "id", + testNow, + testNow, + "resource_owner", + uint64(20211108), + domain.UserStateActive, + domain.UserTypeHuman, + "username", + database.TextArray[string]{"login_name1", "login_name2"}, + "login_name1", + // human + "id", + "first_name", + "last_name", + "nick_name", + "display_name", + "de", + domain.GenderUnspecified, + "avatar_key", + "email", + true, + "phone", + true, + true, + testNow, + testNow, + // machine + nil, + nil, + nil, + nil, + nil, + "id", // orderBy col + }, + }, + ), + }, + object: &Users{ + SearchResponse: SearchResponse{ + Count: 1, + }, + Users: []*User{ + { + ID: "id", + CreationDate: testNow, + ChangeDate: testNow, + ResourceOwner: "resource_owner", + Sequence: 20211108, + State: domain.UserStateActive, + Type: domain.UserTypeHuman, + Username: "username", + LoginNames: database.TextArray[string]{"login_name1", "login_name2"}, + PreferredLoginName: "login_name1", + Human: &Human{ + FirstName: "first_name", + LastName: "last_name", + NickName: "nick_name", + DisplayName: "display_name", + AvatarKey: "avatar_key", + PreferredLanguage: language.German, + Gender: domain.GenderUnspecified, + Email: "email", + IsEmailVerified: true, + Phone: "phone", + IsPhoneVerified: true, + PasswordChangeRequired: true, + PasswordChanged: testNow, + MFAInitSkipped: testNow, + }, + }, + }, + }, + }, { name: "prepareUsersQuery multiple results", prepare: func() (sq.SelectBuilder, func(*sql.Rows) (*Users, error)) {