stratagem 0.2.3 → 0.2.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.
- 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
@@ -15,9 +15,7 @@ module Stratagem::Crawler
|
|
15
15
|
begin
|
16
16
|
call_route!(route_info, track_invocations)
|
17
17
|
rescue Exception
|
18
|
-
|
19
|
-
puts "ERROR: #{$!.message}"
|
20
|
-
puts $!.backtrace
|
18
|
+
Stratagem.logger.error($!)
|
21
19
|
end
|
22
20
|
end
|
23
21
|
|
@@ -31,8 +29,8 @@ module Stratagem::Crawler
|
|
31
29
|
invocations = model_invocations_for_request do
|
32
30
|
case verb
|
33
31
|
when 'get'
|
32
|
+
puts "\t#{route_info[:path].to_s == '/connections'} - #{route_info[:path]}"
|
34
33
|
do_get(route_info)
|
35
|
-
puts "\tresponse code: #{response.code}" if response
|
36
34
|
when 'post'
|
37
35
|
do_post(route_info)
|
38
36
|
when 'put'
|
@@ -43,20 +41,20 @@ module Stratagem::Crawler
|
|
43
41
|
end
|
44
42
|
end
|
45
43
|
|
46
|
-
if (response)
|
47
|
-
|
48
|
-
|
44
|
+
if (response && track_invocations)
|
45
|
+
changes = detect_attribute_changes_in_models(invocations)
|
46
|
+
if (![500].include?(response.code) || (changes.size > 0) || (invocations.size > 0))
|
49
47
|
puts "\tfound #{invocations.size} invocations"
|
50
48
|
invocations.each do |i|
|
51
49
|
puts "\t\t#{i.controller_action} -> #{i.model_class}"
|
52
50
|
end
|
53
|
-
|
54
|
-
|
55
|
-
|
51
|
+
puts "\tchanges values: #{changes.values.inspect}"
|
52
|
+
page = site_model.add(route_info[:route_container], controller, request, response, invocations, changes) {|redirect_url| redirect_proc.call(redirect_url) }
|
53
|
+
puts "\tresponse code: #{response.code} - body size: #{page.response_body.size}"
|
56
54
|
puts "\tadded to site model"
|
57
55
|
end
|
58
56
|
else
|
59
|
-
puts "ERROR: did not call #{route_info
|
57
|
+
puts "ERROR: did not call #{route_info[:path]}"
|
60
58
|
end
|
61
59
|
end
|
62
60
|
|
@@ -169,7 +167,6 @@ module Stratagem::Crawler
|
|
169
167
|
|
170
168
|
def guess_form_for_route(route_info)
|
171
169
|
forms = []
|
172
|
-
pages = site_models.map {|sm| sm.pages }.flatten
|
173
170
|
site_models.each do |site_model|
|
174
171
|
site_model.pages.each do |page|
|
175
172
|
page.forms.each do |form|
|
@@ -178,7 +175,7 @@ module Stratagem::Crawler
|
|
178
175
|
(route_info[:path].sub(/\.\(\:format\)*/, '') == form.action) &&
|
179
176
|
((form.implied_method || form.method).to_s.downcase == route_info[:verb].to_s.downcase)
|
180
177
|
end
|
181
|
-
puts "\
|
178
|
+
puts "\tpageset: #{site_model.name} - form: #{form.action} - #{form.implied_method || form.method} - #{usable} - #{form.inputs.map{|i| i.name}}"
|
182
179
|
forms << form if (usable)
|
183
180
|
end
|
184
181
|
end
|
@@ -56,6 +56,7 @@ module Stratagem::Crawler::Session
|
|
56
56
|
end
|
57
57
|
|
58
58
|
def crawler_session(application_model=nil)
|
59
|
+
aquifer # force fill
|
59
60
|
@application_model = application_model if application_model
|
60
61
|
open_session do |session|
|
61
62
|
@session = session
|
@@ -68,7 +69,16 @@ module Stratagem::Crawler::Session
|
|
68
69
|
end
|
69
70
|
|
70
71
|
def aquifer(initial_capacity=6)
|
71
|
-
@aquifer ||=
|
72
|
+
@aquifer ||= begin
|
73
|
+
Stratagem.logger.phase "mocking_models"
|
74
|
+
|
75
|
+
if Stratagem.configuration.use_automatic_mocking
|
76
|
+
Stratagem::AutoMock::Aquifer.init(application_model).fill_by_automock(initial_capacity)
|
77
|
+
else
|
78
|
+
# TODO - refactor out into another method
|
79
|
+
Stratagem::AutoMock::Aquifer.init(application_model).fill_by_configuration(Stratagem.configuration.credentials)
|
80
|
+
end
|
81
|
+
end
|
72
82
|
end
|
73
83
|
|
74
84
|
def site_models
|
@@ -81,11 +91,13 @@ module Stratagem::Crawler::Session
|
|
81
91
|
end
|
82
92
|
|
83
93
|
def page_set(name, &block)
|
94
|
+
Stratagem.logger.phase "traversing_site"
|
95
|
+
|
84
96
|
log "---------------------------------------"
|
85
97
|
log "Crawling page set #{name}"
|
86
98
|
log "---------------------------------------"
|
87
99
|
reset!
|
88
|
-
site_models << Stratagem::Crawler::SiteModel.new(name)
|
100
|
+
site_models << Stratagem::Crawler::SiteModel::PageSet.new(name)
|
89
101
|
yield site_model
|
90
102
|
end
|
91
103
|
|
@@ -1,174 +1,5 @@
|
|
1
|
-
module Stratagem::Crawler
|
2
|
-
class SiteModel
|
3
|
-
include Stratagem::Crawler::HtmlUtils
|
1
|
+
module Stratagem::Crawler::SiteModel; end
|
4
2
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
def initialize(name)
|
9
|
-
@name = name
|
10
|
-
@pages = []
|
11
|
-
@edges = []
|
12
|
-
end
|
13
|
-
|
14
|
-
def export
|
15
|
-
{
|
16
|
-
:name => name,
|
17
|
-
:pages => @pages.map {|page| page.export },
|
18
|
-
:edges => @edges.map {|edge| edge.export },
|
19
|
-
:authentication => authentication.nil? ? nil : {
|
20
|
-
:authenticated_user_id => authentication.authenticated_with.object_id,
|
21
|
-
:success => authentication.success,
|
22
|
-
:login_page_external_id => authentication.login_page.object_id,
|
23
|
-
:response_page_external_id => authentication.response_page.object_id,
|
24
|
-
:ssl => authentication.ssl
|
25
|
-
},
|
26
|
-
}
|
27
|
-
end
|
28
|
-
|
29
|
-
def add_edge(from,to,type)
|
30
|
-
self.edges << Edge.new(from,to,type)
|
31
|
-
end
|
32
|
-
|
33
|
-
def add(route, controller, request, response, invocations=[], model_changes={}, &block)
|
34
|
-
page = Page.new(self, controller, request, response, invocations, model_changes, &block)
|
35
|
-
self.pages << page
|
36
|
-
page
|
37
|
-
end
|
38
|
-
|
39
|
-
def pages_for(id)
|
40
|
-
if (id.kind_of?(String))
|
41
|
-
pages.select {|page| page.url == id }
|
42
|
-
else
|
43
|
-
pages.select {|page| page.route == id }
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
end
|
48
|
-
|
49
|
-
class Edge
|
50
|
-
# type -> :link, :redirect,
|
51
|
-
attr_accessor :from, :to, :type
|
52
|
-
|
53
|
-
def initialize(from, to, type)
|
54
|
-
@from = from
|
55
|
-
@to = to
|
56
|
-
@type = type
|
57
|
-
end
|
58
|
-
|
59
|
-
def export
|
60
|
-
{
|
61
|
-
:from => from.object_id,
|
62
|
-
:to => to.object_id,
|
63
|
-
:relation_type => type
|
64
|
-
}
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
class Page
|
69
|
-
include Stratagem::Crawler::HtmlUtils
|
70
|
-
|
71
|
-
attr_reader :response
|
72
|
-
|
73
|
-
attr_accessor :url
|
74
|
-
attr_accessor :path
|
75
|
-
attr_accessor :method
|
76
|
-
attr_accessor :redirected_to
|
77
|
-
attr_accessor :document
|
78
|
-
attr_accessor :response_body
|
79
|
-
|
80
|
-
def initialize(site_model, controller, request, response, invocations, model_changes, &block)
|
81
|
-
@site_model = site_model
|
82
|
-
@invocations = invocations
|
83
|
-
@model_changes = model_changes
|
84
|
-
@authenticity_checked = (controller && controller.methods.include?(:authenticity_checked?)) ? controller.authenticity_checked? : true
|
85
|
-
init(request, response, &block)
|
86
|
-
end
|
87
|
-
|
88
|
-
def route
|
89
|
-
@route ||= Stratagem::Model::Application.instance.routes.recognize(self)
|
90
|
-
end
|
91
|
-
|
92
|
-
def export
|
93
|
-
h = {
|
94
|
-
:external_id => self.object_id,
|
95
|
-
:url => url,
|
96
|
-
:path => path,
|
97
|
-
:request_method => method,
|
98
|
-
:redirected_to_page_external_id => redirected_to ? redirected_to.object_id : nil,
|
99
|
-
:route_external_id => route ? route.object_id : nil,
|
100
|
-
:references => @invocations.map {|i| i.to_reference.export },
|
101
|
-
:model_changes => Hash[@model_changes.map {|model,changes| [model.object_id, changes] }].to_json,
|
102
|
-
:authenticity_checked => @authenticity_checked,
|
103
|
-
:parameters => @request.parameters.to_json,
|
104
|
-
:response_body => @response_body
|
105
|
-
}
|
106
|
-
h
|
107
|
-
end
|
108
|
-
|
109
|
-
def init(request, response, &block)
|
110
|
-
@request = request.clone
|
111
|
-
@response = response.clone
|
112
|
-
@url = request.url
|
113
|
-
@path = request.path
|
114
|
-
@method = request.method
|
115
|
-
begin
|
116
|
-
@document = Nokogiri::HTML(response.body)
|
117
|
-
rescue
|
118
|
-
puts "ERROR: Could not parse html: #{$!.message} - #{response.body}"
|
119
|
-
end
|
120
|
-
@response_body = response.body
|
121
|
-
self.redirected_to = block.call(response.redirect_url) if response.redirect?
|
122
|
-
end
|
123
|
-
|
124
|
-
def reload(&block)
|
125
|
-
# TODO - should support all the verbs and params, but
|
126
|
-
# hack together for now to reload the authenticity token
|
127
|
-
request,response = yield url
|
128
|
-
init(request, response) {|redirected_to| }
|
129
|
-
end
|
130
|
-
|
131
|
-
def redirected?
|
132
|
-
!self.redirected_to.nil?
|
133
|
-
end
|
134
|
-
|
135
|
-
def forms
|
136
|
-
@forms ||= begin
|
137
|
-
if (@document)
|
138
|
-
forms = self.parse_forms(@document)
|
139
|
-
forms.each do |form|
|
140
|
-
form.page = self
|
141
|
-
end
|
142
|
-
forms
|
143
|
-
else
|
144
|
-
[]
|
145
|
-
end
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
def login_form
|
150
|
-
self.find_login_form(@document)
|
151
|
-
end
|
152
|
-
|
153
|
-
def to_html
|
154
|
-
@document.to_html
|
155
|
-
end
|
156
|
-
|
157
|
-
def outbound_edges(type=nil)
|
158
|
-
@site_model.edges.select {|edge| edge.from == self && (type.nil? || (type == edge.type)) }
|
159
|
-
end
|
160
|
-
|
161
|
-
def inbound_edges(type=nil)
|
162
|
-
@site_model.edges.select {|edge| (edge.to == self) && (type.nil? || (type == edge.type)) }
|
163
|
-
end
|
164
|
-
|
165
|
-
def title
|
166
|
-
if ((@document) && !(@title))
|
167
|
-
title = (@document/'head title').first
|
168
|
-
@title = title.inner_html if title
|
169
|
-
end
|
170
|
-
@title
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
|
-
end
|
3
|
+
require 'stratagem/crawler/site_model/page_set'
|
4
|
+
require 'stratagem/crawler/site_model/page'
|
5
|
+
require 'stratagem/crawler/site_model/edge'
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Stratagem::Crawler::SiteModel
|
2
|
+
class Edge
|
3
|
+
# type -> :link, :redirect,
|
4
|
+
attr_accessor :from, :to, :type
|
5
|
+
|
6
|
+
def initialize(from, to, type)
|
7
|
+
@from = from
|
8
|
+
@to = to
|
9
|
+
@type = type
|
10
|
+
end
|
11
|
+
|
12
|
+
def export
|
13
|
+
{
|
14
|
+
:from_page_external_id => from.object_id,
|
15
|
+
:to_page_external_id => to.object_id,
|
16
|
+
:relation_type => type
|
17
|
+
}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
module Stratagem::Crawler::SiteModel
|
2
|
+
|
3
|
+
class Page
|
4
|
+
include Stratagem::Crawler::HtmlUtils
|
5
|
+
|
6
|
+
attr_reader :response
|
7
|
+
|
8
|
+
attr_accessor :url
|
9
|
+
attr_accessor :path
|
10
|
+
attr_accessor :method
|
11
|
+
attr_accessor :redirected_to
|
12
|
+
attr_accessor :document
|
13
|
+
attr_accessor :response_body
|
14
|
+
|
15
|
+
def initialize(site_model, controller, request, response, invocations, model_changes, &block)
|
16
|
+
@site_model = site_model
|
17
|
+
@invocations = invocations
|
18
|
+
@model_changes = model_changes
|
19
|
+
@authenticity_checked = (controller && controller.methods.include?(:authenticity_checked?)) ? controller.authenticity_checked? : true
|
20
|
+
init(request, response, &block)
|
21
|
+
end
|
22
|
+
|
23
|
+
def route
|
24
|
+
@route ||= Stratagem::Model::Application.instance.routes.recognize(self)
|
25
|
+
end
|
26
|
+
|
27
|
+
def export
|
28
|
+
h = {
|
29
|
+
:external_id => self.object_id,
|
30
|
+
:url => url,
|
31
|
+
:path => path,
|
32
|
+
:request_method => method,
|
33
|
+
:redirected_to_page_external_id => redirected_to ? redirected_to.object_id : nil,
|
34
|
+
:route_external_id => route ? route.object_id : nil,
|
35
|
+
:references_attributes => @invocations.map {|i| i.to_reference.export },
|
36
|
+
:model_changes => Hash[@model_changes.map {|model,changes| [model.object_id, changes] }].to_json,
|
37
|
+
:authenticity_checked => @authenticity_checked,
|
38
|
+
:parameters => @request.parameters.to_json,
|
39
|
+
:response_body => @response_body,
|
40
|
+
:response_code => @response.code
|
41
|
+
}
|
42
|
+
h
|
43
|
+
end
|
44
|
+
|
45
|
+
def init(request, response, &block)
|
46
|
+
@request = request.clone
|
47
|
+
@response = response.clone
|
48
|
+
@url = request.url
|
49
|
+
@path = request.path
|
50
|
+
@method = request.method
|
51
|
+
body = response.body
|
52
|
+
begin
|
53
|
+
if [500, 400, 302].include?(response.code)
|
54
|
+
body = ''
|
55
|
+
elsif
|
56
|
+
body.kind_of?(Array)
|
57
|
+
body = body.join
|
58
|
+
body = body.slice(0,20000)
|
59
|
+
end
|
60
|
+
|
61
|
+
@document = Nokogiri::HTML(body)
|
62
|
+
rescue
|
63
|
+
puts "ERROR: Could not parse html: #{$!.message} - #{body}"
|
64
|
+
end
|
65
|
+
|
66
|
+
@response_body = body
|
67
|
+
|
68
|
+
self.redirected_to = block.call(response.redirect_url) if response.redirect?
|
69
|
+
end
|
70
|
+
|
71
|
+
def reload(&block)
|
72
|
+
# TODO - should support all the verbs and params, but
|
73
|
+
# hack together for now to reload the authenticity token
|
74
|
+
request,response = yield url
|
75
|
+
init(request, response) {|redirected_to| }
|
76
|
+
end
|
77
|
+
|
78
|
+
def redirected?
|
79
|
+
!self.redirected_to.nil?
|
80
|
+
end
|
81
|
+
|
82
|
+
def forms
|
83
|
+
@forms ||= begin
|
84
|
+
if (@document)
|
85
|
+
forms = self.parse_forms(@document)
|
86
|
+
forms.each do |form|
|
87
|
+
form.page = self
|
88
|
+
end
|
89
|
+
forms
|
90
|
+
else
|
91
|
+
[]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def login_form
|
97
|
+
self.find_login_form(@document)
|
98
|
+
end
|
99
|
+
|
100
|
+
def to_html
|
101
|
+
@document.to_html
|
102
|
+
end
|
103
|
+
|
104
|
+
def outbound_edges(type=nil)
|
105
|
+
@site_model.edges.select {|edge| edge.from == self && (type.nil? || (type == edge.type)) }
|
106
|
+
end
|
107
|
+
|
108
|
+
def inbound_edges(type=nil)
|
109
|
+
@site_model.edges.select {|edge| (edge.to == self) && (type.nil? || (type == edge.type)) }
|
110
|
+
end
|
111
|
+
|
112
|
+
def title
|
113
|
+
if ((@document) && !(@title))
|
114
|
+
title = (@document/'head title').first
|
115
|
+
@title = title.inner_html if title
|
116
|
+
end
|
117
|
+
@title
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Stratagem::Crawler::SiteModel
|
2
|
+
|
3
|
+
class PageSet
|
4
|
+
include Stratagem::Crawler::HtmlUtils
|
5
|
+
|
6
|
+
attr_reader :pages, :edges, :name
|
7
|
+
attr_accessor :authentication
|
8
|
+
|
9
|
+
def initialize(name)
|
10
|
+
@name = name
|
11
|
+
@pages = []
|
12
|
+
@edges = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def export
|
16
|
+
puts "Exporting page set #{name} with #{@pages.size} initial pages"
|
17
|
+
pages = @pages.select {|page| page.response_body && page.response_body.size > 0 }
|
18
|
+
puts "\t#{pages.size} filtered pages"
|
19
|
+
pages = pages.map {|page| page.export }
|
20
|
+
|
21
|
+
pages << authentication.login_page.export if authentication && authentication.login_page
|
22
|
+
pages << authentication.response_page.export if authentication && authentication.response_page
|
23
|
+
|
24
|
+
puts "\t#{pages.size} exported pages"
|
25
|
+
{
|
26
|
+
:name => name,
|
27
|
+
:pages_attributes => pages,
|
28
|
+
:edges_attributes => @edges.map {|edge| edge.export },
|
29
|
+
:authentication_attributes => authentication.nil? ? nil : {
|
30
|
+
:authenticated_user_id => authentication.authenticated_with.object_id,
|
31
|
+
:success => authentication.success,
|
32
|
+
:login_page_external_id => authentication.login_page ? authentication.login_page.object_id : nil,
|
33
|
+
:response_page_external_id => authentication.response_page ? authentication.response_page.object_id : nil,
|
34
|
+
:ssl => authentication.ssl
|
35
|
+
},
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
def add_edge(from,to,type)
|
40
|
+
self.edges << Edge.new(from,to,type)
|
41
|
+
end
|
42
|
+
|
43
|
+
def add(route, controller, request, response, invocations=[], model_changes={}, &block)
|
44
|
+
page = Page.new(self, controller, request, response, invocations, model_changes, &block)
|
45
|
+
self.pages << page
|
46
|
+
page
|
47
|
+
end
|
48
|
+
|
49
|
+
def pages_for(id)
|
50
|
+
if (id.kind_of?(String))
|
51
|
+
pages.select {|page| page.url == id }
|
52
|
+
else
|
53
|
+
pages.select {|page| page.route == id }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|