stratagem 0.1.7

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 (101) hide show
  1. data/Manifest +99 -0
  2. data/Rakefile +17 -0
  3. data/bin/stratagem +10 -0
  4. data/init.rb +2 -0
  5. data/lib/bootstrap.rb +31 -0
  6. data/lib/stratagem/authentication.rb +64 -0
  7. data/lib/stratagem/auto_mock/aquifer.rb +86 -0
  8. data/lib/stratagem/auto_mock/factory.rb +213 -0
  9. data/lib/stratagem/auto_mock/value_generator.rb +174 -0
  10. data/lib/stratagem/auto_mock.rb +6 -0
  11. data/lib/stratagem/blocker.rb +16 -0
  12. data/lib/stratagem/client.rb +32 -0
  13. data/lib/stratagem/command.rb +13 -0
  14. data/lib/stratagem/commands/analyze.rb +22 -0
  15. data/lib/stratagem/commands/base.rb +11 -0
  16. data/lib/stratagem/commands/devel_crawl.rb +27 -0
  17. data/lib/stratagem/commands/devel_mock.rb +10 -0
  18. data/lib/stratagem/commands.rb +7 -0
  19. data/lib/stratagem/crawler/authentication.rb +109 -0
  20. data/lib/stratagem/crawler/form.rb +101 -0
  21. data/lib/stratagem/crawler/html_utils.rb +92 -0
  22. data/lib/stratagem/crawler/session.rb +296 -0
  23. data/lib/stratagem/crawler/site_model.rb +138 -0
  24. data/lib/stratagem/crawler/trace_utils.rb +10 -0
  25. data/lib/stratagem/crawler.rb +9 -0
  26. data/lib/stratagem/extensions/class.rb +9 -0
  27. data/lib/stratagem/extensions/hash.rb +16 -0
  28. data/lib/stratagem/extensions/module.rb +11 -0
  29. data/lib/stratagem/extensions/object.rb +15 -0
  30. data/lib/stratagem/extensions/red_parse.rb +86 -0
  31. data/lib/stratagem/extensions/string.rb +20 -0
  32. data/lib/stratagem/extensions.rb +6 -0
  33. data/lib/stratagem/framework_extensions/controllers/action_controller.rb +10 -0
  34. data/lib/stratagem/framework_extensions/controllers/action_mailer.rb +12 -0
  35. data/lib/stratagem/framework_extensions/controllers.rb +5 -0
  36. data/lib/stratagem/framework_extensions/models/adapters/active_model/detect.rb +7 -0
  37. data/lib/stratagem/framework_extensions/models/adapters/active_model/extensions.rb +35 -0
  38. data/lib/stratagem/framework_extensions/models/adapters/active_model/metadata.rb +103 -0
  39. data/lib/stratagem/framework_extensions/models/adapters/active_model/tracing.rb +50 -0
  40. data/lib/stratagem/framework_extensions/models/adapters/authlogic/detect.rb +11 -0
  41. data/lib/stratagem/framework_extensions/models/adapters/authlogic/extensions.rb +10 -0
  42. data/lib/stratagem/framework_extensions/models/adapters/authlogic/metadata.rb +30 -0
  43. data/lib/stratagem/framework_extensions/models/adapters/authlogic/tracing.rb +4 -0
  44. data/lib/stratagem/framework_extensions/models/adapters/common/authentication_metadata.rb +21 -0
  45. data/lib/stratagem/framework_extensions/models/adapters/restful_authentication/detect.rb +13 -0
  46. data/lib/stratagem/framework_extensions/models/adapters/restful_authentication/extensions.rb +19 -0
  47. data/lib/stratagem/framework_extensions/models/adapters/restful_authentication/metadata.rb +30 -0
  48. data/lib/stratagem/framework_extensions/models/adapters/restful_authentication/tracing.rb +4 -0
  49. data/lib/stratagem/framework_extensions/models/annotations.rb +79 -0
  50. data/lib/stratagem/framework_extensions/models/detect.rb +7 -0
  51. data/lib/stratagem/framework_extensions/models/metadata.rb +85 -0
  52. data/lib/stratagem/framework_extensions/models/mocking.rb +23 -0
  53. data/lib/stratagem/framework_extensions/models/tracing.rb +71 -0
  54. data/lib/stratagem/framework_extensions/models.rb +21 -0
  55. data/lib/stratagem/framework_extensions/rails.rb +8 -0
  56. data/lib/stratagem/framework_extensions.rb +6 -0
  57. data/lib/stratagem/interface/browser.rb +37 -0
  58. data/lib/stratagem/interface/public/images/backgrounds/content.png +0 -0
  59. data/lib/stratagem/interface/public/images/backgrounds/shadow.png +0 -0
  60. data/lib/stratagem/interface/public/javascripts/jquery-1.4.2.min.js +154 -0
  61. data/lib/stratagem/interface/public/javascripts/stratagem.js +27 -0
  62. data/lib/stratagem/interface/public/javascripts/stratagem_debug.js +53 -0
  63. data/lib/stratagem/interface/public/stylesheets/960.css +1 -0
  64. data/lib/stratagem/interface/public/stylesheets/reset.css +10 -0
  65. data/lib/stratagem/interface/public/stylesheets/stratagem.css +20 -0
  66. data/lib/stratagem/interface/public/stylesheets/stratagem_debug.css +20 -0
  67. data/lib/stratagem/interface/views/debug.haml +43 -0
  68. data/lib/stratagem/interface/views/index.haml +35 -0
  69. data/lib/stratagem/labs/auto_mock.rb +7 -0
  70. data/lib/stratagem/labs/crawler.rb +0 -0
  71. data/lib/stratagem/logger.rb +46 -0
  72. data/lib/stratagem/model/application.rb +157 -0
  73. data/lib/stratagem/model/components/base.rb +55 -0
  74. data/lib/stratagem/model/components/controller.rb +118 -0
  75. data/lib/stratagem/model/components/model.rb +170 -0
  76. data/lib/stratagem/model/components/reference.rb +30 -0
  77. data/lib/stratagem/model/components/route.rb +53 -0
  78. data/lib/stratagem/model/components/static_file.rb +18 -0
  79. data/lib/stratagem/model/components/view.rb +186 -0
  80. data/lib/stratagem/model/parse_util.rb +61 -0
  81. data/lib/stratagem/model.rb +12 -0
  82. data/lib/stratagem/model_builder.rb +146 -0
  83. data/lib/stratagem/recipes/deploy.rb +30 -0
  84. data/lib/stratagem/scan/checks/capistrano/secure_deploy.rb +43 -0
  85. data/lib/stratagem/scan/checks/email_address.rb +15 -0
  86. data/lib/stratagem/scan/checks/error_pages.rb +25 -0
  87. data/lib/stratagem/scan/checks/filter_parameter_logging.rb +6 -0
  88. data/lib/stratagem/scan/checks/mongo_mapper/base.rb +19 -0
  89. data/lib/stratagem/scan/checks/mongo_mapper/foreign_keys_exposed.rb +32 -0
  90. data/lib/stratagem/scan/checks/routes.rb +16 -0
  91. data/lib/stratagem/scan/checks/ssl/secure_login_page.rb +19 -0
  92. data/lib/stratagem/scan/checks/ssl/secure_login_submit.rb +18 -0
  93. data/lib/stratagem/scan/result.rb +45 -0
  94. data/lib/stratagem/scan.rb +19 -0
  95. data/lib/stratagem/scanner.rb +32 -0
  96. data/lib/stratagem/site_crawler.rb +47 -0
  97. data/lib/stratagem/snapshot.rb +33 -0
  98. data/lib/stratagem.rb +77 -0
  99. data/lib/tasks/_old_stratagem.rake +99 -0
  100. data/stratagem.gemspec +56 -0
  101. metadata +380 -0
