stratagem 0.1.8 → 0.1.9

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -51,12 +51,12 @@ module Stratagem::AutoMock
51
51
  return [object,valid] if valid
52
52
  end
53
53
 
54
- protected
55
-
56
54
  def add_mocked(instance)
57
55
  (mocked(instance.class)) << instance
58
56
  end
59
57
 
58
+ protected
59
+
60
60
  def mocked(model=nil)
61
61
  @mocked ||= {}
62
62
  if (model)
@@ -11,7 +11,7 @@ module Stratagem
11
11
  url = URI.parse("#{@authentication.base_url}/snapshots")
12
12
  req = Net::HTTP::Post.new(url.path)
13
13
  req.set_form_data({
14
- 'api_key' => @authentication.credentials[:token],
14
+ 'auth_token' => @authentication.credentials[:token],
15
15
  'project_id' => @authentication.credentials[:project],
16
16
  'timestamp' => snapshot.timestamp.to_i,
17
17
  'model' => snapshot.model.export.to_json
@@ -5,5 +5,7 @@ require 'stratagem/crawler/form'
5
5
  require 'stratagem/crawler/trace_utils'
6
6
  require 'stratagem/crawler/html_utils'
7
7
  require 'stratagem/crawler/authentication'
8
+ require 'stratagem/crawler/parameter_resolver'
9
+ require 'stratagem/crawler/route_invoker'
8
10
  require 'stratagem/crawler/session'
9
11
  require 'stratagem/crawler/site_model'
@@ -41,14 +41,14 @@ module Stratagem::Crawler
41
41
  reset_authentication
42
42
 
43
43
  login(user)
44
- route = application_model.routes.recognize(response.request.path, :post)
44
+ route = application_model.routes.recognize(request.path, :post)
45
45
 
46
46
  redirected_to = nil
47
- page = site_model.add(route, response) {|redirect_url| redirected_to = redirect_url }
47
+ page = site_model.add(route, request, response) {|redirect_url| redirected_to = redirect_url }
48
48
  authentication.response_page = page
49
49
 
50
50
  begin
51
- if (response.request.url == (redirected_to || '')) || (![200,302].include?(response.code.to_i))
51
+ if (request.url == (redirected_to || '')) || (![200,302].include?(response.code.to_i))
52
52
  authentication.success = false
53
53
  else
54
54
  authentication.success = authentication.response_page.login_form.nil?
@@ -60,7 +60,7 @@ module Stratagem::Crawler
60
60
 
61
61
  puts "authenticated? #{authentication.success}"
62
62
  if (response && authentication.success)
63
- authentication.ssl = response.request.ssl?
63
+ authentication.ssl = request.ssl?
64
64
  yield
65
65
  logout
66
66
  else
@@ -90,15 +90,13 @@ module Stratagem::Crawler
90
90
  end
91
91
 
92
92
  def logout
93
- get "/signout"
94
- get "/logout"
95
- delete "/user_sessions/1"
93
+ reset!
96
94
  end
97
95
 
98
96
  def login(user)
99
97
  populate_login_form(user).submit {|action,params|
100
98
  post(action, params)
101
- puts response.body
99
+ # puts response.body
102
100
  }
103
101
  end
104
102
 
@@ -124,7 +122,10 @@ module Stratagem::Crawler
124
122
  def populate_login_form(user)
125
123
  # set up the form
126
124
  page = find_login_form
127
- page.reload {|url| get url; response }
125
+ p page.login_form
126
+ page.reload {|url| get url; [request,response] }
127
+ p page.login_form
128
+ p page.response.body
128
129
  form = page.login_form
129
130
 
130
131
  # map the input values
@@ -0,0 +1,83 @@
1
+ module Stratagem::Crawler
2
+ module ParameterResolver
3
+
4
+ def resolve_parameter_types(route_container)
5
+ log "\tresolving parameter types"
6
+ resolved_params = {}
7
+ route_infos, params = build_url(route_container, resolved_params)
8
+ route_info = route_infos.first
9
+ unknown_params = params.keys
10
+ log "\tunknown params: #{unknown_params.inspect} - #{unknown_params.size}"
11
+
12
+ resolve_with_convention(unknown_params, resolved_params)
13
+ log "\tunknown params after convention: #{unknown_params.inspect} - #{unknown_params.size}"
14
+
15
+ resolve_with_instrumentation(route_container, resolved_params)
16
+ log "\tunknown params after instrumentation: #{unknown_params.inspect} - #{unknown_params.size}"
17
+
18
+ p resolved_params
19
+
20
+ if (resolved_params.size > 0)
21
+ resolved_params
22
+ else
23
+ nil
24
+ end
25
+ end
26
+
27
+ def resolve_with_instrumentation(route_container, resolved_params)
28
+ route_infos, params = build_url(route_container, resolved_params)
29
+ route_info = route_infos.first
30
+ unknown_params = params.keys
31
+
32
+ progress = nil
33
+ while ((unknown_params.size > 0) && (progress.nil? || (progress > 0)))
34
+ progress = 0
35
+
36
+ puts "\tloading model invocations for request"
37
+ delta = model_invocations_for_request do
38
+ call_route(route_info, false)
39
+ end
40
+
41
+ puts "\tcalled route, found #{delta.size} invocations"
42
+
43
+ unknown_params.clone.each do |key|
44
+ value = params[key]
45
+ value_s = params[key].map {|v| v.to_s }
46
+ delta.each do |invocation|
47
+ # TODO inspect is a hack, refactor
48
+ if (invocation.args.include?(value.first)) || (invocation.args.inspect.include?('"'+value.first.to_s+'"'))
49
+ # found match
50
+ puts "\t\tresolved #{key} to #{invocation.model_class}"
51
+ unknown_params.delete(key)
52
+ resolved_params[key] = invocation.model_class
53
+ progress += 1
54
+ break
55
+ end
56
+ end
57
+ end
58
+
59
+ route_infos, params = build_url(route_container, resolved_params)
60
+ route_info = route_infos.first
61
+ end
62
+ end
63
+
64
+ def resolve_with_convention(unknown_params, resolved_params)
65
+ unknown_params.each do |param|
66
+ if (param =~ /_id$/)
67
+ begin
68
+ model = param.gsub(/^:/,'').gsub(/_id$/, '').camelize.constantize
69
+ #success
70
+ resolved_params[param] = model
71
+ unknown_params.delete(param)
72
+ puts "\t\tresolved #{param} to #{model} using convention"
73
+ rescue NameError
74
+ puts $!
75
+ puts $!.backtrace
76
+ # not a model
77
+ end
78
+ end
79
+ end
80
+ end
81
+
82
+ end
83
+ end
@@ -0,0 +1,187 @@
1
+ module Stratagem::Crawler
2
+ module RouteInvoker
3
+ include Stratagem::Crawler::ParameterResolver
4
+
5
+ def visit(route_container)
6
+ puts "Visiting #{route_container.route}"
7
+ build_urls(route_container).each do |route_info|
8
+ call_route(route_info)
9
+ end
10
+ end
11
+
12
+ def call_route(route_info, track_invocations=true)
13
+ begin
14
+ call_route!(route_info, track_invocations)
15
+ rescue
16
+ # TODO - add exception as a response page
17
+ puts "ERROR: #{$!.message}"
18
+ end
19
+ end
20
+
21
+ def call_route!(route_info, track_invocations=true)
22
+ return if route_info.nil?
23
+
24
+ puts 'CALLING: .'+route_info[:verb].downcase+". - "+route_info[:path]
25
+ verb = route_info[:verb].downcase
26
+ verb = 'get' if verb == '' || verb == 'any'
27
+
28
+ invocations = model_invocations_for_request do
29
+ case verb
30
+ when 'get'
31
+ do_get(route_info)
32
+ puts "\tresponse code: #{response.code}" if response
33
+ when 'post'
34
+ when 'put'
35
+ do_put(route_info)
36
+ when 'delete'
37
+ else
38
+ raise "Unsupported verb: #{route[:verb]}"
39
+ end
40
+ end
41
+
42
+ if (response)
43
+ if (track_invocations)
44
+ changes = detect_attribute_changes_in_models(invocations)
45
+ puts "\tfound #{invocations.size} invocations"
46
+ puts "\tchanges: #{changes.values.inspect}" if changes.size > 0
47
+ site_model.add(route_info[:route_container], request, response, invocations, changes) {|redirect_url| redirect_proc.call(redirect_url) }
48
+ end
49
+ else
50
+ puts "ERROR: did not call #{route_info.inspect}"
51
+ end
52
+ end
53
+
54
+ def do_get(route_info)
55
+ get route_info[:path]
56
+ end
57
+
58
+ def do_put(route_info)
59
+
60
+ # note: this should fail to generate anything meaningful, as we have not yet set up the parameters
61
+ put route_info[:path]
62
+
63
+ # let's find out what the method is looking for in the params object
64
+ params = map_models_to_attributes(infer_models_for_param_reads(route_info[:route_container],controller.params.hash_reads))
65
+
66
+ # run again with the params
67
+ puts "PUTTING: #{route_info[:path]} with #{params.inspect}"
68
+
69
+ invocation_delta = model_invocations_for_request(:write) do
70
+ put route_info[:path], params
71
+ end
72
+ end
73
+
74
+ private
75
+
76
+
77
+ def map_models_to_attributes(models)
78
+ result = {}
79
+ models.each {|param_read,model|
80
+ result[param_read] = aquifer.mock_attributes(model.klass)
81
+ }
82
+ result
83
+ end
84
+
85
+ def infer_models_for_param_reads(route,param_reads)
86
+ param_reads = param_reads.select {|read| read.to_s !~ /_id$/ }
87
+ param_reads -= [:action,'action',:controller,'controller',:id,'id',:format,'format']
88
+
89
+ result = {}
90
+
91
+ # resolve param reads to model types
92
+ # only support simple expected mappings at the moment
93
+ param_reads.each do |param_read|
94
+ class_name = param_read.to_s.camelize
95
+ if (class_name.singularize == class_name)
96
+ # this looks promising
97
+ model = application_model.models.find {|model| model.klass.name == class_name }
98
+ if (model)
99
+ puts "\t\tresolved param #{param_read} to #{model.klass.name}"
100
+ result[param_read] = model
101
+ end
102
+ end
103
+ end
104
+
105
+ result
106
+ end
107
+
108
+ def detect_attribute_changes_in_models(invocations)
109
+ changes = {}
110
+ invocations.select {|invocation| invocation.type == :write }.each do |invocation|
111
+ if (invocation.model_instance)
112
+ model = application_model.models.find {|m| m.klass == invocation.model_instance.class }
113
+
114
+ puts "\t\t#{invocation.model_class}.#{invocation.method} - #{invocation.model_instance}"
115
+ prior = aquifer.instances_of(invocation.model_instance.class).find {|m| m.id == invocation.model_instance.id }
116
+ post = invocation.model_instance
117
+ attribute_names = (prior.stratagem.attribute_names + prior.stratagem.foreign_keys)
118
+ changes[model] = attribute_names.select {|an|
119
+ begin
120
+ prior.send(an) != post.send(an)
121
+ rescue
122
+ puts "\t\t\t#{an} cannot be determined - #{$!.message}"
123
+ end
124
+ }
125
+ end
126
+ end
127
+ changes
128
+ end
129
+
130
+ # Builds a list of string URLs for a given route. This is done
131
+ # by replacing :xyz_id segments in the route with known values
132
+ # from the well
133
+ def build_urls(route_container)
134
+ urls = []
135
+ route = route_container.route
136
+ param_types = (self.parameter_types[route_container] ||= resolve_parameter_types(route_container))
137
+ route_infos, params = build_url(route_container, param_types)
138
+ route_infos
139
+ end
140
+
141
+ def url_permutations(route, segment_values, &block)
142
+ path = route.path.sub('(.:format)', '')
143
+ if (segment_values.size == 0)
144
+ yield path
145
+ else
146
+ combinations = segment_values[0].product(*segment_values.slice(1,segment_values.size-1))
147
+ combinations.each do |combination|
148
+ url = path.clone
149
+ route.segment_keys.each_with_index {|segment_key,i| url.gsub!(':'+segment_key.to_s, combination[i].to_s) }
150
+ yield url
151
+ end
152
+ end
153
+ end
154
+
155
+ def build_url(route_container, parameter_types={})
156
+ parameter_types ||= {}
157
+ params = {}
158
+ route = route_container.route
159
+ verb = route_container.verb.to_s
160
+
161
+
162
+ i = 12345
163
+ insert_values = (route.segment_keys - [:format]).map {|segment_key|
164
+ model = parameter_types[segment_key.to_s]
165
+ value = nil
166
+ if (model)
167
+ value = (aquifer.instances_of model).map {|inst|
168
+ inst.methods_include?(segment_key) ? inst.send(segment_key) : inst.to_param
169
+ }
170
+ else
171
+ value = [i += 1]
172
+ end
173
+ params[segment_key.to_s] = value
174
+ }
175
+
176
+ routes = []
177
+ url_permutations(route_container,insert_values) do |path|
178
+ puts "yielded: #{path}"
179
+ permutation = {:verb => verb, :path => path, :route_container => route_container}
180
+ routes << permutation
181
+ end
182
+
183
+ [routes, params]
184
+ end
185
+
186
+ end
187
+ end
@@ -29,6 +29,20 @@ module Stratagem::Crawler::Session
29
29
  include Stratagem::Crawler::HtmlUtils
30
30
  include Stratagem::Crawler::TraceUtils
31
31
  include Stratagem::Crawler::Authentication
32
+ include Stratagem::Crawler::RouteInvoker
33
+
34
+ attr_writer :aquifer
35
+
36
+ # def self.app
37
+ # # DEPRECATE Rails application fallback
38
+ # # This should be set by the initializer
39
+ # (defined?(Rails.application) && Rails.application) || nil
40
+ # end
41
+ #
42
+
43
+ def app
44
+ (defined?(Rails.application) && Rails.application) || nil
45
+ end
32
46
 
33
47
  def log(msg)
34
48
  Stratagem.logger.debug msg
@@ -68,14 +82,18 @@ module Stratagem::Crawler::Session
68
82
  end
69
83
 
70
84
  def page_set(name, &block)
85
+ reset!
71
86
  site_models << Stratagem::Crawler::SiteModel.new(name)
72
87
  yield site_model
73
88
  end
74
89
 
75
- def display
90
+ def print
76
91
  # print out pages and inbound / outbound links
77
92
  site_model.pages.each do |page|
78
- log "Page: #{page.url} - #{page.title} - #{page.response.code}"
93
+ title = page.title
94
+ title ||= page.redirected_to.url if page.redirected_to
95
+ title ||= page.response.code
96
+ log "Page: #{page.url} - #{title} - #{page.response.code}"
79
97
  page.outbound_edges.each do |edge|
80
98
  log "\tout: #{edge.to.url} - #{edge.to.title} - #{edge.to.route}"
81
99
  end
@@ -102,10 +120,10 @@ module Stratagem::Crawler::Session
102
120
  else
103
121
  if (application_model.routes.invalid.include?(route_container))
104
122
  log "Skipping invalid route #{route_container.route.to_s}"
105
- elsif (verbs.include?(route_container.route.conditions[:method]))
123
+ elsif (verbs.include?(route_container.verb))
106
124
  visit(route_container)
107
125
  else
108
- log "Skipping route with verb #{route_container.route.conditions[:method]} - #{route_container.route.to_s}"
126
+ log "Skipping route with verb #{route_container.verb} - #{route_container.route.to_s}"
109
127
  end
110
128
  end
111
129
  }
@@ -120,203 +138,6 @@ module Stratagem::Crawler::Session
120
138
 
121
139
  private
122
140
 
123
- def visit(route_container)
124
- puts "Visiting #{route_container.route}"
125
- build_urls(route_container).each do |route_info|
126
- call_route(route_container, route_info)
127
- end
128
- end
129
-
130
- def call_route(route, route_info, track_invocations=true)
131
- return if route_info.nil?
132
-
133
- puts 'CALLING: .'+route_info[:verb].downcase+". - "+route_info[:path]
134
- verb = route_info[:verb].downcase
135
- verb = 'get' if verb == '' || verb == 'any'
136
-
137
- begin
138
- invocations = model_invocations_for_request do
139
- case verb
140
- when 'get'
141
- do_get(route, route_info[:path])
142
- puts "\tresponse code: #{response.code}" if response
143
- when 'post'
144
- when 'put'
145
- do_put(route, route_info[:path])
146
- when 'delete'
147
- else
148
- raise "Unsupported verb: #{route[:verb]}"
149
- end
150
- end
151
-
152
- if (response)
153
- changes = detect_attribute_changes_in_models(invocations)
154
- puts "\tfound #{invocations.size} invocations"
155
- puts "\tchanges: #{changes.values.inspect}" if changes.size > 0
156
- site_model.add(route, response, invocations, changes) {|redirect_url| redirect_proc.call(redirect_url) }
157
- else
158
- puts "ERROR: did not call #{route_info.inspect}"
159
- end
160
- rescue
161
- puts $!.message
162
- puts $!.backtrace
163
- end
164
- end
165
-
166
- def do_get(route,path)
167
- get path
168
- end
169
-
170
- def do_put(route,path)
171
-
172
- # note: this should fail to generate anything meaningful, as we have not yet set up the parameters
173
- put path
174
-
175
- # let's find out what the method is looking for in the params object
176
- params = map_models_to_attributes(infer_models_for_param_reads(route,controller.params.hash_reads))
177
-
178
- # run again with the params
179
- puts "PUTTING: #{path} with #{params.inspect}"
180
-
181
- invocation_delta = model_invocations_for_request(:write) do
182
- put path, params
183
- end
184
- end
185
-
186
- def map_models_to_attributes(models)
187
- result = {}
188
- models.each {|param_read,model|
189
- result[param_read] = aquifer.mock_attributes(model.klass)
190
- }
191
- result
192
- end
193
-
194
- def infer_models_for_param_reads(route,param_reads)
195
- param_reads = param_reads.select {|read| read.to_s !~ /_id$/ }
196
- param_reads -= [:action,'action',:controller,'controller',:id,'id',:format,'format']
197
-
198
- result = {}
199
-
200
- # resolve param reads to model types
201
- # only support simple expected mappings at the moment
202
- param_reads.each do |param_read|
203
- class_name = param_read.to_s.camelize
204
- if (class_name.singularize == class_name)
205
- # this looks promising
206
- model = application_model.models.find {|model| model.klass.name == class_name }
207
- if (model)
208
- puts "\t\tresolved param #{param_read} to #{model.klass.name}"
209
- result[param_read] = model
210
- end
211
- end
212
- end
213
-
214
- result
215
- end
216
-
217
- def detect_attribute_changes_in_models(invocations)
218
- changes = {}
219
- invocations.select {|invocation| invocation.type == :write }.each do |invocation|
220
- if (invocation.model_instance)
221
- model = application_model.models.find {|m| m.klass == invocation.model_instance.class }
222
-
223
- puts "\t\t#{invocation.model_class}.#{invocation.method} - #{invocation.model_instance}"
224
- prior = aquifer.instances_of(invocation.model_instance.class).find {|m| m.id == invocation.model_instance.id }
225
- post = invocation.model_instance
226
- attribute_names = (prior.stratagem.attribute_names + prior.stratagem.foreign_keys)
227
- changes[model] = attribute_names.select {|an|
228
- begin
229
- prior.send(an) != post.send(an)
230
- rescue
231
- puts "\t\t\t#{an} cannot be determined - #{$!.message}"
232
- end
233
- }
234
- end
235
- end
236
- changes
237
- end
238
-
239
- # Builds a list of string URLs for a given route. This is done
240
- # by replacing :xyz_id segments in the route with known values
241
- # from the well
242
- def build_urls(route_container)
243
- urls = []
244
- route = route_container.route
245
- param_types = (self.parameter_types[route_container] ||= resolve_parameter_types(route_container))
246
- route_infos, params = build_url(route_container, param_types)
247
- # puts "route: #{route_container.route.to_s} - #{parameter_types.inspect} - permutations:"
248
- # route_infos.each do |info|
249
- # puts "\t#{info[:path]}"
250
- # end
251
- route_infos
252
- end
253
-
254
- def url_permutations(meta_segments, segment_stack=[], &block)
255
- if (segment_stack.size == meta_segments.size)
256
- yield segment_stack
257
- else
258
- cursor = segment_stack.size
259
- options = meta_segments[cursor]
260
- if (options.kind_of?(Array))
261
- options.each do |option|
262
- url_permutations(meta_segments, segment_stack + [option], &block)
263
- end
264
- else
265
- url_permutations(meta_segments, segment_stack + [options], &block)
266
- end
267
- end
268
- end
269
-
270
- def build_url(route_container, parameter_types={})
271
- params = {}
272
- route = route_container.route
273
- name = route.to_s
274
- verb = route.conditions[:method].to_s
275
-
276
- parameter_types ||= {}
277
-
278
- i = 12345
279
- segs = route.segments.inject([]) {|accumulated,segment|
280
- s = segment.to_s
281
- if (s =~ /^:/)
282
- model = parameter_types[s]
283
- value = nil
284
- if (model)
285
- if (aquifer.instances_of(model).size == 0)
286
- aquifer.print
287
- end
288
- value = (aquifer.instances_of model).map {|inst|
289
- attr_name = s.gsub(/^:/, '').to_sym
290
- if inst.methods_include?(attr_name)
291
- inst.send(attr_name)
292
- else
293
- inst.id
294
- end
295
- }
296
- else
297
- i += 1
298
- value = [i]
299
- end
300
- accumulated << value
301
- params[s] = value
302
- else
303
- accumulated << s
304
- end
305
- accumulated
306
- }
307
-
308
- routes = []
309
- reqs = route.requirements.empty? ? "" : route.requirements.inspect
310
- url_permutations(segs) do |segments|
311
- path = segments.join('').gsub('(.:format)', '').gsub(/\/$/, '')
312
- puts "\t\tbuilt url: #{path}"
313
- permutation = {:name => name, :verb => verb, :segs => segs, :reqs => reqs, :path => path}
314
- routes << permutation
315
- end
316
-
317
- [routes, params]
318
- end
319
-
320
141
  def handle_redirect(redirect_url)
321
142
  existing_pages = site_model.pages_for(response.redirect_url)
322
143
  if (existing_pages.size > 0)
@@ -326,59 +147,10 @@ module Stratagem::Crawler::Session
326
147
  get redirect_url
327
148
  end
328
149
 
329
- site_model.add(nil, response) {|redirect_url|
150
+ site_model.add(nil, request, response) {|redirect_url|
330
151
  # TODO - record as bug!
331
152
  puts "recursive redirect #{redirect_url}"
332
153
  }
333
154
  end
334
155
  end
335
-
336
- def resolve_parameter_types(route_container)
337
- puts "\tresolving parameter types"
338
- resolved_parameters = {}
339
- route_infos, params = build_url(route_container, resolved_parameters)
340
- route_info = route_infos.first
341
- unknown_params = params.keys
342
- log "\tunknown params: #{unknown_params.inspect} - #{unknown_params.size}"
343
- progress = nil
344
- while ((unknown_params.size > 0) && (progress.nil? || (progress > 0)))
345
- progress = 0
346
-
347
- puts "\tloading model invocations for request"
348
- delta = model_invocations_for_request do
349
- call_route(route_container, route_info, false)
350
- end
351
-
352
- puts "\tcalled route, found #{delta.size} invocations"
353
-
354
- unknown_params.clone.each do |key|
355
- value = params[key]
356
- value_s = params[key].map {|v| v.to_s }
357
- delta.each do |invocation|
358
- # puts "\t#{route_info[:path]} - #{invocation.model_class.name} - #{invocation.method} - #{invocation.args.inspect} - #{value_s}"
359
- # TODO inspect is a hack, refactor
360
- if (invocation.args.include?(value.first)) || (invocation.args.inspect.include?('"'+value.first.to_s+'"'))
361
- # found match
362
-
363
- puts "\t\tresolved #{key} to #{invocation.model_class}"
364
- unknown_params.delete(key)
365
- resolved_parameters[key] = invocation.model_class
366
- progress += 1
367
-
368
- break
369
- end
370
- end
371
- end
372
-
373
- route_infos, params = build_url(route_container, resolved_parameters)
374
- route_info = route_infos.first
375
- end
376
-
377
- if (resolved_parameters.size > 0)
378
- resolved_parameters
379
- else
380
- nil
381
- end
382
- end
383
-
384
156
  end