metasploit_data_models 0.19.3 → 0.19.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- MWU5ODZlY2I0YjdjYmY1Mzg1N2U4OGUwNDhiYjc3NjA1NThkYjY1NA==
4
+ OGVlZmE2OTg5NzU3YmU2OTdiZWI0N2UwYjU5MTJhNTEzNzE4ZjhhNQ==
5
5
  data.tar.gz: !binary |-
6
- ZjdjNWY0YjZkZjZhZDVhODA5NTUyZGYwOThlZGZjNjcxMTE4MzBlYQ==
6
+ NWZiNzhiMDEyYjQ3ODdiZWE3NmQ3Njg5YjE5YjkyNTUxYTA0MmNlYQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- MDNiYTJmYjE1N2JkNGJiNTNjZWU4MzhlMjZjMzA1MGQ5ZTc4NDlkZTA4NDM1
10
- ZjAyZWExYTdlMmI1NzIwMWRmNjk5MTMxM2I1MDJmZWMzMDY4YzZiNmE0ZWEz
11
- YzkwYjMyYzM5MDcwNzFlNGEyMDcyZjhkMGQxY2EzYzM1MjQ3ZGU=
9
+ MjBmZjA1Njg3MWRkMGRiMDM1NWFiMzUxYzQ3OWJiZTMzZWVjZWIxOTU0Mzc5
10
+ YWQ2NTg5MzMyZjczMjg4ZTIyOTBmNDRhZGJjMzg3YzA5Y2NkMDVjYTE3Y2Zm
11
+ ZThhN2FkNmMwODI5NzJmMzg5MTgzOTQ5ZGJmYzQwZGNiMWYxZDc=
12
12
  data.tar.gz: !binary |-
13
- NjIyNzQyMmMzNjIyMzI0YjA5NGIyNTA2YjkzNDA1YTg3NGE1OTIwNzE1YWRk
14
- NjI1NjY1NGRmNmZiMTRjYWQ0Mjg5Mjg4NDM0YTk0ZTM0MjlhMTA0NDY3MGQz
15
- NzdjMDY5NDgyZDNmOGVkMjAxNWRlOTdmNjA2ODJiY2JiNGI3MTI=
13
+ ZjM4MDllNmZkYzlkYmU5NmM3MmRjYmQ3Mzc4NGIwOTFlZjY5ZjlmZjZjZmQ4
14
+ NjVhYzdjMDMwN2I0OGRiYjMzNDgzNmIzMGQ0YmMzYWM3ODQyMGEzOTYzMDhk
15
+ YTdlOTEzYTg0ODFjMTU1ZjE2OGZkMzdmNmRlNWFkODRhZDJiMjI=
@@ -189,7 +189,7 @@ class Mdm::Service < ActiveRecord::Base
189
189
  # Search Associations
190
190
  #
191
191
 
192
- search_association :host
192
+ search_associations host: :tags
193
193
 
194
194
  #
195
195
  # Search Attributes
@@ -208,14 +208,6 @@ class Mdm::Service < ActiveRecord::Base
208
208
  # Search Withs
209
209
  #
210
210
 
211
- # Have to declare on Mdm::Service because non-attribute operators cannot function as association operators
212
- search_with MetasploitDataModels::Search::Operator::Multitext,
213
- name: :'host.os',
214
- operator_names: [
215
- :'host.os_name',
216
- :'host.os_flavor',
217
- :'host.os_sp'
218
- ]
219
211
  search_with MetasploitDataModels::Search::Operator::Port::List
220
212
 
221
213
  #
@@ -3,7 +3,7 @@ class MetasploitDataModels::Search::Visitor::Attribute
3
3
  include Metasploit::Model::Visitation::Visit
4
4
 
5
5
  visit 'Metasploit::Model::Search::Operator::Association' do |operator|
6
- visit operator.attribute_operator
6
+ visit operator.source_operator
7
7
  end
8
8
 
