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

Commit 09ff24f

Browse files
committed
Fix bug when running non-interactively and password change required
In the situation when running non-interactively without when a password change was required, such as running the following on a vanilla db ``` cypher-shell -u neo4j -p neo4j "RETURN 1" ``` the user was first prompted for a password but then failed with the error >This procedure is no longer available, use: 'ALTER CURRENT USER SET PASSWORD' This was due to a recent change how we handle interactive commands, what happens is we never run the `ping` so we never get a chance to set the `version` field in `BoltStateHandler` which in turn messes up the updating of the password since it thinks we are communicating with an older db.
1 parent 93a5765 commit 09ff24f

File tree

3 files changed

+32
-8
lines changed

3 files changed

+32
-8
lines changed

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

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
import static org.neo4j.shell.ShellRunner.isInputInteractive;
2424
import static org.neo4j.shell.ShellRunner.isOutputInteractive;
25+
import static org.neo4j.shell.util.Versions.isPasswordChangeRequiredException;
2526

2627
public class Main {
2728
static final String NEO_CLIENT_ERROR_SECURITY_UNAUTHORIZED = "Neo.ClientError.Security.Unauthorized";
@@ -172,7 +173,7 @@ private void connectMaybeInteractively( @Nonnull CypherShell shell,
172173
promptForUsernameAndPassword(connectionConfig, outputInteractive);
173174
didPrompt = true;
174175
} catch (Neo4jException e) {
175-
if (passwordChangeRequiredException(e)) {
176+
if (isPasswordChangeRequiredException(e)) {
176177
promptForPasswordChange(connectionConfig, outputInteractive);
177178
shell.changePassword(connectionConfig);
178179
didPrompt = true;
@@ -183,10 +184,6 @@ private void connectMaybeInteractively( @Nonnull CypherShell shell,
183184
}
184185
}
185186

186-
private boolean passwordChangeRequiredException(Neo4jException e) {
187-
return "Neo.ClientError.Security.CredentialsExpired".equalsIgnoreCase(e.code());
188-
}
189-
190187
private void promptForUsernameAndPassword(ConnectionConfig connectionConfig, boolean outputInteractive) throws Exception {
191188
OutputStream promptOutputStream = getOutputStreamForInteractivePrompt();
192189
ConsoleReader consoleReader = new ConsoleReader(in, promptOutputStream);

cypher-shell/src/main/java/org/neo4j/shell/state/BoltStateHandler.java

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.neo4j.driver.Value;
2626
import org.neo4j.driver.Values;
2727
import org.neo4j.driver.exceptions.ClientException;
28+
import org.neo4j.driver.exceptions.Neo4jException;
2829
import org.neo4j.driver.exceptions.SessionExpiredException;
2930
import org.neo4j.driver.internal.Scheme;
3031
import org.neo4j.driver.summary.DatabaseInfo;
@@ -38,6 +39,7 @@
3839
import org.neo4j.shell.exception.CommandException;
3940
import org.neo4j.shell.log.NullLogging;
4041

42+
import static org.neo4j.shell.util.Versions.isPasswordChangeRequiredException;
4143
import static org.neo4j.shell.util.Versions.majorVersion;
4244

4345
/**
@@ -218,10 +220,28 @@ else if ( systemBookmark != null )
218220

219221
session = driver.session( builder.build() );
220222

221-
ThrowingAction<CommandException> action = command != null ? command : getPing();
222-
223223
resetActualDbName(); // Set this to null first in case run throws an exception
224-
action.apply();
224+
wrap(command).apply();
225+
}
226+
227+
private ThrowingAction<CommandException> wrap(ThrowingAction<CommandException> command) {
228+
return command == null ? getPing() : () ->
229+
{
230+
try
231+
{
232+
command.apply();
233+
}
234+
catch ( Neo4jException e )
235+
{
236+
//If we need to update password we need to call the apply
237+
//to set the server version and such.
238+
if (isPasswordChangeRequiredException( e ))
239+
{
240+
getPing().apply();
241+
}
242+
throw e;
243+
}
244+
};
225245
}
226246

227247
private ThrowingAction<CommandException> getPing() {
@@ -401,6 +421,7 @@ public void reset() {
401421
public void disconnect() {
402422
reset();
403423
silentDisconnect();
424+
version = null;
404425
}
405426

406427
List<Query> getTransactionStatements() {

cypher-shell/src/main/java/org/neo4j/shell/util/Versions.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.neo4j.shell.util;
22

3+
import org.neo4j.driver.exceptions.Neo4jException;
4+
35
import static java.lang.Integer.parseInt;
46
import static java.lang.String.format;
57

@@ -47,4 +49,8 @@ public static Version version(String version) {
4749
format("%s is not a proper version string, it should be of the form X.Y.Z ", version));
4850
}
4951
}
52+
53+
public static boolean isPasswordChangeRequiredException( Neo4jException e) {
54+
return "Neo.ClientError.Security.CredentialsExpired".equalsIgnoreCase(e.code());
55+
}
5056
}

0 commit comments

Comments
 (0)