stratagem 0.2.3 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. data/Manifest +16 -6
  2. data/Rakefile +8 -1
  3. data/lib/generators/stratagem/install/install_base.rb +13 -3
  4. data/lib/generators/stratagem/install/install_generator.rb +1 -1
  5. data/lib/stratagem.rb +42 -18
  6. data/lib/stratagem/authentication.rb +2 -5
  7. data/lib/stratagem/auto_mock.rb +1 -0
  8. data/lib/stratagem/auto_mock/aquifer.rb +49 -26
  9. data/lib/stratagem/auto_mock/factory.rb +1 -6
  10. data/lib/stratagem/auto_mock/user_loader.rb +38 -0
  11. data/lib/stratagem/client.rb +15 -4
  12. data/lib/stratagem/configuration/auth_auth.rb +19 -0
  13. data/lib/stratagem/configuration/core.rb +20 -0
  14. data/lib/stratagem/crawler/authentication.rb +17 -12
  15. data/lib/stratagem/crawler/authentication/automated.rb +40 -0
  16. data/lib/stratagem/crawler/authentication/base.rb +140 -0
  17. data/lib/stratagem/crawler/authentication/configured.rb +27 -0
  18. data/lib/stratagem/crawler/parameter_resolver.rb +12 -8
  19. data/lib/stratagem/crawler/route_invoker.rb +10 -13
  20. data/lib/stratagem/crawler/session.rb +14 -2
  21. data/lib/stratagem/crawler/site_model.rb +4 -173
  22. data/lib/stratagem/crawler/site_model/edge.rb +20 -0
  23. data/lib/stratagem/crawler/site_model/page.rb +121 -0
  24. data/lib/stratagem/crawler/site_model/page_set.rb +58 -0
  25. data/lib/stratagem/instrumentation/models.rb +3 -14
  26. data/lib/stratagem/instrumentation/models/annotations.rb +39 -5
  27. data/lib/stratagem/instrumentation/models/authentication.rb +0 -1
  28. data/lib/stratagem/instrumentation/models/authentication/authlogic/detect.rb +1 -0
  29. data/lib/stratagem/instrumentation/models/authentication/devise/detect.rb +1 -1
  30. data/lib/stratagem/instrumentation/models/authentication/devise/instrumentation.rb +0 -4
  31. data/lib/stratagem/instrumentation/models/metadata.rb +23 -1
  32. data/lib/stratagem/instrumentation/models/persistence.rb +3 -4
  33. data/lib/stratagem/instrumentation/models/persistence/active_record/metadata.rb +2 -2
  34. data/lib/stratagem/interface/browser.rb +9 -3
  35. data/lib/stratagem/interface/public/javascripts/stratagem.js +14 -12
  36. data/lib/stratagem/interface/views/index.haml +3 -3
  37. data/lib/stratagem/logger.rb +28 -2
  38. data/lib/stratagem/model.rb +6 -0
  39. data/lib/stratagem/model/application.rb +21 -134
  40. data/lib/stratagem/model/components/base.rb +1 -4
  41. data/lib/stratagem/model/components/controller.rb +1 -2
  42. data/lib/stratagem/model/components/model.rb +15 -15
  43. data/lib/stratagem/model/components/route.rb +3 -2
  44. data/lib/stratagem/model/components/view.rb +0 -1
  45. data/lib/stratagem/model/containers/base.rb +60 -0
  46. data/lib/stratagem/model/containers/gem.rb +25 -0
  47. data/lib/stratagem/model/containers/plugin.rb +11 -0
  48. data/lib/stratagem/model/containers/route.rb +19 -0
  49. data/lib/stratagem/model/parse_util.rb +3 -3
  50. data/lib/stratagem/model_builder.rb +1 -4
  51. data/lib/stratagem/rack_hack.rb +15 -0
  52. data/lib/stratagem/site_crawler.rb +5 -4
  53. data/lib/stratagem/snapshot.rb +5 -7
  54. data/spec/stratagem/configuration_spec.rb +32 -0
  55. data/stratagem.gemspec +5 -8
  56. data/templates/install/environments/stratagem.rb.erb +31 -2
  57. data/templates/install/script/stratagem +16 -0
  58. data/templates/install/tasks/stratagem.rake +2 -2
  59. metadata +36 -65
  60. data/bin/stratagem +0 -58
  61. data/lib/stratagem/scan.rb +0 -19
  62. data/lib/stratagem/scan/checks/email_address.rb +0 -15
  63. data/lib/stratagem/scan/checks/error_pages.rb +0 -25
  64. data/lib/stratagem/scan/result.rb +0 -45
  65. data/lib/stratagem/scanner.rb +0 -32
