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

Prompt for password is shown even when --help is used #460

Open
perlun opened this issue Nov 28, 2018 · 2 comments
Open

Prompt for password is shown even when --help is used #460

perlun opened this issue Nov 28, 2018 · 2 comments

Comments

@perlun
Copy link

perlun commented Nov 28, 2018

Thanks for a great library. My scenario: I am writing a command line tool that requires a password to be provided.

If I specify the required = true setting in the @Parameter annotation for my password field, the user will have to type --password which isn't really what I want - I want them to always be asked for the password, unless the password is set using an environment variable.

Because of this, I've come up with an approach that looks like below:

    @Parameter(names = { "-h", "--help" }, help = true)
    protected boolean help;

    @Parameter(names = "--password", description = "Connection password", password = true)
    protected String password = System.getenv("THE_PASSWORD");

    void someMethod(String[] args) {
        List<String> argsList = Lists.newArrayList( args );

        if ( password == null ) {
            // Environment variable not set - add to list of arguments.
            argsList.add( "--password" );
        }

        JCommander jCommander = JCommander.newBuilder()
                .addObject( this )
                .build();

        jCommander.parse( modifiedArgs );

        if (help) {
            jCommander.usage();
        }

...i.e, add a "fake" argument --password to the list of argument being passed to JCommander.

This works reasonably well for most scenarios, but I've seen at least one such where it does not:

  • If the user types --help, they will be first prompted for the password where they can press Enter, and then they will get the command line usage.

I believe this is flawed - the help = true argument should take precedence over all password = true arguments. If the user asked for help, it does not make much sense to force them to provide all password-flagged arguments (even if they typed --password on the command line, or as in my case, it was injected by the program) - since execution of the program will be aborted anyway.

If you have some other suggestion(s), I'm open for it.

@remkop
Copy link

remkop commented Dec 21, 2018

You get use the System.console().readPassword() API in your application.

With picocli this would look something like this (JCommander should be fairly similar):

import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;

@Command(name = "app", mixinStandardHelpOptions = true,
        description = "Password example app", version = "1.0")
public class PasswordExample implements Runnable {

    @Option(names = "--password", description = "Connection password", interactive = true)
    protected String password = System.getenv("THE_PASSWORD");

    public static void main(String[] args) {
        CommandLine.run(new PasswordExample(), args);
    }
    
    public void run() {
        if (password == null) {
            password = new String(System.console().readPassword("Connection password: "));
        }
        System.out.printf("Your password is: %s", password);
    }
}

If I start the app without arguments, it prompts me for the password.
When the environment variable is defined, it uses that value as the password without prompting.

With --help, it shows this:

Usage: app [-hV] [--password=<password>]
Password example app
      --password=<password>
                  Connection password
  -h, --help      Show this help message and exit.
  -V, --version   Print version information and exit.

@navneet-kumar
Copy link

    @Parameter(names = { "-h", "--help" }, help = true)
    protected boolean help;

    @Parameter(names = "--password", description = "Connection password", password = true)
    protected String password = System.getenv("THE_PASSWORD");

    void someMethod(String[] args) {
        List<String> argsList = Lists.newArrayList( args );

        // check if it's a help request here itself, since password argument is not added it wont ask for password
        if (help) {
            jCommander.usage();
        }

        if ( password == null ) {
            // Environment variable not set - add to list of arguments.
            argsList.add( "--password" );
        }

        JCommander jCommander = JCommander.newBuilder()
                .addObject( this )
                .build();

        jCommander.parse( modifiedArgs );

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants