stratagem 0.1.7
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest +99 -0
- data/Rakefile +17 -0
- data/bin/stratagem +10 -0
- data/init.rb +2 -0
- data/lib/bootstrap.rb +31 -0
- data/lib/stratagem/authentication.rb +64 -0
- data/lib/stratagem/auto_mock/aquifer.rb +86 -0
- data/lib/stratagem/auto_mock/factory.rb +213 -0
- data/lib/stratagem/auto_mock/value_generator.rb +174 -0
- data/lib/stratagem/auto_mock.rb +6 -0
- data/lib/stratagem/blocker.rb +16 -0
- data/lib/stratagem/client.rb +32 -0
- data/lib/stratagem/command.rb +13 -0
- data/lib/stratagem/commands/analyze.rb +22 -0
- data/lib/stratagem/commands/base.rb +11 -0
- data/lib/stratagem/commands/devel_crawl.rb +27 -0
- data/lib/stratagem/commands/devel_mock.rb +10 -0
- data/lib/stratagem/commands.rb +7 -0
- data/lib/stratagem/crawler/authentication.rb +109 -0
- data/lib/stratagem/crawler/form.rb +101 -0
- data/lib/stratagem/crawler/html_utils.rb +92 -0
- data/lib/stratagem/crawler/session.rb +296 -0
- data/lib/stratagem/crawler/site_model.rb +138 -0
- data/lib/stratagem/crawler/trace_utils.rb +10 -0
- data/lib/stratagem/crawler.rb +9 -0
- data/lib/stratagem/extensions/class.rb +9 -0
- data/lib/stratagem/extensions/hash.rb +16 -0
- data/lib/stratagem/extensions/module.rb +11 -0
- data/lib/stratagem/extensions/object.rb +15 -0
- data/lib/stratagem/extensions/red_parse.rb +86 -0
- data/lib/stratagem/extensions/string.rb +20 -0
- data/lib/stratagem/extensions.rb +6 -0
- data/lib/stratagem/framework_extensions/controllers/action_controller.rb +10 -0
- data/lib/stratagem/framework_extensions/controllers/action_mailer.rb +12 -0
- data/lib/stratagem/framework_extensions/controllers.rb +5 -0
- data/lib/stratagem/framework_extensions/models/adapters/active_model/detect.rb +7 -0
- data/lib/stratagem/framework_extensions/models/adapters/active_model/extensions.rb +35 -0
- data/lib/stratagem/framework_extensions/models/adapters/active_model/metadata.rb +103 -0
- data/lib/stratagem/framework_extensions/models/adapters/active_model/tracing.rb +50 -0
- data/lib/stratagem/framework_extensions/models/adapters/authlogic/detect.rb +11 -0
- data/lib/stratagem/framework_extensions/models/adapters/authlogic/extensions.rb +10 -0
- data/lib/stratagem/framework_extensions/models/adapters/authlogic/metadata.rb +30 -0
- data/lib/stratagem/framework_extensions/models/adapters/authlogic/tracing.rb +4 -0
- data/lib/stratagem/framework_extensions/models/adapters/common/authentication_metadata.rb +21 -0
- data/lib/stratagem/framework_extensions/models/adapters/restful_authentication/detect.rb +13 -0
- data/lib/stratagem/framework_extensions/models/adapters/restful_authentication/extensions.rb +19 -0
- data/lib/stratagem/framework_extensions/models/adapters/restful_authentication/metadata.rb +30 -0
- data/lib/stratagem/framework_extensions/models/adapters/restful_authentication/tracing.rb +4 -0
- data/lib/stratagem/framework_extensions/models/annotations.rb +79 -0
- data/lib/stratagem/framework_extensions/models/detect.rb +7 -0
- data/lib/stratagem/framework_extensions/models/metadata.rb +85 -0
- data/lib/stratagem/framework_extensions/models/mocking.rb +23 -0
- data/lib/stratagem/framework_extensions/models/tracing.rb +71 -0
- data/lib/stratagem/framework_extensions/models.rb +21 -0
- data/lib/stratagem/framework_extensions/rails.rb +8 -0
- data/lib/stratagem/framework_extensions.rb +6 -0
- data/lib/stratagem/interface/browser.rb +37 -0
- data/lib/stratagem/interface/public/images/backgrounds/content.png +0 -0
- data/lib/stratagem/interface/public/images/backgrounds/shadow.png +0 -0
- data/lib/stratagem/interface/public/javascripts/jquery-1.4.2.min.js +154 -0
- data/lib/stratagem/interface/public/javascripts/stratagem.js +27 -0
- data/lib/stratagem/interface/public/javascripts/stratagem_debug.js +53 -0
- data/lib/stratagem/interface/public/stylesheets/960.css +1 -0
- data/lib/stratagem/interface/public/stylesheets/reset.css +10 -0
- data/lib/stratagem/interface/public/stylesheets/stratagem.css +20 -0
- data/lib/stratagem/interface/public/stylesheets/stratagem_debug.css +20 -0
- data/lib/stratagem/interface/views/debug.haml +43 -0
- data/lib/stratagem/interface/views/index.haml +35 -0
- data/lib/stratagem/labs/auto_mock.rb +7 -0
- data/lib/stratagem/labs/crawler.rb +0 -0
- data/lib/stratagem/logger.rb +46 -0
- data/lib/stratagem/model/application.rb +157 -0
- data/lib/stratagem/model/components/base.rb +55 -0
- data/lib/stratagem/model/components/controller.rb +118 -0
- data/lib/stratagem/model/components/model.rb +170 -0
- data/lib/stratagem/model/components/reference.rb +30 -0
- data/lib/stratagem/model/components/route.rb +53 -0
- data/lib/stratagem/model/components/static_file.rb +18 -0
- data/lib/stratagem/model/components/view.rb +186 -0
- data/lib/stratagem/model/parse_util.rb +61 -0
- data/lib/stratagem/model.rb +12 -0
- data/lib/stratagem/model_builder.rb +146 -0
- data/lib/stratagem/recipes/deploy.rb +30 -0
- data/lib/stratagem/scan/checks/capistrano/secure_deploy.rb +43 -0
- data/lib/stratagem/scan/checks/email_address.rb +15 -0
- data/lib/stratagem/scan/checks/error_pages.rb +25 -0
- data/lib/stratagem/scan/checks/filter_parameter_logging.rb +6 -0
- data/lib/stratagem/scan/checks/mongo_mapper/base.rb +19 -0
- data/lib/stratagem/scan/checks/mongo_mapper/foreign_keys_exposed.rb +32 -0
- data/lib/stratagem/scan/checks/routes.rb +16 -0
- data/lib/stratagem/scan/checks/ssl/secure_login_page.rb +19 -0
- data/lib/stratagem/scan/checks/ssl/secure_login_submit.rb +18 -0
- data/lib/stratagem/scan/result.rb +45 -0
- data/lib/stratagem/scan.rb +19 -0
- data/lib/stratagem/scanner.rb +32 -0
- data/lib/stratagem/site_crawler.rb +47 -0
- data/lib/stratagem/snapshot.rb +33 -0
- data/lib/stratagem.rb +77 -0
- data/lib/tasks/_old_stratagem.rake +99 -0
- data/stratagem.gemspec +56 -0
- metadata +380 -0
@@ -0,0 +1,157 @@
|
|
1
|
+
# Note that an exception may be raised when a Gem is missing
|
2
|
+
# and not configured in environment.rb. Check for this case
|
3
|
+
# when loading classes
|
4
|
+
# Stratagem::Model
|
5
|
+
|
6
|
+
require 'set'
|
7
|
+
require 'singleton'
|
8
|
+
|
9
|
+
module Stratagem::Model
|
10
|
+
# container for application
|
11
|
+
class Application
|
12
|
+
include Singleton
|
13
|
+
|
14
|
+
attr_accessor :crawler
|
15
|
+
attr_reader :models, :controllers, :routes, :views, :static_files, :gems, :plugins
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
log "initializing application model"
|
19
|
+
@models = ComponentContainer.new self
|
20
|
+
@controllers = ComponentContainer.new self
|
21
|
+
@routes = RouteContainer.new self
|
22
|
+
@views = ComponentContainer.new self
|
23
|
+
@static_files = ComponentContainer.new self
|
24
|
+
@gems = GemContainer.new self
|
25
|
+
@plugins = PluginContainer.new self
|
26
|
+
end
|
27
|
+
|
28
|
+
def log(msg)
|
29
|
+
Stratagem.logger.debug(msg)
|
30
|
+
end
|
31
|
+
|
32
|
+
def export
|
33
|
+
puts "exporting site model"
|
34
|
+
p crawler.export
|
35
|
+
puts "done."
|
36
|
+
h = {
|
37
|
+
:rails_version => rails_version,
|
38
|
+
:models => @models.export,
|
39
|
+
:controllers => @controllers.export,
|
40
|
+
:routes => @routes.export,
|
41
|
+
:views => @views.export,
|
42
|
+
:gems => @gems.export,
|
43
|
+
:plugins => @plugins.export,
|
44
|
+
:site_model => crawler.export,
|
45
|
+
:references => []
|
46
|
+
}
|
47
|
+
h
|
48
|
+
end
|
49
|
+
|
50
|
+
def rails_version
|
51
|
+
Rails.stratagem_rails_version
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
protected
|
56
|
+
|
57
|
+
class GemContainer
|
58
|
+
include Enumerable
|
59
|
+
|
60
|
+
def initialize(app_model)
|
61
|
+
@app_model = app_model
|
62
|
+
@gems = Gem.loaded_specs
|
63
|
+
end
|
64
|
+
|
65
|
+
def names
|
66
|
+
@gems.map {|g| g[0] }
|
67
|
+
end
|
68
|
+
|
69
|
+
def export(options=nil)
|
70
|
+
@gems.map {|g|
|
71
|
+
name, spec = g
|
72
|
+
[name, {:version => spec.version.version}]
|
73
|
+
}
|
74
|
+
end
|
75
|
+
|
76
|
+
def each
|
77
|
+
@gems.each {|spec| yield spec }
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
class ComponentContainer
|
82
|
+
include Enumerable
|
83
|
+
|
84
|
+
attr_reader :invalid, :missing, :parse_trees, :components, :errors
|
85
|
+
|
86
|
+
def initialize(app_model)
|
87
|
+
@app_model = app_model
|
88
|
+
@components = Set.new()
|
89
|
+
@parse_trees = {}
|
90
|
+
@invalid = []
|
91
|
+
@missing = {}
|
92
|
+
end
|
93
|
+
|
94
|
+
def export(options=nil)
|
95
|
+
{
|
96
|
+
:components => @components.to_a.map {|c| c.export }.compact,
|
97
|
+
:invalid => @invalid.map {|c| c.export }.compact
|
98
|
+
}
|
99
|
+
end
|
100
|
+
|
101
|
+
def find
|
102
|
+
@components.find{|component| yield component }
|
103
|
+
end
|
104
|
+
|
105
|
+
def size
|
106
|
+
@components.size
|
107
|
+
end
|
108
|
+
|
109
|
+
def -(other)
|
110
|
+
@components-other
|
111
|
+
end
|
112
|
+
|
113
|
+
def each
|
114
|
+
@components.each {|e| yield e }
|
115
|
+
end
|
116
|
+
|
117
|
+
def << (component)
|
118
|
+
if (component.kind_of?(Array))
|
119
|
+
component.each {|e|
|
120
|
+
@components << e
|
121
|
+
e.app_model = @app_model if e.methods_include?(:app_model=)
|
122
|
+
}
|
123
|
+
elsif (component.kind_of?(Exception))
|
124
|
+
errors << component
|
125
|
+
else
|
126
|
+
@components << component
|
127
|
+
component.app_model = @app_model if component.methods_include?(:app_model=)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
class RouteContainer < ComponentContainer
|
133
|
+
def recognize(page, method=nil)
|
134
|
+
path = nil
|
135
|
+
if (page.kind_of?(Stratagem::Crawler::Page))
|
136
|
+
method = page.method
|
137
|
+
path = page.path
|
138
|
+
else
|
139
|
+
path = page
|
140
|
+
end
|
141
|
+
#ActionController::Routing::Routes.recognize_path('http://www.example.com/user_sessions/new', {:method => :get})
|
142
|
+
route = ActionController::Routing::Routes.routes.find {|r| r.recognize(path, {:method => method}) }
|
143
|
+
self.find {|r| r.route == route }
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
class PluginContainer < ComponentContainer
|
148
|
+
def names
|
149
|
+
components.map {|plugin| plugin.name }
|
150
|
+
end
|
151
|
+
|
152
|
+
def export(options=nil)
|
153
|
+
names
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Stratagem::Model::Component
|
2
|
+
class Base
|
3
|
+
include Stratagem::Model::ParseUtil
|
4
|
+
|
5
|
+
attr_reader :path, :source, :parse_tree, :klass
|
6
|
+
attr_accessor :app_model
|
7
|
+
|
8
|
+
def initialize(path, parse_tree, klass)
|
9
|
+
@path = path
|
10
|
+
@parse_tree = parse_tree
|
11
|
+
@klass = klass
|
12
|
+
end
|
13
|
+
|
14
|
+
def logger
|
15
|
+
Stratagem.logger
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.logger
|
19
|
+
Stratagem.logger
|
20
|
+
end
|
21
|
+
|
22
|
+
def name
|
23
|
+
classname = @klass ? @klass.name : self.class.name.gsub(/.*[^A-Z0-9a-z]/, '')
|
24
|
+
"#{path}$#{classname}"
|
25
|
+
end
|
26
|
+
|
27
|
+
# loads all classes contained within a given filename
|
28
|
+
def self.load_all(path)
|
29
|
+
if (path =~ /\.rb$/)
|
30
|
+
source = File.read(path)
|
31
|
+
begin
|
32
|
+
parse_tree = RedParse.new(source).parse
|
33
|
+
Stratagem::Model::ParseUtil.find_classes(parse_tree).map {|klass|
|
34
|
+
self.new(path, parse_tree, klass)
|
35
|
+
}
|
36
|
+
rescue
|
37
|
+
puts $!.message
|
38
|
+
logger.fatal "Unable to load parse tree for #{path}"
|
39
|
+
[]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def ==(other)
|
45
|
+
if (other.kind_of?(String))
|
46
|
+
self.path == other
|
47
|
+
elsif (other.kind_of?(self.class))
|
48
|
+
self.path == other.path
|
49
|
+
else
|
50
|
+
raise "unknown comparison to #{other.class.name}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module Stratagem::Model::Component
|
4
|
+
class Action
|
5
|
+
def initialize(controller, name, method)
|
6
|
+
@name = name
|
7
|
+
@method = method # :put, :get, :post, :delete
|
8
|
+
@models_rendered = {} # model => [MethodInvocation]
|
9
|
+
end
|
10
|
+
|
11
|
+
def models_read
|
12
|
+
models(ActiveRecord::Base.stratagem.read_invocations)
|
13
|
+
end
|
14
|
+
|
15
|
+
def models_modified
|
16
|
+
models(ActiveRecord::Base.stratagem.write_invocations)
|
17
|
+
end
|
18
|
+
|
19
|
+
def models(invocations)
|
20
|
+
invocations.values.select {|invocation|
|
21
|
+
(invocation.controller_path == controller.path) &&
|
22
|
+
(invocation.controller_action == self.name)
|
23
|
+
}.map {|invocation|
|
24
|
+
invocation.model_class
|
25
|
+
}.uniq
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
class Controller < Base
|
31
|
+
attr_reader :clazz, :actions
|
32
|
+
attr_accessor :invalid_routes # named routes linked to the controller that are invalid
|
33
|
+
|
34
|
+
def initialize(*args)
|
35
|
+
super(*args)
|
36
|
+
@invalid_routes = {}
|
37
|
+
@actions = []
|
38
|
+
end
|
39
|
+
|
40
|
+
def add_routable_action(name, method)
|
41
|
+
@actions << Action.new(self, name, method)
|
42
|
+
end
|
43
|
+
|
44
|
+
def export
|
45
|
+
{
|
46
|
+
:external_id => self.object_id,
|
47
|
+
:type => :controller,
|
48
|
+
:path => @path.gsub(RAILS_ROOT+'/', ''),
|
49
|
+
:class_name => @klass.name,
|
50
|
+
:invalid_routes => @invalid_routes
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
# returns a list of references that create or update the specified model.
|
55
|
+
# see deletes? for destruction of model
|
56
|
+
def modifies(model)
|
57
|
+
# @modifies ||= {}
|
58
|
+
# @modifies[model] ||= begin
|
59
|
+
# outline = {} # method keys, value is hash of variables and values
|
60
|
+
# current_method = nil
|
61
|
+
# references = Set.new
|
62
|
+
#
|
63
|
+
# # return [] unless ((model.klass == WineFollow) && (self.klass == FollowsController))
|
64
|
+
#
|
65
|
+
# self.parse_tree.walk {|parent,i,subi,node|
|
66
|
+
# case node
|
67
|
+
# when RedParse::MethodNode #... do something with method calls
|
68
|
+
# current_method = node.name
|
69
|
+
# outline[current_method] = {}
|
70
|
+
# # puts "CURRENTMETHOD: #{current_method}"
|
71
|
+
# when RedParse::AssignNode
|
72
|
+
# if (node.left.kind_of?(RedParse::VarNode))
|
73
|
+
# begin
|
74
|
+
# # puts "assigning:#{node.left.name} -> #{node.right.dereference}"
|
75
|
+
# deref = node.right.dereference
|
76
|
+
# ((outline[current_method][node.left.name] ||= []) << deref) if current_method && deref
|
77
|
+
# rescue
|
78
|
+
# puts $!.message
|
79
|
+
# puts $!.backtrace
|
80
|
+
# logger.error("Cannot dereference node #{node.right.to_s}")
|
81
|
+
# end
|
82
|
+
# end
|
83
|
+
# when RedParse::CallNode
|
84
|
+
# ['update','create','new'].each {|m|
|
85
|
+
# # then this is a crud operation (excluding destroy)
|
86
|
+
# if (node.name.include?(m))
|
87
|
+
# if (node.talking_about? model)
|
88
|
+
# references << create_reference(node, current_method, model)
|
89
|
+
# break
|
90
|
+
# elsif (node.receiver && node.receiver.methods_include?(:name) && outline[current_method])
|
91
|
+
# if ((outline[current_method][node.receiver.name] || []).include?(model.klass))
|
92
|
+
# references << create_reference(node, current_method, model)
|
93
|
+
# break
|
94
|
+
# end
|
95
|
+
# end
|
96
|
+
# end
|
97
|
+
# }
|
98
|
+
# end
|
99
|
+
# node
|
100
|
+
# }
|
101
|
+
# references.to_a
|
102
|
+
# end
|
103
|
+
[]
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
def create_reference(node, method, model)
|
109
|
+
Reference.new(
|
110
|
+
:from_class => self.klass,
|
111
|
+
:to_class => model.klass,
|
112
|
+
:method => method,
|
113
|
+
:line_number => node.linerange.first,
|
114
|
+
:reference_type => :write
|
115
|
+
)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,170 @@
|
|
1
|
+
module Stratagem::Model::Component
|
2
|
+
class Model < Base
|
3
|
+
attr_reader :model_attributes # database attributes that the model contains
|
4
|
+
attr_reader :model_assignable_attributes # fields / methods that can be manipulated in Model.new(..)
|
5
|
+
attr_reader :model_internal_attributes
|
6
|
+
attr_reader :model_accessible_attributes
|
7
|
+
attr_accessor :model_referenced_by # other classes / libraries that reference this model
|
8
|
+
|
9
|
+
ModificationMethods = ['update','create','new']
|
10
|
+
|
11
|
+
def initialize(*args)
|
12
|
+
super(*args)
|
13
|
+
load_attributes
|
14
|
+
@model_assignable_attributes = find_assignable_attributes
|
15
|
+
@model_instance_methods = self.klass.instance_methods
|
16
|
+
end
|
17
|
+
|
18
|
+
def stratagem?
|
19
|
+
klass.methods_include?(:stratagem)
|
20
|
+
end
|
21
|
+
|
22
|
+
# iterate model's associations to see if there's an association with the specific
|
23
|
+
# name and class. This is used as an aproximation to determine whether or
|
24
|
+
# not a node in the parse tree could be talking about a specific relationship
|
25
|
+
def association_match?(association_name, desired_model)
|
26
|
+
@association_matches ||= {}
|
27
|
+
@association_matches[association_name+"_"+desired_model.klass.name] ||= begin
|
28
|
+
klass.stratagem.relations.select {|relation|
|
29
|
+
(relation.name.to_sym == association_name.to_sym) && (relation.klass == desired_model.klass)
|
30
|
+
}.map {|relation|
|
31
|
+
relation.klass.name
|
32
|
+
}.first
|
33
|
+
rescue
|
34
|
+
Rails.logger.error("unable to lookup associations on #{self.klass.name} not active record model?")
|
35
|
+
Rails.logger.error($!)
|
36
|
+
false
|
37
|
+
end
|
38
|
+
@association_matches[association_name+"_"+desired_model.klass.name]
|
39
|
+
end
|
40
|
+
|
41
|
+
def load_attributes
|
42
|
+
@model_attributes = {}
|
43
|
+
if (stratagem?)
|
44
|
+
object = klass.new # used to look up metadata
|
45
|
+
object.stratagem.attribute_names.each {|attribute|
|
46
|
+
@model_attributes[attribute.to_sym] = object.stratagem.attribute_type(attribute.to_sym)
|
47
|
+
}
|
48
|
+
@model_foreign_keys = object.stratagem.foreign_keys
|
49
|
+
@model_internal_attributes = object.stratagem.internal_attributes
|
50
|
+
@model_accessible_attributes = object.stratagem.attribute_names - object.stratagem.unaccessible_attributes
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# TODO - refactor into model persistence strategy
|
55
|
+
def find_assignable_attributes
|
56
|
+
assignable_attributes = []
|
57
|
+
|
58
|
+
# Using instance methods allows us to check for functions that would be mass assignable
|
59
|
+
# in addition to Active Record attributes
|
60
|
+
begin
|
61
|
+
if (stratagem?)
|
62
|
+
object = klass.new # used to look up metadata
|
63
|
+
if (object)
|
64
|
+
methods = nil
|
65
|
+
if (klass.stratagem.unaccessible_attributes)
|
66
|
+
assignable_attributes = (klass.stratagem.attribute_names - klass.stratagem.unaccessible_attributes).to_a
|
67
|
+
else
|
68
|
+
methods = klass.instance_methods + object.stratagem.attribute_names
|
69
|
+
methods.each {|method|
|
70
|
+
param_name = method.to_s.gsub('=','').to_sym
|
71
|
+
val = rand(100)
|
72
|
+
params = { param_name => val }
|
73
|
+
begin
|
74
|
+
instance = klass.new(params)
|
75
|
+
assignable_attributes << param_name.to_sym
|
76
|
+
rescue ActiveRecord::UnknownAttributeError
|
77
|
+
# the attribute is not mass assignable
|
78
|
+
rescue
|
79
|
+
# the function was called but an error was raised
|
80
|
+
assignable_attributes << param_name.to_sym
|
81
|
+
end
|
82
|
+
}
|
83
|
+
end
|
84
|
+
end
|
85
|
+
assignable_attributes.uniq
|
86
|
+
end
|
87
|
+
rescue
|
88
|
+
puts "Unable to analyze model #{klass.name}"
|
89
|
+
puts $!.message
|
90
|
+
puts $!.backtrace
|
91
|
+
# raise $!
|
92
|
+
[]
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# References to the find and find_x methods on the model
|
97
|
+
def references_to_finders()
|
98
|
+
references = []
|
99
|
+
method = nil
|
100
|
+
app_model.controllers.each {|controller|
|
101
|
+
controller.parse_tree.walk {|parent,i,subi,node|
|
102
|
+
case node
|
103
|
+
when RedParse::MethodNode
|
104
|
+
method = node
|
105
|
+
when RedParse::CallNode
|
106
|
+
if (!(parent.kind_of?(RedParse::AssignNode)) && (node.receiver) && (node.receiver.to_s == klass.name))
|
107
|
+
references << ControllerModelReference.new(controller, method.name, node.name, node)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
case parent
|
112
|
+
when RedParse::AssignNode
|
113
|
+
# p parent
|
114
|
+
begin
|
115
|
+
if (node.kind_of?(RedParse::CallNode) && (node.receiver) && (node.receiver.name == klass.name))
|
116
|
+
references << ControllerModelReference.new(controller, method.name, node.name, node)
|
117
|
+
end
|
118
|
+
rescue
|
119
|
+
puts $!.message
|
120
|
+
puts $!.backtrace
|
121
|
+
# p parent
|
122
|
+
end
|
123
|
+
end
|
124
|
+
true
|
125
|
+
}
|
126
|
+
}
|
127
|
+
references
|
128
|
+
end
|
129
|
+
|
130
|
+
def export
|
131
|
+
adapters = stratagem? ? klass.stratagem.callbacks.map {|c| c.class.name } : []
|
132
|
+
{
|
133
|
+
:type => :model,
|
134
|
+
:path => @path.gsub(RAILS_ROOT+'/', ''),
|
135
|
+
:class_name => @klass.name,
|
136
|
+
:superclass => @klass.superclass.name,
|
137
|
+
:included_modules => @klass.included_modules.map {|m| m.name},
|
138
|
+
:attributes => @model_attributes,
|
139
|
+
:foreign_keys => @model_foreign_keys,
|
140
|
+
:assignable_attributes => @model_assignable_attributes,
|
141
|
+
:internal_attributes => @model_internal_attributes,
|
142
|
+
:accessible_attributes => @model_accessible_attributes,
|
143
|
+
:whitelists_attributes => stratagem? ? @klass.stratagem.whitelists_attributes? : nil,
|
144
|
+
:blacklists_attributes => stratagem? ? @klass.stratagem.blacklists_attributes? : nil,
|
145
|
+
:instance_methods => @model_instance_methods,
|
146
|
+
:referenced_by => @model_referenced_by.map {|r| r.export },
|
147
|
+
:relations => relations.map {|r| r.export },
|
148
|
+
:adapters => adapters
|
149
|
+
}
|
150
|
+
end
|
151
|
+
|
152
|
+
private
|
153
|
+
|
154
|
+
def relations
|
155
|
+
if (stratagem?)
|
156
|
+
@relations ||= klass.stratagem.relations.map {|relation|
|
157
|
+
Reference.new(:reference_type => relation.macro, :from_class => self.klass, :to_class => relation.klass)
|
158
|
+
}
|
159
|
+
else
|
160
|
+
[]
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def assignable(object, assignable_attributes, attribute)
|
165
|
+
column = object.column_for_attribute(attribute)
|
166
|
+
assignable_attributes[attribute] = column ? column.type : nil
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
170
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Stratagem::Model::Component
|
2
|
+
class Reference
|
3
|
+
attr_accessor :reference_type # :read, :write
|
4
|
+
attr_accessor :from_class, :to_class
|
5
|
+
attr_accessor :line_number
|
6
|
+
attr_accessor :method
|
7
|
+
|
8
|
+
Vars = [:reference_type, :from_class, :to_class, :line_number, :method]
|
9
|
+
|
10
|
+
def initialize(args={})
|
11
|
+
args.each {|key,val| self.send("#{key}=", val) }
|
12
|
+
end
|
13
|
+
|
14
|
+
def ==(other)
|
15
|
+
Vars.each do |attribute|
|
16
|
+
self.send(attribute) == other.send(attribute)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def export
|
21
|
+
h = {}
|
22
|
+
Vars.each do |key|
|
23
|
+
h[key.to_s] = self.send(key).to_s
|
24
|
+
end
|
25
|
+
h[:from_class.to_s] = from_class.name
|
26
|
+
h[:to_class.to_s] = to_class.name
|
27
|
+
h
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Stratagem::Model::Component
|
2
|
+
class Route < Base
|
3
|
+
attr_reader :route
|
4
|
+
|
5
|
+
def initialize(route)
|
6
|
+
@route = route
|
7
|
+
end
|
8
|
+
|
9
|
+
def controller
|
10
|
+
if (route.requirements[:controller])
|
11
|
+
begin
|
12
|
+
controller_class = "#{route.requirements[:controller].to_s.camelize}Controller".constantize
|
13
|
+
Stratagem::Model::Application.instance.controllers.find {|c| c.klass == controller_class }
|
14
|
+
rescue
|
15
|
+
puts "unable to determine controller #{route.requirements[:controller]}"
|
16
|
+
puts $!.message
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
else
|
20
|
+
nil
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def action
|
25
|
+
route.requirements[:action] ? route.requirements[:action].to_sym : nil
|
26
|
+
end
|
27
|
+
|
28
|
+
def ==(other)
|
29
|
+
if (other.kind_of?(ActionController::Routing::Route))
|
30
|
+
self.route == other
|
31
|
+
elsif (other.kind_of?(Stratagem::Model::Component::Route))
|
32
|
+
self.route.requirements == other.route.requirements && self.route.segments == other.route.segments
|
33
|
+
else
|
34
|
+
raise "unknown comparison to #{other.class.name}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def export
|
39
|
+
p @route.requirements
|
40
|
+
p action
|
41
|
+
puts "--"
|
42
|
+
{
|
43
|
+
:external_id => self.object_id,
|
44
|
+
:type => :route,
|
45
|
+
:path => nil,
|
46
|
+
:requirements => @route.requirements,
|
47
|
+
:segments => @route.segments.map {|s| s.to_s },
|
48
|
+
:controller_external_id => controller ? controller.object_id : nil,
|
49
|
+
:action => action,
|
50
|
+
}
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Stratagem::Model::Component
|
2
|
+
class StaticFile < Base
|
3
|
+
|
4
|
+
def initialize(public_path)
|
5
|
+
@path = public_path
|
6
|
+
end
|
7
|
+
|
8
|
+
def read
|
9
|
+
File.read(full_path)
|
10
|
+
end
|
11
|
+
|
12
|
+
def full_path
|
13
|
+
File.join(RAILS_ROOT, 'public', path)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|