stratagem 0.1.8 → 0.1.9
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.
- data/Manifest +16 -18
- data/Rakefile +3 -3
- data/bin/stratagem +54 -6
- data/generators/stratagem/stratagem_generator.rb +26 -0
- data/lib/generators/stratagem/install/USAGE +0 -0
- data/lib/generators/stratagem/install/install_base.rb +35 -0
- data/lib/generators/stratagem/install/install_generator.rb +24 -0
- data/lib/stratagem.rb +87 -57
- data/lib/stratagem/authentication.rb +2 -2
- data/lib/stratagem/auto_mock/aquifer.rb +6 -1
- data/lib/stratagem/auto_mock/factory.rb +2 -2
- data/lib/stratagem/client.rb +1 -1
- data/lib/stratagem/crawler.rb +2 -0
- data/lib/stratagem/crawler/authentication.rb +10 -9
- data/lib/stratagem/crawler/parameter_resolver.rb +83 -0
- data/lib/stratagem/crawler/route_invoker.rb +187 -0
- data/lib/stratagem/crawler/session.rb +23 -251
- data/lib/stratagem/crawler/site_model.rb +18 -16
- data/lib/stratagem/framework_extensions.rb +12 -1
- data/lib/stratagem/framework_extensions/method_invocation.rb +50 -0
- data/lib/stratagem/framework_extensions/models/adapters/active_model/detect.rb +1 -1
- data/lib/stratagem/framework_extensions/models/adapters/active_model/extensions.rb +20 -11
- data/lib/stratagem/framework_extensions/models/adapters/active_model/metadata.rb +7 -3
- data/lib/stratagem/framework_extensions/models/adapters/active_model/tracing.rb +11 -9
- data/lib/stratagem/framework_extensions/models/adapters/friendly_id/detect.rb +12 -0
- data/lib/stratagem/framework_extensions/models/adapters/friendly_id/extensions.rb +0 -0
- data/lib/stratagem/framework_extensions/models/adapters/friendly_id/metadata.rb +21 -0
- data/lib/stratagem/framework_extensions/models/adapters/friendly_id/tracing.rb +4 -0
- data/lib/stratagem/framework_extensions/models/annotations.rb +1 -24
- data/lib/stratagem/framework_extensions/models/tracing.rb +9 -3
- data/lib/stratagem/framework_extensions/rails.rb +0 -6
- data/lib/stratagem/framework_extensions/{controllers → rails2}/action_controller.rb +0 -0
- data/lib/stratagem/framework_extensions/{controllers → rails2}/action_mailer.rb +0 -0
- data/lib/stratagem/framework_extensions/rails3/parameters.rb +14 -0
- data/lib/stratagem/interface/browser.rb +3 -1
- data/lib/stratagem/model/application.rb +6 -6
- data/lib/stratagem/model/components/controller.rb +17 -63
- data/lib/stratagem/model/components/model.rb +33 -33
- data/lib/stratagem/model/components/reference.rb +8 -4
- data/lib/stratagem/model/components/route.rb +40 -14
- data/lib/stratagem/model/components/view.rb +1 -1
- data/lib/stratagem/model_builder.rb +71 -42
- data/lib/stratagem/site_crawler.rb +1 -1
- data/lib/stratagem/snapshot.rb +0 -1
- data/stratagem.gemspec +10 -7
- data/templates/install/environments/stratagem.rb.erb +16 -0
- data/templates/install/tasks/stratagem.rake +18 -0
- metadata +57 -40
- data/lib/stratagem/framework_extensions/controllers.rb +0 -5
- data/lib/stratagem/scan/checks/filter_parameter_logging.rb +0 -6
- data/lib/stratagem/scan/checks/mongo_mapper/base.rb +0 -19
- data/lib/stratagem/scan/checks/mongo_mapper/foreign_keys_exposed.rb +0 -32
- data/lib/stratagem/scan/checks/routes.rb +0 -16
- data/lib/tasks/_old_stratagem.rake +0 -99
- data/spec/model/component_spec.rb +0 -43
- data/spec/model/components/view_spec.rb +0 -43
- data/spec/model/test_spec.rb +0 -10
- data/spec/samples/404.html.erb +0 -30
- data/spec/samples/_form.html.erb +0 -8
- data/spec/samples/index.html.erb +0 -77
- data/spec/samples/sample_model.rb +0 -5
- data/spec/samples/signup.html.erb +0 -14
- data/spec/scan/checks/email_address_spec.rb +0 -24
- data/spec/scan/checks/error_pages_spec.rb +0 -22
@@ -29,8 +29,8 @@ module Stratagem::Crawler
|
|
29
29
|
self.edges << Edge.new(from,to,type)
|
30
30
|
end
|
31
31
|
|
32
|
-
def add(route, response, invocations=[], model_changes={}, &block)
|
33
|
-
page = Page.new(self, response, invocations, model_changes, &block)
|
32
|
+
def add(route, request, response, invocations=[], model_changes={}, &block)
|
33
|
+
page = Page.new(self, request, response, invocations, model_changes, &block)
|
34
34
|
self.pages << page
|
35
35
|
page
|
36
36
|
end
|
@@ -59,7 +59,7 @@ module Stratagem::Crawler
|
|
59
59
|
{
|
60
60
|
:from => from.object_id,
|
61
61
|
:to => to.object_id,
|
62
|
-
:
|
62
|
+
:relation_type => type
|
63
63
|
}
|
64
64
|
end
|
65
65
|
end
|
@@ -75,36 +75,38 @@ module Stratagem::Crawler
|
|
75
75
|
attr_accessor :redirected_to
|
76
76
|
attr_accessor :document
|
77
77
|
|
78
|
-
def initialize(site_model, response, invocations, model_changes, &block)
|
78
|
+
def initialize(site_model, request, response, invocations, model_changes, &block)
|
79
79
|
@site_model = site_model
|
80
80
|
@invocations = invocations
|
81
81
|
@model_changes = model_changes
|
82
|
-
init(response, &block)
|
82
|
+
init(request, response, &block)
|
83
83
|
end
|
84
84
|
|
85
85
|
def route
|
86
|
-
Stratagem::Model::Application.instance.routes.recognize(self)
|
86
|
+
@route ||= Stratagem::Model::Application.instance.routes.recognize(self)
|
87
87
|
end
|
88
88
|
|
89
89
|
def export
|
90
|
-
{
|
90
|
+
h = {
|
91
91
|
:external_id => self.object_id,
|
92
92
|
:url => url,
|
93
93
|
:path => path,
|
94
|
-
:
|
94
|
+
:request_method => method,
|
95
95
|
:redirected_to_page_external_id => redirected_to ? redirected_to.object_id : nil,
|
96
|
-
:route_external_id => route.object_id,
|
96
|
+
:route_external_id => route ? route.object_id : nil,
|
97
97
|
:references => @invocations.map {|i| i.to_reference.export },
|
98
98
|
:model_changes => Hash[@model_changes.map {|model,changes| [model.object_id, changes] }].to_json,
|
99
|
-
:parameters =>
|
99
|
+
:parameters => @request.parameters.to_json
|
100
100
|
}
|
101
|
+
h
|
101
102
|
end
|
102
103
|
|
103
|
-
def init(response, &block)
|
104
|
+
def init(request, response, &block)
|
105
|
+
@request = request.clone
|
104
106
|
@response = response.clone
|
105
|
-
@url =
|
106
|
-
@path =
|
107
|
-
@method =
|
107
|
+
@url = request.url
|
108
|
+
@path = request.path
|
109
|
+
@method = request.method
|
108
110
|
@document = Nokogiri::HTML(response.body)
|
109
111
|
self.redirected_to = block.call(response.redirect_url) if response.redirect?
|
110
112
|
end
|
@@ -112,8 +114,8 @@ module Stratagem::Crawler
|
|
112
114
|
def reload(&block)
|
113
115
|
# TODO - should support all the verbs and params, but
|
114
116
|
# hack together for now to reload the authenticity token
|
115
|
-
response = yield url
|
116
|
-
init(response) {|redirected_to| }
|
117
|
+
request,response = yield url
|
118
|
+
init(request, response) {|redirected_to| }
|
117
119
|
end
|
118
120
|
|
119
121
|
def redirected?
|
@@ -1,6 +1,17 @@
|
|
1
1
|
module Stratagem::ApplicationExtensions; end
|
2
2
|
|
3
3
|
require 'stratagem/framework_extensions/rails'
|
4
|
-
require 'stratagem/framework_extensions/
|
4
|
+
require 'stratagem/framework_extensions/method_invocation'
|
5
5
|
require 'stratagem/framework_extensions/models'
|
6
6
|
|
7
|
+
if (Stratagem.rails_3?)
|
8
|
+
require 'stratagem/framework_extensions/rails3/parameters'
|
9
|
+
elsif (Stratagem.rails_2?)
|
10
|
+
require 'stratagem/framework_extensions/rails2/action_controller'
|
11
|
+
require 'stratagem/framework_extensions/rails2/action_mailer'
|
12
|
+
else
|
13
|
+
raise "Unsupported Rails version #{Stratagem.rails_version}"
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Stratagem::ApplicationExtensions
|
2
|
+
class MethodInvocation
|
3
|
+
attr_accessor :method, :controller_path, :controller_action, :line_number, :model_instance, :model_class, :stack_trace, :args, :type
|
4
|
+
|
5
|
+
EQUALITY_ATTRS = [:method, :controller_path, :controller_action, :line_number, :model_class]
|
6
|
+
|
7
|
+
# TODO - refactor, ugly constructor is a result of quick port from Struct
|
8
|
+
def initialize(*args)
|
9
|
+
arg_keys = [:method, :controller_path, :controller_action, :line_number, :model_instance, :model_class, :stack_trace, :args, :type]
|
10
|
+
args.each_with_index do |val,i|
|
11
|
+
self.send("#{arg_keys[i].to_s}=", val)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def <=>(other)
|
16
|
+
e = self.==(other)
|
17
|
+
e ? 0 : 1
|
18
|
+
end
|
19
|
+
|
20
|
+
def ==(other)
|
21
|
+
eql?(other)
|
22
|
+
end
|
23
|
+
|
24
|
+
# override so that uniq works properly
|
25
|
+
def eql?(other)
|
26
|
+
EQUALITY_ATTRS.find {|key|
|
27
|
+
(self.send(key) != other.send(key))
|
28
|
+
}.nil?
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_reference
|
32
|
+
app = Stratagem::Model::Application.instance
|
33
|
+
model = model_class ? app.models.find {|model| model.klass == model_class } : nil
|
34
|
+
controller = controller_path ? app.controllers.find {|controller| controller.path == controller_path } : nil
|
35
|
+
Stratagem::Model::Component::Reference.new(
|
36
|
+
:from_component => controller,
|
37
|
+
:to_component => model,
|
38
|
+
:function => controller_action,
|
39
|
+
:request_method => method,
|
40
|
+
:line_number => line_number,
|
41
|
+
:reference_type => type,
|
42
|
+
:stack_trace => stack_trace
|
43
|
+
)
|
44
|
+
end
|
45
|
+
|
46
|
+
def print
|
47
|
+
puts "#{controller_path}.#{controller_action}:#{line_number} -> #{model_class.name}.#{method}"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module Stratagem::ApplicationExtensions::Models::Adapters::
|
1
|
+
module Stratagem::ApplicationExtensions::Models::Adapters::ActiveRecord
|
2
2
|
class Detect < Stratagem::ApplicationExtensions::Models::Detect
|
3
3
|
def self.supports?(model)
|
4
4
|
model.ancestors.include?(ActiveRecord::Base)
|
@@ -17,18 +17,27 @@ class ActiveRecord::Base
|
|
17
17
|
|
18
18
|
end
|
19
19
|
|
20
|
-
|
20
|
+
class ActiveRecord::Base #Validations::ClassMethods
|
21
21
|
@@removed_validators = []
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
22
|
+
#
|
23
|
+
# instance_methods.each do |m|
|
24
|
+
# if (m =~ /^validates_/) && (m !~ /validates_each/)
|
25
|
+
# alias_method "old_#{m}", m
|
26
|
+
# undef_method m
|
27
|
+
# puts "removing validator #{m}"
|
28
|
+
# @@removed_validators << m.to_sym
|
29
|
+
#
|
30
|
+
#
|
31
|
+
# new_method = %Q{
|
32
|
+
# def #{m.to_sym}(*args)
|
33
|
+
# stratagem.validator_called(method, args)
|
34
|
+
# puts "calling validator \#\{method.to_s\} with \#\{args.inspect\}"
|
35
|
+
# send("old_"+method.to_s, *args, &block)
|
36
|
+
# end}
|
37
|
+
# instance_eval new_method
|
38
|
+
# end
|
39
|
+
# end
|
40
|
+
#
|
32
41
|
def removed_validators
|
33
42
|
@@removed_validators
|
34
43
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module Stratagem::ApplicationExtensions::Models::Adapters::
|
1
|
+
module Stratagem::ApplicationExtensions::Models::Adapters::ActiveRecord
|
2
2
|
|
3
3
|
# prefix method names with to avoid collision
|
4
4
|
class Metadata
|
@@ -13,8 +13,12 @@ module Stratagem::ApplicationExtensions::Models::Adapters::ActiveModel
|
|
13
13
|
def relations(relation_type=nil) # :belongs_to, :has_many
|
14
14
|
@relations ||= {}
|
15
15
|
@relations[relation_type || :all] ||= model.reflect_on_all_associations(relation_type).map {|a|
|
16
|
-
|
17
|
-
|
16
|
+
begin
|
17
|
+
Stratagem::ApplicationExtensions::Models::Metadata::StratagemAssociation.new(a.name.to_sym, a.association_foreign_key.to_sym, a.klass, a.macro, a.options)
|
18
|
+
rescue
|
19
|
+
puts "ERROR: #{$!.message}"
|
20
|
+
end
|
21
|
+
}.compact
|
18
22
|
end
|
19
23
|
|
20
24
|
def unaccessible_attributes
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module Stratagem::ApplicationExtensions::Models::Adapters::
|
1
|
+
module Stratagem::ApplicationExtensions::Models::Adapters::ActiveRecord
|
2
2
|
module Tracing
|
3
3
|
def self.included(model)
|
4
4
|
model.class_eval do
|
@@ -22,14 +22,17 @@ module Stratagem::ApplicationExtensions::Models::Adapters::ActiveModel
|
|
22
22
|
# enhance method missing
|
23
23
|
class << self
|
24
24
|
def method_missing(method, *args, &block)
|
25
|
-
|
25
|
+
method = method.to_sym
|
26
|
+
if (self.removed_methods.include?(method))
|
26
27
|
# puts "read invocation: #{self.name} -> #{method} -> #{args.inspect}"
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
stratagem.validator_called(method, args)
|
31
|
-
puts "calling validator #{method.to_s} with #{args.inspect}"
|
28
|
+
if (@@removed_finder_methods.include?(method))# && ![:finder_needs_type_condition?].include?(method))
|
29
|
+
stratagem.read_invocation(method, args)
|
30
|
+
end
|
32
31
|
send("old_"+method.to_s, *args, &block)
|
32
|
+
# elsif (self.removed_validators.include?(method.to_sym))
|
33
|
+
# stratagem.validator_called(method, args)
|
34
|
+
# puts "calling validator #{method.to_s} with #{args.inspect}"
|
35
|
+
# send("old_"+method.to_s, *args, &block)
|
33
36
|
else
|
34
37
|
old_method_missing(method, *args, &block)
|
35
38
|
end
|
@@ -40,14 +43,13 @@ module Stratagem::ApplicationExtensions::Models::Adapters::ActiveModel
|
|
40
43
|
|
41
44
|
def create_or_update(*args)
|
42
45
|
alternate_model = nil
|
43
|
-
path,action,line,trace,index = stratagem.controller_trace(
|
46
|
+
path,action,line,trace,index = stratagem.controller_trace(/\/active_record\/transactions\.rb/)
|
44
47
|
if (index)
|
45
48
|
model_path,model_action,model_line = find_model_path(trace,index)
|
46
49
|
if (model_path)
|
47
50
|
puts "WRITE INVOCATION - USING: #{model_path},#{model_action},#{model_line}"
|
48
51
|
alternate_model = Stratagem::Model::Application.instance.models.find {|m| m.path == model_path }.klass
|
49
52
|
action = model_action
|
50
|
-
puts alternate_model
|
51
53
|
end
|
52
54
|
end
|
53
55
|
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Stratagem::ApplicationExtensions::Models::Adapters::FriendlyId
|
2
|
+
class Detect < Stratagem::ApplicationExtensions::Models::Detect
|
3
|
+
def self.supports?(model)
|
4
|
+
begin
|
5
|
+
model.ancestors.include?(FriendlyId::ActiveRecordAdapter::SluggedModel) ||
|
6
|
+
model.ancestors.include?(FriendlyId::ActiveRecordAdapter::SimpleModel)
|
7
|
+
rescue
|
8
|
+
false
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
File without changes
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Stratagem::ApplicationExtensions::Models::Adapters::FriendlyId
|
2
|
+
|
3
|
+
# prefix method names with to avoid collision
|
4
|
+
class Metadata
|
5
|
+
def initialize(model)
|
6
|
+
@model = model
|
7
|
+
end
|
8
|
+
|
9
|
+
def exclude_attributes_for_mocking
|
10
|
+
# open id
|
11
|
+
attrs = @model.stratagem.attribute_names.select {|a|
|
12
|
+
(a =~ /friendly_id/)
|
13
|
+
}
|
14
|
+
attrs << :friendly_id_config
|
15
|
+
attrs << :cached_slug
|
16
|
+
|
17
|
+
attrs.uniq
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -1,30 +1,7 @@
|
|
1
1
|
# Defines the stratagem namespace attached to the model
|
2
2
|
module Stratagem::ApplicationExtensions::Models
|
3
|
-
MethodInvocation = Struct.new(:method, :controller_path, :controller_action, :line_number, :model_instance, :model_class, :stack_trace, :args, :type)
|
4
3
|
ValidatorDefinition = Struct.new(:validation, :field, :args, :model_class)
|
5
4
|
|
6
|
-
# Ability to convert a MethodInvocation object to a Reference object. Sort of a hack.
|
7
|
-
module MethodInvocationToReference
|
8
|
-
def to_reference
|
9
|
-
app = Stratagem::Model::Application.instance
|
10
|
-
model = model_class ? app.models.find {|model| model.klass == model_class } : nil
|
11
|
-
controller = controller_path ? app.controllers.find {|controller| controller.path == controller_path } : nil
|
12
|
-
Stratagem::Model::Component::Reference.new(
|
13
|
-
:from_component => controller,
|
14
|
-
:to_component => model,
|
15
|
-
:function => controller_action,
|
16
|
-
:method => method,
|
17
|
-
:line_number => line_number,
|
18
|
-
:reference_type => type,
|
19
|
-
:stack_trace => stack_trace
|
20
|
-
)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
MethodInvocation.class_eval do
|
24
|
-
include MethodInvocationToReference
|
25
|
-
end
|
26
|
-
|
27
|
-
|
28
5
|
class InstanceAnnotations
|
29
6
|
include Mocking
|
30
7
|
|
@@ -48,7 +25,7 @@ module Stratagem::ApplicationExtensions::Models
|
|
48
25
|
class << self
|
49
26
|
def configure(model)
|
50
27
|
puts "configuring #{model.name}"
|
51
|
-
|
28
|
+
|
52
29
|
# add the stratagem namespace
|
53
30
|
model.class_eval do
|
54
31
|
def self.stratagem
|
@@ -38,14 +38,20 @@ module Stratagem::ApplicationExtensions::Models
|
|
38
38
|
|
39
39
|
def read_invocation(method, *args)
|
40
40
|
# ensure that the read did not stem from a write operation
|
41
|
-
|
42
|
-
|
41
|
+
|
42
|
+
# the first line in the stack trace will be StrataGem instrumentation
|
43
|
+
# if the second line is active record then the invocation was called from another invocation
|
44
|
+
# and should be ignored
|
45
|
+
unless (caller()[1].include?('active_record/base.rb'))
|
46
|
+
path,action,line,trace,index = controller_trace(/active_record\/base\.rb/)
|
47
|
+
invocation(method, args, read_invocations, :read) unless (action =~ /create/) || (action =~ /update/) || (action =~ /save/)
|
48
|
+
end
|
43
49
|
end
|
44
50
|
|
45
51
|
def invocation(method, args, enumeration, type, object=nil, alternate_model=nil)
|
46
52
|
path,action,line,trace,index = controller_trace
|
47
53
|
args = args.first if args && (args.size == 1) && (args.first.kind_of?(Array))
|
48
|
-
add_invocation enumeration, MethodInvocation.new(method, path, action, line, object, alternate_model || model, caller, args, type) if (path)
|
54
|
+
add_invocation enumeration, Stratagem::ApplicationExtensions::MethodInvocation.new(method, path, action, line, object, alternate_model || model, caller, args, type) if (path)
|
49
55
|
end
|
50
56
|
|
51
57
|
def controller_trace(regex = /_controller\.rb/)
|
File without changes
|
File without changes
|
@@ -34,6 +34,8 @@ module Stratagem::Model
|
|
34
34
|
references = @controllers.map {|c| c.references }.flatten.map {|r| r.export }.uniq
|
35
35
|
h = {
|
36
36
|
:rails_version => rails_version,
|
37
|
+
:rails_environment => Rails.env,
|
38
|
+
:rails_root => Rails.root,
|
37
39
|
:models => @models.export,
|
38
40
|
:controllers => @controllers.export,
|
39
41
|
:routes => @routes.export,
|
@@ -43,12 +45,12 @@ module Stratagem::Model
|
|
43
45
|
:site_model => crawler ? crawler.export : nil,
|
44
46
|
:references => references
|
45
47
|
}
|
46
|
-
|
48
|
+
puts h.to_json
|
47
49
|
h
|
48
50
|
end
|
49
51
|
|
50
52
|
def rails_version
|
51
|
-
|
53
|
+
Stratagem.rails_version
|
52
54
|
end
|
53
55
|
end
|
54
56
|
|
@@ -134,7 +136,7 @@ module Stratagem::Model
|
|
134
136
|
end
|
135
137
|
|
136
138
|
class RouteContainer < ComponentContainer
|
137
|
-
def recognize(page, method=
|
139
|
+
def recognize(page, method = :get)
|
138
140
|
path = nil
|
139
141
|
if (page.kind_of?(Stratagem::Crawler::Page))
|
140
142
|
method = page.method
|
@@ -142,9 +144,7 @@ module Stratagem::Model
|
|
142
144
|
else
|
143
145
|
path = page
|
144
146
|
end
|
145
|
-
|
146
|
-
route = ActionController::Routing::Routes.routes.find {|r| r.recognize(path, {:method => method}) }
|
147
|
-
self.find {|r| r.route == route }
|
147
|
+
self.find {|r| r.responds_to?(path, method) }
|
148
148
|
end
|
149
149
|
end
|
150
150
|
|