9
9
  visit 'Metasploit::Model::Search::Operator::Attribute',
@@ -12,14 +12,29 @@ class MetasploitDataModels::Search::Visitor::Includes
12
12
  parent.children.flat_map { |child|
13
13
  visit child
14
14
  }
15
- end
15
+ end
16
+
17
+ visit 'Metasploit::Model::Search::Operation::Association' do |operation|
18
+ association = visit operation.operator
19
+ nested_associations = visit operation.source_operation
20
+
21
+ if nested_associations.empty?
22
+ [association]
23
+ else
24
+ [
25
+ {
26
+ association => nested_associations
27
+ }
28
+ ]
29
+ end
30
+ end
16
31
 
17
32
  visit 'Metasploit::Model::Search::Operation::Base' do |operation|
18
33
  visit operation.operator
19
34
  end
20
35
 
21
36
  visit 'Metasploit::Model::Search::Operator::Association' do |operator|
22
- [operator.association]
37
+ operator.association
23
38
  end
24
39
 
25
40
  visit 'Metasploit::Model::Search::Operator::Attribute',
@@ -34,12 +34,27 @@ class MetasploitDataModels::Search::Visitor::Joins
34
34
  common_join_set.to_a
35
35
  end
36
36
 
37
+ visit 'Metasploit::Model::Search::Operation::Association' do |operation|
38
+ association = visit operation.operator
39
+ nested_associations = visit operation.source_operation
40
+
41
+ if nested_associations.empty?
42
+ [association]
43
+ else
44
+ [
45
+ {
46
+ association => nested_associations
47
+ }
48
+ ]
49
+ end
50
+ end
51
+
37
52
  visit 'Metasploit::Model::Search::Operation::Base' do |operation|
38
53
  visit operation.operator
39
54
  end
40
55
 
41
56
  visit 'Metasploit::Model::Search::Operator::Association' do |operator|
42
- [operator.association]
57
+ operator.association
43
58
  end
44
59
 
45
60
  visit 'Metasploit::Model::Search::Operator::Attribute',
@@ -38,6 +38,10 @@ class MetasploitDataModels::Search::Visitor::Where
38
38
  attribute.eq(operation.value)
39
39
  end
40
40
 
41
+ visit 'Metasploit::Model::Search::Operation::Association' do |operation|
42
+ visit operation.source_operation
43
+ end
44
+
41
45
  visit 'Metasploit::Model::Search::Operation::String' do |operation|
42
46
  attribute = attribute_visitor.visit operation.operator
43
47
  match_value = "%#{operation.value}%"
@@ -6,7 +6,7 @@ module MetasploitDataModels
6
6
  # The minor version number, scoped to the {MAJOR} version number.
7
7
  MINOR = 19
8
8
  # The patch number, scoped to the {MINOR} version number.
9
- PATCH = 3
9
+ PATCH = 4
10
10
 
11
11
  # The full version string, including the {MAJOR}, {MINOR}, {PATCH}, and optionally, the `PRERELEASE` in the
12
12
  # {http://semver.org/spec/v2.0.0.html semantic versioning v2.0.0} format.
@@ -40,7 +40,7 @@ Gem::Specification.new do |s|
40
40
  s.add_runtime_dependency 'activerecord', '>= 3.2.13', '< 4.0.0'
41
41
  s.add_runtime_dependency 'activesupport'
42
42
  s.add_runtime_dependency 'metasploit-concern', '~> 0.1.0'
43
- s.add_runtime_dependency 'metasploit-model', '>= 0.25.1', '< 0.26'
43
+ s.add_runtime_dependency 'metasploit-model', '~> 0.26.1'
44
44
 
45
45
  # arel-helpers: Useful tools to help construct database queries with ActiveRecord and Arel.
46
46
  s.add_runtime_dependency 'arel-helpers'
@@ -47,28 +47,28 @@ describe MetasploitDataModels::Search::Visitor::Attribute do
47
47
  end
