mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
chore: Add watch workspace endpoint (#1493)
This commit is contained in:
+14
-8
@@ -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
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
})
|
||||
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
|
||||
|
||||
@@ -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),
|
||||
})
|
||||
|
||||
|
||||
@@ -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),
|
||||
})
|
||||
|
||||
|
||||
@@ -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),
|
||||
})
|
||||
|
||||
|
||||
@@ -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),
|
||||
})
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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),
|
||||
})
|
||||
|
||||
|
||||
@@ -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),
|
||||
})
|
||||
|
||||
|
||||
@@ -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),
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user