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

Commit 677ef97

Browse files
authored
Merge pull request #253 from pontusmelke/4.0-non-interactive-fix
4.0 non interactive fix
2 parents a0a5ff2 + 25d06de commit 677ef97

File tree

3 files changed

+60
-35
lines changed

3 files changed

+60
-35
lines changed

cypher-shell/src/integration-test/java/org/neo4j/shell/MainIntegrationTest.java

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ private void ensureDefaultDatabaseStarted() throws Exception {
118118
cliArgs.setPassword("neo", "");
119119
cliArgs.setDatabase("system");
120120
ShellAndConnection sac = getShell(cliArgs);
121-
main.connectMaybeInteractively(sac.shell, sac.connectionConfig, true, false);
121+
main.connectMaybeInteractively(sac.shell, sac.connectionConfig, true, false, true);
122122
sac.shell.execute("START DATABASE " + DatabaseManager.DEFAULT_DEFAULT_DB_NAME);
123123
}
124124

@@ -128,7 +128,7 @@ public void promptsOnWrongAuthenticationIfInteractive() throws Exception {
128128
assertEquals("", connectionConfig.username());
129129
assertEquals("", connectionConfig.password());
130130

131-
main.connectMaybeInteractively(shell, connectionConfig, true, true);
131+
main.connectMaybeInteractively(shell, connectionConfig, true, true, true);
132132

133133
// then
134134
// should be connected
@@ -150,7 +150,7 @@ public void promptsOnPasswordChangeRequired() throws Exception {
150150
// when
151151
inputBuffer.put(String.format("foo%npass%nnewpass%n").getBytes());
152152
baos.reset();
153-
main.connectMaybeInteractively(shell, connectionConfig, true, true);
153+
main.connectMaybeInteractively(shell, connectionConfig, true, true, true);
154154

155155
// then
156156
assertTrue(shell.isConnected());
@@ -233,6 +233,23 @@ public void shouldBePromptedIfRunningNonInteractiveCypherThatDoesntUpdatePasswor
233233
"foo", "pass2", "RETURN 42 AS n" ) ) );
234234
}
235235

