mongoid 8.0.11 → 8.0.12

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 78040726b40c1709f9218bc28850b802cf5aedfbdd178c2ed90322ffb16ba0ee
4
- data.tar.gz: 438d1fee26567d71150518c5df2f764d6671c49ea6cc02c0582a7cd15e80fd7a
3
+ metadata.gz: f08452ead2923923372a78e2e981543ced23f0353ece5109a3f19411e29a9e29
4
+ data.tar.gz: 2ec3d115f4be09f2ca9b04704b965bdffc266eb047ca2701ecdc7018353be5fc
5
5
  SHA512:
6
- metadata.gz: 8420a185b4baf6c1183ff188bc16f5d79fc75f44f1784c37df163836b70939250efbefceaeb53269a9d97f0b7bc9ae997a6586306223bea424db8738a3f2513e
7
- data.tar.gz: 1f8dc137d3de2c5bc6ff676f8330471e4a792fe259839e6edec6107e145fd3b81bd4013df64e4b2410a62793ce2d35855069672a4a8784cf2de076f3ac4fda61
6
+ metadata.gz: 88300684eb21ca82ff1a43c58dcb5dbe0d45d8d5c187d569c31b6e1653293ffedbcc699bccf92941a47eb83ce9d11a9dcb1c1c51a2db5af70d1a1ed0db459a3a
7
+ data.tar.gz: 2b6207d2c5b2d94bcd24b7299ed4dc47bc1f5df5035c887253b4aa456dabe4653b19de6da5db094b109aea5ea2455754c15c8e19a6c84231102fe613d562948f
@@ -95,6 +95,10 @@ module Mongoid
95
95
  [MONGOID_WRAPPING_LIBRARY] + options[:wrapping_libraries]
96
96
  else
97
97
  [MONGOID_WRAPPING_LIBRARY]
98
+ end.tap do |wrap|
99
+ if defined?(::Rails) && ::Rails.respond_to?(:version)
100
+ wrap << { name: 'Rails', version: ::Rails.version }
101
+ end
98
102
  end
99
103
  options[:wrapping_libraries] = wrap_lib
100
104
  end
@@ -167,6 +167,28 @@ module Mongoid
167
167
  true
168
168
  end
169
169
 
170
+ ALLOWED_TO_CRITERIA_METHODS = %i[
171
+ all all_in all_of and any_in any_of asc ascending
172
+ batch_size between
173
+ collation comment cursor_type
174
+ desc descending
175
+ elem_match eq exists extras
176
+ geo_spatial group gt gte
177
+ hint
178
+ in includes
179
+ limit lt lte
180
+ max_distance max_scan max_time_ms merge mod
181
+ ne near near_sphere nin no_timeout none none_of nor not not_in
182
+ offset only or order order_by
183
+ project
184
+ raw read reorder
185
+ scoped skip slice snapshot
186
+ text_search type
187
+ unscoped unwind
188
+ where with_size with_type without
189
+ ].freeze
190
+ private_constant :ALLOWED_TO_CRITERIA_METHODS
191
+
170
192
  # Convert this hash to a criteria. Will iterate over each keys in the
171
193
  # hash which must correspond to method on a criteria object. The hash
172
194
  # must also include a "klass" key.
@@ -178,7 +200,11 @@ module Mongoid
178
200
  def to_criteria
179
201
  criteria = Criteria.new(delete(:klass) || delete("klass"))
180
202
  each_pair do |method, args|
181
- criteria = criteria.__send__(method, args)
203
+ method_sym = method.to_sym
204
+ unless ALLOWED_TO_CRITERIA_METHODS.include?(method_sym)
205
+ raise ArgumentError, "Method '#{method}' is not allowed in to_criteria"
206
+ end
207
+ criteria = criteria.public_send(method_sym, args)
182
208
  end
183
209
  criteria
184
210
  end
@@ -5,5 +5,5 @@ module Mongoid
5
5
  #
6
6
  # Note that this file is automatically updated via `rake candidate:create`.
7
7
  # Manual changes to this file will be overwritten by that rake task.
8
- VERSION = '8.0.11'
8
+ VERSION = '8.0.12'
9
9
  end
@@ -29,6 +29,32 @@ describe Mongoid::Clients::Factory do
29
29
  end
30
30
  end
31
31
 
