mongo 2.14.0 → 2.15.0.alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (230) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/README.md +4 -1
  5. data/Rakefile +8 -15
  6. data/lib/mongo.rb +23 -0
  7. data/lib/mongo/auth/aws/conversation.rb +1 -4
  8. data/lib/mongo/auth/base.rb +13 -7
  9. data/lib/mongo/auth/conversation_base.rb +32 -0
  10. data/lib/mongo/auth/cr/conversation.rb +6 -29
  11. data/lib/mongo/auth/gssapi/conversation.rb +4 -15
  12. data/lib/mongo/auth/ldap/conversation.rb +3 -14
  13. data/lib/mongo/auth/sasl_conversation_base.rb +1 -13
  14. data/lib/mongo/auth/scram_conversation_base.rb +7 -34
  15. data/lib/mongo/auth/user/view.rb +16 -9
  16. data/lib/mongo/auth/x509/conversation.rb +4 -25
  17. data/lib/mongo/background_thread.rb +11 -0
  18. data/lib/mongo/bulk_write.rb +21 -18
  19. data/lib/mongo/client.rb +82 -6
  20. data/lib/mongo/cluster.rb +19 -28
  21. data/lib/mongo/cluster/reapers/cursor_reaper.rb +6 -2
  22. data/lib/mongo/cluster/sdam_flow.rb +14 -0
  23. data/lib/mongo/collection.rb +8 -6
  24. data/lib/mongo/collection/view/aggregation.rb +1 -1
  25. data/lib/mongo/collection/view/change_stream.rb +1 -1
  26. data/lib/mongo/collection/view/iterable.rb +1 -1
  27. data/lib/mongo/collection/view/map_reduce.rb +2 -2
  28. data/lib/mongo/collection/view/readable.rb +42 -20
  29. data/lib/mongo/collection/view/writable.rb +14 -14
  30. data/lib/mongo/cursor.rb +2 -2
  31. data/lib/mongo/database.rb +22 -5
  32. data/lib/mongo/database/view.rb +1 -1
  33. data/lib/mongo/error.rb +9 -1
  34. data/lib/mongo/error/bulk_write_error.rb +17 -3
  35. data/lib/mongo/error/internal_driver_error.rb +22 -0
  36. data/lib/mongo/error/operation_failure.rb +21 -2
  37. data/lib/mongo/error/parser.rb +65 -12
  38. data/lib/mongo/error/server_api_conflict.rb +23 -0
  39. data/lib/mongo/error/server_api_not_supported.rb +24 -0
  40. data/lib/mongo/error/unmet_dependency.rb +21 -0
  41. data/lib/mongo/grid/fs_bucket.rb +37 -37
  42. data/lib/mongo/index/view.rb +21 -11
  43. data/lib/mongo/monitoring.rb +13 -4
  44. data/lib/mongo/monitoring/event/server_heartbeat_failed.rb +27 -16
  45. data/lib/mongo/monitoring/event/server_heartbeat_succeeded.rb +26 -15
  46. data/lib/mongo/operation.rb +2 -2
  47. data/lib/mongo/operation/collections_info.rb +18 -1
  48. data/lib/mongo/operation/collections_info/command.rb +2 -2
  49. data/lib/mongo/operation/context.rb +99 -0
  50. data/lib/mongo/operation/indexes.rb +15 -1
  51. data/lib/mongo/operation/insert/command.rb +2 -2
  52. data/lib/mongo/operation/insert/legacy.rb +2 -2
  53. data/lib/mongo/operation/insert/op_msg.rb +2 -2
  54. data/lib/mongo/operation/list_collections/result.rb +4 -1
  55. data/lib/mongo/operation/result.rb +2 -0
  56. data/lib/mongo/operation/shared/executable.rb +24 -14
  57. data/lib/mongo/operation/shared/executable_no_validate.rb +2 -2
  58. data/lib/mongo/operation/shared/op_msg_or_command.rb +1 -7
  59. data/lib/mongo/operation/shared/op_msg_or_find_command.rb +1 -7
  60. data/lib/mongo/operation/shared/polymorphic_operation.rb +39 -0
  61. data/lib/mongo/operation/shared/response_handling.rb +23 -23
  62. data/lib/mongo/operation/shared/sessions_supported.rb +13 -2
  63. data/lib/mongo/operation/shared/write.rb +8 -18
  64. data/lib/mongo/protocol/compressed.rb +51 -5
  65. data/lib/mongo/protocol/message.rb +20 -2
  66. data/lib/mongo/protocol/msg.rb +36 -11
  67. data/lib/mongo/query_cache.rb +30 -0
  68. data/lib/mongo/retryable.rb +1 -1
  69. data/lib/mongo/server.rb +7 -15
  70. data/lib/mongo/server/app_metadata.rb +52 -18
  71. data/lib/mongo/server/connection.rb +5 -0
  72. data/lib/mongo/server/connection_base.rb +13 -10
  73. data/lib/mongo/server/connection_pool.rb +6 -4
  74. data/lib/mongo/server/description.rb +4 -0
  75. data/lib/mongo/server/description/features.rb +9 -8
  76. data/lib/mongo/server/monitor.rb +20 -1
  77. data/lib/mongo/server/monitor/app_metadata.rb +1 -1
  78. data/lib/mongo/server/monitor/connection.rb +9 -10
  79. data/lib/mongo/server/pending_connection.rb +24 -6
  80. data/lib/mongo/server/push_monitor.rb +11 -1
  81. data/lib/mongo/session.rb +2 -2
  82. data/lib/mongo/session/session_pool.rb +4 -2
  83. data/lib/mongo/socket.rb +29 -4
  84. data/lib/mongo/socket/ssl.rb +8 -0
  85. data/lib/mongo/srv/monitor.rb +0 -11
  86. data/lib/mongo/uri/options_mapper.rb +38 -0
  87. data/lib/mongo/utils.rb +15 -0
  88. data/lib/mongo/version.rb +1 -1
  89. data/spec/README.md +24 -1
  90. data/spec/integration/auth_spec.rb +25 -15
  91. data/spec/integration/bulk_write_error_message_spec.rb +41 -0
  92. data/spec/integration/change_stream_spec.rb +4 -4
  93. data/spec/integration/command_monitoring_spec.rb +2 -2
  94. data/spec/integration/connection_spec.rb +2 -0
  95. data/spec/integration/docs_examples_spec.rb +8 -1
  96. data/spec/integration/fork_reconnect_spec.rb +4 -1
  97. data/spec/integration/ocsp_verifier_spec.rb +13 -7
  98. data/spec/integration/operation_failure_code_spec.rb +1 -1
  99. data/spec/integration/operation_failure_message_spec.rb +90 -0
  100. data/spec/integration/reconnect_spec.rb +1 -1
  101. data/spec/integration/sdam_error_handling_spec.rb +1 -1
  102. data/spec/integration/sdam_events_spec.rb +3 -5
  103. data/spec/integration/snappy_compression_spec.rb +25 -0
  104. data/spec/integration/srv_monitoring_spec.rb +1 -1
  105. data/spec/integration/transactions_examples_spec.rb +6 -0
  106. data/spec/integration/zlib_compression_spec.rb +1 -1
  107. data/spec/integration/zstd_compression_spec.rb +26 -0
  108. data/spec/lite_spec_helper.rb +7 -1
  109. data/spec/mongo/address_spec.rb +15 -11
  110. data/spec/mongo/auth/ldap/conversation_spec.rb +1 -1
  111. data/spec/mongo/auth/ldap_spec.rb +5 -1
  112. data/spec/mongo/auth/scram_negotiation_spec.rb +1 -1
  113. data/spec/mongo/auth/scram_spec.rb +1 -1
  114. data/spec/mongo/auth/x509/conversation_spec.rb +3 -3
  115. data/spec/mongo/client_construction_spec.rb +207 -33
  116. data/spec/mongo/client_spec.rb +17 -0
  117. data/spec/mongo/cluster_spec.rb +3 -18
  118. data/spec/mongo/collection/view/explainable_spec.rb +1 -1
  119. data/spec/mongo/collection/view/readable_spec.rb +33 -19
  120. data/spec/mongo/collection_crud_spec.rb +4357 -0
  121. data/spec/mongo/collection_ddl_spec.rb +534 -0
  122. data/spec/mongo/collection_spec.rb +5 -4859
  123. data/spec/mongo/database_spec.rb +66 -4
  124. data/spec/mongo/error/bulk_write_error_spec.rb +3 -3
  125. data/spec/mongo/error/parser_spec.rb +37 -6
  126. data/spec/mongo/index/view_spec.rb +8 -2
  127. data/spec/mongo/monitoring/event/server_heartbeat_failed_spec.rb +1 -1
  128. data/spec/mongo/monitoring/event/server_heartbeat_succeeded_spec.rb +1 -1
  129. data/spec/mongo/operation/aggregate_spec.rb +2 -1
  130. data/spec/mongo/operation/collections_info_spec.rb +4 -1
  131. data/spec/mongo/operation/command_spec.rb +6 -3
  132. data/spec/mongo/operation/create_index_spec.rb +6 -3
  133. data/spec/mongo/operation/create_user_spec.rb +6 -3
  134. data/spec/mongo/operation/delete/bulk_spec.rb +9 -6
  135. data/spec/mongo/operation/delete_spec.rb +11 -7
  136. data/spec/mongo/operation/drop_index_spec.rb +6 -2
  137. data/spec/mongo/operation/find/legacy_spec.rb +3 -1
  138. data/spec/mongo/operation/get_more_spec.rb +3 -1
  139. data/spec/mongo/operation/indexes_spec.rb +5 -1
  140. data/spec/mongo/operation/insert/bulk_spec.rb +10 -7
  141. data/spec/mongo/operation/insert_spec.rb +15 -12
  142. data/spec/mongo/operation/map_reduce_spec.rb +5 -2
  143. data/spec/mongo/operation/remove_user_spec.rb +6 -3
  144. data/spec/mongo/operation/result_spec.rb +1 -1
  145. data/spec/mongo/operation/update/bulk_spec.rb +9 -6
  146. data/spec/mongo/operation/update_spec.rb +10 -7
  147. data/spec/mongo/operation/update_user_spec.rb +4 -1
  148. data/spec/mongo/protocol/compressed_spec.rb +26 -12
  149. data/spec/mongo/query_cache_middleware_spec.rb +55 -0
  150. data/spec/mongo/retryable_spec.rb +3 -2
  151. data/spec/mongo/server/app_metadata_spec.rb +2 -0
  152. data/spec/mongo/server/connection_pool/populator_spec.rb +3 -1
  153. data/spec/mongo/server/connection_pool_spec.rb +1 -1
  154. data/spec/mongo/server/connection_spec.rb +24 -17
  155. data/spec/mongo/server/monitor/connection_spec.rb +17 -7
  156. data/spec/mongo/server/monitor_spec.rb +9 -1
  157. data/spec/mongo/server_spec.rb +15 -2
  158. data/spec/mongo/socket/ssl_spec.rb +40 -0
  159. data/spec/mongo/socket_spec.rb +2 -2
  160. data/spec/mongo/tls_context_hooks_spec.rb +37 -0
  161. data/spec/runners/connection_string.rb +0 -4
  162. data/spec/runners/crud/requirement.rb +40 -3
  163. data/spec/runners/crud/verifier.rb +8 -0
  164. data/spec/runners/transactions/operation.rb +13 -2
  165. data/spec/runners/transactions/test.rb +1 -0
  166. data/spec/runners/unified.rb +96 -0
  167. data/spec/runners/unified/assertions.rb +249 -0
  168. data/spec/runners/unified/change_stream_operations.rb +26 -0
  169. data/spec/runners/unified/crud_operations.rb +199 -0
  170. data/spec/runners/unified/ddl_operations.rb +96 -0
  171. data/spec/runners/unified/entity_map.rb +39 -0
  172. data/spec/runners/unified/error.rb +25 -0
  173. data/spec/runners/unified/event_subscriber.rb +91 -0
  174. data/spec/runners/unified/exceptions.rb +21 -0
  175. data/spec/runners/unified/grid_fs_operations.rb +55 -0
  176. data/spec/runners/unified/support_operations.rb +250 -0
  177. data/spec/runners/unified/test.rb +393 -0
  178. data/spec/runners/unified/test_group.rb +28 -0
  179. data/spec/runners/unified/using_hash.rb +31 -0
  180. data/spec/shared/bin/get-mongodb-download-url +17 -0
  181. data/spec/shared/lib/mrss/cluster_config.rb +218 -0
  182. data/spec/shared/lib/mrss/constraints.rb +43 -0
  183. data/spec/shared/lib/mrss/docker_runner.rb +262 -0
  184. data/spec/shared/lib/mrss/server_version_registry.rb +112 -0
  185. data/spec/shared/lib/mrss/utils.rb +15 -0
  186. data/spec/shared/share/Dockerfile.erb +231 -0
  187. data/spec/shared/shlib/distro.sh +73 -0
  188. data/spec/shared/shlib/server.sh +290 -0
  189. data/spec/shared/shlib/set_env.sh +128 -0
  190. data/spec/solo/clean_exit_spec.rb +21 -0
  191. data/spec/spec_helper.rb +4 -1
  192. data/spec/spec_tests/crud_unified_spec.rb +10 -0
  193. data/spec/spec_tests/data/change_streams/change-streams.yml +0 -1
  194. data/spec/spec_tests/data/crud_unified/estimatedDocumentCount.yml +267 -0
  195. data/spec/spec_tests/data/retryable_reads/estimatedDocumentCount-4.9.yml +60 -0
  196. data/spec/spec_tests/data/retryable_reads/{estimatedDocumentCount.yml → estimatedDocumentCount-pre4.9.yml} +2 -0
  197. data/spec/spec_tests/data/retryable_reads/estimatedDocumentCount-serverErrors-4.9.yml +146 -0
  198. data/spec/spec_tests/data/retryable_reads/{estimatedDocumentCount-serverErrors.yml → estimatedDocumentCount-serverErrors-pre4.9.yml} +2 -0
  199. data/spec/spec_tests/data/retryable_reads/listIndexNames.yml +1 -1
  200. data/spec/spec_tests/data/unified/valid-fail/operation-failure.yml +31 -0
  201. data/spec/spec_tests/data/unified/valid-pass/poc-change-streams.yml +220 -0
  202. data/spec/spec_tests/data/unified/valid-pass/poc-command-monitoring.yml +102 -0
  203. data/spec/spec_tests/data/unified/valid-pass/poc-crud.yml +184 -0
  204. data/spec/spec_tests/data/unified/valid-pass/poc-gridfs.yml +155 -0
  205. data/spec/spec_tests/data/unified/valid-pass/poc-retryable-reads.yml +193 -0
  206. data/spec/spec_tests/data/unified/valid-pass/poc-retryable-writes.yml +210 -0
  207. data/spec/spec_tests/data/unified/valid-pass/poc-sessions.yml +215 -0
  208. data/spec/spec_tests/data/unified/valid-pass/poc-transactions-convenient-api.yml +235 -0
  209. data/spec/spec_tests/data/unified/valid-pass/poc-transactions-mongos-pin-auto.yml +169 -0
  210. data/spec/spec_tests/data/unified/valid-pass/poc-transactions.yml +170 -0
  211. data/spec/spec_tests/data/uri_options/compression-options.yml +1 -1
  212. data/spec/spec_tests/data/versioned_api/crud-api-version-1-strict.yml +416 -0
  213. data/spec/spec_tests/data/versioned_api/crud-api-version-1.yml +409 -0
  214. data/spec/spec_tests/data/versioned_api/runcommand-helper-no-api-version-declared.yml +67 -0
  215. data/spec/spec_tests/data/versioned_api/test-commands-deprecation-errors.yml +47 -0
  216. data/spec/spec_tests/data/versioned_api/test-commands-strict-mode.yml +44 -0
  217. data/spec/spec_tests/data/versioned_api/transaction-handling.yml +180 -0
  218. data/spec/spec_tests/unified_spec.rb +15 -0
  219. data/spec/spec_tests/uri_options_spec.rb +16 -0
  220. data/spec/spec_tests/versioned_api_spec.rb +10 -0
  221. data/spec/support/common_shortcuts.rb +15 -1
  222. data/spec/support/shared/session.rb +2 -2
  223. data/spec/support/spec_config.rb +46 -3
  224. data/spec/support/spec_setup.rb +48 -38
  225. data/spec/support/utils.rb +64 -3
  226. metadata +1104 -992
  227. metadata.gz.sig +0 -0
  228. data/lib/mongo/operation/shared/collections_info_or_list_collections.rb +0 -58
  229. data/lib/mongo/operation/shared/op_msg_or_list_indexes_command.rb +0 -47
  230. data/spec/support/cluster_config.rb +0 -207
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7bfb22d052a842e256744a88c7e3cbd3b958643cc3e0f4425bf97be8f913f167
4
- data.tar.gz: b63f3605ad8223e99a5f6a62aabff94a8c8600095b84265b6b4deb38e7223013
3
+ metadata.gz: a6312ea7c8c11a1e4f3dd355691d19bacf67bb3862395e69156133dace4b3503
4
+ data.tar.gz: 7a5f97640136a0f32e6e3d8a08f6fdb3a8b726342e7105391a49d18427c41016
5
5
  SHA512:
