mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
chore: update v1 schema (#643)
This commit is contained in:
@@ -19,6 +19,13 @@ func parseUUID(rw http.ResponseWriter, r *http.Request, param string) (uuid.UUID
|
||||
})
|
||||
return uuid.UUID{}, false
|
||||
}
|
||||
|
||||
// Automatically set uuid.Nil to the acting users id.
|
||||
if param == UserKey && rawID == "me" {
|
||||
key := APIKey(r)
|
||||
return key.UserID, true
|
||||
}
|
||||
|
||||
parsed, err := uuid.Parse(rawID)
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{
|
||||
@@ -26,5 +33,6 @@ func parseUUID(rw http.ResponseWriter, r *http.Request, param string) (uuid.UUID
|
||||
})
|
||||
return uuid.UUID{}, false
|
||||
}
|
||||
|
||||
return parsed, true
|
||||
}
|
||||
|
||||
@@ -7,8 +7,6 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"github.com/coder/coder/coderd/database"
|
||||
"github.com/coder/coder/coderd/httpapi"
|
||||
)
|
||||
@@ -40,17 +38,15 @@ func OrganizationMemberParam(r *http.Request) database.OrganizationMember {
|
||||
func ExtractOrganizationParam(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) {
|
||||
organizationID := chi.URLParam(r, "organization")
|
||||
if organizationID == "" {
|
||||
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{
|
||||
Message: "organization must be provided",
|
||||
})
|
||||
orgID, ok := parseUUID(rw, r, "organization")
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
organization, err := db.GetOrganizationByID(r.Context(), organizationID)
|
||||
|
||||
organization, err := db.GetOrganizationByID(r.Context(), orgID)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
httpapi.Write(rw, http.StatusNotFound, httpapi.Response{
|
||||
Message: fmt.Sprintf("organization %q does not exist", organizationID),
|
||||
Message: fmt.Sprintf("organization %q does not exist", orgID),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -60,6 +56,7 @@ func ExtractOrganizationParam(db database.Store) func(http.Handler) http.Handler
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
apiKey := APIKey(r)
|
||||
organizationMember, err := db.GetOrganizationMemberByUserID(r.Context(), database.GetOrganizationMemberByUserIDParams{
|
||||
OrganizationID: organization.ID,
|
||||
|
||||
@@ -32,10 +32,11 @@ func TestOrganizationParam(t *testing.T) {
|
||||
Name: httpmw.AuthCookie,
|
||||
Value: fmt.Sprintf("%s-%s", id, secret),
|
||||
})
|
||||
userID, err := cryptorand.String(16)
|
||||
require.NoError(t, err)
|
||||
|
||||
userID := uuid.New()
|
||||
username, err := cryptorand.String(8)
|
||||
require.NoError(t, err)
|
||||
|
||||
user, err := db.InsertUser(r.Context(), database.InsertUserParams{
|
||||
ID: userID,
|
||||
Email: "testaccount@coder.com",
|
||||
@@ -86,7 +87,7 @@ func TestOrganizationParam(t *testing.T) {
|
||||
r, _ = setupAuthentication(db)
|
||||
rtr = chi.NewRouter()
|
||||
)
|
||||
chi.RouteContext(r.Context()).URLParams.Add("organization", "nothin")
|
||||
chi.RouteContext(r.Context()).URLParams.Add("organization", uuid.NewString())
|
||||
rtr.Use(
|
||||
httpmw.ExtractAPIKey(db, nil),
|
||||
httpmw.ExtractOrganizationParam(db),
|
||||
@@ -98,6 +99,26 @@ func TestOrganizationParam(t *testing.T) {
|
||||
require.Equal(t, http.StatusNotFound, res.StatusCode)
|
||||
})
|
||||
|
||||
t.Run("InvalidUUID", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
var (
|
||||
db = databasefake.New()
|
||||
rw = httptest.NewRecorder()
|
||||
r, _ = setupAuthentication(db)
|
||||
rtr = chi.NewRouter()
|
||||
)
|
||||
chi.RouteContext(r.Context()).URLParams.Add("organization", "not-a-uuid")
|
||||
rtr.Use(
|
||||
httpmw.ExtractAPIKey(db, nil),
|
||||
httpmw.ExtractOrganizationParam(db),
|
||||
)
|
||||
rtr.Get("/", nil)
|
||||
rtr.ServeHTTP(rw, r)
|
||||
res := rw.Result()
|
||||
defer res.Body.Close()
|
||||
require.Equal(t, http.StatusBadRequest, res.StatusCode)
|
||||
})
|
||||
|
||||
t.Run("NotInOrganization", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
var (
|
||||
@@ -107,13 +128,13 @@ func TestOrganizationParam(t *testing.T) {
|
||||
rtr = chi.NewRouter()
|
||||
)
|
||||
organization, err := db.InsertOrganization(r.Context(), database.InsertOrganizationParams{
|
||||
ID: uuid.NewString(),
|
||||
ID: uuid.New(),
|
||||
Name: "test",
|
||||
CreatedAt: database.Now(),
|
||||
UpdatedAt: database.Now(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
chi.RouteContext(r.Context()).URLParams.Add("organization", organization.ID)
|
||||
chi.RouteContext(r.Context()).URLParams.Add("organization", organization.ID.String())
|
||||
rtr.Use(
|
||||
httpmw.ExtractAPIKey(db, nil),
|
||||
httpmw.ExtractOrganizationParam(db),
|
||||
@@ -134,7 +155,7 @@ func TestOrganizationParam(t *testing.T) {
|
||||
rtr = chi.NewRouter()
|
||||
)
|
||||
organization, err := db.InsertOrganization(r.Context(), database.InsertOrganizationParams{
|
||||
ID: uuid.NewString(),
|
||||
ID: uuid.New(),
|
||||
Name: "test",
|
||||
CreatedAt: database.Now(),
|
||||
UpdatedAt: database.Now(),
|
||||
@@ -147,7 +168,7 @@ func TestOrganizationParam(t *testing.T) {
|
||||
UpdatedAt: database.Now(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
chi.RouteContext(r.Context()).URLParams.Add("organization", organization.ID)
|
||||
chi.RouteContext(r.Context()).URLParams.Add("organization", organization.ID.String())
|
||||
rtr.Use(
|
||||
httpmw.ExtractAPIKey(db, nil),
|
||||
httpmw.ExtractOrganizationParam(db),
|
||||
|
||||
@@ -46,7 +46,7 @@ func ExtractProjectParam(db database.Store) func(http.Handler) http.Handler {
|
||||
}
|
||||
|
||||
ctx := context.WithValue(r.Context(), projectParamContextKey{}, project)
|
||||
chi.RouteContext(ctx).URLParams.Add("organization", project.OrganizationID)
|
||||
chi.RouteContext(ctx).URLParams.Add("organization", project.OrganizationID.String())
|
||||
next.ServeHTTP(rw, r.WithContext(ctx))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -32,8 +32,8 @@ func TestProjectParam(t *testing.T) {
|
||||
Name: httpmw.AuthCookie,
|
||||
Value: fmt.Sprintf("%s-%s", id, secret),
|
||||
})
|
||||
userID, err := cryptorand.String(16)
|
||||
require.NoError(t, err)
|
||||
|
||||
userID := uuid.New()
|
||||
username, err := cryptorand.String(8)
|
||||
require.NoError(t, err)
|
||||
user, err := db.InsertUser(r.Context(), database.InsertUserParams{
|
||||
@@ -47,6 +47,7 @@ func TestProjectParam(t *testing.T) {
|
||||
UpdatedAt: database.Now(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = db.InsertAPIKey(r.Context(), database.InsertAPIKeyParams{
|
||||
ID: id,
|
||||
UserID: user.ID,
|
||||
@@ -55,8 +56,8 @@ func TestProjectParam(t *testing.T) {
|
||||
ExpiresAt: database.Now().Add(time.Minute),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
orgID, err := cryptorand.String(16)
|
||||
require.NoError(t, err)
|
||||
|
||||
orgID := uuid.New()
|
||||
organization, err := db.InsertOrganization(r.Context(), database.InsertOrganizationParams{
|
||||
ID: orgID,
|
||||
Name: "banana",
|
||||
@@ -65,6 +66,7 @@ func TestProjectParam(t *testing.T) {
|
||||
UpdatedAt: database.Now(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = db.InsertOrganizationMember(r.Context(), database.InsertOrganizationMemberParams{
|
||||
OrganizationID: orgID,
|
||||
UserID: user.ID,
|
||||
|
||||
@@ -47,7 +47,7 @@ func ExtractProjectVersionParam(db database.Store) func(http.Handler) http.Handl
|
||||
}
|
||||
|
||||
ctx := context.WithValue(r.Context(), projectVersionParamContextKey{}, projectVersion)
|
||||
chi.RouteContext(ctx).URLParams.Add("organization", projectVersion.OrganizationID)
|
||||
chi.RouteContext(ctx).URLParams.Add("organization", projectVersion.OrganizationID.String())
|
||||
next.ServeHTTP(rw, r.WithContext(ctx))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -32,8 +32,8 @@ func TestProjectVersionParam(t *testing.T) {
|
||||
Name: httpmw.AuthCookie,
|
||||
Value: fmt.Sprintf("%s-%s", id, secret),
|
||||
})
|
||||
userID, err := cryptorand.String(16)
|
||||
require.NoError(t, err)
|
||||
|
||||
userID := uuid.New()
|
||||
username, err := cryptorand.String(8)
|
||||
require.NoError(t, err)
|
||||
user, err := db.InsertUser(r.Context(), database.InsertUserParams{
|
||||
@@ -47,6 +47,7 @@ func TestProjectVersionParam(t *testing.T) {
|
||||
UpdatedAt: database.Now(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = db.InsertAPIKey(r.Context(), database.InsertAPIKeyParams{
|
||||
ID: id,
|
||||
UserID: user.ID,
|
||||
@@ -55,8 +56,8 @@ func TestProjectVersionParam(t *testing.T) {
|
||||
ExpiresAt: database.Now().Add(time.Minute),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
orgID, err := cryptorand.String(16)
|
||||
require.NoError(t, err)
|
||||
|
||||
orgID := uuid.New()
|
||||
organization, err := db.InsertOrganization(r.Context(), database.InsertOrganizationParams{
|
||||
ID: orgID,
|
||||
Name: "banana",
|
||||
@@ -65,6 +66,7 @@ func TestProjectVersionParam(t *testing.T) {
|
||||
UpdatedAt: database.Now(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = db.InsertOrganizationMember(r.Context(), database.InsertOrganizationMemberParams{
|
||||
OrganizationID: orgID,
|
||||
UserID: user.ID,
|
||||
@@ -72,6 +74,7 @@ func TestProjectVersionParam(t *testing.T) {
|
||||
UpdatedAt: database.Now(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
project, err := db.InsertProject(context.Background(), database.InsertProjectParams{
|
||||
ID: uuid.New(),
|
||||
OrganizationID: organization.ID,
|
||||
|
||||
@@ -5,12 +5,12 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"github.com/coder/coder/coderd/database"
|
||||
"github.com/coder/coder/coderd/httpapi"
|
||||
)
|
||||
|
||||
const UserKey = "user"
|
||||
|
||||
type userParamContextKey struct{}
|
||||
|
||||
// UserParam returns the user from the ExtractUserParam handler.
|
||||
@@ -26,21 +26,20 @@ func UserParam(r *http.Request) database.User {
|
||||
func ExtractUserParam(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) {
|
||||
userID := chi.URLParam(r, "user")
|
||||
if userID == "" {
|
||||
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{
|
||||
Message: "user id or name must be provided",
|
||||
})
|
||||
userID, ok := parseUUID(rw, r, UserKey)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
apiKey := APIKey(r)
|
||||
if apiKey.UserID != userID && userID != "me" {
|
||||
if apiKey.UserID != userID {
|
||||
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{
|
||||
Message: "getting non-personal users isn't supported yet",
|
||||
})
|
||||
return
|
||||
}
|
||||
user, err := db.GetUserByID(r.Context(), apiKey.UserID)
|
||||
|
||||
user, err := db.GetUserByID(r.Context(), userID)
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
|
||||
Message: fmt.Sprintf("get user: %s", err.Error()),
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/coder/coder/coderd/database"
|
||||
@@ -32,18 +33,20 @@ func TestUserParam(t *testing.T) {
|
||||
Value: fmt.Sprintf("%s-%s", id, secret),
|
||||
})
|
||||
|
||||
_, err := db.InsertUser(r.Context(), database.InsertUserParams{
|
||||
ID: "bananas",
|
||||
user, err := db.InsertUser(r.Context(), database.InsertUserParams{
|
||||
ID: uuid.New(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = db.InsertAPIKey(r.Context(), database.InsertAPIKeyParams{
|
||||
ID: id,
|
||||
UserID: "bananas",
|
||||
UserID: user.ID,
|
||||
HashedSecret: hashed[:],
|
||||
LastUsed: database.Now(),
|
||||
ExpiresAt: database.Now().Add(time.Minute),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
return db, rw, r
|
||||
}
|
||||
|
||||
@@ -82,7 +85,7 @@ func TestUserParam(t *testing.T) {
|
||||
require.Equal(t, http.StatusBadRequest, res.StatusCode)
|
||||
})
|
||||
|
||||
t.Run("Me", func(t *testing.T) {
|
||||
t.Run("me", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
db, rw, r := setup(t)
|
||||
|
||||
|
||||
@@ -32,8 +32,8 @@ func TestWorkspaceBuildParam(t *testing.T) {
|
||||
Name: httpmw.AuthCookie,
|
||||
Value: fmt.Sprintf("%s-%s", id, secret),
|
||||
})
|
||||
userID, err := cryptorand.String(16)
|
||||
require.NoError(t, err)
|
||||
|
||||
userID := uuid.New()
|
||||
username, err := cryptorand.String(8)
|
||||
require.NoError(t, err)
|
||||
user, err := db.InsertUser(r.Context(), database.InsertUserParams{
|
||||
@@ -47,6 +47,7 @@ func TestWorkspaceBuildParam(t *testing.T) {
|
||||
UpdatedAt: database.Now(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = db.InsertAPIKey(r.Context(), database.InsertAPIKeyParams{
|
||||
ID: id,
|
||||
UserID: user.ID,
|
||||
@@ -55,6 +56,7 @@ func TestWorkspaceBuildParam(t *testing.T) {
|
||||
ExpiresAt: database.Now().Add(time.Minute),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
workspace, err := db.InsertWorkspace(context.Background(), database.InsertWorkspaceParams{
|
||||
ID: uuid.New(),
|
||||
ProjectID: uuid.New(),
|
||||
@@ -64,7 +66,7 @@ func TestWorkspaceBuildParam(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := chi.NewRouteContext()
|
||||
ctx.URLParams.Add("user", userID)
|
||||
ctx.URLParams.Add("user", userID.String())
|
||||
ctx.URLParams.Add("workspace", workspace.Name)
|
||||
r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, ctx))
|
||||
return r, workspace
|
||||
|
||||
@@ -32,8 +32,8 @@ func TestWorkspaceParam(t *testing.T) {
|
||||
Name: httpmw.AuthCookie,
|
||||
Value: fmt.Sprintf("%s-%s", id, secret),
|
||||
})
|
||||
userID, err := cryptorand.String(16)
|
||||
require.NoError(t, err)
|
||||
|
||||
userID := uuid.New()
|
||||
username, err := cryptorand.String(8)
|
||||
require.NoError(t, err)
|
||||
user, err := db.InsertUser(r.Context(), database.InsertUserParams{
|
||||
@@ -47,6 +47,7 @@ func TestWorkspaceParam(t *testing.T) {
|
||||
UpdatedAt: database.Now(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = db.InsertAPIKey(r.Context(), database.InsertAPIKeyParams{
|
||||
ID: id,
|
||||
UserID: user.ID,
|
||||
@@ -105,7 +106,7 @@ func TestWorkspaceParam(t *testing.T) {
|
||||
r, _ := setup(db)
|
||||
workspace, err := db.InsertWorkspace(context.Background(), database.InsertWorkspaceParams{
|
||||
ID: uuid.New(),
|
||||
OwnerID: "not-me",
|
||||
OwnerID: uuid.New(),
|
||||
Name: "hello",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
Reference in New Issue
Block a user