mirror of
https://github.com/coder/coder.git
synced 2026-09-22 05:05:20 +08:00
feat: Workspaces filtering (#1972)
Co-authored-by: G r e y <grey@coder.com> Co-authored-by: Kira Pilot <kira@coder.com>
This commit is contained in:
co-authored by
G r e y
Kira Pilot
parent
ac6cb269db
commit
8b03e2b0e1
@@ -328,6 +328,9 @@ func (q *fakeQuerier) GetWorkspacesWithFilter(_ context.Context, arg database.Ge
|
||||
if !arg.Deleted && workspace.Deleted {
|
||||
continue
|
||||
}
|
||||
if arg.Name != "" && workspace.Name != arg.Name {
|
||||
continue
|
||||
}
|
||||
workspaces = append(workspaces, workspace)
|
||||
}
|
||||
|
||||
|
||||
@@ -3509,16 +3509,28 @@ WHERE
|
||||
owner_id = $3
|
||||
ELSE true
|
||||
END
|
||||
-- Filter by name
|
||||
AND CASE
|
||||
WHEN $4 :: text != '' THEN
|
||||
LOWER(name) = LOWER($4)
|
||||
ELSE true
|
||||
END
|
||||
`
|
||||
|
||||
type GetWorkspacesWithFilterParams struct {
|
||||
Deleted bool `db:"deleted" json:"deleted"`
|
||||
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
|
||||
OwnerID uuid.UUID `db:"owner_id" json:"owner_id"`
|
||||
Name string `db:"name" json:"name"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) GetWorkspacesWithFilter(ctx context.Context, arg GetWorkspacesWithFilterParams) ([]Workspace, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getWorkspacesWithFilter, arg.Deleted, arg.OrganizationID, arg.OwnerID)
|
||||
rows, err := q.db.QueryContext(ctx, getWorkspacesWithFilter,
|
||||
arg.Deleted,
|
||||
arg.OrganizationID,
|
||||
arg.OwnerID,
|
||||
arg.Name,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -28,6 +28,12 @@ WHERE
|
||||
owner_id = @owner_id
|
||||
ELSE true
|
||||
END
|
||||
-- Filter by name
|
||||
AND CASE
|
||||
WHEN @name :: text != '' THEN
|
||||
LOWER(name) = LOWER(@name)
|
||||
ELSE true
|
||||
END
|
||||
;
|
||||
|
||||
-- name: GetWorkspacesByOrganizationIDs :many
|
||||
|
||||
+10
-13
@@ -137,17 +137,14 @@ func (api *API) workspaces(rw http.ResponseWriter, r *http.Request) {
|
||||
// Empty strings mean no filter
|
||||
orgFilter := r.URL.Query().Get("organization_id")
|
||||
ownerFilter := r.URL.Query().Get("owner")
|
||||
nameFilter := r.URL.Query().Get("name")
|
||||
|
||||
filter := database.GetWorkspacesWithFilterParams{Deleted: false}
|
||||
if orgFilter != "" {
|
||||
orgID, err := uuid.Parse(orgFilter)
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{
|
||||
Message: fmt.Sprintf("organization_id must be a uuid: %s", err.Error()),
|
||||
})
|
||||
return
|
||||
if err == nil {
|
||||
filter.OrganizationID = orgID
|
||||
}
|
||||
filter.OrganizationID = orgID
|
||||
}
|
||||
if ownerFilter == "me" {
|
||||
filter.OwnerID = apiKey.UserID
|
||||
@@ -160,15 +157,15 @@ func (api *API) workspaces(rw http.ResponseWriter, r *http.Request) {
|
||||
Username: ownerFilter,
|
||||
Email: ownerFilter,
|
||||
})
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{
|
||||
Message: "owner must be a uuid or username",
|
||||
})
|
||||
return
|
||||
if err == nil {
|
||||
filter.OwnerID = user.ID
|
||||
}
|
||||
userID = user.ID
|
||||
} else {
|
||||
filter.OwnerID = userID
|
||||
}
|
||||
filter.OwnerID = userID
|
||||
}
|
||||
if nameFilter != "" {
|
||||
filter.Name = nameFilter
|
||||
}
|
||||
|
||||
workspaces, err := api.Database.GetWorkspacesWithFilter(r.Context(), filter)
|
||||
|
||||
@@ -268,6 +268,37 @@ func TestWorkspacesByOwner(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Len(t, workspaces, 1)
|
||||
})
|
||||
|
||||
t.Run("ListName", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerD: true})
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
w := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
|
||||
|
||||
// Create noise workspace that should be filtered out
|
||||
_ = coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
|
||||
|
||||
// Use name filter
|
||||
workspaces, err := client.Workspaces(context.Background(), codersdk.WorkspaceFilter{
|
||||
Name: w.Name,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Len(t, workspaces, 1)
|
||||
|
||||
// Create same name workspace that should be included
|
||||
other := coderdtest.CreateAnotherUser(t, client, user.OrganizationID)
|
||||
_ = coderdtest.CreateWorkspace(t, other, user.OrganizationID, template.ID, func(cwr *codersdk.CreateWorkspaceRequest) { cwr.Name = w.Name })
|
||||
|
||||
workspaces, err = client.Workspaces(context.Background(), codersdk.WorkspaceFilter{
|
||||
Name: w.Name,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Len(t, workspaces, 2)
|
||||
})
|
||||
}
|
||||
|
||||
func TestWorkspaceByOwnerAndName(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user