metasploit-model 0.25.7 → 0.26.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (26) hide show
  1. checksums.yaml +8 -8
  2. data/app/models/metasploit/model/search/operation/association.rb +57 -0
  3. data/app/models/metasploit/model/search/operator/association.rb +24 -14
  4. data/app/models/metasploit/model/search/operator/base.rb +19 -3
  5. data/app/models/metasploit/model/search/operator/single.rb +21 -1
  6. data/app/models/metasploit/model/search/query.rb +20 -1
  7. data/lib/metasploit/model/association/tree.rb +130 -0
  8. data/lib/metasploit/model/search.rb +61 -27
  9. data/lib/metasploit/model/search/association.rb +152 -8
  10. data/lib/metasploit/model/search/attribute.rb +112 -22
  11. data/lib/metasploit/model/search/operator.rb +53 -1
  12. data/lib/metasploit/model/search/operator/help.rb +39 -1
  13. data/lib/metasploit/model/search/with.rb +44 -1
  14. data/lib/metasploit/model/version.rb +2 -2
  15. data/spec/app/models/metasploit/model/search/operation/association_spec.rb +67 -0
  16. data/spec/app/models/metasploit/model/search/operator/association_spec.rb +76 -76
  17. data/spec/app/models/metasploit/model/search/operator/deprecated/author_spec.rb +54 -18
  18. data/spec/app/models/metasploit/model/search/operator/deprecated/authority_spec.rb +20 -8
  19. data/spec/app/models/metasploit/model/search/operator/deprecated/platform_spec.rb +20 -8
  20. data/spec/app/models/metasploit/model/search/operator/deprecated/ref_spec.rb +86 -26
  21. data/spec/app/models/metasploit/model/search/operator/deprecated/text_spec.rb +63 -21
  22. data/spec/lib/metasploit/model/search/association/tree_spec.rb +385 -0
  23. data/spec/lib/metasploit/model/search/association_spec.rb +99 -10
  24. data/spec/lib/metasploit/model/search_spec.rb +48 -107
  25. data/spec/support/shared/examples/search/query/metasploit/model/search/operator/deprecated/authority.rb +19 -7
  26. metadata +7 -1
@@ -1,29 +1,173 @@
1
1
  module Metasploit
2
2
  module Model
3
3
  module Search
4
- # Registers associations that can be searched.
4
+ # Use search operators registered on an associated class using
5
+ # {Metasploit::Model::Search::Attribute::ClassMethods#search_attribute},
6
+ # {Metasploit::Model::Search::With::ClassMethods#search_with}.
7
+ #
8
+ # Searchable associations are declared explicitly so that associations cycles can be avoided and the search
9
+ # interface can be tuned for clarity and complexity.
10
+ #
11
+ # # Testing
12
+ #
13
+ # {ClassMethods#search_association} calls can be tested with the 'search_association' shared example. First,
14
+ # ensure the shared examples from `metasploit-model` are required in your `spec_helper.rb`:
15
+ #
16
+ # # spec/spec_helper.rb
17
+ # support_glob = Metasploit::Model::Engine.root.join('spec', 'support', '**', '*.rb')
18
+ #
19
+ # Dir.glob(support_glob) do |path|
20
+ # require path
21
+ # end
22
+ #
23
+ # In the spec for the `Class` that called `search_association`, use the 'search_association' shared example:
24
+ #
25
+ # # spec/app/models/my_class_spec.rb
26
+ # require 'spec_helper'
27
+ #
28
+ # describe MyClass do
29
+ # context 'search' do
30
+ # context 'associations' do
31
+ # it_should_be_like 'search_association', :association_name
32
+ # end
33
+ # end
34
+ # end
35
+ #
36
+ # @example Search near and far associations
37
+ # class Root
38
+ # include Metasploit::Model::Association
39
+ # include Metasploit::Model::Search
40
+ #
41
+ # #
42
+ # # Associations
43
+ # #
44
+ #
45
+ # association :children,
46
+ # class_name: 'Child'
47
+ #
48
+ # #
49
+ # # Search
50
+ # #
51
+ #
52
+ # search_association children: :grandchildren
53
+ # end
54
+ #
55
+ # class Child
56
+ # include Metasploit::Model::Association
57
+ # include Metasploit::Model::Search
58
+ #
59
+ # #
60
+ # # Associations
61
+ # #
62
+ #
63
+ # association :grandchildren,
64
+ # class_name: 'Grandchild'
65
+ #
66
+ # #
67
+ # # Search
68
+ # #
69
+ #
70
+ # search_attribute :name,
71
+ # type: :string
72
+ # end
73
+ #
74
+ # class Grandchild
75
+ # include Metasploit::Model::Search
76
+ #
77
+ # search_attribute :age,
78
+ # type: :integer
79
+ # end
80
+ #
81
+ # Root.search_operator_by_name.each_value
82
+ # # :'children.name'
83
+ # # :'children.grandchildren.age'
84
+ #
85
+ # Child.search_operator_by_name.each_value
86
+ # # :name
87
+ # # @note ``:'grandchildren.age'`` is not in `Child`'s operators because it didn't declare
88
+ # # `search_association :grandchildren`, only `Root` did.
89
+ #
90
+ # Grandchild.search_operator_name
91
+ # # :age
92
+ #
5
93
  module Association