@@ -15,9 +15,7 @@ module Stratagem::Crawler
15
15
  begin
16
16
  call_route!(route_info, track_invocations)
17
17
  rescue Exception
18
- # TODO - add exception as a response page
19
- puts "ERROR: #{$!.message}"
20
- puts $!.backtrace
18
+ Stratagem.logger.error($!)
21
19
  end
22
20
  end
23
21
 
@@ -31,8 +29,8 @@ module Stratagem::Crawler
31
29
  invocations = model_invocations_for_request do
32
30
  case verb
33
31
  when 'get'
32
+ puts "\t#{route_info[:path].to_s == '/connections'} - #{route_info[:path]}"
34
33
  do_get(route_info)
35
- puts "\tresponse code: #{response.code}" if response
36
34
  when 'post'
37
35
  do_post(route_info)
38
36
  when 'put'
@@ -43,20 +41,20 @@ module Stratagem::Crawler
43
41
  end
44
42
  end
45
43
 
46
- if (response)
47
- if (track_invocations)
48
- changes = detect_attribute_changes_in_models(invocations)
44
+ if (response && track_invocations)
45
+ changes = detect_attribute_changes_in_models(invocations)
46
+ if (![500].include?(response.code) || (changes.size > 0) || (invocations.size > 0))
49
47
  puts "\tfound #{invocations.size} invocations"
50
48
  invocations.each do |i|
51
49
  puts "\t\t#{i.controller_action} -> #{i.model_class}"
52
50
  end
53
-
54
- puts "\tchanges values: #{changes.values.inspect}" if changes.size > 0
55
- site_model.add(route_info[:route_container], controller, request, response, invocations, changes) {|redirect_url| redirect_proc.call(redirect_url) }
51
+ puts "\tchanges values: #{changes.values.inspect}"
52
+ page = site_model.add(route_info[:route_container], controller, request, response, invocations, changes) {|redirect_url| redirect_proc.call(redirect_url) }
53
+ puts "\tresponse code: #{response.code} - body size: #{page.response_body.size}"
56
54
  puts "\tadded to site model"
57
55
  end
58
56
  else
59
- puts "ERROR: did not call #{route_info.inspect}"
57
+ puts "ERROR: did not call #{route_info[:path]}"
60
58
  end
61
59
  end
62
60
 
@@ -169,7 +167,6 @@ module Stratagem::Crawler
169
167
 
170
168
  def guess_form_for_route(route_info)
171
169
  forms = []
172
- pages = site_models.map {|sm| sm.pages }.flatten
173
170
  site_models.each do |site_model|
174
171
  site_model.pages.each do |page|
175
172
  page.forms.each do |form|
@@ -178,7 +175,7 @@ module Stratagem::Crawler
178
175
  (route_info[:path].sub(/\.\(\:format\)*/, '') == form.action) &&
179
176
  ((form.implied_method || form.method).to_s.downcase == route_info[:verb].to_s.downcase)
180
177
  end
181
- puts "\tform: #{form.action} - #{form.implied_method || form.method} - #{usable}"
178
+ puts "\tpageset: #{site_model.name} - form: #{form.action} - #{form.implied_method || form.method} - #{usable} - #{form.inputs.map{|i| i.name}}"
182
179
  forms << form if (usable)
183
180
  end
184
181
  end
@@ -56,6 +56,7 @@ module Stratagem::Crawler::Session
56
56
  end
57
57
 
58
58
  def crawler_session(application_model=nil)
59
+ aquifer # force fill
59
60
  @application_model = application_model if application_model
60
61
  open_session do |session|
61
62
  @session = session
@@ -68,7 +69,16 @@ module Stratagem::Crawler::Session
68
69
  end
69
70
 
70
71
  def aquifer(initial_capacity=6)
