mirror of
https://github.com/coder/coder.git
synced 2026-06-02 20:48:20 +00:00
refactor(coderd/rbac): extract organization-workspace-access role
Introduce the organization-workspace-access role and split the member and service-account perms into a floor plus an elevation set. The elevation lives in the new OrgWorkspaceAccessMemberPerms helper and is mirrored onto the new role; both OrgMemberPermissions and OrgServiceAccountPermissions compose floor + elevation today, so this PR is behavior-preserving. A future PR will gate the elevation on the minimum-implicit-member experiment so a user without organization-workspace-access has only the floor. Org admins, owners, user admins, and the system role can assign the new role. The helper carries the same "Intentionally omitted at Member scope" rationale as the prior enumeration so that owner-less resources (e.g. ResourceTemplate, ResourceWorkspaceProxy) are not re-added by mistake.
This commit is contained in:
+122
-128
@@ -3,6 +3,7 @@ package rbac
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"slices"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -35,6 +36,7 @@ const (
|
|||||||
orgUserAdmin string = "organization-user-admin"
|
orgUserAdmin string = "organization-user-admin"
|
||||||
orgTemplateAdmin string = "organization-template-admin"
|
orgTemplateAdmin string = "organization-template-admin"
|
||||||
orgWorkspaceCreationBan string = "organization-workspace-creation-ban"
|
orgWorkspaceCreationBan string = "organization-workspace-creation-ban"
|
||||||
|
orgWorkspaceAccess string = "organization-workspace-access"
|
||||||
|
|
||||||
prebuildsOrchestrator string = "prebuilds-orchestrator"
|
prebuildsOrchestrator string = "prebuilds-orchestrator"
|
||||||
)
|
)
|
||||||
@@ -173,6 +175,10 @@ func RoleOrgWorkspaceCreationBan() string {
|
|||||||
return orgWorkspaceCreationBan
|
return orgWorkspaceCreationBan
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RoleOrgWorkspaceAccess() string {
|
||||||
|
return orgWorkspaceAccess
|
||||||
|
}
|
||||||
|
|
||||||
// ScopedRoleOrgAdmin is the org role with the organization ID
|
// ScopedRoleOrgAdmin is the org role with the organization ID
|
||||||
func ScopedRoleOrgAdmin(organizationID uuid.UUID) RoleIdentifier {
|
func ScopedRoleOrgAdmin(organizationID uuid.UUID) RoleIdentifier {
|
||||||
return RoleIdentifier{Name: RoleOrgAdmin(), OrganizationID: organizationID}
|
return RoleIdentifier{Name: RoleOrgAdmin(), OrganizationID: organizationID}
|
||||||
@@ -203,6 +209,74 @@ func ScopedRoleAgentsAccess(organizationID uuid.UUID) RoleIdentifier {
|
|||||||
return RoleIdentifier{Name: RoleAgentsAccess(), OrganizationID: organizationID}
|
return RoleIdentifier{Name: RoleAgentsAccess(), OrganizationID: organizationID}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ScopedRoleOrgWorkspaceAccess(organizationID uuid.UUID) RoleIdentifier {
|
||||||
|
return RoleIdentifier{Name: RoleOrgWorkspaceAccess(), OrganizationID: organizationID}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OrgWorkspaceAccessMemberPerms returns the member-scoped permission set
|
||||||
|
// for the organization-workspace-access role.
|
||||||
|
func OrgWorkspaceAccessMemberPerms() []Permission {
|
||||||
|
return Permissions(map[string][]policy.Action{
|
||||||
|
// Members own their workspaces.
|
||||||
|
ResourceWorkspace.Type: ResourceWorkspace.AvailableActions(),
|
||||||
|
|
||||||
|
// Dormant workspaces share the workspace action set minus the
|
||||||
|
// build, ssh, and exec actions.
|
||||||
|
ResourceWorkspaceDormant.Type: {
|
||||||
|
policy.ActionRead,
|
||||||
|
policy.ActionDelete,
|
||||||
|
policy.ActionCreate,
|
||||||
|
policy.ActionUpdate,
|
||||||
|
policy.ActionWorkspaceStop,
|
||||||
|
policy.ActionCreateAgent,
|
||||||
|
policy.ActionDeleteAgent,
|
||||||
|
policy.ActionUpdateAgent,
|
||||||
|
},
|
||||||
|
|
||||||
|
// Upload and read template files used during workspace build
|
||||||
|
// (File.RBACObject sets WithOwner(CreatedBy)).
|
||||||
|
ResourceFile.Type: {policy.ActionCreate, policy.ActionRead},
|
||||||
|
|
||||||
|
// Create and read user-scoped provisioner daemons. The Upsert
|
||||||
|
// path in dbauthz sets WithOwner(tag_owner) when scope=user, so
|
||||||
|
// members can run their own daemons. Read is granted for
|
||||||
|
// symmetry with workspace ownership; update and delete remain
|
||||||
|
// dead at Member scope.
|
||||||
|
ResourceProvisionerDaemon.Type: {policy.ActionCreate, policy.ActionRead},
|
||||||
|
|
||||||
|
// Tasks ride along with workspaces and are owner-scoped.
|
||||||
|
ResourceTask.Type: ResourceTask.AvailableActions(),
|
||||||
|
|
||||||
|
// Read-self group-membership record. GroupMember.RBACObject
|
||||||
|
// sets WithOwner to the user's own ID.
|
||||||
|
ResourceGroupMember.Type: {policy.ActionRead},
|
||||||
|
|
||||||
|
// Intentionally omitted at Member scope (resources without an
|
||||||
|
// Owner field on their RBACObject; Member-level grants never
|
||||||
|
// fire for them). Listed here because these can be common
|
||||||
|
// misconceptions:
|
||||||
|
//
|
||||||
|
// - ResourceTemplate: templates are only owned by orgs, not
|
||||||
|
// users. Users granted access via ACL and (generally) the
|
||||||
|
// "Everyone" group.
|
||||||
|
// - ResourceGroup: groups have no owner. "Groups I'm a
|
||||||
|
// member of can read themselves" is handled by the ACL
|
||||||
|
// applied implicitly in RBACObject().
|
||||||
|
// - ResourceWorkspaceProxy, ResourceProvisionerJobs,
|
||||||
|
// ResourceWorkspaceAgentResourceMonitor,
|
||||||
|
// ResourceWorkspaceAgentDevcontainers,
|
||||||
|
// ResourceTailnetCoordinator, ResourceReplicas: these
|
||||||
|
// resources have no DB model that sets Owner; all
|
||||||
|
// production call sites use the bare resource or
|
||||||
|
// .InOrg(...) only. Access for these flows through Org
|
||||||
|
// perms on the appropriate role, or through system /
|
||||||
|
// agent / template-admin roles defined elsewhere.
|
||||||
|
// - ResourceProvisionerDaemon update/delete: only create and
|
||||||
|
// read fire at Member scope via the user-scoped Upsert
|
||||||
|
// path; other actions go through the bare InOrg path.
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func allPermsExcept(excepts ...Objecter) []Permission {
|
func allPermsExcept(excepts ...Objecter) []Permission {
|
||||||
resources := AllResources()
|
resources := AllResources()
|
||||||
var perms []Permission
|
var perms []Permission
|
||||||
@@ -609,6 +683,23 @@ func ReloadBuiltinRoles(opts *RoleOptions) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// orgWorkspaceAccess grants the workspace-operations
|
||||||
|
// capabilities org members need to use their workspaces.
|
||||||
|
// See OrgWorkspaceAccessMemberPerms for the perm set.
|
||||||
|
orgWorkspaceAccess: func(organizationID uuid.UUID) Role {
|
||||||
|
return Role{
|
||||||
|
Identifier: RoleIdentifier{Name: orgWorkspaceAccess, OrganizationID: organizationID},
|
||||||
|
DisplayName: "Organization Workspace Access",
|
||||||
|
Site: []Permission{},
|
||||||
|
User: []Permission{},
|
||||||
|
ByOrgID: map[string]OrgPermissions{
|
||||||
|
organizationID.String(): {
|
||||||
|
Org: []Permission{},
|
||||||
|
Member: OrgWorkspaceAccessMemberPerms(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
// ActionDelete is intentionally excluded because hard-deletion goes through
|
// ActionDelete is intentionally excluded because hard-deletion goes through
|
||||||
// ResourceSystem in dbpurge.
|
// ResourceSystem in dbpurge.
|
||||||
agentsAccess: func(organizationID uuid.UUID) Role {
|
agentsAccess: func(organizationID uuid.UUID) Role {
|
||||||
@@ -651,6 +742,7 @@ var assignRoles = map[string]map[string]bool{
|
|||||||
orgUserAdmin: true,
|
orgUserAdmin: true,
|
||||||
orgTemplateAdmin: true,
|
orgTemplateAdmin: true,
|
||||||
orgWorkspaceCreationBan: true,
|
orgWorkspaceCreationBan: true,
|
||||||
|
orgWorkspaceAccess: true,
|
||||||
templateAdmin: true,
|
templateAdmin: true,
|
||||||
userAdmin: true,
|
userAdmin: true,
|
||||||
customSiteRole: true,
|
customSiteRole: true,
|
||||||
@@ -667,6 +759,7 @@ var assignRoles = map[string]map[string]bool{
|
|||||||
orgUserAdmin: true,
|
orgUserAdmin: true,
|
||||||
orgTemplateAdmin: true,
|
orgTemplateAdmin: true,
|
||||||
orgWorkspaceCreationBan: true,
|
orgWorkspaceCreationBan: true,
|
||||||
|
orgWorkspaceAccess: true,
|
||||||
templateAdmin: true,
|
templateAdmin: true,
|
||||||
userAdmin: true,
|
userAdmin: true,
|
||||||
customSiteRole: true,
|
customSiteRole: true,
|
||||||
@@ -676,6 +769,7 @@ var assignRoles = map[string]map[string]bool{
|
|||||||
userAdmin: {
|
userAdmin: {
|
||||||
member: true,
|
member: true,
|
||||||
orgMember: true,
|
orgMember: true,
|
||||||
|
orgWorkspaceAccess: true,
|
||||||
agentsAccess: true,
|
agentsAccess: true,
|
||||||
},
|
},
|
||||||
orgAdmin: {
|
orgAdmin: {
|
||||||
@@ -685,11 +779,13 @@ var assignRoles = map[string]map[string]bool{
|
|||||||
orgUserAdmin: true,
|
orgUserAdmin: true,
|
||||||
orgTemplateAdmin: true,
|
orgTemplateAdmin: true,
|
||||||
orgWorkspaceCreationBan: true,
|
orgWorkspaceCreationBan: true,
|
||||||
|
orgWorkspaceAccess: true,
|
||||||
customOrganizationRole: true,
|
customOrganizationRole: true,
|
||||||
agentsAccess: true,
|
agentsAccess: true,
|
||||||
},
|
},
|
||||||
orgUserAdmin: {
|
orgUserAdmin: {
|
||||||
orgMember: true,
|
orgMember: true,
|
||||||
|
orgWorkspaceAccess: true,
|
||||||
agentsAccess: true,
|
agentsAccess: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -1055,59 +1151,16 @@ func OrgMemberPermissions(org OrgSettings) OrgRolePermissions {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enumerate the per-member resources explicitly so new resources do
|
// Floor: perms every org member always has, regardless of whether
|
||||||
// not auto-grant to org members. Adding a resource to the codebase
|
// organization-workspace-access is attached. Chat access requires
|
||||||
// requires an explicit decision to expose it here.
|
// the agents-access role and is intentionally not granted here.
|
||||||
//
|
floor := Permissions(map[string][]policy.Action{
|
||||||
// Member-level grants only fire when input.object.owner ==
|
|
||||||
// input.subject.id (see the org_member rule in
|
|
||||||
// coderd/rbac/policy.rego). Only resources whose RBACObject() calls
|
|
||||||
// WithOwner(...) at production call sites belong here; see the
|
|
||||||
// "Intentionally omitted" block at the bottom.
|
|
||||||
memberPerms := Permissions(map[string][]policy.Action{
|
|
||||||
// Workspace lifecycle on resources owned by this member.
|
|
||||||
ResourceWorkspace.Type: ResourceWorkspace.AvailableActions(),
|
|
||||||
|
|
||||||
// Dormant workspaces share the workspace action set minus the
|
|
||||||
// build, ssh, and exec actions.
|
|
||||||
ResourceWorkspaceDormant.Type: {
|
|
||||||
policy.ActionRead,
|
|
||||||
policy.ActionDelete,
|
|
||||||
policy.ActionCreate,
|
|
||||||
policy.ActionUpdate,
|
|
||||||
policy.ActionWorkspaceStop,
|
|
||||||
policy.ActionCreateAgent,
|
|
||||||
policy.ActionDeleteAgent,
|
|
||||||
policy.ActionUpdateAgent,
|
|
||||||
},
|
|
||||||
|
|
||||||
// Upload and read template files the member created during
|
|
||||||
// workspace build (File.RBACObject sets WithOwner(CreatedBy)).
|
|
||||||
ResourceFile.Type: {policy.ActionCreate, policy.ActionRead},
|
|
||||||
|
|
||||||
// Create and read user-scoped provisioner daemons. The Upsert
|
|
||||||
// path in dbauthz sets WithOwner(tag_owner) when scope=user, so
|
|
||||||
// members can run their own daemons. Read is granted for
|
|
||||||
// symmetry with workspace ownership: members can inspect
|
|
||||||
// daemons they spawned even though no production call site
|
|
||||||
// currently uses the member-scope read path (read on the bare
|
|
||||||
// InOrg object continues to require Org-level perms).
|
|
||||||
ResourceProvisionerDaemon.Type: {policy.ActionCreate, policy.ActionRead},
|
|
||||||
|
|
||||||
// Tasks ride along with workspaces and are owner-scoped.
|
|
||||||
ResourceTask.Type: ResourceTask.AvailableActions(),
|
|
||||||
|
|
||||||
// Read-self group-membership record. GroupMember.RBACObject
|
|
||||||
// sets WithOwner to the user's own ID.
|
|
||||||
ResourceGroupMember.Type: {policy.ActionRead},
|
|
||||||
|
|
||||||
// Read-self org-member record.
|
// Read-self org-member record.
|
||||||
ResourceOrganizationMember.Type: {policy.ActionRead},
|
ResourceOrganizationMember.Type: {policy.ActionRead},
|
||||||
|
|
||||||
// Members can create and update AI Bridge interceptions they
|
// Members can create and update AI Bridge interceptions they
|
||||||
// initiate (dbauthz layer sets WithOwner(InitiatorID)) but
|
// initiate (dbauthz layer sets WithOwner(InitiatorID)) but
|
||||||
// cannot read them back. Chat access requires the
|
// cannot read them back.
|
||||||
// agents-access role and is intentionally not granted here.
|
|
||||||
ResourceAibridgeInterception.Type: {policy.ActionCreate, policy.ActionUpdate},
|
ResourceAibridgeInterception.Type: {policy.ActionCreate, policy.ActionUpdate},
|
||||||
|
|
||||||
// Own session tokens and workspace agent auth keys.
|
// Own session tokens and workspace agent auth keys.
|
||||||
@@ -1118,32 +1171,17 @@ func OrgMemberPermissions(org OrgSettings) OrgRolePermissions {
|
|||||||
ResourceNotificationMessage.Type: {policy.ActionRead, policy.ActionUpdate},
|
ResourceNotificationMessage.Type: {policy.ActionRead, policy.ActionUpdate},
|
||||||
ResourceNotificationPreference.Type: ResourceNotificationPreference.AvailableActions(),
|
ResourceNotificationPreference.Type: ResourceNotificationPreference.AvailableActions(),
|
||||||
ResourceInboxNotification.Type: ResourceInboxNotification.AvailableActions(),
|
ResourceInboxNotification.Type: ResourceInboxNotification.AvailableActions(),
|
||||||
|
|
||||||
// Intentionally omitted at Member scope (resources without an
|
|
||||||
// Owner field on their RBACObject; Member-level grants never
|
|
||||||
// fire for them). Listed here so a future maintainer who sees
|
|
||||||
// these dropped relative to the legacy allPermsExcept(...)
|
|
||||||
// wildcard does not "restore" them:
|
|
||||||
//
|
|
||||||
// - ResourceTemplate: templates have no owner. Org-member
|
|
||||||
// template.use is authorized via the ACL path
|
|
||||||
// (acl_group_list[org_owner] "Everyone" group, populated
|
|
||||||
// on each template's GroupACL).
|
|
||||||
// - ResourceGroup: groups have no owner. "Groups I'm a
|
|
||||||
// member of can read themselves" is granted via the
|
|
||||||
// per-group GroupACL.
|
|
||||||
// - ResourceWorkspaceProxy, ResourceProvisionerJobs,
|
|
||||||
// ResourceWorkspaceAgentResourceMonitor,
|
|
||||||
// ResourceWorkspaceAgentDevcontainers,
|
|
||||||
// ResourceTailnetCoordinator, ResourceReplicas: these
|
|
||||||
// resources have no DB model that sets Owner; all
|
|
||||||
// production call sites use the bare resource or
|
|
||||||
// .InOrg(...) only. Access for these flows through Org
|
|
||||||
// perms on the appropriate role (e.g. ProvisionerDaemon
|
|
||||||
// above), or through system / agent / template-admin
|
|
||||||
// roles defined elsewhere.
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Workspace-ops elevation. Today bundled into organization-member;
|
||||||
|
// the minimum-implicit-member experiment will move the binding
|
||||||
|
// exclusively onto organization-workspace-access so a user without
|
||||||
|
// that role has only the floor. See OrgWorkspaceAccessMemberPerms
|
||||||
|
// for the perm set and the "Intentionally omitted" rationale.
|
||||||
|
elevation := OrgWorkspaceAccessMemberPerms()
|
||||||
|
|
||||||
|
memberPerms := slices.Concat(elevation, floor)
|
||||||
|
|
||||||
if org.ShareableWorkspaceOwners != ShareableWorkspaceOwnersEveryone {
|
if org.ShareableWorkspaceOwners != ShareableWorkspaceOwnersEveryone {
|
||||||
memberPerms = append(memberPerms, Permission{
|
memberPerms = append(memberPerms, Permission{
|
||||||
Negate: true,
|
Negate: true,
|
||||||
@@ -1189,61 +1227,17 @@ func OrgServiceAccountPermissions(org OrgSettings) OrgRolePermissions {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// service account-scoped permissions (resources owned by the
|
// service account-scoped permissions. Composed from a floor plus the
|
||||||
// service account). Enumerated explicitly so new resources do not
|
// same workspace-ops elevation as OrgMemberPermissions; the service
|
||||||
// auto-grant to service accounts.
|
// account role mirrors the org-member partition.
|
||||||
//
|
floor := Permissions(map[string][]policy.Action{
|
||||||
// Member-level grants only fire when input.object.owner ==
|
|
||||||
// input.subject.id (see the org_member rule in
|
|
||||||
// coderd/rbac/policy.rego). Only resources whose RBACObject() calls
|
|
||||||
// WithOwner(...) at production call sites belong here; see the
|
|
||||||
// "Intentionally omitted" block at the bottom.
|
|
||||||
memberPerms := Permissions(map[string][]policy.Action{
|
|
||||||
// Workspace lifecycle on resources owned by this service account.
|
|
||||||
ResourceWorkspace.Type: ResourceWorkspace.AvailableActions(),
|
|
||||||
|
|
||||||
// Dormant workspaces share the workspace action set minus the
|
|
||||||
// build, ssh, and exec actions.
|
|
||||||
ResourceWorkspaceDormant.Type: {
|
|
||||||
policy.ActionRead,
|
|
||||||
policy.ActionDelete,
|
|
||||||
policy.ActionCreate,
|
|
||||||
policy.ActionUpdate,
|
|
||||||
policy.ActionWorkspaceStop,
|
|
||||||
policy.ActionCreateAgent,
|
|
||||||
policy.ActionDeleteAgent,
|
|
||||||
policy.ActionUpdateAgent,
|
|
||||||
},
|
|
||||||
|
|
||||||
// Upload and read template files the service account created
|
|
||||||
// during workspace build (File.RBACObject sets
|
|
||||||
// WithOwner(CreatedBy)).
|
|
||||||
ResourceFile.Type: {policy.ActionCreate, policy.ActionRead},
|
|
||||||
|
|
||||||
// Create and read user-scoped provisioner daemons. The Upsert
|
|
||||||
// path in dbauthz sets WithOwner(tag_owner) when scope=user, so
|
|
||||||
// service accounts can run their own daemons. Read is granted
|
|
||||||
// for symmetry with workspace ownership: service accounts can
|
|
||||||
// inspect daemons they spawned even though no production call
|
|
||||||
// site currently uses the member-scope read path (read on the
|
|
||||||
// bare InOrg object continues to require Org-level perms).
|
|
||||||
ResourceProvisionerDaemon.Type: {policy.ActionCreate, policy.ActionRead},
|
|
||||||
|
|
||||||
// Tasks ride along with workspaces and are owner-scoped.
|
|
||||||
ResourceTask.Type: ResourceTask.AvailableActions(),
|
|
||||||
|
|
||||||
// Read-self group-membership record. GroupMember.RBACObject
|
|
||||||
// sets WithOwner to the user's own ID.
|
|
||||||
ResourceGroupMember.Type: {policy.ActionRead},
|
|
||||||
|
|
||||||
// Read-self org-member record.
|
// Read-self org-member record.
|
||||||
ResourceOrganizationMember.Type: {policy.ActionRead},
|
ResourceOrganizationMember.Type: {policy.ActionRead},
|
||||||
|
|
||||||
// Service accounts can create and update AI Bridge
|
// Service accounts can create and update AI Bridge interceptions
|
||||||
// interceptions they initiate (dbauthz layer sets
|
// they initiate (dbauthz layer sets WithOwner(InitiatorID)) but
|
||||||
// WithOwner(InitiatorID)) but cannot read them back. Chat
|
// cannot read them back. Chat access requires the agents-access
|
||||||
// access requires the agents-access role and is intentionally
|
// role and is intentionally not granted here.
|
||||||
// not granted here.
|
|
||||||
ResourceAibridgeInterception.Type: {policy.ActionCreate, policy.ActionUpdate},
|
ResourceAibridgeInterception.Type: {policy.ActionCreate, policy.ActionUpdate},
|
||||||
|
|
||||||
// Own session tokens and workspace agent auth keys.
|
// Own session tokens and workspace agent auth keys.
|
||||||
@@ -1254,11 +1248,11 @@ func OrgServiceAccountPermissions(org OrgSettings) OrgRolePermissions {
|
|||||||
ResourceNotificationMessage.Type: {policy.ActionRead, policy.ActionUpdate},
|
ResourceNotificationMessage.Type: {policy.ActionRead, policy.ActionUpdate},
|
||||||
ResourceNotificationPreference.Type: ResourceNotificationPreference.AvailableActions(),
|
ResourceNotificationPreference.Type: ResourceNotificationPreference.AvailableActions(),
|
||||||
ResourceInboxNotification.Type: ResourceInboxNotification.AvailableActions(),
|
ResourceInboxNotification.Type: ResourceInboxNotification.AvailableActions(),
|
||||||
|
|
||||||
// Intentionally omitted at Member scope. See
|
|
||||||
// OrgMemberPermissions above for the rationale; the service
|
|
||||||
// account role mirrors the same partition.
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
elevation := OrgWorkspaceAccessMemberPerms()
|
||||||
|
|
||||||
|
memberPerms := slices.Concat(elevation, floor)
|
||||||
|
|
||||||
return OrgRolePermissions{Org: orgPerms, Member: memberPerms}
|
return OrgRolePermissions{Org: orgPerms, Member: memberPerms}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1497,6 +1497,7 @@ func TestListRoles(t *testing.T) {
|
|||||||
fmt.Sprintf("organization-user-admin:%s", orgID.String()),
|
fmt.Sprintf("organization-user-admin:%s", orgID.String()),
|
||||||
fmt.Sprintf("organization-template-admin:%s", orgID.String()),
|
fmt.Sprintf("organization-template-admin:%s", orgID.String()),
|
||||||
fmt.Sprintf("organization-workspace-creation-ban:%s", orgID.String()),
|
fmt.Sprintf("organization-workspace-creation-ban:%s", orgID.String()),
|
||||||
|
fmt.Sprintf("organization-workspace-access:%s", orgID.String()),
|
||||||
fmt.Sprintf("agents-access:%s", orgID.String()),
|
fmt.Sprintf("agents-access:%s", orgID.String()),
|
||||||
},
|
},
|
||||||
orgRoleNames)
|
orgRoleNames)
|
||||||
|
|||||||
@@ -15,4 +15,5 @@ const (
|
|||||||
RoleOrganizationTemplateAdmin string = "organization-template-admin"
|
RoleOrganizationTemplateAdmin string = "organization-template-admin"
|
||||||
RoleOrganizationUserAdmin string = "organization-user-admin"
|
RoleOrganizationUserAdmin string = "organization-user-admin"
|
||||||
RoleOrganizationWorkspaceCreationBan string = "organization-workspace-creation-ban"
|
RoleOrganizationWorkspaceCreationBan string = "organization-workspace-creation-ban"
|
||||||
|
RoleOrganizationWorkspaceAccess string = "organization-workspace-access"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -505,6 +505,7 @@ func TestListRoles(t *testing.T) {
|
|||||||
{Name: codersdk.RoleOrganizationTemplateAdmin, OrganizationID: owner.OrganizationID}: false,
|
{Name: codersdk.RoleOrganizationTemplateAdmin, OrganizationID: owner.OrganizationID}: false,
|
||||||
{Name: codersdk.RoleOrganizationUserAdmin, OrganizationID: owner.OrganizationID}: false,
|
{Name: codersdk.RoleOrganizationUserAdmin, OrganizationID: owner.OrganizationID}: false,
|
||||||
{Name: codersdk.RoleOrganizationWorkspaceCreationBan, OrganizationID: owner.OrganizationID}: false,
|
{Name: codersdk.RoleOrganizationWorkspaceCreationBan, OrganizationID: owner.OrganizationID}: false,
|
||||||
|
{Name: codersdk.RoleOrganizationWorkspaceAccess, OrganizationID: owner.OrganizationID}: false,
|
||||||
{Name: codersdk.RoleAgentsAccess, OrganizationID: owner.OrganizationID}: false,
|
{Name: codersdk.RoleAgentsAccess, OrganizationID: owner.OrganizationID}: false,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
@@ -539,6 +540,7 @@ func TestListRoles(t *testing.T) {
|
|||||||
{Name: codersdk.RoleOrganizationTemplateAdmin, OrganizationID: owner.OrganizationID}: true,
|
{Name: codersdk.RoleOrganizationTemplateAdmin, OrganizationID: owner.OrganizationID}: true,
|
||||||
{Name: codersdk.RoleOrganizationUserAdmin, OrganizationID: owner.OrganizationID}: true,
|
{Name: codersdk.RoleOrganizationUserAdmin, OrganizationID: owner.OrganizationID}: true,
|
||||||
{Name: codersdk.RoleOrganizationWorkspaceCreationBan, OrganizationID: owner.OrganizationID}: true,
|
{Name: codersdk.RoleOrganizationWorkspaceCreationBan, OrganizationID: owner.OrganizationID}: true,
|
||||||
|
{Name: codersdk.RoleOrganizationWorkspaceAccess, OrganizationID: owner.OrganizationID}: true,
|
||||||
{Name: codersdk.RoleAgentsAccess, OrganizationID: owner.OrganizationID}: true,
|
{Name: codersdk.RoleAgentsAccess, OrganizationID: owner.OrganizationID}: true,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
@@ -573,6 +575,7 @@ func TestListRoles(t *testing.T) {
|
|||||||
{Name: codersdk.RoleOrganizationTemplateAdmin, OrganizationID: owner.OrganizationID}: true,
|
{Name: codersdk.RoleOrganizationTemplateAdmin, OrganizationID: owner.OrganizationID}: true,
|
||||||
{Name: codersdk.RoleOrganizationUserAdmin, OrganizationID: owner.OrganizationID}: true,
|
{Name: codersdk.RoleOrganizationUserAdmin, OrganizationID: owner.OrganizationID}: true,
|
||||||
{Name: codersdk.RoleOrganizationWorkspaceCreationBan, OrganizationID: owner.OrganizationID}: true,
|
{Name: codersdk.RoleOrganizationWorkspaceCreationBan, OrganizationID: owner.OrganizationID}: true,
|
||||||
|
{Name: codersdk.RoleOrganizationWorkspaceAccess, OrganizationID: owner.OrganizationID}: true,
|
||||||
{Name: codersdk.RoleAgentsAccess, OrganizationID: owner.OrganizationID}: true,
|
{Name: codersdk.RoleAgentsAccess, OrganizationID: owner.OrganizationID}: true,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
|||||||
Generated
+6
@@ -7300,6 +7300,12 @@ export const RoleOrganizationTemplateAdmin = "organization-template-admin";
|
|||||||
*/
|
*/
|
||||||
export const RoleOrganizationUserAdmin = "organization-user-admin";
|
export const RoleOrganizationUserAdmin = "organization-user-admin";
|
||||||
|
|
||||||
|
// From codersdk/rbacroles.go
|
||||||
|
/**
|
||||||
|
* Ideally these roles would be generated from the rbac/roles.go package.
|
||||||
|
*/
|
||||||
|
export const RoleOrganizationWorkspaceAccess = "organization-workspace-access";
|
||||||
|
|
||||||
// From codersdk/rbacroles.go
|
// From codersdk/rbacroles.go
|
||||||
/**
|
/**
|
||||||
* Ideally these roles would be generated from the rbac/roles.go package.
|
* Ideally these roles would be generated from the rbac/roles.go package.
|
||||||
|
|||||||
Reference in New Issue
Block a user