6
94
  extend ActiveSupport::Concern
7
95
 
8
96
  # Adds {#search_association} DSL to make {Metasploit::Model::Search::Operator::Association association search
9
97
  # operators}.
10
98
  module ClassMethods
99
+ # @note Use {#search_associations} to declare multiple associations or a tree of far associations as
100
+ # searchable.
101
+ #
11
102
  # Registers association for search.
12
103
  #
104
+ # @example a single searchable association
105
+ # search_association :children
106
+ #
13
107
  # @param association [#to_sym] name of association to search.
14
108
  # @return [void]
109
+ # @see #search_associations
15
110
  def search_association(association)
16
- search_association_set.add(association.to_sym)
111
+ search_association_tree[association.to_sym] ||= nil
17
112
  end
18
113
 
19
- # Set of all associations that are searchable.
114
+ # Registers a tree of near and far associations for search. When a tree is used, all intermediate association
115
+ # on the paths are used, so `search_association children: :grandchildren` makes both `children.granchildren`
116
+ # *and* `children` as search operator prefixes.
117
+ #
118
+ # @example a single search association
119
+ # search_associations :children
120
+ #
121
+ # @example multiple near associations
122
+ # search_associations :first,
123
+ # :second
124
+ #
125
+ # @example far association
126
+ # search_associations near: :far
127
+ #
128
+ # @example multiple far associations
129
+ # search_associations near: [
130
+ # :first_far,
131
+ # :second_far
132
+ # ]
133
+ #
134
+ # @example mix of near and far associations
135
+ # # Keep associations in order by near association names by mixing Symbols and Hash{Symbol => Object}
136
+ # search_associations :apple,
137
+ # {
138
+ # banana: :peel
139
+ # },
140
+ # :cucumber
141
+ #
20
142
  #
21
- # @example Adding association to search
22
- # search_association :things
143
+ # @param associations [Array<Array, Hash, Symbol>, Hash, Symbol]
144
+ # @return [void]
145
+ # @see search_association
146
+ def search_associations(*associations)
147
+ expanded_associations = Metasploit::Model::Association::Tree.expand(associations)
148
+
149
+ @search_association_tree = Metasploit::Model::Association::Tree.merge(
150
+ search_association_tree,
151
+ expanded_associations
152
+ )
153
+ end
154
+
155
+ # The association operators for the searchable associations declared with {#search_association} and
156
+ # {#search_associations}.
157
+ #
158
+ # @return (see Metasploit::Model::Association::Tree.operators)
159
+ def search_association_operators
160
+ @search_association_operators ||= Metasploit::Model::Association::Tree.operators(
161
+ search_association_tree,
162
+ class: self
163
+ )
164
+ end
165
+
166
+ # Tree of associations that are searchable.
23
167
  #
