mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: allow TemplateAdmin to delete prebuilds via auth layer (#18333)
## Description This PR adds support for deleting prebuilt workspaces via the authorization layer. It introduces special-case handling to ensure that `prebuilt_workspace` permissions are evaluated when attempting to delete a prebuilt workspace, falling back to the standard `workspace` resource as needed. Prebuilt workspaces are a subset of workspaces, identified by having `owner_id` set to `PREBUILD_SYSTEM_USER`. This means: * A user with `prebuilt_workspace.delete` permission is allowed to **delete only prebuilt workspaces**. * A user with `workspace.delete` permission can **delete both normal and prebuilt workspaces**. ⚠️ This implementation is scoped to **deletion operations only**. No other operations are currently supported for the `prebuilt_workspace` resource. To delete a workspace, users must have the following permissions: * `workspace.read`: to read the current workspace state * `update`: to modify workspace metadata and related resources during deletion (e.g., updating the `deleted` field in the database) * `delete`: to perform the actual deletion of the workspace ## Changes * Introduced `authorizeWorkspace()` helper to handle prebuilt workspace authorization logic. * Ensured both `prebuilt_workspace` and `workspace` permissions are checked. * Added comments to clarify the current behavior and limitations. * Moved `SystemUserID` constant from the `prebuilds` package to the `database` package `PrebuildsSystemUserID` to resolve an import cycle (commit https://github.com/coder/coder/pull/18333/commits/f24e4ab4b6f0a56726fd04be2d7302c9fdb52d53). * Update middleware `ExtractOrganizationMember` to include system user members.
This commit is contained in:
@@ -229,6 +229,24 @@ func (w Workspace) RBACObject() rbac.Object {
|
||||
return w.WorkspaceTable().RBACObject()
|
||||
}
|
||||
|
||||
// IsPrebuild returns true if the workspace is a prebuild workspace.
|
||||
// A workspace is considered a prebuild if its owner is the prebuild system user.
|
||||
func (w Workspace) IsPrebuild() bool {
|
||||
return w.OwnerID == PrebuildsSystemUserID
|
||||
}
|
||||
|
||||
// AsPrebuild returns the RBAC object corresponding to the workspace type.
|
||||
// If the workspace is a prebuild, it returns a prebuilt_workspace RBAC object.
|
||||
// Otherwise, it returns a normal workspace RBAC object.
|
||||
func (w Workspace) AsPrebuild() rbac.Object {
|
||||
if w.IsPrebuild() {
|
||||
return rbac.ResourcePrebuiltWorkspace.WithID(w.ID).
|
||||
InOrg(w.OrganizationID).
|
||||
WithOwner(w.OwnerID.String())
|
||||
}
|
||||
return w.RBACObject()
|
||||
}
|
||||
|
||||
func (w WorkspaceTable) RBACObject() rbac.Object {
|
||||
if w.DormantAt.Valid {
|
||||
return w.DormantRBAC()
|
||||
@@ -246,6 +264,24 @@ func (w WorkspaceTable) DormantRBAC() rbac.Object {
|
||||
WithOwner(w.OwnerID.String())
|
||||
}
|
||||
|
||||
// IsPrebuild returns true if the workspace is a prebuild workspace.
|
||||
// A workspace is considered a prebuild if its owner is the prebuild system user.
|
||||
func (w WorkspaceTable) IsPrebuild() bool {
|
||||
return w.OwnerID == PrebuildsSystemUserID
|
||||
}
|
||||
|
||||
// AsPrebuild returns the RBAC object corresponding to the workspace type.
|
||||
// If the workspace is a prebuild, it returns a prebuilt_workspace RBAC object.
|
||||
// Otherwise, it returns a normal workspace RBAC object.
|
||||
func (w WorkspaceTable) AsPrebuild() rbac.Object {
|
||||
if w.IsPrebuild() {
|
||||
return rbac.ResourcePrebuiltWorkspace.WithID(w.ID).
|
||||
InOrg(w.OrganizationID).
|
||||
WithOwner(w.OwnerID.String())
|
||||
}
|
||||
return w.RBACObject()
|
||||
}
|
||||
|
||||
func (m OrganizationMember) RBACObject() rbac.Object {
|
||||
return rbac.ResourceOrganizationMember.
|
||||
WithID(m.UserID).
|
||||
|
||||
Reference in New Issue
Block a user