Skip to content

Commit 52835d5

Browse files
committed
chore: rolestore to handle custom org roles
1 parent 520d32e commit 52835d5

File tree

8 files changed

+69
-11
lines changed

8 files changed

+69
-11
lines changed

cli/organizationroles_test.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"github.com/coder/coder/v2/coderd/coderdtest"
1212
"github.com/coder/coder/v2/coderd/database"
1313
"github.com/coder/coder/v2/coderd/database/dbgen"
14+
"github.com/coder/coder/v2/coderd/rbac"
1415
"github.com/coder/coder/v2/testutil"
1516
)
1617

@@ -20,8 +21,9 @@ func TestShowOrganizationRoles(t *testing.T) {
2021
t.Run("OK", func(t *testing.T) {
2122
t.Parallel()
2223

23-
client, db := coderdtest.NewWithDatabase(t, &coderdtest.Options{})
24-
owner := coderdtest.CreateFirstUser(t, client)
24+
ownerClient, db := coderdtest.NewWithDatabase(t, &coderdtest.Options{})
25+
owner := coderdtest.CreateFirstUser(t, ownerClient)
26+
client, _ := coderdtest.CreateAnotherUser(t, ownerClient, owner.OrganizationID, rbac.RoleUserAdmin())
2527

2628
const expectedRole = "test-role"
2729
dbgen.CustomRole(t, db, database.CustomRole{
@@ -36,7 +38,6 @@ func TestShowOrganizationRoles(t *testing.T) {
3638
},
3739
})
3840

39-
// Requires an owner
4041
ctx := testutil.Context(t, testutil.WaitMedium)
4142
inv, root := clitest.New(t, "organization", "roles", "show")
4243
clitest.SetupConfig(t, client, root)

coderd/database/dbmem/dbmem.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1187,7 +1187,11 @@ func (q *FakeQuerier) CustomRoles(_ context.Context, arg database.CustomRolesPar
11871187
role := role
11881188
if len(arg.LookupRoles) > 0 {
11891189
if !slices.ContainsFunc(arg.LookupRoles, func(s string) bool {
1190-
return strings.EqualFold(s, role.Name)
1190+
roleName := rbac.RoleName(role.Name, "")
1191+
if role.OrganizationID.UUID != uuid.Nil {
1192+
roleName = rbac.RoleName(role.Name, role.OrganizationID.UUID.String())
1193+
}
1194+
return strings.EqualFold(s, roleName)
11911195
}) {
11921196
continue
11931197
}

coderd/database/queries.sql.go

Lines changed: 6 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/queries/roles.sql

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@ FROM
55
custom_roles
66
WHERE
77
true
8-
-- Lookup roles filter
8+
-- Lookup roles filter expects the role names to be in the rbac package
9+
-- format. Eg: name[:<organization_id>]
910
AND CASE WHEN array_length(@lookup_roles :: text[], 1) > 0 THEN
10-
-- Case insensitive
11-
name ILIKE ANY(@lookup_roles :: text [])
11+
-- Case insensitive lookup with org_id appended (if non-null).
12+
-- This will return just the name if org_id is null. It'll append
13+
-- the org_id if not null
14+
concat(name, NULLIF(concat(':', organization_id), ':')) ILIKE ANY(@lookup_roles :: text [])
1215
ELSE true
1316
END
1417
-- Org scoping filter, to only fetch site wide roles

coderd/rbac/rolestore/rolestore.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ func Expand(ctx context.Context, db database.Store, names []string) (rbac.Roles,
7676
dbroles, err := db.CustomRoles(ctx, database.CustomRolesParams{
7777
LookupRoles: lookup,
7878
ExcludeOrgRoles: false,
79+
OrganizationID: uuid.Nil,
7980
})
8081
if err != nil {
8182
return nil, xerrors.Errorf("fetch custom roles: %w", err)
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package rolestore_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/google/uuid"
7+
"github.com/stretchr/testify/require"
8+
9+
"github.com/coder/coder/v2/coderd/database"
10+
"github.com/coder/coder/v2/coderd/database/dbgen"
11+
"github.com/coder/coder/v2/coderd/database/dbmem"
12+
"github.com/coder/coder/v2/coderd/rbac"
13+
"github.com/coder/coder/v2/coderd/rbac/rolestore"
14+
"github.com/coder/coder/v2/testutil"
15+
)
16+
17+
func TestExpandCustomRoleRoles(t *testing.T) {
18+
t.Parallel()
19+
20+
db := dbmem.New()
21+
22+
org := dbgen.Organization(t, db, database.Organization{})
23+
24+
const roleName = "test-role"
25+
dbgen.CustomRole(t, db, database.CustomRole{
26+
Name: roleName,
27+
DisplayName: "",
28+
SitePermissions: nil,
29+
OrgPermissions: nil,
30+
UserPermissions: nil,
31+
OrganizationID: uuid.NullUUID{
32+
UUID: org.ID,
33+
Valid: true,
34+
},
35+
})
36+
37+
ctx := testutil.Context(t, testutil.WaitShort)
38+
roles, err := rolestore.Expand(ctx, db, []string{rbac.RoleName(roleName, org.ID.String())})
39+
require.NoError(t, err)
40+
require.Len(t, roles, 1, "role found")
41+
}

coderd/roles.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package coderd
33
import (
44
"net/http"
55

6+
"github.com/google/uuid"
7+
68
"github.com/coder/coder/v2/coderd/database"
79
"github.com/coder/coder/v2/coderd/database/db2sdk"
810
"github.com/coder/coder/v2/coderd/httpmw"
@@ -32,9 +34,10 @@ func (api *API) AssignableSiteRoles(rw http.ResponseWriter, r *http.Request) {
3234
}
3335

3436
dbCustomRoles, err := api.Database.CustomRoles(ctx, database.CustomRolesParams{
37+
LookupRoles: nil,
3538
// Only site wide custom roles to be included
3639
ExcludeOrgRoles: true,
37-
LookupRoles: nil,
40+
OrganizationID: uuid.Nil,
3841
})
3942
if err != nil {
4043
httpapi.InternalServerError(rw, err)

coderd/roles_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,8 @@ func TestListCustomRoles(t *testing.T) {
164164
t.Parallel()
165165

166166
t.Run("Organizations", func(t *testing.T) {
167+
t.Parallel()
168+
167169
client, db := coderdtest.NewWithDatabase(t, nil)
168170
owner := coderdtest.CreateFirstUser(t, client)
169171

0 commit comments

Comments
 (0)