diff --git a/cmd/list.go b/cmd/list.go index afb9cc07..7c895278 100644 --- a/cmd/list.go +++ b/cmd/list.go @@ -1055,31 +1055,79 @@ var ListOrganizationUsersCmd = &cobra.Command{ lagoonCLIConfig.Lagoons[current].Version, &token, debug) - organization, err := lagoon.GetOrganizationByName(context.Background(), organizationName, lc) + users, err := lagoon.UsersByOrganizationName(context.TODO(), organizationName, lc) if err != nil { return err } - if organization.Name == "" { - return fmt.Errorf("error querying organization by name") + + data := []output.Data{} + for _, user := range *users { + data = append(data, []string{ + returnNonEmptyString(user.ID.String()), + returnNonEmptyString(user.Email), + returnNonEmptyString(user.FirstName), + returnNonEmptyString(user.LastName), + returnNonEmptyString(user.Comment), + }) } - users, err := lagoon.UsersByOrganization(context.TODO(), organization.ID, lc) + dataMain := output.Table{ + Header: []string{"ID", "Email", "First Name", "LastName", "Comment"}, + Data: data, + } + output.RenderOutput(dataMain, outputOptions) + return nil + }, +} + +var ListOrganizationAdminsCmd = &cobra.Command{ + Use: "organization-admins", + Aliases: []string{"org-a"}, + Short: "List admins in an organization", + PreRunE: func(_ *cobra.Command, _ []string) error { + return validateTokenE(cmdLagoon) + }, + RunE: func(cmd *cobra.Command, args []string) error { + debug, err := cmd.Flags().GetBool("debug") + if err != nil { + return err + } + organizationName, err := cmd.Flags().GetString("organization-name") + if err != nil { + return err + } + if err := requiredInputCheck("Organization name", organizationName); err != nil { + return err + } + + current := lagoonCLIConfig.Current + token := lagoonCLIConfig.Lagoons[current].Token + lc := lclient.New( + lagoonCLIConfig.Lagoons[current].GraphQL, + lagoonCLIVersion, + lagoonCLIConfig.Lagoons[current].Version, + &token, + debug) + users, err := lagoon.ListOrganizationAdminsByName(context.TODO(), organizationName, lc) if err != nil { return err } data := []output.Data{} for _, user := range *users { + role := "viewer" + if user.Owner { + role = "owner" + } data = append(data, []string{ - returnNonEmptyString(user.ID), + returnNonEmptyString(user.ID.String()), returnNonEmptyString(user.Email), returnNonEmptyString(user.FirstName), returnNonEmptyString(user.LastName), - returnNonEmptyString(user.Comment), - returnNonEmptyString(fmt.Sprintf("%v", user.Owner)), + returnNonEmptyString(role), }) } dataMain := output.Table{ - Header: []string{"ID", "Email", "First Name", "LastName", "Comment", "Owner"}, + Header: []string{"ID", "Email", "First Name", "LastName", "OrganizationRole"}, Data: data, } output.RenderOutput(dataMain, outputOptions) @@ -1155,6 +1203,7 @@ func init() { listCmd.AddCommand(listUsersGroupsCmd) listCmd.AddCommand(listOrganizationProjectsCmd) listCmd.AddCommand(ListOrganizationUsersCmd) + listCmd.AddCommand(ListOrganizationAdminsCmd) listCmd.AddCommand(listOrganizationGroupsCmd) listCmd.AddCommand(listOrganizationDeployTargetsCmd) listCmd.AddCommand(listOrganizationsCmd) @@ -1167,6 +1216,7 @@ func init() { listVariablesCmd.Flags().BoolP("reveal", "", false, "Reveal the variable values") listOrganizationProjectsCmd.Flags().StringP("organization-name", "O", "", "Name of the organization to list associated projects for") ListOrganizationUsersCmd.Flags().StringP("organization-name", "O", "", "Name of the organization to list associated users for") + ListOrganizationAdminsCmd.Flags().StringP("organization-name", "O", "", "Name of the organization to list associated users for") listOrganizationGroupsCmd.Flags().StringP("organization-name", "O", "", "Name of the organization to list associated groups for") listOrganizationDeployTargetsCmd.Flags().StringP("organization-name", "O", "", "Name of the organization to list associated deploy targets for") listOrganizationDeployTargetsCmd.Flags().Uint("id", 0, "ID of the organization to list associated deploy targets for") diff --git a/cmd/users.go b/cmd/users.go index 40d04c39..8b0d05b9 100644 --- a/cmd/users.go +++ b/cmd/users.go @@ -501,7 +501,7 @@ var addAdministratorToOrganizationCmd = &cobra.Command{ Use: "organization-administrator", Aliases: []string{"org-admin"}, Short: "Add an administrator to an Organization", - Long: "Add an administrator to an Organization. If the owner flag is not provided users will be added as viewers", + Long: "Add an administrator to an Organization. If the role flag is not provided users will be added as viewers", PreRunE: func(_ *cobra.Command, _ []string) error { return validateTokenE(lagoonCLIConfig.Current) }, @@ -522,10 +522,20 @@ var addAdministratorToOrganizationCmd = &cobra.Command{ if err := requiredInputCheck("Organization name", organizationName, "User email", userEmail); err != nil { return err } - owner, err := cmd.Flags().GetBool("owner") + role, err := cmd.Flags().GetString("role") if err != nil { return err } + userInput := schema.AddUserToOrganizationInput{ + User: schema.UserInput{Email: userEmail}, + } + switch strings.ToLower(role) { + case "viewer": + case "owner": + userInput.Owner = true + default: + return fmt.Errorf(`role '%s' is not valid - valid roles include "viewer", "owner"`, role) + } current := lagoonCLIConfig.Current token := lagoonCLIConfig.Lagoons[current].Token @@ -543,15 +553,10 @@ var addAdministratorToOrganizationCmd = &cobra.Command{ if organization.Name == "" { return fmt.Errorf("error querying organization by name") } - - userInput := schema.AddUserToOrganizationInput{ - User: schema.UserInput{Email: userEmail}, - Organization: organization.ID, - Owner: owner, - } + userInput.Organization = organization.ID orgUser := schema.Organization{} - err = lc.AddUserToOrganization(context.TODO(), &userInput, &orgUser) + err = lc.AddAdminToOrganization(context.TODO(), &userInput, &orgUser) if err != nil { return err } @@ -595,10 +600,6 @@ var removeAdministratorFromOrganizationCmd = &cobra.Command{ if err := requiredInputCheck("User email", userEmail); err != nil { return err } - owner, err := cmd.Flags().GetBool("owner") - if err != nil { - return err - } current := lagoonCLIConfig.Current token := lagoonCLIConfig.Lagoons[current].Token @@ -620,13 +621,12 @@ var removeAdministratorFromOrganizationCmd = &cobra.Command{ userInput := schema.AddUserToOrganizationInput{ User: schema.UserInput{Email: userEmail}, Organization: organization.ID, - Owner: owner, } orgUser := schema.Organization{} if yesNo(fmt.Sprintf("You are attempting to remove user '%s' from organization '%s'. This removes the users ability to view or manage the organizations groups, projects, & notifications, are you sure?", userEmail, organization.Name)) { - err = lc.RemoveUserFromOrganization(context.TODO(), &userInput, &orgUser) + err = lc.RemoveAdminFromOrganization(context.TODO(), &userInput, &orgUser) handleError(err) resultData := output.Result{ Result: "success", @@ -707,9 +707,8 @@ func init() { getAllUserKeysCmd.Flags().StringP("name", "N", "", "Name of the group to list users in (if not specified, will default to all groups)") addAdministratorToOrganizationCmd.Flags().StringP("organization-name", "O", "", "Name of the organization") addAdministratorToOrganizationCmd.Flags().StringP("email", "E", "", "Email address of the user") - addAdministratorToOrganizationCmd.Flags().Bool("owner", false, "Set the user as an owner of the organization") + addAdministratorToOrganizationCmd.Flags().StringP("role", "R", "", "Role in the organization [owner, viewer]") removeAdministratorFromOrganizationCmd.Flags().StringP("organization-name", "O", "", "Name of the organization") removeAdministratorFromOrganizationCmd.Flags().StringP("email", "E", "", "Email address of the user") - removeAdministratorFromOrganizationCmd.Flags().Bool("owner", false, "Set the user as an administrator of the organization") resetPasswordCmd.Flags().StringP("email", "E", "", "Email address of the user") } diff --git a/docs/commands/lagoon_add_organization-administrator.md b/docs/commands/lagoon_add_organization-administrator.md index f4e2ed18..18088df3 100644 --- a/docs/commands/lagoon_add_organization-administrator.md +++ b/docs/commands/lagoon_add_organization-administrator.md @@ -4,7 +4,7 @@ Add an administrator to an Organization ### Synopsis -Add an administrator to an Organization. If the owner flag is not provided users will be added as viewers +Add an administrator to an Organization. If the role flag is not provided users will be added as viewers ``` lagoon add organization-administrator [flags] @@ -16,7 +16,7 @@ lagoon add organization-administrator [flags] -E, --email string Email address of the user -h, --help help for organization-administrator -O, --organization-name string Name of the organization - --owner Set the user as an owner of the organization + -R, --role string Role in the organization [owner, viewer] ``` ### Options inherited from parent commands diff --git a/docs/commands/lagoon_delete_organization-administrator.md b/docs/commands/lagoon_delete_organization-administrator.md index 028d01cb..655fe981 100644 --- a/docs/commands/lagoon_delete_organization-administrator.md +++ b/docs/commands/lagoon_delete_organization-administrator.md @@ -12,7 +12,6 @@ lagoon delete organization-administrator [flags] -E, --email string Email address of the user -h, --help help for organization-administrator -O, --organization-name string Name of the organization - --owner Set the user as an administrator of the organization ``` ### Options inherited from parent commands diff --git a/docs/commands/lagoon_list.md b/docs/commands/lagoon_list.md index 06f84d68..76a1f02c 100644 --- a/docs/commands/lagoon_list.md +++ b/docs/commands/lagoon_list.md @@ -43,6 +43,7 @@ List projects, environments, deployments, variables or notifications * [lagoon list groups](lagoon_list_groups.md) - List groups you have access to (alias: g) * [lagoon list invokable-tasks](lagoon_list_invokable-tasks.md) - Print a list of invokable tasks * [lagoon list notification](lagoon_list_notification.md) - List all notifications or notifications on projects +* [lagoon list organization-admins](lagoon_list_organization-admins.md) - List admins in an organization * [lagoon list organization-deploytargets](lagoon_list_organization-deploytargets.md) - List deploy targets in an organization * [lagoon list organization-groups](lagoon_list_organization-groups.md) - List groups in an organization * [lagoon list organization-projects](lagoon_list_organization-projects.md) - List projects in an organization diff --git a/docs/commands/lagoon_list_organization-admins.md b/docs/commands/lagoon_list_organization-admins.md new file mode 100644 index 00000000..ca11b668 --- /dev/null +++ b/docs/commands/lagoon_list_organization-admins.md @@ -0,0 +1,39 @@ +## lagoon list organization-admins + +List admins in an organization + +``` +lagoon list organization-admins [flags] +``` + +### Options + +``` + -h, --help help for organization-admins + -O, --organization-name string Name of the organization to list associated users for +``` + +### Options inherited from parent commands + +``` + --config-file string Path to the config file to use (must be *.yml or *.yaml) + --debug Enable debugging output (if supported) + -e, --environment string Specify an environment to use + --force Force yes on prompts (if supported) + -l, --lagoon string The Lagoon instance to interact with + --no-header No header on table (if supported) + --output-csv Output as CSV (if supported) + --output-json Output as JSON (if supported) + --pretty Make JSON pretty (if supported) + -p, --project string Specify a project to use + --skip-update-check Skip checking for updates + -i, --ssh-key string Specify path to a specific SSH key to use for lagoon authentication + --ssh-publickey string Specify path to a specific SSH public key to use for lagoon authentication using ssh-agent. + This will override any public key identities defined in configuration + -v, --verbose Enable verbose output to stderr (if supported) +``` + +### SEE ALSO + +* [lagoon list](lagoon_list.md) - List projects, environments, deployments, variables or notifications + diff --git a/go.mod b/go.mod index 9f140ddd..aa4907f1 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/spf13/cobra v1.8.0 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.8.2 - github.com/uselagoon/machinery v0.0.22 + github.com/uselagoon/machinery v0.0.23 golang.org/x/crypto v0.21.0 golang.org/x/term v0.18.0 gopkg.in/yaml.v3 v3.0.1 diff --git a/go.sum b/go.sum index 87b0c805..181cb364 100644 --- a/go.sum +++ b/go.sum @@ -66,8 +66,8 @@ github.com/stretchr/testify v1.7.4/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/uselagoon/machinery v0.0.22 h1:4FVJRLS8he2NAZYMIJXQqVb25jQ03tF8dNhQbrBMX3g= -github.com/uselagoon/machinery v0.0.22/go.mod h1:NbgtEofjK2XY0iUpk9aMYazIo+W/NI56+UF72jv8zVY= +github.com/uselagoon/machinery v0.0.23 h1:8fRoVo3/dAByFQQH7Po35vEjFmtT4MmE326EuCkSvFc= +github.com/uselagoon/machinery v0.0.23/go.mod h1:NbgtEofjK2XY0iUpk9aMYazIo+W/NI56+UF72jv8zVY= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=