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.
Files changed (64) hide show
  1. data/Manifest +16 -18
  2. data/Rakefile +3 -3
  3. data/bin/stratagem +54 -6
  4. data/generators/stratagem/stratagem_generator.rb +26 -0
  5. data/lib/generators/stratagem/install/USAGE +0 -0
  6. data/lib/generators/stratagem/install/install_base.rb +35 -0
  7. data/lib/generators/stratagem/install/install_generator.rb +24 -0
  8. data/lib/stratagem.rb +87 -57
  9. data/lib/stratagem/authentication.rb +2 -2
  10. data/lib/stratagem/auto_mock/aquifer.rb +6 -1
  11. data/lib/stratagem/auto_mock/factory.rb +2 -2
  12. data/lib/stratagem/client.rb +1 -1
  13. data/lib/stratagem/crawler.rb +2 -0
  14. data/lib/stratagem/crawler/authentication.rb +10 -9
  15. data/lib/stratagem/crawler/parameter_resolver.rb +83 -0
  16. data/lib/stratagem/crawler/route_invoker.rb +187 -0
  17. data/lib/stratagem/crawler/session.rb +23 -251
  18. data/lib/stratagem/crawler/site_model.rb +18 -16
  19. data/lib/stratagem/framework_extensions.rb +12 -1
  20. data/lib/stratagem/framework_extensions/method_invocation.rb +50 -0
  21. data/lib/stratagem/framework_extensions/models/adapters/active_model/detect.rb +1 -1
  22. data/lib/stratagem/framework_extensions/models/adapters/active_model/extensions.rb +20 -11
  23. data/lib/stratagem/framework_extensions/models/adapters/active_model/metadata.rb +7 -3
  24. data/lib/stratagem/framework_extensions/models/adapters/active_model/tracing.rb +11 -9
  25. data/lib/stratagem/framework_extensions/models/adapters/friendly_id/detect.rb +12 -0
  26. data/lib/stratagem/framework_extensions/models/adapters/friendly_id/extensions.rb +0 -0
  27. data/lib/stratagem/framework_extensions/models/adapters/friendly_id/metadata.rb +21 -0
  28. data/lib/stratagem/framework_extensions/models/adapters/friendly_id/tracing.rb +4 -0
  29. data/lib/stratagem/framework_extensions/models/annotations.rb +1 -24
  30. data/lib/stratagem/framework_extensions/models/tracing.rb +9 -3
  31. data/lib/stratagem/framework_extensions/rails.rb +0 -6
  32. data/lib/stratagem/framework_extensions/{controllers → rails2}/action_controller.rb +0 -0
  33. data/lib/stratagem/framework_extensions/{controllers → rails2}/action_mailer.rb +0 -0
  34. data/lib/stratagem/framework_extensions/rails3/parameters.rb +14 -0
  35. data/lib/stratagem/interface/browser.rb +3 -1
  36. data/lib/stratagem/model/application.rb +6 -6
  37. data/lib/stratagem/model/components/controller.rb +17 -63
  38. data/lib/stratagem/model/components/model.rb +33 -33
  39. data/lib/stratagem/model/components/reference.rb +8 -4
  40. data/lib/stratagem/model/components/route.rb +40 -14
  41. data/lib/stratagem/model/components/view.rb +1 -1
  42. data/lib/stratagem/model_builder.rb +71 -42
  43. data/lib/stratagem/site_crawler.rb +1 -1
  44. data/lib/stratagem/snapshot.rb +0 -1
  45. data/stratagem.gemspec +10 -7
  46. data/templates/install/environments/stratagem.rb.erb +16 -0
  47. data/templates/install/tasks/stratagem.rake +18 -0
  48. metadata +57 -40
  49. data/lib/stratagem/framework_extensions/controllers.rb +0 -5
  50. data/lib/stratagem/scan/checks/filter_parameter_logging.rb +0 -6
  51. data/lib/stratagem/scan/checks/mongo_mapper/base.rb +0 -19
  52. data/lib/stratagem/scan/checks/mongo_mapper/foreign_keys_exposed.rb +0 -32
  53. data/lib/stratagem/scan/checks/routes.rb +0 -16
  54. data/lib/tasks/_old_stratagem.rake +0 -99
  55. data/spec/model/component_spec.rb +0 -43
  56. data/spec/model/components/view_spec.rb +0 -43
  57. data/spec/model/test_spec.rb +0 -10
  58. data/spec/samples/404.html.erb +0 -30
  59. data/spec/samples/_form.html.erb +0 -8
  60. data/spec/samples/index.html.erb +0 -77
  61. data/spec/samples/sample_model.rb +0 -5
  62. data/spec/samples/signup.html.erb +0 -14
  63. data/spec/scan/checks/email_address_spec.rb +0 -24
  64. 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
- :type => type
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
- :method => method,
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 => response.request.parameters.to_json
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 = response.request.url
106
- @path = response.request.path
107
- @method = response.request.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/controllers'
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::ActiveModel
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
- module ActiveRecord::Validations::ClassMethods
20
+ class ActiveRecord::Base #Validations::ClassMethods
21
21
  @@removed_validators = []
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
- end
30
- end
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::ActiveModel
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
- Stratagem::ApplicationExtensions::Models::Metadata::StratagemAssociation.new(a.name.to_sym, a.association_foreign_key.to_sym, a.klass, a.macro, a.options)
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::ActiveModel
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
- if (self.removed_methods.include?(method.to_sym))
25
+ method = method.to_sym
26
+ if (self.removed_methods.include?(method))
26
27
  # puts "read invocation: #{self.name} -> #{method} -> #{args.inspect}"
27
- stratagem.read_invocation(method, args) if (@@removed_finder_methods.include?(method))
28
- send("old_"+method.to_s, *args, &block)
29
- elsif (self.removed_validators.include?(method.to_sym))
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(/active_record\/base\.rb/)
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
@@ -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
@@ -0,0 +1,4 @@
1
+ module Stratagem::ApplicationExtensions::Models::Adapters::FriendlyId
2
+ module Tracing
3
+ end
4
+ 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
- path,action,line,trace,index = controller_trace(/active_record\/base\.rb/)
42
- invocation(method, args, read_invocations, :read) unless (action =~ /create/) || (action =~ /update/) || (action =~ /save/)
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/)
@@ -1,8 +1,2 @@
1
1
  module Rails
2
- def self.stratagem_rails_version
3
- rails_version = Rails.version.split('.')
4
- rails_version << 0 while rails_version.size < 3
5
- rails_version.pop while rails_version.size > 3
6
- rails_version.join.to_i
7
- end
8
2
  end
@@ -0,0 +1,14 @@
1
+ module ActionDispatch
2
+ module Http
3
+ module Parameters
4
+ alias_method :rails_parameters, :parameters
5
+ undef_method :parameters
6
+
7
+ def parameters
8
+ params = rails_parameters
9
+ params.enable_auditing
10
+ params
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,7 +1,9 @@
1
1
  require 'rubygems'
2
2
  require 'sinatra'
3
- require 'erb'
3
+ # require 'erb'
4
4
 
5
+ set :public, File.dirname(__FILE__) + '/public'
6
+ set :views, File.dirname(__FILE__) + '/views'
5
7
  set :run, false
6
8
  enable :sessions
7
9
  disable :logging
@@ -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
- p h
48
+ puts h.to_json
47
49
  h
48
50
  end
49
51
 
50
52
  def rails_version
51
- Rails.stratagem_rails_version
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=nil)
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
- #ActionController::Routing::Routes.recognize_path('http://www.example.com/user_sessions/new', {:method => :get})
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