stratagem 0.1.7

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.
Files changed (101) hide show
  1. data/Manifest +99 -0
  2. data/Rakefile +17 -0
  3. data/bin/stratagem +10 -0
  4. data/init.rb +2 -0
  5. data/lib/bootstrap.rb +31 -0
  6. data/lib/stratagem/authentication.rb +64 -0
  7. data/lib/stratagem/auto_mock/aquifer.rb +86 -0
  8. data/lib/stratagem/auto_mock/factory.rb +213 -0
  9. data/lib/stratagem/auto_mock/value_generator.rb +174 -0
  10. data/lib/stratagem/auto_mock.rb +6 -0
  11. data/lib/stratagem/blocker.rb +16 -0
  12. data/lib/stratagem/client.rb +32 -0
  13. data/lib/stratagem/command.rb +13 -0
  14. data/lib/stratagem/commands/analyze.rb +22 -0
  15. data/lib/stratagem/commands/base.rb +11 -0
  16. data/lib/stratagem/commands/devel_crawl.rb +27 -0
  17. data/lib/stratagem/commands/devel_mock.rb +10 -0
  18. data/lib/stratagem/commands.rb +7 -0
  19. data/lib/stratagem/crawler/authentication.rb +109 -0
  20. data/lib/stratagem/crawler/form.rb +101 -0
  21. data/lib/stratagem/crawler/html_utils.rb +92 -0
  22. data/lib/stratagem/crawler/session.rb +296 -0
  23. data/lib/stratagem/crawler/site_model.rb +138 -0
  24. data/lib/stratagem/crawler/trace_utils.rb +10 -0
  25. data/lib/stratagem/crawler.rb +9 -0
  26. data/lib/stratagem/extensions/class.rb +9 -0
  27. data/lib/stratagem/extensions/hash.rb +16 -0
  28. data/lib/stratagem/extensions/module.rb +11 -0
  29. data/lib/stratagem/extensions/object.rb +15 -0
  30. data/lib/stratagem/extensions/red_parse.rb +86 -0
  31. data/lib/stratagem/extensions/string.rb +20 -0
  32. data/lib/stratagem/extensions.rb +6 -0
  33. data/lib/stratagem/framework_extensions/controllers/action_controller.rb +10 -0
  34. data/lib/stratagem/framework_extensions/controllers/action_mailer.rb +12 -0
  35. data/lib/stratagem/framework_extensions/controllers.rb +5 -0
  36. data/lib/stratagem/framework_extensions/models/adapters/active_model/detect.rb +7 -0
  37. data/lib/stratagem/framework_extensions/models/adapters/active_model/extensions.rb +35 -0
  38. data/lib/stratagem/framework_extensions/models/adapters/active_model/metadata.rb +103 -0
  39. data/lib/stratagem/framework_extensions/models/adapters/active_model/tracing.rb +50 -0
  40. data/lib/stratagem/framework_extensions/models/adapters/authlogic/detect.rb +11 -0
  41. data/lib/stratagem/framework_extensions/models/adapters/authlogic/extensions.rb +10 -0
  42. data/lib/stratagem/framework_extensions/models/adapters/authlogic/metadata.rb +30 -0
  43. data/lib/stratagem/framework_extensions/models/adapters/authlogic/tracing.rb +4 -0
  44. data/lib/stratagem/framework_extensions/models/adapters/common/authentication_metadata.rb +21 -0
  45. data/lib/stratagem/framework_extensions/models/adapters/restful_authentication/detect.rb +13 -0
  46. data/lib/stratagem/framework_extensions/models/adapters/restful_authentication/extensions.rb +19 -0
  47. data/lib/stratagem/framework_extensions/models/adapters/restful_authentication/metadata.rb +30 -0
  48. data/lib/stratagem/framework_extensions/models/adapters/restful_authentication/tracing.rb +4 -0
  49. data/lib/stratagem/framework_extensions/models/annotations.rb +79 -0
  50. data/lib/stratagem/framework_extensions/models/detect.rb +7 -0
  51. data/lib/stratagem/framework_extensions/models/metadata.rb +85 -0
  52. data/lib/stratagem/framework_extensions/models/mocking.rb +23 -0
  53. data/lib/stratagem/framework_extensions/models/tracing.rb +71 -0
  54. data/lib/stratagem/framework_extensions/models.rb +21 -0
  55. data/lib/stratagem/framework_extensions/rails.rb +8 -0
  56. data/lib/stratagem/framework_extensions.rb +6 -0
  57. data/lib/stratagem/interface/browser.rb +37 -0
  58. data/lib/stratagem/interface/public/images/backgrounds/content.png +0 -0
  59. data/lib/stratagem/interface/public/images/backgrounds/shadow.png +0 -0
  60. data/lib/stratagem/interface/public/javascripts/jquery-1.4.2.min.js +154 -0
  61. data/lib/stratagem/interface/public/javascripts/stratagem.js +27 -0
  62. data/lib/stratagem/interface/public/javascripts/stratagem_debug.js +53 -0
  63. data/lib/stratagem/interface/public/stylesheets/960.css +1 -0
  64. data/lib/stratagem/interface/public/stylesheets/reset.css +10 -0
  65. data/lib/stratagem/interface/public/stylesheets/stratagem.css +20 -0
  66. data/lib/stratagem/interface/public/stylesheets/stratagem_debug.css +20 -0
  67. data/lib/stratagem/interface/views/debug.haml +43 -0
  68. data/lib/stratagem/interface/views/index.haml +35 -0
  69. data/lib/stratagem/labs/auto_mock.rb +7 -0
  70. data/lib/stratagem/labs/crawler.rb +0 -0
  71. data/lib/stratagem/logger.rb +46 -0
  72. data/lib/stratagem/model/application.rb +157 -0
  73. data/lib/stratagem/model/components/base.rb +55 -0
  74. data/lib/stratagem/model/components/controller.rb +118 -0
  75. data/lib/stratagem/model/components/model.rb +170 -0
  76. data/lib/stratagem/model/components/reference.rb +30 -0
  77. data/lib/stratagem/model/components/route.rb +53 -0
  78. data/lib/stratagem/model/components/static_file.rb +18 -0
  79. data/lib/stratagem/model/components/view.rb +186 -0
  80. data/lib/stratagem/model/parse_util.rb +61 -0
  81. data/lib/stratagem/model.rb +12 -0
  82. data/lib/stratagem/model_builder.rb +146 -0
  83. data/lib/stratagem/recipes/deploy.rb +30 -0
  84. data/lib/stratagem/scan/checks/capistrano/secure_deploy.rb +43 -0
  85. data/lib/stratagem/scan/checks/email_address.rb +15 -0
  86. data/lib/stratagem/scan/checks/error_pages.rb +25 -0
  87. data/lib/stratagem/scan/checks/filter_parameter_logging.rb +6 -0
  88. data/lib/stratagem/scan/checks/mongo_mapper/base.rb +19 -0
  89. data/lib/stratagem/scan/checks/mongo_mapper/foreign_keys_exposed.rb +32 -0
  90. data/lib/stratagem/scan/checks/routes.rb +16 -0
  91. data/lib/stratagem/scan/checks/ssl/secure_login_page.rb +19 -0
  92. data/lib/stratagem/scan/checks/ssl/secure_login_submit.rb +18 -0
  93. data/lib/stratagem/scan/result.rb +45 -0
  94. data/lib/stratagem/scan.rb +19 -0
  95. data/lib/stratagem/scanner.rb +32 -0
  96. data/lib/stratagem/site_crawler.rb +47 -0
  97. data/lib/stratagem/snapshot.rb +33 -0
  98. data/lib/stratagem.rb +77 -0
  99. data/lib/tasks/_old_stratagem.rake +99 -0
  100. data/stratagem.gemspec +56 -0
  101. metadata +380 -0