48
48
 
49
49
  context 'with Metasploit::Model::Search::Operator::Association' do
50
- let(:attribute_operator) do
51
- double('Attribute Operator')
50
+ let(:source_operator) do
51
+ double('source operator')
52
52
  end
53
53
 
54
54
  let(:node) do
55
55
  Metasploit::Model::Search::Operator::Association.new(
56
- :attribute_operator => attribute_operator
56
+ :source_operator => source_operator
57
57
  )
58
58
  end
59
59
 
60
- it 'should visit Metasploit::Model::Search::Operator::Association#attribute_operator' do
60
+ it 'should visit Metasploit::Model::Search::Operator::Association#source_operator' do
61
61
  visitor.should_receive(:visit).with(node).and_call_original
62
- visitor.should_receive(:visit).with(attribute_operator)
62
+ visitor.should_receive(:visit).with(source_operator)
63
63
 
64
64
  visit
65
65
  end
66
66
 
67
- it 'should return visit of Metasploit::Model::Search::Operator::Association#attribute_operator' do
67
+ it 'should return visit of Metasploit::Model::Search::Operator::Association#source_operator' do
68
68
  visitor.should_receive(:visit).with(node).and_call_original
69
69
 
70
- visited = double('Attribute Operator Visited')
71
- visitor.stub(:visit).with(attribute_operator).and_return(visited)
70
+ visited = double('Source Operator Visited')
71
+ visitor.stub(:visit).with(source_operator).and_return(visited)
72
72
 
73
73
  visit.should == visited
74
74
  end
@@ -29,6 +29,58 @@ describe MetasploitDataModels::Search::Visitor::Includes do
29
29
  end
30
30
  end
31
31
 
32
+ context 'with Metasploit::Model::Search::Operation::Association' do
33
+ let(:association) {
34
+ :parent_association
35
+ }
36
+
37
+ let(:node) {
38
+ operator.operate_on('formatted_value')
39
+ }
40
+
41
+ let(:operator) {
42
+ Metasploit::Model::Search::Operator::Association.new(
43
+ association: association,
44
+ source_operator: source_operator
45
+ )
46
+ }
47
+
48
+ context '#source_operation' do
49
+ let(:attribute_operator) {
50
+ Metasploit::Model::Search::Operator::Attribute.new(
51
+ type: :string
52
+ )
53
+ }
54
+
55
+ context 'with Metasploit::Model::Search::Operation::Association' do
56
+ let(:source_operator) {
57
+ Metasploit::Model::Search::Operator::Association.new(
58
+ association: source_operator_association,
59
+ source_operator: attribute_operator
60
+ )
61
+ }
62
+
63
+ let(:source_operator_association) {
64
+ :child_association
65
+ }
66
+
67
+ it 'is [{ association => nested associations }]' do
68
+ expect(visit).to eq([{association => [source_operator_association]}])
69
+ end
70
+ end
71
+
72
+ context 'without Metasploit::Model::Search::Operation::Association' do
73
+ let(:source_operator) {
74
+ attribute_operator
75
+ }
76
+
77
+ it 'is [association]' do
78
+ expect(visit).to eq([association])
79
+ end
80
+ end
81
+ end
82
+ end
83
+
32
84
  operation_classes = [
33
85
  Metasploit::Model::Search::Operation::Boolean,
34
86
  Metasploit::Model::Search::Operation::Date,
@@ -60,8 +112,8 @@ describe MetasploitDataModels::Search::Visitor::Includes do
60
112
  )
61
113
  end
62
114
 
63
- it 'should include association' do
64
- visit.should include(association)
115
+ it 'is #association' do
116
+ expect(visit).to eq(association)
65
117
  end
66
118
  end
67
119
 
@@ -75,7 +75,9 @@ describe MetasploitDataModels::Search::Visitor::Joins do
75
75
  context 'without child joins' do
76
76
  let(:children) do
