Skip to content

Commit 08fa3a7

Browse files
committed
feat: add filter by status on GET /users
1 parent a7fb018 commit 08fa3a7

File tree

6 files changed

+78
-28
lines changed

6 files changed

+78
-28
lines changed

coderd/database/databasefake/databasefake.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,17 @@ func (q *fakeQuerier) GetUsers(_ context.Context, params database.GetUsersParams
225225
}
226226
users = users[:params.LimitOpt]
227227
}
228+
229+
if params.Status != "" {
230+
usersFilteredByStatus := make([]database.User, 0, len(users))
231+
for i, user := range users {
232+
if user.Status == params.Status {
233+
usersFilteredByStatus = append(usersFilteredByStatus, users[i])
234+
}
235+
}
236+
users = usersFilteredByStatus
237+
}
238+
228239
tmp := make([]database.User, len(users))
229240
copy(tmp, users)
230241

coderd/database/queries.sql.go

Lines changed: 11 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/queries/users.sql

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ WHERE
8080
WHEN @search :: text != '' THEN (
8181
email LIKE concat('%', @search, '%')
8282
OR username LIKE concat('%', @search, '%')
83+
)
84+
WHEN @status :: user_status != '' THEN (
85+
status = @status
8386
)
8487
ELSE true
8588
END

coderd/users.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,11 @@ func (api *api) postFirstUser(rw http.ResponseWriter, r *http.Request) {
9090

9191
func (api *api) users(rw http.ResponseWriter, r *http.Request) {
9292
var (
93-
afterArg = r.URL.Query().Get("after_user")
94-
limitArg = r.URL.Query().Get("limit")
95-
offsetArg = r.URL.Query().Get("offset")
96-
searchName = r.URL.Query().Get("search")
93+
afterArg = r.URL.Query().Get("after_user")
94+
limitArg = r.URL.Query().Get("limit")
95+
offsetArg = r.URL.Query().Get("offset")
96+
searchName = r.URL.Query().Get("search")
97+
statusFilter = r.URL.Query().Get("status")
9798
)
9899

99100
// createdAfter is a user uuid.
@@ -136,6 +137,7 @@ func (api *api) users(rw http.ResponseWriter, r *http.Request) {
136137
OffsetOpt: int32(offset),
137138
LimitOpt: int32(pageLimit),
138139
Search: searchName,
140+
Status: database.UserStatus(statusFilter),
139141
})
140142

141143
if err != nil {

coderd/users_test.go

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -328,18 +328,44 @@ func TestUserByName(t *testing.T) {
328328

329329
func TestGetUsers(t *testing.T) {
330330
t.Parallel()
331-
client := coderdtest.New(t, nil)
332-
user := coderdtest.CreateFirstUser(t, client)
333-
client.CreateUser(context.Background(), codersdk.CreateUserRequest{
334-
Email: "alice@email.com",
335-
Username: "alice",
336-
Password: "password",
337-
OrganizationID: user.OrganizationID,
331+
t.Run("AllUsers", func(t *testing.T) {
332+
t.Parallel()
333+
client := coderdtest.New(t, nil)
334+
user := coderdtest.CreateFirstUser(t, client)
335+
client.CreateUser(context.Background(), codersdk.CreateUserRequest{
336+
Email: "alice@email.com",
337+
Username: "alice",
338+
Password: "password",
339+
OrganizationID: user.OrganizationID,
340+
})
341+
// No params is all users
342+
users, err := client.Users(context.Background(), codersdk.UsersRequest{})
343+
require.NoError(t, err)
344+
require.Len(t, users, 2)
345+
})
346+
t.Run("ActiveUsers", func(t *testing.T) {
347+
t.Parallel()
348+
client := coderdtest.New(t, nil)
349+
user := coderdtest.CreateFirstUser(t, client)
350+
client.CreateUser(context.Background(), codersdk.CreateUserRequest{
351+
Email: "alice@email.com",
352+
Username: "alice",
353+
Password: "password",
354+
OrganizationID: user.OrganizationID,
355+
})
356+
suspendedUser, _ := client.CreateUser(context.Background(), codersdk.CreateUserRequest{
357+
Email: "bruno@email.com",
358+
Username: "bruno",
359+
Password: "password",
360+
OrganizationID: user.OrganizationID,
361+
})
362+
client.SuspendUser(context.Background(), suspendedUser.ID)
363+
users, err := client.Users(context.Background(), codersdk.UsersRequest{
364+
Status: string(codersdk.UserStatusSuspended),
365+
})
366+
require.NoError(t, err)
367+
require.Len(t, users, 2)
338368
})
339-
// No params is all users
340-
users, err := client.Users(context.Background(), codersdk.UsersRequest{})
341-
require.NoError(t, err)
342-
require.Len(t, users, 2)
343369
}
344370

345371
func TestOrganizationsByUser(t *testing.T) {

codersdk/users.go

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@ import (
1414
// Me is used as a replacement for your own ID.
1515
var Me = uuid.Nil
1616

17+
type UserStatus string
18+
19+
const (
20+
UserStatusActive UserStatus = "active"
21+
UserStatusSuspended UserStatus = "suspended"
22+
)
23+
1724
type UsersRequest struct {
1825
AfterUser uuid.UUID `json:"after_user"`
1926
Search string `json:"search"`
@@ -26,15 +33,10 @@ type UsersRequest struct {
2633
// To get the next page, use offset=<limit>*<page_number>.
2734
// Offset is 0 indexed, so the first record sits at offset 0.
2835
Offset int `json:"offset"`
36+
// Filter users by status
37+
Status string `json:"status"`
2938
}
3039

31-
type UserStatus string
32-
33-
const (
34-
UserStatusActive UserStatus = "active"
35-
UserStatusSuspended UserStatus = "suspended"
36-
)
37-
3840
// User represents a user in Coder.
3941
type User struct {
4042
ID uuid.UUID `json:"id" validate:"required"`
@@ -242,6 +244,7 @@ func (c *Client) Users(ctx context.Context, req UsersRequest) ([]User, error) {
242244
}
243245
q.Set("offset", strconv.Itoa(req.Offset))
244246
q.Set("search", req.Search)
247+
q.Set("status", req.Status)
245248
r.URL.RawQuery = q.Encode()
246249
})
247250
if err != nil {

0 commit comments

Comments
 (0)