diff --git a/cli/list_test.go b/cli/list_test.go index 0210fd715f..8cdde03072 100644 --- a/cli/list_test.go +++ b/cli/list_test.go @@ -106,11 +106,7 @@ func TestList(t *testing.T) { t.Parallel() var ( - client, db = coderdtest.NewWithDatabase(t, &coderdtest.Options{ - DeploymentValues: coderdtest.DeploymentValues(t, func(dv *codersdk.DeploymentValues) { - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} - }), - }) + client, db = coderdtest.NewWithDatabase(t, nil) orgOwner = coderdtest.CreateFirstUser(t, client) memberClient, member = coderdtest.CreateAnotherUser(t, client, orgOwner.OrganizationID, rbac.ScopedRoleOrgAuditor(orgOwner.OrganizationID)) sharedWorkspace = dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{ diff --git a/cli/sharing_test.go b/cli/sharing_test.go index 19e1853470..26ad858d09 100644 --- a/cli/sharing_test.go +++ b/cli/sharing_test.go @@ -25,11 +25,7 @@ func TestSharingShare(t *testing.T) { t.Parallel() var ( - client, db = coderdtest.NewWithDatabase(t, &coderdtest.Options{ - DeploymentValues: coderdtest.DeploymentValues(t, func(dv *codersdk.DeploymentValues) { - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} - }), - }) + client, db = coderdtest.NewWithDatabase(t, nil) orgOwner = coderdtest.CreateFirstUser(t, client) workspaceOwnerClient, workspaceOwner = coderdtest.CreateAnotherUser(t, client, orgOwner.OrganizationID, rbac.ScopedRoleOrgAuditor(orgOwner.OrganizationID)) workspace = dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{ @@ -68,12 +64,8 @@ func TestSharingShare(t *testing.T) { t.Parallel() var ( - client, db = coderdtest.NewWithDatabase(t, &coderdtest.Options{ - DeploymentValues: coderdtest.DeploymentValues(t, func(dv *codersdk.DeploymentValues) { - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} - }), - }) - orgOwner = coderdtest.CreateFirstUser(t, client) + client, db = coderdtest.NewWithDatabase(t, nil) + orgOwner = coderdtest.CreateFirstUser(t, client) workspaceOwnerClient, workspaceOwner = coderdtest.CreateAnotherUser(t, client, orgOwner.OrganizationID, rbac.ScopedRoleOrgAuditor(orgOwner.OrganizationID)) workspace = dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{ @@ -127,11 +119,7 @@ func TestSharingShare(t *testing.T) { t.Parallel() var ( - client, db = coderdtest.NewWithDatabase(t, &coderdtest.Options{ - DeploymentValues: coderdtest.DeploymentValues(t, func(dv *codersdk.DeploymentValues) { - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} - }), - }) + client, db = coderdtest.NewWithDatabase(t, nil) orgOwner = coderdtest.CreateFirstUser(t, client) workspaceOwnerClient, workspaceOwner = coderdtest.CreateAnotherUser(t, client, orgOwner.OrganizationID, rbac.ScopedRoleOrgAuditor(orgOwner.OrganizationID)) workspace = dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{ @@ -182,11 +170,7 @@ func TestSharingStatus(t *testing.T) { t.Parallel() var ( - client, db = coderdtest.NewWithDatabase(t, &coderdtest.Options{ - DeploymentValues: coderdtest.DeploymentValues(t, func(dv *codersdk.DeploymentValues) { - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} - }), - }) + client, db = coderdtest.NewWithDatabase(t, nil) orgOwner = coderdtest.CreateFirstUser(t, client) workspaceOwnerClient, workspaceOwner = coderdtest.CreateAnotherUser(t, client, orgOwner.OrganizationID, rbac.ScopedRoleOrgAuditor(orgOwner.OrganizationID)) workspace = dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{ @@ -230,11 +214,7 @@ func TestSharingRemove(t *testing.T) { t.Parallel() var ( - client, db = coderdtest.NewWithDatabase(t, &coderdtest.Options{ - DeploymentValues: coderdtest.DeploymentValues(t, func(dv *codersdk.DeploymentValues) { - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} - }), - }) + client, db = coderdtest.NewWithDatabase(t, nil) orgOwner = coderdtest.CreateFirstUser(t, client) workspaceOwnerClient, workspaceOwner = coderdtest.CreateAnotherUser(t, client, orgOwner.OrganizationID, rbac.ScopedRoleOrgAuditor(orgOwner.OrganizationID)) workspace = dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{ @@ -291,11 +271,7 @@ func TestSharingRemove(t *testing.T) { t.Parallel() var ( - client, db = coderdtest.NewWithDatabase(t, &coderdtest.Options{ - DeploymentValues: coderdtest.DeploymentValues(t, func(dv *codersdk.DeploymentValues) { - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} - }), - }) + client, db = coderdtest.NewWithDatabase(t, nil) orgOwner = coderdtest.CreateFirstUser(t, client) workspaceOwnerClient, workspaceOwner = coderdtest.CreateAnotherUser(t, client, orgOwner.OrganizationID, rbac.ScopedRoleOrgAuditor(orgOwner.OrganizationID)) workspace = dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{ diff --git a/cli/testdata/coder_server_--help.golden b/cli/testdata/coder_server_--help.golden index 7143abf16a..c9e4818ed9 100644 --- a/cli/testdata/coder_server_--help.golden +++ b/cli/testdata/coder_server_--help.golden @@ -49,10 +49,9 @@ OPTIONS: security purposes if a --wildcard-access-url is configured. --disable-workspace-sharing bool, $CODER_DISABLE_WORKSPACE_SHARING - Disable workspace sharing (requires the "workspace-sharing" experiment - to be enabled). Workspace ACL checking is disabled and only owners can - have ssh, apps and terminal access to workspaces. Access based on the - 'owner' role is also allowed unless disabled via + Disable workspace sharing. Workspace ACL checking is disabled and only + owners can have ssh, apps and terminal access to workspaces. Access + based on the 'owner' role is also allowed unless disabled via --disable-owner-workspace-access. --swagger-enable bool, $CODER_SWAGGER_ENABLE diff --git a/cli/testdata/server-config.yaml.golden b/cli/testdata/server-config.yaml.golden index d8f342c2ed..fa7057c60b 100644 --- a/cli/testdata/server-config.yaml.golden +++ b/cli/testdata/server-config.yaml.golden @@ -523,10 +523,10 @@ disablePathApps: false # workspaces. # (default: , type: bool) disableOwnerWorkspaceAccess: false -# Disable workspace sharing (requires the "workspace-sharing" experiment to be -# enabled). Workspace ACL checking is disabled and only owners can have ssh, apps -# and terminal access to workspaces. Access based on the 'owner' role is also -# allowed unless disabled via --disable-owner-workspace-access. +# Disable workspace sharing. Workspace ACL checking is disabled and only owners +# can have ssh, apps and terminal access to workspaces. Access based on the +# 'owner' role is also allowed unless disabled via +# --disable-owner-workspace-access. # (default: , type: bool) disableWorkspaceSharing: false # These options change the behavior of how clients interact with the Coder. diff --git a/coderd/aitasks.go b/coderd/aitasks.go index a58543fe6e..4d24f86ed7 100644 --- a/coderd/aitasks.go +++ b/coderd/aitasks.go @@ -466,7 +466,6 @@ func (api *API) convertTasks(ctx context.Context, requesterID uuid.UUID, dbTasks apiWorkspaces, err := convertWorkspaces( ctx, - api.Experiments, api.Logger, requesterID, workspaces, @@ -546,7 +545,6 @@ func (api *API) taskGet(rw http.ResponseWriter, r *http.Request) { ws, err := convertWorkspace( ctx, - api.Experiments, api.Logger, apiKey.UserID, workspace, diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index 810fb23cc4..19a4b037f0 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -15097,8 +15097,7 @@ const docTemplate = `{ "workspace-usage", "web-push", "oauth2", - "mcp-server-http", - "workspace-sharing" + "mcp-server-http" ], "x-enum-comments": { "ExperimentAutoFillParameters": "This should not be taken out of experiments until we have redesigned the feature.", @@ -15107,7 +15106,6 @@ const docTemplate = `{ "ExperimentNotifications": "Sends notifications via SMTP and webhooks following certain events.", "ExperimentOAuth2": "Enables OAuth2 provider functionality.", "ExperimentWebPush": "Enables web push notifications through the browser.", - "ExperimentWorkspaceSharing": "Enables updating workspace ACLs for sharing with users and groups.", "ExperimentWorkspaceUsage": "Enables the new workspace usage tracking." }, "x-enum-descriptions": [ @@ -15117,8 +15115,7 @@ const docTemplate = `{ "Enables the new workspace usage tracking.", "Enables web push notifications through the browser.", "Enables OAuth2 provider functionality.", - "Enables the MCP HTTP server functionality.", - "Enables updating workspace ACLs for sharing with users and groups." + "Enables the MCP HTTP server functionality." ], "x-enum-varnames": [ "ExperimentExample", @@ -15127,8 +15124,7 @@ const docTemplate = `{ "ExperimentWorkspaceUsage", "ExperimentWebPush", "ExperimentOAuth2", - "ExperimentMCPServerHTTP", - "ExperimentWorkspaceSharing" + "ExperimentMCPServerHTTP" ] }, "codersdk.ExternalAPIKeyScopes": { diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index 7aa22c553d..31135a891e 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -13624,8 +13624,7 @@ "workspace-usage", "web-push", "oauth2", - "mcp-server-http", - "workspace-sharing" + "mcp-server-http" ], "x-enum-comments": { "ExperimentAutoFillParameters": "This should not be taken out of experiments until we have redesigned the feature.", @@ -13634,7 +13633,6 @@ "ExperimentNotifications": "Sends notifications via SMTP and webhooks following certain events.", "ExperimentOAuth2": "Enables OAuth2 provider functionality.", "ExperimentWebPush": "Enables web push notifications through the browser.", - "ExperimentWorkspaceSharing": "Enables updating workspace ACLs for sharing with users and groups.", "ExperimentWorkspaceUsage": "Enables the new workspace usage tracking." }, "x-enum-descriptions": [ @@ -13644,8 +13642,7 @@ "Enables the new workspace usage tracking.", "Enables web push notifications through the browser.", "Enables OAuth2 provider functionality.", - "Enables the MCP HTTP server functionality.", - "Enables updating workspace ACLs for sharing with users and groups." + "Enables the MCP HTTP server functionality." ], "x-enum-varnames": [ "ExperimentExample", @@ -13654,8 +13651,7 @@ "ExperimentWorkspaceUsage", "ExperimentWebPush", "ExperimentOAuth2", - "ExperimentMCPServerHTTP", - "ExperimentWorkspaceSharing" + "ExperimentMCPServerHTTP" ] }, "codersdk.ExternalAPIKeyScopes": { diff --git a/coderd/coderd.go b/coderd/coderd.go index c439722f20..99a3073ad3 100644 --- a/coderd/coderd.go +++ b/coderd/coderd.go @@ -1526,10 +1526,6 @@ func New(options *Options) *API { }) r.Get("/timings", api.workspaceTimings) r.Route("/acl", func(r chi.Router) { - r.Use( - httpmw.RequireExperiment(api.Experiments, codersdk.ExperimentWorkspaceSharing), - ) - r.Get("/", api.workspaceACL) r.Patch("/", api.patchWorkspaceACL) r.Delete("/", api.deleteWorkspaceACL) diff --git a/coderd/workspaces.go b/coderd/workspaces.go index 1077cafe6a..847b2403e7 100644 --- a/coderd/workspaces.go +++ b/coderd/workspaces.go @@ -114,7 +114,6 @@ func (api *API) workspace(rw http.ResponseWriter, r *http.Request) { w, err := convertWorkspace( ctx, - api.Experiments, api.Logger, apiKey.UserID, workspace, @@ -240,7 +239,6 @@ func (api *API) workspaces(rw http.ResponseWriter, r *http.Request) { wss, err := convertWorkspaces( ctx, - api.Experiments, api.Logger, apiKey.UserID, workspaces, @@ -336,7 +334,6 @@ func (api *API) workspaceByOwnerAndName(rw http.ResponseWriter, r *http.Request) w, err := convertWorkspace( ctx, - api.Experiments, api.Logger, apiKey.UserID, workspace, @@ -868,7 +865,6 @@ func createWorkspace( w, err := convertWorkspace( ctx, - api.Experiments, api.Logger, initiatorID, workspace, @@ -1514,7 +1510,6 @@ func (api *API) putWorkspaceDormant(rw http.ResponseWriter, r *http.Request) { w, err := convertWorkspace( ctx, - api.Experiments, api.Logger, apiKey.UserID, workspace, @@ -2094,7 +2089,6 @@ func (api *API) watchWorkspace( } w, err := convertWorkspace( ctx, - api.Experiments, api.Logger, apiKey.UserID, workspace, @@ -2236,8 +2230,7 @@ func (api *API) workspaceACL(rw http.ResponseWriter, r *http.Request) { // the case here. This data goes directly to an unauthorized user. We are // just straight up breaking security promises. // - // Fine for now while behind the shared-workspaces experiment, but needs to - // be fixed before GA. + // TODO: This needs to be fixed before GA. Currently in beta. // Fetch all of the users and their organization memberships userIDs := make([]uuid.UUID, 0, len(workspaceACL.Users)) @@ -2595,7 +2588,6 @@ func (api *API) workspaceData(ctx context.Context, workspaces []database.Workspa func convertWorkspaces( ctx context.Context, - experiments codersdk.Experiments, logger slog.Logger, requesterID uuid.UUID, workspaces []database.Workspace, @@ -2633,7 +2625,6 @@ func convertWorkspaces( w, err := convertWorkspace( ctx, - experiments, logger, requesterID, workspace, @@ -2653,7 +2644,6 @@ func convertWorkspaces( func convertWorkspace( ctx context.Context, - experiments codersdk.Experiments, logger slog.Logger, requesterID uuid.UUID, workspace database.Workspace, @@ -2752,20 +2742,15 @@ func convertWorkspace( NextStartAt: nextStartAt, IsPrebuild: workspace.IsPrebuild(), TaskID: workspace.TaskID, - SharedWith: sharedWorkspaceActors(ctx, experiments, logger, workspace), + SharedWith: sharedWorkspaceActors(ctx, logger, workspace), }, nil } func sharedWorkspaceActors( ctx context.Context, - experiments codersdk.Experiments, logger slog.Logger, workspace database.Workspace, ) []codersdk.SharedWorkspaceActor { - if !experiments.Enabled(codersdk.ExperimentWorkspaceSharing) { - return nil - } - out := make([]codersdk.SharedWorkspaceActor, 0, len(workspace.UserACL)+len(workspace.GroupACL)) // Users diff --git a/coderd/workspaces_test.go b/coderd/workspaces_test.go index e09ea3a29b..c3b80396b9 100644 --- a/coderd/workspaces_test.go +++ b/coderd/workspaces_test.go @@ -1899,7 +1899,6 @@ func TestWorkspaceFilter(t *testing.T) { t.Parallel() dv := coderdtest.DeploymentValues(t) - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} var ( client, db = coderdtest.NewWithDatabase(t, &coderdtest.Options{ @@ -1937,7 +1936,6 @@ func TestWorkspaceFilter(t *testing.T) { t.Parallel() dv := coderdtest.DeploymentValues(t) - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} var ( client, db = coderdtest.NewWithDatabase(t, &coderdtest.Options{ @@ -1975,7 +1973,6 @@ func TestWorkspaceFilter(t *testing.T) { t.Parallel() dv := coderdtest.DeploymentValues(t) - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} var ( client, db = coderdtest.NewWithDatabase(t, &coderdtest.Options{ @@ -2013,7 +2010,6 @@ func TestWorkspaceFilter(t *testing.T) { t.Parallel() dv := coderdtest.DeploymentValues(t) - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} var ( client, db = coderdtest.NewWithDatabase(t, &coderdtest.Options{ @@ -5249,7 +5245,7 @@ func TestUpdateWorkspaceACL(t *testing.T) { t.Parallel() dv := coderdtest.DeploymentValues(t) - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} + adminClient := coderdtest.New(t, &coderdtest.Options{ IncludeProvisionerDaemon: true, DeploymentValues: dv, @@ -5285,7 +5281,7 @@ func TestUpdateWorkspaceACL(t *testing.T) { t.Parallel() dv := coderdtest.DeploymentValues(t) - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} + adminClient := coderdtest.New(t, &coderdtest.Options{ IncludeProvisionerDaemon: true, DeploymentValues: dv, @@ -5318,7 +5314,7 @@ func TestUpdateWorkspaceACL(t *testing.T) { t.Parallel() dv := coderdtest.DeploymentValues(t) - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} + adminClient := coderdtest.New(t, &coderdtest.Options{ IncludeProvisionerDaemon: true, DeploymentValues: dv, @@ -5358,7 +5354,7 @@ func TestUpdateWorkspaceACL(t *testing.T) { t.Cleanup(func() { rbac.SetWorkspaceACLDisabled(prevWorkspaceACLDisabled) }) dv := coderdtest.DeploymentValues(t) - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} + adminClient := coderdtest.New(t, &coderdtest.Options{ IncludeProvisionerDaemon: true, DeploymentValues: dv, @@ -5426,11 +5422,7 @@ func TestDeleteWorkspaceACL(t *testing.T) { t.Parallel() var ( - client, db = coderdtest.NewWithDatabase(t, &coderdtest.Options{ - DeploymentValues: coderdtest.DeploymentValues(t, func(dv *codersdk.DeploymentValues) { - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} - }), - }) + client, db = coderdtest.NewWithDatabase(t, nil) admin = coderdtest.CreateFirstUser(t, client) workspaceOwnerClient, workspaceOwner = coderdtest.CreateAnotherUser(t, client, admin.OrganizationID) _, toShareWithUser = coderdtest.CreateAnotherUser(t, client, admin.OrganizationID) @@ -5461,11 +5453,7 @@ func TestDeleteWorkspaceACL(t *testing.T) { t.Parallel() var ( - client, db = coderdtest.NewWithDatabase(t, &coderdtest.Options{ - DeploymentValues: coderdtest.DeploymentValues(t, func(dv *codersdk.DeploymentValues) { - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} - }), - }) + client, db = coderdtest.NewWithDatabase(t, nil) admin = coderdtest.CreateFirstUser(t, client) workspaceOwnerClient, workspaceOwner = coderdtest.CreateAnotherUser(t, client, admin.OrganizationID) sharedUseClient, toShareWithUser = coderdtest.CreateAnotherUser(t, client, admin.OrganizationID) @@ -5504,11 +5492,7 @@ func TestWorkspaceReadCanListACL(t *testing.T) { t.Cleanup(func() { rbac.SetWorkspaceACLDisabled(prevWorkspaceACLDisabled) }) var ( - client, db = coderdtest.NewWithDatabase(t, &coderdtest.Options{ - DeploymentValues: coderdtest.DeploymentValues(t, func(dv *codersdk.DeploymentValues) { - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} - }), - }) + client, db = coderdtest.NewWithDatabase(t, nil) admin = coderdtest.CreateFirstUser(t, client) workspaceOwnerClient, workspaceOwner = coderdtest.CreateAnotherUser(t, client, admin.OrganizationID) sharedUserClientA, sharedUserA = coderdtest.CreateAnotherUser(t, client, admin.OrganizationID) @@ -5558,7 +5542,6 @@ func TestWorkspaceSharingDisabled(t *testing.T) { var ( client, db = coderdtest.NewWithDatabase(t, &coderdtest.Options{ DeploymentValues: coderdtest.DeploymentValues(t, func(dv *codersdk.DeploymentValues) { - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} // DisableWorkspaceSharing is false (default) }), }) @@ -5592,7 +5575,6 @@ func TestWorkspaceSharingDisabled(t *testing.T) { var ( client, db = coderdtest.NewWithDatabase(t, &coderdtest.Options{ DeploymentValues: coderdtest.DeploymentValues(t, func(dv *codersdk.DeploymentValues) { - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} dv.DisableWorkspaceSharing = true }), }) diff --git a/codersdk/deployment.go b/codersdk/deployment.go index 85ce2ea255..a586c6cf56 100644 --- a/codersdk/deployment.go +++ b/codersdk/deployment.go @@ -3042,7 +3042,7 @@ func (c *DeploymentValues) Options() serpent.OptionSet { }, { Name: "Disable Workspace Sharing", - Description: `Disable workspace sharing (requires the "workspace-sharing" experiment to be enabled). Workspace ACL checking is disabled and only owners can have ssh, apps and terminal access to workspaces. Access based on the 'owner' role is also allowed unless disabled via --disable-owner-workspace-access.`, + Description: `Disable workspace sharing. Workspace ACL checking is disabled and only owners can have ssh, apps and terminal access to workspaces. Access based on the 'owner' role is also allowed unless disabled via --disable-owner-workspace-access.`, Flag: "disable-workspace-sharing", Env: "CODER_DISABLE_WORKSPACE_SHARING", @@ -4265,7 +4265,6 @@ const ( ExperimentWebPush Experiment = "web-push" // Enables web push notifications through the browser. ExperimentOAuth2 Experiment = "oauth2" // Enables OAuth2 provider functionality. ExperimentMCPServerHTTP Experiment = "mcp-server-http" // Enables the MCP HTTP server functionality. - ExperimentWorkspaceSharing Experiment = "workspace-sharing" // Enables updating workspace ACLs for sharing with users and groups. ) func (e Experiment) DisplayName() string { @@ -4284,8 +4283,6 @@ func (e Experiment) DisplayName() string { return "OAuth2 Provider Functionality" case ExperimentMCPServerHTTP: return "MCP HTTP Server Functionality" - case ExperimentWorkspaceSharing: - return "Workspace Sharing" default: // Split on hyphen and convert to title case // e.g. "web-push" -> "Web Push", "mcp-server-http" -> "Mcp Server Http" @@ -4303,7 +4300,6 @@ var ExperimentsKnown = Experiments{ ExperimentWebPush, ExperimentOAuth2, ExperimentMCPServerHTTP, - ExperimentWorkspaceSharing, } // ExperimentsSafe should include all experiments that are safe for diff --git a/docs/manifest.json b/docs/manifest.json index 21f0b5bdc2..f60af02a2a 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -325,7 +325,7 @@ "description": "Sharing workspaces", "path": "./user-guides/shared-workspaces.md", "icon_path": "./images/icons/generic.svg", - "state": ["early access"] + "state": ["beta"] }, { "title": "Workspace Scheduling", diff --git a/docs/reference/api/schemas.md b/docs/reference/api/schemas.md index 65c2bc0781..8c194f406d 100644 --- a/docs/reference/api/schemas.md +++ b/docs/reference/api/schemas.md @@ -3981,9 +3981,9 @@ CreateWorkspaceRequest provides options for creating a new workspace. Only one o #### Enumerated Values -| Value(s) | -|-------------------------------------------------------------------------------------------------------------------------------------| -| `auto-fill-parameters`, `example`, `mcp-server-http`, `notifications`, `oauth2`, `web-push`, `workspace-sharing`, `workspace-usage` | +| Value(s) | +|----------------------------------------------------------------------------------------------------------------| +| `auto-fill-parameters`, `example`, `mcp-server-http`, `notifications`, `oauth2`, `web-push`, `workspace-usage` | ## codersdk.ExternalAPIKeyScopes diff --git a/docs/reference/cli/server.md b/docs/reference/cli/server.md index f7a26fceaa..85a314b16a 100644 --- a/docs/reference/cli/server.md +++ b/docs/reference/cli/server.md @@ -1167,7 +1167,7 @@ Remove the permission for the 'owner' role to have workspace execution on all wo | Environment | $CODER_DISABLE_WORKSPACE_SHARING | | YAML | disableWorkspaceSharing | -Disable workspace sharing (requires the "workspace-sharing" experiment to be enabled). Workspace ACL checking is disabled and only owners can have ssh, apps and terminal access to workspaces. Access based on the 'owner' role is also allowed unless disabled via --disable-owner-workspace-access. +Disable workspace sharing. Workspace ACL checking is disabled and only owners can have ssh, apps and terminal access to workspaces. Access based on the 'owner' role is also allowed unless disabled via --disable-owner-workspace-access. ### --session-duration diff --git a/enterprise/cli/sharing_test.go b/enterprise/cli/sharing_test.go index 9e99b85886..6e1e3c8dd4 100644 --- a/enterprise/cli/sharing_test.go +++ b/enterprise/cli/sharing_test.go @@ -31,11 +31,6 @@ func TestSharingShare(t *testing.T) { var ( client, db, orgOwner = coderdenttest.NewWithDatabase(t, &coderdenttest.Options{ - Options: &coderdtest.Options{ - DeploymentValues: coderdtest.DeploymentValues(t, func(dv *codersdk.DeploymentValues) { - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} - }), - }, LicenseOptions: &coderdenttest.LicenseOptions{ Features: license.Features{ codersdk.FeatureTemplateRBAC: 1, @@ -84,11 +79,6 @@ func TestSharingShare(t *testing.T) { var ( client, db, orgOwner = coderdenttest.NewWithDatabase(t, &coderdenttest.Options{ - Options: &coderdtest.Options{ - DeploymentValues: coderdtest.DeploymentValues(t, func(dv *codersdk.DeploymentValues) { - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} - }), - }, LicenseOptions: &coderdenttest.LicenseOptions{ Features: license.Features{ codersdk.FeatureTemplateRBAC: 1, @@ -140,11 +130,6 @@ func TestSharingShare(t *testing.T) { var ( client, db, orgOwner = coderdenttest.NewWithDatabase(t, &coderdenttest.Options{ - Options: &coderdtest.Options{ - DeploymentValues: coderdtest.DeploymentValues(t, func(dv *codersdk.DeploymentValues) { - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} - }), - }, LicenseOptions: &coderdenttest.LicenseOptions{ Features: license.Features{ codersdk.FeatureTemplateRBAC: 1, @@ -198,11 +183,6 @@ func TestSharingStatus(t *testing.T) { var ( client, db, orgOwner = coderdenttest.NewWithDatabase(t, &coderdenttest.Options{ - Options: &coderdtest.Options{ - DeploymentValues: coderdtest.DeploymentValues(t, func(dv *codersdk.DeploymentValues) { - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} - }), - }, LicenseOptions: &coderdenttest.LicenseOptions{ Features: license.Features{ codersdk.FeatureTemplateRBAC: 1, @@ -255,11 +235,6 @@ func TestSharingRemove(t *testing.T) { var ( client, db, orgOwner = coderdenttest.NewWithDatabase(t, &coderdenttest.Options{ - Options: &coderdtest.Options{ - DeploymentValues: coderdtest.DeploymentValues(t, func(dv *codersdk.DeploymentValues) { - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} - }), - }, LicenseOptions: &coderdenttest.LicenseOptions{ Features: license.Features{ codersdk.FeatureTemplateRBAC: 1, @@ -328,11 +303,6 @@ func TestSharingRemove(t *testing.T) { var ( client, db, orgOwner = coderdenttest.NewWithDatabase(t, &coderdenttest.Options{ - Options: &coderdtest.Options{ - DeploymentValues: coderdtest.DeploymentValues(t, func(dv *codersdk.DeploymentValues) { - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} - }), - }, LicenseOptions: &coderdenttest.LicenseOptions{ Features: license.Features{ codersdk.FeatureTemplateRBAC: 1, diff --git a/enterprise/cli/testdata/coder_server_--help.golden b/enterprise/cli/testdata/coder_server_--help.golden index b602cb93a1..a253c074a0 100644 --- a/enterprise/cli/testdata/coder_server_--help.golden +++ b/enterprise/cli/testdata/coder_server_--help.golden @@ -50,10 +50,9 @@ OPTIONS: security purposes if a --wildcard-access-url is configured. --disable-workspace-sharing bool, $CODER_DISABLE_WORKSPACE_SHARING - Disable workspace sharing (requires the "workspace-sharing" experiment - to be enabled). Workspace ACL checking is disabled and only owners can - have ssh, apps and terminal access to workspaces. Access based on the - 'owner' role is also allowed unless disabled via + Disable workspace sharing. Workspace ACL checking is disabled and only + owners can have ssh, apps and terminal access to workspaces. Access + based on the 'owner' role is also allowed unless disabled via --disable-owner-workspace-access. --swagger-enable bool, $CODER_SWAGGER_ENABLE diff --git a/enterprise/coderd/coderd.go b/enterprise/coderd/coderd.go index 00a80c9540..a897711597 100644 --- a/enterprise/coderd/coderd.go +++ b/enterprise/coderd/coderd.go @@ -364,9 +364,6 @@ func New(ctx context.Context, options *Options) (_ *API, err error) { r.Get("/idpsync/field-values", api.organizationIDPSyncClaimFieldValues) r.Route("/workspace-sharing", func(r chi.Router) { - r.Use( - httpmw.RequireExperiment(api.AGPL.Experiments, codersdk.ExperimentWorkspaceSharing), - ) r.Get("/", api.workspaceSharingSettings) r.Patch("/", api.patchWorkspaceSharingSettings) }) diff --git a/enterprise/coderd/workspaces_test.go b/enterprise/coderd/workspaces_test.go index aeb524265b..e40c0fa485 100644 --- a/enterprise/coderd/workspaces_test.go +++ b/enterprise/coderd/workspaces_test.go @@ -3651,7 +3651,6 @@ func TestWorkspacesFiltering(t *testing.T) { t.Parallel() dv := coderdtest.DeploymentValues(t) - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} ownerClient, db, owner := coderdenttest.NewWithDatabase(t, &coderdenttest.Options{ Options: &coderdtest.Options{ @@ -3703,7 +3702,6 @@ func TestWorkspacesFiltering(t *testing.T) { t.Parallel() dv := coderdtest.DeploymentValues(t) - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} var ( ownerClient, db, owner = coderdenttest.NewWithDatabase(t, &coderdenttest.Options{ @@ -3757,7 +3755,6 @@ func TestWorkspacesFiltering(t *testing.T) { t.Parallel() dv := coderdtest.DeploymentValues(t) - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} var ( ownerClient, db, owner = coderdenttest.NewWithDatabase(t, &coderdenttest.Options{ @@ -3806,7 +3803,6 @@ func TestWorkspacesFiltering(t *testing.T) { t.Parallel() dv := coderdtest.DeploymentValues(t) - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} var ( ownerClient, db, owner = coderdenttest.NewWithDatabase(t, &coderdenttest.Options{ @@ -3854,7 +3850,6 @@ func TestWorkspacesFiltering(t *testing.T) { t.Parallel() dv := coderdtest.DeploymentValues(t) - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} var ( ownerClient, db, owner = coderdenttest.NewWithDatabase(t, &coderdenttest.Options{ @@ -4356,7 +4351,7 @@ func TestUpdateWorkspaceACL(t *testing.T) { t.Parallel() dv := coderdtest.DeploymentValues(t) - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} + adminClient, adminUser := coderdenttest.New(t, &coderdenttest.Options{ Options: &coderdtest.Options{ IncludeProvisionerDaemon: true, @@ -4405,7 +4400,7 @@ func TestUpdateWorkspaceACL(t *testing.T) { t.Parallel() dv := coderdtest.DeploymentValues(t) - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} + adminClient := coderdtest.New(t, &coderdtest.Options{ IncludeProvisionerDaemon: true, DeploymentValues: dv, @@ -4449,7 +4444,6 @@ func TestDeleteWorkspaceACL(t *testing.T) { client, db, admin = coderdenttest.NewWithDatabase(t, &coderdenttest.Options{ Options: &coderdtest.Options{ DeploymentValues: coderdtest.DeploymentValues(t, func(dv *codersdk.DeploymentValues) { - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} }), }, LicenseOptions: &coderdenttest.LicenseOptions{ @@ -4493,7 +4487,6 @@ func TestDeleteWorkspaceACL(t *testing.T) { client, db, admin = coderdenttest.NewWithDatabase(t, &coderdenttest.Options{ Options: &coderdtest.Options{ DeploymentValues: coderdtest.DeploymentValues(t, func(dv *codersdk.DeploymentValues) { - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} }), }, LicenseOptions: &coderdenttest.LicenseOptions{ @@ -4543,7 +4536,6 @@ func TestWorkspacesSharedWith(t *testing.T) { t.Parallel() dv := coderdtest.DeploymentValues(t) - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} client, db, user := coderdenttest.NewWithDatabase(t, &coderdenttest.Options{ Options: &coderdtest.Options{ @@ -4631,7 +4623,6 @@ func TestWorkspacesSharedWith(t *testing.T) { t.Parallel() dv := coderdtest.DeploymentValues(t) - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} client, db, user := coderdenttest.NewWithDatabase(t, &coderdenttest.Options{ Options: &coderdtest.Options{ diff --git a/enterprise/coderd/workspacesharing_test.go b/enterprise/coderd/workspacesharing_test.go index 2b196b1b70..e55c095a2a 100644 --- a/enterprise/coderd/workspacesharing_test.go +++ b/enterprise/coderd/workspacesharing_test.go @@ -25,7 +25,6 @@ func TestWorkspaceSharingSettings(t *testing.T) { t.Parallel() dv := coderdtest.DeploymentValues(t) - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} client, first := coderdenttest.New(t, &coderdenttest.Options{ Options: &coderdtest.Options{ @@ -45,7 +44,6 @@ func TestWorkspaceSharingSettings(t *testing.T) { t.Parallel() dv := coderdtest.DeploymentValues(t) - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} client, first := coderdenttest.New(t, &coderdenttest.Options{ Options: &coderdtest.Options{ @@ -77,7 +75,6 @@ func TestWorkspaceSharingSettings(t *testing.T) { t.Parallel() dv := coderdtest.DeploymentValues(t) - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} client, first := coderdenttest.New(t, &coderdenttest.Options{ Options: &coderdtest.Options{ @@ -101,7 +98,6 @@ func TestWorkspaceSharingSettings(t *testing.T) { auditor := audit.NewMock() dv := coderdtest.DeploymentValues(t) - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} client, first := coderdenttest.New(t, &coderdenttest.Options{ AuditLogging: true, @@ -131,23 +127,6 @@ func TestWorkspaceSharingSettings(t *testing.T) { require.Equal(t, database.ResourceTypeOrganization, alog.ResourceType) require.Equal(t, first.OrganizationID, alog.ResourceID) }) - - t.Run("ExperimentDisabled", func(t *testing.T) { - t.Parallel() - - // Note: NOT setting the experiment flag. - client, first := coderdenttest.New(t, &coderdenttest.Options{}) - - ctx := testutil.Context(t, testutil.WaitMedium) - - memberClient, _ := coderdtest.CreateAnotherUser(t, client, first.OrganizationID) - _, err := memberClient.WorkspaceSharingSettings(ctx, first.OrganizationID.String()) - var apiErr *codersdk.Error - require.ErrorAs(t, err, &apiErr) - require.Equal(t, http.StatusForbidden, apiErr.StatusCode()) - require.Contains(t, apiErr.Message, "requires enabling") - require.Contains(t, apiErr.Message, "workspace-sharing") - }) } func TestWorkspaceSharingDisabled(t *testing.T) { @@ -157,7 +136,6 @@ func TestWorkspaceSharingDisabled(t *testing.T) { t.Parallel() dv := coderdtest.DeploymentValues(t) - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} client, db, owner := coderdenttest.NewWithDatabase(t, &coderdenttest.Options{ Options: &coderdtest.Options{ @@ -211,7 +189,6 @@ func TestWorkspaceSharingDisabled(t *testing.T) { t.Parallel() dv := coderdtest.DeploymentValues(t) - dv.Experiments = []string{string(codersdk.ExperimentWorkspaceSharing)} client, db, owner := coderdenttest.NewWithDatabase(t, &coderdenttest.Options{ Options: &coderdtest.Options{ diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index 9b968ce899..5d7c7bfb75 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -1939,7 +1939,6 @@ export type Experiment = | "notifications" | "oauth2" | "web-push" - | "workspace-sharing" | "workspace-usage"; export const Experiments: Experiment[] = [ @@ -1949,7 +1948,6 @@ export const Experiments: Experiment[] = [ "notifications", "oauth2", "web-push", - "workspace-sharing", "workspace-usage", ]; diff --git a/site/src/pages/OrganizationSettingsPage/OrganizationSettingsPageView.tsx b/site/src/pages/OrganizationSettingsPage/OrganizationSettingsPageView.tsx index aa0b538416..ba3d9137df 100644 --- a/site/src/pages/OrganizationSettingsPage/OrganizationSettingsPageView.tsx +++ b/site/src/pages/OrganizationSettingsPage/OrganizationSettingsPageView.tsx @@ -8,6 +8,7 @@ import { ErrorAlert } from "components/Alert/ErrorAlert"; import { Button } from "components/Button/Button"; import { Checkbox } from "components/Checkbox/Checkbox"; import { DeleteDialog } from "components/Dialogs/DeleteDialog/DeleteDialog"; +import { FeatureStageBadge } from "components/FeatureStageBadge/FeatureStageBadge"; import { FormFields, FormFooter, @@ -147,7 +148,12 @@ export const OrganizationSettingsPageView: FC< {onToggleWorkspaceSharing && ( + Workspace Sharing + + + } description="Control whether workspace owners can share their workspaces." >
diff --git a/site/src/pages/WorkspacePage/WorkspaceActions/ShareButton.tsx b/site/src/pages/WorkspacePage/WorkspaceActions/ShareButton.tsx index e0b9e375fb..de225be488 100644 --- a/site/src/pages/WorkspacePage/WorkspaceActions/ShareButton.tsx +++ b/site/src/pages/WorkspacePage/WorkspaceActions/ShareButton.tsx @@ -1,4 +1,5 @@ import type { Workspace } from "api/typesGenerated"; +import { FeatureStageBadge } from "components/FeatureStageBadge/FeatureStageBadge"; import { TopbarButton } from "components/FullPageLayout/Topbar"; import { Popover, @@ -32,6 +33,10 @@ export const ShareButton: FC = ({ +
+

Workspace Sharing

+ +
= ({ workspace, sharingDisabled, }) => { - const { experiments } = useDashboard(); - return ( = ({ Schedule - {experiments.includes("workspace-sharing") && !sharingDisabled && ( + {!sharingDisabled && ( Sharing + )}