mirror of
https://github.com/coder/coder.git
synced 2026-06-02 20:48:20 +00:00
fix: show a notice when workspace sharing is disabled globally in organization settings (#22580)
This commit is contained in:
@@ -70,7 +70,7 @@ func (r *RootCmd) organizationSettings(orgContext *OrganizationContext) *serpent
|
||||
Aliases: []string{"workspacesharing"},
|
||||
Short: "Workspace sharing settings for the organization.",
|
||||
Patch: func(ctx context.Context, cli *codersdk.Client, org uuid.UUID, input json.RawMessage) (any, error) {
|
||||
var req codersdk.WorkspaceSharingSettings
|
||||
var req codersdk.UpdateWorkspaceSharingSettingsRequest
|
||||
err := json.Unmarshal(input, &req)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("unmarshalling workspace sharing settings: %w", err)
|
||||
|
||||
Generated
+13
-1
@@ -4808,7 +4808,7 @@ const docTemplate = `{
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.WorkspaceSharingSettings"
|
||||
"$ref": "#/definitions/codersdk.UpdateWorkspaceSharingSettingsRequest"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20283,6 +20283,14 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.UpdateWorkspaceSharingSettingsRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"sharing_disabled": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.UpdateWorkspaceTTLRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -22121,6 +22129,10 @@ const docTemplate = `{
|
||||
"properties": {
|
||||
"sharing_disabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sharing_globally_disabled": {
|
||||
"description": "SharingGloballyDisabled is true if sharing has been disabled for this\norganization because of a deployment-wide setting.",
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Generated
+13
-1
@@ -4253,7 +4253,7 @@
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.WorkspaceSharingSettings"
|
||||
"$ref": "#/definitions/codersdk.UpdateWorkspaceSharingSettingsRequest"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18601,6 +18601,14 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.UpdateWorkspaceSharingSettingsRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"sharing_disabled": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.UpdateWorkspaceTTLRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -20337,6 +20345,10 @@
|
||||
"properties": {
|
||||
"sharing_disabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sharing_globally_disabled": {
|
||||
"description": "SharingGloballyDisabled is true if sharing has been disabled for this\norganization because of a deployment-wide setting.",
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -7,8 +7,18 @@ import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// WorkspaceSharingSettings represents workspace sharing settings for an organization.
|
||||
// WorkspaceSharingSettings represents workspace sharing settings affecting an
|
||||
// organization.
|
||||
type WorkspaceSharingSettings struct {
|
||||
// SharingGloballyDisabled is true if sharing has been disabled for this
|
||||
// organization because of a deployment-wide setting.
|
||||
SharingGloballyDisabled bool `json:"sharing_globally_disabled"`
|
||||
SharingDisabled bool `json:"sharing_disabled"`
|
||||
}
|
||||
|
||||
// UpdateWorkspaceSharingSettingsRequest represents workspace sharing settings
|
||||
// that can be updated for an organization.
|
||||
type UpdateWorkspaceSharingSettingsRequest struct {
|
||||
SharingDisabled bool `json:"sharing_disabled"`
|
||||
}
|
||||
|
||||
@@ -28,7 +38,7 @@ func (c *Client) WorkspaceSharingSettings(ctx context.Context, orgID string) (Wo
|
||||
}
|
||||
|
||||
// PatchWorkspaceSharingSettings modifies the workspace sharing settings for an organization.
|
||||
func (c *Client) PatchWorkspaceSharingSettings(ctx context.Context, orgID string, req WorkspaceSharingSettings) (WorkspaceSharingSettings, error) {
|
||||
func (c *Client) PatchWorkspaceSharingSettings(ctx context.Context, orgID string, req UpdateWorkspaceSharingSettingsRequest) (WorkspaceSharingSettings, error) {
|
||||
res, err := c.Request(ctx, http.MethodPatch, fmt.Sprintf("/api/v2/organizations/%s/settings/workspace-sharing", orgID), req)
|
||||
if err != nil {
|
||||
return WorkspaceSharingSettings{}, err
|
||||
|
||||
Generated
+6
-4
@@ -2851,7 +2851,8 @@ curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/setting
|
||||
|
||||
```json
|
||||
{
|
||||
"sharing_disabled": true
|
||||
"sharing_disabled": true,
|
||||
"sharing_globally_disabled": true
|
||||
}
|
||||
```
|
||||
|
||||
@@ -2881,7 +2882,8 @@ curl -X PATCH http://coder-server:8080/api/v2/organizations/{organization}/setti
|
||||
|
||||
```json
|
||||
{
|
||||
"sharing_disabled": true
|
||||
"sharing_disabled": true,
|
||||
"sharing_globally_disabled": true
|
||||
}
|
||||
```
|
||||
|
||||
@@ -2905,8 +2907,8 @@ curl -X PATCH http://coder-server:8080/api/v2/organizations/{organization}/setti
|
||||
### Responses
|
||||
|
||||
| Status | Meaning | Description | Schema |
|
||||
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------------|
|
||||
| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.WorkspaceSharingSettings](schemas.md#codersdkworkspacesharingsettings) |
|
||||
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------------------------------------------------|
|
||||
| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.UpdateWorkspaceSharingSettingsRequest](schemas.md#codersdkupdateworkspacesharingsettingsrequest) |
|
||||
|
||||
To perform this operation, you must be authenticated. [Learn more](authentication.md).
|
||||
|
||||
|
||||
Generated
+18
-2
@@ -9809,6 +9809,20 @@ If the schedule is empty, the user will be updated to use the default schedule.|
|
||||
|--------|--------|----------|--------------|-------------|
|
||||
| `name` | string | false | | |
|
||||
|
||||
## codersdk.UpdateWorkspaceSharingSettingsRequest
|
||||
|
||||
```json
|
||||
{
|
||||
"sharing_disabled": true
|
||||
}
|
||||
```
|
||||
|
||||
### Properties
|
||||
|
||||
| Name | Type | Required | Restrictions | Description |
|
||||
|--------------------|---------|----------|--------------|-------------|
|
||||
| `sharing_disabled` | boolean | false | | |
|
||||
|
||||
## codersdk.UpdateWorkspaceTTLRequest
|
||||
|
||||
```json
|
||||
@@ -12278,15 +12292,17 @@ If the schedule is empty, the user will be updated to use the default schedule.|
|
||||
|
||||
```json
|
||||
{
|
||||
"sharing_disabled": true
|
||||
"sharing_disabled": true,
|
||||
"sharing_globally_disabled": true
|
||||
}
|
||||
```
|
||||
|
||||
### Properties
|
||||
|
||||
| Name | Type | Required | Restrictions | Description |
|
||||
|--------------------|---------|----------|--------------|-------------|
|
||||
|-----------------------------|---------|----------|--------------|----------------------------------------------------------------------------------------------------------------------------|
|
||||
| `sharing_disabled` | boolean | false | | |
|
||||
| `sharing_globally_disabled` | boolean | false | | Sharing globally disabled is true if sharing has been disabled for this organization because of a deployment-wide setting. |
|
||||
|
||||
## codersdk.WorkspaceStatus
|
||||
|
||||
|
||||
@@ -34,8 +34,10 @@ func (api *API) workspaceSharingSettings(rw http.ResponseWriter, r *http.Request
|
||||
return
|
||||
}
|
||||
|
||||
globallyDisabled := bool(api.DeploymentValues.DisableWorkspaceSharing)
|
||||
httpapi.Write(ctx, rw, http.StatusOK, codersdk.WorkspaceSharingSettings{
|
||||
SharingDisabled: org.WorkspaceSharingDisabled,
|
||||
SharingGloballyDisabled: globallyDisabled,
|
||||
SharingDisabled: org.WorkspaceSharingDisabled || globallyDisabled,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -47,7 +49,7 @@ func (api *API) workspaceSharingSettings(rw http.ResponseWriter, r *http.Request
|
||||
// @Tags Enterprise
|
||||
// @Param organization path string true "Organization ID" format(uuid)
|
||||
// @Param request body codersdk.WorkspaceSharingSettings true "Workspace sharing settings"
|
||||
// @Success 200 {object} codersdk.WorkspaceSharingSettings
|
||||
// @Success 200 {object} codersdk.UpdateWorkspaceSharingSettingsRequest
|
||||
// @Router /organizations/{organization}/settings/workspace-sharing [patch]
|
||||
func (api *API) patchWorkspaceSharingSettings(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
|
||||
@@ -54,7 +54,7 @@ func TestWorkspaceSharingSettings(t *testing.T) {
|
||||
ctx := testutil.Context(t, testutil.WaitMedium)
|
||||
|
||||
orgAdminClient, _ := coderdtest.CreateAnotherUser(t, client, first.OrganizationID, rbac.ScopedRoleOrgAdmin(first.OrganizationID))
|
||||
settings, err := orgAdminClient.PatchWorkspaceSharingSettings(ctx, first.OrganizationID.String(), codersdk.WorkspaceSharingSettings{
|
||||
settings, err := orgAdminClient.PatchWorkspaceSharingSettings(ctx, first.OrganizationID.String(), codersdk.UpdateWorkspaceSharingSettingsRequest{
|
||||
SharingDisabled: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@@ -64,7 +64,7 @@ func TestWorkspaceSharingSettings(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.True(t, settings.SharingDisabled)
|
||||
|
||||
settings, err = orgAdminClient.PatchWorkspaceSharingSettings(ctx, first.OrganizationID.String(), codersdk.WorkspaceSharingSettings{
|
||||
settings, err = orgAdminClient.PatchWorkspaceSharingSettings(ctx, first.OrganizationID.String(), codersdk.UpdateWorkspaceSharingSettingsRequest{
|
||||
SharingDisabled: false,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@@ -85,7 +85,7 @@ func TestWorkspaceSharingSettings(t *testing.T) {
|
||||
ctx := testutil.Context(t, testutil.WaitMedium)
|
||||
|
||||
memberClient, _ := coderdtest.CreateAnotherUser(t, client, first.OrganizationID)
|
||||
_, err := memberClient.PatchWorkspaceSharingSettings(ctx, first.OrganizationID.String(), codersdk.WorkspaceSharingSettings{
|
||||
_, err := memberClient.PatchWorkspaceSharingSettings(ctx, first.OrganizationID.String(), codersdk.UpdateWorkspaceSharingSettingsRequest{
|
||||
SharingDisabled: true,
|
||||
})
|
||||
var apiErr *codersdk.Error
|
||||
@@ -116,7 +116,7 @@ func TestWorkspaceSharingSettings(t *testing.T) {
|
||||
|
||||
orgAdminClient, _ := coderdtest.CreateAnotherUser(t, client, first.OrganizationID, rbac.ScopedRoleOrgAdmin(first.OrganizationID))
|
||||
auditor.ResetLogs()
|
||||
_, err := orgAdminClient.PatchWorkspaceSharingSettings(ctx, first.OrganizationID.String(), codersdk.WorkspaceSharingSettings{
|
||||
_, err := orgAdminClient.PatchWorkspaceSharingSettings(ctx, first.OrganizationID.String(), codersdk.UpdateWorkspaceSharingSettingsRequest{
|
||||
SharingDisabled: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@@ -152,7 +152,7 @@ func TestWorkspaceSharingDisabled(t *testing.T) {
|
||||
ctx := testutil.Context(t, testutil.WaitMedium)
|
||||
|
||||
orgAdminClient, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.ScopedRoleOrgAdmin(owner.OrganizationID))
|
||||
_, err := orgAdminClient.PatchWorkspaceSharingSettings(ctx, owner.OrganizationID.String(), codersdk.WorkspaceSharingSettings{
|
||||
_, err := orgAdminClient.PatchWorkspaceSharingSettings(ctx, owner.OrganizationID.String(), codersdk.UpdateWorkspaceSharingSettingsRequest{
|
||||
SharingDisabled: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@@ -235,12 +235,12 @@ func TestWorkspaceSharingDisabled(t *testing.T) {
|
||||
require.Equal(t, codersdk.WorkspaceRoleUse, acl.Groups[0].Role)
|
||||
|
||||
orgAdminClient, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.ScopedRoleOrgAdmin(owner.OrganizationID))
|
||||
_, err = orgAdminClient.PatchWorkspaceSharingSettings(ctx, owner.OrganizationID.String(), codersdk.WorkspaceSharingSettings{
|
||||
_, err = orgAdminClient.PatchWorkspaceSharingSettings(ctx, owner.OrganizationID.String(), codersdk.UpdateWorkspaceSharingSettingsRequest{
|
||||
SharingDisabled: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = orgAdminClient.PatchWorkspaceSharingSettings(ctx, owner.OrganizationID.String(), codersdk.WorkspaceSharingSettings{
|
||||
_, err = orgAdminClient.PatchWorkspaceSharingSettings(ctx, owner.OrganizationID.String(), codersdk.UpdateWorkspaceSharingSettingsRequest{
|
||||
SharingDisabled: false,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
+1
-1
@@ -828,7 +828,7 @@ class ApiMethods {
|
||||
*/
|
||||
patchWorkspaceSharingSettings = async (
|
||||
organization: string,
|
||||
data: TypesGen.WorkspaceSharingSettings,
|
||||
data: TypesGen.UpdateWorkspaceSharingSettingsRequest,
|
||||
): Promise<TypesGen.WorkspaceSharingSettings> => {
|
||||
const response = await this.axios.patch<TypesGen.WorkspaceSharingSettings>(
|
||||
`/api/v2/organizations/${organization}/settings/workspace-sharing`,
|
||||
|
||||
Generated
+16
-1
@@ -6523,6 +6523,15 @@ export interface UpdateWorkspaceRequest {
|
||||
readonly name?: string;
|
||||
}
|
||||
|
||||
// From codersdk/workspacesharing.go
|
||||
/**
|
||||
* UpdateWorkspaceSharingSettingsRequest represents workspace sharing settings
|
||||
* that can be updated for an organization.
|
||||
*/
|
||||
export interface UpdateWorkspaceSharingSettingsRequest {
|
||||
readonly sharing_disabled: boolean;
|
||||
}
|
||||
|
||||
// From codersdk/workspaces.go
|
||||
/**
|
||||
* UpdateWorkspaceTTLRequest is a request to update a workspace's TTL.
|
||||
@@ -7556,9 +7565,15 @@ export const WorkspaceRoles: WorkspaceRole[] = ["admin", "", "use"];
|
||||
|
||||
// From codersdk/workspacesharing.go
|
||||
/**
|
||||
* WorkspaceSharingSettings represents workspace sharing settings for an organization.
|
||||
* WorkspaceSharingSettings represents workspace sharing settings affecting an
|
||||
* organization.
|
||||
*/
|
||||
export interface WorkspaceSharingSettings {
|
||||
/**
|
||||
* SharingGloballyDisabled is true if sharing has been disabled for this
|
||||
* organization because of a deployment-wide setting.
|
||||
*/
|
||||
readonly sharing_globally_disabled: boolean;
|
||||
readonly sharing_disabled: boolean;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ const OrganizationSettingsPage: FC = () => {
|
||||
|
||||
const sharingSettingsQuery = useQuery({
|
||||
...workspaceSharingSettings(organization?.id ?? ""),
|
||||
enabled: !!organization,
|
||||
enabled: Boolean(organization),
|
||||
});
|
||||
|
||||
const patchSharingSettingsMutation = useMutation(
|
||||
@@ -112,6 +112,9 @@ const OrganizationSettingsPage: FC = () => {
|
||||
);
|
||||
}
|
||||
}}
|
||||
workspaceSharingGloballyDisabled={
|
||||
sharingSettingsQuery.data?.sharing_globally_disabled
|
||||
}
|
||||
workspaceSharingEnabled={
|
||||
!(sharingSettingsQuery.data?.sharing_disabled ?? false)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import type {
|
||||
Organization,
|
||||
UpdateOrganizationRequest,
|
||||
} from "api/typesGenerated";
|
||||
import { Alert, AlertTitle } from "components/Alert/Alert";
|
||||
import { ErrorAlert } from "components/Alert/ErrorAlert";
|
||||
import { Button } from "components/Button/Button";
|
||||
import { Checkbox } from "components/Checkbox/Checkbox";
|
||||
@@ -50,9 +51,10 @@ interface OrganizationSettingsPageViewProps {
|
||||
error: unknown;
|
||||
onSubmit: (values: UpdateOrganizationRequest) => Promise<void>;
|
||||
onDeleteOrganization: () => void;
|
||||
workspaceSharingEnabled?: boolean;
|
||||
onToggleWorkspaceSharing?: (enabled: boolean) => void;
|
||||
isTogglingWorkspaceSharing?: boolean;
|
||||
workspaceSharingGloballyDisabled?: boolean;
|
||||
workspaceSharingEnabled: boolean;
|
||||
onToggleWorkspaceSharing: (enabled: boolean) => void;
|
||||
isTogglingWorkspaceSharing: boolean;
|
||||
}
|
||||
|
||||
export const OrganizationSettingsPageView: FC<
|
||||
@@ -62,7 +64,8 @@ export const OrganizationSettingsPageView: FC<
|
||||
error,
|
||||
onSubmit,
|
||||
onDeleteOrganization,
|
||||
workspaceSharingEnabled = true,
|
||||
workspaceSharingGloballyDisabled,
|
||||
workspaceSharingEnabled,
|
||||
onToggleWorkspaceSharing,
|
||||
isTogglingWorkspaceSharing,
|
||||
}) => {
|
||||
@@ -156,11 +159,25 @@ export const OrganizationSettingsPageView: FC<
|
||||
}
|
||||
description="Control whether workspace owners can share their workspaces."
|
||||
>
|
||||
<div className="flex flex-col gap-2">
|
||||
{workspaceSharingGloballyDisabled && (
|
||||
<Alert severity="warning" className="mb-4">
|
||||
<AlertTitle>Disabled by deployment settings</AlertTitle>
|
||||
Workspace sharing has been disallowed by an administrator.
|
||||
Sharing must be allowed by an administrator before sharing can
|
||||
be used in this organization.
|
||||
</Alert>
|
||||
)}
|
||||
<div className="flex items-start gap-3">
|
||||
<Checkbox
|
||||
id="workspace-sharing"
|
||||
checked={workspaceSharingEnabled}
|
||||
disabled={isTogglingWorkspaceSharing}
|
||||
checked={
|
||||
!workspaceSharingGloballyDisabled && workspaceSharingEnabled
|
||||
}
|
||||
disabled={
|
||||
workspaceSharingGloballyDisabled ||
|
||||
isTogglingWorkspaceSharing
|
||||
}
|
||||
onCheckedChange={(checked) => {
|
||||
if (checked) {
|
||||
onToggleWorkspaceSharing(true);
|
||||
@@ -177,8 +194,9 @@ export const OrganizationSettingsPageView: FC<
|
||||
Allow workspace sharing
|
||||
</label>
|
||||
<div className="text-sm text-content-secondary">
|
||||
When enabled, workspace owners can share their workspaces with
|
||||
other users in this organization.
|
||||
When enabled, workspace owners can share their workspaces
|
||||
with other users in this organization.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user