From 19140926b921dad20c6c24f4edf05082b9461072 Mon Sep 17 00:00:00 2001 From: Bruno Date: Fri, 15 Apr 2022 15:49:30 +0000 Subject: [PATCH 1/3] feat: add GET /api/v2/users --- coderd/coderd.go | 1 + coderd/database/databasefake/databasefake.go | 7 ++++ coderd/database/querier.go | 1 + coderd/database/queries.sql.go | 40 ++++++++++++++++++++ coderd/database/queries/users.sql | 6 +++ coderd/users.go | 19 ++++++++++ coderd/users_test.go | 15 ++++++++ codersdk/users.go | 13 +++++++ peerbroker/proto/peerbroker.pb.go | 2 +- provisionerd/proto/provisionerd.pb.go | 2 +- provisionersdk/proto/provisioner.pb.go | 2 +- 11 files changed, 105 insertions(+), 3 deletions(-) diff --git a/coderd/coderd.go b/coderd/coderd.go index dde99869c5464..847b871c260c8 100644 --- a/coderd/coderd.go +++ b/coderd/coderd.go @@ -138,6 +138,7 @@ func New(options *Options) (http.Handler, func()) { }) }) r.Route("/users", func(r chi.Router) { + r.Get("/", api.getUsers) r.Get("/first", api.firstUser) r.Post("/first", api.postFirstUser) r.Post("/login", api.postLogin) diff --git a/coderd/database/databasefake/databasefake.go b/coderd/database/databasefake/databasefake.go index 8e582d85c5ddc..aac3531a77c29 100644 --- a/coderd/database/databasefake/databasefake.go +++ b/coderd/database/databasefake/databasefake.go @@ -164,6 +164,13 @@ func (q *fakeQuerier) GetUserCount(_ context.Context) (int64, error) { return int64(len(q.users)), nil } +func (q *fakeQuerier) GetUsers(_ context.Context) ([]database.User, error) { + q.mutex.RLock() + defer q.mutex.RUnlock() + + return q.users, nil +} + func (q *fakeQuerier) GetWorkspacesByTemplateID(_ context.Context, arg database.GetWorkspacesByTemplateIDParams) ([]database.Workspace, error) { q.mutex.RLock() defer q.mutex.RUnlock() diff --git a/coderd/database/querier.go b/coderd/database/querier.go index 073113a2451df..d993a5ab31075 100644 --- a/coderd/database/querier.go +++ b/coderd/database/querier.go @@ -38,6 +38,7 @@ type querier interface { GetUserByEmailOrUsername(ctx context.Context, arg GetUserByEmailOrUsernameParams) (User, error) GetUserByID(ctx context.Context, id uuid.UUID) (User, error) GetUserCount(ctx context.Context) (int64, error) + GetUsers(ctx context.Context) ([]User, error) GetWorkspaceAgentByAuthToken(ctx context.Context, authToken uuid.UUID) (WorkspaceAgent, error) GetWorkspaceAgentByID(ctx context.Context, id uuid.UUID) (WorkspaceAgent, error) GetWorkspaceAgentByInstanceID(ctx context.Context, authInstanceID string) (WorkspaceAgent, error) diff --git a/coderd/database/queries.sql.go b/coderd/database/queries.sql.go index b8550e38a1180..49fb4dc759fa2 100644 --- a/coderd/database/queries.sql.go +++ b/coderd/database/queries.sql.go @@ -1851,6 +1851,46 @@ func (q *sqlQuerier) GetUserCount(ctx context.Context) (int64, error) { return count, err } +const getUsers = `-- name: GetUsers :many +SELECT + id, email, name, revoked, login_type, hashed_password, created_at, updated_at, username +FROM + users +` + +func (q *sqlQuerier) GetUsers(ctx context.Context) ([]User, error) { + rows, err := q.db.QueryContext(ctx, getUsers) + if err != nil { + return nil, err + } + defer rows.Close() + var items []User + for rows.Next() { + var i User + if err := rows.Scan( + &i.ID, + &i.Email, + &i.Name, + &i.Revoked, + &i.LoginType, + &i.HashedPassword, + &i.CreatedAt, + &i.UpdatedAt, + &i.Username, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + const insertUser = `-- name: InsertUser :one INSERT INTO users ( diff --git a/coderd/database/queries/users.sql b/coderd/database/queries/users.sql index f41a96877d4d6..46e8c330ef0f1 100644 --- a/coderd/database/queries/users.sql +++ b/coderd/database/queries/users.sql @@ -51,3 +51,9 @@ SET updated_at = $5 WHERE id = $1 RETURNING *; + +-- name: GetUsers :many +SELECT + * +FROM + users; diff --git a/coderd/users.go b/coderd/users.go index 6fcab0814033f..e579dd809b59f 100644 --- a/coderd/users.go +++ b/coderd/users.go @@ -23,6 +23,25 @@ import ( "github.com/coder/coder/cryptorand" ) +// Lists all the users +func (api *api) getUsers(rw http.ResponseWriter, r *http.Request) { + users, err := api.Database.GetUsers(r.Context()) + + if err != nil { + httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ + Message: fmt.Sprintf("get users: %s", err.Error()), + }) + return + } + + var res []codersdk.User + for _, user := range users { + res = append(res, convertUser(user)) + } + + httpapi.Write(rw, http.StatusOK, res) +} + // Returns whether the initial user has been created or not. func (api *api) firstUser(rw http.ResponseWriter, r *http.Request) { userCount, err := api.Database.GetUserCount(r.Context()) diff --git a/coderd/users_test.go b/coderd/users_test.go index d733f022ae560..35bfea01e9ece 100644 --- a/coderd/users_test.go +++ b/coderd/users_test.go @@ -313,6 +313,21 @@ func TestUserByName(t *testing.T) { require.NoError(t, err) } +func TestGetUsers(t *testing.T) { + t.Parallel() + client := coderdtest.New(t, nil) + user := coderdtest.CreateFirstUser(t, client) + client.CreateUser(context.Background(), codersdk.CreateUserRequest{ + Email: "bruno@coder.com", + Username: "bruno", + Password: "password", + OrganizationID: user.OrganizationID, + }) + users, err := client.GetUsers(context.Background()) + require.NoError(t, err) + require.Len(t, users, 2) +} + func TestOrganizationsByUser(t *testing.T) { t.Parallel() client := coderdtest.New(t, nil) diff --git a/codersdk/users.go b/codersdk/users.go index d6a920a4c4bdc..a2939afd9bbc7 100644 --- a/codersdk/users.go +++ b/codersdk/users.go @@ -136,6 +136,19 @@ func (c *Client) UpdateUserProfile(ctx context.Context, userID uuid.UUID, req Up return user, json.NewDecoder(res.Body).Decode(&user) } +func (c *Client) GetUsers(ctx context.Context) ([]User, error) { + res, err := c.request(ctx, http.MethodGet, "/api/v2/users", nil) + if err != nil { + return []User{}, err + } + defer res.Body.Close() + if res.StatusCode != http.StatusOK { + return []User{}, readBodyAsError(res) + } + var users []User + return users, json.NewDecoder(res.Body).Decode(&users) +} + // CreateAPIKey generates an API key for the user ID provided. func (c *Client) CreateAPIKey(ctx context.Context, userID uuid.UUID) (*GenerateAPIKeyResponse, error) { res, err := c.request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/users/%s/keys", uuidOrMe(userID)), nil) diff --git a/peerbroker/proto/peerbroker.pb.go b/peerbroker/proto/peerbroker.pb.go index b1a880bf8ce36..8a443e6e42192 100644 --- a/peerbroker/proto/peerbroker.pb.go +++ b/peerbroker/proto/peerbroker.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0 -// protoc v3.19.4 +// protoc v3.6.1 // source: peerbroker/proto/peerbroker.proto package proto diff --git a/provisionerd/proto/provisionerd.pb.go b/provisionerd/proto/provisionerd.pb.go index d7d835df2275d..27f3301b083cf 100644 --- a/provisionerd/proto/provisionerd.pb.go +++ b/provisionerd/proto/provisionerd.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0 -// protoc v3.19.4 +// protoc v3.6.1 // source: provisionerd/proto/provisionerd.proto package proto diff --git a/provisionersdk/proto/provisioner.pb.go b/provisionersdk/proto/provisioner.pb.go index 72d37a0083f94..cdb0f4ee271a0 100644 --- a/provisionersdk/proto/provisioner.pb.go +++ b/provisionersdk/proto/provisioner.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0 -// protoc v3.19.4 +// protoc v3.6.1 // source: provisionersdk/proto/provisioner.proto package proto From 1841e7f7f1d6e11a5f40cd1aba4f40fde27f4cbf Mon Sep 17 00:00:00 2001 From: Bruno Date: Fri, 15 Apr 2022 15:58:50 +0000 Subject: [PATCH 2/3] fix: requires auth to get all users --- coderd/coderd.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coderd/coderd.go b/coderd/coderd.go index 847b871c260c8..0a33af6f72070 100644 --- a/coderd/coderd.go +++ b/coderd/coderd.go @@ -138,7 +138,6 @@ func New(options *Options) (http.Handler, func()) { }) }) r.Route("/users", func(r chi.Router) { - r.Get("/", api.getUsers) r.Get("/first", api.firstUser) r.Post("/first", api.postFirstUser) r.Post("/login", api.postLogin) @@ -146,6 +145,7 @@ func New(options *Options) (http.Handler, func()) { r.Group(func(r chi.Router) { r.Use(httpmw.ExtractAPIKey(options.Database, nil)) r.Post("/", api.postUsers) + r.Get("/", api.getUsers) r.Route("/{user}", func(r chi.Router) { r.Use(httpmw.ExtractUserParam(options.Database)) r.Get("/", api.userByName) From e90c285b253d18eb3e4a9d2e1fdf65571ec2d20a Mon Sep 17 00:00:00 2001 From: Bruno Date: Mon, 18 Apr 2022 17:08:10 +0000 Subject: [PATCH 3/3] style: rename getUsers to user and update protoc version --- coderd/coderd.go | 2 +- coderd/users.go | 2 +- peerbroker/proto/peerbroker.pb.go | 2 +- provisionerd/proto/provisionerd.pb.go | 2 +- provisionersdk/proto/provisioner.pb.go | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/coderd/coderd.go b/coderd/coderd.go index 0a33af6f72070..0f3c4537f6a71 100644 --- a/coderd/coderd.go +++ b/coderd/coderd.go @@ -145,7 +145,7 @@ func New(options *Options) (http.Handler, func()) { r.Group(func(r chi.Router) { r.Use(httpmw.ExtractAPIKey(options.Database, nil)) r.Post("/", api.postUsers) - r.Get("/", api.getUsers) + r.Get("/", api.users) r.Route("/{user}", func(r chi.Router) { r.Use(httpmw.ExtractUserParam(options.Database)) r.Get("/", api.userByName) diff --git a/coderd/users.go b/coderd/users.go index e579dd809b59f..aff5443d27f54 100644 --- a/coderd/users.go +++ b/coderd/users.go @@ -24,7 +24,7 @@ import ( ) // Lists all the users -func (api *api) getUsers(rw http.ResponseWriter, r *http.Request) { +func (api *api) users(rw http.ResponseWriter, r *http.Request) { users, err := api.Database.GetUsers(r.Context()) if err != nil { diff --git a/peerbroker/proto/peerbroker.pb.go b/peerbroker/proto/peerbroker.pb.go index 8a443e6e42192..b1a880bf8ce36 100644 --- a/peerbroker/proto/peerbroker.pb.go +++ b/peerbroker/proto/peerbroker.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0 -// protoc v3.6.1 +// protoc v3.19.4 // source: peerbroker/proto/peerbroker.proto package proto diff --git a/provisionerd/proto/provisionerd.pb.go b/provisionerd/proto/provisionerd.pb.go index 27f3301b083cf..d7d835df2275d 100644 --- a/provisionerd/proto/provisionerd.pb.go +++ b/provisionerd/proto/provisionerd.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0 -// protoc v3.6.1 +// protoc v3.19.4 // source: provisionerd/proto/provisionerd.proto package proto diff --git a/provisionersdk/proto/provisioner.pb.go b/provisionersdk/proto/provisioner.pb.go index cdb0f4ee271a0..72d37a0083f94 100644 --- a/provisionersdk/proto/provisioner.pb.go +++ b/provisionersdk/proto/provisioner.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0 -// protoc v3.6.1 +// protoc v3.19.4 // source: provisionersdk/proto/provisioner.proto package proto