class Mongo::Auth::CR::Conversation

Defines behaviour around a single MONGODB-CR conversation between the client and server.

@since 2.0.0

Constants

LOGIN

The login message base.

@since 2.0.0

Attributes

database[R]

@return [ String ] database The database to authenticate against.

nonce[R]

@return [ String ] nonce The initial auth nonce.

reply[R]

@return [ Protocol::Message ] reply The current reply in the

conversation.
user[R]

@return [ User ] user The user for the conversation.

Public Class Methods

new(user) click to toggle source

Create the new conversation.

@example Create the new conversation.

Conversation.new(user, "admin")

@param [ Auth::User ] user The user to converse about.

@since 2.0.0

# File lib/mongo/auth/cr/conversation.rb, line 123
def initialize(user)
  @user = user
end

Public Instance Methods

continue(reply, connection = nil) click to toggle source

Continue the CR conversation. This sends the client final message to the server after setting the reply from the previous server communication.

@example Continue the conversation.

conversation.continue(reply)

@param [ Protocol::Message ] reply The reply of the previous

message.

@param [ Mongo::Server::Connection ] connection The connection being authenticated.

@return [ Protocol::Query ] The next message to send.

@since 2.0.0

# File lib/mongo/auth/cr/conversation.rb, line 57
def continue(reply, connection = nil)
  validate!(reply)
  if connection && connection.features.op_msg_enabled?
    selector = LOGIN.merge(user: user.name, nonce: nonce, key: user.auth_key(nonce))
    selector[Protocol::Msg::DATABASE_IDENTIFIER] = user.auth_source
    cluster_time = connection.mongos? && connection.cluster_time
    selector[Operation::CLUSTER_TIME] = cluster_time if cluster_time
    Protocol::Msg.new([:none], {}, selector)
  else
    Protocol::Query.new(
      user.auth_source,
      Database::COMMAND,
      LOGIN.merge(user: user.name, nonce: nonce, key: user.auth_key(nonce)),
      limit: -1
    )
  end
end
finalize(reply, connection = nil) click to toggle source

Finalize the CR conversation. This is meant to be iterated until the provided reply indicates the conversation is finished.

@example Finalize the conversation.

conversation.finalize(reply)

@param [ Protocol::Message ] reply The reply of the previous

message.

@return [ Protocol::Query ] The next message to send.

@since 2.0.0

# File lib/mongo/auth/cr/conversation.rb, line 87
def finalize(reply, connection = nil)
  validate!(reply)
end
start(connection = nil) click to toggle source

Start the CR conversation. This returns the first message that needs to be send to the server.

@example Start the conversation.

conversation.start

@return [ Protocol::Query ] The first CR conversation message.

@since 2.0.0

# File lib/mongo/auth/cr/conversation.rb, line 100
def start(connection = nil)
  if connection && connection.features.op_msg_enabled?
    selector = Auth::GET_NONCE.merge(Protocol::Msg::DATABASE_IDENTIFIER => user.auth_source)
    cluster_time = connection.mongos? && connection.cluster_time
    selector[Operation::CLUSTER_TIME] = cluster_time if cluster_time
    Protocol::Msg.new([:none], {}, selector)
  else
    Protocol::Query.new(
      user.auth_source,
      Database::COMMAND,
      Auth::GET_NONCE,
      limit: -1)
  end
end

Private Instance Methods

validate!(reply) click to toggle source
# File lib/mongo/auth/cr/conversation.rb, line 129
def validate!(reply)
  raise Unauthorized.new(user) if reply.documents[0][Operation::Result::OK] != 1
  @nonce = reply.documents[0][Auth::NONCE]
  @reply = reply
end