diff --git a/cli/rename_test.go b/cli/rename_test.go
index 5a08d29c5a7c4..adbe946c0cb82 100644
--- a/cli/rename_test.go
+++ b/cli/rename_test.go
@@ -15,7 +15,7 @@ import (
func TestRename(t *testing.T) {
t.Parallel()
- client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
+ client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true, AllowWorkspaceRenames: true})
owner := coderdtest.CreateFirstUser(t, client)
member, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
version := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, nil)
diff --git a/cli/server.go b/cli/server.go
index 214c4d3a94c97..2caf9f891286d 100644
--- a/cli/server.go
+++ b/cli/server.go
@@ -583,6 +583,7 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd.
HostnamePrefix: vals.SSHConfig.DeploymentName.String(),
SSHConfigOptions: configSSHOptions,
},
+ AllowWorkspaceRenames: vals.AllowWorkspaceRenames.Value(),
}
if httpServers.TLSConfig != nil {
options.TLSCertificates = httpServers.TLSConfig.Certificates
diff --git a/cli/testdata/coder_list_--output_json.golden b/cli/testdata/coder_list_--output_json.golden
index fb6bea96e82ba..55b660694810d 100644
--- a/cli/testdata/coder_list_--output_json.golden
+++ b/cli/testdata/coder_list_--output_json.golden
@@ -59,6 +59,7 @@
"healthy": true,
"failing_agents": []
},
- "automatic_updates": "never"
+ "automatic_updates": "never",
+ "allow_renames": false
}
]
diff --git a/cli/testdata/coder_server_--help.golden b/cli/testdata/coder_server_--help.golden
index 80849f1904cca..5f8cd85a84e2f 100644
--- a/cli/testdata/coder_server_--help.golden
+++ b/cli/testdata/coder_server_--help.golden
@@ -14,6 +14,11 @@ SUBCOMMANDS:
PostgreSQL deployment.
OPTIONS:
+ --allow-workspace-renames bool, $CODER_ALLOW_WORKSPACE_RENAMES (default: false)
+ DEPRECATED: Allow users to rename their workspaces. Use only for
+ temporary compatibility reasons, this will be removed in a future
+ release.
+
--cache-dir string, $CODER_CACHE_DIRECTORY (default: [cache dir])
The directory to cache temporary files. If unspecified and
$CACHE_DIRECTORY is set, it will be used for compatibility with
diff --git a/cli/testdata/server-config.yaml.golden b/cli/testdata/server-config.yaml.golden
index ef071c8b292a6..5abf74e675e68 100644
--- a/cli/testdata/server-config.yaml.golden
+++ b/cli/testdata/server-config.yaml.golden
@@ -462,3 +462,7 @@ userQuietHoursSchedule:
# change their quiet hours schedule and the site default is always used.
# (default: true, type: bool)
allowCustomQuietHours: true
+# DEPRECATED: Allow users to rename their workspaces. Use only for temporary
+# compatibility reasons, this will be removed in a future release.
+# (default: false, type: bool)
+allowWorkspaceRenames: false
diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go
index 569ade9033a13..0bf86fc999dd3 100644
--- a/coderd/apidoc/docs.go
+++ b/coderd/apidoc/docs.go
@@ -8558,6 +8558,9 @@ const docTemplate = `{
"agent_stat_refresh_interval": {
"type": "integer"
},
+ "allow_workspace_renames": {
+ "type": "boolean"
+ },
"autobuild_poll_interval": {
"type": "integer"
},
@@ -11443,6 +11446,9 @@ const docTemplate = `{
"codersdk.Workspace": {
"type": "object",
"properties": {
+ "allow_renames": {
+ "type": "boolean"
+ },
"automatic_updates": {
"enum": [
"always",
diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json
index 30d83cc50c780..2187fd7a05cf8 100644
--- a/coderd/apidoc/swagger.json
+++ b/coderd/apidoc/swagger.json
@@ -7642,6 +7642,9 @@
"agent_stat_refresh_interval": {
"type": "integer"
},
+ "allow_workspace_renames": {
+ "type": "boolean"
+ },
"autobuild_poll_interval": {
"type": "integer"
},
@@ -10372,6 +10375,9 @@
"codersdk.Workspace": {
"type": "object",
"properties": {
+ "allow_renames": {
+ "type": "boolean"
+ },
"automatic_updates": {
"enum": ["always", "never"],
"allOf": [
diff --git a/coderd/coderd.go b/coderd/coderd.go
index 8dd8cf36936fb..0e7421aa2d257 100644
--- a/coderd/coderd.go
+++ b/coderd/coderd.go
@@ -179,7 +179,8 @@ type Options struct {
// This janky function is used in telemetry to parse fields out of the raw
// JWT. It needs to be passed through like this because license parsing is
// under the enterprise license, and can't be imported into AGPL.
- ParseLicenseClaims func(rawJWT string) (email string, trial bool, err error)
+ ParseLicenseClaims func(rawJWT string) (email string, trial bool, err error)
+ AllowWorkspaceRenames bool
}
// @title Coder API
diff --git a/coderd/coderdtest/coderdtest.go b/coderd/coderdtest/coderdtest.go
index 4d1f832ea9c1e..8de475c784ef3 100644
--- a/coderd/coderdtest/coderdtest.go
+++ b/coderd/coderdtest/coderdtest.go
@@ -144,6 +144,7 @@ type Options struct {
StatsBatcher *batchstats.Batcher
WorkspaceAppsStatsCollectorOptions workspaceapps.StatsCollectorOptions
+ AllowWorkspaceRenames bool
}
// New constructs a codersdk client connected to an in-memory API instance.
@@ -449,6 +450,7 @@ func NewOptions(t testing.TB, options *Options) (func(http.Handler), context.Can
HealthcheckRefresh: options.HealthcheckRefresh,
StatsBatcher: options.StatsBatcher,
WorkspaceAppsStatsCollectorOptions: options.WorkspaceAppsStatsCollectorOptions,
+ AllowWorkspaceRenames: options.AllowWorkspaceRenames,
}
}
diff --git a/coderd/workspaces.go b/coderd/workspaces.go
index 238780b1ec1b6..8d4cba7a40087 100644
--- a/coderd/workspaces.go
+++ b/coderd/workspaces.go
@@ -106,6 +106,7 @@ func (api *API) workspace(rw http.ResponseWriter, r *http.Request) {
data.builds[0],
data.templates[0],
ownerName,
+ api.Options.AllowWorkspaceRenames,
))
}
@@ -277,6 +278,7 @@ func (api *API) workspaceByOwnerAndName(rw http.ResponseWriter, r *http.Request)
data.builds[0],
data.templates[0],
ownerName,
+ api.Options.AllowWorkspaceRenames,
))
}
@@ -585,6 +587,7 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
apiBuild,
template,
member.Username,
+ api.Options.AllowWorkspaceRenames,
))
}
@@ -628,6 +631,12 @@ func (api *API) patchWorkspace(rw http.ResponseWriter, r *http.Request) {
// patched in the future, it's enough if one changes.
name := workspace.Name
if req.Name != "" || req.Name != workspace.Name {
+ if !api.Options.AllowWorkspaceRenames {
+ httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
+ Message: "Workspace renames are not allowed.",
+ })
+ return
+ }
name = req.Name
}
@@ -917,6 +926,7 @@ func (api *API) putWorkspaceDormant(rw http.ResponseWriter, r *http.Request) {
data.builds[0],
data.templates[0],
ownerName,
+ api.Options.AllowWorkspaceRenames,
))
}
@@ -1242,6 +1252,7 @@ func (api *API) watchWorkspace(rw http.ResponseWriter, r *http.Request) {
data.builds[0],
data.templates[0],
ownerName,
+ api.Options.AllowWorkspaceRenames,
),
})
}
@@ -1293,9 +1304,10 @@ func (api *API) watchWorkspace(rw http.ResponseWriter, r *http.Request) {
}
type workspaceData struct {
- templates []database.Template
- builds []codersdk.WorkspaceBuild
- users []database.User
+ templates []database.Template
+ builds []codersdk.WorkspaceBuild
+ users []database.User
+ allowRenames bool
}
// workspacesData only returns the data the caller can access. If the caller
@@ -1347,9 +1359,10 @@ func (api *API) workspaceData(ctx context.Context, workspaces []database.Workspa
}
return workspaceData{
- templates: templates,
- builds: apiBuilds,
- users: data.users,
+ templates: templates,
+ builds: apiBuilds,
+ users: data.users,
+ allowRenames: api.Options.AllowWorkspaceRenames,
}, nil
}
@@ -1392,6 +1405,7 @@ func convertWorkspaces(workspaces []database.Workspace, data workspaceData) ([]c
build,
template,
owner.Username,
+ data.allowRenames,
))
}
return apiWorkspaces, nil
@@ -1402,6 +1416,7 @@ func convertWorkspace(
workspaceBuild codersdk.WorkspaceBuild,
template database.Template,
ownerName string,
+ allowRenames bool,
) codersdk.Workspace {
var autostartSchedule *string
if workspace.AutostartSchedule.Valid {
@@ -1456,6 +1471,7 @@ func convertWorkspace(
FailingAgents: failingAgents,
},
AutomaticUpdates: codersdk.AutomaticUpdates(workspace.AutomaticUpdates),
+ AllowRenames: allowRenames,
}
}
diff --git a/coderd/workspaces_test.go b/coderd/workspaces_test.go
index 9c6129b5373f8..69ab38d8cabb9 100644
--- a/coderd/workspaces_test.go
+++ b/coderd/workspaces_test.go
@@ -100,7 +100,10 @@ func TestWorkspace(t *testing.T) {
t.Run("Rename", func(t *testing.T) {
t.Parallel()
- client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
+ client := coderdtest.New(t, &coderdtest.Options{
+ IncludeProvisionerDaemon: true,
+ AllowWorkspaceRenames: true,
+ })
user := coderdtest.CreateFirstUser(t, client)
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
@@ -134,6 +137,29 @@ func TestWorkspace(t *testing.T) {
require.Error(t, err, "workspace rename should have failed")
})
+ t.Run("RenameDisabled", func(t *testing.T) {
+ t.Parallel()
+ client := coderdtest.New(t, &coderdtest.Options{
+ IncludeProvisionerDaemon: true,
+ AllowWorkspaceRenames: false,
+ })
+ user := coderdtest.CreateFirstUser(t, client)
+ version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
+ coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
+ template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
+ ws1 := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
+ coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, ws1.LatestBuild.ID)
+
+ ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitMedium)
+ defer cancel()
+
+ want := "new-name"
+ err := client.UpdateWorkspace(ctx, ws1.ID, codersdk.UpdateWorkspaceRequest{
+ Name: want,
+ })
+ require.ErrorContains(t, err, "Workspace renames are not allowed")
+ })
+
t.Run("TemplateProperties", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
@@ -2152,7 +2178,10 @@ func TestUpdateWorkspaceAutomaticUpdates_NotFound(t *testing.T) {
func TestWorkspaceWatcher(t *testing.T) {
t.Parallel()
- client, closeFunc := coderdtest.NewWithProvisionerCloser(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
+ client, closeFunc := coderdtest.NewWithProvisionerCloser(t, &coderdtest.Options{
+ IncludeProvisionerDaemon: true,
+ AllowWorkspaceRenames: true,
+ })
defer closeFunc.Close()
user := coderdtest.CreateFirstUser(t, client)
authToken := uuid.NewString()
diff --git a/codersdk/deployment.go b/codersdk/deployment.go
index 1e8a4c93ccf98..54b67f127907d 100644
--- a/codersdk/deployment.go
+++ b/codersdk/deployment.go
@@ -181,6 +181,7 @@ type DeploymentValues struct {
EnableTerraformDebugMode clibase.Bool `json:"enable_terraform_debug_mode,omitempty" typescript:",notnull"`
UserQuietHoursSchedule UserQuietHoursScheduleConfig `json:"user_quiet_hours_schedule,omitempty" typescript:",notnull"`
WebTerminalRenderer clibase.String `json:"web_terminal_renderer,omitempty" typescript:",notnull"`
+ AllowWorkspaceRenames clibase.Bool `json:"allow_workspace_renames,omitempty" typescript:",notnull"`
Healthcheck HealthcheckConfig `json:"healthcheck,omitempty" typescript:",notnull"`
Config clibase.YAMLConfigPath `json:"config,omitempty" typescript:",notnull"`
@@ -1842,6 +1843,15 @@ Write out the current server config as YAML to stdout.`,
Group: &deploymentGroupClient,
YAML: "webTerminalRenderer",
},
+ {
+ Name: "Allow Workspace Renames",
+ Description: "DEPRECATED: Allow users to rename their workspaces. Use only for temporary compatibility reasons, this will be removed in a future release.",
+ Flag: "allow-workspace-renames",
+ Env: "CODER_ALLOW_WORKSPACE_RENAMES",
+ Default: "false",
+ Value: &c.AllowWorkspaceRenames,
+ YAML: "allowWorkspaceRenames",
+ },
// Healthcheck Options
{
Name: "Health Check Refresh",
diff --git a/codersdk/workspaces.go b/codersdk/workspaces.go
index 307bbdb0d3b93..59dede325ee0b 100644
--- a/codersdk/workspaces.go
+++ b/codersdk/workspaces.go
@@ -57,6 +57,7 @@ type Workspace struct {
// what is causing an unhealthy status.
Health WorkspaceHealth `json:"health"`
AutomaticUpdates AutomaticUpdates `json:"automatic_updates" enums:"always,never"`
+ AllowRenames bool `json:"allow_renames"`
}
func (w Workspace) FullName() string {
diff --git a/docs/api/general.md b/docs/api/general.md
index 043913bbf2eb8..65d9d4badd499 100644
--- a/docs/api/general.md
+++ b/docs/api/general.md
@@ -153,6 +153,7 @@ curl -X GET http://coder-server:8080/api/v2/deployment/config \
"user": {}
},
"agent_stat_refresh_interval": 0,
+ "allow_workspace_renames": true,
"autobuild_poll_interval": 0,
"browser_only": true,
"cache_directory": "string",
diff --git a/docs/api/schemas.md b/docs/api/schemas.md
index 21eb6dba26ada..991f57bccbb0c 100644
--- a/docs/api/schemas.md
+++ b/docs/api/schemas.md
@@ -2083,6 +2083,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
"user": {}
},
"agent_stat_refresh_interval": 0,
+ "allow_workspace_renames": true,
"autobuild_poll_interval": 0,
"browser_only": true,
"cache_directory": "string",
@@ -2460,6 +2461,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
"user": {}
},
"agent_stat_refresh_interval": 0,
+ "allow_workspace_renames": true,
"autobuild_poll_interval": 0,
"browser_only": true,
"cache_directory": "string",
@@ -2732,6 +2734,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
| `address` | [clibase.HostPort](#clibasehostport) | false | | Address Use HTTPAddress or TLS.Address instead. |
| `agent_fallback_troubleshooting_url` | [clibase.URL](#clibaseurl) | false | | |
| `agent_stat_refresh_interval` | integer | false | | |
+| `allow_workspace_renames` | boolean | false | | |
| `autobuild_poll_interval` | integer | false | | |
| `browser_only` | boolean | false | | |
| `cache_directory` | string | false | | |
@@ -5764,6 +5767,7 @@ If the schedule is empty, the user will be updated to use the default schedule.|
```json
{
+ "allow_renames": true,
"automatic_updates": "always",
"autostart_schedule": "string",
"created_at": "2019-08-24T14:15:22Z",
@@ -5943,6 +5947,7 @@ If the schedule is empty, the user will be updated to use the default schedule.|
| Name | Type | Required | Restrictions | Description |
| ------------------------------------------- | ------------------------------------------------------ | -------- | ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `allow_renames` | boolean | false | | |
| `automatic_updates` | [codersdk.AutomaticUpdates](#codersdkautomaticupdates) | false | | |
| `autostart_schedule` | string | false | | |
| `created_at` | string | false | | |
@@ -7025,6 +7030,7 @@ If the schedule is empty, the user will be updated to use the default schedule.|
"count": 0,
"workspaces": [
{
+ "allow_renames": true,
"automatic_updates": "always",
"autostart_schedule": "string",
"created_at": "2019-08-24T14:15:22Z",
diff --git a/docs/api/workspaces.md b/docs/api/workspaces.md
index 7d0f7973d4425..f825ba5f7c679 100644
--- a/docs/api/workspaces.md
+++ b/docs/api/workspaces.md
@@ -47,6 +47,7 @@ curl -X POST http://coder-server:8080/api/v2/organizations/{organization}/member
```json
{
+ "allow_renames": true,
"automatic_updates": "always",
"autostart_schedule": "string",
"created_at": "2019-08-24T14:15:22Z",
@@ -257,6 +258,7 @@ curl -X GET http://coder-server:8080/api/v2/users/{user}/workspace/{workspacenam
```json
{
+ "allow_renames": true,
"automatic_updates": "always",
"autostart_schedule": "string",
"created_at": "2019-08-24T14:15:22Z",
@@ -470,6 +472,7 @@ curl -X GET http://coder-server:8080/api/v2/workspaces \
"count": 0,
"workspaces": [
{
+ "allow_renames": true,
"automatic_updates": "always",
"autostart_schedule": "string",
"created_at": "2019-08-24T14:15:22Z",
@@ -677,6 +680,7 @@ curl -X GET http://coder-server:8080/api/v2/workspaces/{workspace} \
```json
{
+ "allow_renames": true,
"automatic_updates": "always",
"autostart_schedule": "string",
"created_at": "2019-08-24T14:15:22Z",
@@ -1003,6 +1007,7 @@ curl -X PUT http://coder-server:8080/api/v2/workspaces/{workspace}/dormant \
```json
{
+ "allow_renames": true,
"automatic_updates": "always",
"autostart_schedule": "string",
"created_at": "2019-08-24T14:15:22Z",
diff --git a/docs/cli/server.md b/docs/cli/server.md
index 34fe77b3a59a3..a0c4aad6e97ba 100644
--- a/docs/cli/server.md
+++ b/docs/cli/server.md
@@ -42,6 +42,17 @@ The URL that users will use to access the Coder deployment.
Allow users to set their own quiet hours schedule for workspaces to stop in (depending on template autostop requirement settings). If false, users can't change their quiet hours schedule and the site default is always used.
+### --allow-workspace-renames
+
+| | |
+| ----------- | ------------------------------------------- |
+| Type | bool
|
+| Environment | $CODER_ALLOW_WORKSPACE_RENAMES
|
+| YAML | allowWorkspaceRenames
|
+| Default | false
|
+
+DEPRECATED: Allow users to rename their workspaces. Use only for temporary compatibility reasons, this will be removed in a future release.
+
### --block-direct-connections
| | |
diff --git a/enterprise/cli/testdata/coder_server_--help.golden b/enterprise/cli/testdata/coder_server_--help.golden
index ad404185f0482..0df1bec5bb35d 100644
--- a/enterprise/cli/testdata/coder_server_--help.golden
+++ b/enterprise/cli/testdata/coder_server_--help.golden
@@ -15,6 +15,11 @@ SUBCOMMANDS:
PostgreSQL deployment.
OPTIONS:
+ --allow-workspace-renames bool, $CODER_ALLOW_WORKSPACE_RENAMES (default: false)
+ DEPRECATED: Allow users to rename their workspaces. Use only for
+ temporary compatibility reasons, this will be removed in a future
+ release.
+
--cache-dir string, $CODER_CACHE_DIRECTORY (default: [cache dir])
The directory to cache temporary files. If unspecified and
$CACHE_DIRECTORY is set, it will be used for compatibility with
diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts
index 934f2681fd4a9..53b3eb90672c3 100644
--- a/site/src/api/typesGenerated.ts
+++ b/site/src/api/typesGenerated.ts
@@ -424,6 +424,7 @@ export interface DeploymentValues {
readonly enable_terraform_debug_mode?: boolean;
readonly user_quiet_hours_schedule?: UserQuietHoursScheduleConfig;
readonly web_terminal_renderer?: string;
+ readonly allow_workspace_renames?: boolean;
readonly healthcheck?: HealthcheckConfig;
readonly config?: string;
readonly write_config?: boolean;
@@ -1429,6 +1430,7 @@ export interface Workspace {
readonly dormant_at?: string;
readonly health: WorkspaceHealth;
readonly automatic_updates: AutomaticUpdates;
+ readonly allow_renames: boolean;
}
// From codersdk/workspaceagents.go
diff --git a/site/src/pages/WorkspaceSettingsPage/WorkspaceSettingsForm.tsx b/site/src/pages/WorkspaceSettingsPage/WorkspaceSettingsForm.tsx
index b94eabee07fb4..824d47460ab55 100644
--- a/site/src/pages/WorkspaceSettingsPage/WorkspaceSettingsForm.tsx
+++ b/site/src/pages/WorkspaceSettingsPage/WorkspaceSettingsForm.tsx
@@ -18,9 +18,9 @@ import {
AutomaticUpdateses,
Workspace,
} from "api/typesGenerated";
-import { Alert } from "components/Alert/Alert";
import MenuItem from "@mui/material/MenuItem";
import upperFirst from "lodash/upperFirst";
+import { type Theme } from "@emotion/react";
export type WorkspaceSettingsFormValues = {
name: string;
@@ -34,6 +34,10 @@ export const WorkspaceSettingsForm: FC<{
onCancel: () => void;
onSubmit: (values: WorkspaceSettingsFormValues) => Promise;
}> = ({ onCancel, onSubmit, workspace, error, templatePoliciesEnabled }) => {
+ const formEnabled =
+ (templatePoliciesEnabled && !workspace.template_require_active_version) ||
+ workspace.allow_renames;
+
const form = useFormik({
onSubmit,
initialValues: {
@@ -59,18 +63,19 @@ export const WorkspaceSettingsForm: FC<{
- {form.values.name !== form.initialValues.name && (
-
- Depending on the template, renaming your workspace may be
- destructive
-
- )}
{templatePoliciesEnabled && (
@@ -106,7 +111,17 @@ export const WorkspaceSettingsForm: FC<{
)}
-
+ {formEnabled && (
+
+ )}
);
};
+
+const styles = {
+ nameWarning: (theme: Theme) => ({
+ "& .MuiFormHelperText-root": {
+ color: theme.palette.warning.light,
+ },
+ }),
+};
diff --git a/site/src/pages/WorkspaceSettingsPage/WorkspaceSettingsPage.test.tsx b/site/src/pages/WorkspaceSettingsPage/WorkspaceSettingsPage.test.tsx
index 0aaa510857e8e..d6d8c9a11c1f8 100644
--- a/site/src/pages/WorkspaceSettingsPage/WorkspaceSettingsPage.test.tsx
+++ b/site/src/pages/WorkspaceSettingsPage/WorkspaceSettingsPage.test.tsx
@@ -12,7 +12,7 @@ test("Submit the workspace settings page successfully", async () => {
// Mock the API calls that loads data
jest
.spyOn(api, "getWorkspaceByOwnerAndName")
- .mockResolvedValueOnce(MockWorkspace);
+ .mockResolvedValueOnce({ ...MockWorkspace });
// Mock the API calls that submit data
const patchWorkspaceSpy = jest
.spyOn(api, "patchWorkspace")
@@ -39,3 +39,21 @@ test("Submit the workspace settings page successfully", async () => {
});
});
});
+
+test("Name field is disabled if renames are disabled", async () => {
+ // Mock the API calls that loads data
+ jest
+ .spyOn(api, "getWorkspaceByOwnerAndName")
+ .mockResolvedValueOnce({ ...MockWorkspace, allow_renames: false });
+ renderWithWorkspaceSettingsLayout(, {
+ route: "/@test-user/test-workspace/settings",
+ path: "/:username/:workspace/settings",
+ // Need this because after submit the user is redirected
+ extraRoutes: [{ path: "/:username/:workspace", element: }],
+ });
+ await waitForLoaderToBeRemoved();
+ // Fill the form and submit
+ const form = screen.getByTestId("form");
+ const name = within(form).getByLabelText("Name");
+ expect(name).toBeDisabled();
+});
diff --git a/site/src/pages/WorkspaceSettingsPage/WorkspaceSettingsPageView.stories.tsx b/site/src/pages/WorkspaceSettingsPage/WorkspaceSettingsPageView.stories.tsx
index 1a316b4bb9488..41c2633473be0 100644
--- a/site/src/pages/WorkspaceSettingsPage/WorkspaceSettingsPageView.stories.tsx
+++ b/site/src/pages/WorkspaceSettingsPage/WorkspaceSettingsPageView.stories.tsx
@@ -21,3 +21,9 @@ export const AutoUpdates: Story = {
templatePoliciesEnabled: true,
},
};
+
+export const RenamesDisabled: Story = {
+ args: {
+ workspace: { ...MockWorkspace, allow_renames: false },
+ },
+};
diff --git a/site/src/testHelpers/entities.ts b/site/src/testHelpers/entities.ts
index 14b475a6d1377..743dcd57b7f12 100644
--- a/site/src/testHelpers/entities.ts
+++ b/site/src/testHelpers/entities.ts
@@ -1006,6 +1006,7 @@ export const MockWorkspace: TypesGen.Workspace = {
failing_agents: [],
},
automatic_updates: "never",
+ allow_renames: true,
};
export const MockStoppedWorkspace: TypesGen.Workspace = {