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
data/Manifest
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
Manifest
|
2
|
+
Rakefile
|
3
|
+
bin/stratagem
|
4
|
+
init.rb
|
5
|
+
lib/bootstrap.rb
|
6
|
+
lib/stratagem.rb
|
7
|
+
lib/stratagem/authentication.rb
|
8
|
+
lib/stratagem/auto_mock.rb
|
9
|
+
lib/stratagem/auto_mock/aquifer.rb
|
10
|
+
lib/stratagem/auto_mock/factory.rb
|
11
|
+
lib/stratagem/auto_mock/value_generator.rb
|
12
|
+
lib/stratagem/blocker.rb
|
13
|
+
lib/stratagem/client.rb
|
14
|
+
lib/stratagem/command.rb
|
15
|
+
lib/stratagem/commands.rb
|
16
|
+
lib/stratagem/commands/analyze.rb
|
17
|
+
lib/stratagem/commands/base.rb
|
18
|
+
lib/stratagem/commands/devel_crawl.rb
|
19
|
+
lib/stratagem/commands/devel_mock.rb
|
20
|
+
lib/stratagem/crawler.rb
|
21
|
+
lib/stratagem/crawler/authentication.rb
|
22
|
+
lib/stratagem/crawler/form.rb
|
23
|
+
lib/stratagem/crawler/html_utils.rb
|
24
|
+
lib/stratagem/crawler/session.rb
|
25
|
+
lib/stratagem/crawler/site_model.rb
|
26
|
+
lib/stratagem/crawler/trace_utils.rb
|
27
|
+
lib/stratagem/extensions.rb
|
28
|
+
lib/stratagem/extensions/class.rb
|
29
|
+
lib/stratagem/extensions/hash.rb
|
30
|
+
lib/stratagem/extensions/module.rb
|
31
|
+
lib/stratagem/extensions/object.rb
|
32
|
+
lib/stratagem/extensions/red_parse.rb
|
33
|
+
lib/stratagem/extensions/string.rb
|
34
|
+
lib/stratagem/framework_extensions.rb
|
35
|
+
lib/stratagem/framework_extensions/controllers.rb
|
36
|
+
lib/stratagem/framework_extensions/controllers/action_controller.rb
|
37
|
+
lib/stratagem/framework_extensions/controllers/action_mailer.rb
|
38
|
+
lib/stratagem/framework_extensions/models.rb
|
39
|
+
lib/stratagem/framework_extensions/models/adapters/active_model/detect.rb
|
40
|
+
lib/stratagem/framework_extensions/models/adapters/active_model/extensions.rb
|
41
|
+
lib/stratagem/framework_extensions/models/adapters/active_model/metadata.rb
|
42
|
+
lib/stratagem/framework_extensions/models/adapters/active_model/tracing.rb
|
43
|
+
lib/stratagem/framework_extensions/models/adapters/authlogic/detect.rb
|
44
|
+
lib/stratagem/framework_extensions/models/adapters/authlogic/extensions.rb
|
45
|
+
lib/stratagem/framework_extensions/models/adapters/authlogic/metadata.rb
|
46
|
+
lib/stratagem/framework_extensions/models/adapters/authlogic/tracing.rb
|
47
|
+
lib/stratagem/framework_extensions/models/adapters/common/authentication_metadata.rb
|
48
|
+
lib/stratagem/framework_extensions/models/adapters/restful_authentication/detect.rb
|
49
|
+
lib/stratagem/framework_extensions/models/adapters/restful_authentication/extensions.rb
|
50
|
+
lib/stratagem/framework_extensions/models/adapters/restful_authentication/metadata.rb
|
51
|
+
lib/stratagem/framework_extensions/models/adapters/restful_authentication/tracing.rb
|
52
|
+
lib/stratagem/framework_extensions/models/annotations.rb
|
53
|
+
lib/stratagem/framework_extensions/models/detect.rb
|
54
|
+
lib/stratagem/framework_extensions/models/metadata.rb
|
55
|
+
lib/stratagem/framework_extensions/models/mocking.rb
|
56
|
+
lib/stratagem/framework_extensions/models/tracing.rb
|
57
|
+
lib/stratagem/framework_extensions/rails.rb
|
58
|
+
lib/stratagem/interface/browser.rb
|
59
|
+
lib/stratagem/interface/public/images/backgrounds/content.png
|
60
|
+
lib/stratagem/interface/public/images/backgrounds/shadow.png
|
61
|
+
lib/stratagem/interface/public/javascripts/jquery-1.4.2.min.js
|
62
|
+
lib/stratagem/interface/public/javascripts/stratagem.js
|
63
|
+
lib/stratagem/interface/public/javascripts/stratagem_debug.js
|
64
|
+
lib/stratagem/interface/public/stylesheets/960.css
|
65
|
+
lib/stratagem/interface/public/stylesheets/reset.css
|
66
|
+
lib/stratagem/interface/public/stylesheets/stratagem.css
|
67
|
+
lib/stratagem/interface/public/stylesheets/stratagem_debug.css
|
68
|
+
lib/stratagem/interface/views/debug.haml
|
69
|
+
lib/stratagem/interface/views/index.haml
|
70
|
+
lib/stratagem/labs/auto_mock.rb
|
71
|
+
lib/stratagem/labs/crawler.rb
|
72
|
+
lib/stratagem/logger.rb
|
73
|
+
lib/stratagem/model.rb
|
74
|
+
lib/stratagem/model/application.rb
|
75
|
+
lib/stratagem/model/components/base.rb
|
76
|
+
lib/stratagem/model/components/controller.rb
|
77
|
+
lib/stratagem/model/components/model.rb
|
78
|
+
lib/stratagem/model/components/reference.rb
|
79
|
+
lib/stratagem/model/components/route.rb
|
80
|
+
lib/stratagem/model/components/static_file.rb
|
81
|
+
lib/stratagem/model/components/view.rb
|
82
|
+
lib/stratagem/model/parse_util.rb
|
83
|
+
lib/stratagem/model_builder.rb
|
84
|
+
lib/stratagem/recipes/deploy.rb
|
85
|
+
lib/stratagem/scan.rb
|
86
|
+
lib/stratagem/scan/checks/capistrano/secure_deploy.rb
|
87
|
+
lib/stratagem/scan/checks/email_address.rb
|
88
|
+
lib/stratagem/scan/checks/error_pages.rb
|
89
|
+
lib/stratagem/scan/checks/filter_parameter_logging.rb
|
90
|
+
lib/stratagem/scan/checks/mongo_mapper/base.rb
|
91
|
+
lib/stratagem/scan/checks/mongo_mapper/foreign_keys_exposed.rb
|
92
|
+
lib/stratagem/scan/checks/routes.rb
|
93
|
+
lib/stratagem/scan/checks/ssl/secure_login_page.rb
|
94
|
+
lib/stratagem/scan/checks/ssl/secure_login_submit.rb
|
95
|
+
lib/stratagem/scan/result.rb
|
96
|
+
lib/stratagem/scanner.rb
|
97
|
+
lib/stratagem/site_crawler.rb
|
98
|
+
lib/stratagem/snapshot.rb
|
99
|
+
lib/tasks/_old_stratagem.rake
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'echoe'
|
4
|
+
|
5
|
+
Echoe.new('stratagem', '0.1.7') do |p|
|
6
|
+
p.description = "Intuitive security analysis of your Rails applications"
|
7
|
+
p.url = "http://github.com/stratagem/stratagem"
|
8
|
+
p.author = "Charles Grimes"
|
9
|
+
p.email = "cj@stratagemapp.com"
|
10
|
+
p.executable_pattern = ['bin/*']
|
11
|
+
p.ignore_pattern = ["tmp/*", "script/*", "spec/*", "webapp/*"]
|
12
|
+
p.runtime_dependencies = ["launchy >=0.3.5", "redparse >=0.8.4", "haml >=3.0.0"]
|
13
|
+
p.development_dependencies = ["launchy >=0.3.5", "redparse >=0.8.4", "sinatra =1.0", "haml >=3.0.0", "webrat >=0.4.3"]
|
14
|
+
# p.requirements ["Install the stratagem-ui gem for the web browser interface."]
|
15
|
+
end
|
16
|
+
|
17
|
+
Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
|
data/bin/stratagem
ADDED
data/init.rb
ADDED
data/lib/bootstrap.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
|
2
|
+
# inject environment helpers into Rails class to be used during bootstrapping
|
3
|
+
Rails.class_eval do
|
4
|
+
def self.stratagem_production_env
|
5
|
+
@stratagem_initial_env ||= @_env
|
6
|
+
@_env = ActiveSupport::StringInquirer.new('production')
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.stratagem_restore_env
|
10
|
+
@_env = @stratagem_initial_env
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
# Inject env change into Rails initializer prior to loading controllers
|
16
|
+
# but after framework is initialized. This is to force SSL to work as
|
17
|
+
# if the app were running in production mode
|
18
|
+
Rails::Initializer.class_eval do
|
19
|
+
alias_method :rails_load_application_classes, :load_application_classes
|
20
|
+
|
21
|
+
def load_application_classes
|
22
|
+
puts "LOADING APPLICATION CLASSES"
|
23
|
+
# load stratagem
|
24
|
+
require 'stratagem'
|
25
|
+
|
26
|
+
Rails.stratagem_production_env
|
27
|
+
rails_load_application_classes
|
28
|
+
Rails.stratagem_restore_env
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
require 'singleton'
|
3
|
+
|
4
|
+
module Stratagem
|
5
|
+
class Authentication
|
6
|
+
include Singleton
|
7
|
+
|
8
|
+
FILENAME = '.stratagem'
|
9
|
+
|
10
|
+
attr_reader :token, :project
|
11
|
+
|
12
|
+
def store_credentials(account, token, project)
|
13
|
+
File.open(FILENAME, 'w') do |f|
|
14
|
+
f.puts account
|
15
|
+
f.puts token
|
16
|
+
f.puts project
|
17
|
+
end
|
18
|
+
reload_credentials
|
19
|
+
end
|
20
|
+
|
21
|
+
def url
|
22
|
+
if (credentials.nil?)
|
23
|
+
base_url+"/project_links/new"
|
24
|
+
else
|
25
|
+
base_url+"/project_links/validate/#{credentials[:token]}/#{credentials[:project]}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def base_url
|
30
|
+
subdomain = credentials ? credentials[:account] : 'www'
|
31
|
+
"http://#{subdomain}.#{Stratagem.domain}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def project_url
|
35
|
+
"#{base_url}/projects/#{credentials[:project]}?api_key=#{credentials[:token]}"
|
36
|
+
end
|
37
|
+
|
38
|
+
def credentials
|
39
|
+
@credentials ||= load_credentials
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
def reload_credentials
|
44
|
+
@credentials = nil
|
45
|
+
credentials
|
46
|
+
end
|
47
|
+
|
48
|
+
def load_credentials
|
49
|
+
if File.exists?(FILENAME)
|
50
|
+
credentials = nil
|
51
|
+
File.open(FILENAME) do |f|
|
52
|
+
credentials = {
|
53
|
+
:account => f.readline.strip,
|
54
|
+
:token => f.readline.strip,
|
55
|
+
:project => f.readline.strip
|
56
|
+
}
|
57
|
+
end
|
58
|
+
return credentials
|
59
|
+
else
|
60
|
+
return nil
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'timeout'
|
2
|
+
|
3
|
+
module Stratagem::AutoMock
|
4
|
+
class Aquifer
|
5
|
+
include Singleton
|
6
|
+
include Factory
|
7
|
+
|
8
|
+
attr_accessor :application
|
9
|
+
|
10
|
+
def self.init(application)
|
11
|
+
at_exit { self.instance.destroy }
|
12
|
+
self.instance.application = application
|
13
|
+
self.instance
|
14
|
+
end
|
15
|
+
|
16
|
+
def destroy
|
17
|
+
objects = self.repo.values.inject([]) {|memo,obj| memo += obj.compact }
|
18
|
+
i = 0
|
19
|
+
while (objects.size > 0 && ((i+=1) < objects.size))
|
20
|
+
objects = objects.select do |instance|
|
21
|
+
puts "deleting #{instance.class.name}"
|
22
|
+
begin
|
23
|
+
instance.destroy
|
24
|
+
rescue
|
25
|
+
begin
|
26
|
+
instance.delete
|
27
|
+
rescue
|
28
|
+
puts "Unable to delete object: #{instance.class.name} - #{$!.message}"
|
29
|
+
puts $!.backtrace
|
30
|
+
end
|
31
|
+
end
|
32
|
+
!instance.frozen?
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def instances_of(model_klass)
|
38
|
+
repo[model_klass].clone
|
39
|
+
end
|
40
|
+
|
41
|
+
def random_instance(model_klass)
|
42
|
+
objects = repo[model_klass]
|
43
|
+
puts "found #{objects.size} instances in well"
|
44
|
+
instance = objects[rand objects.size]
|
45
|
+
instance
|
46
|
+
end
|
47
|
+
|
48
|
+
def fill
|
49
|
+
Stratagem.logger.phase "mocking_models"
|
50
|
+
application.models.each do |meta_model|
|
51
|
+
models = mock_model(meta_model.klass) if (meta_model.stratagem?)
|
52
|
+
end
|
53
|
+
puts "aquifer full"
|
54
|
+
application.models.each do |meta_model|
|
55
|
+
puts "#{meta_model.klass.name}"
|
56
|
+
(repo[meta_model.klass] || []).each do |instance|
|
57
|
+
puts "\t#{instance.id}"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def mock_model(klass, count=2)
|
63
|
+
count.times do |i|
|
64
|
+
instance,valid = mock(klass)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
protected
|
69
|
+
|
70
|
+
def instance_call(instance, method, *args)
|
71
|
+
begin
|
72
|
+
timeout(3) do
|
73
|
+
instance.send(method, *args)
|
74
|
+
end
|
75
|
+
rescue Timeout::Error
|
76
|
+
e = StratagemError.new("unable to call method #{method} on model #{instance.class.name}, timed out") # log it
|
77
|
+
puts e.message
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
def repo
|
83
|
+
mocked
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,213 @@
|
|
1
|
+
module Stratagem::AutoMock
|
2
|
+
@@bank = {} # key is model class, value is an array of mocked instances
|
3
|
+
|
4
|
+
# todo - move these to a generic automock file
|
5
|
+
class MockError < StratagemError; end
|
6
|
+
class UnsupportedModelError < MockError; end
|
7
|
+
class UnsupportedColumnTypeError < MockError; end
|
8
|
+
class ColumnValidationError < MockError; end
|
9
|
+
class ParentsExhaustedError < MockError; end
|
10
|
+
|
11
|
+
module Factory
|
12
|
+
include ValueGenerator
|
13
|
+
|
14
|
+
def mock(model,mock_chain=[], belongs_to=nil)
|
15
|
+
return if mock_chain.select {|m| m == model }.size > 1
|
16
|
+
mock_chain << model
|
17
|
+
|
18
|
+
object,valid = model.new, nil
|
19
|
+
begin
|
20
|
+
10.times do |i|
|
21
|
+
log "mocking model #{model.name}"
|
22
|
+
populate_attributes(object, mock_chain)
|
23
|
+
correct_invalid_columns(object, mock_chain)
|
24
|
+
|
25
|
+
valid = populate_relations(object, mock_chain, belongs_to)
|
26
|
+
|
27
|
+
# allow relationship attributes to be invalid
|
28
|
+
valid = save_object(object) if (valid)
|
29
|
+
|
30
|
+
if valid
|
31
|
+
add_mocked(object)
|
32
|
+
break
|
33
|
+
end
|
34
|
+
end
|
35
|
+
rescue
|
36
|
+
puts $!.class.name
|
37
|
+
puts $!.message
|
38
|
+
puts $!.backtrace
|
39
|
+
e = MockError.new("Unexpected error mocking model #{model.name}")
|
40
|
+
e.target = $!
|
41
|
+
# raise e
|
42
|
+
end
|
43
|
+
|
44
|
+
return [object,valid] if valid
|
45
|
+
end
|
46
|
+
|
47
|
+
protected
|
48
|
+
|
49
|
+
def add_mocked(instance)
|
50
|
+
(mocked[instance.class] ||= []) << instance
|
51
|
+
end
|
52
|
+
|
53
|
+
def mocked(model=nil)
|
54
|
+
@mocked ||= {}
|
55
|
+
if (model)
|
56
|
+
@mocked[model] ||= []
|
57
|
+
else
|
58
|
+
@mocked
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def populate_attributes(object, mock_chain)
|
63
|
+
exclude = [:created_at, :updated_at] + object.stratagem.relation_names + object.stratagem.foreign_keys + object.stratagem.internal_attributes
|
64
|
+
|
65
|
+
# exclude the confirmation attributes, as they will be set automatically
|
66
|
+
exclude += object.stratagem.validations(nil, :validates_confirmation_of).map {|v| (v.field.to_s+"_confirmation").to_sym }
|
67
|
+
exclude += object.stratagem.exclude_attributes_for_mocking
|
68
|
+
exclude += object.stratagem.internal_attributes
|
69
|
+
|
70
|
+
exclude_regex = [/^photo/, /picture/]
|
71
|
+
names = object.stratagem.attribute_names.select {|n| n !~ /_id$/ } - exclude
|
72
|
+
puts "mocking names: #{names.inspect}"
|
73
|
+
puts "excluded: #{exclude.inspect}"
|
74
|
+
puts "internal: #{object.stratagem.internal_attributes.inspect}"
|
75
|
+
names.each do |attr_name|
|
76
|
+
next if exclude_regex.find {|r| attr_name =~ r }
|
77
|
+
set_attribute_value(object, attr_name, mock_chain)
|
78
|
+
end
|
79
|
+
|
80
|
+
# check for fields that should be forced into specific values
|
81
|
+
object.stratagem.validations.select {|v| [:validates_acceptance_of, :validates_presence_of].include?(v.validation) }.each do |validator|
|
82
|
+
value = validator.args[:with] || validator.args[:accept]
|
83
|
+
set_attribute_value(object, validator.field, mock_chain, value) if (value && value.kind_of?(String))
|
84
|
+
end
|
85
|
+
|
86
|
+
(object.stratagem.invalid_columns(object)).size == 0
|
87
|
+
end
|
88
|
+
|
89
|
+
def populate_relations(object, mock_chain, belongs_to=nil)
|
90
|
+
# belongs_to relations
|
91
|
+
object.stratagem.relation_names(:belongs_to).each do |attr_name|
|
92
|
+
relation = object.stratagem.relation(attr_name)
|
93
|
+
if (belongs_to && belongs_to.class == relation.klass)
|
94
|
+
object.send(attr_name.to_s+"=", belongs_to)
|
95
|
+
else
|
96
|
+
instances = mocked(relation.klass)
|
97
|
+
if (instances.size > 1)
|
98
|
+
object.send(attr_name.to_s+"=", instances[rand instances.size])
|
99
|
+
else
|
100
|
+
set_attribute_value(object, attr_name, mock_chain)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# has_many relations
|
106
|
+
# object.stratagem.relation_names(:has_many).each do |attr_name|
|
107
|
+
# relation = object.stratagem.relation(attr_name)
|
108
|
+
# # select the instances that don't have an existing belongs_to for this relation type
|
109
|
+
# instances = mocked(relation.klass).select {|i|
|
110
|
+
# br = i.stratagem.relations.find {|r| r.klass == i.class }
|
111
|
+
# if (br && !i.send(br.name).nil?)
|
112
|
+
# false
|
113
|
+
# else
|
114
|
+
# true
|
115
|
+
# end
|
116
|
+
# }
|
117
|
+
# if (instances.size > 2)
|
118
|
+
# collection = object.send(attr_name.to_s)
|
119
|
+
# collection << instances[rand instances.size]
|
120
|
+
# else
|
121
|
+
# mock(relation.klass, mock_chain, object)
|
122
|
+
# end
|
123
|
+
# end
|
124
|
+
|
125
|
+
(object.stratagem.invalid_columns(object)).size == 0
|
126
|
+
end
|
127
|
+
|
128
|
+
def correct_invalid_columns(object, mock_chain)
|
129
|
+
exclude = [:created_at, :updated_at] + object.stratagem.relation_names + object.stratagem.foreign_keys
|
130
|
+
|
131
|
+
# randomize over incorrect values and try to correct
|
132
|
+
(object.stratagem.invalid_columns(object) - exclude).each do |error_column|
|
133
|
+
puts "\t\terrors for #{error_column}: #{object.errors[error_column].inspect}"
|
134
|
+
|
135
|
+
i = 0
|
136
|
+
begin
|
137
|
+
value = set_attribute_value(object, error_column, mock_chain)
|
138
|
+
print_value = value || 'nil'
|
139
|
+
#log "\tattempting value #{print_value} for column #{error_column} to correct error - invalid columns: #{object.stratagem.invalid_columns(object)}"
|
140
|
+
i += 1
|
141
|
+
end while object.stratagem.invalid_columns(object).include?(error_column) && (i < 200)
|
142
|
+
|
143
|
+
if object.stratagem.invalid_columns(object).include?(error_column)
|
144
|
+
raise Stratagem::AutoMock::ColumnValidationError.new("Column #{error_column} cannot be resolved")
|
145
|
+
end
|
146
|
+
end
|
147
|
+
object
|
148
|
+
end
|
149
|
+
|
150
|
+
def save_object(object)
|
151
|
+
valid = true
|
152
|
+
retries = 0
|
153
|
+
begin
|
154
|
+
object.save!
|
155
|
+
rescue Stratagem::AutoMock::MockError
|
156
|
+
puts "Error mocking #{klass.name}"
|
157
|
+
valid = false
|
158
|
+
rescue
|
159
|
+
puts object.stratagem.mock_attributes.inspect
|
160
|
+
puts "Error mocking #{object.class.name} - #{$!.message}"
|
161
|
+
error_column = object.stratagem.column_from_error($!)
|
162
|
+
puts "\terror column: #{error_column}"
|
163
|
+
if error_column && !object.stratagem.foreign_keys.include?(error_column)
|
164
|
+
if retries < 100
|
165
|
+
puts "\tretrying to correct field #{error_column} that was missing validation"
|
166
|
+
set_attribute_value(object, error_column, [])
|
167
|
+
retries += 1
|
168
|
+
retry
|
169
|
+
else
|
170
|
+
valid = false
|
171
|
+
end
|
172
|
+
else
|
173
|
+
valid = false
|
174
|
+
end
|
175
|
+
puts $!.backtrace unless valid
|
176
|
+
end
|
177
|
+
valid
|
178
|
+
end
|
179
|
+
|
180
|
+
def set_attribute_value(object, attr_name, mock_chain=[], value=nil)
|
181
|
+
return if attr_name.to_s =~ /_confirmation$/ # ignore confirmation fields
|
182
|
+
|
183
|
+
unless value
|
184
|
+
if (object.stratagem.relation_names.include?(attr_name))
|
185
|
+
puts "\tmocking relation #{attr_name} for #{object.class.name}"
|
186
|
+
relation = object.stratagem.relation(attr_name)
|
187
|
+
value,valid = mock(relation.klass, mock_chain+[object.class])
|
188
|
+
value = nil unless valid
|
189
|
+
else
|
190
|
+
value = generate_value(attr_name, object.stratagem.attribute_type(attr_name))
|
191
|
+
#puts "#{attr_name} -> #{value}"
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
object.send("#{attr_name}=", value)
|
196
|
+
object.stratagem.write_mock_attribute(attr_name, value)
|
197
|
+
|
198
|
+
confirmation_writer = "#{attr_name}_confirmation="
|
199
|
+
if object.methods_include?(confirmation_writer) || (object.stratagem.validations(attr_name, :validates_confirmation_of).size > 0)
|
200
|
+
puts "setting confirmation field for #{attr_name}"
|
201
|
+
object.send(confirmation_writer, value)
|
202
|
+
object.stratagem.write_mock_attribute("#{attr_name}_confirmation".to_sym, value)
|
203
|
+
end
|
204
|
+
|
205
|
+
|
206
|
+
value
|
207
|
+
end
|
208
|
+
|
209
|
+
def log(msg)
|
210
|
+
Stratagem.logger.debug msg
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|