Files
coder/enterprise/cli/groupedit.go
T
Steven Masley 4c1e63aae8 feat: add display_name field to groups (#8740)
* feat: add display_name field to groups

This is a non-unique human friendly group name for display
purposes. This means a display name can be used instead of
using an environment var to remap groups with OIDC names to
Coder names. Now groups can retain the OIDC name for mapping,
and use a display name for display purposes.
2023-08-02 10:53:06 -05:00

146 lines
3.5 KiB
Go

package cli
import (
"fmt"
"net/mail"
"github.com/google/uuid"
"golang.org/x/xerrors"
agpl "github.com/coder/coder/cli"
"github.com/coder/coder/cli/clibase"
"github.com/coder/coder/cli/cliui"
"github.com/coder/coder/codersdk"
)
func (r *RootCmd) groupEdit() *clibase.Cmd {
var (
avatarURL string
name string
displayName string
addUsers []string
rmUsers []string
)
client := new(codersdk.Client)
cmd := &clibase.Cmd{
Use: "edit <name>",
Short: "Edit a user group",
Middleware: clibase.Chain(
clibase.RequireNArgs(1),
r.InitClient(client),
),
Handler: func(inv *clibase.Invocation) error {
var (
ctx = inv.Context()
groupName = inv.Args[0]
)
org, err := agpl.CurrentOrganization(inv, client)
if err != nil {
return xerrors.Errorf("current organization: %w", err)
}
group, err := client.GroupByOrgAndName(ctx, org.ID, groupName)
if err != nil {
return xerrors.Errorf("group by org and name: %w", err)
}
req := codersdk.PatchGroupRequest{
Name: name,
}
if avatarURL != "" {
req.AvatarURL = &avatarURL
}
if inv.ParsedFlags().Lookup("display-name").Changed {
req.DisplayName = &displayName
}
userRes, err := client.Users(ctx, codersdk.UsersRequest{})
if err != nil {
return xerrors.Errorf("get users: %w", err)
}
req.AddUsers, err = convertToUserIDs(addUsers, userRes.Users)
if err != nil {
return xerrors.Errorf("parse add-users: %w", err)
}
req.RemoveUsers, err = convertToUserIDs(rmUsers, userRes.Users)
if err != nil {
return xerrors.Errorf("parse rm-users: %w", err)
}
group, err = client.PatchGroup(ctx, group.ID, req)
if err != nil {
return xerrors.Errorf("patch group: %w", err)
}
_, _ = fmt.Fprintf(inv.Stdout, "Successfully patched group %s!\n", cliui.DefaultStyles.Keyword.Render(group.Name))
return nil
},
}
cmd.Options = clibase.OptionSet{
{
Flag: "name",
FlagShorthand: "n",
Description: "Update the group name.",
Value: clibase.StringOf(&name),
},
{
Flag: "avatar-url",
FlagShorthand: "u",
Description: "Update the group avatar.",
Value: clibase.StringOf(&avatarURL),
},
{
Flag: "display-name",
Description: `Optional human friendly name for the group.`,
Env: "CODER_DISPLAY_NAME",
Value: clibase.StringOf(&displayName),
},
{
Flag: "add-users",
FlagShorthand: "a",
Description: "Add users to the group. Accepts emails or IDs.",
Value: clibase.StringArrayOf(&addUsers),
},
{
Flag: "rm-users",
FlagShorthand: "r",
Description: "Remove users to the group. Accepts emails or IDs.",
Value: clibase.StringArrayOf(&rmUsers),
},
}
return cmd
}
// convertToUserIDs accepts a list of users in the form of IDs or email addresses
// and translates any emails to the matching user ID.
func convertToUserIDs(userList []string, users []codersdk.User) ([]string, error) {
converted := make([]string, 0, len(userList))
for _, user := range userList {
if _, err := uuid.Parse(user); err == nil {
converted = append(converted, user)
continue
}
if _, err := mail.ParseAddress(user); err == nil {
for _, u := range users {
if u.Email == user {
converted = append(converted, u.ID.String())
break
}
}
continue
}
return nil, xerrors.Errorf("%q must be a valid UUID or email address", user)
}
return converted, nil
}