32
+ shared_examples_for 'includes rails wrapping library' do
33
+ context 'when Rails is available' do
34
+ around do |example|
35
+ original_rails_constant = defined?(::Rails) ? ::Rails : nil
36
+ Object.send(:remove_const, :Rails) if original_rails_constant
37
+
38
+ module ::Rails
39
+ def self.version
40
+ '6.1.0'
41
+ end
42
+ end
43
+
44
+ example.run
45
+
46
+ Object.send(:remove_const, :Rails) if defined?(::Rails)
47
+ Object.const_set(:Rails, original_rails_constant)
48
+ end
49
+
50
+ it 'adds Rails as another wrapping library' do
51
+ expect(client.options[:wrapping_libraries]).to include(
52
+ {'name' => 'Rails', 'version' => '6.1.0'},
53
+ )
54
+ end
55
+ end
56
+ end
57
+
32
58
  describe ".create" do
33
59
 
34
60
  context "when provided a name" do
@@ -88,6 +114,8 @@ describe Mongoid::Clients::Factory do
88
114
  Mongoid::Clients::Factory::MONGOID_WRAPPING_LIBRARY)]
89
115
  end
90
116
 
117
+ it_behaves_like 'includes rails wrapping library'
118
+
91
119
  context 'when configuration specifies a wrapping library' do
92
120
 
93
121
  let(:config) do
@@ -109,6 +137,8 @@ describe Mongoid::Clients::Factory do
109
137
  {'name' => 'Foo'},
110
138
  ]
111
139
  end
140
+
141
+ it_behaves_like 'includes rails wrapping library'
112
142
  end
113
143
  end
114
144
 
@@ -2,7 +2,8 @@
2
2
 
3
3
  require "spec_helper"
4
4
 
5
- describe Bignum do
5
+ describe 'Bignum' do
6
+ ruby_version_lt "2.4"
6
7
 
7
8
  describe ".evolve" do
8
9
 
@@ -2,7 +2,8 @@
2
2
 
3
3
  require "spec_helper"
4
4
 
5
- describe Fixnum do
5
+ describe 'Fixnum' do
6
+ ruby_version_lt "2.4"
6
7
 
7
8
  describe ".evolve" do
8
9
 
@@ -497,4 +497,240 @@ describe Mongoid::Extensions::Hash do
497
497
 
498
498
  it_behaves_like 'unsatisfiable criteria method'
499
499
  end
