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
@@ -1,25 +1,14 @@
|
|
1
1
|
module Stratagem::Instrumentation::Models; end
|
2
2
|
module Stratagem::Instrumentation::Models::Adapters; end
|
3
3
|
|
4
|
+
require 'stratagem/instrumentation/models/association'
|
5
|
+
|
4
6
|
require 'stratagem/instrumentation/models/mocking'
|
5
7
|
require 'stratagem/instrumentation/models/metadata'
|
6
8
|
require 'stratagem/instrumentation/models/tracing'
|
7
9
|
require 'stratagem/instrumentation/models/annotations'
|
8
10
|
require 'stratagem/instrumentation/models/detect'
|
9
11
|
|
10
|
-
require 'stratagem/instrumentation/models/persistence'
|
11
12
|
require 'stratagem/instrumentation/models/authentication'
|
13
|
+
require 'stratagem/instrumentation/models/persistence'
|
12
14
|
require 'stratagem/instrumentation/models/support_libraries'
|
13
|
-
|
14
|
-
# base = File.join(File.dirname(__FILE__), 'models', 'persistence', 'util')
|
15
|
-
# Dir.entries(base).select {|s| s =~ /\.rb$/}.each {|helper|
|
16
|
-
# require File.join(base, helper.gsub(/\.rb/, ''))
|
17
|
-
# }
|
18
|
-
#
|
19
|
-
# base = File.join(File.dirname(__FILE__), 'models', 'persistence')
|
20
|
-
# Dir.entries(base).select {|s| s !~ /^\./ && s != 'util' }.each {|adapter_dir|
|
21
|
-
# require File.join(base, adapter_dir, 'detect')
|
22
|
-
# require File.join(base, adapter_dir, 'tracing')
|
23
|
-
# require File.join(base, adapter_dir, 'metadata')
|
24
|
-
# require File.join(base, adapter_dir, 'extensions')
|
25
|
-
# }
|
@@ -12,6 +12,36 @@ module Stratagem::Instrumentation::Models
|
|
12
12
|
def method_missing(method, *args, &block)
|
13
13
|
@object.class.stratagem.send(method, *args, &block)
|
14
14
|
end
|
15
|
+
|
16
|
+
# objects that are related to this object
|
17
|
+
def related_objects(collection_size_limit=5000)
|
18
|
+
traverse_objects(collection_size_limit)
|
19
|
+
end
|
20
|
+
|
21
|
+
def traverse_objects(collection_size_limit, collection=[], class_chain=[])
|
22
|
+
return if collection.size >= collection_size_limit
|
23
|
+
|
24
|
+
unless collection.include?(@object)
|
25
|
+
collection << @object
|
26
|
+
relations(:has_many).each do |relation|
|
27
|
+
puts "relation #{relation.name} - #{collection.size} - #{relation.klass}"
|
28
|
+
if (relation.klass && !class_chain.include?(relation.klass))
|
29
|
+
class_chain << relation.klass
|
30
|
+
begin
|
31
|
+
related = @object.send(relation.name)
|
32
|
+
if (related.kind_of?(Array))
|
33
|
+
related.each {|r| r.stratagem.traverse_objects(collection_size_limit, collection, class_chain) }
|
34
|
+
elsif (!related.nil?)
|
35
|
+
related.stratagem.traverse_objects(collection_size_limit, collection, class_chain)
|
36
|
+
end
|
37
|
+
rescue
|
38
|
+
Stratagem.logger.error($!)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
collection
|
44
|
+
end
|
15
45
|
end
|
16
46
|
|
17
47
|
class Annotations
|
@@ -43,8 +73,12 @@ module Stratagem::Instrumentation::Models
|
|
43
73
|
# connect the adapters
|
44
74
|
detect_adapters(model).each {|adapter|
|
45
75
|
if adapter.detector.supports?(model)
|
46
|
-
|
47
|
-
|
76
|
+
begin
|
77
|
+
puts "#{model.name} supports #{adapter.tracing.name}"
|
78
|
+
model.send(:include, adapter.tracing)
|
79
|
+
rescue
|
80
|
+
Rails.logger.error($!)
|
81
|
+
end
|
48
82
|
end
|
49
83
|
}
|
50
84
|
end
|
@@ -75,14 +109,14 @@ module Stratagem::Instrumentation::Models
|
|
75
109
|
end
|
76
110
|
|
77
111
|
def initialize(model)
|
78
|
-
puts "initializing stratagem for #{model.name}
|
112
|
+
puts "initializing stratagem for #{model.name}"
|
79
113
|
@model = model
|
80
114
|
self.class.detect_adapters(model).each do |adapter|
|
81
115
|
if adapter.detector.supports?(model)
|
82
116
|
# puts "\t#{model.name} supports #{adapter.detector.name}"
|
83
117
|
instrument_model(adapter)
|
84
|
-
|
85
|
-
|
118
|
+
else
|
119
|
+
# puts "#{model.name} does not support #{adapter.detector.name}"
|
86
120
|
end
|
87
121
|
end
|
88
122
|
rescue
|
@@ -2,6 +2,7 @@ module Stratagem::Instrumentation::Models::Authentication::Authlogic
|
|
2
2
|
class Detect < Stratagem::Instrumentation::Models::Detect
|
3
3
|
def self.supports?(model)
|
4
4
|
begin
|
5
|
+
# puts "AUTHLOGIC MODEL #{model.name} - #{model.ancestors.include?(::Authlogic::ActsAsAuthentic::MagicColumns::Methods)}"
|
5
6
|
model.ancestors.include?(::Authlogic::ActsAsAuthentic::MagicColumns::Methods)
|
6
7
|
rescue
|
7
8
|
false
|
@@ -2,7 +2,7 @@ module Stratagem::Instrumentation::Models::Authentication::Devise
|
|
2
2
|
class Detect < Stratagem::Instrumentation::Models::Detect
|
3
3
|
def self.supports?(model)
|
4
4
|
begin
|
5
|
-
model.ancestors.find {|a| a.name.include?
|
5
|
+
model.ancestors.find {|a| a.name && a.name.include?('Devise::Models') } != nil
|
6
6
|
rescue
|
7
7
|
false
|
8
8
|
end
|
@@ -25,6 +25,10 @@ module Stratagem::Instrumentation::Models
|
|
25
25
|
|
26
26
|
# Convenience methods
|
27
27
|
|
28
|
+
def connected_classes
|
29
|
+
traverse_graph(model) - [model]
|
30
|
+
end
|
31
|
+
|
28
32
|
def subclasses?
|
29
33
|
model.sg_subclasses().size > 0
|
30
34
|
end
|
@@ -61,7 +65,9 @@ module Stratagem::Instrumentation::Models
|
|
61
65
|
end
|
62
66
|
|
63
67
|
def callbacks
|
64
|
-
adapters.select {|a|
|
68
|
+
adapters.select {|a|
|
69
|
+
a.detector.supports?(model)
|
70
|
+
}.map {|a| a.metadata }
|
65
71
|
end
|
66
72
|
|
67
73
|
def validators
|
@@ -71,6 +77,7 @@ module Stratagem::Instrumentation::Models
|
|
71
77
|
private
|
72
78
|
|
73
79
|
def run_callbacks(method, *args)
|
80
|
+
puts "#{self.class.name} model" if (method == :attribute_names)
|
74
81
|
results = callbacks.inject([]) {|memory,callback|
|
75
82
|
begin
|
76
83
|
memory << callback.send(method, *args) if callback.methods_include?(method)
|
@@ -82,5 +89,20 @@ module Stratagem::Instrumentation::Models
|
|
82
89
|
results.flatten.compact.uniq
|
83
90
|
end
|
84
91
|
|
92
|
+
|
93
|
+
private
|
94
|
+
|
95
|
+
# see connected_classes
|
96
|
+
def traverse_graph(application_class, class_chain=[])
|
97
|
+
class_chain << application_class
|
98
|
+
application_class.stratagem.relations.each do |relation|
|
99
|
+
traverse_graph(relation.from_class, class_chain) unless class_chain.include?(relation.from_class)
|
100
|
+
traverse_graph(relation.klass, class_chain) unless class_chain.include?(relation.klass)
|
101
|
+
end
|
102
|
+
puts class_chain.map {|c| c.name }.join(" -> ")
|
103
|
+
class_chain
|
104
|
+
end
|
105
|
+
|
106
|
+
|
85
107
|
end
|
86
108
|
end
|
@@ -2,8 +2,7 @@ module Stratagem::Instrumentation::Models::Persistence; end
|
|
2
2
|
|
3
3
|
base = File.join(File.dirname(__FILE__), 'persistence')
|
4
4
|
Dir.entries(base).select {|s| s !~ /^\./ && s != 'util' }.each {|adapter_dir|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
require File.join(base, adapter_dir, 'extensions')
|
5
|
+
['detect', 'tracing', 'metadata', 'extensions'].each do |extension|
|
6
|
+
require File.join(base, adapter_dir, extension) if File.exists?(File.join(base, adapter_dir, extension+'.rb'))
|
7
|
+
end
|
9
8
|
}
|
@@ -7,7 +7,7 @@ module Stratagem::Instrumentation::Models::Persistence::ActiveRecord
|
|
7
7
|
begin
|
8
8
|
@instance = @model.new unless (@model == ActiveRecord::Base)
|
9
9
|
rescue
|
10
|
-
puts "ERROR: #{@model
|
10
|
+
puts "ERROR: #{@model} could not be instantiated: #{$!.message}"
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
@@ -23,7 +23,7 @@ module Stratagem::Instrumentation::Models::Persistence::ActiveRecord
|
|
23
23
|
begin
|
24
24
|
Stratagem::Instrumentation::Models::Association.new(model, a.name.to_sym, a.association_foreign_key.to_sym, klass, a.macro, a.options)
|
25
25
|
rescue
|
26
|
-
puts "ERROR: #{$!.message}"
|
26
|
+
puts "METADATA ERROR: #{$!.message}"
|
27
27
|
end
|
28
28
|
}.compact
|
29
29
|
end
|
@@ -18,7 +18,7 @@ get '/' do
|
|
18
18
|
end
|
19
19
|
|
20
20
|
get '/credentials' do
|
21
|
-
Stratagem::Authentication.instance.store_credentials(params[:
|
21
|
+
Stratagem::Authentication.instance.store_credentials(params[:api_key], params[:project])
|
22
22
|
redirect '/'
|
23
23
|
end
|
24
24
|
|
@@ -27,9 +27,15 @@ get '/logs' do
|
|
27
27
|
logger = Stratagem.logger
|
28
28
|
logs = [logger.pop]
|
29
29
|
logs << logger.pop until logger.empty?
|
30
|
-
logs.
|
30
|
+
logs.map {|log|
|
31
|
+
{
|
32
|
+
:phase => log.phase,
|
33
|
+
:details => log.details,
|
34
|
+
:level => log.level
|
35
|
+
}
|
36
|
+
}.to_json
|
31
37
|
else
|
32
|
-
|
38
|
+
null
|
33
39
|
end
|
34
40
|
end
|
35
41
|
|
@@ -2,24 +2,26 @@ $(document).ready(function() {
|
|
2
2
|
var currentPhase = null,
|
3
3
|
$phases = $("li");
|
4
4
|
|
5
|
+
function changePhase(name) {
|
6
|
+
$phases.removeClass("active");
|
7
|
+
$("#"+name).addClass("active");
|
8
|
+
if (name == "complete") {
|
9
|
+
window.setTimeout(function() { window.location = $("#completeUrl").attr("href"); }, 1000);
|
10
|
+
}
|
11
|
+
};
|
12
|
+
|
5
13
|
window.setInterval(function() {
|
6
14
|
$.getJSON('/logs', function(data) {
|
7
15
|
var logs = $("#logs .modeling_application ul");
|
8
|
-
if (data == null)
|
9
|
-
|
16
|
+
if (data == null) {
|
17
|
+
changePhase("complete");
|
18
|
+
}
|
10
19
|
|
11
20
|
$.each(data, function(idx, val) {
|
12
|
-
var phase = val[
|
13
|
-
|
14
|
-
|
21
|
+
var phase = val['phase'];
|
22
|
+
|
15
23
|
if (phase != currentPhase) {
|
16
|
-
|
17
|
-
$("#"+phase).addClass("active");
|
18
|
-
|
19
|
-
if (phase == "complete")
|
20
|
-
window.setTimeout(function() {
|
21
|
-
window.location = $("#completeUrl").attr("href");
|
22
|
-
}, 1000);
|
24
|
+
changePhase(phase);
|
23
25
|
}
|
24
26
|
});
|
25
27
|
});
|
@@ -1,4 +1,4 @@
|
|
1
|
-
- phases = ['modeling application', 'mocking models', 'traversing site', '
|
1
|
+
- phases = ['modeling application', 'mocking models', 'traversing site', 'exporting']
|
2
2
|
|
3
3
|
%html
|
4
4
|
%head
|
@@ -26,9 +26,9 @@
|
|
26
26
|
%li{:id => "#{phases[2].gsub(/\s/, '_')}"}
|
27
27
|
crawling your website
|
28
28
|
%li{:id => "#{phases[3].gsub(/\s/, '_')}"}
|
29
|
-
|
29
|
+
exporting security snapshot
|
30
30
|
%li#complete
|
31
|
-
|
31
|
+
complete
|
32
32
|
%li{:style => "display:none"}
|
33
33
|
%a{:id => "completeUrl", :href => Stratagem::Authentication.instance.project_url}
|
34
34
|
|
data/lib/stratagem/logger.rb
CHANGED
@@ -7,9 +7,15 @@ module Stratagem
|
|
7
7
|
|
8
8
|
MESSAGE_QUEUE = []
|
9
9
|
|
10
|
-
Message = Struct.new(:phase, :timestamp, :details)
|
10
|
+
Message = Struct.new(:phase, :timestamp, :details, :level)
|
11
11
|
@@blocker = Blocker.new()
|
12
12
|
|
13
|
+
attr_reader :errors
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@errors = []
|
17
|
+
end
|
18
|
+
|
13
19
|
def phase(phase)
|
14
20
|
@phase = phase
|
15
21
|
end
|
@@ -18,8 +24,17 @@ module Stratagem
|
|
18
24
|
add(Message.new(@phase, Time.now, message))
|
19
25
|
end
|
20
26
|
|
27
|
+
def error(exception)
|
28
|
+
puts exception.message
|
29
|
+
puts exception.backtrace
|
30
|
+
@errors << create_error(exception)
|
31
|
+
end
|
32
|
+
|
21
33
|
def fatal(exception)
|
22
|
-
|
34
|
+
puts exception.message
|
35
|
+
puts exception.backtrace
|
36
|
+
@errors << create_error(exception)
|
37
|
+
# add(Message.new(@phase, Time.now, $!.message))
|
23
38
|
end
|
24
39
|
|
25
40
|
def pop
|
@@ -33,6 +48,17 @@ module Stratagem
|
|
33
48
|
|
34
49
|
private
|
35
50
|
|
51
|
+
def create_error(exception)
|
52
|
+
if (exception.kind_of?(Exception))
|
53
|
+
{ :message => exception.message, :backtrace => exception.backtrace.slice(0,50) }
|
54
|
+
elsif (e.kind_of?(String))
|
55
|
+
{ :message => exception, :backtrace => [] }
|
56
|
+
else
|
57
|
+
puts "ERROR: unknown error type #{e.class.name}"
|
58
|
+
nil
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
36
62
|
def add(obj)
|
37
63
|
puts obj.details
|
38
64
|
MESSAGE_QUEUE << obj
|
data/lib/stratagem/model.rb
CHANGED
@@ -3,6 +3,12 @@ end
|
|
3
3
|
|
4
4
|
require 'stratagem/model/application'
|
5
5
|
require 'stratagem/model/parse_util'
|
6
|
+
|
7
|
+
require 'stratagem/model/containers/base'
|
8
|
+
require 'stratagem/model/containers/gem'
|
9
|
+
require 'stratagem/model/containers/route'
|
10
|
+
require 'stratagem/model/containers/plugin'
|
11
|
+
|
6
12
|
require 'stratagem/model/components/base'
|
7
13
|
require 'stratagem/model/components/reference'
|
8
14
|
require 'stratagem/model/components/model'
|
@@ -16,13 +16,13 @@ module Stratagem::Model
|
|
16
16
|
|
17
17
|
def initialize
|
18
18
|
log "initializing application model"
|
19
|
-
@models =
|
20
|
-
@controllers =
|
21
|
-
@routes =
|
22
|
-
@views =
|
23
|
-
@static_files =
|
24
|
-
@gems =
|
25
|
-
@plugins =
|
19
|
+
@models = Stratagem::Model::Containers::Base.new self
|
20
|
+
@controllers = Stratagem::Model::Containers::Base.new self
|
21
|
+
@routes = Stratagem::Model::Containers::Route.new self
|
22
|
+
@views = Stratagem::Model::Containers::Base.new self
|
23
|
+
@static_files = Stratagem::Model::Containers::Base.new self
|
24
|
+
@gems = Stratagem::Model::Containers::Gem.new self
|
25
|
+
@plugins = Stratagem::Model::Containers::Plugin.new self
|
26
26
|
end
|
27
27
|
|
28
28
|
def log(msg)
|
@@ -31,7 +31,7 @@ module Stratagem::Model
|
|
31
31
|
|
32
32
|
def export
|
33
33
|
puts "exporting site model"
|
34
|
-
puts "references
|
34
|
+
puts "\tmapping #{Stratagem::Instrumentation::Models::Tracing.invocations_audit.size} references"
|
35
35
|
references = []
|
36
36
|
begin
|
37
37
|
references = Stratagem::Instrumentation::Models::Tracing.invocations_audit.uniq.map {|ia| ia.to_reference.export }.uniq
|
@@ -39,28 +39,30 @@ module Stratagem::Model
|
|
39
39
|
puts $!.message
|
40
40
|
puts $!.backtrace
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
|
+
puts "\tmapping #{Stratagem.logger.errors.size} errors"
|
44
|
+
errors = Stratagem.logger.errors.compact.uniq
|
43
45
|
begin
|
44
|
-
# references = @controllers.map {|c| c.references }.flatten.map {|r| r.export }.uniq
|
45
46
|
h = {
|
46
47
|
:rails_version => rails_version,
|
47
48
|
:rails_environment => Rails.env,
|
48
49
|
:rails_root => Rails.root.to_s,
|
49
|
-
:models => @models.export,
|
50
|
-
:controllers => @controllers.export,
|
51
|
-
:routes => @routes.export,
|
52
|
-
:views => @views.export,
|
53
|
-
:gems => @gems.export,
|
54
50
|
:plugins => @plugins.export,
|
55
|
-
:
|
56
|
-
|
51
|
+
:scanning_exceptions_attributes => errors,
|
52
|
+
|
53
|
+
:models_attributes => @models.export,
|
54
|
+
:controllers_attributes => @controllers.export,
|
55
|
+
:routes_attributes => @routes.export,
|
56
|
+
:views_attributes => @views.export,
|
57
|
+
:gems => @gems.export,
|
58
|
+
:references_attributes => references,
|
59
|
+
:site_attributes => crawler ? crawler.export : {},
|
57
60
|
}
|
58
61
|
rescue
|
59
62
|
puts $!.message
|
60
63
|
puts $!.backtrace
|
61
64
|
end
|
62
|
-
puts "
|
63
|
-
puts h.to_json
|
65
|
+
puts "Sending snapshot of #{h.to_json.size} bytes"
|
64
66
|
h
|
65
67
|
end
|
66
68
|
|
@@ -69,120 +71,5 @@ module Stratagem::Model
|
|
69
71
|
end
|
70
72
|
end
|
71
73
|
|
72
|
-
protected
|
73
|
-
|
74
|
-
class GemContainer
|
75
|
-
include Enumerable
|
76
|
-
|
77
|
-
def initialize(app_model)
|
78
|
-
@app_model = app_model
|
79
|
-
@gems = Gem.loaded_specs
|
80
|
-
end
|
81
|
-
|
82
|
-
def names
|
83
|
-
@gems.map {|g| g[0] }
|
84
|
-
end
|
85
|
-
|
86
|
-
def export(options=nil)
|
87
|
-
@gems.map {|g|
|
88
|
-
name, spec = g
|
89
|
-
[name, {:version => spec.version.version}]
|
90
|
-
}
|
91
|
-
end
|
92
|
-
|
93
|
-
def each
|
94
|
-
@gems.each {|spec| yield spec }
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
class ComponentContainer
|
99
|
-
include Enumerable
|
100
|
-
|
101
|
-
attr_reader :invalid, :missing, :parse_trees, :components, :errors
|
102
|
-
|
103
|
-
def initialize(app_model)
|
104
|
-
@app_model = app_model
|
105
|
-
@components = Set.new()
|
106
|
-
@parse_trees = {}
|
107
|
-
@invalid = []
|
108
|
-
@missing = {}
|
109
|
-
end
|
110
|
-
|
111
|
-
def export(options=nil)
|
112
|
-
{
|
113
|
-
:components => @components.to_a.map {|c| c.export }.compact,
|
114
|
-
:invalid => @invalid.map {|c| c.export }.compact
|
115
|
-
}
|
116
|
-
end
|
117
|
-
|
118
|
-
def find
|
119
|
-
@components.find{|component| yield component }
|
120
|
-
end
|
121
|
-
|
122
|
-
def clear
|
123
|
-
@components.clear
|
124
|
-
end
|
125
|
-
|
126
|
-
def size
|
127
|
-
@components.size
|
128
|
-
end
|
129
|
-
|
130
|
-
def -(other)
|
131
|
-
@components-other
|
132
|
-
end
|
133
|
-
|
134
|
-
def each
|
135
|
-
@components.each {|e| yield e }
|
136
|
-
end
|
137
|
-
|
138
|
-
def map
|
139
|
-
@components.map {|e| yield e }
|
140
|
-
end
|
141
|
-
|
142
|
-
def << (component)
|
143
|
-
if (component.kind_of?(Array))
|
144
|
-
component.each {|e|
|
145
|
-
@components << e
|
146
|
-
e.app_model = @app_model if e.methods_include?(:app_model=)
|
147
|
-
}
|
148
|
-
elsif (component.kind_of?(Exception))
|
149
|
-
errors << component
|
150
|
-
else
|
151
|
-
@components << component
|
152
|
-
component.app_model = @app_model if component.methods_include?(:app_model=)
|
153
|
-
end
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
class RouteContainer < ComponentContainer
|
158
|
-
def recognize(page, method = :get)
|
159
|
-
path = nil
|
160
|
-
if (page.kind_of?(Stratagem::Crawler::Page))
|
161
|
-
method = page.method
|
162
|
-
path = page.path
|
163
|
-
else
|
164
|
-
path = page
|
165
|
-
end
|
166
|
-
|
167
|
-
unless path.nil?
|
168
|
-
# path = path.gsub('http://www.example.com', '')
|
169
|
-
route = self.find {|r| r.responds_to?(path, method) }
|
170
|
-
puts "route: #{route.path}" if route
|
171
|
-
route
|
172
|
-
else
|
173
|
-
nil
|
174
|
-
end
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
class PluginContainer < ComponentContainer
|
179
|
-
def names
|
180
|
-
components.map {|plugin| plugin.name }
|
181
|
-
end
|
182
|
-
|
183
|
-
def export(options=nil)
|
184
|
-
names
|
185
|
-
end
|
186
|
-
end
|
187
74
|
end
|
188
75
|
|