Skip to content

Commit 34d898a

Browse files
committed
Add comments
1 parent ad85b71 commit 34d898a

File tree

14 files changed

+244
-53
lines changed

14 files changed

+244
-53
lines changed

Makefile

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,14 @@ else
2727
endif
2828
.PHONY: fmt/prettier
2929

30-
fmt: fmt/prettier
30+
fmt/sql:
31+
npx sql-formatter \
32+
--language postgresql \
33+
--lines-between-queries 2 \
34+
./database/query.sql \
35+
--output ./database/query.sql
36+
37+
fmt: fmt/prettier fmt/sql
3138
.PHONY: fmt
3239

3340
gen: database/generate peerbroker/proto provisionersdk/proto

coderd/coderdtest/coderdtest.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,21 @@ func New(t *testing.T) Server {
3636
require.NoError(t, err)
3737
t.Cleanup(srv.Close)
3838

39-
client := codersdk.New(u, &codersdk.Options{})
39+
client := codersdk.New(u)
4040
_, err = client.CreateInitialUser(context.Background(), coderd.CreateUserRequest{
4141
Email: "testuser@coder.com",
4242
Username: "testuser",
4343
Password: "testpassword",
4444
})
4545
require.NoError(t, err)
4646

47-
err = client.LoginWithPassword(context.Background(), coderd.LoginWithPasswordRequest{
47+
login, err := client.LoginWithPassword(context.Background(), coderd.LoginWithPasswordRequest{
4848
Email: "testuser@coder.com",
4949
Password: "testpassword",
5050
})
5151
require.NoError(t, err)
52+
err = client.SetSessionToken(login.SessionToken)
53+
require.NoError(t, err)
5254

5355
return Server{
5456
Client: client,

coderd/users.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,24 +19,28 @@ import (
1919
"github.com/coder/coder/httpmw"
2020
)
2121

22+
// User is the JSON representation of a Coder user.
2223
type User struct {
2324
ID string `json:"id" validate:"required"`
2425
Email string `json:"email" validate:"required"`
2526
CreatedAt time.Time `json:"created_at" validate:"required"`
2627
Username string `json:"username" validate:"required"`
2728
}
2829

30+
// CreateUserRequest enables callers to create a new user.
2931
type CreateUserRequest struct {
3032
Email string `json:"email" validate:"required,email"`
3133
Username string `json:"username" validate:"required,username"`
3234
Password string `json:"password" validate:"required"`
3335
}
3436

37+
// LoginWithPasswordRequest enables callers to authenticate with email and password.
3538
type LoginWithPasswordRequest struct {
3639
Email string `json:"email" validate:"required,email"`
3740
Password string `json:"password" validate:"required"`
3841
}
3942

43+
// LoginWithPasswordResponse contains a session token for the newly authenticated user.
4044
type LoginWithPasswordResponse struct {
4145
SessionToken string `json:"session_token" validate:"required"`
4246
}
@@ -51,13 +55,15 @@ func (users *users) createInitialUser(rw http.ResponseWriter, r *http.Request) {
5155
if !httpapi.Read(rw, r, &createUser) {
5256
return
5357
}
58+
// This should only function for the first user.
5459
userCount, err := users.Database.GetUserCount(r.Context())
5560
if err != nil {
5661
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
5762
Message: fmt.Sprintf("get user count: %s", err.Error()),
5863
})
5964
return
6065
}
66+
// If a user already exists, the initial admin user no longer can be created.
6167
if userCount != 0 {
6268
httpapi.Write(rw, http.StatusConflict, httpapi.Response{
6369
Message: "the initial user has already been created",
@@ -116,6 +122,7 @@ func (users *users) getAuthenticatedUser(rw http.ResponseWriter, r *http.Request
116122
})
117123
}
118124

125+
// Authenticates the user with an email and password.
119126
func (users *users) loginWithPassword(rw http.ResponseWriter, r *http.Request) {
120127
var loginWithPassword LoginWithPasswordRequest
121128
if !httpapi.Read(rw, r, &loginWithPassword) {
@@ -170,6 +177,7 @@ func (users *users) loginWithPassword(rw http.ResponseWriter, r *http.Request) {
170177
return
171178
}
172179

180+
// This format is consumed by the APIKey middleware.
173181
sessionToken := fmt.Sprintf("%s-%s", id, secret)
174182
http.SetCookie(rw, &http.Cookie{
175183
Name: httpmw.AuthCookie,
@@ -185,6 +193,7 @@ func (users *users) loginWithPassword(rw http.ResponseWriter, r *http.Request) {
185193
})
186194
}
187195

196+
// Generates a new ID and secret for an API key.
188197
func generateAPIKeyIDSecret() (string, string, error) {
189198
// Length of an API Key ID.
190199
id, err := cryptorand.String(10)

coderd/users_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ func TestUsers(t *testing.T) {
3333
t.Run("LoginNoEmail", func(t *testing.T) {
3434
t.Parallel()
3535
server := coderdtest.New(t)
36-
err := server.Client.LoginWithPassword(context.Background(), coderd.LoginWithPasswordRequest{
36+
_, err := server.Client.LoginWithPassword(context.Background(), coderd.LoginWithPasswordRequest{
3737
Email: "hello@io.io",
3838
Password: "wowie",
3939
})
@@ -46,7 +46,7 @@ func TestUsers(t *testing.T) {
4646
user, err := server.Client.User(context.Background(), "")
4747
require.NoError(t, err)
4848

49-
err = server.Client.LoginWithPassword(context.Background(), coderd.LoginWithPasswordRequest{
49+
_, err = server.Client.LoginWithPassword(context.Background(), coderd.LoginWithPasswordRequest{
5050
Email: user.Email,
5151
Password: "bananas",
5252
})

codersdk/client.go

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,34 +17,22 @@ import (
1717
"github.com/coder/coder/httpmw"
1818
)
1919

20-
type Options struct {
21-
SessionToken string
22-
HTTPClient *http.Client
23-
}
24-
25-
func New(url *url.URL, options *Options) *Client {
26-
if options == nil {
27-
options = &Options{}
28-
}
29-
if options.HTTPClient == nil {
30-
// Don't use http.DefaultClient because we override
31-
// all the cookies!
32-
options.HTTPClient = &http.Client{}
33-
}
20+
// New creates a Coder client for the provided URL.
21+
func New(url *url.URL) *Client {
3422
return &Client{
35-
url: url,
36-
sessionToken: options.SessionToken,
37-
httpClient: options.HTTPClient,
23+
url: url,
24+
httpClient: &http.Client{},
3825
}
3926
}
4027

28+
// Client is an HTTP caller for methods to the Coder API.
4129
type Client struct {
42-
url *url.URL
43-
sessionToken string
44-
httpClient *http.Client
30+
url *url.URL
31+
httpClient *http.Client
4532
}
4633

47-
func (c *Client) setSessionToken(token string) error {
34+
// SetSessionToken applies the provided token to the current client.
35+
func (c *Client) SetSessionToken(token string) error {
4836
if c.httpClient.Jar == nil {
4937
var err error
5038
c.httpClient.Jar, err = cookiejar.New(nil)
@@ -56,10 +44,11 @@ func (c *Client) setSessionToken(token string) error {
5644
Name: httpmw.AuthCookie,
5745
Value: token,
5846
}})
59-
c.sessionToken = token
6047
return nil
6148
}
6249

50+
// request performs an HTTP request with the body provided.
51+
// The caller is responsible for closing the response body.
6352
func (c *Client) request(ctx context.Context, method, path string, body interface{}) (*http.Response, error) {
6453
url, err := c.url.Parse(path)
6554
if err != nil {
@@ -91,6 +80,8 @@ func (c *Client) request(ctx context.Context, method, path string, body interfac
9180
return resp, err
9281
}
9382

83+
// readBodyAsError reads the response as an httpapi.Message, and
84+
// wraps it in a codersdk.Error type for easy marshalling.
9485
func readBodyAsError(res *http.Response) error {
9586
var m httpapi.Response
9687
err := json.NewDecoder(res.Body).Decode(&m)
@@ -109,6 +100,7 @@ func readBodyAsError(res *http.Response) error {
109100
}
110101
}
111102

103+
// Error represents an unaccepted or invalid request to the API.
112104
type Error struct {
113105
httpapi.Response
114106

codersdk/users.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ import (
99
"github.com/coder/coder/coderd"
1010
)
1111

12+
// CreateInitialUser attempts to create the first user on a Coder deployment.
13+
// This initial user has superadmin privileges. If >0 users exist, this request
14+
// will fail.
1215
func (c *Client) CreateInitialUser(ctx context.Context, req coderd.CreateUserRequest) (coderd.User, error) {
1316
res, err := c.request(ctx, http.MethodPost, "/api/v2/user", req)
1417
if err != nil {
@@ -37,20 +40,22 @@ func (c *Client) User(ctx context.Context, id string) (coderd.User, error) {
3740
return user, json.NewDecoder(res.Body).Decode(&user)
3841
}
3942

40-
func (c *Client) LoginWithPassword(ctx context.Context, req coderd.LoginWithPasswordRequest) error {
43+
// LoginWithPassword creates a session token authenticating with an email and password.
44+
// Call `SetSessionToken()` to apply the newly acquired token to the client.
45+
func (c *Client) LoginWithPassword(ctx context.Context, req coderd.LoginWithPasswordRequest) (coderd.LoginWithPasswordResponse, error) {
4146
res, err := c.request(ctx, http.MethodPost, "/api/v2/login", req)
4247
if err != nil {
43-
return err
48+
return coderd.LoginWithPasswordResponse{}, err
4449
}
4550
defer res.Body.Close()
4651
if res.StatusCode != http.StatusCreated {
4752
fmt.Printf("Are we reading here?\n")
48-
return readBodyAsError(res)
53+
return coderd.LoginWithPasswordResponse{}, readBodyAsError(res)
4954
}
5055
var resp coderd.LoginWithPasswordResponse
5156
err = json.NewDecoder(res.Body).Decode(&resp)
5257
if err != nil {
53-
return err
58+
return coderd.LoginWithPasswordResponse{}, err
5459
}
55-
return c.setSessionToken(resp.SessionToken)
60+
return coderd.LoginWithPasswordResponse{}, nil
5661
}

database/databasefake/databasefake.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ func New() database.Store {
1515
}
1616
}
1717

18+
// fakeQuerier replicates database functionality to enable quick testing.
1819
type fakeQuerier struct {
1920
apiKeys []database.APIKey
2021
users []database.User

database/query.sql

Lines changed: 90 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,106 @@
1+
-- Database queries are generated using sqlc. See:
2+
-- https://docs.sqlc.dev/en/latest/tutorials/getting-started-postgresql.html
3+
--
4+
-- Run "make gen" to generate models and query functions.
5+
16
-- name: GetAPIKeyByID :one
27
SELECT
3-
*
8+
*
49
FROM
5-
api_keys
10+
api_keys
611
WHERE
7-
id = $1
8-
LIMIT 1;
12+
id = $1
13+
LIMIT
14+
1;
915

1016
-- name: GetUserByID :one
11-
SELECT * FROM users WHERE id = $1 LIMIT 1;
17+
SELECT
18+
*
19+
FROM
20+
users
21+
WHERE
22+
id = $1
23+
LIMIT
24+
1;
1225

1326
-- name: GetUserByEmailOrUsername :one
14-
SELECT * FROM users WHERE username = $1 OR email = $2 LIMIT 1;
27+
SELECT
28+
*
29+
FROM
30+
users
31+
WHERE
32+
username = $1
33+
OR email = $2
34+
LIMIT
35+
1;
1536

1637
-- name: GetUserCount :one
17-
SELECT COUNT(*) FROM users;
38+
SELECT
39+
COUNT(*)
40+
FROM
41+
users;
1842

1943
-- name: InsertAPIKey :one
20-
INSERT INTO api_keys (id, hashed_secret, user_id, application, name, last_used, expires_at, created_at, updated_at, login_type, oidc_access_token, oidc_refresh_token, oidc_id_token, oidc_expiry, devurl_token) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15) RETURNING *;
44+
INSERT INTO
45+
api_keys (
46+
id,
47+
hashed_secret,
48+
user_id,
49+
application,
50+
name,
51+
last_used,
52+
expires_at,
53+
created_at,
54+
updated_at,
55+
login_type,
56+
oidc_access_token,
57+
oidc_refresh_token,
58+
oidc_id_token,
59+
oidc_expiry,
60+
devurl_token
61+
)
62+
VALUES
63+
(
64+
$1,
65+
$2,
66+
$3,
67+
$4,
68+
$5,
69+
$6,
70+
$7,
71+
$8,
72+
$9,
73+
$10,
74+
$11,
75+
$12,
76+
$13,
77+
$14,
78+
$15
79+
) RETURNING *;
2180

2281
-- name: InsertUser :one
23-
INSERT INTO users (id, email, name, login_type, hashed_password, created_at, updated_at, username) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING *;
82+
INSERT INTO
83+
users (
84+
id,
85+
email,
86+
name,
87+
login_type,
88+
hashed_password,
89+
created_at,
90+
updated_at,
91+
username
92+
)
93+
VALUES
94+
($1, $2, $3, $4, $5, $6, $7, $8) RETURNING *;
2495

2596
-- name: UpdateAPIKeyByID :exec
26-
UPDATE api_keys SET last_used = $2, expires_at = $3, oidc_access_token = $4, oidc_refresh_token = $5, oidc_expiry = $6 WHERE id = $1;
97+
UPDATE
98+
api_keys
99+
SET
100+
last_used = $2,
101+
expires_at = $3,
102+
oidc_access_token = $4,
103+
oidc_refresh_token = $5,
104+
oidc_expiry = $6
105+
WHERE
106+
id = $1;

0 commit comments

Comments
 (0)