Skip to content
This repository has been archived by the owner on Jul 6, 2023. It is now read-only.

Commit

Permalink
Merge pull request #252 from pontusmelke/4.1-non-interactive-fix
Browse files Browse the repository at this point in the history
4.1 non interactive fix
  • Loading branch information
pontusmelke authored Sep 15, 2020
2 parents f4155f5 + e370117 commit 251abcd
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ private void ensureDefaultDatabaseStarted() throws Exception {
cliArgs.setPassword("neo", "");
cliArgs.setDatabase("system");
ShellAndConnection sac = getShell(cliArgs);
main.connectMaybeInteractively(sac.shell, sac.connectionConfig, true, false);
main.connectMaybeInteractively(sac.shell, sac.connectionConfig, true, false, true);
sac.shell.execute("START DATABASE " + DatabaseManager.DEFAULT_DEFAULT_DB_NAME);
}

Expand All @@ -130,7 +130,7 @@ public void promptsOnWrongAuthenticationIfInteractive() throws Exception {
assertEquals("", connectionConfig.username());
assertEquals("", connectionConfig.password());

main.connectMaybeInteractively(shell, connectionConfig, true, true);
main.connectMaybeInteractively(shell, connectionConfig, true, true, true);

// then
// should be connected
Expand All @@ -152,7 +152,7 @@ public void promptsOnPasswordChangeRequired() throws Exception {
// when
inputBuffer.put(String.format("foo%npass%nnewpass%n").getBytes());
baos.reset();
main.connectMaybeInteractively(shell, connectionConfig, true, true);
main.connectMaybeInteractively(shell, connectionConfig, true, true, true);

// then
assertTrue(shell.isConnected());
Expand Down Expand Up @@ -235,6 +235,23 @@ public void shouldBePromptedIfRunningNonInteractiveCypherThatDoesntUpdatePasswor
"foo", "pass2", "RETURN 42 AS n" ) ) );
}

@Test
public void shouldNotBePromptedIfRunningWithExplicitNonInteractiveCypherThatDoesntUpdatePassword() throws Exception {
//given a user that require a password change
int majorVersion = getVersionAndCreateUserWithPasswordChangeRequired();

//when
assumeTrue( majorVersion >= 4 );

//when interactively asked for a password use this
inputBuffer.put( String.format( "pass2%n" ).getBytes() );
baos.reset();
CliArgs args = args( DEFAULT_DEFAULT_DB_NAME, "foo", "pass",
"MATCH (n) RETURN n" );
args.setNonInteractive( true );
assertEquals( EXIT_FAILURE, main.runShell( args, shell, mock( Logger.class ) ) );
}

@Test
public void doesNotPromptToStdOutOnWrongAuthenticationIfOutputRedirected() throws Exception {
// when
Expand All @@ -250,7 +267,7 @@ public void doesNotPromptToStdOutOnWrongAuthenticationIfOutputRedirected() throw
// Create a Main with the standard in and out
try {
Main realMain = new Main();
realMain.connectMaybeInteractively(shell, connectionConfig, true, false);
realMain.connectMaybeInteractively(shell, connectionConfig, true, false, true);

// then
// should be connected
Expand Down Expand Up @@ -282,7 +299,7 @@ public void wrongPortWithBolt() throws Exception

exception.expect( ServiceUnavailableException.class );
exception.expectMessage( "Unable to connect to localhost:1234, ensure the database is running and that there is a working network connection to it" );
main.connectMaybeInteractively( shell, connectionConfig, true, true );
main.connectMaybeInteractively( shell, connectionConfig, true, true, true);
}

@Test
Expand All @@ -299,7 +316,7 @@ public void wrongPortWithNeo4j() throws Exception

exception.expect( ServiceUnavailableException.class );
// The error message here may be subject to change and is not stable across versions so let us not assert on it
main.connectMaybeInteractively( shell, connectionConfig, true, true );
main.connectMaybeInteractively( shell, connectionConfig, true, true, true);
}

