Browse Source

Fix building of MongoDB connection string with authentication db

This commit restores the previous behavior of MongoDB auto-
configuration, where the value of the
`spring.data.mongodb.authentication-database` is set in the
credentials when provided.

Fixes gh-35567
pull/35716/head
Scott Frederick 3 years ago
parent
commit
a02eb48528
  1. 39
      spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/PropertiesMongoConnectionDetails.java
  2. 90
      spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoAutoConfigurationTests.java
  3. 90
      spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoReactiveAutoConfigurationTests.java
  4. 65
      spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/PropertiesMongoConnectionDetailsTests.java

39
spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/PropertiesMongoConnectionDetails.java

@ -16,6 +16,9 @@ @@ -16,6 +16,9 @@
package org.springframework.boot.autoconfigure.mongo;
import java.util.ArrayList;
import java.util.List;
import com.mongodb.ConnectionString;
/**
@ -24,6 +27,7 @@ import com.mongodb.ConnectionString; @@ -24,6 +27,7 @@ import com.mongodb.ConnectionString;
* @author Moritz Halbritter
* @author Andy Wilkinson
* @author Phillip Webb
* @author Scott Frederick
* @since 3.1.0
*/
public class PropertiesMongoConnectionDetails implements MongoConnectionDetails {
@ -44,7 +48,9 @@ public class PropertiesMongoConnectionDetails implements MongoConnectionDetails @@ -44,7 +48,9 @@ public class PropertiesMongoConnectionDetails implements MongoConnectionDetails
if (this.properties.getUsername() != null) {
builder.append(this.properties.getUsername());
builder.append(":");
builder.append(this.properties.getPassword());
if (this.properties.getPassword() != null) {
builder.append(this.properties.getPassword());
}
builder.append("@");
}
builder.append((this.properties.getHost() != null) ? this.properties.getHost() : "localhost");
@ -55,20 +61,12 @@ public class PropertiesMongoConnectionDetails implements MongoConnectionDetails @@ -55,20 +61,12 @@ public class PropertiesMongoConnectionDetails implements MongoConnectionDetails
if (this.properties.getAdditionalHosts() != null) {
builder.append(String.join(",", this.properties.getAdditionalHosts()));
}
if (this.properties.getMongoClientDatabase() != null || this.properties.getReplicaSetName() != null
|| this.properties.getAuthenticationDatabase() != null) {
builder.append("/");
if (this.properties.getMongoClientDatabase() != null) {
builder.append(this.properties.getMongoClientDatabase());
}
else if (this.properties.getAuthenticationDatabase() != null) {
builder.append(this.properties.getAuthenticationDatabase());
}
if (this.properties.getReplicaSetName() != null) {
builder.append("?");
builder.append("replicaSet=");
builder.append(this.properties.getReplicaSetName());
}
builder.append("/");
builder.append(this.properties.getMongoClientDatabase());
List<String> options = getOptions();
if (!options.isEmpty()) {
builder.append("?");
builder.append(String.join("&", options));
}
return new ConnectionString(builder.toString());
}
@ -79,4 +77,15 @@ public class PropertiesMongoConnectionDetails implements MongoConnectionDetails @@ -79,4 +77,15 @@ public class PropertiesMongoConnectionDetails implements MongoConnectionDetails
PropertiesMongoConnectionDetails.this.properties.getGridfs().getBucket());
}
private List<String> getOptions() {
List<String> options = new ArrayList<>();
if (this.properties.getReplicaSetName() != null) {
options.add("replicaSet=" + this.properties.getReplicaSetName());
}
if (this.properties.getUsername() != null && this.properties.getAuthenticationDatabase() != null) {
options.add("authSource=" + this.properties.getAuthenticationDatabase());
}
return options;
}
}

90
spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoAutoConfigurationTests.java

