Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0706c60

Browse files
authored
chore: Add watch workspace endpoint (#1493)
1 parent b8ee939 commit 0706c60

21 files changed

+259
-37
lines changed

coderd/coderd.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,7 @@ func New(options *Options) (http.Handler, func()) {
310310
r.Route("/autostop", func(r chi.Router) {
311311
r.Put("/", api.putWorkspaceAutostop)
312312
})
313+
r.Get("/watch", api.watchWorkspace)
313314
})
314315
})
315316
r.Route("/workspacebuilds/{workspacebuild}", func(r chi.Router) {

coderd/coderd_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ func TestAuthorizeAllEndpoints(t *testing.T) {
128128
"PUT:/api/v2/workspaces/{workspace}/autostop": {NoAuthorize: true},
129129
"GET:/api/v2/workspaces/{workspace}/builds": {NoAuthorize: true},
130130
"POST:/api/v2/workspaces/{workspace}/builds": {NoAuthorize: true},
131+
"GET:/api/v2/workspaces/{workspace}/watch": {NoAuthorize: true},
131132

132133
"POST:/api/v2/files": {NoAuthorize: true},
133134
"GET:/api/v2/files/{hash}": {NoAuthorize: true},

coderd/httpmw/apikey.go

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

20-
// AuthCookie represents the name of the cookie the API key is stored in.
21-
const AuthCookie = "session_token"
20+
// SessionTokenKey represents the name of the cookie or query paramater the API key is stored in.
21+
const SessionTokenKey = "session_token"
2222

2323
type apiKeyContextKey struct{}
2424

@@ -43,18 +43,24 @@ type OAuth2Configs struct {
4343
func ExtractAPIKey(db database.Store, oauth *OAuth2Configs) func(http.Handler) http.Handler {
4444
return func(next http.Handler) http.Handler {
4545
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
46-
cookie, err := r.Cookie(AuthCookie)
46+
var cookieValue string
47+
cookie, err := r.Cookie(SessionTokenKey)
4748
if err != nil {
49+
cookieValue = r.URL.Query().Get(SessionTokenKey)
50+
} else {
51+
cookieValue = cookie.Value
52+
}
53+
if cookieValue == "" {
4854
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{
49-
Message: fmt.Sprintf("%q cookie must be provided", AuthCookie),
55+
Message: fmt.Sprintf("%q cookie or query parameter must be provided", SessionTokenKey),
5056
})
5157
return
5258
}
53-
parts := strings.Split(cookie.Value, "-")
59+
parts := strings.Split(cookieValue, "-")
5460
// APIKeys are formatted: ID-SECRET
5561
if len(parts) != 2 {
5662
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{
57-
Message: fmt.Sprintf("invalid %q cookie api key format", AuthCookie),
63+
Message: fmt.Sprintf("invalid %q cookie api key format", SessionTokenKey),
5864
})
5965
return
6066
}
@@ -63,13 +69,13 @@ func ExtractAPIKey(db database.Store, oauth *OAuth2Configs) func(http.Handler) h
6369
// Ensuring key lengths are valid.
6470
if len(keyID) != 10 {
6571
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{
66-
Message: fmt.Sprintf("invalid %q cookie api key id", AuthCookie),
72+
Message: fmt.Sprintf("invalid %q cookie api key id", SessionTokenKey),
6773
})
6874
return
6975
}
7076
if len(keySecret) != 22 {
7177
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{
72-
Message: fmt.Sprintf("invalid %q cookie api key secret", AuthCookie),
78+
Message: fmt.Sprintf("invalid %q cookie api key secret", SessionTokenKey),
7379
})
7480
return
7581
}

coderd/httpmw/apikey_test.go

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ func TestAPIKey(t *testing.T) {
5656
rw = httptest.NewRecorder()
5757
)
5858
r.AddCookie(&http.Cookie{
59-
Name: httpmw.AuthCookie,
59+
Name: httpmw.SessionTokenKey,
6060
Value: "test-wow-hello",
6161
})
6262

@@ -74,7 +74,7 @@ func TestAPIKey(t *testing.T) {
7474
rw = httptest.NewRecorder()
7575
)
7676
r.AddCookie(&http.Cookie{
77-
Name: httpmw.AuthCookie,
77+
Name: httpmw.SessionTokenKey,
7878
Value: "test-wow",
7979
})
8080

@@ -92,7 +92,7 @@ func TestAPIKey(t *testing.T) {
9292
rw = httptest.NewRecorder()
9393
)
9494
r.AddCookie(&http.Cookie{
95-
Name: httpmw.AuthCookie,
95+
Name: httpmw.SessionTokenKey,
9696
Value: "testtestid-wow",
9797
})
9898

@@ -111,7 +111,7 @@ func TestAPIKey(t *testing.T) {
111111
rw = httptest.NewRecorder()
112112
)
113113
r.AddCookie(&http.Cookie{
114-
Name: httpmw.AuthCookie,
114+
Name: httpmw.SessionTokenKey,
115115
Value: fmt.Sprintf("%s-%s", id, secret),
116116
})
117117

@@ -130,7 +130,7 @@ func TestAPIKey(t *testing.T) {
130130
rw = httptest.NewRecorder()
131131
)
132132
r.AddCookie(&http.Cookie{
133-
Name: httpmw.AuthCookie,
133+
Name: httpmw.SessionTokenKey,
134134
Value: fmt.Sprintf("%s-%s", id, secret),
135135
})
136136

@@ -157,7 +157,7 @@ func TestAPIKey(t *testing.T) {
157157
rw = httptest.NewRecorder()
158158
)
159159
r.AddCookie(&http.Cookie{
160-
Name: httpmw.AuthCookie,
160+
Name: httpmw.SessionTokenKey,
161161
Value: fmt.Sprintf("%s-%s", id, secret),
162162
})
163163

@@ -182,7 +182,7 @@ func TestAPIKey(t *testing.T) {
182182
rw = httptest.NewRecorder()
183183
)
184184
r.AddCookie(&http.Cookie{
185-
Name: httpmw.AuthCookie,
185+
Name: httpmw.SessionTokenKey,
186186
Value: fmt.Sprintf("%s-%s", id, secret),
187187
})
188188

@@ -209,6 +209,37 @@ func TestAPIKey(t *testing.T) {
209209
require.Equal(t, sentAPIKey.ExpiresAt, gotAPIKey.ExpiresAt)
210210
})
211211

212+
t.Run("QueryParameter", func(t *testing.T) {
213+
t.Parallel()
214+
var (
215+
db = databasefake.New()
216+
id, secret = randomAPIKeyParts()
217+
hashed = sha256.Sum256([]byte(secret))
218+
r = httptest.NewRequest("GET", "/", nil)
219+
rw = httptest.NewRecorder()
220+
)
221+
q := r.URL.Query()
222+
q.Add(httpmw.SessionTokenKey, fmt.Sprintf("%s-%s", id, secret))
223+
r.URL.RawQuery = q.Encode()
224+
225+
_, err := db.InsertAPIKey(r.Context(), database.InsertAPIKeyParams{
226+
ID: id,
227+
HashedSecret: hashed[:],
228+
ExpiresAt: database.Now().AddDate(0, 0, 1),
229+
})
230+
require.NoError(t, err)
231+
httpmw.ExtractAPIKey(db, nil)(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
232+
// Checks that it exists on the context!
233+
_ = httpmw.APIKey(r)
234+
httpapi.Write(rw, http.StatusOK, httpapi.Response{
235+
Message: "it worked!",
236+
})
237+
})).ServeHTTP(rw, r)
238+
res := rw.Result()
239+
defer res.Body.Close()
240+
require.Equal(t, http.StatusOK, res.StatusCode)
241+
})
242+
212243
t.Run("ValidUpdateLastUsed", func(t *testing.T) {
213244
t.Parallel()
214245
var (
@@ -219,7 +250,7 @@ func TestAPIKey(t *testing.T) {
219250
rw = httptest.NewRecorder()
220251
)
221252
r.AddCookie(&http.Cookie{
222-
Name: httpmw.AuthCookie,
253+
Name: httpmw.SessionTokenKey,
223254
Value: fmt.Sprintf("%s-%s", id, secret),
224255
})
225256

@@ -252,7 +283,7 @@ func TestAPIKey(t *testing.T) {
252283
rw = httptest.NewRecorder()
253284
)
254285
r.AddCookie(&http.Cookie{
255-
Name: httpmw.AuthCookie,
286+
Name: httpmw.SessionTokenKey,
256287
Value: fmt.Sprintf("%s-%s", id, secret),
257288
})
258289

@@ -285,7 +316,7 @@ func TestAPIKey(t *testing.T) {
285316
rw = httptest.NewRecorder()
286317
)
287318
r.AddCookie(&http.Cookie{
288-
Name: httpmw.AuthCookie,
319+
Name: httpmw.SessionTokenKey,
289320
Value: fmt.Sprintf("%s-%s", id, secret),
290321
})
291322

@@ -319,7 +350,7 @@ func TestAPIKey(t *testing.T) {
319350
rw = httptest.NewRecorder()
320351
)
321352
r.AddCookie(&http.Cookie{
322-
Name: httpmw.AuthCookie,
353+
Name: httpmw.SessionTokenKey,
323354
Value: fmt.Sprintf("%s-%s", id, secret),
324355
})
325356

coderd/httpmw/authorize_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ func TestExtractUserRoles(t *testing.T) {
9494

9595
req := httptest.NewRequest("GET", "/", nil)
9696
req.AddCookie(&http.Cookie{
97-
Name: httpmw.AuthCookie,
97+
Name: httpmw.SessionTokenKey,
9898
Value: token,
9999
})
100100

coderd/httpmw/organizationparam_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func TestOrganizationParam(t *testing.T) {
2929
hashed = sha256.Sum256([]byte(secret))
3030
)
3131
r.AddCookie(&http.Cookie{
32-
Name: httpmw.AuthCookie,
32+
Name: httpmw.SessionTokenKey,
3333
Value: fmt.Sprintf("%s-%s", id, secret),
3434
})
3535

coderd/httpmw/templateparam_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func TestTemplateParam(t *testing.T) {
2929
)
3030
r := httptest.NewRequest("GET", "/", nil)
3131
r.AddCookie(&http.Cookie{
32-
Name: httpmw.AuthCookie,
32+
Name: httpmw.SessionTokenKey,
3333
Value: fmt.Sprintf("%s-%s", id, secret),
3434
})
3535

coderd/httpmw/templateversionparam_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func TestTemplateVersionParam(t *testing.T) {
2929
)
3030
r := httptest.NewRequest("GET", "/", nil)
3131
r.AddCookie(&http.Cookie{
32-
Name: httpmw.AuthCookie,
32+
Name: httpmw.SessionTokenKey,
3333
Value: fmt.Sprintf("%s-%s", id, secret),
3434
})
3535

coderd/httpmw/userparam_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func TestUserParam(t *testing.T) {
2929
rw = httptest.NewRecorder()
3030
)
3131
r.AddCookie(&http.Cookie{
32-
Name: httpmw.AuthCookie,
32+
Name: httpmw.SessionTokenKey,
3333
Value: fmt.Sprintf("%s-%s", id, secret),
3434
})
3535

coderd/httpmw/workspaceagent.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ func WorkspaceAgent(r *http.Request) database.WorkspaceAgent {
2828
func ExtractWorkspaceAgent(db database.Store) func(http.Handler) http.Handler {
2929
return func(next http.Handler) http.Handler {
3030
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
31-
cookie, err := r.Cookie(AuthCookie)
31+
cookie, err := r.Cookie(SessionTokenKey)
3232
if err != nil {
3333
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{
34-
Message: fmt.Sprintf("%q cookie must be provided", AuthCookie),
34+
Message: fmt.Sprintf("%q cookie must be provided", SessionTokenKey),
3535
})
3636
return
3737
}

coderd/httpmw/workspaceagent_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ func TestWorkspaceAgent(t *testing.T) {
2222
token := uuid.New()
2323
r := httptest.NewRequest("GET", "/", nil)
2424
r.AddCookie(&http.Cookie{
25-
Name: httpmw.AuthCookie,
25+
Name: httpmw.SessionTokenKey,
2626
Value: token.String(),
2727
})
2828
return r, token

coderd/httpmw/workspaceagentparam_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func TestWorkspaceAgentParam(t *testing.T) {
2929
)
3030
r := httptest.NewRequest("GET", "/", nil)
3131
r.AddCookie(&http.Cookie{
32-
Name: httpmw.AuthCookie,
32+
Name: httpmw.SessionTokenKey,
3333
Value: fmt.Sprintf("%s-%s", id, secret),
3434
})
3535

coderd/httpmw/workspacebuildparam_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func TestWorkspaceBuildParam(t *testing.T) {
2929
)
3030
r := httptest.NewRequest("GET", "/", nil)
3131
r.AddCookie(&http.Cookie{
32-
Name: httpmw.AuthCookie,
32+
Name: httpmw.SessionTokenKey,
3333
Value: fmt.Sprintf("%s-%s", id, secret),
3434
})
3535

coderd/httpmw/workspaceparam_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func TestWorkspaceParam(t *testing.T) {
2929
)
3030
r := httptest.NewRequest("GET", "/", nil)
3131
r.AddCookie(&http.Cookie{
32-
Name: httpmw.AuthCookie,
32+
Name: httpmw.SessionTokenKey,
3333
Value: fmt.Sprintf("%s-%s", id, secret),
3434
})
3535

coderd/users.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -690,7 +690,7 @@ func (*api) postLogout(rw http.ResponseWriter, _ *http.Request) {
690690
cookie := &http.Cookie{
691691
// MaxAge < 0 means to delete the cookie now
692692
MaxAge: -1,
693-
Name: httpmw.AuthCookie,
693+
Name: httpmw.SessionTokenKey,
694694
Path: "/",
695695
}
696696

@@ -748,7 +748,7 @@ func (api *api) createAPIKey(rw http.ResponseWriter, r *http.Request, params dat
748748
// This format is consumed by the APIKey middleware.
749749
sessionToken := fmt.Sprintf("%s-%s", keyID, keySecret)
750750
http.SetCookie(rw, &http.Cookie{
751-
Name: httpmw.AuthCookie,
751+
Name: httpmw.SessionTokenKey,
752752
Value: sessionToken,
753753
Path: "/",
754754
HttpOnly: true,

coderd/users_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ func TestPostLogout(t *testing.T) {
122122
cookies := response.Cookies()
123123
require.Len(t, cookies, 1, "Exactly one cookie should be returned")
124124

125-
require.Equal(t, cookies[0].Name, httpmw.AuthCookie, "Cookie should be the auth cookie")
125+
require.Equal(t, cookies[0].Name, httpmw.SessionTokenKey, "Cookie should be the auth cookie")
126126
require.Equal(t, cookies[0].MaxAge, -1, "Cookie should be set to delete")
127127
})
128128
}

0 commit comments

Comments
 (0)