6
- metadata.gz: 85566c0080b9bcfa67438a365114dd062425df557040e05c0db0448aedd37a0f52dae5b8612b08af196a9e35c1e5b41553a89607d780d187d4e2e28602471c76
7
- data.tar.gz: 5172ab2d71a8d7e048fcb2d87e7219024a2028c3909f2cce48081d1b3014071df13b02426019508bda6542e4870992ca869cd3393caf3aaf6483ad4c74f1abf3
6
+ metadata.gz: 84fd33ac8d290e04c5ad2ca1c1dfa4022d9123d7ab7f8c3c9a621cf29dac04336f8dde8f73c8ff281107def7667ee0f3d5f3b596c90cee0ca8a88845754216f8
7
+ data.tar.gz: ccd825f5fba748bc45f75adef77f93f1a340862d32daa53145cb60e64a5e9b6dfd216c5eca033d1d3e6144a8931f548316315f3eb49b1dafed1dd63de978aa1a
checksums.yaml.gz.sig CHANGED
Binary file
data.tar.gz.sig CHANGED
Binary file
data/README.md CHANGED
@@ -14,7 +14,10 @@ Documentation
14
14
  High level documentation and usage examples are located
15
15
  [here](http://docs.mongodb.org/ecosystem/drivers/ruby/).
16
16
 
17
- API documentation can be found [here](https://api.mongodb.org/ruby/).
17
+ API documentation for the most recent release can be found
18
+ [here](https://docs.mongodb.com/ruby-driver/current/api/).
19
+ To build API documentation for the master branch, check out the
20
+ repository locally and run `rake docs`.
18
21
 
19
22
 
20
23
  Support
data/Rakefile CHANGED
@@ -1,26 +1,19 @@
1
- #!/usr/bin/env ruby
1
+ # -*- mode: ruby -*-
2
2
 
3
- require 'rubygems'
4
-
5
- begin
6
- require 'bundler'
7
- require 'bundler/gem_tasks'
8
- rescue LoadError
9
- raise '[FAIL] Bundler not found! Install it with ' +
10
- '`gem install bundler; bundle install`.'
11
- end
12
-
13
- default_groups = [:default, :testing]
14
- Bundler.require(*default_groups)
3
+ require 'bundler'
4
+ require 'bundler/gem_tasks'
5
+ require 'rspec/core/rake_task'
6
+ # TODO move the mongo require into the individual tasks that actually need it
7
+ require 'mongo'
15
8
 
16
9
  ROOT = File.expand_path(File.join(File.dirname(__FILE__)))
17
10
 
18
11
  $: << File.join(ROOT, 'spec/shared/lib')
19
12
 
20
- require 'rspec/core/rake_task'
21
13
  require 'mrss/spec_organizer'
22
14
 
23
15
  CLASSIFIERS = [
16
+ [%r,^mongo/server,, :unit_server],
24
17
  [%r,^mongo,, :unit],
25
18
  [%r,^kerberos,, :unit],
26
19
  [%r,^integration/sdam_error_handling,, :sdam_integration],
@@ -34,7 +27,7 @@ CLASSIFIERS = [
34
27
 
35
28
  RUN_PRIORITY = %i(
36
29
  tx_examples
37
- unit
30
+ unit unit_server
38
31
  integration sdam_integration cursor_reaping query_cache
39
32
  spec spec_sdam_integration
40
33
  )
data/lib/mongo.rb CHANGED
@@ -78,4 +78,27 @@ module Mongo
78
78
  module_function def clear_ocsp_cache
79
79
  Socket::OcspCache.clear
80
80
  end
81
+
82
+ # This is a user-settable list of hooks that will be invoked when any new
83
+ # TLS socket is connected. Each hook should be a Proc that takes
84
+ # an OpenSSL::SSL::SSLContext object as an argument. These hooks can be used
85
+ # to modify the TLS context (for example to disallow certain ciphers).
86
+ #
87
+ # @return [ Array<Proc> ] The list of procs to be invoked when a TLS socket
88
+ # is connected (may be an empty Array).
89
+ module_function def tls_context_hooks
90
+ @tls_context_hooks ||= []
91
+ end
92
+
93
+ # Set the TLS context hooks.
94
+ #
95
+ # @param [ Array<Proc> ] hooks An Array of Procs, each of which should take
96
+ # an OpenSSL::SSL::SSLContext object as an argument.
97
+ module_function def tls_context_hooks=(hooks)
98
+ unless hooks.is_a?(Array) && hooks.all? { |hook| hook.is_a?(Proc) }
99
+ raise ArgumentError, "TLS context hooks must be an array of Procs"
100
+ end
101
+
102
+ @tls_context_hooks = hooks
103
+ end
81
104
  end
@@ -49,10 +49,7 @@ module Mongo
49
49
  payload: BSON::Binary.new(client_final_payload),
50
50
  conversationId: conversation_id,
51
51
  )
52
- selector[Protocol::Msg::DATABASE_IDENTIFIER] = user.auth_source
53
- cluster_time = connection.mongos? && connection.cluster_time
54
- selector[Operation::CLUSTER_TIME] = cluster_time if cluster_time
55
- Protocol::Msg.new([], {}, selector)
52
+ build_message(connection, user.auth_source, selector)
56
53
  end
57
54
 
58
55
  private
@@ -100,7 +100,13 @@ module Mongo
100
100
  end
101
101
 
102
102
  def dispatch_msg(connection, conversation, msg)
103
- reply = connection.dispatch([msg])
103
+ context = Operation::Context.new(options: {
104
+ server_api: connection.options[:server_api],
105
+ })
106
+ if server_api = context.server_api
107
+ msg = msg.maybe_add_server_api(server_api)
108
+ end
109
+ reply = connection.dispatch([msg], context)
104
110
  reply_document = reply.documents.first
105
111
  validate_reply!(connection, conversation, reply_document)
106
112
  result = Operation::Result.new(reply, connection.description)
@@ -112,14 +118,14 @@ module Mongo
112
118
  # raises Unauthorized if not.
113
119
  def validate_reply!(connection, conversation, doc)
114
120
  if doc[:ok] != 1
115
- extra = [doc[:code], doc[:codeName]].compact.join(': ')
116
- msg = doc[:errmsg]
117
- unless extra.empty?
118
- msg += " (#{extra})"
119
- end
121
+ message = Error::Parser.build_message(
122
+ code: doc[:code],
123
+ code_name: doc[:codeName],
124
+ message: doc[:errmsg],
125
+ )
120
126
  raise Unauthorized.new(user,
121
127
  used_mechanism: self.class.const_get(:MECHANISM),
122
- message: msg,
128
+ message: message,
123
129
  server: connection.server,
124
130
  )
125
131
  end
@@ -47,6 +47,38 @@ module Mongo
47
47
  def speculative_auth_document
48
48
  nil
49
49
  end
50
+
51
+ # @return [ Protocol::Message ] The message to send.
52
+ def build_message(connection, auth_source, selector)
53
+ if connection && connection.features.op_msg_enabled?
54
+ selector = selector.dup
55
+ selector[Protocol::Msg::DATABASE_IDENTIFIER] = auth_source
56
+ cluster_time = connection.mongos? && connection.cluster_time
57
+ if cluster_time
58
+ selector[Operation::CLUSTER_TIME] = cluster_time
59
+ end
60
+ Protocol::Msg.new([], {}, selector)
61
+ else
62
+ Protocol::Query.new(
63
+ auth_source,
64
+ Database::COMMAND,
65
+ selector,
66
+ limit: -1,
67
+ )
68
+ end
69
+ end
70
+
71
+ def validate_external_auth_source
72
+ if user.auth_source != '$external'
73
+ user_name_msg = if user.name
74
+ " #{user.name}"
75
+ else
76
+ ''
77
+ end
78
+ mechanism = user.mechanism
79
+ raise Auth::InvalidConfiguration, "User#{user_name_msg} specifies auth source '#{user.auth_source}', but the only valid auth source for #{mechanism} is '$external'"
80
+ end
81
+ end
50
82
  end
51
83
  end
52
84
  end
@@ -43,22 +43,12 @@ module Mongo
43
43
  # @param [ Server::Connection ] connection The connection being
44
44
  # authenticated.
45
45
  #
46
- # @return [ Protocol::Query ] The first CR conversation message.
46
+ # @return [ Protocol::Message ] The first CR conversation message.
47
47
  #
48
48
  # @since 2.0.0
49
49
  def start(connection)
50
- if connection && connection.features.op_msg_enabled?
51
- selector = Auth::GET_NONCE.merge(Protocol::Msg::DATABASE_IDENTIFIER => user.auth_source)
52
- cluster_time = connection.mongos? && connection.cluster_time
53
- selector[Operation::CLUSTER_TIME] = cluster_time if cluster_time
54
- Protocol::Msg.new([], {}, selector)
55
- else
56
- Protocol::Query.new(
57
- user.auth_source,
58
- Database::COMMAND,
59
- Auth::GET_NONCE,
60
- limit: -1)
61
- end
50
+ selector = Auth::GET_NONCE
51
+ build_message(connection, user.auth_source, selector)
62
52
  end
63
53
 
64
54
  # Continue the CR conversation. This sends the client final message
@@ -70,26 +60,13 @@ module Mongo
70
60
  # @param [ Mongo::Server::Connection ] connection The connection being
71
61
  # authenticated.
72
62
  #
73
- # @return [ Protocol::Query ] The next message to send.
63
+ # @return [ Protocol::Message ] The next message to send.
74
64
  #
75
65
  # @since 2.0.0
76
66
  def continue(reply_document, connection)
77
67
  @nonce = reply_document[Auth::NONCE]
78
-
79
- if connection && connection.features.op_msg_enabled?
80
- selector = LOGIN.merge(user: user.name, nonce: nonce, key: user.auth_key(nonce))
81
- selector[Protocol::Msg::DATABASE_IDENTIFIER] = user.auth_source
82
- cluster_time = connection.mongos? && connection.cluster_time
83
- selector[Operation::CLUSTER_TIME] = cluster_time if cluster_time
84
- Protocol::Msg.new([], {}, selector)
85
- else
86
- Protocol::Query.new(
87
- user.auth_source,
88
- Database::COMMAND,
89
- LOGIN.merge(user: user.name, nonce: nonce, key: user.auth_key(nonce)),
90
- limit: -1
91
- )
92
- end
68
+ selector = LOGIN.merge(user: user.name, nonce: nonce, key: user.auth_key(nonce))
69
+ build_message(connection, user.auth_source, selector)
93
70
  end
94
71
  end
95
72
  end
@@ -70,20 +70,14 @@ module Mongo
70
70
  # @param [ BSON::Document ] reply_document The reply document of the
71
71
  # previous message.
72
72
  #
73
- # @return [ Protocol::Query ] The next query to execute.
73
+ # @return [ Protocol::Message ] The next query to execute.
74
74
  def continue(reply_document, connection)
75
75
  @id = reply_document['conversationId']
76
76
  payload = reply_document['payload']
77
77
 
78
78
  continue_token = authenticator.evaluate_challenge(payload)
79
79
  selector = CONTINUE_MESSAGE.merge(payload: continue_token, conversationId: id)
80
-
81
- Protocol::Query.new(
82
- Auth::EXTERNAL,
83
- Database::COMMAND,
84
- selector,
85
- limit: 1,
86
- )
80
+ build_message(connection, '$external', selector)
87
81
  end
88
82
 
89
83
  def process_continue_response(reply_document)
@@ -92,15 +86,10 @@ module Mongo
92
86
  @continue_token = authenticator.evaluate_challenge(payload)
93
87
  end
94
88
 
89
+ # @return [ Protocol::Message ] The next query to execute.
95
90
  def finalize(connection)
96
91
  selector = CONTINUE_MESSAGE.merge(payload: @continue_token, conversationId: id)
97
-
98
- Protocol::Query.new(
99
- Auth::EXTERNAL,
100
- Database::COMMAND,
101
- selector,
102
- limit: 1,
103
- )
92
+ build_message(connection, '$external', selector)
104
93
  end
105
94
  end
106
95
  end
@@ -38,20 +38,9 @@ module Mongo
38
38
  #
39
39
  # @since 2.0.0
40
40
  def start(connection)
41
- if connection && connection.features.op_msg_enabled?
42
- selector = LOGIN.merge(payload: payload, mechanism: LDAP::MECHANISM)
43
- selector[Protocol::Msg::DATABASE_IDENTIFIER] = Auth::EXTERNAL
44
- cluster_time = connection.mongos? && connection.cluster_time
45
- selector[Operation::CLUSTER_TIME] = cluster_time if cluster_time
46
- Protocol::Msg.new([], {}, selector)
47
- else
48
- Protocol::Query.new(
49
- Auth::EXTERNAL,
50
- Database::COMMAND,
51
- LOGIN.merge(payload: payload, mechanism: LDAP::MECHANISM),
52
- limit: -1
53
- )
54
- end
41
+ validate_external_auth_source
42
+ selector = LOGIN.merge(payload: payload, mechanism: LDAP::MECHANISM)
43
+ build_message(connection, '$external', selector)
55
44
  end
56
45
 
57
46
  private
@@ -35,19 +35,7 @@ module Mongo
35
35
  # @return [ Protocol::Message ] The first SASL conversation message.
36
36
  def start(connection)
37
37
  selector = client_first_document
38
- if connection && connection.features.op_msg_enabled?
39
- selector[Protocol::Msg::DATABASE_IDENTIFIER] = user.auth_source
40
- cluster_time = connection.mongos? && connection.cluster_time
41
- selector[Operation::CLUSTER_TIME] = cluster_time if cluster_time
42
- Protocol::Msg.new([], {}, selector)
43
- else
44
- Protocol::Query.new(
45
- user.auth_source,
46
- Database::COMMAND,
47
- selector,
48
- limit: -1,
49
- )
50
- end
38
+ build_message(connection, user.auth_source, selector)
51
39
  end
52
40
 
53
41
  private
@@ -87,19 +87,7 @@ module Mongo
87
87
  payload: client_final_message,
88
88
  conversationId: id,
89
89
  )
90
- if connection && connection.features.op_msg_enabled?
91
- selector[Protocol::Msg::DATABASE_IDENTIFIER] = user.auth_source
92
- cluster_time = connection.mongos? && connection.cluster_time
93
- selector[Operation::CLUSTER_TIME] = cluster_time if cluster_time
94
- Protocol::Msg.new([], {}, selector)
95
- else
96
- Protocol::Query.new(
97
- user.auth_source,
98
- Database::COMMAND,
99
- selector,
100
- limit: -1,
101
- )
102
- end
90
+ build_message(connection, user.auth_source, selector)
103
91
  end
104
92
 
105
93
  # Processes the second response from the server.
@@ -116,28 +104,13 @@ module Mongo
116
104
  #
117
105
  # @param [ Server::Connection ] connection The connection being authenticated.
118
106
  #
119
- # @return [ Protocol::Query ] The next message to send.
107
+ # @return [ Protocol::Message ] The next message to send.
120
108
  def finalize(connection)
121
- if connection && connection.features.op_msg_enabled?
122
- selector = CLIENT_CONTINUE_MESSAGE.merge(
123
- payload: client_empty_message,
124
- conversationId: id,
125
- )
126
- selector[Protocol::Msg::DATABASE_IDENTIFIER] = user.auth_source
127
- cluster_time = connection.mongos? && connection.cluster_time
128
- selector[Operation::CLUSTER_TIME] = cluster_time if cluster_time
129
- Protocol::Msg.new([], {}, selector)
130
- else
131
- Protocol::Query.new(
132
- user.auth_source,
133
- Database::COMMAND,
134
- CLIENT_CONTINUE_MESSAGE.merge(
135
- payload: client_empty_message,
136
- conversationId: id,
137
- ),
138
- limit: -1,
139
- )
140
- end
109
+ selector = CLIENT_CONTINUE_MESSAGE.merge(
110
+ payload: client_empty_message,
111
+ conversationId: id,
112
+ )
113
+ build_message(connection, user.auth_source, selector)
141
114
  end
142
115
 
143
116
  # Returns the hash to provide to the server in the handshake
@@ -44,13 +44,13 @@ module Mongo
44
44
  # @since 2.0.0
45
45
  def create(user_or_name, options = {})
46
46
  user = generate(user_or_name, options)
47
- client.send(:with_session, options) do |session|
47
+ execute_operation(options) do |session|
48
48
  Operation::CreateUser.new(
49
49
  user: user,
50
50
  db_name: database.name,
51
51
  session: session,
52
52
  write_concern: options[:write_concern] && WriteConcern.get(options[:write_concern]),
53
- ).execute(next_primary(nil, session), client: client)
53
+ )
54
54
  end
55
55
  end
56
56
 
@@ -81,13 +81,13 @@ module Mongo
81
81
  #
82
82
  # @since 2.0.0
83
83
  def remove(name, options = {})
84
- client.send(:with_session, options) do |session|
84
+ execute_operation(options) do |session|
85
85
  Operation::RemoveUser.new(
86
86
  user_name: name,
87
87
  db_name: database.name,
88
88
  session: session,
89
89
  write_concern: options[:write_concern] && WriteConcern.get(options[:write_concern]),
90
- ).execute(next_primary(nil, session), client: client)
90
+ )
91
91
  end
92
92
  end
93
93
 
@@ -106,14 +106,14 @@ module Mongo
106
106
  #
107
107
  # @since 2.0.0
108
108
  def update(user_or_name, options = {})
109
- client.send(:with_session, options) do |session|
110
- user = generate(user_or_name, options)
109
+ user = generate(user_or_name, options)
110
+ execute_operation(options) do |session|
111
111
  Operation::UpdateUser.new(
112
112
  user: user,
113
113
  db_name: database.name,
114
114
  session: session,
115
115
  write_concern: options[:write_concern] && WriteConcern.get(options[:write_concern]),
116
- ).execute(next_primary(nil, session), client: client)
116
+ )
117
117
  end
118
118
  end
119
119
 
@@ -137,18 +137,25 @@ module Mongo
137
137
  private
138
138
 
139
139
  def user_query(name, options = {})
140
- client.send(:with_session, options) do |session|
140
+ execute_operation(options) do |session|
141
141
  Operation::UsersInfo.new(
142
142
  user_name: name,
143
143
  db_name: database.name,
144
144
  session: session
145
- ).execute(next_primary(nil, session), client: client)
145
+ )
146
146
  end
147
147
  end
148
148
 
149
149
  def generate(user, options)
150
150
  user.is_a?(String) ? Auth::User.new({ user: user }.merge(options)) : user
151
151
  end
152
+
153
+ def execute_operation(options)
154
+ client.send(:with_session, options) do |session|
155
+ op = yield session
156
+ op.execute(next_primary(nil, session), context: Operation::Context.new(client: client, session: session))
157
+ end
158
+ end
152
159
  end
153
160
  end
154
161
  end