From 44613508af7487779af8f0a797390ffdf6281609 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Nov 2023 10:44:33 +0000 Subject: [PATCH 01/14] Bump github.com/auth0/go-auth0 from 1.2.0 to 1.3.0 (#908) Bumps [github.com/auth0/go-auth0](https://github.com/auth0/go-auth0) from 1.2.0 to 1.3.0. - [Release notes](https://github.com/auth0/go-auth0/releases) - [Changelog](https://github.com/auth0/go-auth0/blob/main/CHANGELOG.md) - [Commits](https://github.com/auth0/go-auth0/compare/v1.2.0...v1.3.0) --- updated-dependencies: - dependency-name: github.com/auth0/go-auth0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c8e27160a..3070443bd 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.20 require ( github.com/AlecAivazis/survey/v2 v2.3.7 github.com/PuerkitoBio/rehttp v1.3.0 - github.com/auth0/go-auth0 v1.2.0 + github.com/auth0/go-auth0 v1.3.0 github.com/briandowns/spinner v1.23.0 github.com/charmbracelet/glamour v0.6.0 github.com/fsnotify/fsnotify v1.7.0 diff --git a/go.sum b/go.sum index 0a663f00d..a6e48e491 100644 --- a/go.sum +++ b/go.sum @@ -18,8 +18,8 @@ github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/ github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= -github.com/auth0/go-auth0 v1.2.0 h1:pZWzWCWk038jDsItwfqrbuoN37xcNHUClfPzW+rk1ok= -github.com/auth0/go-auth0 v1.2.0/go.mod h1:tLH1Qv816g3dpqituiPNN4ET+YoNtk5++68aRg+MxaA= +github.com/auth0/go-auth0 v1.3.0 h1:46bo0C6HYtsdSj4BEF4j6IaQrSAiUqehwuv+IO3qDJ0= +github.com/auth0/go-auth0 v1.3.0/go.mod h1:gm0NUM340x77a9YVZB50HUrJJkSchD9DkiqqbAl+s34= github.com/aybabtme/iocontrol v0.0.0-20150809002002-ad15bcfc95a0 h1:0NmehRCgyk5rljDQLKUO+cRJCnduDyn11+zGZIc9Z48= github.com/aybabtme/iocontrol v0.0.0-20150809002002-ad15bcfc95a0/go.mod h1:6L7zgvqo0idzI7IO8de6ZC051AfXb5ipkIJ7bIA2tGA= github.com/aymanbagabas/go-osc52 v1.0.3 h1:DTwqENW7X9arYimJrPeGZcV0ln14sGMt3pHZspWD+Mg= From 205439459fbb500b6518083d5a2a9d181ca905a5 Mon Sep 17 00:00:00 2001 From: Michael Christenson II Date: Mon, 13 Nov 2023 12:10:00 -0500 Subject: [PATCH 02/14] dxcdt-615-goreleaser-upgrade (#909) * Fix: Remove or replace deprecations for GoReleaser config Remove deprecated replacements Replace deprecated brews tap Replace deprecated scoop entries Fix name_template to reflect exact current naming conventions * DXCDT-582: Convert audience into a drop down in interactive mode in test token cmd (#906) Convert audience into a drop down in interactive mode in test token cmd * Bump github.com/auth0/go-auth0 from 1.2.0 to 1.3.0 (#908) Bumps [github.com/auth0/go-auth0](https://github.com/auth0/go-auth0) from 1.2.0 to 1.3.0. - [Release notes](https://github.com/auth0/go-auth0/releases) - [Changelog](https://github.com/auth0/go-auth0/blob/main/CHANGELOG.md) - [Commits](https://github.com/auth0/go-auth0/compare/v1.2.0...v1.3.0) --- updated-dependencies: - dependency-name: github.com/auth0/go-auth0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --------- Signed-off-by: dependabot[bot] Co-authored-by: Sergiu Ghitea <28300158+sergiught@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .gitignore | 1 + .goreleaser.yml | 37 ++++++++++++++++--------------------- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/.gitignore b/.gitignore index a1560ab06..2d6eec10e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ /auth0 /test/integration/identifiers coverage* +/dist # Swap [._]*.s[a-v][a-z] diff --git a/.goreleaser.yml b/.goreleaser.yml index 2fdc5222f..e044543cc 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -18,12 +18,7 @@ builds: - -X 'github.com/auth0/auth0-cli/internal/buildinfo.BuildDate={{.Date}}' - -X 'github.com/auth0/auth0-cli/internal/instrumentation.SentryDSN={{.Env.SENTRY_DSN}}' archives: - - replacements: - darwin: Darwin - linux: Linux - windows: Windows - 386: i386 - amd64: x86_64 + - name_template: '{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ if eq .Arch "arm64" }}arm64{{ else }}x86_64{{ end }}' files: - none* format_overrides: @@ -37,7 +32,7 @@ changelog: skip: true brews: - name: auth0 - tap: + repository: owner: auth0 name: homebrew-auth0-cli commit_author: @@ -54,17 +49,17 @@ brews: (fish_completion/"auth0.fish").write `#{bin}/auth0 completion fish` (zsh_completion/"_auth0").write `#{bin}/auth0 completion zsh` caveats: "Thanks for installing the Auth0 CLI" -scoop: - name: auth0 - bucket: - owner: auth0 - name: scoop-auth0-cli - commit_author: - name: auth0 - email: support@auth0.com - commit_msg_template: "Scoop manifest update for {{ .ProjectName }} version {{ .Tag }}" - homepage: https://auth0.github.io/auth0-cli - description: Build, manage and test your Auth0 integrations from the command line - license: MIT - skip_upload: auto - post_install: ["Write-Host 'Thanks for installing the Auth0 CLI'"] +scoops: + - name: auth0 + repository: + owner: auth0 + name: scoop-auth0-cli + commit_author: + name: auth0 + email: support@auth0.com + commit_msg_template: "Scoop manifest update for {{ .ProjectName }} version {{ .Tag }}" + homepage: https://auth0.github.io/auth0-cli + description: Build, manage and test your Auth0 integrations from the command line + license: MIT + skip_upload: auto + post_install: ["Write-Host 'Thanks for installing the Auth0 CLI'"] From 1da363159ffebcde4680b5fc9c4c54d19ad83c1b Mon Sep 17 00:00:00 2001 From: Sergiu Ghitea <28300158+sergiught@users.noreply.github.com> Date: Sat, 11 Nov 2023 09:05:49 +0100 Subject: [PATCH 03/14] DXCDT-582: Convert audience into a drop down in interactive mode in test token cmd (#906) Convert audience into a drop down in interactive mode in test token cmd Title Os for final release name fit --- .goreleaser.yml | 2 +- docs/auth0_test_login.md | 2 +- docs/auth0_test_token.md | 2 +- internal/cli/test.go | 78 ++++++++++++++++++++++++++++++++++++---- 4 files changed, 75 insertions(+), 9 deletions(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index e044543cc..8b2e336e9 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -18,7 +18,7 @@ builds: - -X 'github.com/auth0/auth0-cli/internal/buildinfo.BuildDate={{.Date}}' - -X 'github.com/auth0/auth0-cli/internal/instrumentation.SentryDSN={{.Env.SENTRY_DSN}}' archives: - - name_template: '{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ if eq .Arch "arm64" }}arm64{{ else }}x86_64{{ end }}' + - name_template: '{{ .ProjectName }}_{{ .Version }}_{{ title .Os }}_{{ if eq .Arch "arm64" }}arm64{{ else }}x86_64{{ end }}' files: - none* format_overrides: diff --git a/docs/auth0_test_login.md b/docs/auth0_test_login.md index 6dd41ee08..27a031a53 100644 --- a/docs/auth0_test_login.md +++ b/docs/auth0_test_login.md @@ -30,7 +30,7 @@ auth0 test login [flags] ## Flags ``` - -a, --audience string The unique identifier of the target API you want to access. + -a, --audience string The unique identifier of the target API you want to access. For Machine to Machine and Regular Web Applications, only the enabled APIs will be shown within the interactive prompt. -c, --connection-name string The connection name to test during login. -d, --domain string One of your custom domains. --force Skip confirmation. diff --git a/docs/auth0_test_token.md b/docs/auth0_test_token.md index 5ad8e2850..cdc62f310 100644 --- a/docs/auth0_test_token.md +++ b/docs/auth0_test_token.md @@ -27,7 +27,7 @@ auth0 test token [flags] ## Flags ``` - -a, --audience string The unique identifier of the target API you want to access. + -a, --audience string The unique identifier of the target API you want to access. For Machine to Machine and Regular Web Applications, only the enabled APIs will be shown within the interactive prompt. --force Skip confirmation. --json Output in json format. -s, --scopes strings The list of scopes you want to use. diff --git a/internal/cli/test.go b/internal/cli/test.go index e8f59f29f..b17f9d40a 100644 --- a/internal/cli/test.go +++ b/internal/cli/test.go @@ -36,7 +36,7 @@ var ( Name: "Audience", LongForm: "audience", ShortForm: "a", - Help: "The unique identifier of the target API you want to access.", + Help: "The unique identifier of the target API you want to access. For Machine to Machine and Regular Web Applications, only the enabled APIs will be shown within the interactive prompt.", } testAudienceRequired = Flag{ @@ -193,18 +193,20 @@ func testTokenCmd(cli *cli) *cobra.Command { return err } - if err := testAudience.Ask(cmd, &inputs.Audience, nil); err != nil { + if err := testAudienceRequired.Pick( + cmd, + &inputs.Audience, + cli.audiencePickerOptions(client), + ); err != nil { return err } - appType := client.GetAppType() - cli.renderer.Infof("Domain : " + ansi.Blue(cli.tenant)) cli.renderer.Infof("Client ID : " + ansi.Bold(client.GetClientID())) - cli.renderer.Infof("Type : " + display.ApplyColorToFriendlyAppType(display.FriendlyAppType(appType))) + cli.renderer.Infof("Type : " + display.ApplyColorToFriendlyAppType(display.FriendlyAppType(client.GetAppType()))) cli.renderer.Newline() - if appType == appTypeNonInteractive { + if client.GetAppType() == appTypeNonInteractive { tokenResponse, err := runClientCredentialsFlow(cmd.Context(), cli, client, inputs.Audience, cli.tenant) if err != nil { return fmt.Errorf( @@ -342,6 +344,70 @@ func (c *cli) appPickerWithCreateOption(ctx context.Context) (pickerOptions, err return enhancedOptions, nil } +func (c *cli) audiencePickerOptions(client *management.Client) func(ctx context.Context) (pickerOptions, error) { + return func(ctx context.Context) (pickerOptions, error) { + var opts pickerOptions + + switch client.GetAppType() { + case "regular_web", "non_interactive": + clientGrants, err := c.api.ClientGrant.List( + ctx, + management.PerPage(100), + management.Parameter("client_id", client.GetClientID()), + ) + if err != nil { + return nil, err + } + + if len(clientGrants.ClientGrants) == 0 { + return nil, fmt.Errorf( + "the %s application is not authorized to request access tokens for any APIs.\n\n"+ + "Run: 'auth0 apps open %s' to open the dashboard and authorize the application.", + ansi.Bold(client.GetName()), + client.GetClientID(), + ) + } + + for _, grant := range clientGrants.ClientGrants { + resourceServer, err := c.api.ResourceServer.Read(ctx, grant.GetAudience()) + if err != nil { + return nil, err + } + + label := fmt.Sprintf( + "%s %s", + resourceServer.GetName(), + ansi.Faint(fmt.Sprintf("(%s)", resourceServer.GetIdentifier())), + ) + + opts = append(opts, pickerOption{ + label: label, + value: resourceServer.GetIdentifier(), + }) + } + default: + resourceServerList, err := c.api.ResourceServer.List(ctx, management.PerPage(100)) + if err != nil { + return nil, err + } + + for _, resourceServer := range resourceServerList.ResourceServers { + label := fmt.Sprintf( + "%s %s", + resourceServer.GetName(), + ansi.Faint(fmt.Sprintf("(%s)", resourceServer.GetIdentifier())), + ) + opts = append(opts, pickerOption{ + label: label, + value: resourceServer.GetIdentifier(), + }) + } + } + + return opts, nil + } +} + func checkClientIsAuthorizedForAPI(ctx context.Context, cli *cli, client *management.Client, audience string) error { var list *management.ClientGrantList if err := ansi.Waiting(func() (err error) { From 651dd2e26949705771c4110fb6cc885fa51ed7f1 Mon Sep 17 00:00:00 2001 From: Michael Christenson II Date: Thu, 30 Nov 2023 09:16:28 -0500 Subject: [PATCH 04/14] Added batch deletes to actions --- internal/cli/actions.go | 21 ++++++++++++------- internal/cli/arguments.go | 21 +++++++++++++++++++ internal/cli/input.go | 10 +++++++++ internal/cli/picker_options.go | 12 +++++++++++ ..._option_test.go => picker_options_test.go} | 16 ++++++++++++++ internal/prompt/prompt.go | 11 ++++++++++ 6 files changed, 83 insertions(+), 8 deletions(-) rename internal/cli/{picker_option_test.go => picker_options_test.go} (65%) diff --git a/internal/cli/actions.go b/internal/cli/actions.go index a73019cf4..20999caad 100644 --- a/internal/cli/actions.go +++ b/internal/cli/actions.go @@ -358,14 +358,10 @@ func updateActionCmd(cli *cli) *cobra.Command { } func deleteActionCmd(cli *cli) *cobra.Command { - var inputs struct { - ID string - } - cmd := &cobra.Command{ Use: "delete", Aliases: []string{"rm"}, - Args: cobra.MaximumNArgs(1), + Args: cobra.MinimumNArgs(0), Short: "Delete an action", Long: "Delete an action.\n\n" + "To delete interactively, use `auth0 actions delete` with no arguments.\n\n" + @@ -375,12 +371,15 @@ func deleteActionCmd(cli *cli) *cobra.Command { auth0 actions delete auth0 actions delete --force`, RunE: func(cmd *cobra.Command, args []string) error { + var ids []string if len(args) == 0 { - if err := actionID.Pick(cmd, &inputs.ID, cli.actionPickerOptions); err != nil { + if err := actionID.PickMany(cmd, &ids, cli.actionPickerOptions); err != nil { return err } } else { - inputs.ID = args[0] + for _, id := range args[0:] { + ids = append(ids, id) + } } if !cli.force && canPrompt(cmd) { @@ -390,7 +389,13 @@ func deleteActionCmd(cli *cli) *cobra.Command { } return ansi.Spinner("Deleting action", func() error { - return cli.api.Action.Delete(cmd.Context(), inputs.ID) + var errs []error + for _, id := range ids { + if err := cli.api.Action.Delete(cmd.Context(), id); err != nil { + errs = append(errs, err) + } + } + return errors.Join(errs...) }) }, } diff --git a/internal/cli/arguments.go b/internal/cli/arguments.go index a3f04ec39..9897768d0 100644 --- a/internal/cli/arguments.go +++ b/internal/cli/arguments.go @@ -58,6 +58,27 @@ func (a *Argument) Pick(cmd *cobra.Command, result *string, fn pickerOptionsFunc return nil } +func (a *Argument) PickMany(cmd *cobra.Command, result *[]string, fn pickerOptionsFunc) error { + var opts pickerOptions + err := ansi.Waiting(func() error { + var err error + opts, err = fn(cmd.Context()) + return err + }) + + if err != nil { + return err + } + + var values []string + if err := askMultiSelect(a, &values, false, opts.labels()...); err != nil { + return err + } + + *result = opts.getValues(values...) + return nil +} + func selectArgument(cmd *cobra.Command, a *Argument, value interface{}, options []string, defaultValue *string) error { if canPrompt(cmd) { return _select(a, value, options, defaultValue, false) diff --git a/internal/cli/input.go b/internal/cli/input.go index 32d9d7ac6..e2ed018cf 100644 --- a/internal/cli/input.go +++ b/internal/cli/input.go @@ -58,6 +58,16 @@ func askPassword(i commandInput, value interface{}, isUpdate bool) error { return nil } +func askMultiSelect(i commandInput, value interface{}, isUpdate bool, options ...string) error { + _ = isInputRequired(i, isUpdate) // TODO: handle isRequired + + if err := prompt.AskMultiSelect(i.GetLabel(), value, options...); err != nil { + handleInputError(err) + } + + return nil +} + func _select(i commandInput, value interface{}, options []string, defaultValue *string, isUpdate bool) error { isRequired := isInputRequired(i, isUpdate) diff --git a/internal/cli/picker_options.go b/internal/cli/picker_options.go index e73d431ad..4feef793e 100644 --- a/internal/cli/picker_options.go +++ b/internal/cli/picker_options.go @@ -1,5 +1,7 @@ package cli +import "slices" + type pickerOptions []pickerOption func (p pickerOptions) labels() []string { @@ -26,6 +28,16 @@ func (p pickerOptions) getValue(label string) string { return "" } +func (p pickerOptions) getValues(labels ...string) []string { + var values []string + for _, o := range p { + if i := slices.Index(labels, o.label); i > -1 { + values = append(values, o.value) + } + } + return values +} + type pickerOption struct { label string value string diff --git a/internal/cli/picker_option_test.go b/internal/cli/picker_options_test.go similarity index 65% rename from internal/cli/picker_option_test.go rename to internal/cli/picker_options_test.go index 93b0e0068..2ad163e45 100644 --- a/internal/cli/picker_option_test.go +++ b/internal/cli/picker_options_test.go @@ -46,4 +46,20 @@ func TestPickerOptions(t *testing.T) { assert.Equal(t, want, got) }) + + t.Run("return the values for a given set of labels", func(t *testing.T) { + options := pickerOptions{pickerOption{label: "Foo", value: "0"}, pickerOption{label: "Bar", value: "1"}, pickerOption{label: "Baz", value: "2"}} + want := []string{"0", "2"} + got := options.getValues("Foo", "Fizz") + + assert.Equal(t, want, got) + }) + + t.Run("returns empty values for a given set of non-existant labels", func(t *testing.T) { + options := pickerOptions{pickerOption{label: "Foo", value: "0"}, pickerOption{label: "Bar", value: "1"}, pickerOption{label: "Baz", value: "2"}} + want := []string(nil) + got := options.getValues("Buz") + + assert.Equal(t, want, got) + }) } diff --git a/internal/prompt/prompt.go b/internal/prompt/prompt.go index 45ae3936a..2d2598962 100644 --- a/internal/prompt/prompt.go +++ b/internal/prompt/prompt.go @@ -24,6 +24,17 @@ func askOne(prompt survey.Prompt, response interface{}) error { return survey.AskOne(prompt, response, stdErrWriter, Icons) } +func AskMultiSelect(message string, response interface{}, options ...string) error { + prompt := &survey.MultiSelect{ + Message: message, + Options: options, + } + + err := askOne(prompt, response) + + return err +} + func AskBool(message string, value *bool, defaultValue bool) error { prompt := &survey.Confirm{ Message: message, From 70123ac96b297a2618f56e76d0dd4a5dd81ef5f9 Mon Sep 17 00:00:00 2001 From: Michael Christenson II Date: Thu, 30 Nov 2023 09:16:28 -0500 Subject: [PATCH 05/14] Add batch deletions Added batch deletion to actions command Added batch deletion to apis command Added batch deletion to apps command Added batch deletion to custom domains command Added batch deletion to log streams command Added batch deletion for organizations command Added batch deletion for roles command Added batch deletion for rules command Added batch deletion for users non-interactive command Added batch deletion for user blocks non-interactive command Update required golang minimum version --- go.mod | 2 +- internal/cli/actions.go | 2 +- internal/cli/apis.go | 28 +++++++++++++++------------- internal/cli/apps.go | 28 ++++++++++++++++------------ internal/cli/custom_domains.go | 29 +++++++++++++++++------------ internal/cli/log_streams.go | 27 +++++++++++++++------------ internal/cli/organizations.go | 27 +++++++++++++++------------ internal/cli/roles.go | 27 +++++++++++++++------------ internal/cli/rules.go | 31 +++++++++++++++++-------------- internal/cli/users.go | 29 +++++++++++++++++------------ internal/cli/users_blocks.go | 31 +++++++++++++++++-------------- 11 files changed, 146 insertions(+), 115 deletions(-) diff --git a/go.mod b/go.mod index 3bdffe579..2847f6e0b 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/auth0/auth0-cli -go 1.20 +go 1.21 require ( github.com/AlecAivazis/survey/v2 v2.3.7 diff --git a/internal/cli/actions.go b/internal/cli/actions.go index 20999caad..12994ded4 100644 --- a/internal/cli/actions.go +++ b/internal/cli/actions.go @@ -371,7 +371,7 @@ func deleteActionCmd(cli *cli) *cobra.Command { auth0 actions delete auth0 actions delete --force`, RunE: func(cmd *cobra.Command, args []string) error { - var ids []string + ids := make([]string, len(args)) if len(args) == 0 { if err := actionID.PickMany(cmd, &ids, cli.actionPickerOptions); err != nil { return err diff --git a/internal/cli/apis.go b/internal/cli/apis.go index ffb91f9a4..f68cc9e67 100644 --- a/internal/cli/apis.go +++ b/internal/cli/apis.go @@ -390,14 +390,10 @@ func updateAPICmd(cli *cli) *cobra.Command { } func deleteAPICmd(cli *cli) *cobra.Command { - var inputs struct { - ID string - } - cmd := &cobra.Command{ Use: "delete", Aliases: []string{"rm"}, - Args: cobra.MaximumNArgs(1), + Args: cobra.MinimumNArgs(0), Short: "Delete an API", Long: "Delete an API.\n\n" + "To delete interactively, use `auth0 apis delete` with no arguments.\n\n" + @@ -407,13 +403,15 @@ func deleteAPICmd(cli *cli) *cobra.Command { auth0 apis delete auth0 apis delete --force`, RunE: func(cmd *cobra.Command, args []string) error { + var ids []string if len(args) == 0 { - err := apiID.Pick(cmd, &inputs.ID, cli.apiPickerOptions) - if err != nil { + if err := apiID.PickMany(cmd, &ids, cli.apiPickerOptions); err != nil { return err } } else { - inputs.ID = args[0] + for _, id := range args[0:] { + ids = append(ids, id) + } } if !cli.force && canPrompt(cmd) { @@ -423,13 +421,17 @@ func deleteAPICmd(cli *cli) *cobra.Command { } return ansi.Spinner("Deleting API", func() error { - _, err := cli.api.ResourceServer.Read(cmd.Context(), url.PathEscape(inputs.ID)) + var errs []error + for _, id := range ids { + if _, err := cli.api.ResourceServer.Read(cmd.Context(), url.PathEscape(id)); err != nil { + errs = append(errs, fmt.Errorf("Unable to read API for deletion: %w", err)) + } - if err != nil { - return fmt.Errorf("Unable to delete API: %w", err) + if err := cli.api.ResourceServer.Delete(cmd.Context(), url.PathEscape(id)); err != nil { + errs = append(errs, fmt.Errorf("Unable to delete API: %w", err)) + } } - - return cli.api.ResourceServer.Delete(cmd.Context(), url.PathEscape(inputs.ID)) + return errors.Join(errs...) }) }, } diff --git a/internal/cli/apps.go b/internal/cli/apps.go index 6eb76c7ea..d39bd5e9e 100644 --- a/internal/cli/apps.go +++ b/internal/cli/apps.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "net/url" "strings" "github.com/auth0/go-auth0/management" @@ -302,14 +303,10 @@ func showAppCmd(cli *cli) *cobra.Command { } func deleteAppCmd(cli *cli) *cobra.Command { - var inputs struct { - ID string - } - cmd := &cobra.Command{ Use: "delete", Aliases: []string{"rm"}, - Args: cobra.MaximumNArgs(1), + Args: cobra.MinimumNArgs(0), Short: "Delete an application", Long: "Delete an application.\n\n" + "To delete interactively, use `auth0 apps delete` with no arguments.\n\n" + @@ -320,13 +317,16 @@ func deleteAppCmd(cli *cli) *cobra.Command { auth0 apps delete auth0 apps delete --force`, RunE: func(cmd *cobra.Command, args []string) error { + ids := make([]string, len(args)) if len(args) == 0 { - err := appID.Pick(cmd, &inputs.ID, cli.appPickerOptions()) + err := appID.PickMany(cmd, &ids, cli.appPickerOptions()) if err != nil { return err } } else { - inputs.ID = args[0] + for _, id := range args[0:] { + ids = append(ids, id) + } } if !cli.force && canPrompt(cmd) { @@ -336,13 +336,17 @@ func deleteAppCmd(cli *cli) *cobra.Command { } return ansi.Spinner("Deleting Application", func() error { - _, err := cli.api.Client.Read(cmd.Context(), inputs.ID) + var errs []error + for _, id := range ids { + if _, err := cli.api.Client.Read(cmd.Context(), url.PathEscape(id)); err != nil { + errs = append(errs, fmt.Errorf("Unable to read application for deletion: %w", err)) + } - if err != nil { - return fmt.Errorf("Unable to delete application: %w", err) + if err := cli.api.Client.Delete(cmd.Context(), url.PathEscape(id)); err != nil { + errs = append(errs, fmt.Errorf("Unable to delete application: %w", err)) + } } - - return cli.api.Client.Delete(cmd.Context(), inputs.ID) + return errors.Join(errs...) }) }, } diff --git a/internal/cli/custom_domains.go b/internal/cli/custom_domains.go index f651204c6..d5e348e0c 100644 --- a/internal/cli/custom_domains.go +++ b/internal/cli/custom_domains.go @@ -2,6 +2,7 @@ package cli import ( "context" + "errors" "fmt" "net/url" @@ -323,14 +324,10 @@ func updateCustomDomainCmd(cli *cli) *cobra.Command { } func deleteCustomDomainCmd(cli *cli) *cobra.Command { - var inputs struct { - ID string - } - cmd := &cobra.Command{ Use: "delete", Aliases: []string{"rm"}, - Args: cobra.MaximumNArgs(1), + Args: cobra.MinimumNArgs(0), Short: "Delete a custom domain", Long: "Delete a custom domain.\n\n" + "To delete interactively, use `auth0 domains delete` with no arguments.\n\n" + @@ -341,13 +338,16 @@ func deleteCustomDomainCmd(cli *cli) *cobra.Command { auth0 domains delete auth0 domains delete --force`, RunE: func(cmd *cobra.Command, args []string) error { + ids := make([]string, len(args)) if len(args) == 0 { - err := customDomainID.Pick(cmd, &inputs.ID, cli.customDomainsPickerOptions) + err := customDomainID.PickMany(cmd, &ids, cli.customDomainsPickerOptions) if err != nil { return err } } else { - inputs.ID = args[0] + for _, id := range args[0:] { + ids = append(ids, id) + } } if !cli.force && canPrompt(cmd) { @@ -357,13 +357,18 @@ func deleteCustomDomainCmd(cli *cli) *cobra.Command { } return ansi.Spinner("Deleting custom domain", func() error { - _, err := cli.api.CustomDomain.Read(cmd.Context(), url.PathEscape(inputs.ID)) - - if err != nil { - return fmt.Errorf("Unable to delete custom domain: %w", err) + var errs []error + for _, id := range ids { + if _, err := cli.api.CustomDomain.Read(cmd.Context(), url.PathEscape(id)); err != nil { + return fmt.Errorf("Unable to read custom domain for deletion: %w", err) + } + + if err := cli.api.CustomDomain.Delete(cmd.Context(), url.PathEscape(id)); err != nil { + return fmt.Errorf("Unable to delete custom domain: %w", err) + } } - return cli.api.CustomDomain.Delete(cmd.Context(), url.PathEscape(inputs.ID)) + return errors.Join(errs...) }) }, } diff --git a/internal/cli/log_streams.go b/internal/cli/log_streams.go index 64d671016..6d4a497e1 100644 --- a/internal/cli/log_streams.go +++ b/internal/cli/log_streams.go @@ -168,14 +168,10 @@ func updateLogStreamCmd(cli *cli) *cobra.Command { } func deleteLogStreamCmd(cli *cli) *cobra.Command { - var inputs struct { - ID string - } - cmd := &cobra.Command{ Use: "delete", Aliases: []string{"rm"}, - Args: cobra.MaximumNArgs(1), + Args: cobra.MinimumNArgs(0), Short: "Delete a log stream", Long: "Delete a log stream.\n\n" + "To delete interactively, use `auth0 logs streams delete` with no arguments.\n\n" + @@ -186,13 +182,16 @@ func deleteLogStreamCmd(cli *cli) *cobra.Command { auth0 logs streams delete auth0 logs streams delete --force`, RunE: func(cmd *cobra.Command, args []string) error { + ids := make([]string, len(args)) if len(args) == 0 { - err := logStreamID.Pick(cmd, &inputs.ID, cli.allLogStreamsPickerOptions) + err := logStreamID.PickMany(cmd, &ids, cli.allLogStreamsPickerOptions) if err != nil { return err } } else { - inputs.ID = args[0] + for _, id := range args[0:] { + ids = append(ids, id) + } } if !cli.force && canPrompt(cmd) { @@ -202,13 +201,17 @@ func deleteLogStreamCmd(cli *cli) *cobra.Command { } return ansi.Spinner("Deleting Log Stream", func() error { - _, err := cli.api.LogStream.Read(cmd.Context(), inputs.ID) - - if err != nil { - return fmt.Errorf("Unable to delete log stream: %w", err) + var errs []error + for _, id := range ids { + if _, err := cli.api.LogStream.Read(cmd.Context(), id); err != nil { + errs = append(errs, fmt.Errorf("Unable to read log stream for deletion: %w", err)) + } + if err := cli.api.LogStream.Delete(cmd.Context(), id); err != nil { + errs = append(errs, fmt.Errorf("Unable to delete log stream: %w", err)) + } } - return cli.api.LogStream.Delete(cmd.Context(), inputs.ID) + return errors.Join(errs...) }) }, } diff --git a/internal/cli/organizations.go b/internal/cli/organizations.go index ba5192eb3..71795c99c 100644 --- a/internal/cli/organizations.go +++ b/internal/cli/organizations.go @@ -408,14 +408,10 @@ func updateOrganizationCmd(cli *cli) *cobra.Command { } func deleteOrganizationCmd(cli *cli) *cobra.Command { - var inputs struct { - ID string - } - cmd := &cobra.Command{ Use: "delete", Aliases: []string{"rm"}, - Args: cobra.MaximumNArgs(1), + Args: cobra.MinimumNArgs(0), Short: "Delete an organization", Long: "Delete an organization.\n\n" + "To delete interactively, use `auth0 orgs delete` with no arguments.\n\n" + @@ -426,13 +422,16 @@ func deleteOrganizationCmd(cli *cli) *cobra.Command { auth0 orgs delete auth0 orgs delete --force`, RunE: func(cmd *cobra.Command, args []string) error { + ids := make([]string, len(args)) if len(args) == 0 { - err := organizationID.Pick(cmd, &inputs.ID, cli.organizationPickerOptions) + err := organizationID.PickMany(cmd, &ids, cli.organizationPickerOptions) if err != nil { return err } } else { - inputs.ID = args[0] + for _, id := range args { + ids = append(ids, id) + } } if !cli.force && canPrompt(cmd) { @@ -442,13 +441,17 @@ func deleteOrganizationCmd(cli *cli) *cobra.Command { } return ansi.Spinner("Deleting organization", func() error { - _, err := cli.api.Organization.Read(cmd.Context(), url.PathEscape(inputs.ID)) + var errs []error + for _, id := range ids { + if _, err := cli.api.Organization.Read(cmd.Context(), url.PathEscape(id)); err != nil { + errs = append(errs, fmt.Errorf("Unable to read organization for deletion: %w", err)) + } - if err != nil { - return fmt.Errorf("Unable to delete organization: %w", err) + if err := cli.api.Organization.Delete(cmd.Context(), url.PathEscape(id)); err != nil { + errs = append(errs, fmt.Errorf("Unable to delete organization: %w", err)) + } } - - return cli.api.Organization.Delete(cmd.Context(), url.PathEscape(inputs.ID)) + return errors.Join(errs...) }) }, } diff --git a/internal/cli/roles.go b/internal/cli/roles.go index 96e25e420..c4789a6ef 100644 --- a/internal/cli/roles.go +++ b/internal/cli/roles.go @@ -282,14 +282,10 @@ func updateRoleCmd(cli *cli) *cobra.Command { } func deleteRoleCmd(cli *cli) *cobra.Command { - var inputs struct { - ID string - } - cmd := &cobra.Command{ Use: "delete", Aliases: []string{"rm"}, - Args: cobra.MaximumNArgs(1), + Args: cobra.MinimumNArgs(0), Short: "Delete a role", Long: "Delete a role.\n\n" + "To delete interactively, use `auth0 roles delete`.\n\n" + @@ -299,13 +295,16 @@ func deleteRoleCmd(cli *cli) *cobra.Command { auth0 roles delete auth0 roles delete --force`, RunE: func(cmd *cobra.Command, args []string) error { + ids := make([]string, len(args)) if len(args) == 0 { - err := roleID.Pick(cmd, &inputs.ID, cli.rolePickerOptions) + err := roleID.PickMany(cmd, &ids, cli.rolePickerOptions) if err != nil { return err } } else { - inputs.ID = args[0] + for _, id := range args { + ids = append(ids, id) + } } if !cli.force && canPrompt(cmd) { @@ -315,13 +314,17 @@ func deleteRoleCmd(cli *cli) *cobra.Command { } return ansi.Spinner("Deleting Role", func() error { - _, err := cli.api.Role.Read(cmd.Context(), inputs.ID) + var errs []error + for _, id := range ids { + if _, err := cli.api.Role.Read(cmd.Context(), id); err != nil { + errs = append(errs, fmt.Errorf("Unable to read role for deletion: %w", err)) + } - if err != nil { - return fmt.Errorf("Unable to delete role: %w", err) + if err := cli.api.Role.Delete(cmd.Context(), id); err != nil { + errs = append(errs, fmt.Errorf("Unable to delete role: %w", err)) + } } - - return cli.api.Role.Delete(cmd.Context(), inputs.ID) + return errors.Join(errs...) }) }, } diff --git a/internal/cli/rules.go b/internal/cli/rules.go index ac2f9d20b..a357416be 100644 --- a/internal/cli/rules.go +++ b/internal/cli/rules.go @@ -249,14 +249,10 @@ func showRuleCmd(cli *cli) *cobra.Command { } func deleteRuleCmd(cli *cli) *cobra.Command { - var inputs struct { - ID string - } - cmd := &cobra.Command{ Use: "delete", Aliases: []string{"rm"}, - Args: cobra.MaximumNArgs(1), + Args: cobra.MinimumNArgs(0), Short: "Delete a rule", Long: rulesDeprecationDocumentationText + "Delete a rule.\n\n" + "To delete interactively, use `auth0 rules delete` with no arguments.\n\n" + @@ -266,13 +262,16 @@ func deleteRuleCmd(cli *cli) *cobra.Command { auth0 rules delete auth0 rules delete --force`, RunE: func(cmd *cobra.Command, args []string) error { - if len(args) > 0 { - inputs.ID = args[0] - } else { - err := ruleID.Pick(cmd, &inputs.ID, cli.rulePickerOptions) + ids := make([]string, len(args)) + if len(args) == 0 { + err := ruleID.PickMany(cmd, &ids, cli.rulePickerOptions) if err != nil { return err } + } else { + for _, id := range args { + ids = append(ids, id) + } } if !cli.force && canPrompt(cmd) { @@ -282,13 +281,17 @@ func deleteRuleCmd(cli *cli) *cobra.Command { } return ansi.Spinner("Deleting Rule", func() error { - _, err := cli.api.Rule.Read(cmd.Context(), inputs.ID) + var errs []error + for _, id := range ids { + if _, err := cli.api.Rule.Read(cmd.Context(), id); err != nil { + errs = append(errs, fmt.Errorf("Unable to read rule for deletion: %w", err)) + } - if err != nil { - return fmt.Errorf("Unable to delete rule: %w", err) + if err := cli.api.Rule.Delete(cmd.Context(), id); err != nil { + errs = append(errs, fmt.Errorf("Unable to delete rule: %w", err)) + } } - - return cli.api.Rule.Delete(cmd.Context(), inputs.ID) + return errors.Join(errs...) }) }, } diff --git a/internal/cli/users.go b/internal/cli/users.go index 1e2fad6b6..9d95e6831 100644 --- a/internal/cli/users.go +++ b/internal/cli/users.go @@ -357,14 +357,10 @@ func showUserCmd(cli *cli) *cobra.Command { } func deleteUserCmd(cli *cli) *cobra.Command { - var inputs struct { - ID string - } - cmd := &cobra.Command{ Use: "delete", Aliases: []string{"rm"}, - Args: cobra.MaximumNArgs(1), + Args: cobra.MinimumNArgs(0), Short: "Delete a user", Long: "Delete a user.\n\n" + "To delete interactively, use `auth0 users delete` with no arguments.\n\n" + @@ -374,12 +370,17 @@ func deleteUserCmd(cli *cli) *cobra.Command { auth0 users delete auth0 users delete --force`, RunE: func(cmd *cobra.Command, args []string) error { + ids := make([]string, len(args)) if len(args) == 0 { - if err := userID.Ask(cmd, &inputs.ID); err != nil { + var id string + if err := userID.Ask(cmd, &id); err != nil { return err } + ids = append(ids, id) } else { - inputs.ID = args[0] + for _, id := range args { + ids = append(ids, id) + } } if !cli.force && canPrompt(cmd) { @@ -389,13 +390,17 @@ func deleteUserCmd(cli *cli) *cobra.Command { } return ansi.Spinner("Deleting user", func() error { - _, err := cli.api.User.Read(cmd.Context(), inputs.ID) + var errs []error + for _, id := range ids { + if _, err := cli.api.User.Read(cmd.Context(), id); err != nil { + errs = append(errs, fmt.Errorf("Unable to read user for deletion: %w", err)) + } - if err != nil { - return fmt.Errorf("Unable to delete user: %w", err) + if err := cli.api.User.Delete(cmd.Context(), id); err != nil { + errs = append(errs, fmt.Errorf("Unable to delete user: %w", err)) + } } - - return cli.api.User.Delete(cmd.Context(), inputs.ID) + return errors.Join(errs...) }) }, } diff --git a/internal/cli/users_blocks.go b/internal/cli/users_blocks.go index 657a930cf..8eb75a83f 100644 --- a/internal/cli/users_blocks.go +++ b/internal/cli/users_blocks.go @@ -1,6 +1,7 @@ package cli import ( + "errors" "fmt" "github.com/auth0/go-auth0/management" @@ -64,33 +65,35 @@ func listUserBlocksCmd(cli *cli) *cobra.Command { } func deleteUserBlocksCmd(cli *cli) *cobra.Command { - var inputs struct { - userID string - } - cmd := &cobra.Command{ Use: "unblock", - Args: cobra.MaximumNArgs(1), + Args: cobra.MinimumNArgs(0), Short: "Remove brute-force protection blocks for a given user", Long: "Remove brute-force protection blocks for a given user.", Example: ` auth0 users blocks unblock `, RunE: func(cmd *cobra.Command, args []string) error { + ids := make([]string, len(args)) if len(args) == 0 { - if err := userID.Ask(cmd, &inputs.userID); err != nil { + var id string + if err := userID.Ask(cmd, &id); err != nil { return err } + ids = append(ids, id) } else { - inputs.userID = args[0] + for _, id := range args { + ids = append(ids, id) + } } - err := ansi.Spinner("Unblocking user...", func() error { - return cli.api.User.Unblock(cmd.Context(), inputs.userID) + return ansi.Spinner("Unblocking user...", func() error { + var errs []error + for _, id := range ids { + if err := cli.api.User.Unblock(cmd.Context(), id); err != nil { + errs = append(errs, fmt.Errorf("failed to unblock user with ID %s: %w", id, err)) + } + } + return errors.Join(errs...) }) - if err != nil { - return fmt.Errorf("failed to unblock user with ID %s: %w", inputs.userID, err) - } - - return nil }, } From cd2247142349efd0bfe1161a05abbdff917d2fef Mon Sep 17 00:00:00 2001 From: Sergiu Ghitea <28300158+sergiught@users.noreply.github.com> Date: Thu, 30 Nov 2023 17:50:59 +0100 Subject: [PATCH 06/14] DXCDT-595: Add ability to update signing alg for apis (#926) * Add ability to update signing alg for apis * Removing short alias --------- Co-authored-by: Will Vedder --- docs/auth0_apis_create.md | 4 +- docs/auth0_apis_update.md | 5 +- internal/cli/apis.go | 86 +++++++++++++++++---------- internal/display/apis.go | 30 +++++----- test/integration/apis-test-cases.yaml | 13 +++- 5 files changed, 87 insertions(+), 51 deletions(-) diff --git a/docs/auth0_apis_create.md b/docs/auth0_apis_create.md index 1e23ac5d0..3de450543 100644 --- a/docs/auth0_apis_create.md +++ b/docs/auth0_apis_create.md @@ -25,7 +25,8 @@ auth0 apis create [flags] auth0 apis create --name myapi --identifier http://my-api --token-lifetime 6100 auth0 apis create --name myapi --identifier http://my-api --token-lifetime 6100 --offline-access=true auth0 apis create --name myapi --identifier http://my-api --token-lifetime 6100 --offline-access=false --scopes "letter:write,letter:read" - auth0 apis create -n myapi -i http://my-api -t 6100 -o false -s "letter:write,letter:read" --json + auth0 apis create --name myapi --identifier http://my-api --token-lifetime 6100 --offline-access=false --scopes "letter:write,letter:read" --signing-alg "RS256" + auth0 apis create -n myapi -i http://my-api -t 6100 -o false -s "letter:write,letter:read" --signing-alg "RS256" --json ``` @@ -37,6 +38,7 @@ auth0 apis create [flags] -n, --name string Name of the API. -o, --offline-access Whether Refresh Tokens can be issued for this API (true) or not (false). -s, --scopes strings Comma-separated list of scopes (permissions). + --signing-alg string Algorithm used to sign JWTs. Can be HS256 or RS256. PS256 available via addon. (default "RS256") -l, --token-lifetime int The amount of time in seconds that the token will be valid after being issued. Default value is 86400 seconds (1 day). ``` diff --git a/docs/auth0_apis_update.md b/docs/auth0_apis_update.md index 1419f0c06..b0b637901 100644 --- a/docs/auth0_apis_update.md +++ b/docs/auth0_apis_update.md @@ -24,8 +24,8 @@ auth0 apis update [flags] auth0 apis update --name myapi auth0 apis update --name myapi --token-lifetime 6100 auth0 apis update --name myapi --token-lifetime 6100 --offline-access=false - auth0 apis update --name myapi --token-lifetime 6100 --offline-access=false --scopes "letter:write,letter:read" - auth0 apis update -n myapi -t 6100 -o false -s "letter:write,letter:read" --json + auth0 apis update --name myapi --token-lifetime 6100 --offline-access=false --scopes "letter:write,letter:read" --signing-alg "RS256" + auth0 apis update -n myapi -t 6100 -o false -s "letter:write,letter:read" --signing-alg "RS256" --json ``` @@ -36,6 +36,7 @@ auth0 apis update [flags] -n, --name string Name of the API. -o, --offline-access Whether Refresh Tokens can be issued for this API (true) or not (false). -s, --scopes strings Comma-separated list of scopes (permissions). + --signing-alg string Algorithm used to sign JWTs. Can be HS256 or RS256. PS256 available via addon. (default "RS256") -l, --token-lifetime int The amount of time in seconds that the token will be valid after being issued. Default value is 86400 seconds (1 day). ``` diff --git a/internal/cli/apis.go b/internal/cli/apis.go index f68cc9e67..3fd96a1da 100644 --- a/internal/cli/apis.go +++ b/internal/cli/apis.go @@ -15,6 +15,8 @@ import ( "github.com/auth0/auth0-cli/internal/prompt" ) +const apiDefaultTokenLifetime = 86400 + var ( apiID = Argument{ Name: "Id", @@ -55,6 +57,11 @@ var ( Help: "Whether Refresh Tokens can be issued for this API (true) or not (false).", AlwaysPrompt: true, } + apiSigningAlgorithm = Flag{ + Name: "Signing Algorithm", + LongForm: "signing-alg", + Help: "Algorithm used to sign JWTs. Can be HS256 or RS256. PS256 available via addon.", + } apiNumber = Flag{ Name: "Number", LongForm: "number", @@ -204,6 +211,7 @@ func createAPICmd(cli *cli) *cobra.Command { Scopes []string TokenLifetime int AllowOfflineAccess bool + SigningAlgorithm string } cmd := &cobra.Command{ @@ -220,7 +228,8 @@ func createAPICmd(cli *cli) *cobra.Command { auth0 apis create --name myapi --identifier http://my-api --token-lifetime 6100 auth0 apis create --name myapi --identifier http://my-api --token-lifetime 6100 --offline-access=true auth0 apis create --name myapi --identifier http://my-api --token-lifetime 6100 --offline-access=false --scopes "letter:write,letter:read" - auth0 apis create -n myapi -i http://my-api -t 6100 -o false -s "letter:write,letter:read" --json`, + auth0 apis create --name myapi --identifier http://my-api --token-lifetime 6100 --offline-access=false --scopes "letter:write,letter:read" --signing-alg "RS256" + auth0 apis create -n myapi -i http://my-api -t 6100 -o false -s "letter:write,letter:read" --signing-alg "RS256" --json`, RunE: func(cmd *cobra.Command, args []string) error { if err := apiName.Ask(cmd, &inputs.Name, nil); err != nil { return err @@ -234,7 +243,7 @@ func createAPICmd(cli *cli) *cobra.Command { return err } - defaultTokenLifetime := strconv.Itoa(apiDefaultTokenLifetime()) + defaultTokenLifetime := strconv.Itoa(apiDefaultTokenLifetime) if err := apiTokenLifetime.Ask(cmd, &inputs.TokenLifetime, &defaultTokenLifetime); err != nil { return err } @@ -243,20 +252,24 @@ func createAPICmd(cli *cli) *cobra.Command { return err } + if err := apiSigningAlgorithm.Ask(cmd, &inputs.SigningAlgorithm, auth0.String("RS256")); err != nil { + return err + } + api := &management.ResourceServer{ Name: &inputs.Name, Identifier: &inputs.Identifier, AllowOfflineAccess: &inputs.AllowOfflineAccess, TokenLifetime: &inputs.TokenLifetime, + SigningAlgorithm: &inputs.SigningAlgorithm, } if len(inputs.Scopes) > 0 { api.Scopes = apiScopesFor(inputs.Scopes) } - // Set token lifetime if inputs.TokenLifetime <= 0 { - api.TokenLifetime = auth0.Int(apiDefaultTokenLifetime()) + api.TokenLifetime = auth0.Int(apiDefaultTokenLifetime) } else { api.TokenLifetime = auth0.Int(inputs.TokenLifetime) } @@ -264,10 +277,16 @@ func createAPICmd(cli *cli) *cobra.Command { if err := ansi.Waiting(func() error { return cli.api.ResourceServer.Create(cmd.Context(), api) }); err != nil { - return fmt.Errorf("An unexpected error occurred while attempting to create an API with name '%s' and identifier '%s': %w", inputs.Name, inputs.Identifier, err) + return fmt.Errorf( + "failed to create an API with name '%s' and identifier '%s': %w", + inputs.Name, + inputs.Identifier, + err, + ) } cli.renderer.APICreate(api) + return nil }, } @@ -278,6 +297,7 @@ func createAPICmd(cli *cli) *cobra.Command { apiScopes.RegisterStringSlice(cmd, &inputs.Scopes, nil) apiOfflineAccess.RegisterBool(cmd, &inputs.AllowOfflineAccess, false) apiTokenLifetime.RegisterInt(cmd, &inputs.TokenLifetime, 0) + apiSigningAlgorithm.RegisterString(cmd, &inputs.SigningAlgorithm, "RS256") return cmd } @@ -289,6 +309,7 @@ func updateAPICmd(cli *cli) *cobra.Command { Scopes []string TokenLifetime int AllowOfflineAccess bool + SigningAlgorithm string } cmd := &cobra.Command{ @@ -304,26 +325,23 @@ func updateAPICmd(cli *cli) *cobra.Command { auth0 apis update --name myapi auth0 apis update --name myapi --token-lifetime 6100 auth0 apis update --name myapi --token-lifetime 6100 --offline-access=false - auth0 apis update --name myapi --token-lifetime 6100 --offline-access=false --scopes "letter:write,letter:read" - auth0 apis update -n myapi -t 6100 -o false -s "letter:write,letter:read" --json`, + auth0 apis update --name myapi --token-lifetime 6100 --offline-access=false --scopes "letter:write,letter:read" --signing-alg "RS256" + auth0 apis update -n myapi -t 6100 -o false -s "letter:write,letter:read" --signing-alg "RS256" --json`, RunE: func(cmd *cobra.Command, args []string) error { - var current *management.ResourceServer - if len(args) == 0 { - err := apiID.Pick(cmd, &inputs.ID, cli.apiPickerOptions) - if err != nil { + if err := apiID.Pick(cmd, &inputs.ID, cli.apiPickerOptions); err != nil { return err } } else { inputs.ID = args[0] } - if err := ansi.Waiting(func() error { - var err error - current, err = cli.api.ResourceServer.Read(cmd.Context(), url.PathEscape(inputs.ID)) + var current *management.ResourceServer + if err := ansi.Waiting(func() (err error) { + current, err = cli.api.ResourceServer.Read(cmd.Context(), inputs.ID) return err }); err != nil { - return fmt.Errorf("Unable to load API: %w", err) + return fmt.Errorf("failed to find API with ID %q: %w", inputs.ID, err) } if err := apiName.AskU(cmd, &inputs.Name, current.Name); err != nil { @@ -334,48 +352,55 @@ func updateAPICmd(cli *cli) *cobra.Command { return err } - currentTokenLifetime := strconv.Itoa(auth0.IntValue(current.TokenLifetime)) - if err := apiTokenLifetime.AskU(cmd, &inputs.TokenLifetime, ¤tTokenLifetime); err != nil { + currentTokenLifetime := strconv.Itoa(current.GetTokenLifetime()) + if err := apiTokenLifetime.AskIntU(cmd, &inputs.TokenLifetime, ¤tTokenLifetime); err != nil { return err } if !apiOfflineAccess.IsSet(cmd) { - inputs.AllowOfflineAccess = auth0.BoolValue(current.AllowOfflineAccess) + inputs.AllowOfflineAccess = current.GetAllowOfflineAccess() } if err := apiOfflineAccess.AskBoolU(cmd, &inputs.AllowOfflineAccess, current.AllowOfflineAccess); err != nil { return err } + if err := apiSigningAlgorithm.AskU(cmd, &inputs.SigningAlgorithm, current.SigningAlgorithm); err != nil { + return err + } + api := &management.ResourceServer{ AllowOfflineAccess: &inputs.AllowOfflineAccess, } - if len(inputs.Name) == 0 { - api.Name = current.Name - } else { + api.Name = current.Name + if len(inputs.Name) != 0 { api.Name = &inputs.Name } - if len(inputs.Scopes) == 0 { - api.Scopes = current.Scopes - } else { + api.Scopes = current.Scopes + if len(inputs.Scopes) != 0 { api.Scopes = apiScopesFor(inputs.Scopes) } - if inputs.TokenLifetime == 0 { - api.TokenLifetime = current.TokenLifetime - } else { + api.TokenLifetime = current.TokenLifetime + if inputs.TokenLifetime != 0 { api.TokenLifetime = &inputs.TokenLifetime } + api.SigningAlgorithm = current.SigningAlgorithm + if inputs.SigningAlgorithm != "" { + api.SigningAlgorithm = &inputs.SigningAlgorithm + } + if err := ansi.Waiting(func() error { return cli.api.ResourceServer.Update(cmd.Context(), current.GetID(), api) }); err != nil { - return fmt.Errorf("An unexpected error occurred while trying to update an API with Id '%s': %w", inputs.ID, err) + return fmt.Errorf("failed to update the API with ID %q: %w", inputs.ID, err) } cli.renderer.APIUpdate(api) + return nil }, } @@ -385,6 +410,7 @@ func updateAPICmd(cli *cli) *cobra.Command { apiScopes.RegisterStringSliceU(cmd, &inputs.Scopes, nil) apiOfflineAccess.RegisterBoolU(cmd, &inputs.AllowOfflineAccess, false) apiTokenLifetime.RegisterIntU(cmd, &inputs.TokenLifetime, 0) + apiSigningAlgorithm.RegisterStringU(cmd, &inputs.SigningAlgorithm, "RS256") return cmd } @@ -552,10 +578,6 @@ func apiScopesFor(scopes []string) *[]management.ResourceServerScope { return &models } -func apiDefaultTokenLifetime() int { - return 86400 -} - func (c *cli) apiPickerOptions(ctx context.Context) (pickerOptions, error) { return c.filteredAPIPickerOptions(ctx, func(r *management.ResourceServer) bool { return true diff --git a/internal/display/apis.go b/internal/display/apis.go index 6b00c5921..581c318a4 100644 --- a/internal/display/apis.go +++ b/internal/display/apis.go @@ -13,12 +13,13 @@ import ( ) type apiView struct { - ID string - Name string - Identifier string - Scopes string - TokenLifetime int - OfflineAccess string + ID string + Name string + Identifier string + Scopes string + TokenLifetime int + OfflineAccess string + SigningAlgorithm string raw interface{} } @@ -39,6 +40,7 @@ func (v *apiView) KeyValues() [][]string { {"SCOPES", v.Scopes}, {"TOKEN LIFETIME", strconv.Itoa(v.TokenLifetime)}, {"ALLOW OFFLINE ACCESS", v.OfflineAccess}, + {"SIGNING ALGORITHM", v.SigningAlgorithm}, } } @@ -111,14 +113,14 @@ func (r *Renderer) APIUpdate(api *management.ResourceServer) { func makeAPIView(api *management.ResourceServer) (*apiView, bool) { scopes, scopesTruncated := getScopes(api.GetScopes()) view := &apiView{ - ID: ansi.Faint(api.GetID()), - Name: api.GetName(), - Identifier: api.GetIdentifier(), - Scopes: scopes, - TokenLifetime: api.GetTokenLifetime(), - OfflineAccess: boolean(api.GetAllowOfflineAccess()), - - raw: api, + ID: ansi.Faint(api.GetID()), + Name: api.GetName(), + Identifier: api.GetIdentifier(), + Scopes: scopes, + TokenLifetime: api.GetTokenLifetime(), + OfflineAccess: boolean(api.GetAllowOfflineAccess()), + SigningAlgorithm: api.GetSigningAlgorithm(), + raw: api, } return view, scopesTruncated } diff --git a/test/integration/apis-test-cases.yaml b/test/integration/apis-test-cases.yaml index 9d30e6fc6..780c0932a 100644 --- a/test/integration/apis-test-cases.yaml +++ b/test/integration/apis-test-cases.yaml @@ -22,7 +22,7 @@ tests: - number flag invalid, please pass a number between 1 and 1000 003 - apis create and check data: - command: auth0 apis create --name integration-test-api-def1 --identifier http://integration-test-api-def1 --scopes read:todos,write:todos --json + command: auth0 apis create --name integration-test-api-def1 --identifier http://integration-test-api-def1 --scopes read:todos,write:todos --signing-alg RS256 --json exit-code: 0 stdout: json: @@ -31,9 +31,10 @@ tests: scopes: "[map[value:read:todos] map[value:write:todos]]" token_lifetime: "86400" allow_offline_access: "false" + signing_alg: "RS256" 004 - apis create and check output: - command: auth0 apis create --name integration-test-api-def2 --identifier http://integration-test-api-def2 --scopes read:todos,write:todos + command: auth0 apis create --name integration-test-api-def2 --identifier http://integration-test-api-def2 --scopes read:todos,write:todos --signing-alg RS256 exit-code: 0 stdout: contains: @@ -42,6 +43,7 @@ tests: - SCOPES read:todos write:todos - TOKEN LIFETIME 86400 - ALLOW OFFLINE ACCESS ✗ + - SIGNING ALGORITHM RS256 # Test 'apis create' --token-lifetime flag 005 - apis create token lifetime 1000 and check data: @@ -142,6 +144,13 @@ tests: allow_offline_access: "false" exit-code: 0 + 018 - apis update signing algorithm: + command: auth0 apis update $(./test/integration/scripts/get-api-id.sh) --signing-alg=HS256 --json + stdout: + json: + signing_alg: "HS256" + exit-code: 0 + 018 - it successfully prints out a URL to open: command: auth0 apis open $(./test/integration/scripts/get-api-id.sh) --no-input exit-code: 0 From d5637f0c9f83688f15c479bdbcd2980109ef117e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Dec 2023 11:05:45 +0000 Subject: [PATCH 07/14] Bump github.com/auth0/go-auth0 from 1.3.0 to 1.3.1 (#929) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 2847f6e0b..0b6654a49 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.21 require ( github.com/AlecAivazis/survey/v2 v2.3.7 github.com/PuerkitoBio/rehttp v1.3.0 - github.com/auth0/go-auth0 v1.3.0 + github.com/auth0/go-auth0 v1.3.1 github.com/briandowns/spinner v1.23.0 github.com/charmbracelet/glamour v0.6.0 github.com/fsnotify/fsnotify v1.7.0 diff --git a/go.sum b/go.sum index 48e300036..b9b9f227e 100644 --- a/go.sum +++ b/go.sum @@ -18,8 +18,8 @@ github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/ github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= -github.com/auth0/go-auth0 v1.3.0 h1:46bo0C6HYtsdSj4BEF4j6IaQrSAiUqehwuv+IO3qDJ0= -github.com/auth0/go-auth0 v1.3.0/go.mod h1:gm0NUM340x77a9YVZB50HUrJJkSchD9DkiqqbAl+s34= +github.com/auth0/go-auth0 v1.3.1 h1:J9QIKOMKs/uE9eo1OvTHfci8inuPau0M4WSgdNmPRaQ= +github.com/auth0/go-auth0 v1.3.1/go.mod h1:lpfYGQAGw5RFFWCmVc0kJI4c6w9mA1CbEaJfZ7xZycw= github.com/aybabtme/iocontrol v0.0.0-20150809002002-ad15bcfc95a0 h1:0NmehRCgyk5rljDQLKUO+cRJCnduDyn11+zGZIc9Z48= github.com/aybabtme/iocontrol v0.0.0-20150809002002-ad15bcfc95a0/go.mod h1:6L7zgvqo0idzI7IO8de6ZC051AfXb5ipkIJ7bIA2tGA= github.com/aymanbagabas/go-osc52 v1.0.3 h1:DTwqENW7X9arYimJrPeGZcV0ln14sGMt3pHZspWD+Mg= From e42a5522cded5e98e3ede5c45c26ddd87a1cd87a Mon Sep 17 00:00:00 2001 From: Michael Christenson II Date: Fri, 1 Dec 2023 09:51:25 -0500 Subject: [PATCH 08/14] Updated docs --- docs/auth0_actions_delete.md | 2 ++ docs/auth0_apis_delete.md | 2 ++ docs/auth0_apps_delete.md | 2 ++ docs/auth0_domains_delete.md | 2 ++ docs/auth0_logs_streams_delete.md | 2 ++ docs/auth0_orgs_delete.md | 2 ++ docs/auth0_roles_delete.md | 2 ++ docs/auth0_rules_delete.md | 2 ++ docs/auth0_users_blocks_unblock.md | 2 ++ docs/auth0_users_delete.md | 2 ++ internal/cli/actions.go | 4 +++- internal/cli/apis.go | 4 +++- internal/cli/apps.go | 4 +++- internal/cli/custom_domains.go | 4 +++- internal/cli/log_streams.go | 4 +++- internal/cli/organizations.go | 4 +++- internal/cli/picker_options_test.go | 2 +- internal/cli/roles.go | 4 +++- internal/cli/rules.go | 4 +++- internal/cli/users.go | 4 +++- internal/cli/users_blocks.go | 12 +++++++----- 21 files changed, 55 insertions(+), 15 deletions(-) diff --git a/docs/auth0_actions_delete.md b/docs/auth0_actions_delete.md index c7c9b2d49..753b2a538 100644 --- a/docs/auth0_actions_delete.md +++ b/docs/auth0_actions_delete.md @@ -23,6 +23,8 @@ auth0 actions delete [flags] auth0 actions rm auth0 actions delete auth0 actions delete --force + auth0 actions delete + auth0 actions delete --force ``` diff --git a/docs/auth0_apis_delete.md b/docs/auth0_apis_delete.md index 15df2480a..4777fb789 100644 --- a/docs/auth0_apis_delete.md +++ b/docs/auth0_apis_delete.md @@ -23,6 +23,8 @@ auth0 apis delete [flags] auth0 apis rm auth0 apis delete auth0 apis delete --force + auth0 apis delete + auth0 apis delete --force ``` diff --git a/docs/auth0_apps_delete.md b/docs/auth0_apps_delete.md index 3fe06b0ca..ba4058335 100644 --- a/docs/auth0_apps_delete.md +++ b/docs/auth0_apps_delete.md @@ -23,6 +23,8 @@ auth0 apps delete [flags] auth0 apps rm auth0 apps delete auth0 apps delete --force + auth0 apps delete + auth0 apps delete --force ``` diff --git a/docs/auth0_domains_delete.md b/docs/auth0_domains_delete.md index 13af4235b..3c9af2cb0 100644 --- a/docs/auth0_domains_delete.md +++ b/docs/auth0_domains_delete.md @@ -23,6 +23,8 @@ auth0 domains delete [flags] auth0 domains rm auth0 domains delete auth0 domains delete --force + auth0 domains delete + auth0 domains delete --force ``` diff --git a/docs/auth0_logs_streams_delete.md b/docs/auth0_logs_streams_delete.md index 9e680b7bc..55e74fba2 100644 --- a/docs/auth0_logs_streams_delete.md +++ b/docs/auth0_logs_streams_delete.md @@ -23,6 +23,8 @@ auth0 logs streams delete [flags] auth0 logs streams rm auth0 logs streams delete auth0 logs streams delete --force + auth0 logs streams delete + auth0 logs streams delete --force ``` diff --git a/docs/auth0_orgs_delete.md b/docs/auth0_orgs_delete.md index c65758374..547fd1004 100644 --- a/docs/auth0_orgs_delete.md +++ b/docs/auth0_orgs_delete.md @@ -23,6 +23,8 @@ auth0 orgs delete [flags] auth0 orgs rm auth0 orgs delete auth0 orgs delete --force + auth0 orgs delete + auth0 orgs delete --force ``` diff --git a/docs/auth0_roles_delete.md b/docs/auth0_roles_delete.md index e85284a9b..915279be8 100644 --- a/docs/auth0_roles_delete.md +++ b/docs/auth0_roles_delete.md @@ -23,6 +23,8 @@ auth0 roles delete [flags] auth0 roles rm auth0 roles delete auth0 roles delete --force + auth0 roles delete + auth0 roles delete --force ``` diff --git a/docs/auth0_rules_delete.md b/docs/auth0_rules_delete.md index f8bd8794a..cb72e58a0 100644 --- a/docs/auth0_rules_delete.md +++ b/docs/auth0_rules_delete.md @@ -25,6 +25,8 @@ auth0 rules delete [flags] auth0 rules rm auth0 rules delete auth0 rules delete --force + auth0 rules delete + auth0 rules delete --force ``` diff --git a/docs/auth0_users_blocks_unblock.md b/docs/auth0_users_blocks_unblock.md index c0d8d2201..f84002051 100644 --- a/docs/auth0_users_blocks_unblock.md +++ b/docs/auth0_users_blocks_unblock.md @@ -15,7 +15,9 @@ auth0 users blocks unblock [flags] ## Examples ``` + auth0 users blocks unblock auth0 users blocks unblock + auth0 users blocks unblock ``` diff --git a/docs/auth0_users_delete.md b/docs/auth0_users_delete.md index 9609609cd..aae614965 100644 --- a/docs/auth0_users_delete.md +++ b/docs/auth0_users_delete.md @@ -23,6 +23,8 @@ auth0 users delete [flags] auth0 users rm auth0 users delete auth0 users delete --force + auth0 users delete + auth0 users delete --force ``` diff --git a/internal/cli/actions.go b/internal/cli/actions.go index 12994ded4..32e80e467 100644 --- a/internal/cli/actions.go +++ b/internal/cli/actions.go @@ -369,7 +369,9 @@ func deleteActionCmd(cli *cli) *cobra.Command { Example: ` auth0 actions delete auth0 actions rm auth0 actions delete - auth0 actions delete --force`, + auth0 actions delete --force + auth0 actions delete + auth0 actions delete --force`, RunE: func(cmd *cobra.Command, args []string) error { ids := make([]string, len(args)) if len(args) == 0 { diff --git a/internal/cli/apis.go b/internal/cli/apis.go index 3fd96a1da..8cc48d71d 100644 --- a/internal/cli/apis.go +++ b/internal/cli/apis.go @@ -427,7 +427,9 @@ func deleteAPICmd(cli *cli) *cobra.Command { Example: ` auth0 apis delete auth0 apis rm auth0 apis delete - auth0 apis delete --force`, + auth0 apis delete --force + auth0 apis delete + auth0 apis delete --force`, RunE: func(cmd *cobra.Command, args []string) error { var ids []string if len(args) == 0 { diff --git a/internal/cli/apps.go b/internal/cli/apps.go index d39bd5e9e..caddc4a3d 100644 --- a/internal/cli/apps.go +++ b/internal/cli/apps.go @@ -315,7 +315,9 @@ func deleteAppCmd(cli *cli) *cobra.Command { Example: ` auth0 apps delete auth0 apps rm auth0 apps delete - auth0 apps delete --force`, + auth0 apps delete --force + auth0 apps delete + auth0 apps delete --force`, RunE: func(cmd *cobra.Command, args []string) error { ids := make([]string, len(args)) if len(args) == 0 { diff --git a/internal/cli/custom_domains.go b/internal/cli/custom_domains.go index d5e348e0c..a7fde2e44 100644 --- a/internal/cli/custom_domains.go +++ b/internal/cli/custom_domains.go @@ -336,7 +336,9 @@ func deleteCustomDomainCmd(cli *cli) *cobra.Command { Example: ` auth0 domains delete auth0 domains rm auth0 domains delete - auth0 domains delete --force`, + auth0 domains delete --force + auth0 domains delete + auth0 domains delete --force`, RunE: func(cmd *cobra.Command, args []string) error { ids := make([]string, len(args)) if len(args) == 0 { diff --git a/internal/cli/log_streams.go b/internal/cli/log_streams.go index 6d4a497e1..b1f5a987e 100644 --- a/internal/cli/log_streams.go +++ b/internal/cli/log_streams.go @@ -180,7 +180,9 @@ func deleteLogStreamCmd(cli *cli) *cobra.Command { Example: ` auth0 logs streams delete auth0 logs streams rm auth0 logs streams delete - auth0 logs streams delete --force`, + auth0 logs streams delete --force + auth0 logs streams delete + auth0 logs streams delete --force`, RunE: func(cmd *cobra.Command, args []string) error { ids := make([]string, len(args)) if len(args) == 0 { diff --git a/internal/cli/organizations.go b/internal/cli/organizations.go index 71795c99c..97ec7884b 100644 --- a/internal/cli/organizations.go +++ b/internal/cli/organizations.go @@ -420,7 +420,9 @@ func deleteOrganizationCmd(cli *cli) *cobra.Command { Example: ` auth0 orgs delete auth0 orgs rm auth0 orgs delete - auth0 orgs delete --force`, + auth0 orgs delete --force + auth0 orgs delete + auth0 orgs delete --force`, RunE: func(cmd *cobra.Command, args []string) error { ids := make([]string, len(args)) if len(args) == 0 { diff --git a/internal/cli/picker_options_test.go b/internal/cli/picker_options_test.go index 2ad163e45..01c200196 100644 --- a/internal/cli/picker_options_test.go +++ b/internal/cli/picker_options_test.go @@ -50,7 +50,7 @@ func TestPickerOptions(t *testing.T) { t.Run("return the values for a given set of labels", func(t *testing.T) { options := pickerOptions{pickerOption{label: "Foo", value: "0"}, pickerOption{label: "Bar", value: "1"}, pickerOption{label: "Baz", value: "2"}} want := []string{"0", "2"} - got := options.getValues("Foo", "Fizz") + got := options.getValues("Foo", "Baz") assert.Equal(t, want, got) }) diff --git a/internal/cli/roles.go b/internal/cli/roles.go index c4789a6ef..ee1a64c85 100644 --- a/internal/cli/roles.go +++ b/internal/cli/roles.go @@ -293,7 +293,9 @@ func deleteRoleCmd(cli *cli) *cobra.Command { Example: ` auth0 roles delete auth0 roles rm auth0 roles delete - auth0 roles delete --force`, + auth0 roles delete --force + auth0 roles delete + auth0 roles delete --force`, RunE: func(cmd *cobra.Command, args []string) error { ids := make([]string, len(args)) if len(args) == 0 { diff --git a/internal/cli/rules.go b/internal/cli/rules.go index a357416be..9c7f0c97c 100644 --- a/internal/cli/rules.go +++ b/internal/cli/rules.go @@ -260,7 +260,9 @@ func deleteRuleCmd(cli *cli) *cobra.Command { Example: ` auth0 rules delete auth0 rules rm auth0 rules delete - auth0 rules delete --force`, + auth0 rules delete --force + auth0 rules delete + auth0 rules delete --force`, RunE: func(cmd *cobra.Command, args []string) error { ids := make([]string, len(args)) if len(args) == 0 { diff --git a/internal/cli/users.go b/internal/cli/users.go index 9d95e6831..d129186fb 100644 --- a/internal/cli/users.go +++ b/internal/cli/users.go @@ -368,7 +368,9 @@ func deleteUserCmd(cli *cli) *cobra.Command { Example: ` auth0 users delete auth0 users rm auth0 users delete - auth0 users delete --force`, + auth0 users delete --force + auth0 users delete + auth0 users delete --force`, RunE: func(cmd *cobra.Command, args []string) error { ids := make([]string, len(args)) if len(args) == 0 { diff --git a/internal/cli/users_blocks.go b/internal/cli/users_blocks.go index 8eb75a83f..c23cd0fbb 100644 --- a/internal/cli/users_blocks.go +++ b/internal/cli/users_blocks.go @@ -66,11 +66,13 @@ func listUserBlocksCmd(cli *cli) *cobra.Command { func deleteUserBlocksCmd(cli *cli) *cobra.Command { cmd := &cobra.Command{ - Use: "unblock", - Args: cobra.MinimumNArgs(0), - Short: "Remove brute-force protection blocks for a given user", - Long: "Remove brute-force protection blocks for a given user.", - Example: ` auth0 users blocks unblock `, + Use: "unblock", + Args: cobra.MinimumNArgs(0), + Short: "Remove brute-force protection blocks for a given user", + Long: "Remove brute-force protection blocks for a given user.", + Example: ` auth0 users blocks unblock + auth0 users blocks unblock + auth0 users blocks unblock `, RunE: func(cmd *cobra.Command, args []string) error { ids := make([]string, len(args)) if len(args) == 0 { From c50664202ebc1c0d649746eec5a1a06affee53b1 Mon Sep 17 00:00:00 2001 From: Michael Christenson II Date: Fri, 1 Dec 2023 10:04:18 -0500 Subject: [PATCH 09/14] Simplify args loops --- internal/cli/actions.go | 4 +--- internal/cli/apis.go | 4 +--- internal/cli/apps.go | 4 +--- internal/cli/custom_domains.go | 4 +--- internal/cli/log_streams.go | 4 +--- internal/cli/organizations.go | 4 +--- internal/cli/roles.go | 4 +--- internal/cli/rules.go | 4 +--- internal/cli/users.go | 4 +--- internal/cli/users_blocks.go | 4 +--- 10 files changed, 10 insertions(+), 30 deletions(-) diff --git a/internal/cli/actions.go b/internal/cli/actions.go index 32e80e467..e4bbea73e 100644 --- a/internal/cli/actions.go +++ b/internal/cli/actions.go @@ -379,9 +379,7 @@ func deleteActionCmd(cli *cli) *cobra.Command { return err } } else { - for _, id := range args[0:] { - ids = append(ids, id) - } + ids = append(ids, args...) } if !cli.force && canPrompt(cmd) { diff --git a/internal/cli/apis.go b/internal/cli/apis.go index 8cc48d71d..1b0c42aca 100644 --- a/internal/cli/apis.go +++ b/internal/cli/apis.go @@ -437,9 +437,7 @@ func deleteAPICmd(cli *cli) *cobra.Command { return err } } else { - for _, id := range args[0:] { - ids = append(ids, id) - } + ids = append(ids, args...) } if !cli.force && canPrompt(cmd) { diff --git a/internal/cli/apps.go b/internal/cli/apps.go index caddc4a3d..be7efac8b 100644 --- a/internal/cli/apps.go +++ b/internal/cli/apps.go @@ -326,9 +326,7 @@ func deleteAppCmd(cli *cli) *cobra.Command { return err } } else { - for _, id := range args[0:] { - ids = append(ids, id) - } + ids = append(ids, args...) } if !cli.force && canPrompt(cmd) { diff --git a/internal/cli/custom_domains.go b/internal/cli/custom_domains.go index a7fde2e44..f71d5d7b4 100644 --- a/internal/cli/custom_domains.go +++ b/internal/cli/custom_domains.go @@ -347,9 +347,7 @@ func deleteCustomDomainCmd(cli *cli) *cobra.Command { return err } } else { - for _, id := range args[0:] { - ids = append(ids, id) - } + ids = append(ids, args...) } if !cli.force && canPrompt(cmd) { diff --git a/internal/cli/log_streams.go b/internal/cli/log_streams.go index b1f5a987e..cc5e6cec5 100644 --- a/internal/cli/log_streams.go +++ b/internal/cli/log_streams.go @@ -191,9 +191,7 @@ func deleteLogStreamCmd(cli *cli) *cobra.Command { return err } } else { - for _, id := range args[0:] { - ids = append(ids, id) - } + ids = append(ids, args...) } if !cli.force && canPrompt(cmd) { diff --git a/internal/cli/organizations.go b/internal/cli/organizations.go index 97ec7884b..03fcd171a 100644 --- a/internal/cli/organizations.go +++ b/internal/cli/organizations.go @@ -431,9 +431,7 @@ func deleteOrganizationCmd(cli *cli) *cobra.Command { return err } } else { - for _, id := range args { - ids = append(ids, id) - } + ids = append(ids, args...) } if !cli.force && canPrompt(cmd) { diff --git a/internal/cli/roles.go b/internal/cli/roles.go index ee1a64c85..10c972f5b 100644 --- a/internal/cli/roles.go +++ b/internal/cli/roles.go @@ -304,9 +304,7 @@ func deleteRoleCmd(cli *cli) *cobra.Command { return err } } else { - for _, id := range args { - ids = append(ids, id) - } + ids = append(ids, args...) } if !cli.force && canPrompt(cmd) { diff --git a/internal/cli/rules.go b/internal/cli/rules.go index 9c7f0c97c..3af86aca4 100644 --- a/internal/cli/rules.go +++ b/internal/cli/rules.go @@ -271,9 +271,7 @@ func deleteRuleCmd(cli *cli) *cobra.Command { return err } } else { - for _, id := range args { - ids = append(ids, id) - } + ids = append(ids, args...) } if !cli.force && canPrompt(cmd) { diff --git a/internal/cli/users.go b/internal/cli/users.go index d129186fb..8ef64c6e1 100644 --- a/internal/cli/users.go +++ b/internal/cli/users.go @@ -380,9 +380,7 @@ func deleteUserCmd(cli *cli) *cobra.Command { } ids = append(ids, id) } else { - for _, id := range args { - ids = append(ids, id) - } + ids = append(ids, args...) } if !cli.force && canPrompt(cmd) { diff --git a/internal/cli/users_blocks.go b/internal/cli/users_blocks.go index c23cd0fbb..e83aab07d 100644 --- a/internal/cli/users_blocks.go +++ b/internal/cli/users_blocks.go @@ -82,9 +82,7 @@ func deleteUserBlocksCmd(cli *cli) *cobra.Command { } ids = append(ids, id) } else { - for _, id := range args { - ids = append(ids, id) - } + ids = append(ids, args...) } return ansi.Spinner("Unblocking user...", func() error { From e590a5973602f7f5ff19900601a62926ddace746 Mon Sep 17 00:00:00 2001 From: Michael Christenson II Date: Mon, 4 Dec 2023 11:04:51 -0500 Subject: [PATCH 10/14] Updates for code review Ensure valid id before deletion process Normalize messages for deletion Remove unnecessary path escapes Continue on read failure instead of attempting delete Inform user of failed id on batch deletion Only document at most two ids likely --- internal/cli/actions.go | 9 +++++---- internal/cli/apis.go | 18 ++++++++++-------- internal/cli/apps.go | 19 ++++++++++--------- internal/cli/custom_domains.go | 19 ++++++++++--------- internal/cli/log_streams.go | 20 +++++++++++--------- internal/cli/organizations.go | 18 ++++++++++-------- internal/cli/roles.go | 18 ++++++++++-------- internal/cli/rules.go | 18 ++++++++++-------- internal/cli/users.go | 18 ++++++++++-------- internal/cli/users_blocks.go | 9 +++++---- 10 files changed, 91 insertions(+), 75 deletions(-) diff --git a/internal/cli/actions.go b/internal/cli/actions.go index e4bbea73e..5885c11ff 100644 --- a/internal/cli/actions.go +++ b/internal/cli/actions.go @@ -361,7 +361,6 @@ func deleteActionCmd(cli *cli) *cobra.Command { cmd := &cobra.Command{ Use: "delete", Aliases: []string{"rm"}, - Args: cobra.MinimumNArgs(0), Short: "Delete an action", Long: "Delete an action.\n\n" + "To delete interactively, use `auth0 actions delete` with no arguments.\n\n" + @@ -388,11 +387,13 @@ func deleteActionCmd(cli *cli) *cobra.Command { } } - return ansi.Spinner("Deleting action", func() error { + return ansi.Spinner("Deleting action(s)", func() error { var errs []error for _, id := range ids { - if err := cli.api.Action.Delete(cmd.Context(), id); err != nil { - errs = append(errs, err) + if id != "" { + if err := cli.api.Action.Delete(cmd.Context(), id); err != nil { + errs = append(errs, err) + } } } return errors.Join(errs...) diff --git a/internal/cli/apis.go b/internal/cli/apis.go index 1b0c42aca..d7aa66a5a 100644 --- a/internal/cli/apis.go +++ b/internal/cli/apis.go @@ -419,7 +419,6 @@ func deleteAPICmd(cli *cli) *cobra.Command { cmd := &cobra.Command{ Use: "delete", Aliases: []string{"rm"}, - Args: cobra.MinimumNArgs(0), Short: "Delete an API", Long: "Delete an API.\n\n" + "To delete interactively, use `auth0 apis delete` with no arguments.\n\n" + @@ -446,15 +445,18 @@ func deleteAPICmd(cli *cli) *cobra.Command { } } - return ansi.Spinner("Deleting API", func() error { + return ansi.Spinner("Deleting API(s)", func() error { var errs []error for _, id := range ids { - if _, err := cli.api.ResourceServer.Read(cmd.Context(), url.PathEscape(id)); err != nil { - errs = append(errs, fmt.Errorf("Unable to read API for deletion: %w", err)) - } - - if err := cli.api.ResourceServer.Delete(cmd.Context(), url.PathEscape(id)); err != nil { - errs = append(errs, fmt.Errorf("Unable to delete API: %w", err)) + if id != "" { + if _, err := cli.api.ResourceServer.Read(cmd.Context(), url.PathEscape(id)); err != nil { + errs = append(errs, fmt.Errorf("Unable to delete API (%s): %w", id, err)) + continue + } + + if err := cli.api.ResourceServer.Delete(cmd.Context(), url.PathEscape(id)); err != nil { + errs = append(errs, fmt.Errorf("Unable to delete API (%s): %w", id, err)) + } } } return errors.Join(errs...) diff --git a/internal/cli/apps.go b/internal/cli/apps.go index be7efac8b..f900ff1d2 100644 --- a/internal/cli/apps.go +++ b/internal/cli/apps.go @@ -4,7 +4,6 @@ import ( "context" "errors" "fmt" - "net/url" "strings" "github.com/auth0/go-auth0/management" @@ -306,7 +305,6 @@ func deleteAppCmd(cli *cli) *cobra.Command { cmd := &cobra.Command{ Use: "delete", Aliases: []string{"rm"}, - Args: cobra.MinimumNArgs(0), Short: "Delete an application", Long: "Delete an application.\n\n" + "To delete interactively, use `auth0 apps delete` with no arguments.\n\n" + @@ -335,15 +333,18 @@ func deleteAppCmd(cli *cli) *cobra.Command { } } - return ansi.Spinner("Deleting Application", func() error { + return ansi.Spinner("Deleting Application(s)", func() error { var errs []error for _, id := range ids { - if _, err := cli.api.Client.Read(cmd.Context(), url.PathEscape(id)); err != nil { - errs = append(errs, fmt.Errorf("Unable to read application for deletion: %w", err)) - } - - if err := cli.api.Client.Delete(cmd.Context(), url.PathEscape(id)); err != nil { - errs = append(errs, fmt.Errorf("Unable to delete application: %w", err)) + if id != "" { + if _, err := cli.api.Client.Read(cmd.Context(), id); err != nil { + errs = append(errs, fmt.Errorf("Unable to delete application (%s): %w", id, err)) + continue + } + + if err := cli.api.Client.Delete(cmd.Context(), id); err != nil { + errs = append(errs, fmt.Errorf("Unable to delete application (%s): %w", id, err)) + } } } return errors.Join(errs...) diff --git a/internal/cli/custom_domains.go b/internal/cli/custom_domains.go index f71d5d7b4..e36e234cc 100644 --- a/internal/cli/custom_domains.go +++ b/internal/cli/custom_domains.go @@ -327,7 +327,6 @@ func deleteCustomDomainCmd(cli *cli) *cobra.Command { cmd := &cobra.Command{ Use: "delete", Aliases: []string{"rm"}, - Args: cobra.MinimumNArgs(0), Short: "Delete a custom domain", Long: "Delete a custom domain.\n\n" + "To delete interactively, use `auth0 domains delete` with no arguments.\n\n" + @@ -337,8 +336,8 @@ func deleteCustomDomainCmd(cli *cli) *cobra.Command { auth0 domains rm auth0 domains delete auth0 domains delete --force - auth0 domains delete - auth0 domains delete --force`, + auth0 domains delete + auth0 domains delete --force`, RunE: func(cmd *cobra.Command, args []string) error { ids := make([]string, len(args)) if len(args) == 0 { @@ -359,12 +358,14 @@ func deleteCustomDomainCmd(cli *cli) *cobra.Command { return ansi.Spinner("Deleting custom domain", func() error { var errs []error for _, id := range ids { - if _, err := cli.api.CustomDomain.Read(cmd.Context(), url.PathEscape(id)); err != nil { - return fmt.Errorf("Unable to read custom domain for deletion: %w", err) - } - - if err := cli.api.CustomDomain.Delete(cmd.Context(), url.PathEscape(id)); err != nil { - return fmt.Errorf("Unable to delete custom domain: %w", err) + if id != "" { + if _, err := cli.api.CustomDomain.Read(cmd.Context(), url.PathEscape(id)); err != nil { + return fmt.Errorf("Unable to delete custom domain (%s): %w", id, err) + } + + if err := cli.api.CustomDomain.Delete(cmd.Context(), url.PathEscape(id)); err != nil { + return fmt.Errorf("Unable to delete custom domain (%s): %w", id, err) + } } } diff --git a/internal/cli/log_streams.go b/internal/cli/log_streams.go index cc5e6cec5..d33e92247 100644 --- a/internal/cli/log_streams.go +++ b/internal/cli/log_streams.go @@ -171,7 +171,6 @@ func deleteLogStreamCmd(cli *cli) *cobra.Command { cmd := &cobra.Command{ Use: "delete", Aliases: []string{"rm"}, - Args: cobra.MinimumNArgs(0), Short: "Delete a log stream", Long: "Delete a log stream.\n\n" + "To delete interactively, use `auth0 logs streams delete` with no arguments.\n\n" + @@ -181,8 +180,8 @@ func deleteLogStreamCmd(cli *cli) *cobra.Command { auth0 logs streams rm auth0 logs streams delete auth0 logs streams delete --force - auth0 logs streams delete - auth0 logs streams delete --force`, + auth0 logs streams delete + auth0 logs streams delete --force`, RunE: func(cmd *cobra.Command, args []string) error { ids := make([]string, len(args)) if len(args) == 0 { @@ -200,14 +199,17 @@ func deleteLogStreamCmd(cli *cli) *cobra.Command { } } - return ansi.Spinner("Deleting Log Stream", func() error { + return ansi.Spinner("Deleting Log Stream(s)", func() error { var errs []error for _, id := range ids { - if _, err := cli.api.LogStream.Read(cmd.Context(), id); err != nil { - errs = append(errs, fmt.Errorf("Unable to read log stream for deletion: %w", err)) - } - if err := cli.api.LogStream.Delete(cmd.Context(), id); err != nil { - errs = append(errs, fmt.Errorf("Unable to delete log stream: %w", err)) + if id != "" { + if _, err := cli.api.LogStream.Read(cmd.Context(), id); err != nil { + errs = append(errs, fmt.Errorf("Unable to delete log stream (%s): %w", id, err)) + continue + } + if err := cli.api.LogStream.Delete(cmd.Context(), id); err != nil { + errs = append(errs, fmt.Errorf("Unable to delete log stream (%s): %w", id, err)) + } } } diff --git a/internal/cli/organizations.go b/internal/cli/organizations.go index 03fcd171a..b39e7e5e2 100644 --- a/internal/cli/organizations.go +++ b/internal/cli/organizations.go @@ -411,7 +411,6 @@ func deleteOrganizationCmd(cli *cli) *cobra.Command { cmd := &cobra.Command{ Use: "delete", Aliases: []string{"rm"}, - Args: cobra.MinimumNArgs(0), Short: "Delete an organization", Long: "Delete an organization.\n\n" + "To delete interactively, use `auth0 orgs delete` with no arguments.\n\n" + @@ -440,15 +439,18 @@ func deleteOrganizationCmd(cli *cli) *cobra.Command { } } - return ansi.Spinner("Deleting organization", func() error { + return ansi.Spinner("Deleting organization(s)", func() error { var errs []error for _, id := range ids { - if _, err := cli.api.Organization.Read(cmd.Context(), url.PathEscape(id)); err != nil { - errs = append(errs, fmt.Errorf("Unable to read organization for deletion: %w", err)) - } - - if err := cli.api.Organization.Delete(cmd.Context(), url.PathEscape(id)); err != nil { - errs = append(errs, fmt.Errorf("Unable to delete organization: %w", err)) + if id != "" { + if _, err := cli.api.Organization.Read(cmd.Context(), id); err != nil { + errs = append(errs, fmt.Errorf("Unable to delete organization (%s): %w", id, err)) + continue + } + + if err := cli.api.Organization.Delete(cmd.Context(), id); err != nil { + errs = append(errs, fmt.Errorf("Unable to delete organization (%s): %w", id, err)) + } } } return errors.Join(errs...) diff --git a/internal/cli/roles.go b/internal/cli/roles.go index 10c972f5b..e63091e55 100644 --- a/internal/cli/roles.go +++ b/internal/cli/roles.go @@ -285,7 +285,6 @@ func deleteRoleCmd(cli *cli) *cobra.Command { cmd := &cobra.Command{ Use: "delete", Aliases: []string{"rm"}, - Args: cobra.MinimumNArgs(0), Short: "Delete a role", Long: "Delete a role.\n\n" + "To delete interactively, use `auth0 roles delete`.\n\n" + @@ -313,15 +312,18 @@ func deleteRoleCmd(cli *cli) *cobra.Command { } } - return ansi.Spinner("Deleting Role", func() error { + return ansi.Spinner("Deleting Role(s)", func() error { var errs []error for _, id := range ids { - if _, err := cli.api.Role.Read(cmd.Context(), id); err != nil { - errs = append(errs, fmt.Errorf("Unable to read role for deletion: %w", err)) - } - - if err := cli.api.Role.Delete(cmd.Context(), id); err != nil { - errs = append(errs, fmt.Errorf("Unable to delete role: %w", err)) + if id != "" { + if _, err := cli.api.Role.Read(cmd.Context(), id); err != nil { + errs = append(errs, fmt.Errorf("Unable to delete role (%s): %w", id, err)) + continue + } + + if err := cli.api.Role.Delete(cmd.Context(), id); err != nil { + errs = append(errs, fmt.Errorf("Unable to delete role (%s): %w", id, err)) + } } } return errors.Join(errs...) diff --git a/internal/cli/rules.go b/internal/cli/rules.go index 3af86aca4..5a317d2cb 100644 --- a/internal/cli/rules.go +++ b/internal/cli/rules.go @@ -252,7 +252,6 @@ func deleteRuleCmd(cli *cli) *cobra.Command { cmd := &cobra.Command{ Use: "delete", Aliases: []string{"rm"}, - Args: cobra.MinimumNArgs(0), Short: "Delete a rule", Long: rulesDeprecationDocumentationText + "Delete a rule.\n\n" + "To delete interactively, use `auth0 rules delete` with no arguments.\n\n" + @@ -280,15 +279,18 @@ func deleteRuleCmd(cli *cli) *cobra.Command { } } - return ansi.Spinner("Deleting Rule", func() error { + return ansi.Spinner("Deleting Rule(s)", func() error { var errs []error for _, id := range ids { - if _, err := cli.api.Rule.Read(cmd.Context(), id); err != nil { - errs = append(errs, fmt.Errorf("Unable to read rule for deletion: %w", err)) - } - - if err := cli.api.Rule.Delete(cmd.Context(), id); err != nil { - errs = append(errs, fmt.Errorf("Unable to delete rule: %w", err)) + if id != "" { + if _, err := cli.api.Rule.Read(cmd.Context(), id); err != nil { + errs = append(errs, fmt.Errorf("Unable to delete rule (%s): %w", id, err)) + continue + } + + if err := cli.api.Rule.Delete(cmd.Context(), id); err != nil { + errs = append(errs, fmt.Errorf("Unable to delete rule (%s): %w", id, err)) + } } } return errors.Join(errs...) diff --git a/internal/cli/users.go b/internal/cli/users.go index 8ef64c6e1..2f458a2be 100644 --- a/internal/cli/users.go +++ b/internal/cli/users.go @@ -360,7 +360,6 @@ func deleteUserCmd(cli *cli) *cobra.Command { cmd := &cobra.Command{ Use: "delete", Aliases: []string{"rm"}, - Args: cobra.MinimumNArgs(0), Short: "Delete a user", Long: "Delete a user.\n\n" + "To delete interactively, use `auth0 users delete` with no arguments.\n\n" + @@ -389,15 +388,18 @@ func deleteUserCmd(cli *cli) *cobra.Command { } } - return ansi.Spinner("Deleting user", func() error { + return ansi.Spinner("Deleting user(s)", func() error { var errs []error for _, id := range ids { - if _, err := cli.api.User.Read(cmd.Context(), id); err != nil { - errs = append(errs, fmt.Errorf("Unable to read user for deletion: %w", err)) - } - - if err := cli.api.User.Delete(cmd.Context(), id); err != nil { - errs = append(errs, fmt.Errorf("Unable to delete user: %w", err)) + if id != "" { + if _, err := cli.api.User.Read(cmd.Context(), id); err != nil { + errs = append(errs, fmt.Errorf("Unable to delete user (%s): %w", id, err)) + continue + } + + if err := cli.api.User.Delete(cmd.Context(), id); err != nil { + errs = append(errs, fmt.Errorf("Unable to delete user (%s): %w", id, err)) + } } } return errors.Join(errs...) diff --git a/internal/cli/users_blocks.go b/internal/cli/users_blocks.go index e83aab07d..223452812 100644 --- a/internal/cli/users_blocks.go +++ b/internal/cli/users_blocks.go @@ -67,7 +67,6 @@ func listUserBlocksCmd(cli *cli) *cobra.Command { func deleteUserBlocksCmd(cli *cli) *cobra.Command { cmd := &cobra.Command{ Use: "unblock", - Args: cobra.MinimumNArgs(0), Short: "Remove brute-force protection blocks for a given user", Long: "Remove brute-force protection blocks for a given user.", Example: ` auth0 users blocks unblock @@ -85,11 +84,13 @@ func deleteUserBlocksCmd(cli *cli) *cobra.Command { ids = append(ids, args...) } - return ansi.Spinner("Unblocking user...", func() error { + return ansi.Spinner("Unblocking user(s)...", func() error { var errs []error for _, id := range ids { - if err := cli.api.User.Unblock(cmd.Context(), id); err != nil { - errs = append(errs, fmt.Errorf("failed to unblock user with ID %s: %w", id, err)) + if id != "" { + if err := cli.api.User.Unblock(cmd.Context(), id); err != nil { + errs = append(errs, fmt.Errorf("failed to unblock user with ID %s: %w", id, err)) + } } } return errors.Join(errs...) From 2d7e444c41a059e813c856703eff528dc229368e Mon Sep 17 00:00:00 2001 From: Michael Christenson II Date: Mon, 4 Dec 2023 11:55:15 -0500 Subject: [PATCH 11/14] Validate input for askMultiSelect --- internal/cli/input.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/internal/cli/input.go b/internal/cli/input.go index e2ed018cf..d088d2d44 100644 --- a/internal/cli/input.go +++ b/internal/cli/input.go @@ -3,6 +3,7 @@ package cli import ( "fmt" "os" + "reflect" "github.com/AlecAivazis/survey/v2/terminal" "github.com/auth0/go-auth0" @@ -59,7 +60,10 @@ func askPassword(i commandInput, value interface{}, isUpdate bool) error { } func askMultiSelect(i commandInput, value interface{}, isUpdate bool, options ...string) error { - _ = isInputRequired(i, isUpdate) // TODO: handle isRequired + v := reflect.ValueOf(value) + if v.Kind() != reflect.Slice || v.Len() <= 0 { + handleInputError(fmt.Errorf("there is not enough data to select from")) + } if err := prompt.AskMultiSelect(i.GetLabel(), value, options...); err != nil { handleInputError(err) From 1da47fa03ae8d38602d770201c0355c374715d24 Mon Sep 17 00:00:00 2001 From: Michael Christenson II Date: Mon, 4 Dec 2023 11:58:40 -0500 Subject: [PATCH 12/14] Update docs --- docs/auth0_domains_delete.md | 4 ++-- docs/auth0_logs_streams_delete.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/auth0_domains_delete.md b/docs/auth0_domains_delete.md index 3c9af2cb0..6fd486dc2 100644 --- a/docs/auth0_domains_delete.md +++ b/docs/auth0_domains_delete.md @@ -23,8 +23,8 @@ auth0 domains delete [flags] auth0 domains rm auth0 domains delete auth0 domains delete --force - auth0 domains delete - auth0 domains delete --force + auth0 domains delete + auth0 domains delete --force ``` diff --git a/docs/auth0_logs_streams_delete.md b/docs/auth0_logs_streams_delete.md index 55e74fba2..a2bae1d57 100644 --- a/docs/auth0_logs_streams_delete.md +++ b/docs/auth0_logs_streams_delete.md @@ -23,8 +23,8 @@ auth0 logs streams delete [flags] auth0 logs streams rm auth0 logs streams delete auth0 logs streams delete --force - auth0 logs streams delete - auth0 logs streams delete --force + auth0 logs streams delete + auth0 logs streams delete --force ``` From 16d0d6b2d2aaa594ac587e6c916adf25d72f9d6d Mon Sep 17 00:00:00 2001 From: Michael Christenson II Date: Mon, 4 Dec 2023 12:01:43 -0500 Subject: [PATCH 13/14] Remove unused variable --- internal/cli/arguments.go | 2 +- internal/cli/input.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/cli/arguments.go b/internal/cli/arguments.go index 9897768d0..5e1ea559d 100644 --- a/internal/cli/arguments.go +++ b/internal/cli/arguments.go @@ -71,7 +71,7 @@ func (a *Argument) PickMany(cmd *cobra.Command, result *[]string, fn pickerOptio } var values []string - if err := askMultiSelect(a, &values, false, opts.labels()...); err != nil { + if err := askMultiSelect(a, &values, opts.labels()...); err != nil { return err } diff --git a/internal/cli/input.go b/internal/cli/input.go index d088d2d44..f861dcbdb 100644 --- a/internal/cli/input.go +++ b/internal/cli/input.go @@ -59,7 +59,7 @@ func askPassword(i commandInput, value interface{}, isUpdate bool) error { return nil } -func askMultiSelect(i commandInput, value interface{}, isUpdate bool, options ...string) error { +func askMultiSelect(i commandInput, value interface{}, options ...string) error { v := reflect.ValueOf(value) if v.Kind() != reflect.Slice || v.Len() <= 0 { handleInputError(fmt.Errorf("there is not enough data to select from")) From e514e215e0f96a09d2a2c9a5fbc1e9d3036a6897 Mon Sep 17 00:00:00 2001 From: Michael Christenson II Date: Tue, 5 Dec 2023 10:15:38 -0500 Subject: [PATCH 14/14] Use Batch deletion for integration test cleanup --- test/integration/scripts/test-cleanup.sh | 157 ++++------------------- 1 file changed, 25 insertions(+), 132 deletions(-) diff --git a/test/integration/scripts/test-cleanup.sh b/test/integration/scripts/test-cleanup.sh index da5a09913..e080e04c4 100755 --- a/test/integration/scripts/test-cleanup.sh +++ b/test/integration/scripts/test-cleanup.sh @@ -1,142 +1,35 @@ #! /bin/bash -apps=$( auth0 apps list --json --no-input ) +function delete_resources { + local cmd=${1-} name=${2-} field=${3-} -for app in $( echo "${apps}" | jq -r '.[] | @base64' ); do - _jq() { - echo "${app}" | base64 --decode | jq -r "${1}" - } + printf "\r\nGathering resource %ss for %s...\r\n" ${field} ${cmd} + resources=$( auth0 ${cmd} list --json --no-input | jq -r ".[] | select(.name | test(\"^${name}.+\")) | .${field}" | tr '\n' ' ' ) - clientid=$(_jq '.client_id') - name=$(_jq '.name') - # TODO(jfatta): should remove only those - # created during the same test session - if [[ $name = integration-test-app-* ]] - then - echo deleting "$name" - $( auth0 apps delete "$clientid") - fi -done + if [[ $resources ]] + then + echo "Deleting resources for ${cmd}... ${field} (e.g. IDs): ${resources}" + auth0 ${cmd} delete --force ${resources[*]} + fi +} -apis=$( auth0 apis list --json --no-input ) - -for api in $( echo "${apis}" | jq -r '.[] | @base64' ); do - _jq() { - echo "${api}" | base64 --decode | jq -r "${1}" - } - - id=$(_jq '.id') - name=$(_jq '.name') - # TODO(jfatta): should remove only those - # created during the same test session - if [[ $name = integration-test-api-* ]] - then - echo deleting "$name" - $( auth0 apis delete "$id") - fi -done +delete_resources "apps" "integration-test-app" "client_id" +delete_resources "apis" "integration-test-api" "id" +print "\r\nGathering resource user_ids for users...\r\n" # using the search command since users have no list command -users=$( auth0 users search -q "*" --json --no-input ) - -for user in $( echo "${users}" | jq -r '.[] | @base64' ); do - _jq() { - echo "${user}" | base64 --decode | jq -r "${1}" - } - - userid=$(_jq '.user_id') - # created during the same test session - if [[ integration-* ]] - then - echo deleting "$userid" - $( auth0 users delete "$userid") - fi -done - -roles=$( auth0 roles list --json --no-input ) - -for role in $( echo "${roles}" | jq -r '.[] | @base64' ); do - _jq() { - echo "${role}" | base64 --decode | jq -r "${1}" - } - - id=$(_jq '.id') - name=$(_jq '.name') - # TODO(jfatta): should remove only those - # created during the same test session - if [[ $name = integration-test-role-* ]] - then - echo deleting "$name" - $( auth0 roles delete "$id") - fi -done - -rules=$( auth0 rules list --json --no-input ) - -for rule in $( printf "%s" "$rules" | jq -r '.[] | @base64' ); do - _jq() { - echo "${rule}" | base64 --decode | jq -r "${1}" - } - - id=$(_jq '.id') - name=$(_jq '.name') - # TODO(jfatta): should remove only those - # created during the same test session - if [[ $name = integration-test-rule-* ]] - then - echo deleting "$name" - $( auth0 rules delete "$id") - fi -done - -orgs=$( auth0 orgs list --json --no-input ) - -for org in $( echo "${orgs}" | jq -r '.[] | @base64' ); do - _jq() { - echo "${org}" | base64 --decode | jq -r "${1}" - } - - id=$(_jq '.id') - name=$(_jq '.name') - if [[ $name = integration-test-org-* ]] - then - echo deleting "$name" - $( auth0 orgs delete "$id") - fi -done - -actions=$( auth0 actions list --json --no-input ) - -for action in $( echo "${actions}" | jq -r '.[] | @base64' ); do - _jq() { - echo "${action}" | base64 --decode | jq -r "${1}" - } - - id=$(_jq '.id') - name=$(_jq '.name') - - if [[ $name = integration-test-* ]] - then - echo deleting "$name" - $( auth0 actions delete "$id") - fi -done - -logStreams=$( auth0 logs streams list --json ) -for logStream in $( echo "${logStreams}" | jq -r '.[] | @base64' ); do - _jq() { - echo "${logStream}" | base64 --decode | jq -r "${1}" - } - - id=$(_jq '.id') - name=$(_jq '.name') - - if [[ $name = integration-test-* ]] - then - echo deleting "$name" - $( auth0 logs streams delete "$id") - fi -done +users=$( auth0 users search -q "*" --json --no-input | jq -r '.[] | select(.name | test("^integration-.+")) | .user_id' | tr '\n' ' ' ) +if [[ $users ]] +then + echo "Deleting resources for users... id (e.g. IDs): ${users}" + auth0 users delete --force ${users[*]} +fi + +delete_resources "roles" "integration-test-role" "id" +delete_resources "rules" "integration-test-rule" "id" +delete_resources "orgs" "integration-test-org" "id" +delete_resources "actions" "integration-test-" "id" +delete_resources "logs streams" "integration-test-" "id" auth0 domains delete $(./test/integration/scripts/get-custom-domain-id.sh) --no-input