77
77
  Array.new(2) {
78
- Metasploit::Model::Search::Operator::Attribute.new
78
+ operator = Metasploit::Model::Search::Operator::Attribute.new(type: :string)
79
+
80
+ operator.operate_on('formatted_value')
79
81
  }
80
82
  end
81
83
 
@@ -87,20 +89,31 @@ describe MetasploitDataModels::Search::Visitor::Joins do
87
89
  FactoryGirl.generate :metasploit_model_search_operator_association_association
88
90
  end
89
91
 
92
+ let(:association_operation) {
93
+ association_operator.operate_on('formatted_value')
94
+ }
95
+
90
96
  let(:association_operator) do
97
+ source_operator = Metasploit::Model::Search::Operator::Attribute.new(type: :string)
98
+
91
99
  Metasploit::Model::Search::Operator::Association.new(
92
- association: association
100
+ association: association,
101
+ source_operator: source_operator
93
102
  )
94
103
  end
95
104
 
105
+ let(:attribute_operation) {
106
+ attribute_operator.operate_on('formatted_value')
107
+ }
108
+
96
109
  let(:attribute_operator) do
97
- Metasploit::Model::Search::Operator::Attribute.new
110
+ Metasploit::Model::Search::Operator::Attribute.new(type: :string)
98
111
  end
99
112
 
100
113
  let(:children) do
101
114
  [
102
- association_operator,
103
- attribute_operator
115
+ association_operation,
116
+ attribute_operation
104
117
  ]
105
118
  end
106
119
 
@@ -112,15 +125,22 @@ describe MetasploitDataModels::Search::Visitor::Joins do
112
125
  FactoryGirl.generate :metasploit_model_search_operator_association_association
113
126
  end
114
127
 
128
+ let(:association_operation) {
129
+ association_operator.operate_on('formatted_value')
130
+ }
131
+
115
132
  let(:association_operator) do
133
+ source_operator = Metasploit::Model::Search::Operator::Attribute.new(type: :string)
134
+
116
135
  Metasploit::Model::Search::Operator::Association.new(
117
- association: association
136
+ association: association,
137
+ source_operator: source_operator
118
138
  )
119
139
  end
120
140
 
121
141
  let(:children) do
122
142
  Array.new(2) {
123
- association_operator
143
+ association_operation
124
144
  }
125
145
  end
126
146
 
@@ -140,10 +160,19 @@ describe MetasploitDataModels::Search::Visitor::Joins do
140
160
  disjoint_associations[0, 1] + common_associations
141
161
  end
142
162
 
163
+ let(:first_association_operations) {
164
+ first_association_operators.map { |association_operator|
165
+ association_operator.operate_on('formatted_value')
166
+ }
167
+ }
168
+
143
169
  let(:first_association_operators) do
144
170
  first_associations.collect { |association|
171
+ source_operator = Metasploit::Model::Search::Operator::Attribute.new(type: :string)
172
+
145
173
  Metasploit::Model::Search::Operator::Association.new(
146
- association: association
174
+ association: association,
175
+ source_operator: source_operator
147
176
  )
148
177
  }
149
178
  end
@@ -152,16 +181,25 @@ describe MetasploitDataModels::Search::Visitor::Joins do
152
181
  disjoint_associations[1, 1] + common_associations
153
182
  end
154
183
 
184
+ let(:second_association_operations) {
185
+ second_association_operators.map { |association_operator|
186
+ association_operator.operate_on('formatted_value')
187
+ }
188
+ }
189
+
155
190
  let(:second_association_operators) do
156
191
  second_associations.collect { |association|
192
+ source_operator = Metasploit::Model::Search::Operator::Attribute.new(type: :string)
193
+
157
194
  Metasploit::Model::Search::Operator::Association.new(
158
- association: association
195
+ association: association,
196
+ source_operator: source_operator
159
197
  )
160
198
  }
161
199
  end
162
200
 
163
201
  let(:children) do