24
- # @return [Set<Symbol>]
25
- def search_association_set
26
- @search_association_set ||= Set.new
168
+ # @return [Hash{Symbol => Hash,nil}]
169
+ def search_association_tree
170
+ @search_association_tree ||= {}
27
171
  end
28
172
  end
29
173
  end
@@ -1,7 +1,117 @@
1
1
  module Metasploit
2
2
  module Model
3
3
  module Search
4
- # Registers attributes that can be searched.
4
+ # Registers attributes that can be searched. Attributes must be declared to be searchable as a type from
5
+ # {Metasploit::Model::Search::Operator::Attribute::TYPES}. The type of the attribute is used to select a
6
+ # type-specific {Metasploit::Model::Search::Operation}, which will validate the
7
+ # {Metasploit::Model::Search::Operation::Base#value} is of the valid type.
8
+ #
9
+ # # Set attributes
10
+ #
11
+ # Search attributes declared as having an integer set or string set type integer or string set require a
12
+ # `<attribute>_set` method to be defined on the `Class`, which returns the set of allowed values for the search
13
+ # attribute's operation. This method will be called, indirectly by
14
+ # {Metasploit::Model::Search::Operation::Set::Integer}'s and {Metasploit::Model::Search::Operation::Set::String}'s
15
+ # validations.
16
+ #
17
+ # # Help
18
+ #
19
+ # The help for each operator is uses the `I18n` system, so the help for an attribute operator on a given class can
20
+ # added to `config/locales/<lang>.yml`. The scope of the lookup, under the language key is the `Class`'s
21
+ # `i18n_scope`, which is `metasploit.model` if the `Class` includes {Metasploit::Model::Translation} or
22
+ # `active_record` for `ActiveRecord::Base` subclasses. Under the `i18n_scope`, any `Module#ancestor`'s
23
+ # `model_name.i18n_key` can be used to look up the help for an attribute's operator. This allows for super
24
+ # classes or mixins to define the search operator help for subclasses.
25
+ #
26
+ # # config/locales/<lang>.yml
27
+ # <lang>:
28
+ # <Class#i18n_scope>:
29
+ # ancestors:
30
+ # <ancestor.model_name.i18n_key>:
31
+ # search:
32
+ # operator:
33
+ # names:
34
+ # <attribute>:
35
+ # help: "The attribute on the class"
36
+ #
37
+ # # Testing
38
+ #
39
+ # {ClassMethods#search_attribute} calls can be tested with the 'search_attribute' shared example. First, ensure
40
+ # the shared examples from `metasploit-model` are required in your `spec_helper.rb`:
41
+ #
42
+ # # spec/spec_helper.rb
43
+ # support_glob = Metasploit::Model::Engine.root.join('spec', 'support', '**', '*.rb')
44
+ #
45
+ # Dir.glob(support_glob) do |path|
46
+ # require path
47
+ # end
48
+ #
49
+ # In the spec for the `Class` that called `search_attribute`, use the 'search_attribute' shared example by
50
+ # passing that arguments passed to {ClassMethods#search_attribute}.
51
+ #
52
+ # # spec/app/models/my_class_spec.rb
53
+ # require 'spec_helper'
54
+ #
55
+ # describe MyClass do
56
+ # context 'search' do
57
+ # context 'attributes' do
58
+ # it_should_behave_like 'search_attribute',
59
+ # type: {
60
+ # set: :string
61
+ # }
62
+ # end
63
+ # end
64
+ # end
65
+ #
66
+ # @example search an attribute for `true` or `false`
67
+ # search_attribute :flag,
68
+ # type: :boolean
69
+ #
70
+ # @example search an attribute for an integer
71
+ # search_attribute :age,
72
+ # type: :integer
73
+ #
74
+ # @example search an attribute for a restricted set of integers
75
+ # #
76
+ # # Search
77
+ # #
78
+ #
79
+ # search_attribute :bits,
80
+ # set: :integer
81
+ #
82
+ # #
83
+ # # Class Methods
84
+ # #
85
+ #
86
+ # # Return set of allowed values for {#bits} search.
87
+ # #
88
+ # # @return [Set<Integer>]
89
+ # def self.bits_set
90
+ # @bits_set ||= Set.new([32, 64])
91
+ # end
92
+ #
93
+ # @example search an attribute for a restricted set of strings
94
+ # #
95
+ # # Search
96
+ # #
97
+ #
98
+ # search_attribute :endianness,
99
+ # set: :string
100
+ #
101
+ # #
102
+ # # Class Methods
103
+ # #
104
+ #
105
+ # # Return set of allowed values for {#endianness} search.
106
+ # #
107
+ # # @return [Set<String>]
108
+ # def self.endianness_set
109
+ # @endianness_set ||= Set.new(['big', 'litte'])
110
+ # end
111
+ #
112
+ # @example search an attribute by substring (case-insensitve LIKE)
113
+ # search_attribute :description,
114
+ # type: :string
5
115
  module Attribute
