stratagem 0.2.3 → 0.2.4
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest +16 -6
- data/Rakefile +8 -1
- data/lib/generators/stratagem/install/install_base.rb +13 -3
- data/lib/generators/stratagem/install/install_generator.rb +1 -1
- data/lib/stratagem.rb +42 -18
- data/lib/stratagem/authentication.rb +2 -5
- data/lib/stratagem/auto_mock.rb +1 -0
- data/lib/stratagem/auto_mock/aquifer.rb +49 -26
- data/lib/stratagem/auto_mock/factory.rb +1 -6
- data/lib/stratagem/auto_mock/user_loader.rb +38 -0
- data/lib/stratagem/client.rb +15 -4
- data/lib/stratagem/configuration/auth_auth.rb +19 -0
- data/lib/stratagem/configuration/core.rb +20 -0
- data/lib/stratagem/crawler/authentication.rb +17 -12
- data/lib/stratagem/crawler/authentication/automated.rb +40 -0
- data/lib/stratagem/crawler/authentication/base.rb +140 -0
- data/lib/stratagem/crawler/authentication/configured.rb +27 -0
- data/lib/stratagem/crawler/parameter_resolver.rb +12 -8
- data/lib/stratagem/crawler/route_invoker.rb +10 -13
- data/lib/stratagem/crawler/session.rb +14 -2
- data/lib/stratagem/crawler/site_model.rb +4 -173
- data/lib/stratagem/crawler/site_model/edge.rb +20 -0
- data/lib/stratagem/crawler/site_model/page.rb +121 -0
- data/lib/stratagem/crawler/site_model/page_set.rb +58 -0
- data/lib/stratagem/instrumentation/models.rb +3 -14
- data/lib/stratagem/instrumentation/models/annotations.rb +39 -5
- data/lib/stratagem/instrumentation/models/authentication.rb +0 -1
- data/lib/stratagem/instrumentation/models/authentication/authlogic/detect.rb +1 -0
- data/lib/stratagem/instrumentation/models/authentication/devise/detect.rb +1 -1
- data/lib/stratagem/instrumentation/models/authentication/devise/instrumentation.rb +0 -4
- data/lib/stratagem/instrumentation/models/metadata.rb +23 -1
- data/lib/stratagem/instrumentation/models/persistence.rb +3 -4
- data/lib/stratagem/instrumentation/models/persistence/active_record/metadata.rb +2 -2
- data/lib/stratagem/interface/browser.rb +9 -3
- data/lib/stratagem/interface/public/javascripts/stratagem.js +14 -12
- data/lib/stratagem/interface/views/index.haml +3 -3
- data/lib/stratagem/logger.rb +28 -2
- data/lib/stratagem/model.rb +6 -0
- data/lib/stratagem/model/application.rb +21 -134
- data/lib/stratagem/model/components/base.rb +1 -4
- data/lib/stratagem/model/components/controller.rb +1 -2
- data/lib/stratagem/model/components/model.rb +15 -15
- data/lib/stratagem/model/components/route.rb +3 -2
- data/lib/stratagem/model/components/view.rb +0 -1
- data/lib/stratagem/model/containers/base.rb +60 -0
- data/lib/stratagem/model/containers/gem.rb +25 -0
- data/lib/stratagem/model/containers/plugin.rb +11 -0
- data/lib/stratagem/model/containers/route.rb +19 -0
- data/lib/stratagem/model/parse_util.rb +3 -3
- data/lib/stratagem/model_builder.rb +1 -4
- data/lib/stratagem/rack_hack.rb +15 -0
- data/lib/stratagem/site_crawler.rb +5 -4
- data/lib/stratagem/snapshot.rb +5 -7
- data/spec/stratagem/configuration_spec.rb +32 -0
- data/stratagem.gemspec +5 -8
- data/templates/install/environments/stratagem.rb.erb +31 -2
- data/templates/install/script/stratagem +16 -0
- data/templates/install/tasks/stratagem.rake +2 -2
- metadata +36 -65
- data/bin/stratagem +0 -58
- data/lib/stratagem/scan.rb +0 -19
- data/lib/stratagem/scan/checks/email_address.rb +0 -15
- data/lib/stratagem/scan/checks/error_pages.rb +0 -25
- data/lib/stratagem/scan/result.rb +0 -45
- data/lib/stratagem/scanner.rb +0 -32
@@ -0,0 +1,38 @@
|
|
1
|
+
# Locates an instance of a user from configured credentials
|
2
|
+
|
3
|
+
module Stratagem::AutoMock
|
4
|
+
module UserLoader
|
5
|
+
def load_user_from_configuration(credentials)
|
6
|
+
possible_matches = []
|
7
|
+
auth_creds = credentials.authentication_parameters
|
8
|
+
model = credentials.model.constantize
|
9
|
+
@all_user_objects ||= model.all
|
10
|
+
log "\tloaded #{@all_user_objects.size} users from the database"
|
11
|
+
@all_user_objects.each do |user|
|
12
|
+
matching_attributes = matching_credentials(auth_creds, user)
|
13
|
+
possible_matches << [user, matching_attributes] if matching_attributes > 0
|
14
|
+
end
|
15
|
+
|
16
|
+
match = possible_matches.sort {|a,b| a[1] <=> b[1] }.last
|
17
|
+
if (match)
|
18
|
+
user = match.first
|
19
|
+
auth_creds.each {|k,v| user.stratagem.mock_attributes[k] = v }
|
20
|
+
user
|
21
|
+
else
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def matching_credentials(authentication_parameters, user)
|
27
|
+
count = 0
|
28
|
+
authentication_parameters.each do |attribute, value|
|
29
|
+
begin
|
30
|
+
count += 1 if (value == user.send(attribute.to_sym))
|
31
|
+
rescue
|
32
|
+
end
|
33
|
+
end
|
34
|
+
count
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
data/lib/stratagem/client.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
require 'uri'
|
2
|
+
require 'zlib'
|
3
|
+
require 'base64'
|
2
4
|
|
3
5
|
module Stratagem
|
4
6
|
class Client
|
@@ -7,18 +9,29 @@ module Stratagem
|
|
7
9
|
end
|
8
10
|
|
9
11
|
def send(snapshot)
|
12
|
+
Stratagem.logger.phase('exporting')
|
10
13
|
Stratagem.logger.debug "Sending report to server"
|
14
|
+
|
11
15
|
url = URI.parse("#{@authentication.base_url}/snapshots")
|
12
16
|
req = Stratagem.ssl? ? Net::HTTPS::Post.new(url.path) : Net::HTTP::Post.new(url.path)
|
17
|
+
model = snapshot.model.export.to_json
|
18
|
+
puts "Size: #{model.size}"
|
19
|
+
compressed = Zlib::Deflate.deflate(model, Zlib::BEST_COMPRESSION)
|
20
|
+
base64 = Base64.encode64(compressed)
|
21
|
+
puts "Compressed size: #{compressed.size}"
|
22
|
+
puts "Compressed size base 64: #{base64.size}"
|
13
23
|
|
14
24
|
req.set_form_data({
|
15
25
|
'auth_token' => @authentication.credentials[:token],
|
16
26
|
'project_id' => @authentication.credentials[:project],
|
17
27
|
'timestamp' => snapshot.timestamp.to_i,
|
18
|
-
'model' =>
|
28
|
+
'model' => model
|
19
29
|
}, ';')
|
20
30
|
client = Stratagem.ssl? ? Net::HTTPS.new(url.host, url.port) : Net::HTTP.new(url.host, url.port)
|
21
|
-
res = client.start {|http|
|
31
|
+
res = client.start {|http|
|
32
|
+
http.read_timeout= 360
|
33
|
+
http.request(req)
|
34
|
+
}
|
22
35
|
puts "response:"
|
23
36
|
case res
|
24
37
|
when Net::HTTPSuccess, Net::HTTPRedirection
|
@@ -27,8 +40,6 @@ module Stratagem
|
|
27
40
|
else
|
28
41
|
res.error!
|
29
42
|
end
|
30
|
-
|
31
|
-
Stratagem.logger.phase('complete')
|
32
43
|
end
|
33
44
|
end
|
34
45
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Stratagem
|
2
|
+
module Configuration
|
3
|
+
class AuthAuth
|
4
|
+
attr_accessor :model, :authorized_to_view_others_data, :authorized_to_modify_others_data, :authorized_to_upload_files, :authentication_parameters
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
self.authorized_to_view_others_data = true
|
8
|
+
self.authorized_to_modify_others_data = false
|
9
|
+
self.authorized_to_upload_files = true
|
10
|
+
self.model = 'User'
|
11
|
+
end
|
12
|
+
|
13
|
+
def credentials(authentication_parameters)
|
14
|
+
self.authentication_parameters = authentication_parameters
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Stratagem
|
2
|
+
module Configuration
|
3
|
+
class Core
|
4
|
+
attr_accessor :use_transactional_crawling, :use_automatic_mocking
|
5
|
+
attr_reader :credentials
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@use_automatic_mocking = false
|
9
|
+
@use_transactional_crawling = true
|
10
|
+
@credentials = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def authenticate_with(&block)
|
14
|
+
user = AuthAuth.new
|
15
|
+
block.call(user)
|
16
|
+
@credentials << user
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -7,20 +7,25 @@ module Stratagem::Crawler
|
|
7
7
|
module Authentication
|
8
8
|
include Stratagem::Crawler::TraceUtils
|
9
9
|
|
10
|
-
def
|
10
|
+
def user_model
|
11
|
+
model = nil
|
11
12
|
page = find_login_form
|
12
|
-
users = []
|
13
13
|
if (page)
|
14
14
|
form = page.login_form
|
15
15
|
attr_names = form.inputs.map {|input| input.guess_attribute.to_sym }
|
16
16
|
model = guess_login_model(attr_names)
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
end
|
18
|
+
log "Authenticating with model #{model.klass.name}"
|
19
|
+
model
|
20
|
+
end
|
21
|
+
|
22
|
+
def users
|
23
|
+
users = []
|
24
|
+
model = user_model()
|
25
|
+
if (model)
|
26
|
+
users = aquifer.instances_of(model.klass).select {|user| user.stratagem.mock_attributes.size > 0 }
|
22
27
|
else
|
23
|
-
log "ERROR:
|
28
|
+
log "ERROR: Unable to determine authentication model and / or form"
|
24
29
|
end
|
25
30
|
users
|
26
31
|
end
|
@@ -54,8 +59,7 @@ module Stratagem::Crawler
|
|
54
59
|
authentication.success = authentication.response_page.login_form.nil?
|
55
60
|
end
|
56
61
|
rescue
|
57
|
-
|
58
|
-
puts $!.backtrace
|
62
|
+
Stratagem.logger.error($!)
|
59
63
|
end
|
60
64
|
|
61
65
|
puts "authenticated? #{authentication.success}"
|
@@ -80,12 +84,13 @@ module Stratagem::Crawler
|
|
80
84
|
|
81
85
|
# if the first page has one or more redirects to it then use it; otherwise select with page with the fewest inputs
|
82
86
|
if (possibilities.first.inbound_edges(:redirect).size > 0)
|
83
|
-
|
87
|
+
authentication.login_page = possibilities.first
|
88
|
+
return authentication.login_page
|
84
89
|
else
|
85
90
|
page = possibilities.sort {|a,b| a.login_form.inputs.size <=> b.login_form.inputs.size }.first
|
86
91
|
if (page)
|
87
92
|
authentication.login_page = page
|
88
|
-
return
|
93
|
+
return authentication.login_page
|
89
94
|
end
|
90
95
|
end
|
91
96
|
else
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Stratagem::Crawler::Authentication
|
2
|
+
class AuthenticationData
|
3
|
+
attr_accessor :success, :login_page, :form, :response_page, :ssl, :authenticated_with
|
4
|
+
end
|
5
|
+
|
6
|
+
class Base
|
7
|
+
include Stratagem::Crawler::TraceUtils
|
8
|
+
|
9
|
+
def user_models
|
10
|
+
model = nil
|
11
|
+
page = find_login_form
|
12
|
+
if (page)
|
13
|
+
form = page.login_form
|
14
|
+
attr_names = form.inputs.map {|input| input.guess_attribute.to_sym }
|
15
|
+
model = guess_login_model(attr_names)
|
16
|
+
end
|
17
|
+
log "Authenticating with model #{model.klass.name}"
|
18
|
+
[model]
|
19
|
+
end
|
20
|
+
|
21
|
+
def guess_login_model(attr_names)
|
22
|
+
selections = application_model.models.select {|model|
|
23
|
+
puts "#{model.klass.name} - #{model.model_attributes.keys.inspect}"
|
24
|
+
intersect = (model.model_attributes.keys & attr_names)
|
25
|
+
intersect.size > 0
|
26
|
+
}.sort {|a,b|
|
27
|
+
a_intersect = (a.model_attributes.keys & attr_names)
|
28
|
+
b_intersect = (b.model_attributes.keys & attr_names)
|
29
|
+
b_intersect.size <=> a_intersect.size
|
30
|
+
}
|
31
|
+
|
32
|
+
explicit_model = application_model.models.find {|model| model.klass.name == 'User' }
|
33
|
+
selections.unshift explicit_model if explicit_model
|
34
|
+
|
35
|
+
puts "selecting model #{selections.first.klass.name} for authentication" if (selections.size > 0)
|
36
|
+
selections.first
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
module Stratagem::Crawler::Authentication
|
2
|
+
class AuthenticationData
|
3
|
+
attr_accessor :success, :login_page, :form, :response_page, :ssl, :authenticated_with
|
4
|
+
end
|
5
|
+
|
6
|
+
class Base
|
7
|
+
include Stratagem::Crawler::TraceUtils
|
8
|
+
|
9
|
+
def users
|
10
|
+
users = []
|
11
|
+
user_models.each do |user_model|
|
12
|
+
users += aquifer.instances_of(user_model.klass).select {|user| user.stratagem.mock_attributes.size > 0 }
|
13
|
+
end
|
14
|
+
users
|
15
|
+
end
|
16
|
+
|
17
|
+
def reset_authentication
|
18
|
+
@authentication_data = nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def authentication
|
22
|
+
unless @authentication_data
|
23
|
+
@authentication_data = AuthenticationData.new()
|
24
|
+
site_model.authentication = @authentication_data
|
25
|
+
end
|
26
|
+
@authentication_data
|
27
|
+
end
|
28
|
+
|
29
|
+
def authenticate(user, recursion_count=0)
|
30
|
+
reset_authentication
|
31
|
+
|
32
|
+
login(user)
|
33
|
+
route = application_model.routes.recognize(request.path, :post)
|
34
|
+
|
35
|
+
redirected_to = nil
|
36
|
+
page = site_model.add(route, controller, request, response) {|redirect_url| redirected_to = redirect_url }
|
37
|
+
authentication.response_page = page
|
38
|
+
|
39
|
+
begin
|
40
|
+
if (request.url == (redirected_to || '')) || (![200,302].include?(response.code.to_i))
|
41
|
+
authentication.success = false
|
42
|
+
else
|
43
|
+
authentication.success = authentication.response_page.login_form.nil?
|
44
|
+
end
|
45
|
+
rescue
|
46
|
+
Stratagem.logger.error($!)
|
47
|
+
end
|
48
|
+
|
49
|
+
puts "authenticated? #{authentication.success}"
|
50
|
+
if (response && authentication.success)
|
51
|
+
authentication.ssl = request.ssl?
|
52
|
+
authentication.authenticated_with = user
|
53
|
+
yield
|
54
|
+
logout
|
55
|
+
else
|
56
|
+
puts response.body
|
57
|
+
false
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def find_login_form
|
62
|
+
puts "finding login form"
|
63
|
+
if authentication.login_page.nil?
|
64
|
+
puts "locating login page"
|
65
|
+
puts "testing #{site_models.first.pages.size} pages"
|
66
|
+
possibilities = site_models.first.pages.select {|page| page.login_form != nil }
|
67
|
+
possibilities.sort! {|a,b| b.inbound_edges(:redirect).size <=> a.inbound_edges(:redirect).size }
|
68
|
+
|
69
|
+
# if the first page has one or more redirects to it then use it; otherwise select with page with the fewest inputs
|
70
|
+
if (possibilities.first.inbound_edges(:redirect).size > 0)
|
71
|
+
authentication.login_page = possibilities.first
|
72
|
+
return authentication.login_page
|
73
|
+
else
|
74
|
+
page = possibilities.sort {|a,b| a.login_form.inputs.size <=> b.login_form.inputs.size }.first
|
75
|
+
if (page)
|
76
|
+
authentication.login_page = page
|
77
|
+
return authentication.login_page
|
78
|
+
end
|
79
|
+
end
|
80
|
+
else
|
81
|
+
return authentication.login_page
|
82
|
+
end
|
83
|
+
nil
|
84
|
+
end
|
85
|
+
|
86
|
+
def logout
|
87
|
+
reset!
|
88
|
+
end
|
89
|
+
|
90
|
+
def login(user)
|
91
|
+
populate_login_form(user).submit {|action,params|
|
92
|
+
post(action, params)
|
93
|
+
}
|
94
|
+
end
|
95
|
+
|
96
|
+
def populate_login_form(user)
|
97
|
+
# set up the form
|
98
|
+
page = find_login_form
|
99
|
+
page.reload {|url| get url; [request,response] }
|
100
|
+
form = page.login_form
|
101
|
+
|
102
|
+
# map the input values
|
103
|
+
form.inputs.each do |input|
|
104
|
+
# try the expected
|
105
|
+
attribute_name = input.guess_attribute.to_sym
|
106
|
+
attribute_value = user.stratagem.read_mock_attribute(attribute_name) || input.value
|
107
|
+
|
108
|
+
# try again
|
109
|
+
if (attribute_value.nil? || attribute_value == '')
|
110
|
+
attribute_name = input.guess_alternate_attribute.to_sym
|
111
|
+
attribute_value = user.stratagem.read_mock_attribute(attribute_name) || input.value
|
112
|
+
end
|
113
|
+
|
114
|
+
# if it still failed is it a confirmation value? if so, try the original
|
115
|
+
if (attribute_value.nil? || attribute_value == '')
|
116
|
+
if (attribute_name.to_s =~ /confirm/)
|
117
|
+
possible_match = attribute_name.to_s.split('_').select {|a| a !~ /confirm/ }.join('_')
|
118
|
+
if user.stratagem.mock_attributes.keys.include?(possible_match)
|
119
|
+
attribute_value = user.stratagem.read_mock_attribute(possible_match) || input.value
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
|
125
|
+
if (input.kind_of? Stratagem::Crawler::Toggle)
|
126
|
+
input.check
|
127
|
+
elsif (user.stratagem.mock_attributes.keys.include?(attribute_name))
|
128
|
+
input.value = user.stratagem.read_mock_attribute(attribute_name) unless input.hidden?
|
129
|
+
elsif (attribute_name.to_s == 'authenticity_token')
|
130
|
+
puts input.value
|
131
|
+
else
|
132
|
+
puts user.stratagem.mock_attributes.inspect
|
133
|
+
puts "ERROR: Cannot find attribute #{attribute_name} in model #{user.class.name}"
|
134
|
+
end
|
135
|
+
end
|
136
|
+
form
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Stratagem::Crawler::Authentication
|
2
|
+
class Configured < Base
|
3
|
+
include Stratagem::AutoMock::UserLoader
|
4
|
+
|
5
|
+
def user_models
|
6
|
+
credentials.map {|user_credentials|
|
7
|
+
application_model.models.find {|model| model.klass.name == user_credentials.model }
|
8
|
+
}.compact
|
9
|
+
end
|
10
|
+
|
11
|
+
def users
|
12
|
+
log "Loading users for #{credentials.size} sets of credentials"
|
13
|
+
credentials.each do |user_credentials|
|
14
|
+
user = load_user_from_configuration(user_credentials)
|
15
|
+
if (user)
|
16
|
+
log "Loaded credentials for user #{user.id}: #{user.stratagem.mock_attributes.inspect}"
|
17
|
+
user.stratagem.related_objects.each do |object|
|
18
|
+
(objects_by_class[object.class] ||= []) << object
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
log "Loaded #{objects_by_class.keys.size} object types: #{objects_by_class.keys.inspect}"
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -6,12 +6,13 @@ module Stratagem::Crawler
|
|
6
6
|
route_infos, params = build_url(route_container, resolved_params)
|
7
7
|
route_info = route_infos.first
|
8
8
|
unknown_params = params.keys
|
9
|
+
puts "resolving parameter types - #{unknown_params.inspect}"
|
9
10
|
|
10
11
|
if (unknown_params.size > 0)
|
11
12
|
resolve_with_convention(unknown_params, resolved_params)
|
12
13
|
resolve_with_instrumentation(route_container, resolved_params)
|
13
14
|
resolve_id_with_convention(route_container, unknown_params, resolved_params)
|
14
|
-
log "\tresolved parameter types - #{resolved_params.inspect}"
|
15
|
+
log "\tresolved parameter types - #{resolved_params.keys.inspect}, unknown - #{unknown_params.inspect}"
|
15
16
|
end
|
16
17
|
|
17
18
|
if (resolved_params.size > 0)
|
@@ -43,7 +44,7 @@ module Stratagem::Crawler
|
|
43
44
|
# TODO inspect is a hack, refactor
|
44
45
|
if (invocation.args.include?(value.first)) || (invocation.args.inspect.include?('"'+value.first.to_s+'"'))
|
45
46
|
# found match
|
46
|
-
puts "\t\tresolved #{key} to #{invocation.model_class}"
|
47
|
+
puts "\t\tresolved #{key} to #{invocation.model_class} using instrumentation"
|
47
48
|
unknown_params.delete(key)
|
48
49
|
resolved_params[key] = invocation.model_class
|
49
50
|
progress += 1
|
@@ -58,15 +59,18 @@ module Stratagem::Crawler
|
|
58
59
|
end
|
59
60
|
|
60
61
|
def resolve_with_convention(unknown_params, resolved_params)
|
61
|
-
unknown_params.each do |param|
|
62
|
-
if (param =~ /_id$/)
|
62
|
+
unknown_params.clone.each do |param|
|
63
|
+
if (param.to_s =~ /_id$/)
|
63
64
|
begin
|
64
|
-
|
65
|
+
puts "\t\tattempting to resolve #{param.sub(/^:/,'').sub(/_id$/, '').camelize}"
|
66
|
+
model = param.sub(/^:/,'').sub(/_id$/, '').camelize.constantize
|
65
67
|
#success
|
66
68
|
resolved_params[param] = model
|
67
69
|
unknown_params.delete(param)
|
68
|
-
puts "\t\tresolved #{param} to #{model} using convention"
|
70
|
+
puts "\t\tresolved #{param} to #{model.name} using convention"
|
69
71
|
rescue NameError
|
72
|
+
puts "NAMEERROR: #{$!.message}"
|
73
|
+
rescue
|
70
74
|
puts "ERROR: #{$!.message}"
|
71
75
|
end
|
72
76
|
end
|
@@ -77,12 +81,12 @@ module Stratagem::Crawler
|
|
77
81
|
def resolve_id_with_convention(route_container, unknown_params, resolved_params)
|
78
82
|
if (unknown_params.include?('id'))
|
79
83
|
route_container.path.split('/').inject(nil) {|prev,part|
|
80
|
-
if (prev && part
|
84
|
+
if (prev && part =~ /^\:id/)
|
81
85
|
begin
|
82
86
|
resolved_params['id'] = prev.singularize.camelize.constantize
|
83
87
|
unknown_params.delete('id')
|
84
88
|
rescue
|
85
|
-
|
89
|
+
Stratagem.logger.error($!)
|
86
90
|
end
|
87
91
|
end
|
88
92
|
part
|