Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

apps picker: allow configurability of default app #205

Merged
merged 3 commits into from
Mar 29, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 93 additions & 11 deletions internal/cli/apps.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ var (
Help: "Name of the application.",
IsRequired: true,
}
appNone = Flag{
Name: "None",
LongForm: "none",
ShortForm: "n",
Help: "Specify none of your apps",
}

appType = Flag{
Name: "Type",
LongForm: "type",
Expand Down Expand Up @@ -65,11 +72,11 @@ var (
AlwaysPrompt: true,
}
appOrigins = Flag{
Name: "Allowed Origin URLs",
LongForm: "origins",
ShortForm: "o",
Help: "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.",
IsRequired: false,
Name: "Allowed Origin URLs",
LongForm: "origins",
ShortForm: "o",
Help: "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.",
IsRequired: false,
AlwaysPrompt: true,
}
appWebOrigins = Flag{
Expand Down Expand Up @@ -117,10 +124,60 @@ func appsCmd(cli *cli) *cobra.Command {
cmd.AddCommand(showAppCmd(cli))
cmd.AddCommand(updateAppCmd(cli))
cmd.AddCommand(deleteAppCmd(cli))
cmd.AddCommand(useAppCmd(cli))

return cmd
}

func useAppCmd(cli *cli) *cobra.Command {
var inputs struct {
ID string
None bool
}

cmd := &cobra.Command{
Use: "use",
Short: "Choose a default application",
Long: `auth0 apps use <client-id>
Specify your preferred application for interaction with the auth0 CLI
cyx marked this conversation as resolved.
Show resolved Hide resolved
`,
PreRun: func(cmd *cobra.Command, args []string) {
prepareInteractivity(cmd)
},

RunE: func(cmd *cobra.Command, args []string) error {
if inputs.None {
inputs.ID = ""
} else {
if len(args) == 0 {
err := appID.Pick(cmd, &inputs.ID, cli.appPickerOptions)
if err != nil {
return err
}
} else {
inputs.ID = args[0]
}
}

if err := cli.setDefaultAppID(inputs.ID); err != nil {
return err
}

if inputs.ID == "" {
cli.renderer.Infof("Successfully removed the default application")
} else {
cli.renderer.Infof("Successfully set the default application to %s", ansi.Faint(inputs.ID))
cli.renderer.Infof("%s You might wanna try 'auth0 quickstarts download %s'", ansi.Faint("Hint:"), inputs.ID)
}

return nil
},
}

appNone.RegisterBool(cmd, &inputs.None, false)
return cmd
}

func listAppsCmd(cli *cli) *cobra.Command {
cmd := &cobra.Command{
Use: "list",
Expand Down Expand Up @@ -352,6 +409,10 @@ auth0 apps create --name myapp --type [native|spa|regular|m2m]
return fmt.Errorf("Unable to create application: %w", err)
}

if err := cli.setDefaultAppID(a.GetClientID()); err != nil {
return err
}

// Render result
// note: a is populated with the rest of the client fields by the API during creation.
revealClientSecret := auth0.StringValue(a.AppType) != "native" && auth0.StringValue(a.AppType) != "spa"
Expand Down Expand Up @@ -713,19 +774,40 @@ func (c *cli) appPickerOptions() (pickerOptions, error) {
return nil, err
}

// NOTE: because client names are not unique, we'll just number these
// labels.
var opts pickerOptions
tenant, err := c.getTenant()
if err != nil {
return nil, err
}

// NOTE(cyx): To keep the contract for this simple, we'll rely on the
// implicit knowledge that the default value for the picker is the
// first option. With that in mind, we'll use the state in
// tenant.DefaultAppID to determine which should be chosen as the
// default.
var (
priorityOpts, opts pickerOptions
)
for _, c := range list.Clients {
// empty type means the default client that we shouldn't display.
if c.GetAppType() == "" {
continue
}

value := c.GetClientID()
label := fmt.Sprintf("%s %s", c.GetName(), ansi.Faint("("+value+")"))
opt := pickerOption{value: value, label: label}

opts = append(opts, pickerOption{value: value, label: label})
// check if this is currently the default application.
if tenant.DefaultAppID == c.GetClientID() {
priorityOpts = append(priorityOpts, opt)
} else {
opts = append(opts, opt)
}
}

if len(opts) == 0 {
if len(opts)+len(priorityOpts) == 0 {
return nil, errors.New("There are currently no applications.")
}

return opts, nil
return append(priorityOpts, opts...), nil
}
28 changes: 22 additions & 6 deletions internal/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,12 @@ type config struct {
// tenant is the cli's concept of an auth0 tenant. The fields are tailor fit
// specifically for interacting with the management API.
type tenant struct {
Name string `json:"name"`
Domain string `json:"domain"`
AccessToken string `json:"access_token,omitempty"`
ExpiresAt time.Time `json:"expires_at"`
Apps map[string]app `json:"apps,omitempty"`
Name string `json:"name"`
Domain string `json:"domain"`
AccessToken string `json:"access_token,omitempty"`
ExpiresAt time.Time `json:"expires_at"`
Apps map[string]app `json:"apps,omitempty"`
DefaultAppID string `json:"default_app_id,omitempty"`
}

type app struct {
Expand Down Expand Up @@ -296,9 +297,24 @@ func (c *cli) isFirstCommandRun(clientID string, command string) (bool, error) {
return true, nil
}

func (c *cli) setFirstCommandRun(clientID string, command string) error {
func (c *cli) setDefaultAppID(id string) error {
tenant, err := c.getTenant()
if err != nil {
return err
}

tenant.DefaultAppID = id

c.config.Tenants[tenant.Name] = tenant
if err := c.persistConfig(); err != nil {
return fmt.Errorf("Unexpected error persisting config: %w", err)
}

return nil
}

func (c *cli) setFirstCommandRun(clientID string, command string) error {
tenant, err := c.getTenant()
if err != nil {
return err
}
Expand Down