Skip to content

Commit c774a77

Browse files
committed
add unit test
1 parent 2f8884c commit c774a77

File tree

2 files changed

+105
-16
lines changed

2 files changed

+105
-16
lines changed

cli/organizationroles.go

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"encoding/json"
55
"fmt"
66
"io"
7-
"os"
87
"slices"
98
"strings"
109

@@ -114,7 +113,8 @@ func (r *RootCmd) editOrganizationRole() *serpent.Command {
114113
)
115114

116115
var (
117-
dryRun bool
116+
dryRun bool
117+
jsonInput bool
118118
)
119119

120120
client := new(codersdk.Client)
@@ -135,6 +135,12 @@ func (r *RootCmd) editOrganizationRole() *serpent.Command {
135135
Flag: "dry-run",
136136
Value: serpent.BoolOf(&dryRun),
137137
},
138+
{
139+
Name: "stdin",
140+
Description: "Reads stdin for the json role definition to upload.",
141+
Flag: "stdin",
142+
Value: serpent.BoolOf(&jsonInput),
143+
},
138144
},
139145
Middleware: serpent.Chain(
140146
serpent.RequireRangeArgs(0, 1),
@@ -148,10 +154,9 @@ func (r *RootCmd) editOrganizationRole() *serpent.Command {
148154
}
149155

150156
var customRole codersdk.Role
151-
fi, _ := os.Stdin.Stat()
152-
if (fi.Mode() & os.ModeCharDevice) == 0 {
157+
if jsonInput {
153158
// JSON Upload mode
154-
bytes, err := io.ReadAll(os.Stdin)
159+
bytes, err := io.ReadAll(inv.Stdin)
155160
if err != nil {
156161
return xerrors.Errorf("reading stdin: %w", err)
157162
}
@@ -170,6 +175,10 @@ func (r *RootCmd) editOrganizationRole() *serpent.Command {
170175
return xerrors.Errorf("json input does not appear to be a valid role")
171176
}
172177
} else {
178+
if len(inv.Args) == 0 {
179+
return xerrors.Errorf("missing role name argument, usage: \"coder organizations roles edit <role_name>\"")
180+
}
181+
173182
interactiveRole, err := interactiveOrgRoleEdit(inv, org.ID, client)
174183
if err != nil {
175184
return xerrors.Errorf("editing role: %w", err)
@@ -182,7 +191,7 @@ func (r *RootCmd) editOrganizationRole() *serpent.Command {
182191
for _, o := range customRole.OrganizationPermissions {
183192
totalOrg += len(o)
184193
}
185-
preview := fmt.Sprintf("perms: %d site, %d over %d orgs, %d user",
194+
preview := fmt.Sprintf("permissions: %d site, %d over %d orgs, %d user",
186195
len(customRole.SitePermissions), totalOrg, len(customRole.OrganizationPermissions), len(customRole.UserPermissions))
187196
_, err = cliui.Prompt(inv, cliui.PromptOptions{
188197
Text: "Are you sure you wish to update the role? " + preview,
@@ -276,7 +285,7 @@ customRoleLoop:
276285
for {
277286
selected, err := cliui.Select(inv, cliui.SelectOptions{
278287
Message: "Select which resources to edit permissions",
279-
Options: append(permissionPreviews(role, allowedResources), done, abort),
288+
Options: append(permissionPreviews(role, orgID, allowedResources), done, abort),
280289
})
281290
if err != nil {
282291
return role, xerrors.Errorf("selecting resource: %w", err)
@@ -293,7 +302,7 @@ customRoleLoop:
293302
actions, err := cliui.MultiSelect(inv, cliui.MultiSelectOptions{
294303
Message: fmt.Sprintf("Select actions to allow across the whole deployment for resources=%q", resource),
295304
Options: slice.ToStrings(codersdk.RBACResourceActions[codersdk.RBACResource(resource)]),
296-
Defaults: defaultActions(role, resource),
305+
Defaults: defaultActions(role, orgID, resource),
297306
})
298307
if err != nil {
299308
return role, xerrors.Errorf("selecting actions for resource %q: %w", resource, err)
@@ -309,6 +318,10 @@ customRoleLoop:
309318
}
310319

311320
func applyOrgResourceActions(role *codersdk.Role, orgID uuid.UUID, resource string, actions []string) {
321+
if role.OrganizationPermissions == nil {
322+
role.OrganizationPermissions = map[string][]codersdk.Permission{}
323+
}
324+
312325
if _, ok := role.OrganizationPermissions[orgID.String()]; !ok {
313326
role.OrganizationPermissions[orgID.String()] = []codersdk.Permission{}
314327
}
@@ -334,27 +347,35 @@ func applyOrgResourceActions(role *codersdk.Role, orgID uuid.UUID, resource stri
334347
role.OrganizationPermissions[orgID.String()] = keep
335348
}
336349

337-
func defaultActions(role *codersdk.Role, resource string) []string {
350+
func defaultActions(role *codersdk.Role, orgID uuid.UUID, resource string) []string {
351+
if role.OrganizationPermissions == nil {
352+
role.OrganizationPermissions = map[string][]codersdk.Permission{}
353+
}
354+
338355
defaults := make([]string, 0)
339-
for _, perm := range role.SitePermissions {
356+
for _, perm := range role.OrganizationPermissions[orgID.String()] {
340357
if string(perm.ResourceType) == resource {
341358
defaults = append(defaults, string(perm.Action))
342359
}
343360
}
344361
return defaults
345362
}
346363

347-
func permissionPreviews(role *codersdk.Role, resources []codersdk.RBACResource) []string {
364+
func permissionPreviews(role *codersdk.Role, orgID uuid.UUID, resources []codersdk.RBACResource) []string {
348365
previews := make([]string, 0, len(resources))
349366
for _, resource := range resources {
350-
previews = append(previews, permissionPreview(role, resource))
367+
previews = append(previews, permissionPreview(role, orgID, resource))
351368
}
352369
return previews
353370
}
354371

355-
func permissionPreview(role *codersdk.Role, resource codersdk.RBACResource) string {
372+
func permissionPreview(role *codersdk.Role, orgID uuid.UUID, resource codersdk.RBACResource) string {
373+
if role.OrganizationPermissions == nil {
374+
role.OrganizationPermissions = map[string][]codersdk.Permission{}
375+
}
376+
356377
count := 0
357-
for _, perm := range role.SitePermissions {
378+
for _, perm := range role.OrganizationPermissions[orgID.String()] {
358379
if perm.ResourceType == resource {
359380
count++
360381
}
@@ -377,8 +398,12 @@ func orgPermissionString(perms map[string][]codersdk.Permission) string {
377398
for _, o := range perms {
378399
totalOrg += len(o)
379400
}
380-
return fmt.Sprintf("%d over %d organizations",
381-
totalOrg, len(perms))
401+
plural := ""
402+
if len(perms) > 1 {
403+
plural = "s"
404+
}
405+
return fmt.Sprintf("%d over %d organization%s",
406+
totalOrg, len(perms), plural)
382407
}
383408

384409
type roleTableRow struct {

enterprise/cli/organization_test.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package cli
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
"testing"
7+
8+
"github.com/stretchr/testify/require"
9+
10+
"github.com/coder/coder/v2/cli/clitest"
11+
"github.com/coder/coder/v2/coderd/coderdtest"
12+
"github.com/coder/coder/v2/codersdk"
13+
"github.com/coder/coder/v2/enterprise/coderd/coderdenttest"
14+
"github.com/coder/coder/v2/enterprise/coderd/license"
15+
"github.com/coder/coder/v2/testutil"
16+
)
17+
18+
func TestEditOrganizationRoles(t *testing.T) {
19+
t.Parallel()
20+
21+
t.Run("JSON", func(t *testing.T) {
22+
t.Parallel()
23+
24+
dv := coderdtest.DeploymentValues(t)
25+
dv.Experiments = []string{string(codersdk.ExperimentCustomRoles)}
26+
client, owner := coderdenttest.New(t, &coderdenttest.Options{
27+
Options: &coderdtest.Options{
28+
DeploymentValues: dv,
29+
},
30+
LicenseOptions: &coderdenttest.LicenseOptions{
31+
Features: license.Features{
32+
codersdk.FeatureCustomRoles: 1,
33+
},
34+
}})
35+
36+
ctx := testutil.Context(t, testutil.WaitMedium)
37+
inv, root := clitest.New(t, "organization", "roles", "edit", "--stdin")
38+
// Use json input, as interactive mode would be challenging to control
39+
inv.Stdin = bytes.NewBufferString(fmt.Sprintf(`{
40+
"name": "new-role",
41+
"organization_id": "%[1]s",
42+
"display_name": "",
43+
"site_permissions": [],
44+
"organization_permissions": {
45+
"%[1]s": [
46+
{
47+
"resource_type": "workspace",
48+
"action": "read"
49+
}
50+
]
51+
},
52+
"user_permissions": [],
53+
"assignable": false,
54+
"built_in": false
55+
}`, owner.OrganizationID.String()))
56+
clitest.SetupConfig(t, client, root)
57+
58+
buf := new(bytes.Buffer)
59+
inv.Stdout = buf
60+
err := inv.WithContext(ctx).Run()
61+
require.NoError(t, err)
62+
require.Contains(t, buf.String(), "new-role")
63+
})
64+
}

0 commit comments

Comments
 (0)