6
116
  extend ActiveSupport::Concern
7
117
 
@@ -10,27 +120,7 @@ module Metasploit
10
120
  # Adds {#search_attribute} DSL to make {Metasploit::Model::Search::Operator::Attribute attribute search
11
121
  # operators}.
12
122
  module ClassMethods
13
- # Registers attribute for search. Help for the operator supports i18n.
14
- #
15
- # @example defining help
16
- # # lib/metasploit/model/module/instance.rb
17
- # module Metasploit::Model::Module::Instance
18
- # include Metasploit::Model::Search
19
- #
20
- # included do
21
- # search_attribute :description, :type => :string
22
- # end
23
- # end
24
- #
25
- # # config/locales/en.yml
26
- # en:
27
- # metasploit:
28
- # model:
29
- # module:
30
- # instance:
31
- # search_attribute:
32
- # description:
33
- # help: "A long, paragraph description of what the module does."
123
+ # {include:Metasploit::Model::Search::Attribute}
34
124
  #
35
125
  # @param attribute [#to_sym] name of attribute to search.
36
126
  # @param options [Hash{Symbol => String}]
@@ -1,7 +1,59 @@
1
1
  module Metasploit
2
2
  module Model
3
3
  module Search
4
- # Namespace for search operators
4
+ # # Declaring operator classes
5
+ #
6
+ # ## Interface
7
+ #
8
+ # Operators do not need to subclass any specific superclass, but they are expected to define certain methods.
9
+ #
10
+ # class MyOperator
11
+ # #
12
+ # # Instance Methods
13
+ # #
14
+ #
15
+ # # @param klass [Class] The klass on which `search_with` was called.
16
+ # def initialize(attributes={})
17
+ # # ...
18
+ # end
19
+ #
20
+ # # Description of what this operator searches for.
21
+ # #
22
+ # # @return [String]
23
+ # def help
24
+ # # ...
25
+ # end
26
+ #
27
+ # # Name of this operator. The name of the operator is matched to the string before the ':' in a formatted
28
+ # # operation.
29
+ # #
30
+ # # @return [Symbol]
31
+ # def name
32
+ # # ...
33
+ # end
34
+ #
35
+ # # Creates a one or more operations based on `formatted_value`.
36
+ # #
37
+ # # @return [#operator, Array<#operator>] Operation with this operator as the operation's `operator`.
38
+ # def operate_on(formatted_value)
39
+ # # ...
40
+ # end
41
+ # end
42
+ #
43
+ # ## Help
44
+ #
45
+ # Instead of having define your own `#help` method for your operator `Class`, you can `include`
46
+ # {Metasploit::Model::Search::Operator::Help}.
47
+ #
48
+ # {include:Metasploit::Model::Search::Operator::Help}
49
+ #
50
+ # ## {Metasploit::Model::Search::Operator::Base}
51
+ #
52
+ # {include:Metasploit::Model::Search::Operator::Base}
53
+ #
54
+ # ## {Metasploit::Model::Search::Operator::Single}
55
+ #
56
+ # {include:Metasploit::Model::Search::Operator::Single}
5
57
  module Operator
