diff --git a/internal/api/user_handlers_test.go b/internal/api/user_handlers_test.go index 42ee318..9b34211 100644 --- a/internal/api/user_handlers_test.go +++ b/internal/api/user_handlers_test.go @@ -94,6 +94,45 @@ func TestAdminListUsers_SnakeCaseShape(t *testing.T) { } } +func TestAdminListUsers_SearchMatchesUserID(t *testing.T) { + ts := testutil.NewTestServer(t) + ctx := context.Background() + now := time.Now().UTC() + + u := &storage.User{ + ID: "usr_agent_owner_123", + Email: "agent-owner@example.com", + HashType: "argon2id", + Metadata: "{}", + CreatedAt: now.Format(time.RFC3339), + UpdatedAt: now.Format(time.RFC3339), + } + if err := ts.Store.CreateUser(ctx, u); err != nil { + t.Fatal(err) + } + + resp := ts.GetWithAdminKey("/api/v1/users?search=usr_agent_owner_123") + if resp.StatusCode != http.StatusOK { + t.Fatalf("expected 200, got %d", resp.StatusCode) + } + + var body struct { + Users []struct { + ID string `json:"id"` + Email string `json:"email"` + } `json:"users"` + Total int `json:"total"` + } + ts.DecodeJSON(resp, &body) + + if body.Total != 1 { + t.Fatalf("total: got %d, want 1", body.Total) + } + if len(body.Users) != 1 || body.Users[0].ID != "usr_agent_owner_123" { + t.Fatalf("users: got %+v, want usr_agent_owner_123", body.Users) + } +} + // TestAdminGetUser_SnakeCaseShape verifies the single-user endpoint also // emits snake_case keys. func TestAdminGetUser_SnakeCaseShape(t *testing.T) { diff --git a/internal/storage/sqlite.go b/internal/storage/sqlite.go index d194840..1c97326 100644 --- a/internal/storage/sqlite.go +++ b/internal/storage/sqlite.go @@ -257,9 +257,9 @@ func userListConditions(opts ListUsersOpts) ([]string, []interface{}) { args = append(args, opts.RoleID) } if opts.Search != "" { - conditions = append(conditions, `(email LIKE ? OR name LIKE ?)`) + conditions = append(conditions, `(id LIKE ? OR email LIKE ? OR name LIKE ?)`) search := "%" + opts.Search + "%" - args = append(args, search, search) + args = append(args, search, search, search) } if opts.MFAEnabled != nil { conditions = append(conditions, `mfa_enabled = ?`) diff --git a/internal/storage/storage.go b/internal/storage/storage.go index 93b5a52..99765fa 100644 --- a/internal/storage/storage.go +++ b/internal/storage/storage.go @@ -731,7 +731,7 @@ type DayCount struct { type ListUsersOpts struct { Limit int Offset int - Search string // optional email/name search + Search string // optional id/email/name search MFAEnabled *bool // filter by mfa_enabled EmailVerified *bool // filter by email_verified RoleID string // filter by role assignment