mongo 2.4.3 → 2.5.0.beta
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +3 -2
- data.tar.gz.sig +0 -0
- data/lib/mongo.rb +3 -2
- data/lib/mongo/auth/cr.rb +6 -4
- data/lib/mongo/auth/cr/conversation.rb +33 -17
- data/lib/mongo/auth/ldap.rb +4 -2
- data/lib/mongo/auth/ldap/conversation.rb +19 -9
- data/lib/mongo/auth/scram.rb +7 -4
- data/lib/mongo/auth/scram/conversation.rb +62 -24
- data/lib/mongo/auth/user.rb +10 -0
- data/lib/mongo/auth/user/view.rb +44 -22
- data/lib/mongo/auth/x509.rb +4 -2
- data/lib/mongo/auth/x509/conversation.rb +19 -9
- data/lib/mongo/bulk_write.rb +33 -27
- data/lib/mongo/bulk_write/combineable.rb +5 -0
- data/lib/mongo/bulk_write/transformable.rb +2 -0
- data/lib/mongo/bulk_write/validatable.rb +4 -0
- data/lib/mongo/client.rb +123 -12
- data/lib/mongo/cluster.rb +52 -11
- data/lib/mongo/cluster/app_metadata.rb +8 -2
- data/lib/mongo/cluster/cursor_reaper.rb +0 -1
- data/lib/mongo/cluster/topology.rb +1 -1
- data/lib/mongo/collection.rb +114 -27
- data/lib/mongo/collection/view.rb +8 -2
- data/lib/mongo/collection/view/aggregation.rb +11 -7
- data/lib/mongo/collection/view/builder/aggregation.rb +5 -1
- data/lib/mongo/collection/view/builder/find_command.rb +5 -3
- data/lib/mongo/collection/view/builder/map_reduce.rb +11 -3
- data/lib/mongo/collection/view/builder/op_query.rb +1 -1
- data/lib/mongo/collection/view/change_stream.rb +160 -0
- data/lib/mongo/collection/view/change_stream/retryable.rb +57 -0
- data/lib/mongo/collection/view/iterable.rb +11 -10
- data/lib/mongo/collection/view/map_reduce.rb +22 -18
- data/lib/mongo/collection/view/readable.rb +51 -37
- data/lib/mongo/collection/view/writable.rb +72 -40
- data/lib/mongo/cursor.rb +25 -4
- data/lib/mongo/cursor/builder/get_more_command.rb +4 -2
- data/lib/mongo/database.rb +22 -11
- data/lib/mongo/database/view.rb +16 -12
- data/lib/mongo/error.rb +5 -0
- data/lib/mongo/error/invalid_session.rb +36 -0
- data/lib/mongo/error/missing_resume_token.rb +39 -0
- data/lib/mongo/error/operation_failure.rb +17 -0
- data/lib/mongo/error/parser.rb +3 -2
- data/lib/mongo/error/unknown_payload_type.rb +41 -0
- data/lib/mongo/error/unsupported_array_filters.rb +51 -0
- data/lib/mongo/error/unsupported_message_type.rb +23 -0
- data/lib/mongo/grid/fs_bucket.rb +5 -4
- data/lib/mongo/grid/stream/read.rb +3 -2
- data/lib/mongo/grid/stream/write.rb +2 -2
- data/lib/mongo/index/view.rb +35 -25
- data/lib/mongo/monitoring/event/secure.rb +14 -0
- data/lib/mongo/operation.rb +16 -0
- data/lib/mongo/operation/commands.rb +1 -0
- data/lib/mongo/operation/commands/aggregate.rb +9 -5
- data/lib/mongo/operation/commands/aggregate/result.rb +1 -1
- data/lib/mongo/operation/commands/collections_info.rb +6 -6
- data/lib/mongo/operation/commands/command.rb +2 -1
- data/lib/mongo/operation/commands/create.rb +6 -2
- data/lib/mongo/operation/commands/drop.rb +6 -2
- data/lib/mongo/operation/commands/drop_database.rb +6 -2
- data/lib/mongo/operation/commands/explain.rb +27 -0
- data/lib/mongo/operation/commands/explain/result.rb +52 -0
- data/lib/mongo/operation/commands/indexes.rb +1 -1
- data/lib/mongo/operation/commands/list_collections.rb +1 -1
- data/lib/mongo/operation/commands/list_collections/result.rb +1 -1
- data/lib/mongo/operation/commands/list_indexes.rb +1 -1
- data/lib/mongo/operation/commands/list_indexes/result.rb +1 -1
- data/lib/mongo/operation/commands/map_reduce.rb +8 -4
- data/lib/mongo/operation/commands/map_reduce/result.rb +13 -1
- data/lib/mongo/operation/commands/user_query.rb +1 -1
- data/lib/mongo/operation/commands/users_info.rb +6 -2
- data/lib/mongo/operation/executable.rb +4 -1
- data/lib/mongo/operation/read_preference.rb +10 -5
- data/lib/mongo/operation/result.rb +26 -2
- data/lib/mongo/operation/specifiable.rb +13 -1
- data/lib/mongo/operation/uses_command_op_msg.rb +47 -0
- data/lib/mongo/operation/write/bulk/bulkable.rb +4 -1
- data/lib/mongo/operation/write/bulk/insert/result.rb +4 -4
- data/lib/mongo/operation/write/command/create_index.rb +6 -1
- data/lib/mongo/operation/write/command/delete.rb +28 -4
- data/lib/mongo/operation/write/command/drop_index.rb +6 -1
- data/lib/mongo/operation/write/command/insert.rb +22 -18
- data/lib/mongo/operation/write/command/update.rb +24 -9
- data/lib/mongo/operation/write/command/writable.rb +14 -1
- data/lib/mongo/operation/write/insert.rb +4 -1
- data/lib/mongo/operation/write/insert/result.rb +2 -2
- data/lib/mongo/operation/write/update.rb +7 -1
- data/lib/mongo/operation/write/write_command_enabled.rb +20 -3
- data/lib/mongo/protocol.rb +3 -0
- data/lib/mongo/protocol/bit_vector.rb +2 -2
- data/lib/mongo/protocol/compressed.rb +135 -0
- data/lib/mongo/protocol/delete.rb +8 -6
- data/lib/mongo/protocol/get_more.rb +8 -6
- data/lib/mongo/protocol/insert.rb +8 -6
- data/lib/mongo/protocol/kill_cursors.rb +8 -6
- data/lib/mongo/protocol/message.rb +31 -3
- data/lib/mongo/protocol/msg.rb +172 -0
- data/lib/mongo/protocol/query.rb +26 -6
- data/lib/mongo/protocol/registry.rb +76 -0
- data/lib/mongo/protocol/reply.rb +10 -5
- data/lib/mongo/protocol/serializers.rb +224 -0
- data/lib/mongo/protocol/update.rb +8 -6
- data/lib/mongo/retryable.rb +4 -2
- data/lib/mongo/server.rb +6 -3
- data/lib/mongo/server/connectable.rb +1 -1
- data/lib/mongo/server/connection.rb +30 -8
- data/lib/mongo/server/description.rb +25 -1
- data/lib/mongo/server/description/features.rb +4 -1
- data/lib/mongo/server/monitor.rb +5 -0
- data/lib/mongo/server/monitor/connection.rb +50 -2
- data/lib/mongo/server_selector/nearest.rb +10 -4
- data/lib/mongo/server_selector/primary.rb +20 -0
- data/lib/mongo/server_selector/primary_preferred.rb +10 -4
- data/lib/mongo/server_selector/secondary.rb +10 -4
- data/lib/mongo/server_selector/secondary_preferred.rb +24 -4
- data/lib/mongo/session.rb +180 -0
- data/lib/mongo/session/server_session.rb +73 -0
- data/lib/mongo/session/session_pool.rb +161 -0
- data/lib/mongo/uri.rb +11 -0
- data/lib/mongo/version.rb +1 -1
- data/mongo.gemspec +2 -1
- data/spec/mongo/auth/cr_spec.rb +12 -0
- data/spec/mongo/auth/ldap_spec.rb +2 -0
- data/spec/mongo/auth/scram/conversation_spec.rb +6 -6
- data/spec/mongo/auth/scram_spec.rb +25 -1
- data/spec/mongo/auth/user/view_spec.rb +268 -76
- data/spec/mongo/auth/x509_spec.rb +2 -0
- data/spec/mongo/bulk_write_spec.rb +435 -5
- data/spec/mongo/client_spec.rb +356 -39
- data/spec/mongo/cluster/app_metadata_spec.rb +2 -2
- data/spec/mongo/cluster_spec.rb +176 -0
- data/spec/mongo/collection/view/aggregation_spec.rb +33 -12
- data/spec/mongo/collection/view/builder/find_command_spec.rb +46 -6
- data/spec/mongo/collection/view/change_stream_spec.rb +814 -0
- data/spec/mongo/collection/view/map_reduce_spec.rb +94 -17
- data/spec/mongo/collection/view/readable_spec.rb +3 -12
- data/spec/mongo/collection_spec.rb +1048 -42
- data/spec/mongo/cursor/builder/get_more_command_spec.rb +19 -0
- data/spec/mongo/cursor_spec.rb +2 -2
- data/spec/mongo/database_spec.rb +50 -1
- data/spec/mongo/grid/fs_bucket_spec.rb +225 -137
- data/spec/mongo/grid/stream/read_spec.rb +2 -2
- data/spec/mongo/index/view_spec.rb +146 -8
- data/spec/mongo/monitoring/event/secure_spec.rb +42 -0
- data/spec/mongo/operation/read/query_spec.rb +2 -1
- data/spec/mongo/operation/specifiable_spec.rb +2 -2
- data/spec/mongo/operation/write/command/delete_spec.rb +96 -13
- data/spec/mongo/operation/write/command/insert_spec.rb +111 -12
- data/spec/mongo/operation/write/command/update_spec.rb +93 -10
- data/spec/mongo/operation/write/delete_spec.rb +1 -1
- data/spec/mongo/operation/write/insert_spec.rb +1 -1
- data/spec/mongo/operation/write/update_spec.rb +1 -1
- data/spec/mongo/protocol/compressed_spec.rb +66 -0
- data/spec/mongo/protocol/delete_spec.rb +14 -0
- data/spec/mongo/protocol/get_more_spec.rb +14 -0
- data/spec/mongo/protocol/insert_spec.rb +14 -0
- data/spec/mongo/protocol/kill_cursors_spec.rb +14 -0
- data/spec/mongo/protocol/msg_spec.rb +499 -0
- data/spec/mongo/protocol/query_spec.rb +45 -0
- data/spec/mongo/protocol/registry_spec.rb +31 -0
- data/spec/mongo/protocol/reply_spec.rb +14 -0
- data/spec/mongo/protocol/update_spec.rb +14 -0
- data/spec/mongo/retryable_spec.rb +6 -2
- data/spec/mongo/sdam_spec.rb +4 -0
- data/spec/mongo/server/connection_spec.rb +4 -2
- data/spec/mongo/server/description_spec.rb +28 -1
- data/spec/mongo/session/server_session_spec.rb +16 -0
- data/spec/mongo/session/session_pool_spec.rb +194 -0
- data/spec/mongo/uri_spec.rb +31 -2
- data/spec/spec_helper.rb +104 -0
- data/spec/support/authorization.rb +6 -1
- data/spec/support/crud.rb +3 -1
- data/spec/support/crud/write.rb +6 -1
- data/spec/support/crud_tests/write/findOneAndUpdate-arrayFilters.yml +69 -0
- data/spec/support/crud_tests/write/updateMany-arrayFilters.yml +63 -0
- data/spec/support/crud_tests/write/updateOne-arrayFilters.yml +109 -0
- data/spec/support/sdam/rs/discover_arbiters.yml +1 -1
- data/spec/support/sdam/rs/discover_passives.yml +2 -2
- data/spec/support/sdam/rs/discover_primary.yml +1 -1
- data/spec/support/sdam/rs/discover_secondary.yml +1 -1
- data/spec/support/sdam/rs/discovery.yml +4 -4
- data/spec/support/sdam/rs/equal_electionids.yml +1 -0
- data/spec/support/sdam/rs/ghost_discovered.yml +1 -1
- data/spec/support/sdam/rs/hosts_differ_from_seeds.yml +1 -1
- data/spec/support/sdam/rs/ls_timeout.yml +88 -0
- data/spec/support/sdam/rs/member_reconfig.yml +2 -2
- data/spec/support/sdam/rs/member_standalone.yml +2 -2
- data/spec/support/sdam/rs/new_primary.yml +2 -2
- data/spec/support/sdam/rs/new_primary_new_electionid.yml +3 -0
- data/spec/support/sdam/rs/new_primary_new_setversion.yml +3 -0
- data/spec/support/sdam/rs/new_primary_wrong_set_name.yml +2 -2
- data/spec/support/sdam/rs/non_rs_member.yml +1 -1
- data/spec/support/sdam/rs/normalize_case.yml +1 -1
- data/spec/support/sdam/rs/null_election_id.yml +4 -0
- data/spec/support/sdam/rs/primary_becomes_standalone.yml +2 -2
- data/spec/support/sdam/rs/primary_changes_set_name.yml +2 -2
- data/spec/support/sdam/rs/primary_disconnect.yml +2 -2
- data/spec/support/sdam/rs/primary_disconnect_electionid.yml +5 -0
- data/spec/support/sdam/rs/primary_disconnect_setversion.yml +5 -0
- data/spec/support/sdam/rs/primary_hint_from_secondary_with_mismatched_me.yml +58 -0
- data/spec/support/sdam/rs/primary_reports_new_member.yml +4 -4
- data/spec/support/sdam/rs/primary_to_no_primary_mismatched_me.yml +2 -2
- data/spec/support/sdam/rs/primary_wrong_set_name.yml +1 -1
- data/spec/support/sdam/rs/response_from_removed.yml +2 -2
- data/spec/support/sdam/rs/rsother_discovered.yml +1 -1
- data/spec/support/sdam/rs/sec_not_auth.yml +1 -1
- data/spec/support/sdam/rs/secondary_wrong_set_name.yml +1 -1
- data/spec/support/sdam/rs/secondary_wrong_set_name_with_primary.yml +2 -2
- data/spec/support/sdam/rs/setversion_without_electionid.yml +2 -0
- data/spec/support/sdam/rs/stepdown_change_set_name.yml +2 -2
- data/spec/support/sdam/rs/unexpected_mongos.yml +1 -1
- data/spec/support/sdam/rs/use_setversion_without_electionid.yml +3 -0
- data/spec/support/sdam/rs/wrong_set_name.yml +1 -1
- data/spec/support/sdam/sharded/ls_timeout_mongos.yml +97 -0
- data/spec/support/sdam/sharded/mongos_disconnect.yml +3 -3
- data/spec/support/sdam/sharded/multiple_mongoses.yml +1 -1
- data/spec/support/sdam/sharded/non_mongos_removed.yml +1 -1
- data/spec/support/sdam/sharded/normalize_uri_case.yml +1 -1
- data/spec/support/sdam/single/direct_connection_external_ip.yml +1 -1
- data/spec/support/sdam/single/direct_connection_mongos.yml +1 -1
- data/spec/support/sdam/single/direct_connection_rsarbiter.yml +1 -1
- data/spec/support/sdam/single/direct_connection_rsprimary.yml +1 -1
- data/spec/support/sdam/single/direct_connection_rssecondary.yml +1 -1
- data/spec/support/sdam/single/direct_connection_slave.yml +1 -1
- data/spec/support/sdam/single/direct_connection_standalone.yml +1 -1
- data/spec/support/sdam/single/ls_timeout_standalone.yml +35 -0
- data/spec/support/sdam/single/not_ok_response.yml +1 -1
- data/spec/support/sdam/single/standalone_removed.yml +1 -1
- data/spec/support/sdam/single/unavailable_seed.yml +1 -1
- data/spec/support/server_discovery_and_monitoring.rb +4 -0
- data/spec/support/shared/session.rb +236 -0
- metadata +53 -15
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c4e52038faa9ef6ff0419d1c5855800d4ce07066
|
4
|
+
data.tar.gz: a7b342d735714530107b7b513ee91c8d071472ba
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eb58160cfaa1676ee31df0fcd375e2cad12953b46ba063b8a5f46c6e9dcbdcbf750a5c299e8b4222b3af57c9a0902c9f64fe4dfc33dc37df689730cf19f88e27
|
7
|
+
data.tar.gz: 97cc226f8bc3fc8fd7bda2d1be3b29be4a8d03f1e444b572dc74008e1276f733a3408851132cef3241df936c4e1613e4bce2ef2b3597e2fb55031ccfed49fb4c
|
checksums.yaml.gz.sig
CHANGED
@@ -1,2 +1,3 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
�Ca�? @�7��G�I�ͥ'
|
2
|
+
m�OF/�
|
3
|
+
Z�/(詏�v-�v���d�A�e.R%-Ş�O@Y̽͛�W㞧��ȁC�&�E��>qa�*!~7�>�?[�P�k�H��͍���N�:Yg�S�3ͭ�yf�!���0�|�sd�jٯ�z��"�'J7e��V�i¥~V���+J�<AOs�o���m�!�b���([�|k'���� �#jݱr���@�C<MTAv kA旆Ԧ^�f�ӛ��Ñ�� wX���dx
|
data.tar.gz.sig
CHANGED
Binary file
|
data/lib/mongo.rb
CHANGED
@@ -26,17 +26,18 @@ require 'mongo/error'
|
|
26
26
|
require 'mongo/event'
|
27
27
|
require 'mongo/address'
|
28
28
|
require 'mongo/auth'
|
29
|
+
require 'mongo/protocol'
|
29
30
|
require 'mongo/client'
|
30
31
|
require 'mongo/cluster'
|
31
|
-
require 'mongo/collection'
|
32
32
|
require 'mongo/cursor'
|
33
|
+
require 'mongo/collection'
|
33
34
|
require 'mongo/database'
|
34
35
|
require 'mongo/dbref'
|
35
36
|
require 'mongo/grid'
|
36
37
|
require 'mongo/index'
|
37
|
-
require 'mongo/protocol'
|
38
38
|
require 'mongo/server'
|
39
39
|
require 'mongo/server_selector'
|
40
|
+
require 'mongo/session'
|
40
41
|
require 'mongo/socket'
|
41
42
|
require 'mongo/uri'
|
42
43
|
require 'mongo/version'
|
data/lib/mongo/auth/cr.rb
CHANGED
@@ -49,14 +49,16 @@ module Mongo
|
|
49
49
|
#
|
50
50
|
# @param [ Mongo::Connection ] connection The connection to log into.
|
51
51
|
#
|
52
|
-
# @return [ Protocol::
|
52
|
+
# @return [ Protocol::Message ] The authentication response.
|
53
53
|
#
|
54
54
|
# @since 2.0.0
|
55
55
|
def login(connection)
|
56
56
|
conversation = Conversation.new(user)
|
57
|
-
reply = connection.dispatch([ conversation.start ])
|
58
|
-
|
59
|
-
conversation.
|
57
|
+
reply = connection.dispatch([ conversation.start(connection) ])
|
58
|
+
connection.update_cluster_time(Operation::Result.new(reply))
|
59
|
+
reply = connection.dispatch([ conversation.continue(reply, connection) ])
|
60
|
+
connection.update_cluster_time(Operation::Result.new(reply))
|
61
|
+
conversation.finalize(reply, connection)
|
60
62
|
end
|
61
63
|
end
|
62
64
|
end
|
@@ -27,7 +27,7 @@ module Mongo
|
|
27
27
|
# @since 2.0.0
|
28
28
|
LOGIN = { authenticate: 1 }.freeze
|
29
29
|
|
30
|
-
# @return [ Protocol::
|
30
|
+
# @return [ Protocol::Message ] reply The current reply in the
|
31
31
|
# conversation.
|
32
32
|
attr_reader :reply
|
33
33
|
|
@@ -47,20 +47,29 @@ module Mongo
|
|
47
47
|
# @example Continue the conversation.
|
48
48
|
# conversation.continue(reply)
|
49
49
|
#
|
50
|
-
# @param [ Protocol::
|
50
|
+
# @param [ Protocol::Message ] reply The reply of the previous
|
51
51
|
# message.
|
52
|
+
# @param [ Mongo::Server::Connection ] connection The connection being authenticated.
|
52
53
|
#
|
53
54
|
# @return [ Protocol::Query ] The next message to send.
|
54
55
|
#
|
55
56
|
# @since 2.0.0
|
56
|
-
def continue(reply)
|
57
|
+
def continue(reply, connection = nil)
|
57
58
|
validate!(reply)
|
58
|
-
|
59
|
-
user.
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
59
|
+
if connection && connection.features.op_msg_enabled?
|
60
|
+
selector = LOGIN.merge(user: user.name, nonce: nonce, key: user.auth_key(nonce))
|
61
|
+
selector[Protocol::Msg::DATABASE_IDENTIFIER] = user.auth_source
|
62
|
+
cluster_time = connection.mongos? && connection.cluster_time
|
63
|
+
selector[Operation::CLUSTER_TIME] = cluster_time if cluster_time
|
64
|
+
Protocol::Msg.new([:none], {}, selector)
|
65
|
+
else
|
66
|
+
Protocol::Query.new(
|
67
|
+
user.auth_source,
|
68
|
+
Database::COMMAND,
|
69
|
+
LOGIN.merge(user: user.name, nonce: nonce, key: user.auth_key(nonce)),
|
70
|
+
limit: -1
|
71
|
+
)
|
72
|
+
end
|
64
73
|
end
|
65
74
|
|
66
75
|
# Finalize the CR conversation. This is meant to be iterated until
|
@@ -69,13 +78,13 @@ module Mongo
|
|
69
78
|
# @example Finalize the conversation.
|
70
79
|
# conversation.finalize(reply)
|
71
80
|
#
|
72
|
-
# @param [ Protocol::
|
81
|
+
# @param [ Protocol::Message ] reply The reply of the previous
|
73
82
|
# message.
|
74
83
|
#
|
75
84
|
# @return [ Protocol::Query ] The next message to send.
|
76
85
|
#
|
77
86
|
# @since 2.0.0
|
78
|
-
def finalize(reply)
|
87
|
+
def finalize(reply, connection = nil)
|
79
88
|
validate!(reply)
|
80
89
|
end
|
81
90
|
|
@@ -88,12 +97,19 @@ module Mongo
|
|
88
97
|
# @return [ Protocol::Query ] The first CR conversation message.
|
89
98
|
#
|
90
99
|
# @since 2.0.0
|
91
|
-
def start
|
92
|
-
|
93
|
-
user.auth_source
|
94
|
-
|
95
|
-
|
96
|
-
|
100
|
+
def start(connection = nil)
|
101
|
+
if connection && connection.features.op_msg_enabled?
|
102
|
+
selector = Auth::GET_NONCE.merge(Protocol::Msg::DATABASE_IDENTIFIER => user.auth_source)
|
103
|
+
cluster_time = connection.mongos? && connection.cluster_time
|
104
|
+
selector[Operation::CLUSTER_TIME] = cluster_time if cluster_time
|
105
|
+
Protocol::Msg.new([:none], {}, selector)
|
106
|
+
else
|
107
|
+
Protocol::Query.new(
|
108
|
+
user.auth_source,
|
109
|
+
Database::COMMAND,
|
110
|
+
Auth::GET_NONCE,
|
111
|
+
limit: -1)
|
112
|
+
end
|
97
113
|
end
|
98
114
|
|
99
115
|
# Create the new conversation.
|
data/lib/mongo/auth/ldap.rb
CHANGED
@@ -49,12 +49,14 @@ module Mongo
|
|
49
49
|
# @param [ Mongo::Connection ] connection The connection to log into.
|
50
50
|
# on.
|
51
51
|
#
|
52
|
-
# @return [ Protocol::
|
52
|
+
# @return [ Protocol::Message ] The authentication response.
|
53
53
|
#
|
54
54
|
# @since 2.0.0
|
55
55
|
def login(connection)
|
56
56
|
conversation = Conversation.new(user)
|
57
|
-
|
57
|
+
reply = connection.dispatch([ conversation.start(connection) ])
|
58
|
+
connection.update_cluster_time(Operation::Result.new(reply))
|
59
|
+
conversation.finalize(reply)
|
58
60
|
end
|
59
61
|
end
|
60
62
|
end
|
@@ -27,7 +27,7 @@ module Mongo
|
|
27
27
|
# @since 2.0.0
|
28
28
|
LOGIN = { saslStart: 1, autoAuthorize: 1 }.freeze
|
29
29
|
|
30
|
-
# @return [ Protocol::
|
30
|
+
# @return [ Protocol::Message ] reply The current reply in the
|
31
31
|
# conversation.
|
32
32
|
attr_reader :reply
|
33
33
|
|
@@ -40,7 +40,7 @@ module Mongo
|
|
40
40
|
# @example Finalize the conversation.
|
41
41
|
# conversation.finalize(reply)
|
42
42
|
#
|
43
|
-
# @param [ Protocol::
|
43
|
+
# @param [ Protocol::Message ] reply The reply of the previous
|
44
44
|
# message.
|
45
45
|
#
|
46
46
|
# @return [ Protocol::Query ] The next message to send.
|
@@ -56,16 +56,26 @@ module Mongo
|
|
56
56
|
# @example Start the conversation.
|
57
57
|
# conversation.start
|
58
58
|
#
|
59
|
+
# @param [ Mongo::Server::Connection ] connection The connection being authenticated.
|
60
|
+
#
|
59
61
|
# @return [ Protocol::Query ] The first PLAIN conversation message.
|
60
62
|
#
|
61
63
|
# @since 2.0.0
|
62
|
-
def start
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
64
|
+
def start(connection = nil)
|
65
|
+
if connection && connection.features.op_msg_enabled?
|
66
|
+
selector = LOGIN.merge(payload: payload, mechanism: LDAP::MECHANISM)
|
67
|
+
selector[Protocol::Msg::DATABASE_IDENTIFIER] = Auth::EXTERNAL
|
68
|
+
cluster_time = connection.mongos? && connection.cluster_time
|
69
|
+
selector[Operation::CLUSTER_TIME] = cluster_time if cluster_time
|
70
|
+
Protocol::Msg.new([:none], {}, selector)
|
71
|
+
else
|
72
|
+
Protocol::Query.new(
|
73
|
+
Auth::EXTERNAL,
|
74
|
+
Database::COMMAND,
|
75
|
+
LOGIN.merge(payload: payload, mechanism: LDAP::MECHANISM),
|
76
|
+
limit: -1
|
77
|
+
)
|
78
|
+
end
|
69
79
|
end
|
70
80
|
|
71
81
|
# Create the new conversation.
|
data/lib/mongo/auth/scram.rb
CHANGED
@@ -50,15 +50,18 @@ module Mongo
|
|
50
50
|
# @param [ Mongo::Connection ] connection The connection to log into.
|
51
51
|
# on.
|
52
52
|
#
|
53
|
-
# @return [ Protocol::
|
53
|
+
# @return [ Protocol::Message ] The authentication response.
|
54
54
|
#
|
55
55
|
# @since 2.0.0
|
56
56
|
def login(connection)
|
57
57
|
conversation = Conversation.new(user)
|
58
|
-
reply = connection.dispatch([ conversation.start ])
|
59
|
-
|
58
|
+
reply = connection.dispatch([ conversation.start(connection) ])
|
59
|
+
connection.update_cluster_time(Operation::Result.new(reply))
|
60
|
+
reply = connection.dispatch([ conversation.continue(reply, connection) ])
|
61
|
+
connection.update_cluster_time(Operation::Result.new(reply))
|
60
62
|
until reply.documents[0][Conversation::DONE]
|
61
|
-
reply = connection.dispatch([ conversation.finalize(reply) ])
|
63
|
+
reply = connection.dispatch([ conversation.finalize(reply, connection) ])
|
64
|
+
connection.update_cluster_time(Operation::Result.new(reply))
|
62
65
|
end
|
63
66
|
reply
|
64
67
|
end
|
@@ -88,7 +88,7 @@ module Mongo
|
|
88
88
|
# @return [ String ] nonce The initial user nonce.
|
89
89
|
attr_reader :nonce
|
90
90
|
|
91
|
-
# @return [ Protocol::
|
91
|
+
# @return [ Protocol::Message ] reply The current reply in the
|
92
92
|
# conversation.
|
93
93
|
attr_reader :reply
|
94
94
|
|
@@ -102,20 +102,36 @@ module Mongo
|
|
102
102
|
# @example Continue the conversation.
|
103
103
|
# conversation.continue(reply)
|
104
104
|
#
|
105
|
-
# @param [ Protocol::
|
105
|
+
# @param [ Protocol::Message ] reply The reply of the previous
|
106
106
|
# message.
|
107
|
+
# @param [ Mongo::Server::Connection ] connection The connection being authenticated.
|
107
108
|
#
|
108
109
|
# @return [ Protocol::Query ] The next message to send.
|
109
110
|
#
|
110
111
|
# @since 2.0.0
|
111
|
-
def continue(reply)
|
112
|
+
def continue(reply, connection = nil)
|
112
113
|
validate_first_message!(reply)
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
114
|
+
|
115
|
+
# The salted password needs to be calculated now; otherwise, if the
|
116
|
+
# client key is cached from a previous authentication, the salt in the
|
117
|
+
# reply will no longer be available for when the salted password is
|
118
|
+
# needed to calculate the server key.
|
119
|
+
salted_password
|
120
|
+
|
121
|
+
if connection && connection.features.op_msg_enabled?
|
122
|
+
selector = CLIENT_CONTINUE_MESSAGE.merge(payload: client_final_message, conversationId: id)
|
123
|
+
selector[Protocol::Msg::DATABASE_IDENTIFIER] = user.auth_source
|
124
|
+
cluster_time = connection.mongos? && connection.cluster_time
|
125
|
+
selector[Operation::CLUSTER_TIME] = cluster_time if cluster_time
|
126
|
+
Protocol::Msg.new([:none], {}, selector)
|
127
|
+
else
|
128
|
+
Protocol::Query.new(
|
129
|
+
user.auth_source,
|
130
|
+
Database::COMMAND,
|
131
|
+
CLIENT_CONTINUE_MESSAGE.merge(payload: client_final_message, conversationId: id),
|
132
|
+
limit: -1
|
133
|
+
)
|
134
|
+
end
|
119
135
|
end
|
120
136
|
|
121
137
|
# Finalize the SCRAM conversation. This is meant to be iterated until
|
@@ -124,20 +140,29 @@ module Mongo
|
|
124
140
|
# @example Finalize the conversation.
|
125
141
|
# conversation.finalize(reply)
|
126
142
|
#
|
127
|
-
# @param [ Protocol::
|
143
|
+
# @param [ Protocol::Message ] reply The reply of the previous
|
128
144
|
# message.
|
145
|
+
# @param [ Mongo::Server::Connection ] connection The connection being authenticated.
|
129
146
|
#
|
130
147
|
# @return [ Protocol::Query ] The next message to send.
|
131
148
|
#
|
132
149
|
# @since 2.0.0
|
133
|
-
def finalize(reply)
|
150
|
+
def finalize(reply, connection = nil)
|
134
151
|
validate_final_message!(reply)
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
152
|
+
if connection && connection.features.op_msg_enabled?
|
153
|
+
selector = CLIENT_CONTINUE_MESSAGE.merge(payload: client_empty_message, conversationId: id)
|
154
|
+
selector[Protocol::Msg::DATABASE_IDENTIFIER] = user.auth_source
|
155
|
+
cluster_time = connection.mongos? && connection.cluster_time
|
156
|
+
selector[Operation::CLUSTER_TIME] = cluster_time if cluster_time
|
157
|
+
Protocol::Msg.new([:none], {}, selector)
|
158
|
+
else
|
159
|
+
Protocol::Query.new(
|
160
|
+
user.auth_source,
|
161
|
+
Database::COMMAND,
|
162
|
+
CLIENT_CONTINUE_MESSAGE.merge(payload: client_empty_message, conversationId: id),
|
163
|
+
limit: -1
|
164
|
+
)
|
165
|
+
end
|
141
166
|
end
|
142
167
|
|
143
168
|
# Start the SCRAM conversation. This returns the first message that
|
@@ -146,16 +171,26 @@ module Mongo
|
|
146
171
|
# @example Start the conversation.
|
147
172
|
# conversation.start
|
148
173
|
#
|
174
|
+
# @param [ Mongo::Server::Connection ] connection The connection being authenticated.
|
175
|
+
#
|
149
176
|
# @return [ Protocol::Query ] The first SCRAM conversation message.
|
150
177
|
#
|
151
178
|
# @since 2.0.0
|
152
|
-
def start
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
179
|
+
def start(connection = nil)
|
180
|
+
if connection && connection.features.op_msg_enabled?
|
181
|
+
selector = CLIENT_FIRST_MESSAGE.merge(payload: client_first_message, mechanism: SCRAM::MECHANISM)
|
182
|
+
selector[Protocol::Msg::DATABASE_IDENTIFIER] = user.auth_source
|
183
|
+
cluster_time = connection.mongos? && connection.cluster_time
|
184
|
+
selector[Operation::CLUSTER_TIME] = cluster_time if cluster_time
|
185
|
+
Protocol::Msg.new([:none], {}, selector)
|
186
|
+
else
|
187
|
+
Protocol::Query.new(
|
188
|
+
user.auth_source,
|
189
|
+
Database::COMMAND,
|
190
|
+
CLIENT_FIRST_MESSAGE.merge(payload: client_first_message, mechanism: SCRAM::MECHANISM),
|
191
|
+
limit: -1
|
192
|
+
)
|
193
|
+
end
|
159
194
|
end
|
160
195
|
|
161
196
|
# Get the id of the conversation.
|
@@ -181,6 +216,7 @@ module Mongo
|
|
181
216
|
def initialize(user)
|
182
217
|
@user = user
|
183
218
|
@nonce = SecureRandom.base64
|
219
|
+
@client_key = user.send(:client_key)
|
184
220
|
end
|
185
221
|
|
186
222
|
private
|
@@ -247,6 +283,8 @@ module Mongo
|
|
247
283
|
# @since 2.0.0
|
248
284
|
def client_key
|
249
285
|
@client_key ||= hmac(salted_password, CLIENT_KEY)
|
286
|
+
user.instance_variable_set(:@client_key, @client_key) unless user.send(:client_key)
|
287
|
+
@client_key
|
250
288
|
end
|
251
289
|
|
252
290
|
# Client proof algorithm implementation.
|
data/lib/mongo/auth/user.rb
CHANGED
@@ -131,6 +131,8 @@ module Mongo
|
|
131
131
|
# @option options [ String ] :password The user's password.
|
132
132
|
# @option options [ Symbol ] :auth_mech The authorization mechanism.
|
133
133
|
# @option options [ Array<String>, Array<Hash> ] roles The user roles.
|
134
|
+
# @option options [ String ] :client_key The user's client key cached from a previous
|
135
|
+
# authentication on the same connection.
|
134
136
|
#
|
135
137
|
# @since 2.0.0
|
136
138
|
def initialize(options)
|
@@ -141,6 +143,7 @@ module Mongo
|
|
141
143
|
@mechanism = options[:auth_mech] || :mongodb_cr
|
142
144
|
@auth_mech_properties = options[:auth_mech_properties] || {}
|
143
145
|
@roles = options[:roles] || []
|
146
|
+
@client_key = options[:client_key]
|
144
147
|
end
|
145
148
|
|
146
149
|
# Get the specification for the user, used in creation.
|
@@ -154,6 +157,13 @@ module Mongo
|
|
154
157
|
def spec
|
155
158
|
{ pwd: hashed_password, roles: roles }
|
156
159
|
end
|
160
|
+
|
161
|
+
private
|
162
|
+
|
163
|
+
# The client key for the user.
|
164
|
+
#
|
165
|
+
# @return [ String ] The client key for the user.
|
166
|
+
attr_reader :client_key
|
157
167
|
end
|
158
168
|
end
|
159
169
|
end
|
data/lib/mongo/auth/user/view.rb
CHANGED
@@ -25,7 +25,7 @@ module Mongo
|
|
25
25
|
# @return [ Database ] database The view's database.
|
26
26
|
attr_reader :database
|
27
27
|
|
28
|
-
def_delegators :database, :cluster, :read_preference
|
28
|
+
def_delegators :database, :cluster, :read_preference, :client
|
29
29
|
def_delegators :cluster, :next_primary
|
30
30
|
|
31
31
|
# Create a new user in the database.
|
@@ -36,15 +36,20 @@ module Mongo
|
|
36
36
|
# @param [ Auth::User, String ] user_or_name The user object or user name.
|
37
37
|
# @param [ Hash ] options The user options.
|
38
38
|
#
|
39
|
+
# @option options [ Session ] :session The session to use for the operation.
|
40
|
+
#
|
39
41
|
# @return [ Result ] The command response.
|
40
42
|
#
|
41
43
|
# @since 2.0.0
|
42
44
|
def create(user_or_name, options = {})
|
43
45
|
user = generate(user_or_name, options)
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
46
|
+
client.send(:with_session, options) do |session|
|
47
|
+
Operation::Write::CreateUser.new(
|
48
|
+
user: user,
|
49
|
+
db_name: database.name,
|
50
|
+
session: session
|
51
|
+
).execute(next_primary)
|
52
|
+
end
|
48
53
|
end
|
49
54
|
|
50
55
|
# Initialize the new user view.
|
@@ -65,15 +70,21 @@ module Mongo
|
|
65
70
|
# view.remove('user')
|
66
71
|
#
|
67
72
|
# @param [ String ] name The user name.
|
73
|
+
# @param [ Hash ] options The options for the remove operation.
|
74
|
+
#
|
75
|
+
# @option options [ Session ] :session The session to use for the operation.
|
68
76
|
#
|
69
77
|
# @return [ Result ] The command response.
|
70
78
|
#
|
71
79
|
# @since 2.0.0
|
72
|
-
def remove(name)
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
80
|
+
def remove(name, options = {})
|
81
|
+
client.send(:with_session, options) do |session|
|
82
|
+
Operation::Write::RemoveUser.new(
|
83
|
+
user_name: name,
|
84
|
+
db_name: database.name,
|
85
|
+
session: session
|
86
|
+
).execute(next_primary)
|
87
|
+
end
|
77
88
|
end
|
78
89
|
|
79
90
|
# Update a user in the database.
|
@@ -84,15 +95,20 @@ module Mongo
|
|
84
95
|
# @param [ Auth::User, String ] user_or_name The user object or user name.
|
85
96
|
# @param [ Hash ] options The user options.
|
86
97
|
#
|
98
|
+
# @option options [ Session ] :session The session to use for the operation.
|
99
|
+
#
|
87
100
|
# @return [ Result ] The response.
|
88
101
|
#
|
89
102
|
# @since 2.0.0
|
90
103
|
def update(user_or_name, options = {})
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
104
|
+
client.send(:with_session, options) do |session|
|
105
|
+
user = generate(user_or_name, options)
|
106
|
+
Operation::Write::UpdateUser.new(
|
107
|
+
user: user,
|
108
|
+
db_name: database.name,
|
109
|
+
session: session
|
110
|
+
).execute(next_primary)
|
111
|
+
end
|
96
112
|
end
|
97
113
|
|
98
114
|
# Get info for a particular user in the database.
|
@@ -101,21 +117,27 @@ module Mongo
|
|
101
117
|
# view.info('emily')
|
102
118
|
#
|
103
119
|
# @param [ String ] name The user name.
|
120
|
+
# @param [ Hash ] options The options for the info operation.
|
121
|
+
#
|
122
|
+
# @option options [ Session ] :session The session to use for the operation.
|
104
123
|
#
|
105
124
|
# @return [ Hash ] A document containing information on a particular user.
|
106
125
|
#
|
107
126
|
# @since 2.1.0
|
108
|
-
def info(name)
|
109
|
-
user_query(name).documents
|
127
|
+
def info(name, options = {})
|
128
|
+
user_query(name, options).documents
|
110
129
|
end
|
111
130
|
|
112
131
|
private
|
113
132
|
|
114
|
-
def user_query(name)
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
133
|
+
def user_query(name, options = {})
|
134
|
+
client.send(:with_session, options) do |session|
|
135
|
+
Operation::Commands::UserQuery.new(
|
136
|
+
user_name: name,
|
137
|
+
db_name: database.name,
|
138
|
+
session: session
|
139
|
+
).execute(next_primary)
|
140
|
+
end
|
119
141
|
end
|
120
142
|
|
121
143
|
def generate(user, options)
|