Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit01a8eb0

Browse files
committed
feat: add shared_with_user search filter
1 parent6238937 commit01a8eb0

File tree

7 files changed

+148
-9
lines changed

7 files changed

+148
-9
lines changed

‎coderd/database/modelqueries.go‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@ func (q *sqlQuerier) GetAuthorizedWorkspaces(ctx context.Context, arg GetWorkspa
276276
arg.HasAITask,
277277
arg.HasExternalAgent,
278278
arg.Shared,
279+
arg.SharedWithUserID,
279280
arg.RequesterID,
280281
arg.Offset,
281282
arg.Limit,

‎coderd/database/queries.sql.go‎

Lines changed: 13 additions & 6 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/database/queries/workspaces.sql‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,12 @@ WHERE
384384
(workspaces.user_acl!='{}'::jsonbORworkspaces.group_acl!='{}'::jsonb)=sqlc.narg('shared') ::boolean
385385
ELSE true
386386
END
387-
387+
-- Filter by shared_with_user_id
388+
AND CASE
389+
WHEN @shared_with_user_id :: uuid!='00000000-0000-0000-0000-000000000000'::uuid THEN
390+
workspaces.user_acl ? (@shared_with_user_id :: uuid) ::text
391+
ELSE true
392+
END
388393
-- Authorize Filter clause will be injected below in GetAuthorizedWorkspaces
389394
-- @authorize_filter
390395
), filtered_workspaces_orderAS (

‎coderd/searchquery/search.go‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ func Workspaces(ctx context.Context, db database.Store, query string, page coder
226226
filter.HasExternalAgent=parser.NullableBoolean(values, sql.NullBool{},"has_external_agent")
227227
filter.OrganizationID=parseOrganization(ctx,db,parser,values,"organization")
228228
filter.Shared=parser.NullableBoolean(values, sql.NullBool{},"shared")
229+
filter.SharedWithUserID=parseUser(ctx,db,parser,values,"shared_with_user")
229230

230231
typeparamMatchstruct {
231232
namestring
@@ -363,6 +364,25 @@ func parseOrganization(ctx context.Context, db database.Store, parser *httpapi.Q
363364
})
364365
}
365366

367+
funcparseUser(ctx context.Context,db database.Store,parser*httpapi.QueryParamParser,vals url.Values,queryParamstring) uuid.UUID {
368+
returnhttpapi.ParseCustom(parser,vals,uuid.Nil,queryParam,func(vstring) (uuid.UUID,error) {
369+
ifv=="" {
370+
returnuuid.Nil,nil
371+
}
372+
userID,err:=uuid.Parse(v)
373+
iferr==nil {
374+
returnuserID,nil
375+
}
376+
user,err:=db.GetUserByEmailOrUsername(ctx, database.GetUserByEmailOrUsernameParams{
377+
Username:v,
378+
})
379+
iferr!=nil {
380+
returnuuid.Nil,xerrors.Errorf("user %q either does not exist, or you are unauthorized to view them",v)
381+
}
382+
returnuser.ID,nil
383+
})
384+
}
385+
366386
// splitQueryParameterByDelimiter takes a query string and splits it into the individual elements
367387
// of the query. Each element is separated by a delimiter. All quoted strings are
368388
// kept as a single element.

‎coderd/searchquery/search_test.go‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,31 @@ func TestSearchWorkspace(t *testing.T) {
312312
},
313313
},
314314
},
315+
{
316+
Name:"SharedWithUser",
317+
Query:`shared_with_user:3dd8b1b8-dff5-4b22-8ae9-c243ca136ecf`,
318+
Setup:func(t*testing.T,db database.Store) {
319+
dbgen.User(t,db, database.User{
320+
ID:uuid.MustParse("3dd8b1b8-dff5-4b22-8ae9-c243ca136ecf"),
321+
})
322+
},
323+
Expected: database.GetWorkspacesParams{
324+
SharedWithUserID:uuid.MustParse("3dd8b1b8-dff5-4b22-8ae9-c243ca136ecf"),
325+
},
326+
},
327+
{
328+
Name:"SharedWithUserByName",
329+
Query:`shared_with_user:wibble`,
330+
Setup:func(t*testing.T,db database.Store) {
331+
dbgen.User(t,db, database.User{
332+
ID:uuid.MustParse("3dd8b1b8-dff5-4b22-8ae9-c243ca136ecf"),
333+
Username:"wibble",
334+
})
335+
},
336+
Expected: database.GetWorkspacesParams{
337+
SharedWithUserID:uuid.MustParse("3dd8b1b8-dff5-4b22-8ae9-c243ca136ecf"),
338+
},
339+
},
315340