@Test
Expand All @@ -315,7 +332,7 @@ public void shouldAskForCredentialsWhenConnectingWithAFile() throws Exception {
ShellAndConnection sac = getShell(cliArgs);
CypherShell shell = sac.shell;
ConnectionConfig connectionConfig = sac.connectionConfig;
main.connectMaybeInteractively( shell, connectionConfig, true, true );
main.connectMaybeInteractively( shell, connectionConfig, true, true, true);

// then we should have prompted and set the username and password
assertEquals( format( "username: neo4j%npassword: ***%n" ), baos.toString() );
Expand Down Expand Up @@ -447,7 +464,7 @@ public void doesNotStartWhenDefaultDatabaseUnavailableIfInteractive() throws Exc
assertEquals("", connectionConfig.password());

// when
main.connectMaybeInteractively(shell, connectionConfig, true, true);
main.connectMaybeInteractively(shell, connectionConfig, true, true, true);

// Multiple databases are only available from 4.0
assumeTrue( majorVersion( shell.getServerVersion() ) >= 4 );
Expand All @@ -469,7 +486,7 @@ public void doesNotStartWhenDefaultDatabaseUnavailableIfInteractive() throws Exc
shell.disconnect();

// Should get exception that database is unavailable when trying to connect
main.connectMaybeInteractively(shell, connectionConfig, true, true);
main.connectMaybeInteractively(shell, connectionConfig, true, true, true);
fail("No exception thrown");
} catch(TransientException|ServiceUnavailableException e) {
expectDatabaseUnavailable(e, "neo4j");
Expand All @@ -487,7 +504,7 @@ public void startsAgainstSystemDatabaseWhenDefaultDatabaseUnavailableIfInteracti
assertEquals("", connectionConfig.password());

// when
main.connectMaybeInteractively(shell, connectionConfig, true, true);
main.connectMaybeInteractively(shell, connectionConfig, true, true, true);

// Multiple databases are only available from 4.0
assumeTrue( majorVersion( shell.getServerVersion() ) >= 4 );
Expand Down Expand Up @@ -517,7 +534,7 @@ public void startsAgainstSystemDatabaseWhenDefaultDatabaseUnavailableIfInteracti
// Use the new shell and connection config from here on
shell = sac.shell;
connectionConfig = sac.connectionConfig;
main.connectMaybeInteractively(shell, connectionConfig, true, false);
main.connectMaybeInteractively(shell, connectionConfig, true, false, true);

// then
assertTrue(shell.isConnected());
Expand All @@ -536,7 +553,7 @@ public void switchingToUnavailableDatabaseIfInteractive() throws Exception {
assertEquals("", connectionConfig.password());

// when
main.connectMaybeInteractively(shell, connectionConfig, true, true);
main.connectMaybeInteractively(shell, connectionConfig, true, true, true);

// Multiple databases are only available from 4.0
assumeTrue(majorVersion( shell.getServerVersion() ) >= 4);
Expand Down Expand Up @@ -575,7 +592,7 @@ public void switchingToUnavailableDefaultDatabaseIfInteractive() throws Exceptio
assertEquals("", connectionConfig.password());

// when
main.connectMaybeInteractively(shell, connectionConfig, true, true);
main.connectMaybeInteractively(shell, connectionConfig, true, true, true);

// Multiple databases are only available from 4.0
assumeTrue(majorVersion( shell.getServerVersion() ) >= 4);
Expand Down Expand Up @@ -648,7 +665,7 @@ private CypherShell interactiveShell( LinePrinter linePrinter ) throws Exception
{
PrettyConfig prettyConfig = new PrettyConfig( new CliArgs() );
CypherShell shell = new CypherShell( linePrinter, prettyConfig, true, new ShellParameterMap() );
main.connectMaybeInteractively( shell, connectionConfig, true, true );
main.connectMaybeInteractively( shell, connectionConfig, true, true, true);
shell.setCommandHelper( new CommandHelper( mock( Logger.class ), Historian.empty, shell) );
return shell;
}
Expand Down Expand Up @@ -705,7 +722,7 @@ private CliArgs args(String db, String user, String pass, String cypher)
private int getVersionAndCreateUserWithPasswordChangeRequired() throws Exception {
shell.setCommandHelper( new CommandHelper( mock( Logger.class ), Historian.empty, shell ) );

main.connectMaybeInteractively( shell, connectionConfig, true, true );
main.connectMaybeInteractively( shell, connectionConfig, true, true, true);
String expectedLoginOutput = format( "username: neo4j%npassword: ***%n" );
assertEquals( expectedLoginOutput, baos.toString() );
ensureUser();
Expand Down
18 changes: 13 additions & 5 deletions cypher-shell/src/main/java/org/neo4j/shell/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,20 @@ int runShell(@Nonnull CliArgs cliArgs, @Nonnull CypherShell shell, Logger logger
if ( cliArgs.getCypher().isPresent() )
{
// Can only prompt for password if input has not been redirected
connectMaybeInteractively( shell, connectionConfig, isInputInteractive(), isOutputInteractive(),
connectMaybeInteractively( shell, connectionConfig,
!cliArgs.getNonInteractive() && isInputInteractive(),
!cliArgs.getNonInteractive() && isOutputInteractive(),
!cliArgs.getNonInteractive()/*Don't ask for password if using --non-interactive*/,
() -> shell.execute( cliArgs.getCypher().get() ) );
return EXIT_SUCCESS;
}
else
{
// Can only prompt for password if input has not been redirected
connectMaybeInteractively( shell, connectionConfig, isInputInteractive(), isOutputInteractive());
connectMaybeInteractively( shell, connectionConfig,
!cliArgs.getNonInteractive() && isInputInteractive(),
!cliArgs.getNonInteractive() && isOutputInteractive(),
!cliArgs.getNonInteractive()/*Don't ask for password if using --non-interactive*/);
// Construct shellrunner after connecting, due to interrupt handling
ShellRunner shellRunner = ShellRunner.getShellRunner( cliArgs, shell, logger, connectionConfig );
CommandHelper commandHelper = new CommandHelper( logger, shellRunner.getHistorian(), shell );
Expand All @@ -131,9 +137,10 @@ int runShell(@Nonnull CliArgs cliArgs, @Nonnull CypherShell shell, Logger logger
void connectMaybeInteractively(@Nonnull CypherShell shell,
@Nonnull ConnectionConfig connectionConfig,
boolean inputInteractive,
boolean outputInteractive)
boolean outputInteractive,
boolean shouldPromptForPassword)
throws Exception {
connectMaybeInteractively( shell, connectionConfig, inputInteractive, outputInteractive, null );
connectMaybeInteractively( shell, connectionConfig, inputInteractive, outputInteractive, shouldPromptForPassword, null );
}

/**
Expand All @@ -143,6 +150,7 @@ private void connectMaybeInteractively( @Nonnull CypherShell shell,
@Nonnull ConnectionConfig connectionConfig,
boolean inputInteractive,
boolean outputInteractive,
boolean shouldPromptForPassword,
ThrowingAction<CommandException> command )
throws Exception {

Expand Down Expand Up @@ -173,7 +181,7 @@ private void connectMaybeInteractively( @Nonnull CypherShell shell,
promptForUsernameAndPassword(connectionConfig, outputInteractive);
didPrompt = true;
} catch (Neo4jException e) {
if (isPasswordChangeRequiredException(e)) {
if (shouldPromptForPassword && isPasswordChangeRequiredException(e)) {
promptForPasswordChange(connectionConfig, outputInteractive);
shell.changePassword(connectionConfig);
didPrompt = true;
Expand Down
30 changes: 15 additions & 15 deletions cypher-shell/src/test/java/org/neo4j/shell/MainTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public void nonEndedStringFails() throws Exception {
thrown.expectMessage("No text could be read, exiting");

Main main = new Main(inputStream, out);
main.connectMaybeInteractively(shell, connectionConfig, true, true);
main.connectMaybeInteractively(shell, connectionConfig, true, true, true);
verify(shell, times(1)).connect(connectionConfig, null);
}

Expand All @@ -75,7 +75,7 @@ public void unrelatedErrorDoesNotPrompt() throws Exception {
thrown.expectMessage("bla");

Main main = new Main(mock(InputStream.class), out);
main.connectMaybeInteractively(shell, connectionConfig, true, true);
main.connectMaybeInteractively(shell, connectionConfig, true, true, true);
verify(shell, times(1)).connect(connectionConfig, null);
}

Expand All @@ -90,7 +90,7 @@ public void promptsForUsernameAndPasswordIfNoneGivenIfInteractive() throws Excep
PrintStream ps = new PrintStream(baos);

Main main = new Main(inputStream, ps);
main.connectMaybeInteractively(shell, connectionConfig, true, true);
main.connectMaybeInteractively(shell, connectionConfig, true, true, true);

String out = new String(baos.toByteArray(), StandardCharsets.UTF_8);

Expand Down Expand Up @@ -124,7 +124,7 @@ public void promptsSilentlyForUsernameAndPasswordIfNoneGivenIfOutputRedirected()

try {
Main main = new Main();
main.connectMaybeInteractively(shell, connectionConfig, true, false);
main.connectMaybeInteractively(shell, connectionConfig, true, false, true);

String out = new String(baos.toByteArray(), StandardCharsets.UTF_8);

Expand All @@ -151,7 +151,7 @@ public void doesNotPromptIfInputRedirected() throws Exception {
Main main = new Main(inputStream, ps);

try {
main.connectMaybeInteractively(shell, connectionConfig, false, true);
main.connectMaybeInteractively(shell, connectionConfig, false, true, true);
fail("Expected auth exception");
} catch (AuthenticationException e) {
verify(shell, times(1)).connect(connectionConfig, null);
Expand All @@ -170,7 +170,7 @@ public void promptsForUserIfPassExistsIfInteractive() throws Exception {
PrintStream ps = new PrintStream(baos);

Main main = new Main(inputStream, ps);
main.connectMaybeInteractively(shell, connectionConfig, true, true);
main.connectMaybeInteractively(shell, connectionConfig, true, true, true);

String out = new String(baos.toByteArray(), StandardCharsets.UTF_8);

Expand Down Expand Up @@ -203,7 +203,7 @@ public void promptsSilentlyForUserIfPassExistsIfOutputRedirected() throws Except

try {
Main main = new Main();
main.connectMaybeInteractively(shell, connectionConfig, true, false);
main.connectMaybeInteractively(shell, connectionConfig, true, false, true);

String out = new String(baos.toByteArray(), StandardCharsets.UTF_8);

Expand All @@ -227,7 +227,7 @@ public void promptsForPassBeforeConnectIfUserExistsIfInteractive() throws Except
PrintStream ps = new PrintStream(baos);

Main main = new Main(inputStream, ps);
main.connectMaybeInteractively(shell, connectionConfig, true, true);
main.connectMaybeInteractively(shell, connectionConfig, true, true, true);

String out = new String(baos.toByteArray(), StandardCharsets.UTF_8);

Expand Down Expand Up @@ -260,7 +260,7 @@ public void promptsSilentlyForPassIfUserExistsIfOutputRedirected() throws Except

try {
Main main = new Main();
main.connectMaybeInteractively(shell, connectionConfig, true, false);
main.connectMaybeInteractively(shell, connectionConfig, true, false, true);

String out = new String(baos.toByteArray(), StandardCharsets.UTF_8);

Expand All @@ -286,7 +286,7 @@ public void promptsForNewPasswordIfPasswordChangeRequired() throws Exception {
PrintStream ps = new PrintStream(baos);

Main main = new Main(inputStream, ps);
main.connectMaybeInteractively(shell, connectionConfig, true, true);
main.connectMaybeInteractively(shell, connectionConfig, true, true, true);

String out = new String(baos.toByteArray(), StandardCharsets.UTF_8);

Expand All @@ -311,7 +311,7 @@ public void promptsForNewPasswordIfPasswordChangeRequiredCannotBeEmpty() throws
PrintStream ps = new PrintStream(baos);

Main main = new Main(inputStream, ps);
main.connectMaybeInteractively(shell, connectionConfig, true, true);
main.connectMaybeInteractively(shell, connectionConfig, true, true, true);

String out = new String(baos.toByteArray(), StandardCharsets.UTF_8);

Expand All @@ -334,7 +334,7 @@ public void promptsHandlesBang() throws Exception {
PrintStream ps = new PrintStream(baos);

Main main = new Main(inputStream, ps);
main.connectMaybeInteractively(shell, connectionConfig, true, true);
main.connectMaybeInteractively(shell, connectionConfig, true, true, true);

String out = new String(baos.toByteArray(), StandardCharsets.UTF_8);

Expand All @@ -358,7 +358,7 @@ public void triesOnlyOnceIfUserPassExists() throws Exception {
Main main = new Main(inputStream, ps);

try {
main.connectMaybeInteractively(shell, connectionConfig, true, true);
main.connectMaybeInteractively(shell, connectionConfig, true, true, true);
fail("Expected an exception");
} catch (Neo4jException e) {
assertEquals(authException.code(), e.code());
Expand All @@ -377,7 +377,7 @@ public void repromptsIfUserIsNotProvidedIfInteractive() throws Exception {
PrintStream ps = new PrintStream(baos);

Main main = new Main(inputStream, ps);
main.connectMaybeInteractively(shell, connectionConfig, true, true);
main.connectMaybeInteractively(shell, connectionConfig, true, true, true);

String out = new String(baos.toByteArray(), StandardCharsets.UTF_8);

Expand Down Expand Up @@ -410,7 +410,7 @@ public void doesNotRepromptIfUserIsNotProvidedIfOutputRedirected() throws Except

try {
Main main = new Main();
main.connectMaybeInteractively(shell, connectionConfig, true, false);
main.connectMaybeInteractively(shell, connectionConfig, true, false, true);

String out = new String(baos.toByteArray(), StandardCharsets.UTF_8);

Expand Down

0 comments on commit 251abcd

Please sign in to comment.