railroader 4.3.4
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.
- checksums.yaml +7 -0
- data/CHANGES.md +1091 -0
- data/FEATURES +16 -0
- data/README.md +174 -0
- data/bin/railroader +8 -0
- data/lib/railroader/app_tree.rb +191 -0
- data/lib/railroader/call_index.rb +219 -0
- data/lib/railroader/checks/base_check.rb +505 -0
- data/lib/railroader/checks/check_basic_auth.rb +88 -0
- data/lib/railroader/checks/check_basic_auth_timing_attack.rb +33 -0
- data/lib/railroader/checks/check_content_tag.rb +200 -0
- data/lib/railroader/checks/check_create_with.rb +74 -0
- data/lib/railroader/checks/check_cross_site_scripting.rb +381 -0
- data/lib/railroader/checks/check_default_routes.rb +86 -0
- data/lib/railroader/checks/check_deserialize.rb +56 -0
- data/lib/railroader/checks/check_detailed_exceptions.rb +55 -0
- data/lib/railroader/checks/check_digest_dos.rb +38 -0
- data/lib/railroader/checks/check_divide_by_zero.rb +42 -0
- data/lib/railroader/checks/check_dynamic_finders.rb +48 -0
- data/lib/railroader/checks/check_escape_function.rb +21 -0
- data/lib/railroader/checks/check_evaluation.rb +35 -0
- data/lib/railroader/checks/check_execute.rb +189 -0
- data/lib/railroader/checks/check_file_access.rb +71 -0
- data/lib/railroader/checks/check_file_disclosure.rb +35 -0
- data/lib/railroader/checks/check_filter_skipping.rb +31 -0
- data/lib/railroader/checks/check_forgery_setting.rb +81 -0
- data/lib/railroader/checks/check_header_dos.rb +31 -0
- data/lib/railroader/checks/check_i18n_xss.rb +48 -0
- data/lib/railroader/checks/check_jruby_xml.rb +36 -0
- data/lib/railroader/checks/check_json_encoding.rb +47 -0
- data/lib/railroader/checks/check_json_parsing.rb +107 -0
- data/lib/railroader/checks/check_link_to.rb +132 -0
- data/lib/railroader/checks/check_link_to_href.rb +146 -0
- data/lib/railroader/checks/check_mail_to.rb +49 -0
- data/lib/railroader/checks/check_mass_assignment.rb +196 -0
- data/lib/railroader/checks/check_mime_type_dos.rb +39 -0
- data/lib/railroader/checks/check_model_attr_accessible.rb +55 -0
- data/lib/railroader/checks/check_model_attributes.rb +119 -0
- data/lib/railroader/checks/check_model_serialize.rb +67 -0
- data/lib/railroader/checks/check_nested_attributes.rb +38 -0
- data/lib/railroader/checks/check_nested_attributes_bypass.rb +58 -0
- data/lib/railroader/checks/check_number_to_currency.rb +74 -0
- data/lib/railroader/checks/check_permit_attributes.rb +43 -0
- data/lib/railroader/checks/check_quote_table_name.rb +40 -0
- data/lib/railroader/checks/check_redirect.rb +256 -0
- data/lib/railroader/checks/check_regex_dos.rb +68 -0
- data/lib/railroader/checks/check_render.rb +97 -0
- data/lib/railroader/checks/check_render_dos.rb +37 -0
- data/lib/railroader/checks/check_render_inline.rb +53 -0
- data/lib/railroader/checks/check_response_splitting.rb +21 -0
- data/lib/railroader/checks/check_route_dos.rb +42 -0
- data/lib/railroader/checks/check_safe_buffer_manipulation.rb +31 -0
- data/lib/railroader/checks/check_sanitize_methods.rb +112 -0
- data/lib/railroader/checks/check_secrets.rb +40 -0
- data/lib/railroader/checks/check_select_tag.rb +59 -0
- data/lib/railroader/checks/check_select_vulnerability.rb +60 -0
- data/lib/railroader/checks/check_send.rb +47 -0
- data/lib/railroader/checks/check_send_file.rb +19 -0
- data/lib/railroader/checks/check_session_manipulation.rb +35 -0
- data/lib/railroader/checks/check_session_settings.rb +176 -0
- data/lib/railroader/checks/check_simple_format.rb +58 -0
- data/lib/railroader/checks/check_single_quotes.rb +101 -0
- data/lib/railroader/checks/check_skip_before_filter.rb +60 -0
- data/lib/railroader/checks/check_sql.rb +700 -0
- data/lib/railroader/checks/check_sql_cves.rb +106 -0
- data/lib/railroader/checks/check_ssl_verify.rb +48 -0
- data/lib/railroader/checks/check_strip_tags.rb +89 -0
- data/lib/railroader/checks/check_symbol_dos.rb +71 -0
- data/lib/railroader/checks/check_symbol_dos_cve.rb +30 -0
- data/lib/railroader/checks/check_translate_bug.rb +45 -0
- data/lib/railroader/checks/check_unsafe_reflection.rb +50 -0
- data/lib/railroader/checks/check_unscoped_find.rb +57 -0
- data/lib/railroader/checks/check_validation_regex.rb +116 -0
- data/lib/railroader/checks/check_weak_hash.rb +148 -0
- data/lib/railroader/checks/check_without_protection.rb +80 -0
- data/lib/railroader/checks/check_xml_dos.rb +45 -0
- data/lib/railroader/checks/check_yaml_parsing.rb +121 -0
- data/lib/railroader/checks.rb +209 -0
- data/lib/railroader/codeclimate/engine_configuration.rb +97 -0
- data/lib/railroader/commandline.rb +179 -0
- data/lib/railroader/differ.rb +66 -0
- data/lib/railroader/file_parser.rb +54 -0
- data/lib/railroader/format/style.css +133 -0
- data/lib/railroader/options.rb +339 -0
- data/lib/railroader/parsers/rails2_erubis.rb +6 -0
- data/lib/railroader/parsers/rails2_xss_plugin_erubis.rb +48 -0
- data/lib/railroader/parsers/rails3_erubis.rb +81 -0
- data/lib/railroader/parsers/template_parser.rb +108 -0
- data/lib/railroader/processor.rb +102 -0
- data/lib/railroader/processors/alias_processor.rb +1229 -0
- data/lib/railroader/processors/base_processor.rb +295 -0
- data/lib/railroader/processors/config_processor.rb +14 -0
- data/lib/railroader/processors/controller_alias_processor.rb +278 -0
- data/lib/railroader/processors/controller_processor.rb +249 -0
- data/lib/railroader/processors/erb_template_processor.rb +77 -0
- data/lib/railroader/processors/erubis_template_processor.rb +92 -0
- data/lib/railroader/processors/gem_processor.rb +64 -0
- data/lib/railroader/processors/haml_template_processor.rb +191 -0
- data/lib/railroader/processors/lib/basic_processor.rb +37 -0
- data/lib/railroader/processors/lib/call_conversion_helper.rb +90 -0
- data/lib/railroader/processors/lib/find_all_calls.rb +224 -0
- data/lib/railroader/processors/lib/find_call.rb +183 -0
- data/lib/railroader/processors/lib/find_return_value.rb +166 -0
- data/lib/railroader/processors/lib/module_helper.rb +111 -0
- data/lib/railroader/processors/lib/processor_helper.rb +88 -0
- data/lib/railroader/processors/lib/rails2_config_processor.rb +145 -0
- data/lib/railroader/processors/lib/rails2_route_processor.rb +313 -0
- data/lib/railroader/processors/lib/rails3_config_processor.rb +132 -0
- data/lib/railroader/processors/lib/rails3_route_processor.rb +308 -0
- data/lib/railroader/processors/lib/render_helper.rb +181 -0
- data/lib/railroader/processors/lib/render_path.rb +107 -0
- data/lib/railroader/processors/lib/route_helper.rb +68 -0
- data/lib/railroader/processors/lib/safe_call_helper.rb +16 -0
- data/lib/railroader/processors/library_processor.rb +74 -0
- data/lib/railroader/processors/model_processor.rb +91 -0
- data/lib/railroader/processors/output_processor.rb +144 -0
- data/lib/railroader/processors/route_processor.rb +17 -0
- data/lib/railroader/processors/slim_template_processor.rb +111 -0
- data/lib/railroader/processors/template_alias_processor.rb +118 -0
- data/lib/railroader/processors/template_processor.rb +85 -0
- data/lib/railroader/report/config/remediation.yml +71 -0
- data/lib/railroader/report/ignore/config.rb +153 -0
- data/lib/railroader/report/ignore/interactive.rb +362 -0
- data/lib/railroader/report/pager.rb +112 -0
- data/lib/railroader/report/renderer.rb +24 -0
- data/lib/railroader/report/report_base.rb +292 -0
- data/lib/railroader/report/report_codeclimate.rb +79 -0
- data/lib/railroader/report/report_csv.rb +55 -0
- data/lib/railroader/report/report_hash.rb +23 -0
- data/lib/railroader/report/report_html.rb +216 -0
- data/lib/railroader/report/report_json.rb +45 -0
- data/lib/railroader/report/report_markdown.rb +107 -0
- data/lib/railroader/report/report_table.rb +117 -0
- data/lib/railroader/report/report_tabs.rb +17 -0
- data/lib/railroader/report/report_text.rb +198 -0
- data/lib/railroader/report/templates/controller_overview.html.erb +22 -0
- data/lib/railroader/report/templates/controller_warnings.html.erb +21 -0
- data/lib/railroader/report/templates/error_overview.html.erb +29 -0
- data/lib/railroader/report/templates/header.html.erb +58 -0
- data/lib/railroader/report/templates/ignored_warnings.html.erb +25 -0
- data/lib/railroader/report/templates/model_warnings.html.erb +21 -0
- data/lib/railroader/report/templates/overview.html.erb +38 -0
- data/lib/railroader/report/templates/security_warnings.html.erb +23 -0
- data/lib/railroader/report/templates/template_overview.html.erb +21 -0
- data/lib/railroader/report/templates/view_warnings.html.erb +34 -0
- data/lib/railroader/report/templates/warning_overview.html.erb +17 -0
- data/lib/railroader/report.rb +88 -0
- data/lib/railroader/rescanner.rb +483 -0
- data/lib/railroader/scanner.rb +321 -0
- data/lib/railroader/tracker/collection.rb +93 -0
- data/lib/railroader/tracker/config.rb +154 -0
- data/lib/railroader/tracker/constants.rb +171 -0
- data/lib/railroader/tracker/controller.rb +161 -0
- data/lib/railroader/tracker/library.rb +17 -0
- data/lib/railroader/tracker/model.rb +90 -0
- data/lib/railroader/tracker/template.rb +33 -0
- data/lib/railroader/tracker.rb +362 -0
- data/lib/railroader/util.rb +503 -0
- data/lib/railroader/version.rb +3 -0
- data/lib/railroader/warning.rb +294 -0
- data/lib/railroader/warning_codes.rb +117 -0
- data/lib/railroader.rb +544 -0
- data/lib/ruby_parser/bm_sexp.rb +626 -0
- data/lib/ruby_parser/bm_sexp_processor.rb +116 -0
- metadata +386 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
require 'railroader/processors/output_processor'
|
|
2
|
+
|
|
3
|
+
module Railroader
|
|
4
|
+
class Constant
|
|
5
|
+
attr_reader :name, :name_array, :file, :value, :context
|
|
6
|
+
|
|
7
|
+
def initialize name, value, context = {}
|
|
8
|
+
set_name name, context
|
|
9
|
+
@value = value
|
|
10
|
+
@context = context
|
|
11
|
+
|
|
12
|
+
if @context
|
|
13
|
+
if @context[:class].is_a? Railroader::Controller
|
|
14
|
+
@context[:class] = @context[:class].name
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
@file = @context[:file]
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def line
|
|
22
|
+
if @value.is_a? Sexp
|
|
23
|
+
@value.line
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def set_name name, context
|
|
28
|
+
@name = name
|
|
29
|
+
@name_array = Constants.constant_as_array(name)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def match? name
|
|
33
|
+
if name == @name
|
|
34
|
+
return true
|
|
35
|
+
elsif name.is_a? Sexp and name.node_type == :const and name.value == @name
|
|
36
|
+
return true
|
|
37
|
+
elsif name.is_a? Symbol and name.value == @name
|
|
38
|
+
return true
|
|
39
|
+
elsif name.class == Array
|
|
40
|
+
name == @name_array or
|
|
41
|
+
@name_array.reverse.zip(name.reverse).reduce(true) { |m, a| a[1] ? a[0] == a[1] && m : m }
|
|
42
|
+
else
|
|
43
|
+
false
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
class Constants
|
|
49
|
+
include Railroader::Util
|
|
50
|
+
|
|
51
|
+
def initialize
|
|
52
|
+
@constants = Hash.new { |h, k| h[k] = [] }
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def size
|
|
56
|
+
@constants.length
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def [] exp
|
|
60
|
+
return unless constant? exp
|
|
61
|
+
match = find_constant exp
|
|
62
|
+
|
|
63
|
+
if match
|
|
64
|
+
match.value
|
|
65
|
+
else
|
|
66
|
+
nil
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def find_constant exp
|
|
71
|
+
base_name = Constants.get_constant_base_name(exp)
|
|
72
|
+
|
|
73
|
+
if @constants.key? base_name
|
|
74
|
+
@constants[base_name].find do |c|
|
|
75
|
+
if c.match? exp
|
|
76
|
+
return c
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
name_array = Constants.constant_as_array(exp)
|
|
81
|
+
|
|
82
|
+
# Avoid losing info about dynamic constant values
|
|
83
|
+
return unless name_array.all? { |n| constant? n or n.is_a? Symbol }
|
|
84
|
+
|
|
85
|
+
@constants[base_name].find do |c|
|
|
86
|
+
if c.match? name_array
|
|
87
|
+
return c
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
nil
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def find_all exp
|
|
96
|
+
base_name = Constants.get_constant_base_name(exp)
|
|
97
|
+
@constants[base_name]
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def add name, value, context = nil
|
|
101
|
+
if call? value and value.method == :freeze
|
|
102
|
+
value = value.target
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
base_name = Constants.get_constant_base_name(name)
|
|
106
|
+
@constants[base_name] << Constant.new(name, value, context)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
LITERALS = [:lit, :false, :str, :true, :array, :hash]
|
|
110
|
+
def literal? exp
|
|
111
|
+
exp.is_a? Sexp and LITERALS.include? exp.node_type
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def get_literal name
|
|
115
|
+
if x = self[name] and literal? x
|
|
116
|
+
x
|
|
117
|
+
else
|
|
118
|
+
nil
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def each
|
|
123
|
+
@constants.each do |name, values|
|
|
124
|
+
values.each do |constant|
|
|
125
|
+
yield constant
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def self.constant_as_array exp
|
|
131
|
+
res = []
|
|
132
|
+
while exp
|
|
133
|
+
if exp.is_a? Sexp
|
|
134
|
+
case exp.node_type
|
|
135
|
+
when :const
|
|
136
|
+
res << exp.value
|
|
137
|
+
exp = nil
|
|
138
|
+
when :colon3
|
|
139
|
+
res << exp.value << :""
|
|
140
|
+
exp = nil
|
|
141
|
+
when :colon2
|
|
142
|
+
res << exp.last
|
|
143
|
+
exp = exp[1]
|
|
144
|
+
else
|
|
145
|
+
res << exp
|
|
146
|
+
exp = nil
|
|
147
|
+
end
|
|
148
|
+
else
|
|
149
|
+
res << exp
|
|
150
|
+
exp = nil
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
res.reverse!
|
|
155
|
+
res
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def self.get_constant_base_name exp
|
|
159
|
+
return exp unless exp.is_a? Sexp
|
|
160
|
+
|
|
161
|
+
case exp.node_type
|
|
162
|
+
when :const, :colon3
|
|
163
|
+
exp.value
|
|
164
|
+
when :colon2
|
|
165
|
+
exp.last
|
|
166
|
+
else
|
|
167
|
+
exp
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
require 'railroader/tracker/collection'
|
|
2
|
+
|
|
3
|
+
module Railroader
|
|
4
|
+
module ControllerMethods
|
|
5
|
+
attr_accessor :layout
|
|
6
|
+
|
|
7
|
+
def initialize_controller
|
|
8
|
+
@options[:before_filters] = []
|
|
9
|
+
@options[:skip_filters] = []
|
|
10
|
+
@layout = nil
|
|
11
|
+
@skip_filter_cache = nil
|
|
12
|
+
@before_filter_cache = nil
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def protect_from_forgery?
|
|
16
|
+
@options[:protect_from_forgery]
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def add_before_filter exp
|
|
20
|
+
@options[:before_filters] << exp
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def prepend_before_filter exp
|
|
24
|
+
@options[:before_filters].unshift exp
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def before_filters
|
|
28
|
+
@options[:before_filters]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def skip_filter exp
|
|
32
|
+
@options[:skip_filters] << exp
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def skip_filters
|
|
36
|
+
@options[:skip_filters]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def before_filter_list processor, method
|
|
40
|
+
controller = self
|
|
41
|
+
filters = []
|
|
42
|
+
|
|
43
|
+
while controller
|
|
44
|
+
filters = controller.get_before_filters(processor, method) + filters
|
|
45
|
+
|
|
46
|
+
controller = tracker.controllers[controller.parent] ||
|
|
47
|
+
tracker.libs[controller.parent]
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
remove_skipped_filters processor, filters, method
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def get_skipped_filters processor, method
|
|
54
|
+
filters = []
|
|
55
|
+
|
|
56
|
+
if @skip_filter_cache.nil?
|
|
57
|
+
@skip_filter_cache = skip_filters.map do |filter|
|
|
58
|
+
before_filter_to_hash(processor, filter.args)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
@skip_filter_cache.each do |f|
|
|
63
|
+
if filter_includes_method? f, method
|
|
64
|
+
filters.concat f[:methods]
|
|
65
|
+
else
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
filters
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def remove_skipped_filters processor, filters, method
|
|
74
|
+
controller = self
|
|
75
|
+
|
|
76
|
+
while controller
|
|
77
|
+
filters = filters - controller.get_skipped_filters(processor, method)
|
|
78
|
+
|
|
79
|
+
controller = tracker.controllers[controller.parent] ||
|
|
80
|
+
tracker.libs[controller.parent]
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
filters
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def get_before_filters processor, method
|
|
87
|
+
filters = []
|
|
88
|
+
|
|
89
|
+
if @before_filter_cache.nil?
|
|
90
|
+
@before_filter_cache = []
|
|
91
|
+
|
|
92
|
+
before_filters.each do |filter|
|
|
93
|
+
@before_filter_cache << before_filter_to_hash(processor, filter.args)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
@before_filter_cache.each do |f|
|
|
98
|
+
if filter_includes_method? f, method
|
|
99
|
+
filters.concat f[:methods]
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
filters
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def before_filter_to_hash processor, args
|
|
107
|
+
filter = {}
|
|
108
|
+
|
|
109
|
+
#Process args for the uncommon but possible situation
|
|
110
|
+
#in which some variables are used in the filter.
|
|
111
|
+
args.each do |a|
|
|
112
|
+
if sexp? a
|
|
113
|
+
a = processor.process_default a
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
filter[:methods] = []
|
|
118
|
+
|
|
119
|
+
args.each do |a|
|
|
120
|
+
filter[:methods] << a[1] if a.node_type == :lit
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
if args[-1].node_type == :hash
|
|
124
|
+
option = args[-1][1][1]
|
|
125
|
+
value = args[-1][2]
|
|
126
|
+
case value.node_type
|
|
127
|
+
when :array
|
|
128
|
+
filter[option] = value[1..-1].map {|v| v[1] }
|
|
129
|
+
when :lit, :str
|
|
130
|
+
filter[option] = value[1]
|
|
131
|
+
else
|
|
132
|
+
Railroader.debug "[Notice] Unknown before_filter value: #{option} => #{value}"
|
|
133
|
+
end
|
|
134
|
+
else
|
|
135
|
+
filter[:all] = true
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
filter
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
private
|
|
142
|
+
|
|
143
|
+
def filter_includes_method? filter_rule, method_name
|
|
144
|
+
filter_rule[:all] or
|
|
145
|
+
(filter_rule[:only] == method_name) or
|
|
146
|
+
(filter_rule[:only].is_a? Array and filter_rule[:only].include? method_name) or
|
|
147
|
+
(filter_rule[:except].is_a? Symbol and filter_rule[:except] != method_name) or
|
|
148
|
+
(filter_rule[:except].is_a? Array and not filter_rule[:except].include? method_name)
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
class Controller < Railroader::Collection
|
|
153
|
+
include ControllerMethods
|
|
154
|
+
|
|
155
|
+
def initialize name, parent, file_name, src, tracker
|
|
156
|
+
super
|
|
157
|
+
initialize_controller
|
|
158
|
+
@collection = tracker.controllers
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require 'railroader/tracker/collection'
|
|
2
|
+
require 'railroader/tracker/controller'
|
|
3
|
+
require 'railroader/tracker/model'
|
|
4
|
+
|
|
5
|
+
module Railroader
|
|
6
|
+
class Library < Railroader::Collection
|
|
7
|
+
include ControllerMethods
|
|
8
|
+
include ModelMethods
|
|
9
|
+
|
|
10
|
+
def initialize name, parent, file_name, src, tracker
|
|
11
|
+
super
|
|
12
|
+
initialize_controller
|
|
13
|
+
initialize_model
|
|
14
|
+
@collection = tracker.libs
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
require 'railroader/tracker/collection'
|
|
2
|
+
|
|
3
|
+
module Railroader
|
|
4
|
+
module ModelMethods
|
|
5
|
+
attr_reader :associations, :attr_accessible, :role_accessible
|
|
6
|
+
|
|
7
|
+
def initialize_model
|
|
8
|
+
@associations = {}
|
|
9
|
+
@role_accessible = []
|
|
10
|
+
@attr_accessible = nil
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def association? method_name
|
|
14
|
+
@associations.each do |name, args|
|
|
15
|
+
args.each do |arg|
|
|
16
|
+
if symbol? arg and arg.value == method_name
|
|
17
|
+
return true
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
false
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def unprotected_model?
|
|
26
|
+
@attr_accessible.nil? and !parent_classes_protected? and ancestor?(:"ActiveRecord::Base")
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# go up the chain of parent classes to see if any have attr_accessible
|
|
30
|
+
def parent_classes_protected? seen={}
|
|
31
|
+
seen[self.name] = true
|
|
32
|
+
|
|
33
|
+
if @attr_accessible or self.includes.include? :"ActiveModel::ForbiddenAttributesProtection"
|
|
34
|
+
true
|
|
35
|
+
elsif parent = tracker.models[self.parent] and !seen[self.parent]
|
|
36
|
+
parent.parent_classes_protected? seen
|
|
37
|
+
else
|
|
38
|
+
false
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def set_attr_accessible exp = nil
|
|
43
|
+
if exp
|
|
44
|
+
args = []
|
|
45
|
+
|
|
46
|
+
exp.each_arg do |e|
|
|
47
|
+
if node_type? e, :lit
|
|
48
|
+
args << e.value
|
|
49
|
+
elsif hash? e
|
|
50
|
+
@role_accessible.concat args
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
@attr_accessible ||= []
|
|
55
|
+
@attr_accessible.concat args
|
|
56
|
+
else
|
|
57
|
+
@attr_accessible ||= []
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def set_attr_protected exp
|
|
62
|
+
add_option :attr_protected, exp
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def attr_protected
|
|
66
|
+
@options[:attr_protected]
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
class Model < Railroader::Collection
|
|
71
|
+
include ModelMethods
|
|
72
|
+
|
|
73
|
+
ASSOCIATIONS = Set[:belongs_to, :has_one, :has_many, :has_and_belongs_to_many]
|
|
74
|
+
|
|
75
|
+
def initialize name, parent, file_name, src, tracker
|
|
76
|
+
super
|
|
77
|
+
initialize_model
|
|
78
|
+
@collection = tracker.models
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def add_option name, exp
|
|
82
|
+
if ASSOCIATIONS.include? name
|
|
83
|
+
@associations[name] ||= []
|
|
84
|
+
@associations[name].concat exp.args
|
|
85
|
+
else
|
|
86
|
+
super name, exp.arglist.line(exp.line)
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require 'railroader/tracker/collection'
|
|
2
|
+
|
|
3
|
+
module Railroader
|
|
4
|
+
class Template < Railroader::Collection
|
|
5
|
+
attr_accessor :type
|
|
6
|
+
attr_reader :render_path
|
|
7
|
+
attr_writer :src
|
|
8
|
+
|
|
9
|
+
def initialize name, called_from, file_name, tracker
|
|
10
|
+
super name, nil, file_name, nil, tracker
|
|
11
|
+
@render_path = called_from
|
|
12
|
+
@outputs = []
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def add_output exp
|
|
16
|
+
@outputs << exp
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def each_output
|
|
20
|
+
@outputs.each do |o|
|
|
21
|
+
yield o
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def rendered_from_controller?
|
|
26
|
+
if @render_path
|
|
27
|
+
@render_path.rendered_from_controller?
|
|
28
|
+
else
|
|
29
|
+
false
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|