Skip to content

Commit 1cffd11

Browse files
authored
feat: add workspace sharing page (#19107)
1 parent ddb5b87 commit 1cffd11

File tree

28 files changed

+668
-52
lines changed

28 files changed

+668
-52
lines changed

coderd/apidoc/docs.go

Lines changed: 76 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/apidoc/swagger.json

Lines changed: 66 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/coderd.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1413,6 +1413,12 @@ func New(options *Options) *API {
14131413
r.Delete("/", api.deleteWorkspaceAgentPortShare)
14141414
})
14151415
r.Get("/timings", api.workspaceTimings)
1416+
r.Route("/acl", func(r chi.Router) {
1417+
r.Use(
1418+
httpmw.RequireExperiment(api.Experiments, codersdk.ExperimentWorkspaceSharing))
1419+
1420+
r.Patch("/", api.patchWorkspaceACL)
1421+
})
14161422
})
14171423
})
14181424
r.Route("/workspacebuilds/{workspacebuild}", func(r chi.Router) {

coderd/coderdtest/swaggerparser.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,8 @@ func assertProduce(t *testing.T, comment SwaggerComment) {
360360
(comment.router == "/workspaceagents/me/startup/logs" && comment.method == "patch") ||
361361
(comment.router == "/licenses/{id}" && comment.method == "delete") ||
362362
(comment.router == "/debug/coordinator" && comment.method == "get") ||
363-
(comment.router == "/debug/tailnet" && comment.method == "get") {
363+
(comment.router == "/debug/tailnet" && comment.method == "get") ||
364+
(comment.router == "/workspaces/{workspace}/acl" && comment.method == "patch") {
364365
return // Exception: HTTP 200 is returned without response entity
365366
}
366367

coderd/database/db2sdk/db2sdk.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"github.com/coder/coder/v2/coderd/rbac/policy"
2525
"github.com/coder/coder/v2/coderd/render"
2626
"github.com/coder/coder/v2/coderd/util/ptr"
27+
"github.com/coder/coder/v2/coderd/util/slice"
2728
"github.com/coder/coder/v2/coderd/workspaceapps/appurl"
2829
"github.com/coder/coder/v2/codersdk"
2930
"github.com/coder/coder/v2/provisionersdk/proto"
@@ -781,6 +782,29 @@ func TemplateRoleActions(role codersdk.TemplateRole) []policy.Action {
781782
return []policy.Action{}
782783
}
783784

785+
func WorkspaceRoleActions(role codersdk.WorkspaceRole) []policy.Action {
786+
switch role {
787+
case codersdk.WorkspaceRoleAdmin:
788+
return slice.Omit(
789+
// Small note: This intentionally includes "create" because it's sort of
790+
// double purposed as "can edit ACL". That's maybe a bit "incorrect", but
791+
// it's what templates do already and we're copying that implementation.
792+
rbac.ResourceWorkspace.AvailableActions(),
793+
// Don't let anyone delete something they can't recreate.
794+
policy.ActionDelete,
795+
)
796+
case codersdk.WorkspaceRoleUse:
797+
return []policy.Action{
798+
policy.ActionApplicationConnect,
799+
policy.ActionRead,
800+
policy.ActionSSH,
801+
policy.ActionWorkspaceStart,
802+
policy.ActionWorkspaceStop,
803+
}
804+
}
805+
return []policy.Action{}
806+
}
807+
784808
func ConnectionLogConnectionTypeFromAgentProtoConnectionType(typ agentproto.Connection_Type) (database.ConnectionType, error) {
785809
switch typ {
786810
case agentproto.Connection_SSH:

coderd/database/dbauthz/dbauthz.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4919,6 +4919,18 @@ func (q *querier) UpdateWorkspace(ctx context.Context, arg database.UpdateWorksp
49194919
return updateWithReturn(q.log, q.auth, fetch, q.db.UpdateWorkspace)(ctx, arg)
49204920
}
49214921

4922+
func (q *querier) UpdateWorkspaceACLByID(ctx context.Context, arg database.UpdateWorkspaceACLByIDParams) error {
4923+
fetch := func(ctx context.Context, arg database.UpdateWorkspaceACLByIDParams) (database.WorkspaceTable, error) {
4924+
w, err := q.db.GetWorkspaceByID(ctx, arg.ID)
4925+
if err != nil {
4926+
return database.WorkspaceTable{}, err
4927+
}
4928+
return w.WorkspaceTable(), nil
4929+
}
4930+
4931+
return fetchAndExec(q.log, q.auth, policy.ActionCreate, fetch, q.db.UpdateWorkspaceACLByID)(ctx, arg)
4932+
}
4933+
49224934
func (q *querier) UpdateWorkspaceAgentConnectionByID(ctx context.Context, arg database.UpdateWorkspaceAgentConnectionByIDParams) error {
49234935
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceSystem); err != nil {
49244936
return err

coderd/database/dbauthz/dbauthz_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2146,6 +2146,22 @@ func (s *MethodTestSuite) TestWorkspace() {
21462146
// no asserts here because SQLFilter
21472147
check.Args([]uuid.UUID{}, emptyPreparedAuthorized{}).Asserts()
21482148
}))
2149+
s.Run("UpdateWorkspaceACLByID", s.Subtest(func(db database.Store, check *expects) {
2150+
u := dbgen.User(s.T(), db, database.User{})
2151+
o := dbgen.Organization(s.T(), db, database.Organization{})
2152+
tpl := dbgen.Template(s.T(), db, database.Template{
2153+
OrganizationID: o.ID,
2154+
CreatedBy: u.ID,
2155+
})
2156+
ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{
2157+
OwnerID: u.ID,
2158+
OrganizationID: o.ID,
2159+
TemplateID: tpl.ID,
2160+
})
2161+
check.Args(database.UpdateWorkspaceACLByIDParams{
2162+
ID: ws.ID,
2163+
}).Asserts(ws, policy.ActionCreate)
2164+
}))
21492165
s.Run("GetLatestWorkspaceBuildByWorkspaceID", s.Subtest(func(db database.Store, check *expects) {
21502166
u := dbgen.User(s.T(), db, database.User{})
21512167
o := dbgen.Organization(s.T(), db, database.Organization{})

coderd/database/dbmetrics/querymetrics.go

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

coderd/database/dbmock/dbmock.go

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

coderd/database/modelmethods.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,9 @@ func (w WorkspaceTable) RBACObject() rbac.Object {
276276

277277
return rbac.ResourceWorkspace.WithID(w.ID).
278278
InOrg(w.OrganizationID).
279-
WithOwner(w.OwnerID.String())
279+
WithOwner(w.OwnerID.String()).
280+
WithGroupACL(w.GroupACL.RBACACL()).
281+
WithACLUserList(w.UserACL.RBACACL())
280282
}
281283

282284
func (w WorkspaceTable) DormantRBAC() rbac.Object {

0 commit comments

Comments
 (0)