164
- [first_association_operators, second_association_operators].collect { |grandchildren|
202
+ [first_association_operations, second_association_operations].collect { |grandchildren|
165
203
  Metasploit::Model::Search::Group::Intersection.new(
166
204
  children: grandchildren
167
205
  )
@@ -208,6 +246,58 @@ describe MetasploitDataModels::Search::Visitor::Joins do
208
246
  end
209
247
  end
210
248
 
249
+ context 'with Metasploit::Model::Search::Operation::Association' do
250
+ let(:association) {
251
+ :parent_association
252
+ }
253
+
254
+ let(:node) {
255
+ operator.operate_on('formatted_value')
256
+ }
257
+
258
+ let(:operator) {
259
+ Metasploit::Model::Search::Operator::Association.new(
260
+ association: association,
261
+ source_operator: source_operator
262
+ )
263
+ }
264
+
265
+ context '#source_operation' do
266
+ let(:attribute_operator) {
267
+ Metasploit::Model::Search::Operator::Attribute.new(
268
+ type: :string
269
+ )
270
+ }
271
+
272
+ context 'with Metasploit::Model::Search::Operation::Association' do
273
+ let(:source_operator) {
274
+ Metasploit::Model::Search::Operator::Association.new(
275
+ association: source_operator_association,
276
+ source_operator: attribute_operator
277
+ )
278
+ }
279
+
280
+ let(:source_operator_association) {
281
+ :child_association
282
+ }
283
+
284
+ it 'is [{ association => nested associations }]' do
285
+ expect(visit).to eq([{association => [source_operator_association]}])
286
+ end
287
+ end
288
+
289
+ context 'without Metasploit::Model::Search::Operation::Association' do
290
+ let(:source_operator) {
291
+ attribute_operator
292
+ }
293
+
294
+ it 'is [association]' do
295
+ expect(visit).to eq([association])
296
+ end
297
+ end
298
+ end
299
+ end
300
+
211
301
  operation_classes = [
212
302
  Metasploit::Model::Search::Operation::Boolean,
213
303
  Metasploit::Model::Search::Operation::Date,
@@ -239,8 +329,8 @@ describe MetasploitDataModels::Search::Visitor::Joins do
239
329
  )
240
330
  end
241
331
 
242
- it 'should include association' do
243
- visit.should include(association)
332
+ it 'is #association' do
333
+ expect(visit).to eq(association)
244
334
  end
245
335
  end
246
336
 
@@ -175,11 +175,22 @@ describe MetasploitDataModels::Search::Visitor::Relation do
175
175
  let(:non_matching_host) {
176
176
  FactoryGirl.create(
177
177
  :mdm_host,
178
+ address: non_matching_host_address,
178
179
  name: non_matching_host_name,
179
180
  os_flavor: non_matching_host_os_flavor,
180
181
  os_name: non_matching_host_os_name,
181
182
  os_sp: non_matching_host_os_sp
182
- )
183
+ ).tap { |host|
184
+ FactoryGirl.create(
185
+ :mdm_host_tag,
186
+ host: host,
187
+ tag: non_matching_tag
188
+ )
189
+ }
190
+ }
191
+
192
+ let(:non_matching_host_address) {
193
+ '5.6.7.8'
183
194
  }
184
195
 
185
196
  let(:non_matching_host_name) {
@@ -214,6 +225,22 @@ describe MetasploitDataModels::Search::Visitor::Relation do
214
225
  'udp'
215
226
  }
216
227
 
228
+ let(:non_matching_tag) {
229
+ FactoryGirl.create(
230
+ :mdm_tag,
231
+ desc: non_matching_tag_desc,
232
+ name: non_matching_tag_name
233
+ )
234
+ }
235
+
236
+ let(:non_matching_tag_desc) {
237
+ 'Mdm::Tag#description b'
238
+ }
239
+
240
+ let(:non_matching_tag_name) {
241
+ 'mdm_tag_name.b'
242
+ }
243
+
217
244
  #
218
245
  # let!s
219
246
  #
@@ -323,11 +350,22 @@ describe MetasploitDataModels::Search::Visitor::Relation do
323
350
  let(:matching_host) {
324
351
  FactoryGirl.create(
325
352
  :mdm_host,
353
+ address: matching_host_address,
326
354
  name: matching_host_name,
327
355
  os_flavor: matching_host_os_flavor,
328
356
  os_name: matching_host_os_name,
329
357
  os_sp: matching_host_os_sp
330
- )
358
+ ).tap { |host|
359
+ FactoryGirl.create(
360
+ :mdm_host_tag,
361
+ host: host,
362
+ tag: matching_tag
363
+ )
364
+ }
365
+ }
366
+
367
+ let(:matching_host_address) {
368
+ '1.2.3.4'
331
369
  }
