Skip to content

Commit e3051df

Browse files
authored
chore: add workspace id filter on api (#12483)
* chore: add workspace id filter on api
1 parent 8f40ee3 commit e3051df

File tree

7 files changed

+84
-17
lines changed

7 files changed

+84
-17
lines changed

coderd/database/dbmem/dbmem.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8266,6 +8266,19 @@ func (q *FakeQuerier) GetAuthorizedWorkspaces(ctx context.Context, arg database.
82668266
}
82678267
}
82688268

8269+
if len(arg.WorkspaceIds) > 0 {
8270+
match := false
8271+
for _, id := range arg.WorkspaceIds {
8272+
if workspace.ID == id {
8273+
match = true
8274+
break
8275+
}
8276+
}
8277+
if !match {
8278+
continue
8279+
}
8280+
}
8281+
82698282
// If the filter exists, ensure the object is authorized.
82708283
if prepared != nil && prepared.Authorize(ctx, workspace.RBACObject()) != nil {
82718284
continue

coderd/database/modelqueries.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ func (q *sqlQuerier) GetAuthorizedWorkspaces(ctx context.Context, arg GetWorkspa
221221
arg.OwnerUsername,
222222
arg.TemplateName,
223223
pq.Array(arg.TemplateIDs),
224+
pq.Array(arg.WorkspaceIds),
224225
arg.Name,
225226
arg.HasAgent,
226227
arg.AgentInactiveDisconnectTimeoutSeconds,

coderd/database/queries.sql.go

Lines changed: 25 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/queries/workspaces.sql

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,12 @@ WHERE
204204
workspaces.template_id = ANY(@template_ids)
205205
ELSE true
206206
END
207+
-- Filter by workspace_ids
208+
AND CASE
209+
WHEN array_length(@workspace_ids :: uuid[], 1) > 0 THEN
210+
workspaces.id = ANY(@workspace_ids)
211+
ELSE true
212+
END
207213
-- Filter by name, matching on substring
208214
AND CASE
209215
WHEN @name :: text != '' THEN

coderd/searchquery/search.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ func Workspaces(query string, page codersdk.Pagination, agentInactiveDisconnectT
103103
}
104104

105105
parser := httpapi.NewQueryParamParser()
106+
filter.WorkspaceIds = parser.UUIDs(values, []uuid.UUID{}, "id")
106107
filter.OwnerUsername = parser.String(values, "", "owner")
107108
filter.TemplateName = parser.String(values, "", "template")
108109
filter.Name = parser.String(values, "", "name")

coderd/searchquery/search_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,10 @@ func TestSearchWorkspace(t *testing.T) {
178178
}
179179
assert.Contains(t, s.String(), c.ExpectedErrorContains)
180180
} else {
181+
if len(c.Expected.WorkspaceIds) == len(values.WorkspaceIds) {
182+
// nil slice vs 0 len slice is equivalent for our purposes.
183+
c.Expected.WorkspaceIds = values.WorkspaceIds
184+
}
181185
assert.Len(t, errs, 0, "expected no error")
182186
assert.Equal(t, c.Expected, values, "expected values")
183187
}

coderd/workspaces_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"math"
1010
"net/http"
1111
"os"
12+
"slices"
1213
"strings"
1314
"testing"
1415
"time"
@@ -1356,6 +1357,39 @@ func TestWorkspaceFilterManual(t *testing.T) {
13561357
require.NoError(t, err)
13571358
require.Len(t, res.Workspaces, 0)
13581359
})
1360+
t.Run("IDs", func(t *testing.T) {
1361+
t.Parallel()
1362+
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
1363+
user := coderdtest.CreateFirstUser(t, client)
1364+
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
1365+
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
1366+
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
1367+
alpha := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
1368+
bravo := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
1369+
1370+
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
1371+
defer cancel()
1372+
1373+
// full match
1374+
res, err := client.Workspaces(ctx, codersdk.WorkspaceFilter{
1375+
FilterQuery: fmt.Sprintf("id:%s,%s", alpha.ID, bravo.ID),
1376+
})
1377+
require.NoError(t, err)
1378+
require.Len(t, res.Workspaces, 2)
1379+
require.True(t, slices.ContainsFunc(res.Workspaces, func(workspace codersdk.Workspace) bool {
1380+
return workspace.ID == alpha.ID
1381+
}), "alpha workspace")
1382+
require.True(t, slices.ContainsFunc(res.Workspaces, func(workspace codersdk.Workspace) bool {
1383+
return workspace.ID == alpha.ID
1384+
}), "bravo workspace")
1385+
1386+
// no match
1387+
res, err = client.Workspaces(ctx, codersdk.WorkspaceFilter{
1388+
FilterQuery: fmt.Sprintf("id:%s", uuid.NewString()),
1389+
})
1390+
require.NoError(t, err)
1391+
require.Len(t, res.Workspaces, 0)
1392+
})
13591393
t.Run("Template", func(t *testing.T) {
13601394
t.Parallel()
13611395
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})

0 commit comments

Comments
 (0)