500
+
501
+ describe '#to_criteria' do
502
+ subject(:criteria) { hash.to_criteria }
503
+
504
+ context 'when klass is specified' do
505
+ let(:hash) do
506
+ { klass: Band, where: { name: 'Songs Ohia' } }
507
+ end
508
+
509
+ it 'returns a criteria' do
510
+ expect(criteria).to be_a(Mongoid::Criteria)
511
+ end
512
+
513
+ it 'sets the klass' do
514
+ expect(criteria.klass).to eq(Band)
515
+ end
516
+
517
+ it 'sets the selector' do
518
+ expect(criteria.selector).to eq({ 'name' => 'Songs Ohia' })
519
+ end
520
+ end
521
+
522
+ context 'when klass is missing' do
523
+ let(:hash) do
524
+ { where: { name: 'Songs Ohia' } }
525
+ end
526
+
527
+ it 'returns a criteria' do
528
+ expect(criteria).to be_a(Mongoid::Criteria)
529
+ end
530
+
531
+ it 'has klass nil' do
532
+ expect(criteria.klass).to be_nil
533
+ end
534
+
535
+ it 'sets the selector' do
536
+ expect(criteria.selector).to eq({ 'name' => 'Songs Ohia' })
537
+ end
538
+ end
539
+
540
+ context 'with allowed methods' do
541
+ context 'when using multiple query methods' do
542
+ let(:hash) do
543
+ {
544
+ klass: Band,
545
+ where: { active: true },
546
+ limit: 10,
547
+ skip: 5,
548
+ order_by: { name: 1 }
549
+ }
550
+ end
551
+
552
+ it 'applies all methods successfully' do
553
+ expect(criteria.selector).to eq({ 'active' => true })
554
+ expect(criteria.options[:limit]).to eq(10)
555
+ expect(criteria.options[:skip]).to eq(5)
556
+ expect(criteria.options[:sort]).to eq({ 'name' => 1 })
557
+ end
558
+ end
559
+
560
+ context 'when using query selector methods' do
561
+ let(:hash) do
562
+ {
563
+ klass: Band,
564
+ gt: { members: 2 },
565
+ in: { genre: ['rock', 'metal'] }
566
+ }
567
+ end
568
+
569
+ it 'applies selector methods' do
570
+ expect(criteria.selector['members']).to eq({ '$gt' => 2 })
571
+ expect(criteria.selector['genre']).to eq({ '$in' => ['rock', 'metal'] })
572
+ end
573
+ end
574
+
575
+ context 'when using aggregation methods' do
576
+ let(:hash) do
577
+ {
578
+ klass: Band,
579
+ project: { name: 1, members: 1 }
580
+ }
581
+ end
582
+
583
+ it 'applies aggregation methods' do
584
+ expect { criteria }.not_to raise_error
585
+ end
586
+ end
587
+ end
588
+
589
+ context 'with disallowed methods' do
590
+ context 'when attempting to call create' do
591
+ let(:hash) do
592
+ { klass: Band, create: { name: 'Malicious' } }
593
+ end
594
+
595
+ it 'raises ArgumentError' do
596
+ expect { criteria }.to raise_error(ArgumentError, "Method 'create' is not allowed in to_criteria")
597
+ end
598
+ end
599
+
600
+ context 'when attempting to call create!' do
601
+ let(:hash) do
602
+ { klass: Band, 'create!': { name: 'Malicious' } }
603
+ end
604
+
605
+ it 'raises ArgumentError' do
606
+ expect { criteria }.to raise_error(ArgumentError, "Method 'create!' is not allowed in to_criteria")
607
+ end
608
+ end
609
+
610
+ context 'when attempting to call build' do
611
+ let(:hash) do
612
+ { klass: Band, build: { name: 'Malicious' } }
613
+ end
614
+
615
+ it 'raises ArgumentError' do
616
+ expect { criteria }.to raise_error(ArgumentError, "Method 'build' is not allowed in to_criteria")
617
+ end
618
+ end
619
+
620
+ context 'when attempting to call find' do
621
+ let(:hash) do
622
+ { klass: Band, find: 'some_id' }
623
+ end
624
+
625
+ it 'raises ArgumentError' do
626
+ expect { criteria }.to raise_error(ArgumentError, "Method 'find' is not allowed in to_criteria")
627
+ end
628
+ end
629
+
630
+ context 'when attempting to call execute_or_raise' do
631
+ let(:hash) do
632
+ { klass: Band, execute_or_raise: ['id1', 'id2'] }
633
+ end
634
+
635
+ it 'raises ArgumentError' do
636
+ expect { criteria }.to raise_error(ArgumentError, "Method 'execute_or_raise' is not allowed in to_criteria")
637
+ end
638
+ end
639
+
640
+ context 'when attempting to call new' do
641
+ let(:hash) do
642
+ { klass: Band, new: { name: 'Test' } }
643
+ end
644
+
645
+ it 'raises ArgumentError' do
646
+ expect { criteria }.to raise_error(ArgumentError, "Method 'new' is not allowed in to_criteria")
647
+ end
648
+ end
649
+
650
+ context 'when allowed method is combined with disallowed method' do
651
+ let(:hash) do
652
+ {
653
+ klass: Band,
654
+ where: { active: true },
655
+ create: { name: 'Malicious' }
656
+ }
657
+ end
658
+
659
+ it 'raises ArgumentError before executing any methods' do
660
+ expect { criteria }.to raise_error(ArgumentError, "Method 'create' is not allowed in to_criteria")
661
+ end
662
+ end
663
+ end
664
+
665
+ context 'security validation' do
666
+ # This test ensures that ALL public methods not in the allowlist are blocked
667
+ it 'blocks all dangerous public methods' do
668
+ dangerous_methods = %i[
669
+ build create create! new
670
+ find find_or_create_by find_or_create_by! find_or_initialize_by
671
+ first_or_create first_or_create! first_or_initialize
672
+ execute_or_raise multiple_from_db for_ids
673
+ documents= inclusions= scoping_options=
674
+ initialize freeze as_json
675
+ ]
676
+
677
+ dangerous_methods.each do |method|
678
+ hash = { klass: Band, method => 'arg' }
679
+ expect { hash.to_criteria }.to raise_error(
680
+ ArgumentError,
681
+ "Method '#{method}' is not allowed in to_criteria"
682
+ ), "Expected method '#{method}' to be blocked but it was allowed"
683
+ end
684
+ end
685
+
686
+ it 'blocks dangerous inherited methods from Object' do
687
+ # Critical security test: block send, instance_eval, etc.
688
+ inherited_dangerous = %i[
689
+ send __send__ instance_eval instance_exec
690
+ instance_variable_set method
691
+ ]
692
+
693
+ inherited_dangerous.each do |method|
694
+ hash = { klass: Band, method => 'arg' }
695
+ expect { hash.to_criteria }.to raise_error(
696
+ ArgumentError,
697
+ "Method '#{method}' is not allowed in to_criteria"
698
+ ), "Expected inherited method '#{method}' to be blocked"
699
+ end
700
+ end
701
+
702
+ it 'blocks Enumerable execution methods' do
703
+ # to_criteria should build queries, not execute them
704
+ enumerable_methods = %i[each map select count sum]
705
+
706
+ enumerable_methods.each do |method|
707
+ hash = { klass: Band, method => 'arg' }
708
+ expect { hash.to_criteria }.to raise_error(
709
+ ArgumentError,
710
+ "Method '#{method}' is not allowed in to_criteria"
711
+ ), "Expected Enumerable method '#{method}' to be blocked"
712
+ end
713
+ end
714
+
715
+ it 'allows all whitelisted methods' do
716
+ # Sample of allowed methods from each category
717
+ allowed_sample = {
718
+ where: { name: 'Test' }, # Query selector
719
+ limit: 10, # Query option
720
+ skip: 5, # Query option
721
+ gt: { age: 18 }, # Query selector
722
+ in: { status: ['active'] }, # Query selector
723
+ ascending: :name, # Sorting
724
+ includes: :notes, # Eager loading
725
+ merge: { klass: Band }, # Merge
726
+ }
727
+
728
+ allowed_sample.each do |method, args|
729
+ hash = { klass: Band, method => args }
730
+ expect { hash.to_criteria }.not_to raise_error,
731
+ "Expected method '#{method}' to be allowed but it was blocked"
732
+ end
733
+ end
734
+ end
735
+ end
500
736
  end
