diff --git a/coderd/searchquery/search.go b/coderd/searchquery/search.go index f90f76040d..20291c8033 100644 --- a/coderd/searchquery/search.go +++ b/coderd/searchquery/search.go @@ -218,7 +218,7 @@ func Members(query string, organizationID uuid.UUID) (database.OrganizationMembe return params, parser.Errors } -func Workspaces(ctx context.Context, db database.Store, query string, page codersdk.Pagination, agentInactiveDisconnectTimeout time.Duration) (database.GetWorkspacesParams, []codersdk.ValidationError) { +func Workspaces(ctx context.Context, db database.Store, query string, page codersdk.Pagination, agentInactiveDisconnectTimeout time.Duration, actorID uuid.UUID) (database.GetWorkspacesParams, []codersdk.ValidationError) { filter := database.GetWorkspacesParams{ AgentInactiveDisconnectTimeoutSeconds: int64(agentInactiveDisconnectTimeout.Seconds()), @@ -274,8 +274,7 @@ func Workspaces(ctx context.Context, db database.Store, query string, page coder filter.HasExternalAgent = parser.NullableBoolean(values, sql.NullBool{}, "has_external_agent") filter.OrganizationID = parseOrganization(ctx, db, parser, values, "organization") filter.Shared = parser.NullableBoolean(values, sql.NullBool{}, "shared") - // TODO: support "me" by passing in the actorID - filter.SharedWithUserID = parseUser(ctx, db, parser, values, "shared_with_user", uuid.Nil) + filter.SharedWithUserID = parseUser(ctx, db, parser, values, "shared_with_user", actorID) filter.SharedWithGroupID = parseGroup(ctx, db, parser, values, "shared_with_group") // Translate healthy filter to has-agent statuses // healthy:true = connected, healthy:false = disconnected or timeout diff --git a/coderd/searchquery/search_test.go b/coderd/searchquery/search_test.go index dc7ca9a25e..021df7edc3 100644 --- a/coderd/searchquery/search_test.go +++ b/coderd/searchquery/search_test.go @@ -27,6 +27,7 @@ func TestSearchWorkspace(t *testing.T) { Expected database.GetWorkspacesParams ExpectedErrorContains string Setup func(t *testing.T, db database.Store) + ActorID uuid.UUID }{ { Name: "Empty", @@ -340,6 +341,19 @@ func TestSearchWorkspace(t *testing.T) { HasAgentStatuses: []string{"connecting", "connected"}, }, }, + { + Name: "SharedWithMe", + Query: `shared_with_user:me`, + Setup: func(t *testing.T, db database.Store) { + dbgen.User(t, db, database.User{ + ID: uuid.MustParse("3dd8b1b8-dff5-4b22-8ae9-c243ca136ecf"), + }) + }, + Expected: database.GetWorkspacesParams{ + SharedWithUserID: uuid.MustParse("3dd8b1b8-dff5-4b22-8ae9-c243ca136ecf"), + }, + ActorID: uuid.MustParse("3dd8b1b8-dff5-4b22-8ae9-c243ca136ecf"), + }, { Name: "SharedWithUser", Query: `shared_with_user:3dd8b1b8-dff5-4b22-8ae9-c243ca136ecf`, @@ -485,7 +499,7 @@ func TestSearchWorkspace(t *testing.T) { if c.Setup != nil { c.Setup(t, db) } - values, errs := searchquery.Workspaces(context.Background(), db, c.Query, codersdk.Pagination{}, 0) + values, errs := searchquery.Workspaces(context.Background(), db, c.Query, codersdk.Pagination{}, 0, c.ActorID) if c.ExpectedErrorContains != "" { assert.True(t, len(errs) > 0, "expect some errors") var s strings.Builder @@ -517,7 +531,7 @@ func TestSearchWorkspace(t *testing.T) { query := `` timeout := 1337 * time.Second db, _ := dbtestutil.NewDB(t) - values, errs := searchquery.Workspaces(context.Background(), db, query, codersdk.Pagination{}, timeout) + values, errs := searchquery.Workspaces(context.Background(), db, query, codersdk.Pagination{}, timeout, uuid.Nil) require.Empty(t, errs) require.Equal(t, int64(timeout.Seconds()), values.AgentInactiveDisconnectTimeoutSeconds) }) diff --git a/coderd/workspaces.go b/coderd/workspaces.go index 62cc5e6f53..8d2a388730 100644 --- a/coderd/workspaces.go +++ b/coderd/workspaces.go @@ -157,7 +157,7 @@ func (api *API) workspaces(rw http.ResponseWriter, r *http.Request) { } queryStr := r.URL.Query().Get("q") - filter, errs := searchquery.Workspaces(ctx, api.Database, queryStr, page, api.AgentInactiveDisconnectTimeout) + filter, errs := searchquery.Workspaces(ctx, api.Database, queryStr, page, api.AgentInactiveDisconnectTimeout, apiKey.UserID) if len(errs) > 0 { httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ Message: "Invalid workspace search query.", diff --git a/docs/tutorials/persistent-shared-workspaces.md b/docs/tutorials/persistent-shared-workspaces.md index d3f0f1f6c0..39d0f40db2 100644 --- a/docs/tutorials/persistent-shared-workspaces.md +++ b/docs/tutorials/persistent-shared-workspaces.md @@ -212,9 +212,12 @@ in Okta or Azure AD), you can skip manual share/remove commands entirely: Shared users can find workspaces shared with them: ```shell -# List all workspaces shared with you +# List all shared workspaces you can access, including your own coder list --search shared:true +# List workspaces shared with you +coder list --search shared_with_user:me + # List workspaces shared with a specific user coder list --search shared_with_user:alice diff --git a/docs/user-guides/shared-workspaces.md b/docs/user-guides/shared-workspaces.md index 9da5f5fa08..a63872fbec 100644 --- a/docs/user-guides/shared-workspaces.md +++ b/docs/user-guides/shared-workspaces.md @@ -50,6 +50,7 @@ To show who a workspace is shared with: To list shared workspaces: - `coder list --search shared:true` +- `coder list --search shared_with_user:me` - `coder list --search shared_with_user:` - `coder list --search shared_with_group:`