@@ -0,0 +1,103 @@
1
+ module Stratagem::ApplicationExtensions::Models::Adapters::ActiveModel
2
+
3
+ # prefix method names with to avoid collision
4
+ class Metadata
5
+
6
+ attr_reader :model, :instance
7
+
8
+ def initialize(model)
9
+ @model = model
10
+ @instance = @model.new unless (@model == ActiveRecord::Base)
11
+ end
12
+
13
+ def relations(relation_type=nil) # :belongs_to, :has_many
14
+ @relations ||= {}
15
+ @relations[relation_type || :all] ||= model.reflect_on_all_associations(relation_type).map {|a|
16
+ Stratagem::ApplicationExtensions::Models::Metadata::StratagemAssociation.new(a.name.to_sym, a.association_foreign_key.to_sym, a.klass, a.macro)
17
+ }
18
+ end
19
+
20
+ def unaccessible_attributes
21
+ attrs = []
22
+ if (model.accessible_attributes)
23
+ attrs = model.stratagem.attribute_names - model.accessible_attributes.map {|a| a.to_sym }
24
+ end
25
+ attrs += model.protected_attributes.map {|a| a.to_sym } if model.protected_attributes
26
+ attrs
27
+ end
28
+
29
+ # parses a database error and returns the columns that had problems
30
+ # this is typically a not null enforced by the database but not
31
+ # by the model
32
+ def column_from_error(database_error)
33
+ if (database_error.kind_of?(Mysql::Error) || database_error.kind_of?(::ActiveRecord::StatementInvalid))
34
+ database_error.message =~ /Column '(.*)?' cannot/
35
+ $1 ? $1.to_sym : nil
36
+ else
37
+ puts database_error.class.name
38
+ nil
39
+ end
40
+ end
41
+
42
+
43
+ def valid?
44
+ model.valid?
45
+ end
46
+
47
+ def whitelists_attributes?
48
+ !model.accessible_attributes.nil?
49
+ end
50
+
51
+ def blacklists_attributes?
52
+ !model.protected_attributes.nil?
53
+ end
54
+
55
+ def attribute_names
56
+ instance.attribute_names.map {|a| a.to_sym} - ignore_attributes
57
+ end
58
+
59
+ # junk attributes
60
+ def ignore_attributes
61
+ ["!".to_sym, :[]]
62
+ end
63
+
64
+ # Attributes generally used by the persistence mechanism that should not be human writable
65
+ # accessible from the class
66
+ def internal_attributes
67
+ attrs = [:id, :created_at, :updated_at]
68
+ attrs += attribute_names.select {|a|
69
+ (a.to_s =~ /_count$/) ||
70
+ (a.to_s =~ /_salt$/) ||
71
+ (a.to_s =~ /_token$/) ||
72
+ (a.to_s == 'type')
73
+ }.map {|a| a.to_sym }
74
+ attrs
75
+ end
76
+
77
+ def attribute_type(name)
78
+ column = instance.column_for_attribute(name.to_s)
79
+ if (!column.nil?)
80
+ if (model.stratagem.foreign_keys.include?(name.to_sym))
81
+ :integer
82
+ else
83
+ column.type
84
+ end
85
+ else
86
+ if (name =~ /password/)
87
+ :string
88
+ else
89
+ types = [:string, :boolean, :integer]
90
+ types[rand(3)]
91
+ end
92
+ end
93
+ end
94
+
95
+ def invalid_columns(instance)
96
+ instance.valid?
97
+ errors = []
98
+ instance.errors.each {|error,i| errors << error.to_s.to_sym }
99
+ errors & attribute_names
100
+ end
101
+
102
+ end
103
+ end
@@ -0,0 +1,50 @@
1
+ module Stratagem::ApplicationExtensions::Models::Adapters::ActiveModel
2
+ module Tracing
3
+ def self.included(model)
4
+ model.class_eval do
5
+ # inject read tracing
6
+ @@removed_finder_methods = [:first, :last]+methods.select {|m| m =~ /^find/ }.map {|m| m.to_sym }.uniq
7
+ @@removed_methods = [:method_missing]+@@removed_finder_methods
8
+ class << self
9
+ @@removed_methods.each do |m|
10
+ alias_method "old_#{m}", m
11
+ undef_method m
12
+ end
13
+ end
14
+ model.removed_methods = @@removed_methods
15
+
16
+ # inject write tracing
17
+ [:create_or_update].each do |m|
18
+ alias_method "old_#{m}", m
19
+ undef_method m
20
+ end
21
+
22
+ # enhance method missing
23
+ class << self
24
+ def method_missing(method, *args, &block)
25
+ if (self.removed_methods.include?(method.to_sym))
26
+ # puts "read invocation: #{self.name} -> #{method} -> #{args.inspect}"
27
+ stratagem.read_invocation(method, args) if (@@removed_finder_methods.include?(method))
28
+ send("old_"+method.to_s, *args, &block)
29
+ elsif (self.removed_validators.include?(method.to_sym))
30
+ stratagem.validator_called(method, args)
31
+ puts "calling validator #{method.to_s} with #{args.inspect}"
32
+ send("old_"+method.to_s, *args, &block)
33
+ else
34
+ old_method_missing(method, *args, &block)
35
+ end
36
+ end
37
+ end
38
+
39
+ # add logging of save methods
40
+
41
+ def create_or_update(*args)
42
+ path,action,line = stratagem.controller_trace(/active_record\/base\.rb/)
43
+ stratagem.write_invocation(self, action.to_sym, args)
44
+ old_create_or_update(*args)
45
+ end
46
+ end
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,11 @@
1
+ module Stratagem::ApplicationExtensions::Models::Adapters::Authlogic
2
+ class Detect < Stratagem::ApplicationExtensions::Models::Detect
3
+ def self.supports?(model)
4
+ begin
5
+ model.ancestors.include?(::Authlogic::ActsAsAuthentic::MagicColumns::Methods)
6
+ rescue
7
+ false
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ if defined?(Authlogic)
2
+ module Authlogic::ActsAsAuthentic::MagicColumns::Methods
3
+ def self.included(model)
4
+ # automatically activate the account
5
+ model.class_eval do
6
+ before_save { |record| record.active = true if record.methods_include?(:active) }
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,30 @@
1
+ module Stratagem::ApplicationExtensions::Models::Adapters::Authlogic
2
+
3
+ # prefix method names with to avoid collision
4
+ class Metadata
5
+ include Stratagem::ApplicationExtensions::Models::Adapters::Common::AuthenticationMetadata
6
+
7
+ VIRTUAL_COLUMNS = [:password, :password_confirmation]
8
+
9
+ def authenticates?
10
+ true
11
+ end
12
+
13
+ def initialize(model)
14
+ @model = model
15
+ end
16
+
17
+ def attribute_names
18
+ VIRTUAL_COLUMNS
19
+ end
20
+
21
+ def internal_attributes
22
+ [:crypted_password, :password_salt]
23
+ end
24
+
25
+ def attribute_type(name)
26
+ :string
27
+ end
28
+ end
29
+
30
+ end
@@ -0,0 +1,4 @@
1
+ module Stratagem::ApplicationExtensions::Models::Adapters::Authlogic
2
+ module Tracing
3
+ end
4
+ end
@@ -0,0 +1,21 @@
1
+ module Stratagem::ApplicationExtensions::Models::Adapters::Common
2
+
3
+ # prefix method names with to avoid collision
4
+ module AuthenticationMetadata
5
+ def exclude_attributes_for_mocking
6
+ # open id
7
+ attrs = @model.stratagem.attribute_names.select {|a|
8
+ (a =~ /open_id/ || a =~ /openid/ || a =~ /identity_url/)
9
+ }
10
+ attrs << :identity_url
11
+ attrs << :openid_identifier
12
+
13
+ # aasm
14
+ if (@model.methods_include?(:aasm_column))
15
+ attrs << @model.aasm_column
16
+ end
17
+
18
+ attrs.uniq
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,13 @@
1
+
2
+
3
+ module Stratagem::ApplicationExtensions::Models::Adapters::RestfulAuthentication
4
+ class Detect < Stratagem::ApplicationExtensions::Models::Detect
5
+ def self.supports?(model)
6
+ begin
7
+ model.ancestors.include?(::Authentication::ByPassword)
8
+ rescue
9
+ false
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,19 @@
1
+ if (defined?(Authentication))
2
+ Authentication.subclasses.each do |model|
3
+ model.class_eval do
4
+ # add support for aasm models
5
+ before_save { |record|
6
+ begin
7
+ if (record.methods_include?(:active?) && !record.send(:active?))
8
+ Stratagem.logger.debug "Activating Restful Authentication model #{name}";
9
+ record.send("#{record.class.aasm_column}=", record.class.aasm_initial_state.values.first.to_s)
10
+ record.activate! unless record.active?
11
+ end
12
+ rescue
13
+ puts $!.message
14
+ puts $!.backtrace
15
+ end
16
+ }
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,30 @@
1
+ module Stratagem::ApplicationExtensions::Models::Adapters::RestfulAuthentication
2
+
3
+ # prefix method names with to avoid collision
4
+ class Metadata
5
+ include Stratagem::ApplicationExtensions::Models::Adapters::Common::AuthenticationMetadata
6
+
7
+ VIRTUAL_COLUMNS = [:password, :password_confirmation]
8
+
9
+ def authenticates?
10
+ true
11
+ end
12
+
13
+ def initialize(model)
14
+ @model = model
15
+ end
16
+
17
+ def attribute_names
18
+ VIRTUAL_COLUMNS
19
+ end
20
+
21
+ def internal_attributes
22
+ [:crypted_password]
23
+ end
24
+
25
+ def attribute_type(name)
26
+ :string
27
+ end
28
+ end
29
+
30
+ end
@@ -0,0 +1,4 @@
1
+ module Stratagem::ApplicationExtensions::Models::Adapters::RestfulAuthentication
2
+ module Tracing
3
+ end
4
+ end
@@ -0,0 +1,79 @@
1
+ # Defines the stratagem namespace attached to the model
2
+ module Stratagem::ApplicationExtensions::Models
3
+ MethodInvocation = Struct.new(:method, :controller_path, :controller_action, :line_number, :model_instance, :model_class, :stack_trace, :args)
4
+ ValidatorDefinition = Struct.new(:validation, :field, :args, :model_class)
5
+
6
+ class InstanceAnnotations
7
+ include Mocking
8
+
9
+ def initialize(object)
10
+ @object = object
11
+ end
12
+
13
+ def method_missing(method, *args, &block)
14
+ @object.class.stratagem.send(method, *args, &block)
15
+ end
16
+ end
17
+
18
+ class Annotations
19
+ include Metadata
20
+ include Tracing
21
+
22
+ attr_reader :model
23
+
24
+ AdapterDescriptor = Struct.new(:tracing, :metadata, :detector)
25
+
26
+ class << self
27
+ def configure(model)
28
+ puts "configuring #{model.name}"
29
+
30
+ # add the stratagem namespace
31
+ model.class_eval do
32
+ def self.stratagem
33
+ # one stratagem instance per subclass
34
+ @@stratagem ||= {}
35
+ @@stratagem[self] ||= Stratagem::ApplicationExtensions::Models::Annotations.new(self)
36
+ end
37
+
38
+
39
+ def stratagem
40
+ @stratagem ||= Stratagem::ApplicationExtensions::Models::InstanceAnnotations.new(self)
41
+ end
42
+ end
43
+
44
+ # connect the adapters
45
+ detect_adapters(model).each {|adapter|
46
+ if adapter.detector.supports?(model)
47
+ model.send(:include, adapter.tracing)
48
+ end
49
+ }
50
+ end
51
+
52
+ def detect_adapters(model)
53
+ Detect.subclasses.map do |detector|
54
+ namespace = detector.name.split('::')
55
+ namespace.pop
56
+ namespace = namespace.join('::')
57
+
58
+ tracing = module_eval(namespace+"::Tracing")
59
+ metadata = module_eval(namespace+"::Metadata").new(model)
60
+
61
+ AdapterDescriptor.new(tracing, metadata, detector)
62
+ end
63
+ end
64
+ end
65
+
66
+ def initialize(model)
67
+ puts "initializing stratagem for #{model.name}"
68
+ @model = model
69
+ end
70
+
71
+ def adapters
72
+ # supported adapters may change throughout the lifecycle of a class / object
73
+ @adapters ||= self.class.detect_adapters(model)
74
+ end
75
+
76
+
77
+ end
78
+
79
+ end
@@ -0,0 +1,7 @@
1
+ module Stratagem::ApplicationExtensions::Models
2
+ class Detect
3
+ def self.supports?(model)
4
+ false
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,85 @@
1
+
2
+ module Stratagem::ApplicationExtensions::Models
3
+ module Metadata
4
+ StratagemAssociation = Struct.new(:name, :foreign_key, :klass, :macro)
5
+
6
+ INSTANCE_ENUMERATION_METHODS = [:relations, :attribute_names, :ignore_attributes, :internal_attributes, :unaccessible_attributes, :invalid_columns, :exclude_attributes_for_mocking]
7
+ INSTANCE_ENTITY_METHODS = [:attribute_type, :column_from_error, :authenticates?, :whitelists_attributes?, :blacklists_attributes?]
8
+
9
+ def Metadata.included(mod)
10
+ mod.class_eval do
11
+ INSTANCE_ENUMERATION_METHODS.each do |name|
12
+ define_method(name) do |*args|
13
+ run_callbacks(name, *args)
14
+ end
15
+ end
16
+
17
+ INSTANCE_ENTITY_METHODS.each do |name|
18
+ define_method(name) do |*args|
19
+ val = run_callbacks(name, *args).first
20
+ val ||= false if (name.to_s.include?('?'))
21
+ val
22
+ end
23
+ end
24
+
25
+ end
26
+ end
27
+
28
+ # Convenience methods
29
+
30
+ def foreign_keys
31
+ relations(:belongs_to).map {|relation| relation.foreign_key }
32
+ end
33
+
34
+ def relation(name)
35
+ relations.find {|relation| relation.name == name }
36
+ end
37
+
38
+ def relation_names(relation_type=nil)
39
+ @relation_names ||= {}
40
+ @relation_names[relation_type || :all] ||= relations(relation_type).map {|relation| relation.name }
41
+ end
42
+
43
+
44
+ # Tracking of validates_xyz methods. Population of this data can be found in the tracing library
45
+
46
+ def validations(field=nil, validation=nil)
47
+ validators = self.validators
48
+
49
+ if (field || validation)
50
+ validators.select {|v|
51
+ conditions = []
52
+ conditions << (v.field == field) if field
53
+ conditions << (v.validation == validation) if validation
54
+ !conditions.include?(false)
55
+ }
56
+ else
57
+ validators
58
+ end
59
+ end
60
+
61
+ def callbacks
62
+ adapters.select {|a| a.detector.supports?(model) }.map {|a| a.metadata }
63
+ end
64
+
65
+ def validators
66
+ @validators ||= []
67
+ end
68
+
69
+ private
70
+
71
+ def run_callbacks(method, *args)
72
+ results = callbacks.inject([]) {|memory,callback|
73
+ begin
74
+ memory << callback.send(method, *args) if callback.methods_include?(method) || callback.methods_include?(method.to_s)
75
+ memory
76
+ rescue
77
+ puts $!.message
78
+ puts $!.backtrace
79
+ end
80
+ }
81
+ (results || []).flatten.compact
82
+ end
83
+
84
+ end
85
+ end
@@ -0,0 +1,23 @@
1
+ module Stratagem::ApplicationExtensions::Models
2
+ module Mocking
3
+ def mock_attributes
4
+ @attributes ||= {}
5
+ end
6
+
7
+ def write_mock_attribute(name, value)
8
+ mock_attributes[name] = value
9
+ end
10
+
11
+ def read_mock_attribute(name)
12
+ mock_attributes[name]
13
+ end
14
+
15
+ def used_in_mock_relation
16
+ @available_for_mock_relation = false
17
+ end
18
+
19
+ def used_in_mock_relation?
20
+ @available_for_mock_relation ||= true
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,71 @@
1
+ module Stratagem::ApplicationExtensions::Models
2
+ module Tracing
3
+
4
+ @@invocations_audit = []
5
+
6
+ def invocations_audit
7
+ @@invocations_audit
8
+ end
9
+
10
+ def read_invocations
11
+ @read_invocations ||= []
12
+ end
13
+
14
+ def write_invocations
15
+ @write_invocations ||= []
16
+ end
17
+
18
+ def validator_called(validation, args)
19
+ params = args.find {|a| a.kind_of?(Hash) } || {}
20
+ (args-[params]).each do |field|
21
+ self.validators << ValidatorDefinition.new(validation, field, params, model)
22
+ end
23
+ end
24
+
25
+ def clear_invocations
26
+ read_invocations.clear
27
+ write_invocations.clear
28
+ invocations_audit.clear
29
+ end
30
+
31
+ def write_invocation(model_instance, method, args)
32
+ invocation(method, args, write_invocations, model_instance)
33
+ end
34
+
35
+ def read_invocation(method, *args)
36
+ # ensure that the read did not stem from a write operation
37
+ path,action,line = controller_trace(/active_record\/base\.rb/)
38
+ invocation(method, args, read_invocations) unless (action =~ /create/) || (action =~ /update/) || (action =~ /save/)
39
+ end
40
+
41
+ def invocation(method, args, enumeration, model_instance=nil)
42
+ path,action,line = controller_trace
43
+ args = args.first if args && (args.size == 1) && (args.first.kind_of?(Array))
44
+ add_invocation enumeration, MethodInvocation.new(method, path, action, line, model_instance, model, caller, args) if (path)
45
+ end
46
+
47
+ def controller_trace(regex = /_controller\.rb/)
48
+ controller_trace = caller.select {|c| c =~ regex }.last
49
+ if controller_trace
50
+ path,line,action = controller_trace.split(':')
51
+ action.gsub!(/[`']/, '').gsub!('in ', '')
52
+ line = line.to_i
53
+ [path,action,line]
54
+ else
55
+ []
56
+ end
57
+ end
58
+
59
+ def add_invocation(enumeration, invocation)
60
+ # puts "adding invocation: #{invocation.inspect}"
61
+ invocations = (enumeration ||= [])
62
+ existing = invocations.find {|i|
63
+ i.controller_path == invocation.controller_path &&
64
+ i.controller_action == invocation.controller_action &&
65
+ i.line_number == invocation.line_number
66
+ }
67
+ invocations << invocation unless existing
68
+ invocations_audit << invocation
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,21 @@
1
+ module Stratagem::ApplicationExtensions::Models; end
2
+ module Stratagem::ApplicationExtensions::Models::Adapters; end
3
+
4
+ require 'stratagem/framework_extensions/models/mocking'
5
+ require 'stratagem/framework_extensions/models/metadata'
6
+ require 'stratagem/framework_extensions/models/tracing'
7
+ require 'stratagem/framework_extensions/models/annotations'
8
+ require 'stratagem/framework_extensions/models/detect'
9
+
10
+ base = File.join(File.dirname(__FILE__), 'models', 'adapters', 'common')
11
+ Dir.entries(base).select {|s| s =~ /\.rb$/}.each {|helper|
12
+ require File.join(base, helper.gsub(/\.rb/, ''))
13
+ }
14
+
15
+ base = File.join(File.dirname(__FILE__), 'models', 'adapters')
16
+ Dir.entries(base).select {|s| s !~ /^\./ && s != 'common' }.each {|adapter_dir|
17
+ require File.join(base, adapter_dir, 'detect')
18
+ require File.join(base, adapter_dir, 'tracing')
19
+ require File.join(base, adapter_dir, 'metadata')
20
+ require File.join(base, adapter_dir, 'extensions')
21
+ }
@@ -0,0 +1,8 @@
1
+ module Rails
2
+ def self.stratagem_rails_version
3
+ rails_version = Rails.version.split('.')
4
+ rails_version << 0 while rails_version.size < 3
5
+ rails_version.pop while rails_version.size > 3
6
+ rails_version.join.to_i
7
+ end
8
+ end
@@ -0,0 +1,6 @@
1
+ module Stratagem::ApplicationExtensions; end
2
+
3
+ require 'stratagem/framework_extensions/rails'
4
+ require 'stratagem/framework_extensions/controllers'
5
+ require 'stratagem/framework_extensions/models'
6
+
@@ -0,0 +1,37 @@
1
+ require 'rubygems'
2
+ require 'sinatra'
3
+ require 'erb'
4
+
5
+ set :run, false
6
+ enable :sessions
7
+ disable :logging
8
+ # log = File.new("log/sinatra.log", "a")
9
+ # STDOUT.reopen(log)
10
+ # STDERR.reopen(log)
11
+
12
+ get '/' do
13
+ session[:instance_id] = Stratagem.session_id
14
+ Stratagem.analyze
15
+ haml :index
16
+ end
17
+
18
+ get '/credentials' do
19
+ Stratagem::Authentication.instance.store_credentials(params[:account], params[:api_key], params[:project])
20
+ redirect '/'
21
+ end
22
+
23
+ get '/logs' do
24
+ if (session[:instance_id] == Stratagem.session_id)
25
+ logger = Stratagem.logger
26
+ logs = [logger.pop]
27
+ logs << logger.pop until logger.empty?
28
+ logs.to_json
29
+ else
30
+ ""
31
+ end
32
+ end
33
+
34
+
35
+ Thread.new do
36
+ Sinatra::Application.run!
37
+ end