@Summary Update workspace ACL @ID update-workspace-acl @Security CoderSessionToken @Accept json @Produce json @Tags Workspaces @Param workspace path string true "Workspace ID" format(uuid) @Param request body codersdk.UpdateWorkspaceACL true "Update workspace ACL request" @Success 204 @Router /api/v
(rw http.ResponseWriter, r *http.Request)
| 2470 | // @Success 204 |
| 2471 | // @Router /api/v2/workspaces/{workspace}/acl [patch] |
| 2472 | func (api *API) patchWorkspaceACL(rw http.ResponseWriter, r *http.Request) { |
| 2473 | var ( |
| 2474 | ctx = r.Context() |
| 2475 | workspace = httpmw.WorkspaceParam(r) |
| 2476 | auditor = api.Auditor.Load() |
| 2477 | aReq, commitAudit = audit.InitRequest[database.WorkspaceTable](rw, &audit.RequestParams{ |
| 2478 | Audit: *auditor, |
| 2479 | Log: api.Logger, |
| 2480 | Request: r, |
| 2481 | Action: database.AuditActionWrite, |
| 2482 | OrganizationID: workspace.OrganizationID, |
| 2483 | }) |
| 2484 | ) |
| 2485 | defer commitAudit() |
| 2486 | aReq.Old = workspace.WorkspaceTable() |
| 2487 | |
| 2488 | if !api.allowWorkspaceSharing(ctx, rw, workspace.OrganizationID) { |
| 2489 | return |
| 2490 | } |
| 2491 | |
| 2492 | var req codersdk.UpdateWorkspaceACL |
| 2493 | if !httpapi.Read(ctx, rw, r, &req) { |
| 2494 | return |
| 2495 | } |
| 2496 | |
| 2497 | apiKey := httpmw.APIKey(r) |
| 2498 | if _, ok := req.UserRoles[apiKey.UserID.String()]; ok { |
| 2499 | // Block changing your own sharing role unless you can share any |
| 2500 | // workspace in the organization. This keeps a user whose only access is |
| 2501 | // this share from destructively demoting themselves, while letting org |
| 2502 | // and deployment admins manage their own access. |
| 2503 | if !api.Authorize(r, policy.ActionShare, rbac.ResourceWorkspace.InOrg(workspace.OrganizationID)) { |
| 2504 | httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ |
| 2505 | Message: "You cannot change your own workspace sharing role.", |
| 2506 | }) |
| 2507 | return |
| 2508 | } |
| 2509 | } |
| 2510 | |
| 2511 | validErrs := acl.Validate(ctx, api.Database, WorkspaceACLUpdateValidator(req)) |
| 2512 | if len(validErrs) > 0 { |
| 2513 | httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ |
| 2514 | Message: "Invalid request to update workspace ACL", |
| 2515 | Validations: validErrs, |
| 2516 | }) |
| 2517 | return |
| 2518 | } |
| 2519 | |
| 2520 | err := api.Database.InTx(func(tx database.Store) error { |
| 2521 | var err error |
| 2522 | workspace, err = tx.GetWorkspaceByID(ctx, workspace.ID) |
| 2523 | if err != nil { |
| 2524 | return xerrors.Errorf("get template by ID: %w", err) |
| 2525 | } |
| 2526 | |
| 2527 | for id, role := range req.UserRoles { |
| 2528 | if role == codersdk.WorkspaceRoleDeleted { |
| 2529 | delete(workspace.UserACL, id) |
nothing calls this directly
no test coverage detected