The current code is misleading and in some respect plain wrong. Here is the existing code:
try {
String databaseName = config.getDatabaseName();
log.connectingToMongoDatabase( databaseName );
Boolean containsDatabase;
try {
containsDatabase = mongo.getDatabaseNames().contains( databaseName );
}
catch (MongoException me) {
containsDatabase = null;
}
if ( containsDatabase != null && containsDatabase == Boolean.FALSE ) {
if ( config.isCreateDatabase() ) {
log.creatingDatabase( databaseName );
}
else {
throw log.databaseDoesNotExistException( config.getDatabaseName() );
}
}
DB db = mongo.getDB( databaseName );
if ( containsDatabase == null ) {
int retries = 0;
while (true) {
try {
db.collectionExists( "WeDoNotCareWhatItIsWeNeedToConnect" );
break;
}
catch (MongoTimeoutException me) {
retries++;
if ( retries > 2 ) {
throw me;
}
}
}
}
return mongo.getDB( databaseName );
}
catch (MongoException me) {
switch ( me.getCode() ) {
case AUTHENTICATION_FAILED_CODE:
throw log.authenticationFailed( config.getUsername() );
default:
throw log.unableToConnectToDatastore( config.getHosts().toString(), me );
}
}
The idea is to check whether the specified database exists (using getDatabaseNames) and then depending on config.isCreateDatabase() create it (implicitly, since just calling getDB will create it). This makes really only sense if the database runs in no-auth mode. If the database runs with authentication, the user and database need to exist in the first place, otherwise an authentication error occurs. There is really no point to call getDatabaseNames anymore. Also the current code does just check the authorization error code (18) and in all other cases assumes that there is a privilege problem. That is not the case and should be explicitly tests (see https://github.com/mongodb/mongo/blob/master/src/mongo/base/error_codes.err). The error code of interest is "Unauthorized", 13. Last but not least, collectionExists to indirectly check whether the user has read access (which btw I think is a given and if anything we should check for readWrite access). This should be really replaced with something like:
BasicDBObject commandArguments = new BasicDBObject();
commandArguments.put("user", <user>);
commandArguments.put( "db", "<dbname> );
BasicDBObject command = new BasicDBObject("usersInfo", commandArguments);
CommandResult result = db.command( command );
The result contains the permissions of the given user for the specified database.
|