@@ -0,0 +1,28 @@
1
+ # Candidate Tasks
2
+
3
+ When using the `candidate` rake tasks, you must make sure:
4
+
5
+ 1. You are using at least `git` version 2.49.0.
6
+ 2. You have the `gh` CLI tool installed.
7
+ 3. You are logged into `gh` with an account that has collaborator access to the repository.
8
+ 4. You have run `gh repo set-default` from the root of your local checkout to set the default repository to the canonical MongoDB repo.
9
+ 5. The `origin` remote for your local checkout is set to your own fork.
10
+ 6. The `upstream` remote for your local checkout is set to the canonical
11
+ MongoDB repo.
12
+
13
+ Once configured, you can use the following commands:
14
+
15
+ 1. `rake candidate:prs` - This will list all pull requests that will be included in the next release. Any with `[?]` are unlabelled (or are not labelled with a recognized label). Otherwise, `[b]` means `bug`, `[f]` means `feature`, and `[x]` means `bcbreak`.
16
+ 2. `rake candidate:preview` - This will generate and display the release notes for the next release, based on the associated pull requests.
17
+ 3. `rake candidate:create` - This will create a new PR against the default repository, using the generated release notes as the description. The new PR will be given the `release-candidate` label.
18
+
19
+ Then, after the release candidate PR is approved and merged, the release process will automatically bundle, sign, and release the new version.
20
+
21
+ Once you've merged the PR, you can switch to the "Actions" tab for the repository on GitHub and look for the "Release" workflow (might be named differently), which should have triggered automatically. You can monitor the progress of the release there. If there are any problems, the workflow is generally safe to re-run after you've addressed them.
22
+
23
+ Things to do after the release succeeds:
24
+
25
+ 1. Copy the release notes from the PR and create a new release announcement on the forums (https://www.mongodb.com/community/forums/c/announcements/driver-releases/110).
26
+ 2. If the release was not automatically announced in #ruby, copy a link to the GitHub release or MongoDB forum post there.
27
+ 3. Close the release in Jira.
28
+
@@ -25,19 +25,19 @@ module Mrss
25
25
  end
26
26
 
27
27
  def initialize(root: nil, classifiers:, priority_order:,
28
- spec_root: nil, rspec_json_path: nil, rspec_all_json_path: nil,
29
- randomize: false
28
+ spec_root: nil, rspec_json_path: nil, rspec_all_json_path: nil, rspec_xml_path: nil, randomize: false
30
29
  )
31
30
  @spec_root = spec_root || File.join(root, 'spec')
32
31
  @classifiers = classifiers
33
32
  @priority_order = priority_order
34
33
  @rspec_json_path = rspec_json_path || File.join(root, 'tmp/rspec.json')
35
34
  @rspec_all_json_path = rspec_all_json_path || File.join(root, 'tmp/rspec-all.json')
35
+ @rspec_xml_path = rspec_xml_path || File.join(root, 'tmp/rspec.xml')
36
36
  @randomize = !!randomize
37
37
  end
38
38
 
39
39
  attr_reader :spec_root, :classifiers, :priority_order
40
- attr_reader :rspec_json_path, :rspec_all_json_path
40
+ attr_reader :rspec_json_path, :rspec_all_json_path, :rspec_xml_path
41
41
 
42
42
  def randomize?
43
43
  @randomize
@@ -47,6 +47,25 @@ module Mrss
47
47
  @seed ||= (rand * 100_000).to_i
48
48
  end
49
49
 
50
+ # Remove all XML files from tmp directory before running tests
51
+ def cleanup_xml_files
52
+ xml_pattern = File.join(File.dirname(rspec_xml_path), '*.xml')
53
+ Dir.glob(xml_pattern).each do |xml_file|
54
+ FileUtils.rm_f(xml_file)
55
+ end
56
+ end
57
+
58
+ # Move the XML file to a timestamped version for evergreen upload
59
+ def archive_xml_file(category)
60
+ return unless File.exist?(rspec_xml_path)
61
+
62
+ timestamp = Time.now.strftime('%Y%m%d_%H%M%S_%3N')
63
+ archived_path = rspec_xml_path.sub(/\.xml$/, "-#{category}-#{timestamp}.xml")
64
+
65
+ FileUtils.mv(rspec_xml_path, archived_path)
66
+ puts "Archived XML results to #{archived_path}"
67
+ end
68
+
50
69
  def buckets
51
70
  @buckets ||= {}.tap do |buckets|
52
71
  Find.find(spec_root) do |path|
@@ -96,6 +115,8 @@ module Mrss
96
115
 
97
116
  def run_buckets(*buckets)
98
117
  FileUtils.rm_f(rspec_all_json_path)
118
+ # Clean up all XML files before starting test runs
119
+ cleanup_xml_files
99
120
 
100
121
  buckets.each do |bucket|
101
122
  if bucket && !self.buckets[bucket]
@@ -131,7 +152,12 @@ module Mrss
131
152
  def run_files(category, paths)
132
153
  puts "Running #{category.to_s.gsub('_', ' ')} tests"
133
154
  FileUtils.rm_f(rspec_json_path)
155
+ FileUtils.rm_f(rspec_xml_path) # Clean up XML file before running this bucket
156
+
134
157
  cmd = %w(rspec) + paths
158
+ # Add junit formatter for XML output
159
+ cmd += ['--format', 'Rfc::Riff', '--format', 'RspecJunitFormatter', '--out', rspec_xml_path]
160
+
135
161
  if randomize?
136
162
  cmd += %W(--order rand:#{seed})
137
163
  end
@@ -147,6 +173,9 @@ module Mrss
147
173
  FileUtils.cp(rspec_json_path, rspec_all_json_path)
148
174
  end
149
175
  end
176
+
177
+ # Archive XML file after running this bucket
178
+ archive_xml_file(category)
150
179
  end
151
180
 
152
181
  true
@@ -78,7 +78,7 @@ install_mlaunch_venv() {
78
78
  # Debian11/Ubuntu2204 have venv installed, but it is nonfunctional unless
79
79
  # the python3-venv package is also installed (it lacks the ensurepip
80
80
  # module).
81
- sudo apt-get install --yes python3-venv
81
+ sudo apt-get update && sudo apt-get install --yes python3-venv
82
82
  fi
83
83
  if test "$USE_SYSTEM_PYTHON_PACKAGES" = 1 &&
84
84
  python3 -m pip list |grep mtools
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongoid
3
3
  version: !ruby/object:Gem::Version
4
- version: 8.0.11
4
+ version: 8.0.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - The MongoDB Ruby Team
@@ -831,6 +831,7 @@ files:
831
831
  - spec/mongoid_spec.rb
832
832
  - spec/rails/controller_extension/controller_runtime_spec.rb
833
833
  - spec/rails/mongoid_spec.rb
834
+ - spec/shared/CANDIDATE.md
834
835
  - spec/shared/LICENSE
835
836
  - spec/shared/bin/get-mongodb-download-url
836
837
  - spec/shared/bin/s3-copy
@@ -1154,7 +1155,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
1154
1155
  - !ruby/object:Gem::Version
1155
1156
  version: 1.3.6
1156
1157
  requirements: []
1157
- rubygems_version: 3.7.1
1158
+ rubygems_version: 4.0.4
1158
1159
  specification_version: 4
1159
1160
  summary: Elegant Persistence in Ruby for MongoDB.
1160
1161
  test_files:
@@ -1548,6 +1549,7 @@ test_files:
1548
1549
  - spec/mongoid_spec.rb
1549
1550
  - spec/rails/controller_extension/controller_runtime_spec.rb
1550
1551
  - spec/rails/mongoid_spec.rb
1552
+ - spec/shared/CANDIDATE.md
1551
1553
  - spec/shared/LICENSE
1552
1554
  - spec/shared/bin/get-mongodb-download-url
1553
1555
  - spec/shared/bin/s3-copy