diff --git a/internal/cli/actions.go b/internal/cli/actions.go index 94eb04232..ab588c713 100644 --- a/internal/cli/actions.go +++ b/internal/cli/actions.go @@ -107,7 +107,7 @@ func readJsonFile(filePath string, out interface{}) error { } func testActionCmd(cli *cli) *cobra.Command { - var flags struct { + var inputs struct { ID string File string Version string @@ -117,24 +117,33 @@ func testActionCmd(cli *cli) *cobra.Command { cmd := &cobra.Command{ Use: "test", + Args: cobra.MaximumNArgs(1), Short: "Test an action draft against a payload", - Long: `auth0 actions test --id --file `, + Long: `Test an action draft against a payload: + +auth0 actions test --file payload.json`, PreRun: func(cmd *cobra.Command, args []string) { prepareInteractivity(cmd) }, RunE: func(cmd *cobra.Command, args []string) error { - if shouldPrompt(cmd, actionID) { - input := prompt.TextInput(actionID, "Id:", "Action Id to test.", true) - - if err := prompt.AskOne(input, &flags); err != nil { - return err + if len(args) == 0 { + if shouldPrompt(cmd, actionID) { + input := prompt.TextInput(actionID, "Id:", "Action Id to test.", true) + + if err := prompt.AskOne(input, &inputs); err != nil { + return err + } + } else { + return errors.New("missing action id") } + } else { + inputs.ID = args[0] } if shouldPrompt(cmd, actionFile) { input := prompt.TextInput(actionFile, "File:", "File containing the payload for the test.", true) - if err := prompt.AskOne(input, &flags); err != nil { + if err := prompt.AskOne(input, &inputs); err != nil { return err } } @@ -142,19 +151,19 @@ func testActionCmd(cli *cli) *cobra.Command { if shouldPrompt(cmd, actionVersion) { input := prompt.TextInputDefault(actionVersion, "Version Id:", "Version ID of the action to test. Default: draft", "draft", false) - if err := prompt.AskOne(input, &flags); err != nil { + if err := prompt.AskOne(input, &inputs); err != nil { return err } } - err := readJsonFile(flags.File, &payload) + err := readJsonFile(inputs.File, &payload) if err != nil { return err } var result management.Object - err = ansi.Spinner(fmt.Sprintf("Testing action: %s, version: %s", flags.ID, flags.Version), func() error { - result, err = cli.api.ActionVersion.Test(flags.ID, flags.Version, payload) + err = ansi.Spinner(fmt.Sprintf("Testing action: %s, version: %s", inputs.ID, inputs.Version), func() error { + result, err = cli.api.ActionVersion.Test(inputs.ID, inputs.Version, payload) return err }) @@ -167,47 +176,55 @@ func testActionCmd(cli *cli) *cobra.Command { }, } - cmd.Flags().StringVarP(&flags.ID, actionID, "i", "", "Action Id to test.") - cmd.Flags().StringVarP(&flags.File, actionFile, "f", "", "File containing the payload for the test.") - cmd.Flags().StringVarP(&flags.Version, actionVersion, "v", "draft", "Version Id of the action to test.") - mustRequireFlags(cmd, actionID, actionFile) + cmd.Flags().StringVarP(&inputs.File, actionFile, "f", "", "File containing the payload for the test.") + cmd.Flags().StringVarP(&inputs.Version, actionVersion, "v", "draft", "Version Id of the action to test. Default: draft") + mustRequireFlags(cmd, actionFile) return cmd } func deployActionCmd(cli *cli) *cobra.Command { - var flags struct { + var inputs struct { ID string Version string } cmd := &cobra.Command{ Use: "deploy", + Args: cobra.MaximumNArgs(1), Short: "Deploy the action version", - Long: `auth0 actions deploy --id --version `, + Long: `Deploy the action version: + +auth0 actions deploy --version version-id`, PreRun: func(cmd *cobra.Command, args []string) { prepareInteractivity(cmd) }, RunE: func(cmd *cobra.Command, args []string) error { - if shouldPrompt(cmd, actionID) { - input := prompt.TextInput(actionID, "Id:", "Action Id to deploy.", true) - - if err := prompt.AskOne(input, &flags); err != nil { - return err + if len(args) == 0 { + if shouldPrompt(cmd, actionID) { + input := prompt.TextInput(actionID, "Id:", "Action Id to deploy.", true) + + if err := prompt.AskOne(input, &inputs); err != nil { + return err + } + } else { + return errors.New("missing action id") } + } else { + inputs.ID = args[0] } if shouldPrompt(cmd, actionVersion) { - version, err := askVersion(cli, flags.ID) + version, err := askVersion(cli, inputs.ID) if err != nil { return err } - flags.Version = version + inputs.Version = version } var version *management.ActionVersion - err := ansi.Spinner(fmt.Sprintf("Deploying action: %s, version: %s", flags.ID, flags.Version), func() (err error) { - version, err = cli.api.ActionVersion.Deploy(flags.ID, flags.Version) + err := ansi.Spinner(fmt.Sprintf("Deploying action: %s, version: %s", inputs.ID, inputs.Version), func() (err error) { + version, err = cli.api.ActionVersion.Deploy(inputs.ID, inputs.Version) return err }) @@ -221,9 +238,7 @@ func deployActionCmd(cli *cli) *cobra.Command { }, } - cmd.Flags().StringVarP(&flags.ID, actionID, "i", "", "Action Id to deploy.") - cmd.Flags().StringVarP(&flags.Version, actionVersion, "v", "draft", "Version Id of the action to deploy.") - mustRequireFlags(cmd, actionID) + cmd.Flags().StringVarP(&inputs.Version, actionVersion, "v", "draft", "Version Id of the action to deploy. Default: draft") return cmd } @@ -265,7 +280,7 @@ func askVersion(cli *cli, actionId string) (string, error) { } func downloadActionCmd(cli *cli) *cobra.Command { - var flags struct { + var inputs struct { ID string Version string Path string @@ -273,44 +288,53 @@ func downloadActionCmd(cli *cli) *cobra.Command { cmd := &cobra.Command{ Use: "download", - Short: "Download the action version", - Long: `auth0 actions download --id --version `, + Args: cobra.MaximumNArgs(1), + Short: "Download an action", + Long: `Download an action: + +auth0 actions download --version `, PreRun: func(cmd *cobra.Command, args []string) { prepareInteractivity(cmd) }, RunE: func(cmd *cobra.Command, args []string) error { - if shouldPrompt(cmd, actionID) { - input := prompt.TextInput(actionID, "Id:", "Action Id to download.", true) - - if err := prompt.AskOne(input, &flags); err != nil { - return err + if len(args) == 0 { + if shouldPrompt(cmd, actionID) { + input := prompt.TextInput(actionID, "Id:", "Action Id to download.", true) + + if err := prompt.AskOne(input, &inputs); err != nil { + return err + } + } else { + return errors.New("missing action id") } + } else { + inputs.ID = args[0] } if shouldPrompt(cmd, actionVersion) { - version, err := askVersion(cli, flags.ID) + version, err := askVersion(cli, inputs.ID) if err != nil { return err } - flags.Version = version + inputs.Version = version } if shouldPrompt(cmd, actionPath) { input := prompt.TextInputDefault(actionPath, "Path:", "Path to save the action content.", "./", false) - if err := prompt.AskOne(input, &flags); err != nil { + if err := prompt.AskOne(input, &inputs); err != nil { return err } } - cli.renderer.Infof("It will overwrite files in %s", flags.Path) + cli.renderer.Infof("It will overwrite files in %s", inputs.Path) if confirmed := prompt.Confirm("Do you wish to proceed?"); !confirmed { return nil } var version *management.ActionVersion - err := ansi.Spinner(fmt.Sprintf("Downloading action: %s, version: %s", flags.ID, flags.Version), func() (err error) { - if version, err = cli.api.ActionVersion.Read(flags.ID, flags.Version); err != nil { + err := ansi.Spinner(fmt.Sprintf("Downloading action: %s, version: %s", inputs.ID, inputs.Version), func() (err error) { + if version, err = cli.api.ActionVersion.Read(inputs.ID, inputs.Version); err != nil { return err } @@ -324,9 +348,9 @@ func downloadActionCmd(cli *cli) *cobra.Command { return err } - cli.renderer.Infof("Code downloaded to %s/code.js", flags.Path) + cli.renderer.Infof("Code downloaded to %s/code.js", inputs.Path) - if err := ioutil.WriteFile(flags.Path+"/code.js", []byte(version.Code), 0644); err != nil { + if err := ioutil.WriteFile(inputs.Path+"/code.js", []byte(version.Code), 0644); err != nil { return err } @@ -336,7 +360,7 @@ func downloadActionCmd(cli *cli) *cobra.Command { return err } - if err := ioutil.WriteFile(flags.Path+"/metadata.json", metadata, 0644); err != nil { + if err := ioutil.WriteFile(inputs.Path+"/metadata.json", metadata, 0644); err != nil { return err } @@ -344,38 +368,45 @@ func downloadActionCmd(cli *cli) *cobra.Command { }, } - cmd.Flags().StringVarP(&flags.ID, actionID, "i", "", "Action ID to download.") - cmd.Flags().StringVarP(&flags.Version, actionVersion, "v", "", "Version ID of the action to deploy or draft. Default: draft") - cmd.Flags().StringVarP(&flags.Path, actionPath, "p", "./", "Path to save the action content.") - mustRequireFlags(cmd, actionID) + cmd.Flags().StringVarP(&inputs.Version, actionVersion, "v", "draft", "Version ID of the action to download. Default: draft") + cmd.Flags().StringVarP(&inputs.Path, actionPath, "p", "./", "Path to save the action content.") return cmd } func listActionVersionsCmd(cli *cli) *cobra.Command { - var flags struct { + var inputs struct { ID string } cmd := &cobra.Command{ Use: "versions", + Args: cobra.MaximumNArgs(1), Short: "List the action versions", - Long: `auth0 actions versions --id `, + Long: `List the action versions: + +auth0 actions versions `, PreRun: func(cmd *cobra.Command, args []string) { prepareInteractivity(cmd) }, RunE: func(cmd *cobra.Command, args []string) error { - if shouldPrompt(cmd, actionID) { - input := prompt.TextInput(actionID, "Id:", "Action Id to show versions.", true) - - if err := prompt.AskOne(input, &flags); err != nil { - return err + if len(args) == 0 { + if shouldPrompt(cmd, actionID) { + input := prompt.TextInput(actionID, "Id:", "Action Id to show versions.", true) + + if err := prompt.AskOne(input, &inputs); err != nil { + return err + } + } else { + return errors.New("missing action id") } + } else { + inputs.ID = args[0] } var list *management.ActionVersionList - err := ansi.Spinner(fmt.Sprintf("Loading versions for action: %s", flags.ID), func() (err error) { - list, err = cli.api.ActionVersion.List(flags.ID) + err := ansi.Spinner(fmt.Sprintf("Loading versions for action: %s", inputs.ID), func() (err error) { + list, err = cli.api.ActionVersion.List(inputs.ID) return err }) @@ -389,9 +420,6 @@ func listActionVersionsCmd(cli *cli) *cobra.Command { }, } - cmd.Flags().StringVarP(&flags.ID, actionID, "i", "", "Action Id to show versions.") - mustRequireFlags(cmd, actionID) - return cmd } @@ -523,7 +551,7 @@ Create a new action: } func updateActionCmd(cli *cli) *cobra.Command { - var flags struct { + var inputs struct { ID string File string Script string @@ -533,27 +561,41 @@ func updateActionCmd(cli *cli) *cobra.Command { cmd := &cobra.Command{ Use: "update", + Args: cobra.MaximumNArgs(1), Short: "Updates an existing action", - Long: `$ auth0 actions update -Updates an existing action: + Long: `Updates an existing action: - $ auth0 actions update --id --file action.js --dependency lodash@4.17.19 +$ auth0 actions update --file action.js --dependency lodash@4.17.19 `, RunE: func(cmd *cobra.Command, args []string) error { + if len(args) == 0 { + if shouldPrompt(cmd, actionID) { + input := prompt.TextInput(actionID, "Id:", "Id of the action.", true) + + if err := prompt.AskOne(input, &inputs); err != nil { + return err + } + } else { + return errors.New("missing action id") + } + } else { + inputs.ID = args[0] + } + if shouldPrompt(cmd, actionFile) && shouldPrompt(cmd, actionScript) { input := prompt.TextInput(actionFile, "Action File:", "File containing the action source code.", false) - if err := prompt.AskOne(input, &flags); err != nil { + if err := prompt.AskOne(input, &inputs); err != nil { return err } } - source, err := sourceFromFileOrScript(flags.File, flags.Script) + source, err := sourceFromFileOrScript(inputs.File, inputs.Script) if err != nil { return err } - dependencies, err := validators.Dependencies(flags.Dependency) + dependencies, err := validators.Dependencies(inputs.Dependency) if err != nil { return err } @@ -565,7 +607,7 @@ Updates an existing action: } err = ansi.Spinner("Updating action", func() error { - created, err := createActionVersion(cli.api, flags.ID, !flags.CreateVersion, version) + created, err := createActionVersion(cli.api, inputs.ID, !inputs.CreateVersion, version) if err != nil { return err } @@ -584,14 +626,12 @@ Updates an existing action: }, } - cmd.Flags().StringVar(&flags.ID, actionID, "", "Action ID to update.") - cmd.Flags().StringVarP(&flags.File, actionFile, "f", "", "File containing the action source code.") - cmd.Flags().StringVarP(&flags.Script, actionScript, "s", "", "Raw source code for the action.") - cmd.Flags().StringSliceVarP(&flags.Dependency, actionDependency, "d", nil, "Dependency for the source code (@).") + cmd.Flags().StringVarP(&inputs.File, actionFile, "f", "", "File containing the action source code.") + cmd.Flags().StringVarP(&inputs.Script, actionScript, "s", "", "Raw source code for the action.") + cmd.Flags().StringSliceVarP(&inputs.Dependency, actionDependency, "d", nil, "Dependency for the source code (@).") // TODO: This name is kind of overloaded since it could also refer to the version of the trigger (though there's only v1's at this time) - cmd.Flags().BoolVarP(&flags.CreateVersion, actionVersion, "v", false, "Create an explicit action version from the source code instead of a draft.") + cmd.Flags().BoolVarP(&inputs.CreateVersion, actionVersion, "v", false, "Create an explicit action version from the source code instead of a draft.") - mustRequireFlags(cmd, actionID) if err := cmd.MarkFlagFilename(actionFile); err != nil { panic(err) } @@ -600,23 +640,30 @@ Updates an existing action: } func deleteActionCmd(cli *cli) *cobra.Command { - var flags struct { + var inputs struct { ID string } cmd := &cobra.Command{ Use: "delete", + Args: cobra.MaximumNArgs(1), Short: "Delete an action", - Long: `$ Delete an action: + Long: `Delete an action: - $ auth0 actions delete --id `, +$ auth0 actions delete `, RunE: func(cmd *cobra.Command, args []string) error { - if shouldPrompt(cmd, actionID) { - input := prompt.TextInput(actionID, "Id:", "Id of the action.", true) - - if err := prompt.AskOne(input, &flags); err != nil { - return err + if len(args) == 0 { + if shouldPrompt(cmd, actionID) { + input := prompt.TextInput(actionID, "Id:", "Id of the action.", true) + + if err := prompt.AskOne(input, &inputs); err != nil { + return err + } + } else { + return errors.New("missing action id") } + } else { + inputs.ID = args[0] } if !cli.force && canPrompt(cmd) { @@ -626,7 +673,7 @@ func deleteActionCmd(cli *cli) *cobra.Command { } err := ansi.Spinner("Deleting action", func() error { - return cli.api.Action.Delete(flags.ID) + return cli.api.Action.Delete(inputs.ID) }) if err != nil { @@ -637,43 +684,49 @@ func deleteActionCmd(cli *cli) *cobra.Command { }, } - cmd.Flags().StringVar(&flags.ID, actionID, "", "Action ID to delete.") - mustRequireFlags(cmd, actionID) - return cmd } func showFlowCmd(cli *cli) *cobra.Command { - var flags struct { + var inputs struct { Trigger string } cmd := &cobra.Command{ Use: "show", - Short: "Shows actions by flow", - Long: `auth0 actions flows --trigger post-login`, + Args: cobra.MaximumNArgs(1), + Short: "Show actions by flow", + Long: `Show a list of actions by flow: + +auth0 actions flows show `, PreRun: func(cmd *cobra.Command, args []string) { prepareInteractivity(cmd) }, RunE: func(cmd *cobra.Command, args []string) error { - if shouldPrompt(cmd, actionTrigger) { - input := prompt.SelectInput( - actionTrigger, - "Trigger:", - "Trigger type for action.", - validators.ValidTriggerIDs, - false) - - if err := prompt.AskOne(input, &flags); err != nil { - return err + if len(args) == 0 { + if shouldPrompt(cmd, actionTrigger) { + input := prompt.SelectInput( + actionTrigger, + "Trigger:", + "Trigger type for action.", + validators.ValidTriggerIDs, + false) + + if err := prompt.AskOne(input, &inputs); err != nil { + return err + } + } else { + return errors.New("missing action trigger") } + } else { + inputs.Trigger = args[0] } - if err := validators.TriggerID(flags.Trigger); err != nil { + if err := validators.TriggerID(inputs.Trigger); err != nil { return err } - triggerID := management.TriggerID(flags.Trigger) + triggerID := management.TriggerID(inputs.Trigger) var list *management.ActionBindingList err := ansi.Spinner("Loading actions", func() (err error) { @@ -690,54 +743,61 @@ func showFlowCmd(cli *cli) *cobra.Command { }, } - cmd.Flags().StringVarP(&flags.Trigger, actionTrigger, "t", string(management.PostLogin), "Trigger type for action.") - return cmd } func updateFlowCmd(cli *cli) *cobra.Command { - var flags struct { - File string + var inputs struct { Trigger string + File string } cmd := &cobra.Command{ Use: "update", + Args: cobra.MaximumNArgs(1), Short: "Update actions by flow", - Long: `auth0 actions flows update --trigger --file `, + Long: `Update actions by flow: + +auth0 actions flows update --file bindings.json`, PreRun: func(cmd *cobra.Command, args []string) { prepareInteractivity(cmd) }, RunE: func(cmd *cobra.Command, args []string) error { - if shouldPrompt(cmd, actionFile) { - input := prompt.TextInput(actionFile, "File:", "File containing the bindings.", true) - - if err := prompt.AskOne(input, &flags); err != nil { - return err + if len(args) == 0 { + if shouldPrompt(cmd, actionTrigger) { + input := prompt.SelectInput( + actionTrigger, + "Trigger:", + "Trigger type for action.", + validators.ValidTriggerIDs, + false) + + if err := prompt.AskOne(input, &inputs); err != nil { + return err + } + } else { + return errors.New("missing action trigger") } + } else { + inputs.Trigger = args[0] } - if shouldPrompt(cmd, actionTrigger) { - input := prompt.SelectInput( - actionTrigger, - "Trigger:", - "Trigger type for action.", - validators.ValidTriggerIDs, - false) + if shouldPrompt(cmd, actionFile) { + input := prompt.TextInput(actionFile, "File:", "File containing the bindings.", true) - if err := prompt.AskOne(input, &flags); err != nil { + if err := prompt.AskOne(input, &inputs); err != nil { return err } } - if err := validators.TriggerID(flags.Trigger); err != nil { + if err := validators.TriggerID(inputs.Trigger); err != nil { return err } - triggerID := management.TriggerID(flags.Trigger) + triggerID := management.TriggerID(inputs.Trigger) var list *management.ActionBindingList - err := readJsonFile(flags.File, &list) + err := readJsonFile(inputs.File, &list) if err != nil { return err } @@ -761,27 +821,43 @@ func updateFlowCmd(cli *cli) *cobra.Command { }, } - cmd.Flags().StringVarP(&flags.File, actionFile, "f", "", "File containing the bindings.") - cmd.Flags().StringVarP(&flags.Trigger, actionTrigger, "t", string(management.PostLogin), "Trigger type for action.") + cmd.Flags().StringVarP(&inputs.File, actionFile, "f", "", "File containing the bindings.") mustRequireFlags(cmd, actionFile) return cmd } func bindActionCmd(cli *cli) *cobra.Command { - var flags struct { - Action string + var inputs struct { + ID string Trigger string } cmd := &cobra.Command{ Use: "bind", + Args: cobra.MaximumNArgs(1), Short: "Bind an action to a flow", - Long: `auth0 actions bind --trigger --action `, + Long: `Bind an action to a flow: + +auth0 actions bind --trigger post-login`, PreRun: func(cmd *cobra.Command, args []string) { prepareInteractivity(cmd) }, RunE: func(cmd *cobra.Command, args []string) error { + if len(args) == 0 { + if shouldPrompt(cmd, actionID) { + input := prompt.TextInput(actionID, "Action Id:", "Action Id to bind.", false) + + if err := prompt.AskOne(input, &inputs); err != nil { + return err + } + } else { + return errors.New("missing action id") + } + } else { + inputs.ID = args[0] + } + if shouldPrompt(cmd, actionTrigger) { input := prompt.SelectInput( actionTrigger, @@ -790,31 +866,23 @@ func bindActionCmd(cli *cli) *cobra.Command { validators.ValidTriggerIDs, false) - if err := prompt.AskOne(input, &flags); err != nil { + if err := prompt.AskOne(input, &inputs); err != nil { return err } } - if shouldPrompt(cmd, "action") { - input := prompt.TextInput("action", "Action Id:", "Action Id to bind.", false) - - if err := prompt.AskOne(input, &flags); err != nil { - return err - } - } - - if err := validators.TriggerID(flags.Trigger); err != nil { + if err := validators.TriggerID(inputs.Trigger); err != nil { return err } - triggerID := management.TriggerID(flags.Trigger) + triggerID := management.TriggerID(inputs.Trigger) var binding *management.ActionBinding var list *management.ActionBindingList err := ansi.Spinner("Adding action", func() (err error) { var action *management.Action - if action, err = cli.api.Action.Read(flags.Action); err != nil { + if action, err = cli.api.Action.Read(inputs.ID); err != nil { return err } @@ -846,8 +914,7 @@ func bindActionCmd(cli *cli) *cobra.Command { }, } - cmd.Flags().StringVarP(&flags.Trigger, actionTrigger, "t", string(management.PostLogin), "Trigger type for action.") - cmd.Flags().StringVarP(&flags.Action, "action", "a", "", "Action Id to bind.") + cmd.Flags().StringVarP(&inputs.Trigger, actionTrigger, "t", string(management.PostLogin), "Trigger type for action.") return cmd } diff --git a/internal/cli/apis.go b/internal/cli/apis.go index a2abe1cc8..257ce4211 100644 --- a/internal/cli/apis.go +++ b/internal/cli/apis.go @@ -1,6 +1,7 @@ package cli import ( + "errors" "strings" "github.com/auth0/auth0-cli/internal/ansi" @@ -49,7 +50,7 @@ func scopesCmd(cli *cli) *cobra.Command { func listApisCmd(cli *cli) *cobra.Command { cmd := &cobra.Command{ Use: "list", - Short: "List your existing APIs", + Short: "List your APIs", Long: `auth0 apis list Lists your existing APIs. To create one try: @@ -77,34 +78,41 @@ Lists your existing APIs. To create one try: } func showApiCmd(cli *cli) *cobra.Command { - var flags struct { + var inputs struct { ID string } cmd := &cobra.Command{ Use: "show", + Args: cobra.MaximumNArgs(1), Short: "Show an API", Long: `Show an API: -auth0 apis show --id id +auth0 apis show `, PreRun: func(cmd *cobra.Command, args []string) { prepareInteractivity(cmd) }, RunE: func(cmd *cobra.Command, args []string) error { - if shouldPrompt(cmd, apiID) { - input := prompt.TextInput(apiID, "Id:", "Id of the API.", true) - - if err := prompt.AskOne(input, &flags); err != nil { - return err + if len(args) == 0 { + if shouldPrompt(cmd, apiID) { + input := prompt.TextInput(apiID, "Id:", "Id of the API.", true) + + if err := prompt.AskOne(input, &inputs); err != nil { + return err + } + } else { + return errors.New("missing API id") } + } else { + inputs.ID = args[0] } - api := &management.ResourceServer{ID: &flags.ID} + api := &management.ResourceServer{ID: &inputs.ID} err := ansi.Spinner("Loading API", func() error { var err error - api, err = cli.api.ResourceServer.Read(flags.ID) + api, err = cli.api.ResourceServer.Read(inputs.ID) return err }) @@ -117,9 +125,6 @@ auth0 apis show --id id }, } - cmd.Flags().StringVarP(&flags.ID, apiID, "i", "", "ID of the API.") - mustRequireFlags(cmd, apiID) - return cmd } @@ -202,7 +207,7 @@ auth0 apis create --name myapi --identifier http://my-api } func updateApiCmd(cli *cli) *cobra.Command { - var flags struct { + var inputs struct { ID string Name string Scopes string @@ -210,27 +215,34 @@ func updateApiCmd(cli *cli) *cobra.Command { cmd := &cobra.Command{ Use: "update", + Args: cobra.MaximumNArgs(1), Short: "Update an API", Long: `Update an API: -auth0 apis update --id id --name myapi +auth0 apis update --name myapi `, PreRun: func(cmd *cobra.Command, args []string) { prepareInteractivity(cmd) }, RunE: func(cmd *cobra.Command, args []string) error { - if shouldPrompt(cmd, apiID) { - input := prompt.TextInput(apiID, "Id:", "Id of the API.", true) - - if err := prompt.AskOne(input, &flags); err != nil { - return err + if len(args) == 0 { + if shouldPrompt(cmd, apiID) { + input := prompt.TextInput(apiID, "Id:", "Id of the API.", true) + + if err := prompt.AskOne(input, &inputs); err != nil { + return err + } + } else { + return errors.New("missing API id") } + } else { + inputs.ID = args[0] } if shouldPrompt(cmd, apiName) { input := prompt.TextInput(apiName, "Name:", "Name of the API.", true) - if err := prompt.AskOne(input, &flags); err != nil { + if err := prompt.AskOne(input, &inputs); err != nil { return err } } @@ -238,19 +250,19 @@ auth0 apis update --id id --name myapi if shouldPrompt(cmd, apiScopes) { input := prompt.TextInput(apiScopes, "Scopes:", "Space-separated list of scopes.", false) - if err := prompt.AskOne(input, &flags); err != nil { + if err := prompt.AskOne(input, &inputs); err != nil { return err } } - api := &management.ResourceServer{Name: &flags.Name} + api := &management.ResourceServer{Name: &inputs.Name} - if flags.Scopes != "" { - api.Scopes = getScopes(flags.Scopes) + if inputs.Scopes != "" { + api.Scopes = getScopes(inputs.Scopes) } err := ansi.Spinner("Updating API", func() error { - return cli.api.ResourceServer.Update(flags.ID, api) + return cli.api.ResourceServer.Update(inputs.ID, api) }) if err != nil { @@ -262,36 +274,41 @@ auth0 apis update --id id --name myapi }, } - cmd.Flags().StringVarP(&flags.ID, apiID, "i", "", "ID of the API.") - cmd.Flags().StringVarP(&flags.Name, apiName, "n", "", "Name of the API.") - cmd.Flags().StringVarP(&flags.Scopes, apiScopes, "s", "", "Space-separated list of scopes.") - mustRequireFlags(cmd, apiID) + cmd.Flags().StringVarP(&inputs.Name, apiName, "n", "", "Name of the API.") + cmd.Flags().StringVarP(&inputs.Scopes, apiScopes, "s", "", "Space-separated list of scopes.") return cmd } func deleteApiCmd(cli *cli) *cobra.Command { - var flags struct { + var inputs struct { ID string } cmd := &cobra.Command{ Use: "delete", + Args: cobra.MaximumNArgs(1), Short: "Delete an API", Long: `Delete an API: -auth0 apis delete --id id +auth0 apis delete `, PreRun: func(cmd *cobra.Command, args []string) { prepareInteractivity(cmd) }, RunE: func(cmd *cobra.Command, args []string) error { - if shouldPrompt(cmd, apiID) { - input := prompt.TextInput(apiID, "Id:", "Id of the API.", true) - - if err := prompt.AskOne(input, &flags); err != nil { - return err + if len(args) == 0 { + if shouldPrompt(cmd, apiID) { + input := prompt.TextInput(apiID, "Id:", "Id of the API.", true) + + if err := prompt.AskOne(input, &inputs); err != nil { + return err + } + } else { + return errors.New("missing API id") } + } else { + inputs.ID = args[0] } if !cli.force && canPrompt(cmd) { @@ -301,46 +318,50 @@ auth0 apis delete --id id } return ansi.Spinner("Deleting API", func() error { - return cli.api.ResourceServer.Delete(flags.ID) + return cli.api.ResourceServer.Delete(inputs.ID) }) }, } - cmd.Flags().StringVarP(&flags.ID, apiID, "i", "", "ID of the API.") - mustRequireFlags(cmd, apiID) - return cmd } func listScopesCmd(cli *cli) *cobra.Command { - var flags struct { + var inputs struct { ID string } cmd := &cobra.Command{ Use: "list", + Args: cobra.MaximumNArgs(1), Short: "List the scopes of an API", Long: `List the scopes of an API: -auth0 apis scopes list --id id +auth0 apis scopes list `, PreRun: func(cmd *cobra.Command, args []string) { prepareInteractivity(cmd) }, RunE: func(cmd *cobra.Command, args []string) error { - if shouldPrompt(cmd, apiID) { - input := prompt.TextInput(apiID, "Id:", "Id of the API.", true) - - if err := prompt.AskOne(input, &flags); err != nil { - return err + if len(args) == 0 { + if shouldPrompt(cmd, apiID) { + input := prompt.TextInput(apiID, "Id:", "Id of the API.", true) + + if err := prompt.AskOne(input, &inputs); err != nil { + return err + } + } else { + return errors.New("missing API id") } + } else { + inputs.ID = args[0] } - api := &management.ResourceServer{ID: &flags.ID} + api := &management.ResourceServer{ID: &inputs.ID} err := ansi.Spinner("Loading scopes", func() error { var err error - api, err = cli.api.ResourceServer.Read(flags.ID) + api, err = cli.api.ResourceServer.Read(inputs.ID) return err }) @@ -353,9 +374,6 @@ auth0 apis scopes list --id id }, } - cmd.Flags().StringVarP(&flags.ID, apiID, "i", "", "ID of the API.") - mustRequireFlags(cmd, apiID) - return cmd } diff --git a/internal/cli/apps.go b/internal/cli/apps.go index a69fe214a..0843b99b0 100644 --- a/internal/cli/apps.go +++ b/internal/cli/apps.go @@ -1,6 +1,7 @@ package cli import ( + "errors" "fmt" "strings" @@ -27,6 +28,7 @@ func appsCmd(cli *cli) *cobra.Command { cmd.SetUsageTemplate(resourceUsageTemplate()) cmd.AddCommand(listAppsCmd(cli)) + cmd.AddCommand(showAppCmd(cli)) cmd.AddCommand(createAppCmd(cli)) cmd.AddCommand(updateAppCmd(cli)) cmd.AddCommand(deleteAppCmd(cli)) @@ -63,28 +65,87 @@ Lists your existing applications. To create one try: return cmd } +func showAppCmd(cli *cli) *cobra.Command { + var inputs struct { + ID string + } + + cmd := &cobra.Command{ + Use: "show", + Args: cobra.MaximumNArgs(1), + Short: "Show an application", + Long: `Show an application: + +auth0 apps show +`, + PreRun: func(cmd *cobra.Command, args []string) { + prepareInteractivity(cmd) + }, + RunE: func(cmd *cobra.Command, args []string) error { + if len(args) == 0 { + if shouldPrompt(cmd, appID) { + input := prompt.TextInput(appID, "Id:", "Id of the application.", true) + + if err := prompt.AskOne(input, &inputs); err != nil { + return err + } + } else { + return errors.New("missing application id") + } + } else { + inputs.ID = args[0] + } + + a := &management.Client{ClientID: &inputs.ID} + + err := ansi.Spinner("Loading application", func() error { + var err error + a, err = cli.api.Client.Read(inputs.ID) + return err + }) + + if err != nil { + return err + } + + revealClientSecret := auth0.StringValue(a.AppType) != "native" && auth0.StringValue(a.AppType) != "spa" + cli.renderer.ApplicationShow(a, revealClientSecret) + return nil + }, + } + + return cmd +} + func deleteAppCmd(cli *cli) *cobra.Command { - var flags struct { + var inputs struct { ID string } cmd := &cobra.Command{ Use: "delete", + Args: cobra.MaximumNArgs(1), Short: "Delete an application", Long: `Delete an application: -auth0 apps delete --id id +auth0 apps delete `, PreRun: func(cmd *cobra.Command, args []string) { prepareInteractivity(cmd) }, RunE: func(cmd *cobra.Command, args []string) error { - if shouldPrompt(cmd, appID) { - input := prompt.TextInput(appID, "Id:", "Id of the application.", true) - - if err := prompt.AskOne(input, &flags); err != nil { - return err + if len(args) == 0 { + if shouldPrompt(cmd, appID) { + input := prompt.TextInput(appID, "Id:", "Id of the application.", true) + + if err := prompt.AskOne(input, &inputs); err != nil { + return err + } + } else { + return errors.New("missing application id") } + } else { + inputs.ID = args[0] } if !cli.force && canPrompt(cmd) { @@ -94,14 +155,11 @@ auth0 apps delete --id id } return ansi.Spinner("Deleting application", func() error { - return cli.api.Client.Delete(flags.ID) + return cli.api.Client.Delete(inputs.ID) }) }, } - cmd.Flags().StringVarP(&flags.ID, appID, "i", "", "ID of the application.") - mustRequireFlags(cmd, appID) - return cmd } @@ -199,7 +257,7 @@ auth0 apps create --name myapp --type [native|spa|regular|m2m] } func updateAppCmd(cli *cli) *cobra.Command { - var flags struct { + var inputs struct { ID string Name string Type string @@ -210,27 +268,34 @@ func updateAppCmd(cli *cli) *cobra.Command { cmd := &cobra.Command{ Use: "update", - Short: "Update a new application", - Long: `Update a new application: + Args: cobra.MaximumNArgs(1), + Short: "Update an application", + Long: `Update an application: -auth0 apps update --id id --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) }, RunE: func(cmd *cobra.Command, args []string) error { - if shouldPrompt(cmd, appID) { - input := prompt.TextInput(appID, "Id:", "Id of the application.", true) - - if err := prompt.AskOne(input, &flags); err != nil { - return err + if len(args) == 0 { + if shouldPrompt(cmd, appID) { + input := prompt.TextInput(appID, "Id:", "Id of the application.", true) + + if err := prompt.AskOne(input, &inputs); err != nil { + return err + } + } else { + return errors.New("missing application id") } + } else { + inputs.ID = args[0] } if shouldPrompt(cmd, appName) { input := prompt.TextInput(appName, "Name:", "Name of the application", true) - if err := prompt.AskOne(input, &flags); err != nil { + if err := prompt.AskOne(input, &inputs); err != nil { return err } } @@ -246,7 +311,7 @@ auth0 apps update --id id --name myapp --type [native|spa|regular|m2m] []string{"Native", "Single Page Web Application", "Regular Web Application", "Machine to Machine"}, true) - if err := prompt.AskOne(input, &flags); err != nil { + if err := prompt.AskOne(input, &inputs); err != nil { return err } } @@ -254,21 +319,21 @@ auth0 apps update --id id --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 { + if err := prompt.AskOne(input, &inputs); err != nil { return err } } a := &management.Client{ - Name: &flags.Name, - Description: &flags.Description, - AppType: auth0.String(apiTypeFor(flags.Type)), - Callbacks: apiCallbacksFor(flags.Callbacks), - TokenEndpointAuthMethod: apiAuthMethodFor(flags.AuthMethod), + Name: &inputs.Name, + Description: &inputs.Description, + AppType: auth0.String(apiTypeFor(inputs.Type)), + Callbacks: apiCallbacksFor(inputs.Callbacks), + TokenEndpointAuthMethod: apiAuthMethodFor(inputs.AuthMethod), } err := ansi.Spinner("Updating application", func() error { - return cli.api.Client.Update(flags.ID, a) + return cli.api.Client.Update(inputs.ID, a) }) if err != nil { @@ -283,17 +348,15 @@ auth0 apps update --id id --name myapp --type [native|spa|regular|m2m] }, } - cmd.Flags().StringVarP(&flags.ID, appID, "i", "", "ID of the application.") - cmd.Flags().StringVarP(&flags.Name, "name", "n", "", "Name of the application.") - cmd.Flags().StringVarP(&flags.Type, "type", "t", "", "Type of application:\n"+ + cmd.Flags().StringVarP(&inputs.Name, "name", "n", "", "Name of the application.") + 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(&flags.Description, "description", "d", "", "Description of the application. Max character count is 140.") - 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().StringVar(&flags.AuthMethod, "auth-method", "", "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).") - mustRequireFlags(cmd, appID) + cmd.Flags().StringVarP(&inputs.Description, "description", "d", "", "Description of the application. Max character count is 140.") + 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().StringVar(&inputs.AuthMethod, "auth-method", "", "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).") return cmd } diff --git a/internal/display/apps.go b/internal/display/apps.go index ecc588ac6..b705cc9e1 100644 --- a/internal/display/apps.go +++ b/internal/display/apps.go @@ -49,7 +49,6 @@ func (v *applicationView) AsTableRow() []string { ansi.Faint(v.ClientID), strings.Join(v.Callbacks, ", "), } - } // applicationListView is a slimmed down view of a client for displaying @@ -104,6 +103,21 @@ func (r *Renderer) ApplicationList(clients []*management.Client) { r.Results(res) } +func (r *Renderer) ApplicationShow(client *management.Client, revealSecrets bool) { + r.Heading(ansi.Bold(r.Tenant), "application\n") + + v := &applicationView{ + revealSecret: revealSecrets, + Name: auth0.StringValue(client.Name), + Type: appTypeFor(client.AppType), + ClientID: auth0.StringValue(client.ClientID), + ClientSecret: auth0.StringValue(client.ClientSecret), + Callbacks: callbacksFor(client.Callbacks), + } + + r.Results([]View{v}) +} + func (r *Renderer) ApplicationCreate(client *management.Client, revealSecrets bool) { r.Heading(ansi.Bold(r.Tenant), "application created\n")