332
370
 
333
371
  let(:matching_host_name) {
@@ -362,6 +400,22 @@ describe MetasploitDataModels::Search::Visitor::Relation do
362
400
  'tcp'
363
401
  }
364
402
 
403
+ let(:matching_tag) {
404
+ FactoryGirl.create(
405
+ :mdm_tag,
406
+ desc: matching_tag_desc,
407
+ name: matching_tag_name
408
+ )
409
+ }
410
+
411
+ let(:matching_tag_desc) {
412
+ 'Mdm::Tag#description a'
413
+ }
414
+
415
+ let(:matching_tag_name) {
416
+ 'mdm_tag_name.a'
417
+ }
418
+
365
419
  #
366
420
  # let!s
367
421
  #
@@ -377,6 +431,42 @@ describe MetasploitDataModels::Search::Visitor::Relation do
377
431
  )
378
432
  }
379
433
 
434
+ context 'with host.address operator' do
435
+ let(:formatted) do
436
+ "host.address:#{formatted_address}"
437
+ end
438
+
439
+ context 'with CIDR' do
440
+ let(:formatted_address) {
441
+ '1.3.4.5/8'
442
+ }
443
+
444
+ it 'should find only matching record' do
445
+ expect(visit).to match_array([matching_record])
446
+ end
447
+ end
448
+
449
+ context 'with Range' do
450
+ let(:formatted_address) {
451
+ '1.1.1.1-5.6.7.7'
452
+ }
453
+
454
+ it 'should find only matching record' do
455
+ expect(visit).to match_array([matching_record])
456
+ end
457
+ end
458
+
459
+ context 'with single' do
460
+ let(:formatted_address) {
461
+ '1.2.3.4'
462
+ }
463
+
464
+ it 'should find only matching record' do
465
+ expect(visit).to match_array([matching_record])
466
+ end
467
+ end
468
+ end
469
+
380
470
  it_should_behave_like 'MetasploitDataModels::Search::Visitor::Relation#visit matching record',
381
471
  association: :host,
382
472
  attribute: :name
@@ -441,6 +531,18 @@ describe MetasploitDataModels::Search::Visitor::Relation do
441
531
  association: :host,
442
532
  attribute: :os_sp
443
533
 
534
+ it_should_behave_like 'MetasploitDataModels::Search::Visitor::Relation#visit matching record',
535
+ association: {
536
+ host: :tags
537
+ },
538
+ attribute: :desc
539
+
540
+ it_should_behave_like 'MetasploitDataModels::Search::Visitor::Relation#visit matching record',
541
+ association: {
542
+ host: :tags
543
+ },
544
+ attribute: :name
545
+
444
546
  it_should_behave_like 'MetasploitDataModels::Search::Visitor::Relation#visit matching record',
445
547
  attribute: :info
446
548
 
@@ -453,11 +555,16 @@ describe MetasploitDataModels::Search::Visitor::Relation do
453
555
  context 'with all operators' do
