chore: Add watch workspace endpoint (#1493)

This commit is contained in:
Garrett Delfosse
2022-05-18 16:16:26 -05:00
committed by GitHub
parent b8ee939e52
commit 0706c60445
21 changed files with 259 additions and 37 deletions
+14 -8
View File
@@ -17,8 +17,8 @@ import (
"github.com/coder/coder/coderd/httpapi"
)
// AuthCookie represents the name of the cookie the API key is stored in.
const AuthCookie = "session_token"
// SessionTokenKey represents the name of the cookie or query paramater the API key is stored in.
const SessionTokenKey = "session_token"
type apiKeyContextKey struct{}
@@ -43,18 +43,24 @@ type OAuth2Configs struct {
func ExtractAPIKey(db database.Store, oauth *OAuth2Configs) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
cookie, err := r.Cookie(AuthCookie)
var cookieValue string
cookie, err := r.Cookie(SessionTokenKey)
if err != nil {
cookieValue = r.URL.Query().Get(SessionTokenKey)
} else {
cookieValue = cookie.Value
}
if cookieValue == "" {
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{
Message: fmt.Sprintf("%q cookie must be provided", AuthCookie),
Message: fmt.Sprintf("%q cookie or query parameter must be provided", SessionTokenKey),
})
return
}
parts := strings.Split(cookie.Value, "-")
parts := strings.Split(cookieValue, "-")
// APIKeys are formatted: ID-SECRET
if len(parts) != 2 {
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{
Message: fmt.Sprintf("invalid %q cookie api key format", AuthCookie),
Message: fmt.Sprintf("invalid %q cookie api key format", SessionTokenKey),
})
return
}
@@ -63,13 +69,13 @@ func ExtractAPIKey(db database.Store, oauth *OAuth2Configs) func(http.Handler) h
// Ensuring key lengths are valid.
if len(keyID) != 10 {
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{
Message: fmt.Sprintf("invalid %q cookie api key id", AuthCookie),
Message: fmt.Sprintf("invalid %q cookie api key id", SessionTokenKey),
})
return
}
if len(keySecret) != 22 {
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{
Message: fmt.Sprintf("invalid %q cookie api key secret", AuthCookie),
Message: fmt.Sprintf("invalid %q cookie api key secret", SessionTokenKey),
})
return
}
+42 -11
View File
@@ -56,7 +56,7 @@ func TestAPIKey(t *testing.T) {
rw = httptest.NewRecorder()
)
r.AddCookie(&http.Cookie{
Name: httpmw.AuthCookie,
Name: httpmw.SessionTokenKey,
Value: "test-wow-hello",
})
@@ -74,7 +74,7 @@ func TestAPIKey(t *testing.T) {
rw = httptest.NewRecorder()
)
r.AddCookie(&http.Cookie{
Name: httpmw.AuthCookie,
Name: httpmw.SessionTokenKey,
Value: "test-wow",
})
@@ -92,7 +92,7 @@ func TestAPIKey(t *testing.T) {
rw = httptest.NewRecorder()
)
r.AddCookie(&http.Cookie{
Name: httpmw.AuthCookie,
Name: httpmw.SessionTokenKey,
Value: "testtestid-wow",
})
@@ -111,7 +111,7 @@ func TestAPIKey(t *testing.T) {
rw = httptest.NewRecorder()
)
r.AddCookie(&http.Cookie{
Name: httpmw.AuthCookie,
Name: httpmw.SessionTokenKey,
Value: fmt.Sprintf("%s-%s", id, secret),
})
@@ -130,7 +130,7 @@ func TestAPIKey(t *testing.T) {
rw = httptest.NewRecorder()
)
r.AddCookie(&http.Cookie{
Name: httpmw.AuthCookie,
Name: httpmw.SessionTokenKey,
Value: fmt.Sprintf("%s-%s", id, secret),
})
@@ -157,7 +157,7 @@ func TestAPIKey(t *testing.T) {
rw = httptest.NewRecorder()
)
r.AddCookie(&http.Cookie{
Name: httpmw.AuthCookie,
Name: httpmw.SessionTokenKey,
Value: fmt.Sprintf("%s-%s", id, secret),
})
@@ -182,7 +182,7 @@ func TestAPIKey(t *testing.T) {
rw = httptest.NewRecorder()
)
r.AddCookie(&http.Cookie{
Name: httpmw.AuthCookie,
Name: httpmw.SessionTokenKey,
Value: fmt.Sprintf("%s-%s", id, secret),
})
@@ -209,6 +209,37 @@ func TestAPIKey(t *testing.T) {
require.Equal(t, sentAPIKey.ExpiresAt, gotAPIKey.ExpiresAt)
})
t.Run("QueryParameter", func(t *testing.T) {
t.Parallel()
var (
db = databasefake.New()
id, secret = randomAPIKeyParts()
hashed = sha256.Sum256([]byte(secret))
r = httptest.NewRequest("GET", "/", nil)
rw = httptest.NewRecorder()
)
q := r.URL.Query()
q.Add(httpmw.SessionTokenKey, fmt.Sprintf("%s-%s", id, secret))
r.URL.RawQuery = q.Encode()
_, err := db.InsertAPIKey(r.Context(), database.InsertAPIKeyParams{
ID: id,
HashedSecret: hashed[:],
ExpiresAt: database.Now().AddDate(0, 0, 1),
})
require.NoError(t, err)
httpmw.ExtractAPIKey(db, nil)(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
// Checks that it exists on the context!
_ = httpmw.APIKey(r)
httpapi.Write(rw, http.StatusOK, httpapi.Response{
Message: "it worked!",
})
})).ServeHTTP(rw, r)
res := rw.Result()
defer res.Body.Close()
require.Equal(t, http.StatusOK, res.StatusCode)
})
t.Run("ValidUpdateLastUsed", func(t *testing.T) {
t.Parallel()
var (
@@ -219,7 +250,7 @@ func TestAPIKey(t *testing.T) {
rw = httptest.NewRecorder()
)
r.AddCookie(&http.Cookie{
Name: httpmw.AuthCookie,
Name: httpmw.SessionTokenKey,
Value: fmt.Sprintf("%s-%s", id, secret),
})
@@ -252,7 +283,7 @@ func TestAPIKey(t *testing.T) {
rw = httptest.NewRecorder()
)
r.AddCookie(&http.Cookie{
Name: httpmw.AuthCookie,
Name: httpmw.SessionTokenKey,
Value: fmt.Sprintf("%s-%s", id, secret),
})
@@ -285,7 +316,7 @@ func TestAPIKey(t *testing.T) {
rw = httptest.NewRecorder()
)
r.AddCookie(&http.Cookie{
Name: httpmw.AuthCookie,
Name: httpmw.SessionTokenKey,
Value: fmt.Sprintf("%s-%s", id, secret),
})
@@ -319,7 +350,7 @@ func TestAPIKey(t *testing.T) {
rw = httptest.NewRecorder()
)
r.AddCookie(&http.Cookie{
Name: httpmw.AuthCookie,
Name: httpmw.SessionTokenKey,
Value: fmt.Sprintf("%s-%s", id, secret),
})
+1 -1
View File
@@ -94,7 +94,7 @@ func TestExtractUserRoles(t *testing.T) {
req := httptest.NewRequest("GET", "/", nil)
req.AddCookie(&http.Cookie{
Name: httpmw.AuthCookie,
Name: httpmw.SessionTokenKey,
Value: token,
})
+1 -1
View File
@@ -29,7 +29,7 @@ func TestOrganizationParam(t *testing.T) {
hashed = sha256.Sum256([]byte(secret))
)
r.AddCookie(&http.Cookie{
Name: httpmw.AuthCookie,
Name: httpmw.SessionTokenKey,
Value: fmt.Sprintf("%s-%s", id, secret),
})
+1 -1
View File
@@ -29,7 +29,7 @@ func TestTemplateParam(t *testing.T) {
)
r := httptest.NewRequest("GET", "/", nil)
r.AddCookie(&http.Cookie{
Name: httpmw.AuthCookie,
Name: httpmw.SessionTokenKey,
Value: fmt.Sprintf("%s-%s", id, secret),
})
+1 -1
View File
@@ -29,7 +29,7 @@ func TestTemplateVersionParam(t *testing.T) {
)
r := httptest.NewRequest("GET", "/", nil)
r.AddCookie(&http.Cookie{
Name: httpmw.AuthCookie,
Name: httpmw.SessionTokenKey,
Value: fmt.Sprintf("%s-%s", id, secret),
})
+1 -1
View File
@@ -29,7 +29,7 @@ func TestUserParam(t *testing.T) {
rw = httptest.NewRecorder()
)
r.AddCookie(&http.Cookie{
Name: httpmw.AuthCookie,
Name: httpmw.SessionTokenKey,
Value: fmt.Sprintf("%s-%s", id, secret),
})
+2 -2
View File
@@ -28,10 +28,10 @@ func WorkspaceAgent(r *http.Request) database.WorkspaceAgent {
func ExtractWorkspaceAgent(db database.Store) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
cookie, err := r.Cookie(AuthCookie)
cookie, err := r.Cookie(SessionTokenKey)
if err != nil {
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{
Message: fmt.Sprintf("%q cookie must be provided", AuthCookie),
Message: fmt.Sprintf("%q cookie must be provided", SessionTokenKey),
})
return
}
+1 -1
View File
@@ -22,7 +22,7 @@ func TestWorkspaceAgent(t *testing.T) {
token := uuid.New()
r := httptest.NewRequest("GET", "/", nil)
r.AddCookie(&http.Cookie{
Name: httpmw.AuthCookie,
Name: httpmw.SessionTokenKey,
Value: token.String(),
})
return r, token
+1 -1
View File
@@ -29,7 +29,7 @@ func TestWorkspaceAgentParam(t *testing.T) {
)
r := httptest.NewRequest("GET", "/", nil)
r.AddCookie(&http.Cookie{
Name: httpmw.AuthCookie,
Name: httpmw.SessionTokenKey,
Value: fmt.Sprintf("%s-%s", id, secret),
})
+1 -1
View File
@@ -29,7 +29,7 @@ func TestWorkspaceBuildParam(t *testing.T) {
)
r := httptest.NewRequest("GET", "/", nil)
r.AddCookie(&http.Cookie{
Name: httpmw.AuthCookie,
Name: httpmw.SessionTokenKey,
Value: fmt.Sprintf("%s-%s", id, secret),
})
+1 -1
View File
@@ -29,7 +29,7 @@ func TestWorkspaceParam(t *testing.T) {
)
r := httptest.NewRequest("GET", "/", nil)
r.AddCookie(&http.Cookie{
Name: httpmw.AuthCookie,
Name: httpmw.SessionTokenKey,
Value: fmt.Sprintf("%s-%s", id, secret),
})