236+
@Test
237+
public void shouldNotBePromptedIfRunningWithExplicitNonInteractiveCypherThatDoesntUpdatePassword() throws Exception {
238+
//given a user that require a password change
239+
int majorVersion = getVersionAndCreateUserWithPasswordChangeRequired();
240+
241+
//when
242+
assumeTrue( majorVersion >= 4 );
243+
244+
//when interactively asked for a password use this
245+
inputBuffer.put( String.format( "pass2%n" ).getBytes() );
246+
baos.reset();
247+
CliArgs args = args( DEFAULT_DEFAULT_DB_NAME, "foo", "pass",
248+
"MATCH (n) RETURN n" );
249+
args.setNonInteractive( true );
250+
assertEquals( EXIT_FAILURE, main.runShell( args, shell, mock( Logger.class ) ) );
251+
}
252+
236253
@Test
237254
public void doesNotPromptToStdOutOnWrongAuthenticationIfOutputRedirected() throws Exception {
238255
// when
@@ -248,7 +265,7 @@ public void doesNotPromptToStdOutOnWrongAuthenticationIfOutputRedirected() throw
248265
// Create a Main with the standard in and out
249266
try {
250267
Main realMain = new Main();
251-
realMain.connectMaybeInteractively(shell, connectionConfig, true, false);
268+
realMain.connectMaybeInteractively(shell, connectionConfig, true, false, true);
252269

253270
// then
254271
// should be connected
@@ -280,7 +297,7 @@ public void wrongPortWithBolt() throws Exception
280297

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

286303
@Test
@@ -297,7 +314,7 @@ public void wrongPortWithNeo4j() throws Exception
297314

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

303320
@Test
@@ -313,7 +330,7 @@ public void shouldAskForCredentialsWhenConnectingWithAFile() throws Exception {
313330
ShellAndConnection sac = getShell(cliArgs);
314331
CypherShell shell = sac.shell;
315332
ConnectionConfig connectionConfig = sac.connectionConfig;
316-
main.connectMaybeInteractively( shell, connectionConfig, true, true );
333+
main.connectMaybeInteractively( shell, connectionConfig, true, true, true);
317334

318335
// then we should have prompted and set the username and password
319336
assertEquals( format( "username: neo4j%npassword: ***%n" ), baos.toString() );
@@ -445,7 +462,7 @@ public void doesNotStartWhenDefaultDatabaseUnavailableIfInteractive() throws Exc
445462
assertEquals("", connectionConfig.password());
446463

447464
// when
448-
main.connectMaybeInteractively(shell, connectionConfig, true, true);
465+
main.connectMaybeInteractively(shell, connectionConfig, true, true, true);
449466

450467
// Multiple databases are only available from 4.0
451468
assumeTrue( majorVersion( shell.getServerVersion() ) >= 4 );
@@ -469,7 +486,7 @@ public void doesNotStartWhenDefaultDatabaseUnavailableIfInteractive() throws Exc
469486
// Should get exception that database is unavailable when trying to connect
470487
exception.expect(TransientException.class);
471488
exception.expectMessage("Database 'neo4j' is unavailable");
472-
main.connectMaybeInteractively(shell, connectionConfig, true, true);
489+
main.connectMaybeInteractively(shell, connectionConfig, true, true, true);
473490

474491
// then
475492
assertFalse(shell.isConnected());
@@ -487,7 +504,7 @@ public void startsAgainstSystemDatabaseWhenDefaultDatabaseUnavailableIfInteracti
487504
assertEquals("", connectionConfig.password());
488505

489506
// when
490-
main.connectMaybeInteractively(shell, connectionConfig, true, true);
507+
main.connectMaybeInteractively(shell, connectionConfig, true, true, true);
491508

492509
// Multiple databases are only available from 4.0
493510
assumeTrue( majorVersion( shell.getServerVersion() ) >= 4 );
@@ -517,7 +534,7 @@ public void startsAgainstSystemDatabaseWhenDefaultDatabaseUnavailableIfInteracti
517534
// Use the new shell and connection config from here on
518535
shell = sac.shell;
519536
connectionConfig = sac.connectionConfig;
520-
main.connectMaybeInteractively(shell, connectionConfig, true, false);
537+
main.connectMaybeInteractively(shell, connectionConfig, true, false, true);
521538

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

538555
// when
539-
main.connectMaybeInteractively(shell, connectionConfig, true, true);
556+
main.connectMaybeInteractively(shell, connectionConfig, true, true, true);
540557

541558
// Multiple databases are only available from 4.0
542559
assumeTrue(majorVersion( shell.getServerVersion() ) >= 4);
@@ -574,7 +591,7 @@ public void switchingToUnavailableDefaultDatabaseIfInteractive() throws Exceptio
574591
assertEquals("", connectionConfig.password());
575592

576593
// when
577-
main.connectMaybeInteractively(shell, connectionConfig, true, true);
594+
main.connectMaybeInteractively(shell, connectionConfig, true, true, true);
578595

579596
// Multiple databases are only available from 4.0
580597
assumeTrue(majorVersion( shell.getServerVersion() ) >= 4);
@@ -638,7 +655,7 @@ private CypherShell interactiveShell( LinePrinter linePrinter ) throws Exception
638655
{
639656
PrettyConfig prettyConfig = new PrettyConfig( new CliArgs() );
640657
CypherShell shell = new CypherShell( linePrinter, prettyConfig, true, new ShellParameterMap() );
641-
main.connectMaybeInteractively( shell, connectionConfig, true, true );
658+
main.connectMaybeInteractively( shell, connectionConfig, true, true, true);
642659
shell.setCommandHelper( new CommandHelper( mock( Logger.class ), Historian.empty, shell) );
643660
return shell;
644661
}
@@ -695,7 +712,7 @@ private CliArgs args(String db, String user, String pass, String cypher)
695712
private int getVersionAndCreateUserWithPasswordChangeRequired() throws Exception {
696713
shell.setCommandHelper( new CommandHelper( mock( Logger.class ), Historian.empty, shell ) );
697714

698-
main.connectMaybeInteractively( shell, connectionConfig, true, true );
715+
main.connectMaybeInteractively( shell, connectionConfig, true, true, true);
699716
String expectedLoginOutput = format( "username: neo4j%npassword: ***%n" );
700717
assertEquals( expectedLoginOutput, baos.toString() );
701718
ensureUser();

cypher-shell/src/main/java/org/neo4j/shell/Main.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,14 +104,20 @@ int runShell(@Nonnull CliArgs cliArgs, @Nonnull CypherShell shell, Logger logger
104104
if ( cliArgs.getCypher().isPresent() )
105105
{
106106
// Can only prompt for password if input has not been redirected
107-
connectMaybeInteractively( shell, connectionConfig, isInputInteractive(), isOutputInteractive(),
107+
connectMaybeInteractively( shell, connectionConfig,
108+
!cliArgs.getNonInteractive() && isInputInteractive(),
109+
!cliArgs.getNonInteractive() && isOutputInteractive(),
110+
!cliArgs.getNonInteractive()/*Don't ask for password if using --non-interactive*/,
108111
() -> shell.execute( cliArgs.getCypher().get() ) );
109112
return EXIT_SUCCESS;
110113
}
111114
else
112115
{
113116
// Can only prompt for password if input has not been redirected
114-
connectMaybeInteractively( shell, connectionConfig, isInputInteractive(), isOutputInteractive());
117+
connectMaybeInteractively( shell, connectionConfig,
118+
!cliArgs.getNonInteractive() && isInputInteractive(),
119+
!cliArgs.getNonInteractive() && isOutputInteractive(),
120+
!cliArgs.getNonInteractive()/*Don't ask for password if using --non-interactive*/);
115121
// Construct shellrunner after connecting, due to interrupt handling
116122
ShellRunner shellRunner = ShellRunner.getShellRunner( cliArgs, shell, logger, connectionConfig );
117123
CommandHelper commandHelper = new CommandHelper( logger, shellRunner.getHistorian(), shell );
@@ -131,9 +137,10 @@ int runShell(@Nonnull CliArgs cliArgs, @Nonnull CypherShell shell, Logger logger
131137
void connectMaybeInteractively(@Nonnull CypherShell shell,
132138
@Nonnull ConnectionConfig connectionConfig,
133139
boolean inputInteractive,
134-
boolean outputInteractive)
140+
boolean outputInteractive,
141+
boolean shouldPromptForPassword)
135142
throws Exception {
136-
connectMaybeInteractively( shell, connectionConfig, inputInteractive, outputInteractive, null );
143+
connectMaybeInteractively( shell, connectionConfig, inputInteractive, outputInteractive, shouldPromptForPassword, null );
137144
}
138145

139146
/**
@@ -143,6 +150,7 @@ private void connectMaybeInteractively( @Nonnull CypherShell shell,
143150
@Nonnull ConnectionConfig connectionConfig,
144151
boolean inputInteractive,
145152
boolean outputInteractive,
153+
boolean shouldPromptForPassword,
146154
ThrowingAction<CommandException> command )
147155
throws Exception {
148156

@@ -173,7 +181,7 @@ private void connectMaybeInteractively( @Nonnull CypherShell shell,
173181
promptForUsernameAndPassword(connectionConfig, outputInteractive);
174182
didPrompt = true;
175183
} catch (Neo4jException e) {
176-
if (isPasswordChangeRequiredException(e)) {
184+
if (shouldPromptForPassword && isPasswordChangeRequiredException(e)) {
177185
promptForPasswordChange(connectionConfig, outputInteractive);
178186
shell.changePassword(connectionConfig);
179187
didPrompt = true;

cypher-shell/src/test/java/org/neo4j/shell/MainTest.java

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public void nonEndedStringFails() throws Exception {
6363
thrown.expectMessage("No text could be read, exiting");
6464

6565
Main main = new Main(inputStream, out);
66-
main.connectMaybeInteractively(shell, connectionConfig, true, true);
66+
main.connectMaybeInteractively(shell, connectionConfig, true, true, true);
6767
verify(shell, times(1)).connect(connectionConfig, null);
6868
}
6969

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

7777
Main main = new Main(mock(InputStream.class), out);
78-
main.connectMaybeInteractively(shell, connectionConfig, true, true);
78+
main.connectMaybeInteractively(shell, connectionConfig, true, true, true);
7979
verify(shell, times(1)).connect(connectionConfig, null);
8080
}
8181

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

9292
Main main = new Main(inputStream, ps);
93-
main.connectMaybeInteractively(shell, connectionConfig, true, true);
93+
main.connectMaybeInteractively(shell, connectionConfig, true, true, true);
9494

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

@@ -124,7 +124,7 @@ public void promptsSilentlyForUsernameAndPasswordIfNoneGivenIfOutputRedirected()
124124

125125
try {
126126
Main main = new Main();
127-
main.connectMaybeInteractively(shell, connectionConfig, true, false);
127+
main.connectMaybeInteractively(shell, connectionConfig, true, false, true);
128128

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

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

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

172172
Main main = new Main(inputStream, ps);
173-
main.connectMaybeInteractively(shell, connectionConfig, true, true);
173+
main.connectMaybeInteractively(shell, connectionConfig, true, true, true);
174174

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

@@ -203,7 +203,7 @@ public void promptsSilentlyForUserIfPassExistsIfOutputRedirected() throws Except
203203

204204
try {
205205
Main main = new Main();
206-
main.connectMaybeInteractively(shell, connectionConfig, true, false);
206+
main.connectMaybeInteractively(shell, connectionConfig, true, false, true);
207207

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

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

229229
Main main = new Main(inputStream, ps);
230-
main.connectMaybeInteractively(shell, connectionConfig, true, true);
230+
main.connectMaybeInteractively(shell, connectionConfig, true, true, true);
231231

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

@@ -260,7 +260,7 @@ public void promptsSilentlyForPassIfUserExistsIfOutputRedirected() throws Except
260260

261261
try {
262262
Main main = new Main();
263-
main.connectMaybeInteractively(shell, connectionConfig, true, false);
263+
main.connectMaybeInteractively(shell, connectionConfig, true, false, true);
264264

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

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

288288
Main main = new Main(inputStream, ps);
289-
main.connectMaybeInteractively(shell, connectionConfig, true, true);
289+
main.connectMaybeInteractively(shell, connectionConfig, true, true, true);
290290

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

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

313313
Main main = new Main(inputStream, ps);
314-
main.connectMaybeInteractively(shell, connectionConfig, true, true);
314+
main.connectMaybeInteractively(shell, connectionConfig, true, true, true);
315315

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

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

336336
Main main = new Main(inputStream, ps);
337-
main.connectMaybeInteractively(shell, connectionConfig, true, true);
337+
main.connectMaybeInteractively(shell, connectionConfig, true, true, true);
338338

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

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

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

379379
Main main = new Main(inputStream, ps);
380-
main.connectMaybeInteractively(shell, connectionConfig, true, true);
380+
main.connectMaybeInteractively(shell, connectionConfig, true, true, true);
381381

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

@@ -410,7 +410,7 @@ public void doesNotRepromptIfUserIsNotProvidedIfOutputRedirected() throws Except
410410

411411
try {
412412
Main main = new Main();
413-
main.connectMaybeInteractively(shell, connectionConfig, true, false);
413+
main.connectMaybeInteractively(shell, connectionConfig, true, false, true);
414414

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

0 commit comments

Comments
 (0)