454
556
  let(:formatted) {
455
557
  %Q{
558
+ host.address:1.3.4.5/8
559
+ host.address:1.1.1.1-5.6.7.7
560
+ host.address:1.2.3.4
456
561
  host.name:#{matching_host_name}
457
562
  host.os:"#{matching_host_os_name} #{matching_host_os_flavor} #{matching_host_os_sp}"
458
563
  host.os_flavor:#{matching_host_os_flavor}
459
564
  host.os_name:#{matching_host_os_name}
460
565
  host.os_sp:#{matching_host_os_sp}
566
+ host.tags.desc:"#{matching_tag_desc}"
567
+ host.tags.name:#{matching_tag_name}
461
568
  name:#{matching_name}
462
569
  port:#{matching_port}
463
570
  proto:#{matching_proto}
@@ -4,30 +4,43 @@ shared_examples_for 'MetasploitDataModels::Search::Visitor::Relation#visit match
4
4
  attribute = options.fetch(:attribute)
5
5
  association = options[:association]
6
6
 
7
- if association
8
- formatted_operator = "#{association}.#{attribute}"
9
- else
10
- formatted_operator = attribute.to_s
7
+ def self.nested_hash_to_array(association)
8
+ case association
9
+ when Hash
10
+ hash = association
11
+ keys = hash.keys
12
+
13
+ unless keys.length == 1
14
+ raise ArgumentError, 'Only single key Hashes are allowed to nest associations'
15
+ end
16
+
17
+ parent_association = keys.first
18
+ child_association = hash[parent_association]
19
+
20
+ [parent_association, *nested_hash_to_array(child_association)]
21
+ when Symbol
22
+ [association]
23
+ when nil
24
+ []
25
+ else
26
+ raise TypeError, "Cannot convert #{association.class} (#{association}) to array"
27
+ end
11
28
  end
12
29
 
30
+ associations = nested_hash_to_array(association)
31
+ messages = [*associations, attribute]
32
+ formatted_operator = messages.map(&:to_s).join('.')
33
+
13
34
  context "with #{formatted_operator}" do
14
35
  let(:formatted) do
15
36
  "#{formatted_operator}:\"#{value}\""
16
37
  end
17
38
 
18
- if association
19
- let(:associated) do
20
- # wrap in array so single and plural associations can be handled the same.
21
- Array.wrap(matching_record.send(association)).first
22
- end
23
-
24
- let(:value) do
25
- associated.send(attribute)
26
- end
27
- else
28
- let(:value) do
29
- matching_record.send(attribute)
30
- end
39
+ let(:value) do
40
+ messages.inject(matching_record) { |instance, message|
41
+ # wrap in array so singel and plural associatins can be handled the same
42
+ Array.wrap(instance.send(message)).first
43
+ }
31
44
  end
32
45
 
33
46
  it 'should find only matching record' do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metasploit_data_models
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.19.3
4
+ version: 0.19.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Huckins
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2014-07-23 00:00:00.000000000 Z
14
+ date: 2014-07-29 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: rake
@@ -107,22 +107,16 @@ dependencies:
107
107
  name: metasploit-model
108
108
  requirement: !ruby/object:Gem::Requirement
109
109
  requirements:
110
- - - ! '>='
111
- - !ruby/object:Gem::Version
112
- version: 0.25.1
113
- - - <
110
+ - - ~>
114
111
  - !ruby/object:Gem::Version
115
- version: '0.26'
112
+ version: 0.26.1
116
113
  type: :runtime
117
114
  prerelease: false
118
115
  version_requirements: !ruby/object:Gem::Requirement
119
116
  requirements:
120
- - - ! '>='
121
- - !ruby/object:Gem::Version
122
- version: 0.25.1
123
- - - <
117
+ - - ~>
124
118
  - !ruby/object:Gem::Version
125
- version: '0.26'
119
+ version: 0.26.1
126
120
  - !ruby/object:Gem::Dependency
127
121
  name: arel-helpers
128
122
  requirement: !ruby/object:Gem::Requirement