316341
// Failures
317342
{

‎coderd/workspaces_test.go‎

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1813,7 +1813,7 @@ func TestWorkspaceFilter(t *testing.T) {
18131813
})
18141814
}
18151815

1816-
t.Run("SharedWithUser",func(t*testing.T) {
1816+
t.Run("Shared",func(t*testing.T) {
18171817
t.Parallel()
18181818

18191819
dv:=coderdtest.DeploymentValues(t)
@@ -1851,7 +1851,7 @@ func TestWorkspaceFilter(t *testing.T) {
18511851
require.Equal(t,workspaces.Workspaces[0].ID,sharedWorkspace.ID)
18521852
})
18531853

1854-
t.Run("NotSharedWithUser",func(t*testing.T) {
1854+
t.Run("NotShared",func(t*testing.T) {
18551855
t.Parallel()
18561856

18571857
dv:=coderdtest.DeploymentValues(t)
@@ -1888,6 +1888,82 @@ func TestWorkspaceFilter(t *testing.T) {
18881888
require.Equal(t,1,workspaces.Count,"expected only one workspace")
18891889
require.Equal(t,workspaces.Workspaces[0].ID,notSharedWorkspace.ID)
18901890
})
1891+
1892+
t.Run("SharedWithUserByID",func(t*testing.T) {
1893+
t.Parallel()
1894+
1895+
dv:=coderdtest.DeploymentValues(t)
1896+
dv.Experiments= []string{string(codersdk.ExperimentWorkspaceSharing)}
1897+
1898+
var (
1899+
client,db=coderdtest.NewWithDatabase(t,&coderdtest.Options{
1900+
DeploymentValues:dv,
1901+
})
1902+
orgOwner=coderdtest.CreateFirstUser(t,client)
1903+
_,workspaceOwner=coderdtest.CreateAnotherUser(t,client,orgOwner.OrganizationID,rbac.ScopedRoleOrgAuditor(orgOwner.OrganizationID))
1904+
sharedWorkspace=dbfake.WorkspaceBuild(t,db, database.WorkspaceTable{
1905+
OwnerID:workspaceOwner.ID,
1906+
OrganizationID:orgOwner.OrganizationID,
1907+
}).Do().Workspace
1908+
_=dbfake.WorkspaceBuild(t,db, database.WorkspaceTable{
1909+
OwnerID:workspaceOwner.ID,
1910+
OrganizationID:orgOwner.OrganizationID,
1911+
}).Do().Workspace
1912+
_,toShareWithUser=coderdtest.CreateAnotherUser(t,client,orgOwner.OrganizationID)
1913+
ctx=testutil.Context(t,testutil.WaitMedium)
1914+
)
1915+
1916+
client.UpdateWorkspaceACL(ctx,sharedWorkspace.ID, codersdk.UpdateWorkspaceACL{
1917+
UserRoles:map[string]codersdk.WorkspaceRole{
1918+
toShareWithUser.ID.String():codersdk.WorkspaceRoleUse,
1919+
},
1920+
})
1921+
1922+
workspaces,err:=client.Workspaces(ctx, codersdk.WorkspaceFilter{
1923+
SharedWithUser:toShareWithUser.ID.String(),
1924+
})
1925+
require.NoError(t,err,"fetch workspaces")
1926+
require.Equal(t,1,workspaces.Count,"expected only one workspace")
1927+
require.Equal(t,workspaces.Workspaces[0].ID,sharedWorkspace.ID)
1928+
})
1929+
1930+
t.Run("SharedWithUserByUsername",func(t*testing.T) {
1931+
t.Parallel()
1932+
1933+
dv:=coderdtest.DeploymentValues(t)
1934+
dv.Experiments= []string{string(codersdk.ExperimentWorkspaceSharing)}
1935+
1936+
var (
1937+
client,db=coderdtest.NewWithDatabase(t,&coderdtest.Options{
1938+
DeploymentValues:dv,
1939+
})
1940+
orgOwner=coderdtest.CreateFirstUser(t,client)
1941+
_,workspaceOwner=coderdtest.CreateAnotherUser(t,client,orgOwner.OrganizationID,rbac.ScopedRoleOrgAuditor(orgOwner.OrganizationID))
1942+
sharedWorkspace=dbfake.WorkspaceBuild(t,db, database.WorkspaceTable{
1943+
OwnerID:workspaceOwner.ID,
1944+
OrganizationID:orgOwner.OrganizationID,
1945+
}).Do().Workspace
1946+
_=dbfake.WorkspaceBuild(t,db, database.WorkspaceTable{
1947+
OwnerID:workspaceOwner.ID,
1948+
OrganizationID:orgOwner.OrganizationID,
1949+
}).Do().Workspace
1950+
_,toShareWithUser=coderdtest.CreateAnotherUser(t,client,orgOwner.OrganizationID)
1951+
ctx=testutil.Context(t,testutil.WaitMedium)
1952+
)
1953+
1954+
client.UpdateWorkspaceACL(ctx,sharedWorkspace.ID, codersdk.UpdateWorkspaceACL{
1955+
UserRoles:map[string]codersdk.WorkspaceRole{
1956+
toShareWithUser.ID.String():codersdk.WorkspaceRoleUse,
1957+
},
1958+
})
1959+
1960+
workspaces,err:=client.Workspaces(ctx, codersdk.WorkspaceFilter{
1961+
SharedWithUser:toShareWithUser.Username,
1962+
})
1963+
require.NoError(t,err,"fetch workspaces")
1964+
require.Equal(t,1,workspaces.Count,"expected only one workspace")
1965+
require.Equal(t,workspaces.Workspaces[0].ID,sharedWorkspace.ID)
1966+
})
18911967
}
18921968

18931969
// TestWorkspaceFilterManual runs some specific setups with basic checks.

‎codersdk/workspaces.go‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,8 @@ type WorkspaceFilter struct {
518518
Limitint`json:"limit,omitempty" typescript:"-"`
519519
// Shared is a whether the workspace is shared with any users or groups
520520
Shared*bool`json:"shared,omitempty" typescript:"-"`
521+
// SharedWithUser is the username or ID of the user that the workspace is shared with
522+
SharedWithUserstring`json:"shared_with_user,omitempty" typescript:"-"`
521523
// FilterQuery supports a raw filter query string
522524
FilterQuerystring`json:"q,omitempty"`
523525
}
@@ -544,6 +546,9 @@ func (f WorkspaceFilter) asRequestOption() RequestOption {
544546
iff.Shared!=nil {
545547
params=append(params,fmt.Sprintf("shared:%v",*f.Shared))
546548
}
549+
iff.SharedWithUser!="" {
550+
params=append(params,fmt.Sprintf("shared_with_user:%q",f.SharedWithUser))
551+
}
547552
iff.FilterQuery!="" {
548553
// If custom stuff is added, just add it on here.
549554
params=append(params,f.FilterQuery)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp