From da352f4687995b1470713bd8530dbe37461a7a99 Mon Sep 17 00:00:00 2001 From: Rita Zerrizuela Date: Mon, 14 Jun 2021 15:15:38 -0300 Subject: [PATCH] Add custom domains CRUD (#311) * Add custom domains CRUD * Add autogenerated docs * Address review feedback --- docs/auth0_branding.md | 1 + docs/auth0_branding_domains.md | 29 +++ docs/auth0_branding_domains_create.md | 38 +++ docs/auth0_branding_domains_delete.md | 35 +++ docs/auth0_branding_domains_list.md | 36 +++ docs/auth0_branding_domains_show.md | 35 +++ docs/auth0_branding_domains_verify.md | 35 +++ docs/auth0_logs_streams_create.md | 2 +- docs/auth0_logs_streams_update.md | 2 +- internal/auth/auth.go | 3 +- internal/auth/auth_test.go | 2 +- internal/auth0/custom_domain.go | 13 ++ internal/cli/apis.go | 2 +- internal/cli/apps.go | 2 +- internal/cli/branding.go | 1 + internal/cli/custom_domains.go | 319 ++++++++++++++++++++++++++ internal/cli/log_streams.go | 12 +- internal/cli/roles.go | 2 +- internal/cli/rules.go | 2 +- internal/cli/users.go | 2 +- internal/display/custom_domain.go | 97 ++++++++ internal/display/roles.go | 2 +- internal/display/rules.go | 2 +- 23 files changed, 659 insertions(+), 15 deletions(-) create mode 100644 docs/auth0_branding_domains.md create mode 100644 docs/auth0_branding_domains_create.md create mode 100644 docs/auth0_branding_domains_delete.md create mode 100644 docs/auth0_branding_domains_list.md create mode 100644 docs/auth0_branding_domains_show.md create mode 100644 docs/auth0_branding_domains_verify.md create mode 100644 internal/cli/custom_domains.go create mode 100644 internal/display/custom_domain.go diff --git a/docs/auth0_branding.md b/docs/auth0_branding.md index 8374beda2..a74977b6d 100644 --- a/docs/auth0_branding.md +++ b/docs/auth0_branding.md @@ -22,6 +22,7 @@ Manage branding options. ### SEE ALSO * [auth0](auth0.md) - Supercharge your development workflow. +* [auth0 branding domains](auth0_branding_domains.md) - Manage custom domains * [auth0 branding show](auth0_branding_show.md) - Display the custom branding settings for Universal Login * [auth0 branding templates](auth0_branding_templates.md) - Manage custom page templates * [auth0 branding update](auth0_branding_update.md) - Update the custom branding settings for Universal Login diff --git a/docs/auth0_branding_domains.md b/docs/auth0_branding_domains.md new file mode 100644 index 000000000..e9b46c9fb --- /dev/null +++ b/docs/auth0_branding_domains.md @@ -0,0 +1,29 @@ +## auth0 branding domains + +Manage custom domains. + +### Flags + +``` + -h, --help help for domains +``` + +### Flags inherited from parent commands + +``` + --debug Enable debug mode. + --force Skip confirmation. + --format string Command output format. Options: json. + --no-color Disable colors. + --no-input Disable interactivity. + --tenant string Specific tenant to use. +``` + +### SEE ALSO + +* [auth0 branding](auth0_branding.md) - Manage branding options +* [auth0 branding domains create](auth0_branding_domains_create.md) - Create a custom domain +* [auth0 branding domains delete](auth0_branding_domains_delete.md) - Delete a custom domain +* [auth0 branding domains list](auth0_branding_domains_list.md) - List your custom domains +* [auth0 branding domains show](auth0_branding_domains_show.md) - Show a custom domain +* [auth0 branding domains verify](auth0_branding_domains_verify.md) - Verify a custom domain diff --git a/docs/auth0_branding_domains_create.md b/docs/auth0_branding_domains_create.md new file mode 100644 index 000000000..32477720f --- /dev/null +++ b/docs/auth0_branding_domains_create.md @@ -0,0 +1,38 @@ +## auth0 branding domains create + +Create a custom domain. + +``` +auth0 branding domains create [flags] +``` + +### Examples + +``` +auth0 branding domains create +auth0 branding domains create +``` + +### Flags + +``` + -d, --domain string Domain name. + -h, --help help for create + -t, --type string Custom domain provisioning type. Must be 'auth0' for Auth0-managed certs or 'self' for self-managed certs. + -v, --verification string Custom domain verification method. Must be 'txt'. +``` + +### Flags inherited from parent commands + +``` + --debug Enable debug mode. + --force Skip confirmation. + --format string Command output format. Options: json. + --no-color Disable colors. + --no-input Disable interactivity. + --tenant string Specific tenant to use. +``` + +### SEE ALSO + +* [auth0 branding domains](auth0_branding_domains.md) - Manage custom domains diff --git a/docs/auth0_branding_domains_delete.md b/docs/auth0_branding_domains_delete.md new file mode 100644 index 000000000..1242ef8a7 --- /dev/null +++ b/docs/auth0_branding_domains_delete.md @@ -0,0 +1,35 @@ +## auth0 branding domains delete + +Delete a custom domain. + +``` +auth0 branding domains delete [flags] +``` + +### Examples + +``` +auth0 branding domains delete +auth0 branding domains delete +``` + +### Flags + +``` + -h, --help help for delete +``` + +### Flags inherited from parent commands + +``` + --debug Enable debug mode. + --force Skip confirmation. + --format string Command output format. Options: json. + --no-color Disable colors. + --no-input Disable interactivity. + --tenant string Specific tenant to use. +``` + +### SEE ALSO + +* [auth0 branding domains](auth0_branding_domains.md) - Manage custom domains diff --git a/docs/auth0_branding_domains_list.md b/docs/auth0_branding_domains_list.md new file mode 100644 index 000000000..63168255c --- /dev/null +++ b/docs/auth0_branding_domains_list.md @@ -0,0 +1,36 @@ +## auth0 branding domains list + +List your existing custom domains. To create one try: +auth0 branding domains create + +``` +auth0 branding domains list [flags] +``` + +### Examples + +``` +auth0 branding domains list +auth0 branding domains ls +``` + +### Flags + +``` + -h, --help help for list +``` + +### Flags inherited from parent commands + +``` + --debug Enable debug mode. + --force Skip confirmation. + --format string Command output format. Options: json. + --no-color Disable colors. + --no-input Disable interactivity. + --tenant string Specific tenant to use. +``` + +### SEE ALSO + +* [auth0 branding domains](auth0_branding_domains.md) - Manage custom domains diff --git a/docs/auth0_branding_domains_show.md b/docs/auth0_branding_domains_show.md new file mode 100644 index 000000000..cd617b5e9 --- /dev/null +++ b/docs/auth0_branding_domains_show.md @@ -0,0 +1,35 @@ +## auth0 branding domains show + +Show a custom domain. + +``` +auth0 branding domains show [flags] +``` + +### Examples + +``` +auth0 branding domains show +auth0 branding domains show +``` + +### Flags + +``` + -h, --help help for show +``` + +### Flags inherited from parent commands + +``` + --debug Enable debug mode. + --force Skip confirmation. + --format string Command output format. Options: json. + --no-color Disable colors. + --no-input Disable interactivity. + --tenant string Specific tenant to use. +``` + +### SEE ALSO + +* [auth0 branding domains](auth0_branding_domains.md) - Manage custom domains diff --git a/docs/auth0_branding_domains_verify.md b/docs/auth0_branding_domains_verify.md new file mode 100644 index 000000000..9e837f6e7 --- /dev/null +++ b/docs/auth0_branding_domains_verify.md @@ -0,0 +1,35 @@ +## auth0 branding domains verify + +Verify a custom domain. + +``` +auth0 branding domains verify [flags] +``` + +### Examples + +``` +auth0 branding domains verify +auth0 branding domains verify +``` + +### Flags + +``` + -h, --help help for verify +``` + +### Flags inherited from parent commands + +``` + --debug Enable debug mode. + --force Skip confirmation. + --format string Command output format. Options: json. + --no-color Disable colors. + --no-input Disable interactivity. + --tenant string Specific tenant to use. +``` + +### SEE ALSO + +* [auth0 branding domains](auth0_branding_domains.md) - Manage custom domains diff --git a/docs/auth0_logs_streams_create.md b/docs/auth0_logs_streams_create.md index 94c70cb5d..ee29d5421 100644 --- a/docs/auth0_logs_streams_create.md +++ b/docs/auth0_logs_streams_create.md @@ -30,7 +30,7 @@ auth0 logs streams create -n test-splunk -t splunk --splunk-domain demo.splunk.c -h, --help help for create --http-auth string HTTP Authorization header. --http-endpoint string HTTP endpoint. - --http-format string HTTP Content-Format header. Possible values: JSONLINES, JSONARRAY, JSONOBJECT. + --http-format string HTTP Content-Format header. Possible values: jsonlines, jsonarray, jsonobject. --http-type string HTTP Content-Type header. Possible values: application/json. -n, --name string Name of the log stream. --splunk-domain string The domain name of the splunk instance. diff --git a/docs/auth0_logs_streams_update.md b/docs/auth0_logs_streams_update.md index d55c6b871..dbadba32b 100644 --- a/docs/auth0_logs_streams_update.md +++ b/docs/auth0_logs_streams_update.md @@ -26,7 +26,7 @@ auth0 logs streams update -n myeventbridge -t eventbridge -h, --help help for update --http-auth string HTTP Authorization header. --http-endpoint string HTTP endpoint. - --http-format string HTTP Content-Format header. Possible values: JSONLINES, JSONARRAY, JSONOBJECT. + --http-format string HTTP Content-Format header. Possible values: jsonlines, jsonarray, jsonobject. --http-type string HTTP Content-Type header. Possible values: application/json. -n, --name string Name of the log stream. --splunk-domain string The domain name of the splunk instance. diff --git a/internal/auth/auth.go b/internal/auth/auth.go index f5e66dfe7..eaa00746e 100644 --- a/internal/auth/auth.go +++ b/internal/auth/auth.go @@ -34,7 +34,8 @@ var requiredScopes = []string{ "create:users", "delete:users", "read:users", "update:users", "read:branding", "update:branding", "read:connections", "update:connections", - "read:client_keys", "read:logs", "read:tenant_settings", "read:custom_domains", + "read:client_keys", "read:logs", "read:tenant_settings", + "read:custom_domains", "create:custom_domains", "delete:custom_domains", "read:anomaly_blocks", "delete:anomaly_blocks", "create:log_streams", "delete:log_streams", "read:log_streams", "update:log_streams", } diff --git a/internal/auth/auth_test.go b/internal/auth/auth_test.go index 63600031b..ec0b87009 100644 --- a/internal/auth/auth_test.go +++ b/internal/auth/auth_test.go @@ -29,7 +29,7 @@ func TestRequiredScopes(t *testing.T) { list := []string{ "read:branding", "update:branding", "read:connections", "update:connections", - "read:custom_domains", + "read:custom_domains", "create:custom_domains", "delete:custom_domains", "read:client_keys", "read:logs", "read:tenant_settings", "read:anomaly_blocks", "delete:anomaly_blocks", } diff --git a/internal/auth0/custom_domain.go b/internal/auth0/custom_domain.go index c559b1e62..cc127e7a7 100644 --- a/internal/auth0/custom_domain.go +++ b/internal/auth0/custom_domain.go @@ -4,5 +4,18 @@ package auth0 import "gopkg.in/auth0.v5/management" type CustomDomainAPI interface { + // Create a new custom domain. + Create(c *management.CustomDomain, opts ...management.RequestOption) (err error) + + // Read retrieves a custom domain by its id. + Read(id string, opts ...management.RequestOption) (c *management.CustomDomain, err error) + + // Delete a custom domain. + Delete(id string, opts ...management.RequestOption) (err error) + + // Verify a custom domain. + Verify(id string, opts ...management.RequestOption) (c *management.CustomDomain, err error) + + // List all custom domains. List(opts ...management.RequestOption) (c []*management.CustomDomain, err error) } diff --git a/internal/cli/apis.go b/internal/cli/apis.go index 4d0102019..db461f1c5 100644 --- a/internal/cli/apis.go +++ b/internal/cli/apis.go @@ -373,7 +373,7 @@ auth0 apis delete `, _, err := cli.api.ResourceServer.Read(url.PathEscape(inputs.ID)) if err != nil { - return fmt.Errorf("Unable to delete API. The specified Id: %v doesn't exist", inputs.ID) + return fmt.Errorf("Unable to delete API: %w", err) } return cli.api.ResourceServer.Delete(url.PathEscape(inputs.ID)) diff --git a/internal/cli/apps.go b/internal/cli/apps.go index 91168ea94..7b9eddffe 100644 --- a/internal/cli/apps.go +++ b/internal/cli/apps.go @@ -294,7 +294,7 @@ auth0 apps delete `, _, err := cli.api.Client.Read(inputs.ID) if err != nil { - return fmt.Errorf("Unable to delete application. The specified Id: %v doesn't exist", inputs.ID) + return fmt.Errorf("Unable to delete application: %w", err) } return cli.api.Client.Delete(inputs.ID) diff --git a/internal/cli/branding.go b/internal/cli/branding.go index d6cb324be..168c79839 100644 --- a/internal/cli/branding.go +++ b/internal/cli/branding.go @@ -83,6 +83,7 @@ func brandingCmd(cli *cli) *cobra.Command { cmd.AddCommand(showBrandingCmd(cli)) cmd.AddCommand(updateBrandingCmd(cli)) cmd.AddCommand(templateCmd(cli)) + cmd.AddCommand(customDomainsCmd(cli)) return cmd } diff --git a/internal/cli/custom_domains.go b/internal/cli/custom_domains.go new file mode 100644 index 000000000..bf5052f0a --- /dev/null +++ b/internal/cli/custom_domains.go @@ -0,0 +1,319 @@ +package cli + +import ( + "fmt" + "net/url" + + "github.com/auth0/auth0-cli/internal/ansi" + "github.com/auth0/auth0-cli/internal/auth0" + "github.com/auth0/auth0-cli/internal/prompt" + "github.com/spf13/cobra" + "gopkg.in/auth0.v5/management" +) + +const ( + customDomainProvisioningTypeAuth0 = "auth0_managed_certs" + customDomainProvisioningTypeSelf = "self_managed_certs" + customDomainVerificationMethodTxt = "txt" +) + +var ( + customDomainID = Argument{ + Name: "Id", + Help: "Id of the custom domain.", + } + + customDomainDomain = Flag{ + Name: "Domain", + LongForm: "domain", + ShortForm: "d", + Help: "Domain name.", + IsRequired: true, + } + + customDomainType = Flag{ + Name: "Provisioning Type", + LongForm: "type", + ShortForm: "t", + Help: "Custom domain provisioning type. Must be 'auth0' for Auth0-managed certs or 'self' for self-managed certs.", + } + + customDomainVerification = Flag{ + Name: "Verification Method", + LongForm: "verification", + ShortForm: "v", + Help: "Custom domain verification method. Must be 'txt'.", + } +) + +func customDomainsCmd(cli *cli) *cobra.Command { + cmd := &cobra.Command{ + Use: "domains", + Short: "Manage custom domains", + Long: "Manage custom domains.", + } + + cmd.SetUsageTemplate(resourceUsageTemplate()) + cmd.AddCommand(listCustomDomainsCmd(cli)) + cmd.AddCommand(showCustomDomainCmd(cli)) + cmd.AddCommand(createCustomDomainCmd(cli)) + cmd.AddCommand(deleteCustomDomainCmd(cli)) + cmd.AddCommand(verifyCustomDomainCmd(cli)) + + return cmd +} + +func listCustomDomainsCmd(cli *cli) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Aliases: []string{"ls"}, + Args: cobra.NoArgs, + Short: "List your custom domains", + Long: `List your existing custom domains. To create one try: +auth0 branding domains create`, + Example: `auth0 branding domains list +auth0 branding domains ls`, + RunE: func(cmd *cobra.Command, args []string) error { + var list []*management.CustomDomain + + if err := ansi.Waiting(func() error { + var err error + list, err = cli.api.CustomDomain.List() + return err + }); err != nil { + return fmt.Errorf("An unexpected error occurred: %w", err) + } + + cli.renderer.CustomDomainList(list) + return nil + }, + } + + return cmd +} + +func showCustomDomainCmd(cli *cli) *cobra.Command { + var inputs struct { + ID string + } + + cmd := &cobra.Command{ + Use: "show", + Args: cobra.MaximumNArgs(1), + Short: "Show a custom domain", + Long: "Show a custom domain.", + Example: `auth0 branding domains show +auth0 branding domains show `, + RunE: func(cmd *cobra.Command, args []string) error { + if len(args) == 0 { + err := customDomainID.Pick(cmd, &inputs.ID, cli.customDomainsPickerOptions) + if err != nil { + return err + } + } else { + inputs.ID = args[0] + } + + var customDomain *management.CustomDomain + + if err := ansi.Waiting(func() error { + var err error + customDomain, err = cli.api.CustomDomain.Read(url.PathEscape(inputs.ID)) + return err + }); err != nil { + return fmt.Errorf("Unable to get a custom domain with Id '%s': %w", inputs.ID, err) + } + + cli.renderer.CustomDomainShow(customDomain) + return nil + }, + } + + return cmd +} + +func createCustomDomainCmd(cli *cli) *cobra.Command { + var inputs struct { + Domain string + Type string + VerificationMethod string + } + + cmd := &cobra.Command{ + Use: "create", + Args: cobra.NoArgs, + Short: "Create a custom domain", + Long: "Create a custom domain.", + Example: `auth0 branding domains create +auth0 branding domains create `, + RunE: func(cmd *cobra.Command, args []string) error { + if err := customDomainDomain.Ask(cmd, &inputs.Domain, nil); err != nil { + return err + } + + customDomain := &management.CustomDomain{ + Domain: &inputs.Domain, + } + + if len(inputs.Type) > 0 { + customDomain.Type = apiProvisioningTypeFor(inputs.Type) + } else { + customDomain.Type = auth0.String(customDomainProvisioningTypeAuth0) + } + + if len(inputs.VerificationMethod) > 0 { + customDomain.VerificationMethod = apiVerificationMethodFor(inputs.VerificationMethod) + } + + if err := ansi.Waiting(func() error { + return cli.api.CustomDomain.Create(customDomain) + }); err != nil { + return fmt.Errorf("An unexpected error occurred while attempting to create the custom domain '%s': %w", inputs.Domain, err) + } + + cli.renderer.CustomDomainCreate(customDomain) + return nil + }, + } + + customDomainDomain.RegisterStringU(cmd, &inputs.Domain, "") + customDomainType.RegisterStringU(cmd, &inputs.Type, "") + customDomainVerification.RegisterStringU(cmd, &inputs.VerificationMethod, "") + + return cmd +} + +func deleteCustomDomainCmd(cli *cli) *cobra.Command { + var inputs struct { + ID string + } + + cmd := &cobra.Command{ + Use: "delete", + Args: cobra.MaximumNArgs(1), + Short: "Delete a custom domain", + Long: "Delete a custom domain.", + Example: `auth0 branding domains delete +auth0 branding domains delete `, + RunE: func(cmd *cobra.Command, args []string) error { + if len(args) == 0 { + err := customDomainID.Pick(cmd, &inputs.ID, cli.customDomainsPickerOptions) + if err != nil { + return err + } + } else { + inputs.ID = args[0] + } + + if !cli.force && canPrompt(cmd) { + if confirmed := prompt.Confirm("Are you sure you want to proceed?"); !confirmed { + return nil + } + } + + return ansi.Spinner("Deleting custom domain", func() error { + _, err := cli.api.CustomDomain.Read(url.PathEscape(inputs.ID)) + + if err != nil { + return fmt.Errorf("Unable to delete custom domain: %w", err) + } + + return cli.api.CustomDomain.Delete(url.PathEscape(inputs.ID)) + }) + }, + } + + return cmd +} + +func verifyCustomDomainCmd(cli *cli) *cobra.Command { + var inputs struct { + ID string + } + + cmd := &cobra.Command{ + Use: "verify", + Args: cobra.MaximumNArgs(1), + Short: "Verify a custom domain", + Long: "Verify a custom domain.", + Example: `auth0 branding domains verify +auth0 branding domains verify `, + RunE: func(cmd *cobra.Command, args []string) error { + if len(args) == 0 { + err := customDomainID.Pick(cmd, &inputs.ID, cli.customDomainsPickerOptions) + if err != nil { + return err + } + } else { + inputs.ID = args[0] + } + + var customDomain *management.CustomDomain + + if err := ansi.Waiting(func() error { + var err error + customDomain, err = cli.api.CustomDomain.Verify(url.PathEscape(inputs.ID)) + return err + }); err != nil { + return fmt.Errorf("Unable to verify a custom domain with Id '%s': %w", inputs.ID, err) + } + + cli.renderer.CustomDomainShow(customDomain) + return nil + }, + } + + return cmd +} + +func apiProvisioningTypeFor(v string) *string { + switch v { + case "auth0": + return auth0.String(customDomainProvisioningTypeAuth0) + case "self": + return auth0.String(customDomainProvisioningTypeSelf) + default: + return auth0.String(v) + } +} + +func apiVerificationMethodFor(v string) *string { + switch v { + case "txt": + return auth0.String(customDomainVerificationMethodTxt) + default: + return auth0.String(v) + } +} + +func (c *cli) customDomainsPickerOptions() (pickerOptions, error) { + var opts pickerOptions + + domains, err := c.api.CustomDomain.List() + if err != nil { + errStatus := err.(management.Error) + // 403 is a valid response for free tenants that don't have + // custom domains enabled + if errStatus != nil && errStatus.Status() == 403 { + return nil, errNoCustomDomains + } + + return nil, err + } + + for _, d := range domains { + if d.GetStatus() != "ready" { + continue + } + + value := d.GetID() + label := fmt.Sprintf("%s %s", d.GetDomain(), ansi.Faint("("+value+")")) + opts = append(opts, pickerOption{value: value, label: label}) + } + + if len(opts) == 0 { + return nil, errNoCustomDomains + } + + return opts, nil +} diff --git a/internal/cli/log_streams.go b/internal/cli/log_streams.go index d0010be67..95fd849a3 100644 --- a/internal/cli/log_streams.go +++ b/internal/cli/log_streams.go @@ -63,7 +63,7 @@ var ( httpContentFormat = Flag{ Name: "HTTP Content Format", LongForm: "http-format", - Help: "HTTP Content-Format header. Possible values: JSONLINES, JSONARRAY, JSONOBJECT.", + Help: "HTTP Content-Format header. Possible values: jsonlines, jsonarray, jsonobject.", AlwaysPrompt: true, } httpAuthorization = Flag{ @@ -309,7 +309,7 @@ auth0 logs streams create -n test-splunk -t splunk --splunk-domain demo.splunk.c ls.Sink = &management.LogStreamSinkHTTP{ Authorization: &inputs.HttpAuthorization, ContentType: &inputs.HttpContentType, - ContentFormat: &inputs.HttpContentFormat, + ContentFormat: apiHTTPContentFormatFor(inputs.HttpContentFormat), Endpoint: &inputs.HttpEndpoint, } } @@ -641,7 +641,7 @@ auth0 logs streams update -n myeventbridge -t eventbridge`, } if len(inputs.HttpContentFormat) > 0 { - s.ContentFormat = &inputs.HttpContentFormat + s.ContentFormat = apiHTTPContentFormatFor(inputs.HttpContentFormat) } if len(inputs.HttpAuthorization) > 0 { @@ -724,7 +724,7 @@ auth0 logs streams delete `, _, err := cli.api.LogStream.Read(inputs.ID) if err != nil { - return fmt.Errorf("Unable to delete log stream. The specified Id: %v doesn't exist", inputs.ID) + return fmt.Errorf("Unable to delete log stream: %w", err) } return cli.api.LogStream.Delete(inputs.ID) @@ -792,6 +792,10 @@ func (c *cli) logStreamPickerOptions() (pickerOptions, error) { return opts, nil } +func apiHTTPContentFormatFor(v string) *string { + return auth0.String(strings.ToUpper(v)) +} + func logsTypeFor(v string) string { switch strings.ToLower(v) { case "http": diff --git a/internal/cli/roles.go b/internal/cli/roles.go index 34a1072ea..59ea956e7 100644 --- a/internal/cli/roles.go +++ b/internal/cli/roles.go @@ -270,7 +270,7 @@ auth0 roles delete `, _, err := cli.api.Role.Read(inputs.ID) if err != nil { - return fmt.Errorf("Unable to delete role. The specified Id: %v doesn't exist", inputs.ID) + return fmt.Errorf("Unable to delete role: %w", err) } return cli.api.Role.Delete(inputs.ID) diff --git a/internal/cli/rules.go b/internal/cli/rules.go index f658cee1e..c48306b15 100644 --- a/internal/cli/rules.go +++ b/internal/cli/rules.go @@ -250,7 +250,7 @@ auth0 rules delete `, _, err := cli.api.Rule.Read(inputs.ID) if err != nil { - return fmt.Errorf("Unable to delete application. The specified Id: %v doesn't exist", inputs.ID) + return fmt.Errorf("Unable to delete rule: %w", err) } return cli.api.Rule.Delete(inputs.ID) diff --git a/internal/cli/users.go b/internal/cli/users.go index 92da287a6..89da84af4 100644 --- a/internal/cli/users.go +++ b/internal/cli/users.go @@ -300,7 +300,7 @@ auth0 users delete `, _, err := cli.api.User.Read(inputs.ID) if err != nil { - return fmt.Errorf("Unable to delete user. The specified Id: %v doesn't exist", inputs.ID) + return fmt.Errorf("Unable to delete user: %w", err) } return cli.api.User.Delete(inputs.ID) diff --git a/internal/display/custom_domain.go b/internal/display/custom_domain.go new file mode 100644 index 000000000..6d950f01a --- /dev/null +++ b/internal/display/custom_domain.go @@ -0,0 +1,97 @@ +package display + +import ( + "strconv" + + "github.com/auth0/auth0-cli/internal/ansi" + "gopkg.in/auth0.v5/management" +) + +type customDomainView struct { + ID string + Domain string + Status string + Primary bool + ProvisioningType string + VerificationMethod string +} + +func (v *customDomainView) AsTableHeader() []string { + return []string{"ID", "Domain", "Status"} +} + +func (v *customDomainView) AsTableRow() []string { + return []string{ + ansi.Faint(v.ID), + v.Domain, + v.Status, + } +} + +func (v *customDomainView) KeyValues() [][]string { + return [][]string{ + {"ID", ansi.Faint(v.ID)}, + {"DOMAIN", v.Domain}, + {"STATUS", v.Status}, + {"PRIMARY", strconv.FormatBool(v.Primary)}, + {"PROVISIONING TYPE", v.ProvisioningType}, + {"VERIFICATION METHOD", v.VerificationMethod}, + } +} + +func (r *Renderer) CustomDomainList(customDomains []*management.CustomDomain) { + resource := "custom domains" + + r.Heading(resource) + + if len(customDomains) == 0 { + r.EmptyState(resource) + r.Infof("Use 'auth0 branding domains create' to add one") + return + } + + var res []View + for _, customDomain := range customDomains { + res = append(res, &customDomainView{ + ID: customDomain.GetID(), + Domain: customDomain.GetDomain(), + Status: customDomainStatusColor(customDomain.GetStatus()), + }) + } + + r.Results(res) +} + +func (r *Renderer) CustomDomainShow(customDomain *management.CustomDomain) { + r.Heading("custom domain") + r.customDomainResult(customDomain) +} + +func (r *Renderer) CustomDomainCreate(customDomain *management.CustomDomain) { + r.Heading("custom domain created") + r.customDomainResult(customDomain) +} + +func (r *Renderer) customDomainResult(customDomain *management.CustomDomain) { + r.Result(&customDomainView{ + ID: ansi.Faint(customDomain.GetID()), + Domain: customDomain.GetDomain(), + Status: customDomainStatusColor(customDomain.GetStatus()), + Primary: customDomain.GetPrimary(), + ProvisioningType: customDomain.GetType(), + VerificationMethod: customDomain.GetVerificationMethod(), + }) +} + +func customDomainStatusColor(v string) string { + switch(v) { + case "disabled": + return ansi.Red(v) + case "pending", "pending_verification": + return ansi.Yellow(v) + case "ready": + return ansi.Green(v) + default: + return v + } +} diff --git a/internal/display/roles.go b/internal/display/roles.go index 8f50d1c02..93d0a598d 100644 --- a/internal/display/roles.go +++ b/internal/display/roles.go @@ -12,7 +12,7 @@ type roleView struct { } func (v *roleView) AsTableHeader() []string { - return []string{"Role ID", "Name", "Description"} + return []string{"ID", "Name", "Description"} } func (v *roleView) AsTableRow() []string { diff --git a/internal/display/rules.go b/internal/display/rules.go index 6b7f32a7a..ceaaa8420 100644 --- a/internal/display/rules.go +++ b/internal/display/rules.go @@ -20,7 +20,7 @@ type ruleView struct { } func (v *ruleView) AsTableHeader() []string { - return []string{"Id", "Name", "Enabled", "Order"} + return []string{"ID", "Name", "Enabled", "Order"} } func (v *ruleView) AsTableRow() []string {