71
- @aquifer ||= Stratagem::AutoMock::Aquifer.init(application_model).fill(initial_capacity)
72
+ @aquifer ||= begin
73
+ Stratagem.logger.phase "mocking_models"
74
+
75
+ if Stratagem.configuration.use_automatic_mocking
76
+ Stratagem::AutoMock::Aquifer.init(application_model).fill_by_automock(initial_capacity)
77
+ else
78
+ # TODO - refactor out into another method
79
+ Stratagem::AutoMock::Aquifer.init(application_model).fill_by_configuration(Stratagem.configuration.credentials)
80
+ end
81
+ end
72
82
  end
73
83
 
74
84
  def site_models
@@ -81,11 +91,13 @@ module Stratagem::Crawler::Session
81
91
  end
82
92
 
83
93
  def page_set(name, &block)
94
+ Stratagem.logger.phase "traversing_site"
95
+
84
96
  log "---------------------------------------"
85
97
  log "Crawling page set #{name}"
86
98
  log "---------------------------------------"
87
99
  reset!
88
- site_models << Stratagem::Crawler::SiteModel.new(name)
100
+ site_models << Stratagem::Crawler::SiteModel::PageSet.new(name)
89
101
  yield site_model
90
102
  end
91
103
 
@@ -1,174 +1,5 @@
1
- module Stratagem::Crawler
2
- class SiteModel
3
- include Stratagem::Crawler::HtmlUtils
1
+ module Stratagem::Crawler::SiteModel; end
4
2
 