6
58
 
7
59
  end
@@ -2,7 +2,45 @@ module Metasploit
2
2
  module Model
3
3
  module Search
4
4
  module Operator
5
- # Methods to lookup help text for an operator with a given `#name` registered to a given `#klass`.
5
+ # This allows the help to be looked up using `I18n`, and for the
6
+ # help to be customized based on the following criteria:
7
+ #
8
+ # `klass` on which the operator is declared, including any `Module#ancestors` and the operator `name`
9
+ #
10
+ # # config/locales/<lang>.yml
11
+ # <lang>:
12
+ # <klass.i18n_scope>:
13
+ # ancestors:
14
+ # <klass_ancestor.model_name.i18n_key>:
15
+ # search:
16
+ # operator:
17
+ # names:
18
+ # <name>:
19
+ # help: "Help for searching <name> on <klass>"
20
+ #
21
+ # `class` of the operator, including any `Module#ancestors` and the operator `name`
22
+ #
23
+ # # config/locales/<lang>.yml
24
+ # <lang>:
25
+ # <operator.class.i18n_scope>:
26
+ # search:
27
+ # operator:
28
+ # ancestors:
29
+ # <operator_class_ancestor.model_name.i18n_key>:
30
+ # <name>:
31
+ # help: "Help for searching <name> using <operator.class>"
32
+ #
33
+ # `class` of the operator, including any `Module#ancestors` without the operator `name`
34
+ #
35
+ # # config/locales/<lang>.yml
36
+ # <lang>:
37
+ # <operator.class.i18n_scope>:
38
+ # search:
39
+ # operator:
40
+ # ancestors:
41
+ # <operator_class_ancestor.model_name.i18n_key>:
42
+ # help: "Help for searching using <operator.class>"
43
+ #
6
44
  module Help
7
45
  # @note This uses I18n.translate along with {Metasploit::Model::Translation#search_i18n_scope},
8
46
  # the value is not cached to support changing the I18n.locale and getting the correct help message for that
@@ -1,7 +1,50 @@
1
1
  module Metasploit
2
2
  module Model
3
3
  module Search
4
- # Generalizes operators from attributes to anything directly registered as an operator on a class.
4
+ # Generalizes {Metasploit::Model::Search::Attribute operators from attributes} to anything directly registered as
5
+ # an operator on a class.
6
+ #
7
+ # {include:Metasploit::Model::Search::Operator}
8
+ #
9
+ # # Testing
10
+ #
11
+ # {ClassMethods#search_with} calls can be tested with the 'search_with' shared example. First, ensure
12
+ # the shared examples from `metasploit-model` are required in your `spec_helper.rb`:
13
+ #
14
+ # # spec/spec_helper.rb
15
+ # support_glob = Metasploit::Model::Engine.root.join('spec', 'support', '**', '*.rb')
16
+ #
17
+ # Dir.glob(support_glob) do |path|
18
+ # require path
19
+ # end
20
+ #
21
+ # In the spec fo the `Class` that called `search_with`, use the 'search_with' shared example by passing the
22
+ # arguments passed to {ClassMethods#search_attribute}.
23
+ #
24
+ # # app/models/my_class.rb
25
+ # class MyClass
26
+ # include Metasploit::Model::Search
27
+ #
28
+ # #
29
+ # # Search
30
+ # #
31
+ #
32
+ # search_with MyOperatorClass,
33
+ # foo: :bar
34
+ # end
35
+ #
36
+ # # spec/app/models/my_class_spec.rb
37
+ # require 'spec_helper'
38
+ #
39
+ # describe MyClass do
40
+ # context 'search' do
41
+ # context 'attributes' do
42
+ # it_should_behave_like 'search_with',
43
+ # MyOperatorClass,
44
+ # foo: :bar
45
+ # end
46
+ # end
47
+ # end
5
48
  module With
6
49
  extend ActiveSupport::Concern
7
50