From 068c14ae51ba49462e1c4fc561c103a216caa9dd Mon Sep 17 00:00:00 2001 From: Rita Zerrizuela Date: Thu, 11 Mar 2021 20:12:17 -0300 Subject: [PATCH 01/13] Change Id to ClientId --- internal/cli/apps.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/cli/apps.go b/internal/cli/apps.go index fcdd0899b..e7f5ef9e6 100644 --- a/internal/cli/apps.go +++ b/internal/cli/apps.go @@ -84,7 +84,7 @@ auth0 apps show RunE: func(cmd *cobra.Command, args []string) error { if len(args) == 0 { if canPrompt(cmd) { - input := prompt.TextInput(appID, "Id:", "Id of the application.", true) + input := prompt.TextInput(appID, "Client Id:", "Id of the application.", true) if err := prompt.AskOne(input, &inputs); err != nil { return fmt.Errorf("An unexpected error occurred: %w", err) @@ -136,7 +136,7 @@ auth0 apps delete RunE: func(cmd *cobra.Command, args []string) error { if len(args) == 0 { if canPrompt(cmd) { - input := prompt.TextInput(appID, "Id:", "Id of the application.", true) + input := prompt.TextInput(appID, "Client Id:", "Id of the application.", true) if err := prompt.AskOne(input, &inputs); err != nil { return fmt.Errorf("An unexpected error occurred: %w", err) @@ -304,7 +304,7 @@ auth0 apps update --name myapp --type [native|spa|regular|m2m] RunE: func(cmd *cobra.Command, args []string) error { if len(args) == 0 { if canPrompt(cmd) { - input := prompt.TextInput(appID, "Id:", "Id of the application.", true) + input := prompt.TextInput(appID, "Client Id:", "Id of the application.", true) if err := prompt.AskOne(input, &inputs); err != nil { return fmt.Errorf("An unexpected error occurred: %w", err) From fa419aa8c80946cf0fb984c6f9dce10a995c81f0 Mon Sep 17 00:00:00 2001 From: Rita Zerrizuela Date: Thu, 11 Mar 2021 23:39:13 -0300 Subject: [PATCH 02/13] Add flags PoC --- internal/cli/apps.go | 89 ++++++++++++++++++++++++------------------- internal/cli/flags.go | 50 ++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 40 deletions(-) create mode 100644 internal/cli/flags.go diff --git a/internal/cli/apps.go b/internal/cli/apps.go index fcdd0899b..25ddb0a0a 100644 --- a/internal/cli/apps.go +++ b/internal/cli/apps.go @@ -13,10 +13,38 @@ import ( ) const ( - appID = "id" - appName = "name" - appType = "type" - appDescription = "description" + appID = "id" + appType = "type" +) + +var ( + appName = Flag{ + Name: "Name", + LongForm: "name", + ShortForm: "n", + DefaultValue: "", + Help: "Name of the application.", + IsRequired: true, + IsInteractive: true, + } + appDescription = Flag{ + Name: "Description", + LongForm: "description", + ShortForm: "d", + DefaultValue: "", + Help: "Description of the application. Max character count is 140.", + IsRequired: false, + IsInteractive: true, + } + appAuthMethod = Flag{ + Name: "Auth Method", + LongForm: "auth-method", + ShortForm: "a", + DefaultValue: "", + Help: "Defines the requested authentication method for the token endpoint. Possible values are 'None' (public application without a client secret), 'Post' (application uses HTTP POST parameters) or 'Basic' (application uses HTTP Basic).", + IsRequired: false, + IsInteractive: false, + } ) func appsCmd(cli *cli) *cobra.Command { @@ -182,21 +210,14 @@ func createAppCmd(cli *cli) *cobra.Command { Short: "Create a new application", Long: `Create a new application: -auth0 apps create --name myapp --type [native|spa|regular|m2m] +auth0 apps create --Name myapp --type [native|spa|regular|m2m] `, PreRun: func(cmd *cobra.Command, args []string) { prepareInteractivity(cmd) }, RunE: func(cmd *cobra.Command, args []string) error { - if shouldPrompt(cmd, appName) { - input := prompt.TextInput( - appName, "Name:", - "Name of the application. You can change the name later in the application settings.", - true) - - if err := prompt.AskOne(input, &flags); err != nil { - return fmt.Errorf("An unexpected error occurred: %w", err) - } + if err := appName.Ask(cmd, &flags.Name); err != nil { + return err } if shouldPrompt(cmd, appType) { @@ -215,12 +236,8 @@ auth0 apps create --name myapp --type [native|spa|regular|m2m] } } - if shouldPrompt(cmd, appDescription) { - input := prompt.TextInput(appDescription, "Description:", "Description of the application.", false) - - if err := prompt.AskOne(input, &flags); err != nil { - return fmt.Errorf("An unexpected error occurred: %w", err) - } + if err := appDescription.Ask(cmd, &flags.Description); err != nil { + return err } a := &management.Client{ @@ -257,20 +274,20 @@ auth0 apps create --name myapp --type [native|spa|regular|m2m] }, } - cmd.Flags().StringVarP(&flags.Name, "name", "n", "", "Name of the application.") + appName.RegisterString(cmd, &flags.Name) cmd.Flags().StringVarP(&flags.Type, "type", "t", "", "Type of application:\n"+ "- native: mobile, desktop, CLI and smart device apps running natively.\n"+ "- spa (single page application): a JavaScript front-end app that uses an API.\n"+ "- regular: Traditional web app using redirects.\n"+ "- m2m (machine to machine): CLIs, daemons or services running on your backend.") - cmd.Flags().StringVarP(&flags.Description, "description", "d", "", "Description of the application. Max character count is 140.") + appDescription.RegisterString(cmd, &flags.Description) cmd.Flags().StringSliceVarP(&flags.Callbacks, "callbacks", "c", nil, "After the user authenticates we will only call back to any of these URLs. You can specify multiple valid URLs by comma-separating them (typically to handle different environments like QA or testing). Make sure to specify the protocol (https://) otherwise the callback may fail in some cases. With the exception of custom URI schemes for native apps, all callbacks should use protocol https://.") cmd.Flags().StringSliceVarP(&flags.AllowedOrigins, "origins", "o", nil, "Comma-separated list of URLs allowed to make requests from JavaScript to Auth0 API (typically used with CORS). By default, all your callback URLs will be allowed. This field allows you to enter other origins if necessary. You can also use wildcards at the subdomain level (e.g., https://*.contoso.com). Query strings and hash information are not taken into account when validating these URLs.") cmd.Flags().StringSliceVarP(&flags.AllowedWebOrigins, "web-origins", "w", nil, "Comma-separated list of allowed origins for use with Cross-Origin Authentication, Device Flow, and web message response mode.") cmd.Flags().StringSliceVarP(&flags.AllowedLogoutURLs, "logout-urls", "l", nil, "Comma-separated list of URLs that are valid to redirect to after logout from Auth0. Wildcards are allowed for subdomains.") - cmd.Flags().StringVarP(&flags.AuthMethod, "auth-method", "a", "", "Defines the requested authentication method for the token endpoint. Possible values are 'None' (public application without a client secret), 'Post' (application uses HTTP POST parameters) or 'Basic' (application uses HTTP Basic).") + appAuthMethod.RegisterString(cmd, &flags.AuthMethod) cmd.Flags().StringSliceVarP(&flags.Grants, "grants", "g", nil, "List of grant types supported for this application. Can include code, implicit, refresh-token, credentials, password, password-realm, mfa-oob, mfa-otp, mfa-recovery-code, and device-code.") - mustRequireFlags(cmd, appName, appType) + mustRequireFlags(cmd, appName.LongForm, appType) return cmd } @@ -296,7 +313,7 @@ func updateAppCmd(cli *cli) *cobra.Command { Short: "Update an application", Long: `Update an application: -auth0 apps update --name myapp --type [native|spa|regular|m2m] +auth0 apps update --Name myapp --type [native|spa|regular|m2m] `, PreRun: func(cmd *cobra.Command, args []string) { prepareInteractivity(cmd) @@ -316,12 +333,8 @@ auth0 apps update --name myapp --type [native|spa|regular|m2m] inputs.ID = args[0] } - if shouldPromptWhenFlagless(cmd, appName) { - input := prompt.TextInput(appName, "Name:", "Name of the application", true) - - if err := prompt.AskOne(input, &inputs); err != nil { - return fmt.Errorf("An unexpected error occurred: %w", err) - } + if err := appName.AskUpdate(cmd, &inputs.Name); err != nil { + return err } if shouldPromptWhenFlagless(cmd, appType) { @@ -340,12 +353,8 @@ auth0 apps update --name myapp --type [native|spa|regular|m2m] } } - if shouldPromptWhenFlagless(cmd, appDescription) { - input := prompt.TextInput(appDescription, "Description:", "Description of the application.", false) - - if err := prompt.AskOne(input, &inputs); err != nil { - return fmt.Errorf("An unexpected error occurred: %w", err) - } + if err := appDescription.AskUpdate(cmd, &inputs.Description); err != nil { + return err } if shouldPromptWhenFlagless(cmd, "CallbacksString") { @@ -437,18 +446,18 @@ auth0 apps update --name myapp --type [native|spa|regular|m2m] }, } - cmd.Flags().StringVarP(&inputs.Name, "name", "n", "", "Name of the application.") + appName.RegisterString(cmd, &inputs.Name) cmd.Flags().StringVarP(&inputs.Type, "type", "t", "", "Type of application:\n"+ "- native: mobile, desktop, CLI and smart device apps running natively.\n"+ "- spa (single page application): a JavaScript front-end app that uses an API.\n"+ "- regular: Traditional web app using redirects.\n"+ "- m2m (machine to machine): CLIs, daemons or services running on your backend.") - cmd.Flags().StringVarP(&inputs.Description, "description", "d", "", "Description of the application. Max character count is 140.") + appDescription.RegisterString(cmd, &inputs.Description) cmd.Flags().StringSliceVarP(&inputs.Callbacks, "callbacks", "c", nil, "After the user authenticates we will only call back to any of these URLs. You can specify multiple valid URLs by comma-separating them (typically to handle different environments like QA or testing). Make sure to specify the protocol (https://) otherwise the callback may fail in some cases. With the exception of custom URI schemes for native apps, all callbacks should use protocol https://.") cmd.Flags().StringSliceVarP(&inputs.AllowedOrigins, "origins", "o", nil, "Comma-separated list of URLs allowed to make requests from JavaScript to Auth0 API (typically used with CORS). By default, all your callback URLs will be allowed. This field allows you to enter other origins if necessary. You can also use wildcards at the subdomain level (e.g., https://*.contoso.com). Query strings and hash information are not taken into account when validating these URLs.") cmd.Flags().StringSliceVarP(&inputs.AllowedWebOrigins, "web-origins", "w", nil, "Comma-separated list of allowed origins for use with Cross-Origin Authentication, Device Flow, and web message response mode.") cmd.Flags().StringSliceVarP(&inputs.AllowedLogoutURLs, "logout-urls", "l", nil, "Comma-separated list of URLs that are valid to redirect to after logout from Auth0. Wildcards are allowed for subdomains.") - cmd.Flags().StringVarP(&inputs.AuthMethod, "auth-method", "a", "", "Defines the requested authentication method for the token endpoint. Possible values are 'None' (public application without a client secret), 'Post' (application uses HTTP POST parameters) or 'Basic' (application uses HTTP Basic).") + appAuthMethod.RegisterString(cmd, &inputs.AuthMethod) cmd.Flags().StringSliceVarP(&inputs.Grants, "grants", "g", nil, "List of grant types supported for this application. Can include code, implicit, refresh-token, credentials, password, password-realm, mfa-oob, mfa-otp, mfa-recovery-code, and device-code.") return cmd diff --git a/internal/cli/flags.go b/internal/cli/flags.go new file mode 100644 index 000000000..6d5e2d90c --- /dev/null +++ b/internal/cli/flags.go @@ -0,0 +1,50 @@ +package cli + +import ( + "fmt" + + "github.com/auth0/auth0-cli/internal/prompt" + "github.com/spf13/cobra" +) + +type Flag struct { + Name string + LongForm string + ShortForm string + DefaultValue string + Help string + IsRequired bool + IsInteractive bool +} + +func (f *Flag) Ask(cmd *cobra.Command, value interface{}) error { + return ask(cmd, f, value, false) +} + +func (f *Flag) AskUpdate(cmd *cobra.Command, value interface{}) error { + return ask(cmd, f, value, true) +} + +func (f *Flag) RegisterString(cmd *cobra.Command, value *string) { + cmd.Flags().StringVarP(value, f.LongForm, f.ShortForm, f.DefaultValue, f.Help) +} + +func ask(cmd *cobra.Command, f *Flag, value interface{}, isUpdate bool) error { + var shouldAsk bool + + if isUpdate { + shouldAsk = shouldPromptWhenFlagless(cmd, f.LongForm) + } else { + shouldAsk = shouldPrompt(cmd, f.LongForm) + } + + if f.IsInteractive && shouldAsk { + input := prompt.TextInput("", fmt.Sprintf("%s:", f.Name), f.Help, f.IsRequired) + + if err := prompt.AskOne(input, value); err != nil { + return fmt.Errorf("An unexpected error occurred: %w", err) + } + } + + return nil +} From 47bb30ce89584b6548d23ccfa4c17118d941e9e8 Mon Sep 17 00:00:00 2001 From: Rita Zerrizuela Date: Fri, 12 Mar 2021 00:01:51 -0300 Subject: [PATCH 03/13] Remove IsInteractive --- internal/cli/apps.go | 3 --- internal/cli/flags.go | 3 +-- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/internal/cli/apps.go b/internal/cli/apps.go index 25ddb0a0a..50c8834a4 100644 --- a/internal/cli/apps.go +++ b/internal/cli/apps.go @@ -25,7 +25,6 @@ var ( DefaultValue: "", Help: "Name of the application.", IsRequired: true, - IsInteractive: true, } appDescription = Flag{ Name: "Description", @@ -34,7 +33,6 @@ var ( DefaultValue: "", Help: "Description of the application. Max character count is 140.", IsRequired: false, - IsInteractive: true, } appAuthMethod = Flag{ Name: "Auth Method", @@ -43,7 +41,6 @@ var ( DefaultValue: "", Help: "Defines the requested authentication method for the token endpoint. Possible values are 'None' (public application without a client secret), 'Post' (application uses HTTP POST parameters) or 'Basic' (application uses HTTP Basic).", IsRequired: false, - IsInteractive: false, } ) diff --git a/internal/cli/flags.go b/internal/cli/flags.go index 6d5e2d90c..f8ac5fe68 100644 --- a/internal/cli/flags.go +++ b/internal/cli/flags.go @@ -14,7 +14,6 @@ type Flag struct { DefaultValue string Help string IsRequired bool - IsInteractive bool } func (f *Flag) Ask(cmd *cobra.Command, value interface{}) error { @@ -38,7 +37,7 @@ func ask(cmd *cobra.Command, f *Flag, value interface{}, isUpdate bool) error { shouldAsk = shouldPrompt(cmd, f.LongForm) } - if f.IsInteractive && shouldAsk { + if shouldAsk { input := prompt.TextInput("", fmt.Sprintf("%s:", f.Name), f.Help, f.IsRequired) if err := prompt.AskOne(input, value); err != nil { From 5a0c1a0c534687770a1c49712a04e23214d9415b Mon Sep 17 00:00:00 2001 From: Rita Zerrizuela Date: Fri, 12 Mar 2021 11:47:34 -0300 Subject: [PATCH 04/13] Add RegisterStringU --- internal/cli/apis.go | 58 +++++++++++++++++++++---------------------- internal/cli/apps.go | 12 ++++----- internal/cli/flags.go | 24 ++++++++++++++++-- 3 files changed, 56 insertions(+), 38 deletions(-) diff --git a/internal/cli/apis.go b/internal/cli/apis.go index 1e6b50d27..6203ed4b7 100644 --- a/internal/cli/apis.go +++ b/internal/cli/apis.go @@ -13,11 +13,28 @@ import ( const ( apiID = "id" - apiName = "name" - apiIdentifier = "identifier" apiScopes = "scopes" ) +var ( + apiName = Flag{ + Name: "Name", + LongForm: "name", + ShortForm: "n", + DefaultValue: "", + Help: "Name of the API.", + IsRequired: true, + } + apiIdentifier = Flag{ + Name: "Identifier", + LongForm: "identifier", + ShortForm: "i", + DefaultValue: "", + Help: "Identifier of the API. Cannot be changed once set.", + IsRequired: true, + } +) + func apisCmd(cli *cli) *cobra.Command { cmd := &cobra.Command{ Use: "apis", @@ -147,26 +164,12 @@ auth0 apis create --name myapi --identifier http://my-api prepareInteractivity(cmd) }, RunE: func(cmd *cobra.Command, args []string) error { - if shouldPrompt(cmd, apiName) { - input := prompt.TextInput( - apiName, "Name:", - "Name of the API. You can change the name later in the API settings.", - true) - - if err := prompt.AskOne(input, &flags); err != nil { - return fmt.Errorf("An unexpected error occurred: %w", err) - } + if err := apiName.Ask(cmd, &flags.Name); err != nil { + return err } - if shouldPrompt(cmd, apiIdentifier) { - input := prompt.TextInput( - apiIdentifier, "Identifier:", - "Identifier of the API. Cannot be changed once set.", - true) - - if err := prompt.AskOne(input, &flags); err != nil { - return fmt.Errorf("An unexpected error occurred: %w", err) - } + if err := apiIdentifier.Ask(cmd, &flags.Identifier); err != nil { + return err } if shouldPrompt(cmd, apiScopes) { @@ -199,10 +202,9 @@ auth0 apis create --name myapi --identifier http://my-api }, } - cmd.Flags().StringVarP(&flags.Name, apiName, "n", "", "Name of the API.") - cmd.Flags().StringVarP(&flags.Identifier, apiIdentifier, "i", "", "Identifier of the API.") + apiName.RegisterString(cmd, &flags.Name) + apiIdentifier.RegisterString(cmd, &flags.Identifier) cmd.Flags().StringVarP(&flags.Scopes, apiScopes, "s", "", "Space-separated list of scopes.") - mustRequireFlags(cmd, apiName, apiIdentifier) return cmd } @@ -240,12 +242,8 @@ auth0 apis update --name myapi inputs.ID = args[0] } - if shouldPromptWhenFlagless(cmd, apiName) { - input := prompt.TextInput(apiName, "Name:", "Name of the API.", true) - - if err := prompt.AskOne(input, &inputs); err != nil { - return fmt.Errorf("An unexpected error occurred: %w", err) - } + if err := apiName.AskU(cmd, &inputs.Name); err != nil { + return err } if shouldPromptWhenFlagless(cmd, apiScopes) { @@ -289,7 +287,7 @@ auth0 apis update --name myapi }, } - cmd.Flags().StringVarP(&inputs.Name, apiName, "n", "", "Name of the API.") + apiName.RegisterStringU(cmd, &inputs.Name) cmd.Flags().StringVarP(&inputs.Scopes, apiScopes, "s", "", "Space-separated list of scopes.") return cmd diff --git a/internal/cli/apps.go b/internal/cli/apps.go index 50c8834a4..b0558574d 100644 --- a/internal/cli/apps.go +++ b/internal/cli/apps.go @@ -284,7 +284,7 @@ auth0 apps create --Name myapp --type [native|spa|regular|m2m] cmd.Flags().StringSliceVarP(&flags.AllowedLogoutURLs, "logout-urls", "l", nil, "Comma-separated list of URLs that are valid to redirect to after logout from Auth0. Wildcards are allowed for subdomains.") appAuthMethod.RegisterString(cmd, &flags.AuthMethod) cmd.Flags().StringSliceVarP(&flags.Grants, "grants", "g", nil, "List of grant types supported for this application. Can include code, implicit, refresh-token, credentials, password, password-realm, mfa-oob, mfa-otp, mfa-recovery-code, and device-code.") - mustRequireFlags(cmd, appName.LongForm, appType) + mustRequireFlags(cmd, appType) return cmd } @@ -330,7 +330,7 @@ auth0 apps update --Name myapp --type [native|spa|regular|m2m] inputs.ID = args[0] } - if err := appName.AskUpdate(cmd, &inputs.Name); err != nil { + if err := appName.AskU(cmd, &inputs.Name); err != nil { return err } @@ -350,7 +350,7 @@ auth0 apps update --Name myapp --type [native|spa|regular|m2m] } } - if err := appDescription.AskUpdate(cmd, &inputs.Description); err != nil { + if err := appDescription.AskU(cmd, &inputs.Description); err != nil { return err } @@ -443,18 +443,18 @@ auth0 apps update --Name myapp --type [native|spa|regular|m2m] }, } - appName.RegisterString(cmd, &inputs.Name) + appName.RegisterStringU(cmd, &inputs.Name) cmd.Flags().StringVarP(&inputs.Type, "type", "t", "", "Type of application:\n"+ "- native: mobile, desktop, CLI and smart device apps running natively.\n"+ "- spa (single page application): a JavaScript front-end app that uses an API.\n"+ "- regular: Traditional web app using redirects.\n"+ "- m2m (machine to machine): CLIs, daemons or services running on your backend.") - appDescription.RegisterString(cmd, &inputs.Description) + appDescription.RegisterStringU(cmd, &inputs.Description) cmd.Flags().StringSliceVarP(&inputs.Callbacks, "callbacks", "c", nil, "After the user authenticates we will only call back to any of these URLs. You can specify multiple valid URLs by comma-separating them (typically to handle different environments like QA or testing). Make sure to specify the protocol (https://) otherwise the callback may fail in some cases. With the exception of custom URI schemes for native apps, all callbacks should use protocol https://.") cmd.Flags().StringSliceVarP(&inputs.AllowedOrigins, "origins", "o", nil, "Comma-separated list of URLs allowed to make requests from JavaScript to Auth0 API (typically used with CORS). By default, all your callback URLs will be allowed. This field allows you to enter other origins if necessary. You can also use wildcards at the subdomain level (e.g., https://*.contoso.com). Query strings and hash information are not taken into account when validating these URLs.") cmd.Flags().StringSliceVarP(&inputs.AllowedWebOrigins, "web-origins", "w", nil, "Comma-separated list of allowed origins for use with Cross-Origin Authentication, Device Flow, and web message response mode.") cmd.Flags().StringSliceVarP(&inputs.AllowedLogoutURLs, "logout-urls", "l", nil, "Comma-separated list of URLs that are valid to redirect to after logout from Auth0. Wildcards are allowed for subdomains.") - appAuthMethod.RegisterString(cmd, &inputs.AuthMethod) + appAuthMethod.RegisterStringU(cmd, &inputs.AuthMethod) cmd.Flags().StringSliceVarP(&inputs.Grants, "grants", "g", nil, "List of grant types supported for this application. Can include code, implicit, refresh-token, credentials, password, password-realm, mfa-oob, mfa-otp, mfa-recovery-code, and device-code.") return cmd diff --git a/internal/cli/flags.go b/internal/cli/flags.go index f8ac5fe68..42e98af8f 100644 --- a/internal/cli/flags.go +++ b/internal/cli/flags.go @@ -20,12 +20,16 @@ func (f *Flag) Ask(cmd *cobra.Command, value interface{}) error { return ask(cmd, f, value, false) } -func (f *Flag) AskUpdate(cmd *cobra.Command, value interface{}) error { +func (f *Flag) AskU(cmd *cobra.Command, value interface{}) error { return ask(cmd, f, value, true) } func (f *Flag) RegisterString(cmd *cobra.Command, value *string) { - cmd.Flags().StringVarP(value, f.LongForm, f.ShortForm, f.DefaultValue, f.Help) + registerString(cmd, f, value, false) +} + +func (f *Flag) RegisterStringU(cmd *cobra.Command, value *string) { + registerString(cmd, f, value, true) } func ask(cmd *cobra.Command, f *Flag, value interface{}, isUpdate bool) error { @@ -47,3 +51,19 @@ func ask(cmd *cobra.Command, f *Flag, value interface{}, isUpdate bool) error { return nil } + +func registerString(cmd *cobra.Command, f *Flag, value *string, isUpdate bool) { + cmd.Flags().StringVarP(value, f.LongForm, f.ShortForm, f.DefaultValue, f.Help) + + if err := markFlagRequired(cmd, f, isUpdate); err != nil { + panic(fmt.Errorf("An unexpected error occurred: %w", err)) // TODO: Handle + } +} + +func markFlagRequired(cmd *cobra.Command, f *Flag, isUpdate bool) error { + if f.IsRequired && !isUpdate { + return cmd.MarkFlagRequired(f.LongForm) + } + + return nil +} From 6142d56cbb0b55fc9fc90b6e4a8875b2a1278ed0 Mon Sep 17 00:00:00 2001 From: Rita Zerrizuela Date: Fri, 12 Mar 2021 11:54:18 -0300 Subject: [PATCH 05/13] Fix uppercasing --- internal/cli/apps.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/cli/apps.go b/internal/cli/apps.go index b0558574d..460ce69c3 100644 --- a/internal/cli/apps.go +++ b/internal/cli/apps.go @@ -207,7 +207,7 @@ func createAppCmd(cli *cli) *cobra.Command { Short: "Create a new application", Long: `Create a new application: -auth0 apps create --Name myapp --type [native|spa|regular|m2m] +auth0 apps create --name myapp --type [native|spa|regular|m2m] `, PreRun: func(cmd *cobra.Command, args []string) { prepareInteractivity(cmd) @@ -310,7 +310,7 @@ func updateAppCmd(cli *cli) *cobra.Command { Short: "Update an application", Long: `Update an application: -auth0 apps update --Name myapp --type [native|spa|regular|m2m] +auth0 apps update --name myapp --type [native|spa|regular|m2m] `, PreRun: func(cmd *cobra.Command, args []string) { prepareInteractivity(cmd) From d8667ff15464c734d2085cb3d2332707d3341912 Mon Sep 17 00:00:00 2001 From: Andy Herzog Date: Fri, 12 Mar 2021 09:39:34 -0700 Subject: [PATCH 06/13] fix: version for release binaries --- .goreleaser.yml | 5 +++++ .../{build-info/build_info.go => buildinfo/buildinfo.go} | 0 internal/cli/cli.go | 2 +- internal/cli/root.go | 5 +++-- 4 files changed, 9 insertions(+), 3 deletions(-) rename internal/{build-info/build_info.go => buildinfo/buildinfo.go} (100%) diff --git a/.goreleaser.yml b/.goreleaser.yml index d2ce60741..42f9bd3c6 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -10,6 +10,11 @@ builds: - linux - windows binary: auth0 + ldflags: + - -X github.com/auth0/auth0-cli/internal/buildinfo.Version={{.Version}} + - -X github.com/auth0/auth0-cli/internal/buildinfo.Revision={{.Commit}} + - -X github.com/auth0/auth0-cli/internal/buildinfo.BuildUser=goreleaser' + - -X github.com/auth0/auth0-cli/internal/buildinfo.BuildDate={{.Date}}' archives: - replacements: darwin: Darwin diff --git a/internal/build-info/build_info.go b/internal/buildinfo/buildinfo.go similarity index 100% rename from internal/build-info/build_info.go rename to internal/buildinfo/buildinfo.go diff --git a/internal/cli/cli.go b/internal/cli/cli.go index 47a3cb31b..1e2c36e73 100644 --- a/internal/cli/cli.go +++ b/internal/cli/cli.go @@ -17,7 +17,7 @@ import ( "github.com/auth0/auth0-cli/internal/ansi" "github.com/auth0/auth0-cli/internal/auth" "github.com/auth0/auth0-cli/internal/auth0" - "github.com/auth0/auth0-cli/internal/build-info" + "github.com/auth0/auth0-cli/internal/buildinfo" "github.com/auth0/auth0-cli/internal/display" "github.com/lestrrat-go/jwx/jwt" "github.com/spf13/cobra" diff --git a/internal/cli/root.go b/internal/cli/root.go index 9003656b3..26ca3bc95 100644 --- a/internal/cli/root.go +++ b/internal/cli/root.go @@ -2,11 +2,12 @@ package cli import ( "context" + "os" + "github.com/auth0/auth0-cli/internal/ansi" - "github.com/auth0/auth0-cli/internal/build-info" + "github.com/auth0/auth0-cli/internal/buildinfo" "github.com/auth0/auth0-cli/internal/display" "github.com/spf13/cobra" - "os" ) // Execute is the primary entrypoint of the CLI app. From 3147cb9181719ed8edd912e65da0d50e4ea64fda Mon Sep 17 00:00:00 2001 From: Chris Scott Date: Fri, 12 Mar 2021 12:55:47 -0500 Subject: [PATCH 07/13] Add flag to query logs by client ID. --- internal/cli/logs.go | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/internal/cli/logs.go b/internal/cli/logs.go index 4e97f71fd..4e73b94d7 100644 --- a/internal/cli/logs.go +++ b/internal/cli/logs.go @@ -10,7 +10,7 @@ import ( "gopkg.in/auth0.v5/management" ) -func getLatestLogs(cli *cli, n int) ([]*management.Log, error) { +func getLatestLogs(cli *cli, n int, ClientID string) ([]*management.Log, error) { page := 0 perPage := n @@ -20,18 +20,24 @@ func getLatestLogs(cli *cli, n int) ([]*management.Log, error) { perPage = 1000 } - return cli.api.Log.List( + queryParams := []management.RequestOption{ management.Parameter("sort", "date:-1"), management.Parameter("page", fmt.Sprintf("%d", page)), - management.Parameter("per_page", fmt.Sprintf("%d", perPage)), - ) + management.Parameter("per_page", fmt.Sprintf("%d", perPage))} + + if ClientID != "" { + queryParams = append(queryParams, management.Query(fmt.Sprintf(`client_id:"%s"`, ClientID))) + } + + return cli.api.Log.List(queryParams...) } func logsCmd(cli *cli) *cobra.Command { var flags struct { - Num int - Follow bool - NoColor bool + Num int + Follow bool + NoColor bool + ClientID string } cmd := &cobra.Command{ @@ -42,7 +48,7 @@ Show the tenant logs. `, RunE: func(cmd *cobra.Command, args []string) error { lastLogID := "" - list, err := getLatestLogs(cli, flags.Num) + list, err := getLatestLogs(cli, flags.Num, flags.ClientID) if err != nil { return fmt.Errorf("An unexpected error occurred while getting logs: %v", err) } @@ -68,12 +74,18 @@ Show the tenant logs. defer close(logsCh) for { - list, err = cli.api.Log.List( + queryParams := []management.RequestOption{ management.Query(fmt.Sprintf("log_id:[%s TO *]", lastLogID)), management.Parameter("page", "0"), management.Parameter("per_page", "100"), management.Parameter("sort", "date:-1"), - ) + } + + if flags.ClientID != "" { + queryParams = append(queryParams, management.Query(fmt.Sprintf(`client_id:"%s"`, flags.ClientID))) + } + + list, err = cli.api.Log.List(queryParams...) if err != nil { cli.renderer.Errorf("An unexpected error occurred while getting logs: %v", err) return @@ -109,6 +121,7 @@ Show the tenant logs. cmd.Flags().IntVarP(&flags.Num, "num-entries", "n", 100, "the number of log entries to print") cmd.Flags().BoolVarP(&flags.Follow, "follow", "f", false, "Specify if the logs should be streamed") cmd.Flags().BoolVar(&flags.NoColor, "no-color", false, "turn off colored print") + cmd.Flags().StringVarP(&flags.ClientID, "client-id", "c", "", "client ID to display logs for") return cmd } From b575bfdd061f864a07ba49e137600a6b972fa16f Mon Sep 17 00:00:00 2001 From: Chris Scott Date: Fri, 12 Mar 2021 14:04:11 -0500 Subject: [PATCH 08/13] Move client-id flag to an optional argument --- internal/cli/logs.go | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/internal/cli/logs.go b/internal/cli/logs.go index 4e73b94d7..ed8dd9639 100644 --- a/internal/cli/logs.go +++ b/internal/cli/logs.go @@ -34,21 +34,30 @@ func getLatestLogs(cli *cli, n int, ClientID string) ([]*management.Log, error) func logsCmd(cli *cli) *cobra.Command { var flags struct { - Num int - Follow bool - NoColor bool + Num int + Follow bool + NoColor bool + } + + var inputs struct { ClientID string } cmd := &cobra.Command{ - Use: "logs", + Use: "logs [client-id]", + Args: cobra.MaximumNArgs(1), Short: "Show the tenant logs", - Long: `auth0 logs -Show the tenant logs. + Long: `Show the tenant logs: + +auth0 logs [client-id] `, RunE: func(cmd *cobra.Command, args []string) error { + inputs.ClientID = "" + if len(args) == 1 { + inputs.ClientID = args[0] + } lastLogID := "" - list, err := getLatestLogs(cli, flags.Num, flags.ClientID) + list, err := getLatestLogs(cli, flags.Num, inputs.ClientID) if err != nil { return fmt.Errorf("An unexpected error occurred while getting logs: %v", err) } @@ -81,8 +90,8 @@ Show the tenant logs. management.Parameter("sort", "date:-1"), } - if flags.ClientID != "" { - queryParams = append(queryParams, management.Query(fmt.Sprintf(`client_id:"%s"`, flags.ClientID))) + if inputs.ClientID != "" { + queryParams = append(queryParams, management.Query(fmt.Sprintf(`client_id:"%s"`, inputs.ClientID))) } list, err = cli.api.Log.List(queryParams...) @@ -121,7 +130,6 @@ Show the tenant logs. cmd.Flags().IntVarP(&flags.Num, "num-entries", "n", 100, "the number of log entries to print") cmd.Flags().BoolVarP(&flags.Follow, "follow", "f", false, "Specify if the logs should be streamed") cmd.Flags().BoolVar(&flags.NoColor, "no-color", false, "turn off colored print") - cmd.Flags().StringVarP(&flags.ClientID, "client-id", "c", "", "client ID to display logs for") return cmd } From 2e15176b5307b9ee5a22bdcff96b830fc6f9dbc9 Mon Sep 17 00:00:00 2001 From: "Jorge L. Fatta" Date: Fri, 12 Mar 2021 17:18:04 -0300 Subject: [PATCH 09/13] test: keychain abstraction (#149) * test: keychain abstraction (secrets) * check error on test * fix typo --- internal/auth/secrets_test.go | 63 +++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 internal/auth/secrets_test.go diff --git a/internal/auth/secrets_test.go b/internal/auth/secrets_test.go new file mode 100644 index 000000000..e98a3fdc1 --- /dev/null +++ b/internal/auth/secrets_test.go @@ -0,0 +1,63 @@ +package auth + +import ( + "testing" + + "github.com/zalando/go-keyring" +) + +func TestSecrets(t *testing.T) { + t.Run("fail: not found", func(t *testing.T) { + // init underlying keychain manager + keyring.MockInit() + + kr := &Keyring{} + _, err := kr.Get("mynamespace", "foo") + + if got, want := err, keyring.ErrNotFound; got != want { + t.Fatalf("wanted error: %v, got: %v", want, got) + } + }) + + t.Run("succeed: get secret", func(t *testing.T) { + // init underlying keychain manager + keyring.MockInit() + + // set with the underlying manager: + err := keyring.Set("mynamespace", "foo", "bar") + if err != nil { + t.Fatal(err) + } + + kr := &Keyring{} + v, err := kr.Get("mynamespace", "foo") + if err != nil { + t.Fatal(err) + } + + if got, want := v, "bar"; got != want { + t.Fatalf("wanted error: %v, got: %v", want, got) + } + }) + + t.Run("succeed: set secret", func(t *testing.T) { + // init underlying keychain manager + keyring.MockInit() + + kr := &Keyring{} + err := kr.Set("mynamespace", "foo", "bar") + if err != nil { + t.Fatal(err) + } + + // get with the underlying manager: + v, err := keyring.Get("mynamespace", "foo") + if err != nil { + t.Fatal(err) + } + + if got, want := v, "bar"; got != want { + t.Fatalf("wanted secret: %v, got: %v", want, got) + } + }) +} From da3e724416ca18ee01ee2528545c8024e82b0e66 Mon Sep 17 00:00:00 2001 From: Chris Scott Date: Fri, 12 Mar 2021 15:42:42 -0500 Subject: [PATCH 10/13] Update internal/cli/logs.go Co-authored-by: Rita Zerrizuela --- internal/cli/logs.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/cli/logs.go b/internal/cli/logs.go index ed8dd9639..dd621d1ec 100644 --- a/internal/cli/logs.go +++ b/internal/cli/logs.go @@ -10,7 +10,7 @@ import ( "gopkg.in/auth0.v5/management" ) -func getLatestLogs(cli *cli, n int, ClientID string) ([]*management.Log, error) { +func getLatestLogs(cli *cli, n int, clientID string) ([]*management.Log, error) { page := 0 perPage := n From 6bf267e793219408ce2bc551935903d9f3c340f3 Mon Sep 17 00:00:00 2001 From: Chris Scott Date: Fri, 12 Mar 2021 15:42:50 -0500 Subject: [PATCH 11/13] Update internal/cli/logs.go Co-authored-by: Rita Zerrizuela --- internal/cli/logs.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/cli/logs.go b/internal/cli/logs.go index dd621d1ec..7854a449f 100644 --- a/internal/cli/logs.go +++ b/internal/cli/logs.go @@ -25,7 +25,7 @@ func getLatestLogs(cli *cli, n int, clientID string) ([]*management.Log, error) management.Parameter("page", fmt.Sprintf("%d", page)), management.Parameter("per_page", fmt.Sprintf("%d", perPage))} - if ClientID != "" { + if clientID != "" { queryParams = append(queryParams, management.Query(fmt.Sprintf(`client_id:"%s"`, ClientID))) } From ced4e3f383a770434f6cc630b0f0e58677819d2e Mon Sep 17 00:00:00 2001 From: Chris Scott Date: Fri, 12 Mar 2021 15:42:57 -0500 Subject: [PATCH 12/13] Update internal/cli/logs.go Co-authored-by: Rita Zerrizuela --- internal/cli/logs.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/cli/logs.go b/internal/cli/logs.go index 7854a449f..0ae9a090e 100644 --- a/internal/cli/logs.go +++ b/internal/cli/logs.go @@ -26,7 +26,7 @@ func getLatestLogs(cli *cli, n int, clientID string) ([]*management.Log, error) management.Parameter("per_page", fmt.Sprintf("%d", perPage))} if clientID != "" { - queryParams = append(queryParams, management.Query(fmt.Sprintf(`client_id:"%s"`, ClientID))) + queryParams = append(queryParams, management.Query(fmt.Sprintf(`client_id:"%s"`, clientID))) } return cli.api.Log.List(queryParams...) From 2bf07c97add35858493300ae9e82c30c4f14bb92 Mon Sep 17 00:00:00 2001 From: Rita Zerrizuela Date: Fri, 12 Mar 2021 20:13:17 -0300 Subject: [PATCH 13/13] Display empty KV fields --- internal/display/display.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/internal/display/display.go b/internal/display/display.go index b89beb07e..b19c436ab 100644 --- a/internal/display/display.go +++ b/internal/display/display.go @@ -113,11 +113,7 @@ func (r *Renderer) Result(data View) { for _, pair := range v.KeyValues() { k := pair[0] v := pair[1] - - // NOTE(cyx): We can either nuke it or annotate with ``. For now we're choosing to nuke it. - if v != "" { - kvs = append(kvs, []string{k, v}) - } + kvs = append(kvs, []string{k, v}) } writeTable(r.ResultWriter, nil, kvs) }