stratagem 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
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