@@ -0,0 +1,296 @@
1
+ require 'nokogiri'
2
+
3
+ require 'action_pack'
4
+ require 'action_controller'
5
+
6
+ class CrawlError < StratagemError; end
7
+
8
+ # require 'rack/lint'
9
+ # module Rack
10
+ # # Rack::Lint validates your application and the requests and
11
+ # # responses according to the Rack spec.
12
+ #
13
+ # class Lint
14
+ # alias_method :old_call, :call
15
+ #
16
+ # def call(env)
17
+ # data = env['rack.input']
18
+ # data.set_encoding(Encoding::ASCII_8BIT) if data.respond_to?(:set_encoding)
19
+ #
20
+ # status, headers, body = old_call(env)
21
+ # body.close # fix for Rack
22
+ # [status,headers,body]
23
+ # end
24
+ # end
25
+ # end
26
+
27
+ PHASES = [:unauthenticated,:authenticated]
28
+
29
+ module Stratagem::Crawler::Session
30
+ include ActionController::Integration::Runner
31
+ include Stratagem::Crawler::HtmlUtils
32
+ include Stratagem::Crawler::TraceUtils
33
+ include Stratagem::Crawler::Authentication
34
+
35
+ def log(msg)
36
+ Stratagem.logger.debug msg
37
+ end
38
+
39
+ def crawler_session(application_model=nil)
40
+ @model = application_model
41
+ @model ||= Stratagem::ModelBuilder.new.run
42
+ @redirect_proc = Proc.new {|redirect_url| handle_redirect(redirect_url) }
43
+ @parameter_types = {} # routecontainer -> {:route_segment => Model, :route_segment => Model}
44
+ open_session do |session|
45
+ @session = session
46
+ phase(:unauthenticated)
47
+ yield
48
+ end
49
+ end
50
+
51
+ def application_model
52
+ @model
53
+ end
54
+
55
+ def site_models
56
+ @site_models ||= {} # builds models of the site for various phases of analysis, see PHASES
57
+ end
58
+
59
+ def site_model
60
+ raise Stratagem::Crawler::CrawlError.new("Phase not specified") unless @current_model
61
+ @current_model
62
+ end
63
+
64
+ def phase(new_phase)
65
+ @current_phase = new_phase
66
+ @current_model = site_models[@current_phase] ||= Stratagem::Crawler::SiteModel.new
67
+ end
68
+
69
+ def phases
70
+ site_models
71
+ end
72
+
73
+ def display
74
+ # print out pages and inbound / outbound links
75
+ site_model.pages.each do |page|
76
+ log "Page: #{page.url} - #{page.title} - #{page.response.code}"
77
+ page.outbound_edges.each do |edge|
78
+ log "\tout: #{edge.to.url} - #{edge.to.title} - #{edge.to.route}"
79
+ end
80
+ page.inbound_edges.each do |edge|
81
+ log "\tin: #{edge.from.url} - #{edge.from.title}"
82
+ end
83
+ end
84
+ end
85
+
86
+ def crawl
87
+ # grab all pages independently
88
+ @model.routes.invalid.each {|route_container|
89
+ puts "skipping invalid route #{route_container.route.to_s}"
90
+ }
91
+
92
+ authentication_controller = nil
93
+ if (@current_phase == :authenticated)
94
+ route = @model.routes.recognize(authentication.login_page)
95
+ authentication_controller = route.controller
96
+ end
97
+
98
+ @model.routes.each {|route_container|
99
+ if authentication_controller && route_container.controller && (route_container.controller.klass == authentication_controller.klass)
100
+ log "Skipping authentication routes #{route_container.route.to_s}"
101
+ else
102
+ visit(route_container) unless @model.routes.invalid.include?(route_container)
103
+ end
104
+ }
105
+
106
+ # establish edges on site graph
107
+ site_model.pages.each do |page|
108
+ site_model.add_edge(page, page.redirected_to, :redirect) if page.redirected?
109
+ end
110
+
111
+ site_model
112
+ end
113
+
114
+ private
115
+
116
+ def visit(route_container)
117
+ puts "visiting #{route_container.route}"
118
+ build_urls(route_container).each do |route_info|
119
+ call_route(route_container, route_info)
120
+ end
121
+ end
122
+
123
+ def call_route(route, route_info)
124
+ puts 'CALLING: .'+route_info[:verb].downcase+". - "+route_info[:path]
125
+ verb = route_info[:verb].downcase
126
+ verb = 'get' if verb == '' || verb == 'any'
127
+ case verb
128
+ when 'get'
129
+ do_get(route, route_info[:path])
130
+ puts response.code if response
131
+ when 'post'
132
+ when 'put'
133
+ when 'delete'
134
+ else
135
+ raise "Unsupported verb: #{route[:verb]}"
136
+ end
137
+ end
138
+
139
+ # Builds a list of string URLs for a given route. This is done
140
+ # by replacing :xyz_id segments in the route with known values
141
+ # from the well
142
+ def build_urls(route_container)
143
+ urls = []
144
+ route = route_container.route
145
+ parameter_types = (@parameter_types[route_container] ||= resolve_parameter_types(route_container))
146
+ route_infos, params = build_url(route_container, parameter_types)
147
+ puts "route: #{route_container.route.to_s} permutations:"
148
+ route_infos.each do |info|
149
+ puts "\t#{info[:path]}"
150
+ end
151
+ route_infos
152
+ end
153
+
154
+ def url_permutations(meta_segments, segment_stack=[], &block)
155
+ if (segment_stack.size == meta_segments.size)
156
+ yield segment_stack
157
+ else
158
+ cursor = segment_stack.size
159
+ options = meta_segments[cursor]
160
+ if (options.kind_of?(Array))
161
+ options.each do |option|
162
+ url_permutations(meta_segments, segment_stack + [option], &block)
163
+ end
164
+ else
165
+ url_permutations(meta_segments, segment_stack + [options], &block)
166
+ end
167
+ end
168
+ end
169
+
170
+ def build_url(route_container, parameter_types={})
171
+ params = {}
172
+ route = route_container.route
173
+ name = route.to_s
174
+ verb = route.conditions[:method].to_s
175
+
176
+ parameter_types ||= {}
177
+
178
+ i = 12345
179
+ segs = route.segments.inject([]) {|accumulated,segment|
180
+ s = segment.to_s
181
+ if (s =~ /^:/)
182
+ model = parameter_types[s]
183
+ value = nil
184
+ if (model)
185
+ value = (Stratagem::AutoMock::Aquifer.instance.instances_of model).map {|inst|
186
+ attr_name = s.gsub(/^:/, '').to_sym
187
+ if inst.methods_include?(attr_name)
188
+ puts "#{attr_name} is a method on the object"
189
+ inst.send(attr_name)
190
+ else
191
+ puts "#{attr_name} is being mapped to the id on the object"
192
+ inst.id
193
+ end
194
+ }
195
+ else
196
+ i += 1
197
+ value = [i]
198
+ end
199
+ accumulated << value
200
+ params[s] = value
201
+ else
202
+ accumulated << s
203
+ end
204
+ accumulated
205
+ }
206
+
207
+ routes = []
208
+ reqs = route.requirements.empty? ? "" : route.requirements.inspect
209
+ url_permutations(segs) do |segments|
210
+ path = segments.join('').gsub('(.:format)', '').gsub(/\/$/, '')
211
+ permutation = {:name => name, :verb => verb, :segs => segs, :reqs => reqs, :path => path}
212
+ routes << permutation
213
+ end
214
+
215
+ [routes, params]
216
+ end
217
+
218
+ def handle_redirect(redirect_url)
219
+ existing_pages = site_model.pages_for(response.redirect_url)
220
+ if (existing_pages.size > 0)
221
+ existing_pages.first
222
+ else
223
+ invocation_delta = model_invocations_for_request do
224
+ get redirect_url
225
+ end
226
+
227
+ site_model.add(nil, response) {|redirect_url|
228
+ # TODO - record as bug!
229
+ puts "recursive redirect #{redirect_url}"
230
+ }
231
+ end
232
+ end
233
+
234
+ def do_get(route,path)
235
+ begin
236
+ get path
237
+ site_model.add(route, response) {|redirect_url| @redirect_proc.call(redirect_url) }
238
+ rescue
239
+ puts $!.message
240
+ puts path
241
+ #puts $!.backtrace
242
+ end
243
+ end
244
+
245
+ def resolve_parameter_types(route_container)
246
+ puts "resolving parameter types for #{route_container.route}"
247
+ resolved_parameters = {}
248
+ route_infos, params = build_url(route_container, resolved_parameters)
249
+ route_info = route_infos.first
250
+ unknown_params = params.keys
251
+ puts "unknown params: #{unknown_params}"
252
+ progress = nil
253
+ while ((unknown_params.size > 0) && (progress.nil? || (progress > 0)))
254
+ progress = 0
255
+
256
+ # p route_infos
257
+ # puts "---"
258
+ delta = model_invocations_for_request do
259
+ call_route(route_container, route_info)
260
+ end
261
+
262
+ puts "delta - #{delta.size}"
263
+ #p delta
264
+
265
+ unknown_params.clone.each do |key|
266
+ value = params[key]
267
+ value_s = params[key].map {|v| v.to_s }
268
+ delta.each do |invocation|
269
+ puts "#{route_info[:path]} - #{invocation.model_class.name} - #{invocation.method} - #{invocation.args.inspect} - #{value_s}"
270
+
271
+ # TODO inspect is a hack, refactor
272
+ if (invocation.args.include?(value.first)) || (invocation.args.inspect.include?('"'+value.first.to_s+'"'))
273
+ # found match
274
+
275
+ puts "\tresolved #{key} to #{invocation.model_class}"
276
+ unknown_params.delete(key)
277
+ resolved_parameters[key] = invocation.model_class
278
+ progress += 1
279
+
280
+ break
281
+ end
282
+ end
283
+ end
284
+
285
+ route_infos, params = build_url(route_container, resolved_parameters)
286
+ route_info = route_infos.first
287
+ end
288
+ if (resolved_parameters.size > 0)
289
+ resolved_parameters
290
+ else
291
+ nil
292
+ end
293
+ end
294
+
295
+
296
+ end
@@ -0,0 +1,138 @@
1
+ module Stratagem::Crawler
2
+ class SiteModel
3
+ include Stratagem::Crawler::HtmlUtils
4
+
5
+ attr_reader :pages, :edges
6
+
7
+ def initialize
8
+ @pages = []
9
+ @edges = []
10
+ end
11
+
12
+ def export
13
+ {
14
+ :pages => @pages.map {|page| page.export },
15
+ :edges => @edges.map {|edge| edge.export }
16
+ }
17
+ end
18
+
19
+ def add_edge(from,to,type)
20
+ self.edges << Edge.new(from,to,type)
21
+ end
22
+
23
+ def add(route, response, &block)
24
+ page = Page.new(self, response, &block)
25
+ self.pages << page
26
+ page
27
+ end
28
+
29
+ def pages_for(id)
30
+ if (id.kind_of?(String))
31
+ pages.select {|page| page.url == id }
32
+ else
33
+ pages.select {|page| page.route == id }
34
+ end
35
+ end
36
+
37
+ end
38
+
39
+ class Edge
40
+ # type -> :link, :redirect,
41
+ attr_accessor :from, :to, :type
42
+
43
+ def initialize(from, to, type)
44
+ @from = from
45
+ @to = to
46
+ @type = type
47
+ end
48
+
49
+ def export
50
+ {
51
+ :from => from.object_id,
52
+ :to => to.object_id,
53
+ :type => type
54
+ }
55
+ end
56
+ end
57
+
58
+ class Page
59
+ include Stratagem::Crawler::HtmlUtils
60
+
61
+ attr_reader :response
62
+
63
+ attr_accessor :url
64
+ attr_accessor :path
65
+ attr_accessor :method
66
+ attr_accessor :redirected_to
67
+ attr_accessor :document
68
+
69
+ def initialize(site_model, response, &block)
70
+ @site_model = site_model
71
+ init(response, &block)
72
+ end
73
+
74
+ def route
75
+ Stratagem::Model::Application.instance.routes.recognize(self)
76
+ end
77
+
78
+ def export
79
+ {
80
+ :external_id => self.object_id,
81
+ :url => url,
82
+ :path => path,
83
+ :method => method,
84
+ :redirected_to_page_external_id => redirected_to ? redirected_to.object_id : nil,
85
+ :route_external_id => route.object_id
86
+ }
87
+ end
88
+
89
+ def init(response, &block)
90
+ @response = response.clone
91
+ @url = response.request.url
92
+ @path = response.request.path
93
+ @method = response.request.method
94
+ @document = Nokogiri::HTML(response.body)
95
+ self.redirected_to = block.call(response.redirect_url) if response.redirect?
96
+ end
97
+
98
+ def reload(&block)
99
+ # TODO - should support all the verbs and params, but
100
+ # hack together for now to reload the authenticity token
101
+ response = yield url
102
+ init(response) {|redirected_to| }
103
+ end
104
+
105
+ def redirected?
106
+ !self.redirected_to.nil?
107
+ end
108
+
109
+ def forms
110
+ self.parse_forms(@document)
111
+ end
112
+
113
+ def login_form
114
+ self.find_login_form(@document)
115
+ end
116
+
117
+ def to_html
118
+ @document.to_html
119
+ end
120
+
121
+ def outbound_edges(type=nil)
122
+ @site_model.edges.select {|edge| edge.from == self && (type.nil? || (type == edge.type)) }
123
+ end
124
+
125
+ def inbound_edges(type=nil)
126
+ @site_model.edges.select {|edge| (edge.to == self) && (type.nil? || (type == edge.type)) }
127
+ end
128
+
129
+ def title
130
+ unless @title
131
+ title = (@document/'head title').first
132
+ @title = title.inner_html if title
133
+ end
134
+ @title
135
+ end
136
+ end
137
+
138
+ end
@@ -0,0 +1,10 @@
1
+ module Stratagem::Crawler
2
+ module TraceUtils
3
+ def model_invocations_for_request()
4
+ prior_invocations = ActiveRecord::Base.stratagem.invocations_audit.clone
5
+ yield
6
+ post_invocations = ActiveRecord::Base.stratagem.invocations_audit.clone
7
+ delta = post_invocations - prior_invocations
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ module Stratagem::Crawler
2
+ end
3
+
4
+ require 'stratagem/crawler/form'
5
+ require 'stratagem/crawler/trace_utils'
6
+ require 'stratagem/crawler/html_utils'
7
+ require 'stratagem/crawler/authentication'
8
+ require 'stratagem/crawler/session'
9
+ require 'stratagem/crawler/site_model'
@@ -0,0 +1,9 @@
1
+ class Class
2
+ def classes
3
+ list = [self]
4
+ c = self
5
+ list << c while ((c = c.superclass) != nil)
6
+ list
7
+ end
8
+ end
9
+
@@ -0,0 +1,16 @@
1
+ class Hash
2
+ alias_method :ruby_get, :[]
3
+ attr_reader :hash_reads, :hash_writes
4
+
5
+ def [](name)
6
+ (@hash_reads ||= []) << name if (@auditing)
7
+ ruby_get name
8
+ end
9
+
10
+ def enable_auditing
11
+ @auditing = true
12
+ end
13
+
14
+ # def []=
15
+ # end
16
+ end
@@ -0,0 +1,11 @@
1
+ class Module
2
+ def subclasses
3
+ classes = []
4
+ ObjectSpace.each_object(Class) do |c|
5
+ next unless c.superclass == self || c.ancestors.include?(self)
6
+ next if c == self
7
+ classes << c
8
+ end
9
+ classes
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ class Object
2
+ def methods_include?(name)
3
+ methods.include?(name.to_sym) || methods.include?(name.to_s)
4
+ end
5
+
6
+ def self.subclasses
7
+ classes = []
8
+ ObjectSpace.each_object(Class) do |c|
9
+ next unless c.superclass == self || c.ancestors.include?(self)
10
+ next if c == self
11
+ classes << c
12
+ end
13
+ classes
14
+ end
15
+ end
@@ -0,0 +1,86 @@
1
+ class RedParse::Node
2
+ def talking_about?(model)
3
+ talking_about = false
4
+
5
+ if self.receiver.methods_include?(:name)
6
+ if ((self.receiver) && self.receiver.name == model.klass.name)
7
+ # puts "\treceiver name #{self.receiver.name} is equal to #{model.klass.name}"
8
+ talking_about = true
9
+ elsif (self.receiver)
10
+ name = self.receiver.name
11
+ # if it's lowercase then it's possibly referencing an association
12
+ if (name.downcase == name)
13
+ # look through the models to see if one has an association with this name and class
14
+ Stratagem::Model::Application.instance.models.each do |app_model|
15
+ talking_about = app_model.association_match?(name, model)
16
+ break if talking_about
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ talking_about
23
+ end
24
+
25
+ # iterates the node and figures out the class of the leaf that a call is talking about
26
+ def dereference
27
+ # recursion is evil
28
+ path = []
29
+ current_node = self
30
+ # puts "current:#{current_node.inspect}"
31
+ if (current_node.kind_of?(RedParse::VarNode))
32
+ path << current_node.name if current_node.methods_include?(:name)
33
+ else
34
+ while (current_node.methods_include?(:receiver) && (current_node = current_node.receiver) != nil)
35
+ path << current_node.name if current_node.methods_include?(:name)
36
+ end
37
+ end
38
+ # p path
39
+ previous = nil
40
+ path.reverse!
41
+ path.map! {|element|
42
+ new_val = element
43
+ if (element.downcase != element)
44
+ # class?
45
+ begin
46
+ new_val = Class.class_eval(element)
47
+ rescue
48
+ logger.error "Unable to load class #{element} in #{path.inspect}"
49
+ end
50
+ elsif (element.pluralize == element)
51
+ # collection?
52
+ if (previous)
53
+ if (previous.kind_of?(Class))
54
+ # look up the loaded model of the class
55
+ model = Stratagem::Model::Application.instance.models.find {|m| m.klass == previous }
56
+ if (model)
57
+ match = previous.reflect_on_all_associations.find {|assoc| assoc.name.to_sym == element.to_sym }
58
+ if (match)
59
+ new_val = Class.class_eval(match.class_name)
60
+ else
61
+ logger.error "I give up, cannot determine what #{element} is in #{path.inspect}"
62
+ end
63
+ end
64
+ else
65
+ logger.error "Unknown previous type when trying to dereference a collection #{element} in #{path.inspect}"
66
+ end
67
+ else
68
+ logger.error "Unable to determine prior element for #{element} in #{path.inspect}"
69
+ end
70
+ elsif previous
71
+ # call to the class / object in the previous statement
72
+ if (['find','all','first','last'].include?(element))
73
+ # then expect to receive an instance of the previous type
74
+ new_val = previous
75
+ end
76
+ end
77
+ previous = new_val
78
+ new_val
79
+ }
80
+ path.last
81
+ end
82
+
83
+ def logger
84
+ Rails.logger
85
+ end
86
+ end
@@ -0,0 +1,20 @@
1
+ class String
2
+ def stratagem_strip_erb
3
+ self.gsub(/^[<%=]+/, '').gsub(/[-%>]+$/,'').strip
4
+ end
5
+
6
+ def stratagem_contains_token?(token)
7
+ match = false
8
+ [
9
+ Regexp.compile("^#{token}$", true),
10
+ Regexp.compile("^#{token}[^A-Za-z0-9]", true),
11
+ Regexp.compile("[^A-Za-z0-9]#{token}$", true),
12
+ ].each do |regex|
13
+ if (regex.match(self))
14
+ match = true
15
+ break
16
+ end
17
+ end
18
+ match
19
+ end
20
+ end
@@ -0,0 +1,6 @@
1
+ require 'stratagem/extensions/red_parse'
2
+ require 'stratagem/extensions/class'
3
+ require 'stratagem/extensions/string'
4
+ require 'stratagem/extensions/hash'
5
+ require 'stratagem/extensions/object'
6
+ require 'stratagem/extensions/module'
@@ -0,0 +1,10 @@
1
+ class ActionController::Request
2
+ alias_method :rails_parameters, :parameters
3
+ undef_method :parameters
4
+
5
+ def parameters
6
+ params = rails_parameters
7
+ params.enable_auditing
8
+ params
9
+ end
10
+ end
@@ -0,0 +1,12 @@
1
+ module ActionMailer
2
+ class Base
3
+ def create!(method_name, *parameters)
4
+ puts "Skipping action mailer #{method_name}, #{parameters.inspect}"
5
+ end
6
+
7
+ def deliver!(mail = @mail)
8
+ puts "Skipping delivery in action mailer"
9
+ end
10
+ end
11
+ end
12
+
@@ -0,0 +1,5 @@
1
+ module Stratagem::ApplicationExtensions::Controllers; end
2
+
3
+ require 'stratagem/framework_extensions/controllers/action_controller'
4
+ require 'stratagem/framework_extensions/controllers/action_mailer'
5
+
@@ -0,0 +1,7 @@
1
+ module Stratagem::ApplicationExtensions::Models::Adapters::ActiveModel
2
+ class Detect < Stratagem::ApplicationExtensions::Models::Detect
3
+ def self.supports?(model)
4
+ model.ancestors.include?(ActiveRecord::Base)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,35 @@
1
+ class ActiveRecord::Base
2
+ class << self
3
+ def removed_methods=(methods)
4
+ @@removed_methods = methods
5
+ end
6
+
7
+ def removed_methods
8
+ @@removed_methods
9
+ end
10
+
11
+ def removed_validators=(validators)
12
+ @@removed_validators = validators
13
+ end
14
+ end
15
+
16
+ Stratagem::ApplicationExtensions::Models::Annotations.configure(self)
17
+
18
+ end
19
+
20
+ module ActiveRecord::Validations::ClassMethods
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
+
32
+ def removed_validators
33
+ @@removed_validators
34
+ end
35
+ end