5
- attr_reader :pages, :edges, :name
6
- attr_accessor :authentication
7
-
8
- def initialize(name)
9
- @name = name
10
- @pages = []
11
- @edges = []
12
- end
13
-
14
- def export
15
- {
16
- :name => name,
17
- :pages => @pages.map {|page| page.export },
18
- :edges => @edges.map {|edge| edge.export },
19
- :authentication => authentication.nil? ? nil : {
20
- :authenticated_user_id => authentication.authenticated_with.object_id,
21
- :success => authentication.success,
22
- :login_page_external_id => authentication.login_page.object_id,
23
- :response_page_external_id => authentication.response_page.object_id,
24
- :ssl => authentication.ssl
25
- },
26
- }
27
- end
28
-
29
- def add_edge(from,to,type)
30
- self.edges << Edge.new(from,to,type)
31
- end
32
-
33
- def add(route, controller, request, response, invocations=[], model_changes={}, &block)
34
- page = Page.new(self, controller, request, response, invocations, model_changes, &block)
35
- self.pages << page
36
- page
37
- end
38
-
39
- def pages_for(id)
40
- if (id.kind_of?(String))
41
- pages.select {|page| page.url == id }
42
- else
43
- pages.select {|page| page.route == id }
44
- end
45
- end
46
-
47
- end
48
-
49
- class Edge
50
- # type -> :link, :redirect,
51
- attr_accessor :from, :to, :type
52
-
53
- def initialize(from, to, type)
54
- @from = from
55
- @to = to
56
- @type = type
57
- end
58
-
59
- def export
60
- {
61
- :from => from.object_id,
62
- :to => to.object_id,
63
- :relation_type => type
64
- }
65
- end
66
- end
67
-
68
- class Page
69
- include Stratagem::Crawler::HtmlUtils
70
-
71
- attr_reader :response
72
-
73
- attr_accessor :url
74
- attr_accessor :path
75
- attr_accessor :method
76
- attr_accessor :redirected_to
77
- attr_accessor :document
78
- attr_accessor :response_body
79
-
80
- def initialize(site_model, controller, request, response, invocations, model_changes, &block)
81
- @site_model = site_model
82
- @invocations = invocations
83
- @model_changes = model_changes
84
- @authenticity_checked = (controller && controller.methods.include?(:authenticity_checked?)) ? controller.authenticity_checked? : true
85
- init(request, response, &block)
86
- end
87
-
88
- def route
89
- @route ||= Stratagem::Model::Application.instance.routes.recognize(self)
90
- end
91
-
92
- def export
93
- h = {
94
- :external_id => self.object_id,
95
- :url => url,
96
- :path => path,
97
- :request_method => method,
98
- :redirected_to_page_external_id => redirected_to ? redirected_to.object_id : nil,
99
- :route_external_id => route ? route.object_id : nil,
100
- :references => @invocations.map {|i| i.to_reference.export },
101
- :model_changes => Hash[@model_changes.map {|model,changes| [model.object_id, changes] }].to_json,
102
- :authenticity_checked => @authenticity_checked,
103
- :parameters => @request.parameters.to_json,
104
- :response_body => @response_body
105
- }
106
- h
107
- end
108
-
109
- def init(request, response, &block)
110
- @request = request.clone
111
- @response = response.clone
112
- @url = request.url
113
- @path = request.path
114
- @method = request.method
115
- begin
116
- @document = Nokogiri::HTML(response.body)
117
- rescue
118
- puts "ERROR: Could not parse html: #{$!.message} - #{response.body}"
119
- end
120
- @response_body = response.body
121
- self.redirected_to = block.call(response.redirect_url) if response.redirect?
122
- end
123
-
124
- def reload(&block)
125
- # TODO - should support all the verbs and params, but
126
- # hack together for now to reload the authenticity token
127
- request,response = yield url
128
- init(request, response) {|redirected_to| }
129
- end
130
-
131
- def redirected?
132
- !self.redirected_to.nil?
133
- end
134
-
135
- def forms
136
- @forms ||= begin
137
- if (@document)
138
- forms = self.parse_forms(@document)
139
- forms.each do |form|
140
- form.page = self
141
- end
142
- forms
143
- else
144
- []
145
- end
146
- end
147
- end
148
-
149
- def login_form
150
- self.find_login_form(@document)
151
- end
152
-
153
- def to_html
154
- @document.to_html
155
- end
156
-
157
- def outbound_edges(type=nil)
158
- @site_model.edges.select {|edge| edge.from == self && (type.nil? || (type == edge.type)) }
159
- end
160
-
161
- def inbound_edges(type=nil)
162
- @site_model.edges.select {|edge| (edge.to == self) && (type.nil? || (type == edge.type)) }
163
- end
164
-
165
- def title
166
- if ((@document) && !(@title))
167
- title = (@document/'head title').first
168
- @title = title.inner_html if title
169
- end
170
- @title
171
- end
172
- end
173
-
174
- end
3
+ require 'stratagem/crawler/site_model/page_set'
4
+ require 'stratagem/crawler/site_model/page'
5
+ require 'stratagem/crawler/site_model/edge'
@@ -0,0 +1,20 @@
1
+ module Stratagem::Crawler::SiteModel
2
+ class Edge
3
+ # type -> :link, :redirect,
4
+ attr_accessor :from, :to, :type
5
+
6
+ def initialize(from, to, type)
7
+ @from = from
8
+ @to = to
9
+ @type = type
10
+ end
11
+
12
+ def export
13
+ {
14
+ :from_page_external_id => from.object_id,
15
+ :to_page_external_id => to.object_id,
16
+ :relation_type => type
17
+ }
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,121 @@
1
+ module Stratagem::Crawler::SiteModel
2
+
3
+ class Page
4
+ include Stratagem::Crawler::HtmlUtils
5
+
6
+ attr_reader :response
7
+
8
+ attr_accessor :url
9
+ attr_accessor :path
10
+ attr_accessor :method
11
+ attr_accessor :redirected_to
12
+ attr_accessor :document
13
+ attr_accessor :response_body
14
+
15
+ def initialize(site_model, controller, request, response, invocations, model_changes, &block)
16
+ @site_model = site_model
17
+ @invocations = invocations
18
+ @model_changes = model_changes
19
+ @authenticity_checked = (controller && controller.methods.include?(:authenticity_checked?)) ? controller.authenticity_checked? : true
20
+ init(request, response, &block)
21
+ end
22
+
23
+ def route
24
+ @route ||= Stratagem::Model::Application.instance.routes.recognize(self)
25
+ end
26
+
27
+ def export
28
+ h = {
29
+ :external_id => self.object_id,
30
+ :url => url,
31
+ :path => path,
32
+ :request_method => method,
33
+ :redirected_to_page_external_id => redirected_to ? redirected_to.object_id : nil,
34
+ :route_external_id => route ? route.object_id : nil,
35
+ :references_attributes => @invocations.map {|i| i.to_reference.export },
36
+ :model_changes => Hash[@model_changes.map {|model,changes| [model.object_id, changes] }].to_json,
37
+ :authenticity_checked => @authenticity_checked,
38
+ :parameters => @request.parameters.to_json,
39
+ :response_body => @response_body,
40
+ :response_code => @response.code
41
+ }
42
+ h
43
+ end
44
+
45
+ def init(request, response, &block)
46
+ @request = request.clone
47
+ @response = response.clone
48
+ @url = request.url
49
+ @path = request.path
50
+ @method = request.method
51
+ body = response.body
52
+ begin
53
+ if [500, 400, 302].include?(response.code)
54
+ body = ''
55
+ elsif
56
+ body.kind_of?(Array)
57
+ body = body.join
58
+ body = body.slice(0,20000)
59
+ end
60
+
61
+ @document = Nokogiri::HTML(body)
62
+ rescue
63
+ puts "ERROR: Could not parse html: #{$!.message} - #{body}"
64
+ end
65
+
66
+ @response_body = body
67
+
68
+ self.redirected_to = block.call(response.redirect_url) if response.redirect?
69
+ end
70
+
71
+ def reload(&block)
72
+ # TODO - should support all the verbs and params, but
73
+ # hack together for now to reload the authenticity token
74
+ request,response = yield url
75
+ init(request, response) {|redirected_to| }
76
+ end
77
+
78
+ def redirected?
79
+ !self.redirected_to.nil?
80
+ end
81
+
82
+ def forms
83
+ @forms ||= begin
84
+ if (@document)
85
+ forms = self.parse_forms(@document)
86
+ forms.each do |form|
87
+ form.page = self
88
+ end
89
+ forms
90
+ else
91
+ []
92
+ end
93
+ end
94
+ end
95
+
96
+ def login_form
97
+ self.find_login_form(@document)
98
+ end
99
+
100
+ def to_html
101
+ @document.to_html
102
+ end
103
+
104
+ def outbound_edges(type=nil)
105
+ @site_model.edges.select {|edge| edge.from == self && (type.nil? || (type == edge.type)) }
106
+ end
107
+
108
+ def inbound_edges(type=nil)
109
+ @site_model.edges.select {|edge| (edge.to == self) && (type.nil? || (type == edge.type)) }
110
+ end
111
+
112
+ def title
113
+ if ((@document) && !(@title))
114
+ title = (@document/'head title').first
115
+ @title = title.inner_html if title
116
+ end
117
+ @title
118
+ end
119
+ end
120
+
121
+ end
@@ -0,0 +1,58 @@
1
+ module Stratagem::Crawler::SiteModel
2
+
3
+ class PageSet
4
+ include Stratagem::Crawler::HtmlUtils
5
+
6
+ attr_reader :pages, :edges, :name
7
+ attr_accessor :authentication
8
+
9
+ def initialize(name)
10
+ @name = name
11
+ @pages = []
12
+ @edges = []
13
+ end
14
+
15
+ def export
16
+ puts "Exporting page set #{name} with #{@pages.size} initial pages"
17
+ pages = @pages.select {|page| page.response_body && page.response_body.size > 0 }
18
+ puts "\t#{pages.size} filtered pages"
19
+ pages = pages.map {|page| page.export }
20
+
21
+ pages << authentication.login_page.export if authentication && authentication.login_page
22
+ pages << authentication.response_page.export if authentication && authentication.response_page
23
+
24
+ puts "\t#{pages.size} exported pages"
25
+ {
26
+ :name => name,
27
+ :pages_attributes => pages,
28
+ :edges_attributes => @edges.map {|edge| edge.export },
29
+ :authentication_attributes => authentication.nil? ? nil : {
30
+ :authenticated_user_id => authentication.authenticated_with.object_id,
31
+ :success => authentication.success,
32
+ :login_page_external_id => authentication.login_page ? authentication.login_page.object_id : nil,
33
+ :response_page_external_id => authentication.response_page ? authentication.response_page.object_id : nil,
34
+ :ssl => authentication.ssl
35
+ },
36
+ }
37
+ end
38
+
39
+ def add_edge(from,to,type)
40
+ self.edges << Edge.new(from,to,type)
41
+ end
42
+
43
+ def add(route, controller, request, response, invocations=[], model_changes={}, &block)
44
+ page = Page.new(self, controller, request, response, invocations, model_changes, &block)
45
+ self.pages << page
46
+ page
47
+ end
48
+
49
+ def pages_for(id)
50
+ if (id.kind_of?(String))
51
+ pages.select {|page| page.url == id }
52
+ else
53
+ pages.select {|page| page.route == id }
54
+ end
55
+ end
56
+
57
+ end
58
+ end