feat(coderd/rbac): make organization-member a per-org system custom role (#21359)

Migrated the built-in organization-member role to DB storage so it can be customized per org.

Closes https://github.com/coder/internal/issues/1073 (part 1)
This commit is contained in:
George K
2026-01-12 18:19:19 -08:00
committed by GitHub
parent 2b448c7178
commit cc2efe9e1f
46 changed files with 1845 additions and 438 deletions
+53
View File
@@ -256,6 +256,59 @@ func TestCustomOrganizationRole(t *testing.T) {
require.ErrorContains(t, err, "not allowed to assign user permissions")
})
// Attempt to add org member permissions, which is not allowed.
t.Run("MemberPermissions", func(t *testing.T) {
t.Parallel()
owner, first := coderdenttest.New(t, &coderdenttest.Options{
LicenseOptions: &coderdenttest.LicenseOptions{
Features: license.Features{
codersdk.FeatureCustomRoles: 1,
},
},
})
ctx := testutil.Context(t, testutil.WaitMedium)
role := templateAdminCustom(first.OrganizationID)
role.Name = "test-role-member-perms"
role.OrganizationMemberPermissions = []codersdk.Permission{
{
ResourceType: codersdk.ResourceWorkspace,
Action: codersdk.ActionRead,
},
}
//nolint:gocritic // we want unrestricted permissions for the test
_, err := owner.CreateOrganizationRole(ctx, role)
var apiErr *codersdk.Error
require.ErrorAs(t, err, &apiErr)
require.Equal(t, http.StatusBadRequest, apiErr.StatusCode())
require.ErrorContains(t, err, "not allowed to assign organization member permissions for an organization role")
})
// Attempt to delete a system role, which is not allowed.
t.Run("DeleteSystemRole", func(t *testing.T) {
t.Parallel()
owner, first := coderdenttest.New(t, &coderdenttest.Options{
LicenseOptions: &coderdenttest.LicenseOptions{
Features: license.Features{
codersdk.FeatureCustomRoles: 1,
},
},
})
ctx := testutil.Context(t, testutil.WaitMedium)
//nolint:gocritic // we want unrestricted permissions for the test
err := owner.DeleteOrganizationRole(ctx, first.OrganizationID, rbac.RoleOrgMember())
var apiErr *codersdk.Error
require.ErrorAs(t, err, &apiErr)
require.Equal(t, http.StatusBadRequest, apiErr.StatusCode())
require.ErrorContains(t, err, "Reserved role name")
})
t.Run("NotFound", func(t *testing.T) {
t.Parallel()
owner, first := coderdenttest.New(t, &coderdenttest.Options{