Permalink
Browse files

RUBY-529 raise exception for multiple attempts to auth on the same db

Server side, MongoDB will log out the first user when a second authentication
is issued for the same database. In the past we've handled this by just quietly
updating the authentication credentials we have stored for that db.

The driver spec for auth now requires that we raise an explicit exception so
that users don't unknowingly log out previous authentications applied to the
database.
  • Loading branch information...
1 parent 1a413d9 commit 6428bf699697dbd93622e0a411b5b153295bfe4e @brandonblack brandonblack committed Mar 8, 2013
View
@@ -99,10 +99,8 @@ def initialize(name, client, opts={})
#
# @core authenticate authenticate-instance_method
def authenticate(username, password, save_auth=true)
- if @connection.pool_size > 1
- if !save_auth
- raise MongoArgumentError, "If using connection pooling, :save_auth must be set to true."
- end
+ if @connection.pool_size > 1 && !save_auth
+ raise MongoArgumentError, "If using connection pooling, :save_auth must be set to true."
end
begin
@@ -206,16 +204,12 @@ def remove_user(username)
#
# @return [Boolean]
def logout(opts={})
- if @connection.pool_size > 1
- @connection.logout_pools(@name)
- end
-
+ @connection.logout_pools(@name) if @connection.pool_size > 1
issue_logout(opts)
end
def issue_logout(opts={})
- doc = command({:logout => 1}, :socket => opts[:socket])
- if ok?(doc)
+ if ok?(doc = command({:logout => 1}, :socket => opts[:socket]))
@connection.remove_auth(@name)
true
else
View
@@ -241,7 +241,7 @@ def unlock!
def apply_saved_authentication(opts={})
return false if @auths.empty?
@auths.each do |auth|
- self[auth['db_name']].issue_authentication(auth['username'], auth['password'], false,
+ self[auth[:db_name]].issue_authentication(auth[:username], auth[:password], false,
:socket => opts[:socket])
end
true
@@ -261,11 +261,15 @@ def apply_saved_authentication(opts={})
#
# @return [Hash] a hash representing the authentication just added.
def add_auth(db_name, username, password)
- remove_auth(db_name)
- auth = {}
- auth['db_name'] = db_name
- auth['username'] = username
- auth['password'] = password
+ if @auths.any? {|a| a[:db_name] == db_name}
+ raise MongoArgumentError, "Cannot apply multiple authentications to database '#{db_name}'"
+ end
+
+ auth = {
+ :db_name => db_name,
+ :username => username,
+ :password => password
+ }
@auths << auth
auth
end
@@ -277,11 +281,7 @@ def add_auth(db_name, username, password)
# @return [Boolean]
def remove_auth(db_name)
return unless @auths
- if @auths.reject! { |a| a['db_name'] == db_name }
- true
- else
- false
- end
+ @auths.reject! { |a| a[:db_name] == db_name } ? true : false
end
# Remove all authentication information stored in this connection.
@@ -285,7 +285,7 @@ def parse_hosts(uri_without_proto)
end
if uname && pwd && db
- auths << {'db_name' => db, 'username' => uname, 'password' => pwd}
+ auths << {:db_name => db, :username => uname, :password => pwd}
elsif uname || pwd
raise MongoArgumentError, "MongoDB URI must include username, password, "
"and db if username and password are specified."
@@ -336,8 +336,8 @@ def test_connection_activity
context "Saved authentications" do
setup do
@client = standard_connection
- @auth = {'db_name' => 'test', 'username' => 'bob', 'password' => 'secret'}
- @client.add_auth(@auth['db_name'], @auth['username'], @auth['password'])
+ @auth = {:db_name => 'test', :username => 'bob', :password => 'secret'}
+ @client.add_auth(@auth[:db_name], @auth[:username], @auth[:password])
end
teardown do
@@ -348,11 +348,11 @@ def test_connection_activity
assert_equal @auth, @client.auths[0]
end
- should "replace the auth if given a new auth for the same db" do
- auth = {'db_name' => 'test', 'username' => 'mickey', 'password' => 'm0u53'}
- @client.add_auth(auth['db_name'], auth['username'], auth['password'])
- assert_equal 1, @client.auths.length
- assert_equal auth, @client.auths[0]
+ should "not allow multiple authentications for the same db" do
+ auth = {:db_name => 'test', :username => 'mickey', :password => 'm0u53'}
+ assert_raise Mongo::MongoArgumentError do
+ @client.add_auth(auth[:db_name], auth[:username], auth[:password])
+ end
end
should "remove auths by database" do
@@ -26,17 +26,17 @@ def test_multiple_uris
def test_complex_passwords
parser = Mongo::URIParser.new('mongodb://bob:secret.word@a.example.com:27018/test')
- assert_equal "bob", parser.auths[0]["username"]
- assert_equal "secret.word", parser.auths[0]["password"]
+ assert_equal "bob", parser.auths[0][:username]
+ assert_equal "secret.word", parser.auths[0][:password]
parser = Mongo::URIParser.new('mongodb://bob:s-_3#%R.t@a.example.com:27018/test')
- assert_equal "bob", parser.auths[0]["username"]
- assert_equal "s-_3#%R.t", parser.auths[0]["password"]
+ assert_equal "bob", parser.auths[0][:username]
+ assert_equal "s-_3#%R.t", parser.auths[0][:password]
end
def test_complex_usernames
parser = Mongo::URIParser.new('mongodb://b:ob:secret.word@a.example.com:27018/test')
- assert_equal "b:ob", parser.auths[0]["username"]
+ assert_equal "b:ob", parser.auths[0][:username]
end
def test_passwords_contain_no_commas
@@ -51,12 +51,12 @@ def test_multiple_uris_with_auths
assert_equal ['a.example.com', 27018], parser.nodes[0]
assert_equal ['b.example.com', 27017], parser.nodes[1]
assert_equal 2, parser.auths.length
- assert_equal "bob", parser.auths[0]["username"]
- assert_equal "secret", parser.auths[0]["password"]
- assert_equal "test", parser.auths[0]["db_name"]
- assert_equal "bob", parser.auths[1]["username"]
- assert_equal "secret", parser.auths[1]["password"]
- assert_equal "test", parser.auths[1]["db_name"]
+ assert_equal "bob", parser.auths[0][:username]
+ assert_equal "secret", parser.auths[0][:password]
+ assert_equal "test", parser.auths[0][:db_name]
+ assert_equal "bob", parser.auths[1][:username]
+ assert_equal "secret", parser.auths[1][:password]
+ assert_equal "test", parser.auths[1][:db_name]
end
def test_opts_with_semincolon_separator
View
@@ -128,7 +128,7 @@ class ClientTest < Test::Unit::TestCase
should "parse a uri with a hyphen & underscore in the username or password" do
@client = MongoClient.from_uri("mongodb://hyphen-user_name:p-s_s@localhost:27017/db", :connect => false)
assert_equal ['localhost', 27017], @client.host_port
- auth_hash = { 'db_name' => 'db', 'username' => 'hyphen-user_name', "password" => 'p-s_s' }
+ auth_hash = { :db_name => 'db', :username => 'hyphen-user_name', :password => 'p-s_s' }
assert_equal auth_hash, @client.auths[0]
end
@@ -211,7 +211,7 @@ class ClientTest < Test::Unit::TestCase
ENV['MONGODB_URI'] = "mongodb://hyphen-user_name:p-s_s@localhost:27017/db?connect=false"
@client = MongoClient.new
assert_equal ['localhost', 27017], @client.host_port
- auth_hash = { 'db_name' => 'db', 'username' => 'hyphen-user_name', "password" => 'p-s_s' }
+ auth_hash = { :db_name => 'db', :username => 'hyphen-user_name', :password => 'p-s_s' }
assert_equal auth_hash, @client.auths[0]
end
@@ -122,7 +122,7 @@ class ConnectionTest < Test::Unit::TestCase
should "parse a uri with a hyphen & underscore in the username or password" do
@connection = Mongo::Connection.from_uri("mongodb://hyphen-user_name:p-s_s@localhost:27017/db", :connect => false)
assert_equal ['localhost', 27017], @connection.host_port
- auth_hash = { 'db_name' => 'db', 'username' => 'hyphen-user_name', "password" => 'p-s_s' }
+ auth_hash = { :db_name => 'db', :username => 'hyphen-user_name', :password => 'p-s_s' }
assert_equal auth_hash, @connection.auths[0]
end
@@ -205,7 +205,7 @@ class ConnectionTest < Test::Unit::TestCase
ENV['MONGODB_URI'] = "mongodb://hyphen-user_name:p-s_s@localhost:27017/db?connect=false"
@connection = Mongo::Connection.new
assert_equal ['localhost', 27017], @connection.host_port
- auth_hash = { 'db_name' => 'db', 'username' => 'hyphen-user_name', "password" => 'p-s_s' }
+ auth_hash = { :db_name => 'db', :username => 'hyphen-user_name', :password => 'p-s_s' }
assert_equal auth_hash, @connection.auths[0]
end

0 comments on commit 6428bf6

Please sign in to comment.