@ -20,6 +20,7 @@ import java.util.concurrent.TimeUnit; @@ -20,6 +20,7 @@ import java.util.concurrent.TimeUnit;
import com.mongodb.ConnectionString;
import com.mongodb.MongoClientSettings;
import com.mongodb.MongoCredential;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.internal.MongoClientImpl;
@ -107,6 +108,95 @@ class MongoAutoConfigurationTests { @@ -107,6 +108,95 @@ class MongoAutoConfigurationTests {
});
}
@Test
void doesNotConfigureCredentialsWithoutUsername() {
this.contextRunner
.withPropertyValues("spring.data.mongodb.password=secret",
"spring.data.mongodb.authentication-database=authdb")
.run((context) -> assertThat(getSettings(context).getCredential()).isNull());
}
@Test
void configuresCredentialsFromPropertiesWithDefaultDatabase() {
this.contextRunner
.withPropertyValues("spring.data.mongodb.username=user", "spring.data.mongodb.password=secret")
.run((context) -> {
MongoCredential credential = getSettings(context).getCredential();
assertThat(credential.getUserName()).isEqualTo("user");
assertThat(credential.getPassword()).isEqualTo("secret".toCharArray());
assertThat(credential.getSource()).isEqualTo("test");
});
}
@Test
void configuresCredentialsFromPropertiesWithDatabase() {
this.contextRunner
.withPropertyValues("spring.data.mongodb.username=user", "spring.data.mongodb.password=secret",
"spring.data.mongodb.database=mydb")
.run((context) -> {
MongoCredential credential = getSettings(context).getCredential();
assertThat(credential.getUserName()).isEqualTo("user");
assertThat(credential.getPassword()).isEqualTo("secret".toCharArray());
assertThat(credential.getSource()).isEqualTo("mydb");
});
}
@Test
void configuresCredentialsFromPropertiesWithAuthDatabase() {
this.contextRunner
.withPropertyValues("spring.data.mongodb.username=user", "spring.data.mongodb.password=secret",
"spring.data.mongodb.database=mydb", "spring.data.mongodb.authentication-database=authdb")
.run((context) -> {
MongoCredential credential = getSettings(context).getCredential();
assertThat(credential.getUserName()).isEqualTo("user");
assertThat(credential.getPassword()).isEqualTo("secret".toCharArray());
assertThat(credential.getSource()).isEqualTo("authdb");
});
}
@Test
void doesNotConfigureCredentialsWithoutUsernameInUri() {
this.contextRunner.withPropertyValues("spring.data.mongodb.uri=mongodb://localhost/mydb?authSource=authdb")
.run((context) -> assertThat(getSettings(context).getCredential()).isNull());
}
@Test
void configuresCredentialsFromUriPropertyWithDefaultDatabase() {
this.contextRunner.withPropertyValues("spring.data.mongodb.uri=mongodb://user:secret@localhost/")
.run((context) -> {
MongoCredential credential = getSettings(context).getCredential();
assertThat(credential.getUserName()).isEqualTo("user");
assertThat(credential.getPassword()).isEqualTo("secret".toCharArray());
assertThat(credential.getSource()).isEqualTo("admin");
});
}
@Test
void configuresCredentialsFromUriPropertyWithDatabase() {
this.contextRunner
.withPropertyValues("spring.data.mongodb.uri=mongodb://user:secret@localhost/mydb",
"spring.data.mongodb.database=notused", "spring.data.mongodb.authentication-database=notused")
.run((context) -> {
MongoCredential credential = getSettings(context).getCredential();
assertThat(credential.getUserName()).isEqualTo("user");
assertThat(credential.getPassword()).isEqualTo("secret".toCharArray());
assertThat(credential.getSource()).isEqualTo("mydb");
});
}
@Test
void configuresCredentialsFromUriPropertyWithAuthDatabase() {
this.contextRunner
.withPropertyValues("spring.data.mongodb.uri=mongodb://user:secret@localhost/mydb?authSource=authdb",
"spring.data.mongodb.database=notused", "spring.data.mongodb.authentication-database=notused")
.run((context) -> {
MongoCredential credential = getSettings(context).getCredential();
assertThat(credential.getUserName()).isEqualTo("user");
assertThat(credential.getPassword()).isEqualTo("secret".toCharArray());
assertThat(credential.getSource()).isEqualTo("authdb");
});
}
@Test
void configuresSingleClient() {
this.contextRunner.withUserConfiguration(FallbackMongoClientConfig.class)

90
spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoReactiveAutoConfigurationTests.java

@ -21,6 +21,7 @@ import java.util.concurrent.atomic.AtomicReference; @@ -21,6 +21,7 @@ import java.util.concurrent.atomic.AtomicReference;
import com.mongodb.ConnectionString;
import com.mongodb.MongoClientSettings;
import com.mongodb.MongoCredential;
import com.mongodb.ReadPreference;
import com.mongodb.connection.AsynchronousSocketChannelStreamFactoryFactory;
import com.mongodb.connection.SslSettings;
@ -121,6 +122,95 @@ class MongoReactiveAutoConfigurationTests { @@ -121,6 +122,95 @@ class MongoReactiveAutoConfigurationTests {
});
}
@Test
void doesNotConfigureCredentialsWithoutUsername() {
this.contextRunner
.withPropertyValues("spring.data.mongodb.password=secret",
"spring.data.mongodb.authentication-database=authdb")
.run((context) -> assertThat(getSettings(context).getCredential()).isNull());
}
@Test
void configuresCredentialsFromPropertiesWithDefaultDatabase() {
this.contextRunner
.withPropertyValues("spring.data.mongodb.username=user", "spring.data.mongodb.password=secret")
.run((context) -> {
MongoCredential credential = getSettings(context).getCredential();
assertThat(credential.getUserName()).isEqualTo("user");
assertThat(credential.getPassword()).isEqualTo("secret".toCharArray());
assertThat(credential.getSource()).isEqualTo("test");
});
}
@Test
void configuresCredentialsFromPropertiesWithDatabase() {
this.contextRunner
.withPropertyValues("spring.data.mongodb.username=user", "spring.data.mongodb.password=secret",
"spring.data.mongodb.database=mydb")
.run((context) -> {
MongoCredential credential = getSettings(context).getCredential();
assertThat(credential.getUserName()).isEqualTo("user");
assertThat(credential.getPassword()).isEqualTo("secret".toCharArray());
assertThat(credential.getSource()).isEqualTo("mydb");
});
}
@Test
void configuresCredentialsFromPropertiesWithAuthDatabase() {
this.contextRunner
.withPropertyValues("spring.data.mongodb.username=user", "spring.data.mongodb.password=secret",
"spring.data.mongodb.database=mydb", "spring.data.mongodb.authentication-database=authdb")
.run((context) -> {
MongoCredential credential = getSettings(context).getCredential();
assertThat(credential.getUserName()).isEqualTo("user");
assertThat(credential.getPassword()).isEqualTo("secret".toCharArray());
assertThat(credential.getSource()).isEqualTo("authdb");
});
}
@Test
void doesNotConfigureCredentialsWithoutUsernameInUri() {
this.contextRunner.withPropertyValues("spring.data.mongodb.uri=mongodb://localhost/mydb?authSource=authdb")
.run((context) -> assertThat(getSettings(context).getCredential()).isNull());
}
@Test
void configuresCredentialsFromUriPropertyWithDefaultDatabase() {
this.contextRunner.withPropertyValues("spring.data.mongodb.uri=mongodb://user:secret@localhost/")
.run((context) -> {
MongoCredential credential = getSettings(context).getCredential();
assertThat(credential.getUserName()).isEqualTo("user");
assertThat(credential.getPassword()).isEqualTo("secret".toCharArray());
assertThat(credential.getSource()).isEqualTo("admin");
});
}
@Test
void configuresCredentialsFromUriPropertyWithDatabase() {
this.contextRunner
.withPropertyValues("spring.data.mongodb.uri=mongodb://user:secret@localhost/mydb",
"spring.data.mongodb.database=notused", "spring.data.mongodb.authentication-database=notused")
.run((context) -> {
MongoCredential credential = getSettings(context).getCredential();
assertThat(credential.getUserName()).isEqualTo("user");
assertThat(credential.getPassword()).isEqualTo("secret".toCharArray());
assertThat(credential.getSource()).isEqualTo("mydb");
});
}
@Test
void configuresCredentialsFromUriPropertyWithAuthDatabase() {
this.contextRunner
.withPropertyValues("spring.data.mongodb.uri=mongodb://user:secret@localhost/mydb?authSource=authdb",
"spring.data.mongodb.database=notused", "spring.data.mongodb.authentication-database=notused")
.run((context) -> {
MongoCredential credential = getSettings(context).getCredential();
assertThat(credential.getUserName()).isEqualTo("user");
assertThat(credential.getPassword()).isEqualTo("secret".toCharArray());
assertThat(credential.getSource()).isEqualTo("authdb");
});
}
@Test
void nettyStreamFactoryFactoryIsConfiguredAutomatically() {
AtomicReference<EventLoopGroup> eventLoopGroupReference = new AtomicReference<>();

65
spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/PropertiesMongoConnectionDetailsTests.java

@ -25,11 +25,66 @@ import static org.assertj.core.api.Assertions.assertThat; @@ -25,11 +25,66 @@ import static org.assertj.core.api.Assertions.assertThat;
* Tests for {@link PropertiesMongoConnectionDetails}.
*
* @author Christoph Dreis
* @author Scott Frederick
*/
class PropertiesMongoConnectionDetailsTests {
private final MongoProperties properties = new MongoProperties();
@Test
void credentialsCanBeConfiguredWithUsername() {
this.properties.setUsername("user");
ConnectionString connectionString = getConnectionString();
assertThat(connectionString.getUsername()).isEqualTo("user");
assertThat(connectionString.getPassword()).isEmpty();
assertThat(connectionString.getCredential().getUserName()).isEqualTo("user");
assertThat(connectionString.getCredential().getPassword()).isEmpty();
assertThat(connectionString.getCredential().getSource()).isEqualTo("test");
}
@Test
void credentialsCanBeConfiguredWithUsernameAndPassword() {
this.properties.setUsername("user");
this.properties.setPassword("secret".toCharArray());
ConnectionString connectionString = getConnectionString();
assertThat(connectionString.getUsername()).isEqualTo("user");
assertThat(connectionString.getPassword()).isEqualTo("secret".toCharArray());
assertThat(connectionString.getCredential().getUserName()).isEqualTo("user");
assertThat(connectionString.getCredential().getPassword()).isEqualTo("secret".toCharArray());
assertThat(connectionString.getCredential().getSource()).isEqualTo("test");
}
@Test
void databaseCanBeConfigured() {
this.properties.setDatabase("db");
ConnectionString connectionString = getConnectionString();
assertThat(connectionString.getDatabase()).isEqualTo("db");
}
@Test
void databaseHasDefaultWhenNotConfigured() {
ConnectionString connectionString = getConnectionString();
assertThat(connectionString.getDatabase()).isEqualTo("test");
}
@Test
void authenticationDatabaseCanBeConfigured() {
this.properties.setUsername("user");
this.properties.setDatabase("db");
this.properties.setAuthenticationDatabase("authdb");
ConnectionString connectionString = getConnectionString();
assertThat(connectionString.getDatabase()).isEqualTo("db");
assertThat(connectionString.getCredential().getSource()).isEqualTo("authdb");
assertThat(connectionString.getCredential().getUserName()).isEqualTo("user");
}
@Test
void authenticationDatabaseIsNotConfiguredWhenUsernameIsNotConfigured() {
this.properties.setAuthenticationDatabase("authdb");
ConnectionString connectionString = getConnectionString();
assertThat(connectionString.getCredential()).isNull();
}
@Test
void replicaSetCanBeConfigured() {
this.properties.setReplicaSetName("test");
@ -37,6 +92,16 @@ class PropertiesMongoConnectionDetailsTests { @@ -37,6 +92,16 @@ class PropertiesMongoConnectionDetailsTests {
assertThat(connectionString.getRequiredReplicaSetName()).isEqualTo("test");
}
@Test
void replicaSetCanBeConfiguredWithDatabase() {
this.properties.setUsername("user");
this.properties.setDatabase("db");
this.properties.setReplicaSetName("test");
ConnectionString connectionString = getConnectionString();
assertThat(connectionString.getDatabase()).isEqualTo("db");
assertThat(connectionString.getRequiredReplicaSetName()).isEqualTo("test");
}
private PropertiesMongoConnectionDetails createConnectionDetails() {
return new PropertiesMongoConnectionDetails(this.properties);
}

Loading…
Cancel
Save