Skip to content

Commit 75e7213

Browse files
authored
feat: add cli command to remove organization member (#13619)
1 parent cbdaa63 commit 75e7213

File tree

3 files changed

+87
-2
lines changed

3 files changed

+87
-2
lines changed

cli/organizationmembers.go

+34-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ func (r *RootCmd) organizationMembers() *serpent.Command {
2020
r.listOrganizationMembers(),
2121
r.assignOrganizationRoles(),
2222
r.addOrganizationMember(),
23+
r.removeOrganizationMember(),
2324
},
2425
Handler: func(inv *serpent.Invocation) error {
2526
return inv.Command.HelpHandler(inv)
@@ -29,6 +30,37 @@ func (r *RootCmd) organizationMembers() *serpent.Command {
2930
return cmd
3031
}
3132

33+
func (r *RootCmd) removeOrganizationMember() *serpent.Command {
34+
client := new(codersdk.Client)
35+
36+
cmd := &serpent.Command{
37+
Use: "remove <username | user_id>",
38+
Short: "Remove a new member to the current organization",
39+
Middleware: serpent.Chain(
40+
r.InitClient(client),
41+
serpent.RequireNArgs(1),
42+
),
43+
Handler: func(inv *serpent.Invocation) error {
44+
ctx := inv.Context()
45+
organization, err := CurrentOrganization(r, inv, client)
46+
if err != nil {
47+
return err
48+
}
49+
user := inv.Args[0]
50+
51+
err = client.DeleteOrganizationMember(ctx, organization.ID, user)
52+
if err != nil {
53+
return xerrors.Errorf("could not remove member from organization %q: %w", organization.HumanName(), err)
54+
}
55+
56+
_, _ = fmt.Fprintf(inv.Stdout, "Organization member removed from %q\n", organization.HumanName())
57+
return nil
58+
},
59+
}
60+
61+
return cmd
62+
}
63+
3264
func (r *RootCmd) addOrganizationMember() *serpent.Command {
3365
client := new(codersdk.Client)
3466

@@ -49,10 +81,10 @@ func (r *RootCmd) addOrganizationMember() *serpent.Command {
4981

5082
_, err = client.PostOrganizationMember(ctx, organization.ID, user)
5183
if err != nil {
52-
return xerrors.Errorf("could not add member to organization: %w", err)
84+
return xerrors.Errorf("could not add member to organization %q: %w", organization.HumanName(), err)
5385
}
5486

55-
_, _ = fmt.Fprintln(inv.Stdout, "Organization member added")
87+
_, _ = fmt.Fprintf(inv.Stdout, "Organization member added to %q\n", organization.HumanName())
5688
return nil
5789
},
5890
}

cli/organizationmembers_test.go

+46
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,49 @@ func TestAddOrganizationMembers(t *testing.T) {
7272
require.Len(t, members, 2)
7373
})
7474
}
75+
76+
func TestRemoveOrganizationMembers(t *testing.T) {
77+
t.Parallel()
78+
79+
t.Run("OK", func(t *testing.T) {
80+
t.Parallel()
81+
82+
ownerClient := coderdtest.New(t, &coderdtest.Options{})
83+
owner := coderdtest.CreateFirstUser(t, ownerClient)
84+
orgAdminClient, _ := coderdtest.CreateAnotherUser(t, ownerClient, owner.OrganizationID, rbac.ScopedRoleOrgAdmin(owner.OrganizationID))
85+
_, user := coderdtest.CreateAnotherUser(t, ownerClient, owner.OrganizationID)
86+
87+
ctx := testutil.Context(t, testutil.WaitMedium)
88+
89+
inv, root := clitest.New(t, "organization", "members", "remove", "--organization", owner.OrganizationID.String(), user.Username)
90+
clitest.SetupConfig(t, orgAdminClient, root)
91+
92+
buf := new(bytes.Buffer)
93+
inv.Stdout = buf
94+
err := inv.WithContext(ctx).Run()
95+
require.NoError(t, err)
96+
97+
members, err := orgAdminClient.OrganizationMembers(ctx, owner.OrganizationID)
98+
require.NoError(t, err)
99+
100+
require.Len(t, members, 2)
101+
})
102+
103+
t.Run("UserNotExists", func(t *testing.T) {
104+
t.Parallel()
105+
106+
ownerClient := coderdtest.New(t, &coderdtest.Options{})
107+
owner := coderdtest.CreateFirstUser(t, ownerClient)
108+
orgAdminClient, _ := coderdtest.CreateAnotherUser(t, ownerClient, owner.OrganizationID, rbac.ScopedRoleOrgAdmin(owner.OrganizationID))
109+
110+
ctx := testutil.Context(t, testutil.WaitMedium)
111+
112+
inv, root := clitest.New(t, "organization", "members", "remove", "--organization", owner.OrganizationID.String(), "random_name")
113+
clitest.SetupConfig(t, orgAdminClient, root)
114+
115+
buf := new(bytes.Buffer)
116+
inv.Stdout = buf
117+
err := inv.WithContext(ctx).Run()
118+
require.ErrorContains(t, err, "must be an existing uuid or username")
119+
})
120+
}

codersdk/organizations.go

+7
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,13 @@ type Organization struct {
5050
Icon string `table:"icon" json:"icon"`
5151
}
5252

53+
func (o Organization) HumanName() string {
54+
if o.DisplayName == "" {
55+
return o.Name
56+
}
57+
return o.DisplayName
58+
}
59+
5360
type OrganizationMember struct {
5461
UserID uuid.UUID `table:"user id" json:"user_id" format:"uuid"`
5562
OrganizationID uuid.UUID `table:"organization id" json:"organization_id" format:"uuid"`

0 commit comments

Comments
 (0)