bot-away 1.2.0 → 2.0.0

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 (51) hide show
  1. data/.travis.yml +14 -0
  2. data/History.txt +20 -0
  3. data/README.md +198 -0
  4. data/Rakefile +14 -94
  5. data/bot-away.gemspec +20 -87
  6. data/gemfiles/Gemfile.rails-3.0.x +8 -0
  7. data/gemfiles/Gemfile.rails-3.0.x.lock +121 -0
  8. data/gemfiles/Gemfile.rails-3.1.x +8 -0
  9. data/gemfiles/Gemfile.rails-3.1.x.lock +133 -0
  10. data/lib/bot-away.rb +15 -13
  11. data/lib/bot-away/action_dispatch/params_parser.rb +22 -0
  12. data/lib/bot-away/action_view/helpers/instance_tag.rb +36 -12
  13. data/lib/bot-away/param_parser.rb +2 -2
  14. data/lib/bot-away/railtie.rb +10 -0
  15. data/lib/bot-away/test_case.rb +58 -0
  16. data/lib/bot-away/test_case/controller_test_case.rb +11 -0
  17. data/lib/bot-away/test_case/instance_tag_test_case.rb +15 -0
  18. data/lib/bot-away/test_case/matchers.rb +20 -0
  19. data/lib/bot-away/test_case/matchers/honeypot_matcher.rb +30 -0
  20. data/lib/bot-away/test_case/matchers/obfuscation_matcher.rb +30 -0
  21. data/lib/bot-away/test_case/mock_object.rb +16 -0
  22. data/lib/bot-away/version.rb +12 -0
  23. data/lib/locale/honeypots.yml +6 -0
  24. data/spec/controllers/basic_form_view_spec.rb +112 -0
  25. data/spec/controllers/{test_controller_spec.rb → tests_controller_spec.rb} +29 -80
  26. data/spec/integration/params_post_spec.rb +42 -0
  27. data/spec/lib/action_view/helpers/instance_tag_spec.rb +94 -0
  28. data/spec/{views/lib → lib/action_view}/param_parser_spec.rb +10 -10
  29. data/spec/spec_helper.rb +37 -105
  30. data/spec/test_rails_app/app/controllers/tests_controller.rb +11 -0
  31. data/spec/test_rails_app/app/models/post.rb +13 -0
  32. data/spec/test_rails_app/app/views/tests/basic_form.html.erb +5 -0
  33. data/spec/test_rails_app/app/views/tests/model_form.html.erb +12 -0
  34. data/spec/test_rails_app/config/locales/bot-away-overrides.yml +6 -0
  35. data/spec/views/form_builder_spec.rb +118 -0
  36. metadata +94 -137
  37. data/Manifest.txt +0 -23
  38. data/README.rdoc +0 -179
  39. data/VERSION +0 -1
  40. data/lib/bot-away/action_dispatch/request.rb +0 -20
  41. data/spec/rspec_version.rb +0 -19
  42. data/spec/support/honeypot_matcher.rb +0 -30
  43. data/spec/support/obfuscation_helper.rb +0 -123
  44. data/spec/support/obfuscation_matcher.rb +0 -28
  45. data/spec/support/rails/mock_logger.rb +0 -21
  46. data/spec/support/test_controller.rb +0 -28
  47. data/spec/support/views/test/index.html.erb +0 -4
  48. data/spec/support/views/test/model_form.html.erb +0 -6
  49. data/spec/views/lib/action_view/helpers/instance_tag_spec.rb +0 -75
  50. data/spec/views/lib/disabled_for_spec.rb +0 -101
  51. data/spec/views/lib/form_builder_spec.rb +0 -56
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 1.2.0
@@ -1,20 +0,0 @@
1
- request = (defined?(Rails::VERSION) && Rails::VERSION::STRING >= "3.0") ?
2
- ActionDispatch::Request : # Rails 3.0
3
- ActionController::Request # Rails 2.3
4
-
5
- request.module_eval do
6
- def parameters_with_deobfuscation
7
- # NFC what is happening behind the scenes but Rails 2.3 croaks when we memoize; Rails 3 croaks when we don't.
8
- if defined?(Rails::VERSION) && Rails::VERSION::STRING >= "3.0"
9
- @deobfuscated_parameters ||= begin
10
- BotAway::ParamParser.new(ip, parameters_without_deobfuscation.dup).params
11
- end
12
- else
13
- Rails.logger.info parameters_without_deobfuscation.inspect
14
- BotAway::ParamParser.new(ip, parameters_without_deobfuscation.dup).params
15
- end
16
- end
17
-
18
- alias_method_chain :parameters, :deobfuscation
19
- alias_method :params, :parameters
20
- end
@@ -1,19 +0,0 @@
1
- unless defined?(RSPEC_VERSION)
2
- begin
3
- # RSpec 1.3.0
4
- require 'spec/rake/spectask'
5
- require 'spec/version'
6
-
7
- RSPEC_VERSION = Spec::VERSION::STRING
8
- rescue LoadError
9
- # RSpec 2.0
10
- begin
11
- require 'rspec/core/rake_task'
12
- require 'rspec/core/version'
13
-
14
- RSPEC_VERSION = RSpec::Core::Version::STRING
15
- rescue LoadError
16
- raise "RSpec does not seem to be installed. You must install rspec to test this gem."
17
- end
18
- end
19
- end
@@ -1,30 +0,0 @@
1
- class HoneypotMatcher
2
- def initialize(object_name, method_name)
3
- @object_name, @method_name = object_name, method_name
4
- end
5
-
6
- def matches?(target)
7
- target = target.call if target.kind_of?(Proc)
8
- @target = target
9
- if @method_name.nil?
10
- @rx = /name="#{Regexp::escape @object_name}/m
11
- else
12
- @rx = /name="#{Regexp::escape @object_name}\[#{Regexp::escape @method_name}/m
13
- end
14
- @target[@rx]
15
- end
16
-
17
- def failure_message
18
- "expected #{@target.inspect}\n to match #{@rx.to_s}"
19
- end
20
-
21
- def negative_failure_message
22
- "expected #{@target.inspect}\n to not match #{@rx.to_s}"
23
- end
24
- end
25
-
26
- def include_honeypot(object_name, method_name)
27
- HoneypotMatcher.new(object_name, method_name)
28
- end
29
-
30
- alias contain_honeypot include_honeypot
@@ -1,123 +0,0 @@
1
- module ObfuscationHelper
2
- def controller_class
3
- TestController
4
- end
5
-
6
- def dump
7
- result = yield
8
- puts result if ENV['DUMP']
9
- result
10
- end
11
-
12
- if RAILS_VERSION >= "3.0"
13
- def self.included(base)
14
- base.before(:each) do
15
- session[:_csrf_token] = '1234'
16
- controller.stub!(:protect_from_forgery?).and_return(true)
17
- if respond_to?(:view)
18
- controller.request.path_parameters["action"] ||= "index"
19
- controller.action_name ||= "index"
20
- view.stub!(:request_forgery_protection_token).and_return(:authenticity_token)
21
- view.stub!(:form_authenticity_token).and_return('1234')
22
- else
23
- # response.stub!(:request_forgery_protection_token).and_return(:authenticity_token)
24
- # response.stub!(:form_authenticity_token).and_return('1234')
25
- end
26
- end
27
- end
28
- end
29
-
30
- def builder
31
- return @builder if @builder
32
- if RAILS_VERSION < "3.0"
33
- response = TestController.call(Rack::MockRequest.env_for('/').merge({'REQUEST_URI' => '/',
34
- 'REMOTE_ADDR' => '127.0.0.1'}))
35
- response.template.controller.request_forgery_protection_token = :authenticity_token
36
- response.template.controller.session[:_csrf_token] = '1234'
37
- @builder = ActionView::Helpers::FormBuilder.new(:object_name, MockObject.new, response.template, {}, proc {})
38
- else
39
- @builder = ActionView::Base.default_form_builder.new(:object_name, MockObject.new, view, {}, proc {})
40
- end
41
- end
42
-
43
- # this is the obfuscated version of the string "object_name_method_name"
44
- def obfuscated_id
45
- self.class.obfuscated_id
46
- end
47
-
48
- # this is the obfuscated version of the string "object_name[method_name]"
49
- def obfuscated_name
50
- self.class.obfuscated_name
51
- end
52
-
53
- def object_name
54
- self.class.object_name
55
- end
56
-
57
- def method_name
58
- self.class.method_name
59
- end
60
-
61
- module ClassMethods
62
- def includes_honeypot(object_name, method_name)
63
- it "includes a honeypot called #{object_name}[#{method_name}]" do
64
- subject.should include_honeypot(object_name, method_name)
65
- end
66
- end
67
-
68
- def is_obfuscated_as(id, name)
69
- it "is obfuscated as #{id}, #{name}" do
70
- subject.should be_obfuscated_as(id, name)
71
- end
72
- end
73
-
74
- def obfuscates(method, options = {}, unused = nil, &block)
75
- if !options.kind_of?(Hash)
76
- options = { :obfuscated_id => options, :obfuscated_name => unused }
77
- end
78
-
79
- obfuscated_id = options[:obfuscated_id] || self.obfuscated_id
80
- obfuscated_name = options[:obfuscatd_name] || self.obfuscated_name
81
-
82
- context "##{method}" do
83
- before(:each) { @obfuscates_value = instance_eval(&block) }
84
- subject { proc { dump { @obfuscates_value } } }
85
-
86
- if options[:name]
87
- includes_honeypot(options[:name], nil)
88
- else
89
- includes_honeypot(options[:object_name] || object_name, options[:method_name] || method_name)
90
- end
91
- is_obfuscated_as(obfuscated_id, obfuscated_name)
92
- end
93
- end
94
-
95
- def obfuscated_id
96
- RAILS_VERSION >= "3.0" ? "f51a02a636f507f1bd64722451b71297" : "e21372563297c728093bf74c3cb6b96c"
97
- end
98
-
99
- def obfuscated_name
100
- RAILS_VERSION >= "3.0" ? "cd538a9170613d6dedbcc54a0aa24881" : "a0844d45bf150668ff1d86a6eb491969"
101
- end
102
-
103
- def object_name
104
- "object_name"
105
- end
106
-
107
- def method_name
108
- "method_name"
109
- end
110
- end
111
- end
112
-
113
- if RSPEC_VERSION < "2.0"
114
- Spec::Runner.configure do |config|
115
- config.extend ObfuscationHelper::ClassMethods
116
- config.include ObfuscationHelper
117
- end
118
- else
119
- RSpec.configure do |config|
120
- config.extend ObfuscationHelper::ClassMethods
121
- config.include ObfuscationHelper
122
- end
123
- end
@@ -1,28 +0,0 @@
1
- class ObfuscationMatcher
2
- def initialize(id, name)
3
- @id, @name = id, name
4
- end
5
-
6
- def matches?(target)
7
- target = target.call if target.kind_of?(Proc)
8
- @target = target
9
- match(:id) && match(:name)
10
- end
11
-
12
- def match(which)
13
- @rx = /#{which}=['"]#{Regexp::escape instance_variable_get("@#{which}")}/
14
- @target[@rx]
15
- end
16
-
17
- def failure_message
18
- "expected #{@target.inspect}\n to match #{@rx.inspect}"
19
- end
20
-
21
- def negative_failure_message
22
- "expected #{@target.inspect}\n to not match #{@rx.inspect}"
23
- end
24
- end
25
-
26
- def be_obfuscated_as(id, name)
27
- ObfuscationMatcher.new(id, name)
28
- end
@@ -1,21 +0,0 @@
1
- require 'spec/mocks'
2
-
3
- module Rails
4
- class << self
5
- def logger
6
- return @logger if @logger
7
- @logger = Object.new
8
- klass = class << @logger; self; end
9
- if RSPEC_VERSION < "2.0"
10
- klass.send(:include, Spec::Mocks::Methods)
11
- else
12
- end
13
-
14
- def @logger.debug(message); end
15
- def @logger.info(message); end
16
- def @logger.error(message); end
17
- def @logger.warn(message); end
18
- @logger
19
- end
20
- end
21
- end
@@ -1,28 +0,0 @@
1
- class Post
2
- attr_reader :subject, :body, :subscribers
3
-
4
- if defined?(ActiveModel)
5
- extend ActiveModel::Naming
6
-
7
- def to_key
8
- [1]
9
- end
10
- end
11
- end
12
-
13
- class ApplicationController < ActionController::Base
14
-
15
- end
16
-
17
- class TestController < ApplicationController
18
- def index
19
- end
20
-
21
- def model_form
22
- @post = Post.new
23
- end
24
-
25
- def proc_form
26
- render :text => params.to_yaml
27
- end
28
- end
@@ -1,4 +0,0 @@
1
- <%form_for :test, :url => {:action => 'post_to'} do |f|%>
2
- <%=f.text_field :name%>
3
- <%end%>
4
-
@@ -1,6 +0,0 @@
1
- <%form_for @post, :url => url_for('proc_form') do |f|%>
2
- <p>
3
- <%=f.label :subject%><br/>
4
- <%=f.text_field :subject%>
5
- </p>
6
- <%end%>
@@ -1,75 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe ActionView::Helpers::InstanceTag do
4
- if method_defined?(:controller)
5
- def template
6
- view
7
- end
8
- else
9
- def template
10
- return @response if @response
11
- @response = TestController.call(Rack::MockRequest.env_for('/').merge({'REQUEST_URI' => '/',
12
- 'REMOTE_ADDR' => '127.0.0.1'}))
13
- @response.template.controller.request_forgery_protection_token = :authenticity_token
14
- @response.template.controller.session[:_csrf_token] = '1234'
15
- @response.template
16
- end
17
- end
18
-
19
- def mock_object
20
- @mock_object ||= MockObject.new
21
- end
22
-
23
- def default_instance_tag
24
- ActionView::Helpers::InstanceTag.new("object_name", "method_name", template, mock_object)
25
- end
26
-
27
- subject { default_instance_tag }
28
-
29
- context "with a valid text area tag" do
30
- subject do
31
- dump { default_instance_tag.to_text_area_tag }
32
- end
33
-
34
- it "should produce blank honeypot value" do
35
- subject.should_not =~ /name="object_name\[method_name\]"[^>]+>method_value<\/textarea>/
36
- end
37
- end
38
-
39
- context "with a valid input type=text tag" do
40
- before(:each) { @tag_options = ["input", {:type => 'text', 'name' => 'object_name[method_name]', 'id' => 'object_name_method_name', 'value' => 'method_value'}] }
41
- #subject { dump { default_instance_tag.tag(*@tag_options) } }
42
-
43
- it "should turn off autocomplete for honeypots" do
44
- subject.honeypot_tag(*@tag_options).should =~ /autocomplete="off"/
45
- end
46
-
47
- it "should obfuscate tag name" do
48
- subject.obfuscated_tag(*@tag_options).should =~ /name="#{obfuscated_name}"/
49
- end
50
-
51
- it "should obfuscate tag id" do
52
- subject.obfuscated_tag(*@tag_options).should =~ /id="#{obfuscated_id}"/
53
- end
54
-
55
- # it "should not obfuscate tag value" do
56
- # subject.obfuscated_tag(*@tag_options).should =~ /value="@tag_options"/
57
- # end
58
- #
59
- it "should include unobfuscated tag value" do
60
- subject.obfuscated_tag(*@tag_options).should =~ /value="method_value"/
61
- end
62
-
63
- it "should create honeypot name" do
64
- subject.honeypot_tag(*@tag_options).should =~ /name="object_name\[method_name\]"/
65
- end
66
-
67
- it "should create honeypot id" do
68
- subject.honeypot_tag(*@tag_options).should =~ /id="object_name_method_name"/
69
- end
70
-
71
- it "should create empty honeypot tag value" do
72
- subject.honeypot_tag(*@tag_options).should =~ /value=""/
73
- end
74
- end
75
- end
@@ -1,101 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe "Bot-Away" do
4
- # Basically we're just switching BA on and off, so we only need 2 sets of tests: what to expect when it's on, and
5
- # what to expect when it's off. The rest of this file just flips the switches.
6
-
7
- def test_params
8
- {"model"=>"User", "commit"=>"Sign in",
9
- "authenticity_token"=>"XBQEDkXrm4E8U9slBX45TWNx7TPcx8ww2FSJRy/XXg4=",
10
- "action"=>"index", "controller"=>"test", "user"=>{"username"=>"admin", "password"=>"Admin01"}
11
- }
12
- end
13
-
14
- def self.it_should_be_disabled
15
- it "should not obfuscate the field, because it should be disabled" do
16
- builder.text_field('method_name').should_not match(/name="#{obfuscated_name}/)
17
- end
18
-
19
- it "should not drop invalid params, because it should be disabled" do
20
- parms = BotAway::ParamParser.new('127.0.0.1', test_params).params
21
- parms.should == test_params
22
- end
23
-
24
- it "should be disabled" do
25
- BotAway.disabled_for?(:controller => 'test', :action => "index").should == true
26
- end
27
- end
28
-
29
- def self.it_should_be_enabled
30
- it "should obfuscate the field, because it should be enabled" do
31
- builder.text_field('method_name').should be_obfuscated_as(obfuscated_id, obfuscated_name)
32
- end
33
-
34
- it "should drop invalid params, because it should be enabled" do
35
- parms = BotAway::ParamParser.new('127.0.0.1', test_params).params
36
- parms.should_not == test_params
37
- end
38
-
39
- it "should be disabled" do
40
- BotAway.disabled_for?(:controller => 'test', :action => "index").should == false
41
- end
42
- end
43
-
44
- # flip-switching begins
45
-
46
- context "with matching controller name" do
47
- context "and no action" do
48
- before(:each) { BotAway.disabled_for :controller => 'test' }
49
- it_should_be_disabled
50
- end
51
-
52
- context "and matching action" do
53
- before(:each) { BotAway.disabled_for :controller => 'test', :action => 'index' }
54
- it_should_be_disabled
55
- end
56
-
57
- context "and not matching action" do
58
- before(:each) { BotAway.disabled_for :controller => 'test', :action => 'create' }
59
- it_should_be_enabled
60
- end
61
- end
62
-
63
- context "with not matching controller name" do
64
- context "and no action" do
65
- before(:each) { BotAway.disabled_for :controller => 'users' }
66
- it_should_be_enabled
67
- end
68
-
69
- context "and matching action" do
70
- before(:each) { BotAway.disabled_for :controller => 'users', :action => 'index' }
71
- it_should_be_enabled
72
- end
73
-
74
- context "and not matching action" do
75
- before(:each) { BotAway.disabled_for :controller => 'users', :action => 'create' }
76
- it_should_be_enabled
77
- end
78
- end
79
-
80
- context "with no controller name" do
81
- context "and matching action" do
82
- before(:each) { BotAway.disabled_for :action => 'index' }
83
- it_should_be_disabled
84
- end
85
-
86
- context "and not matching action" do
87
- before(:each) { BotAway.disabled_for :action => 'create' }
88
- it_should_be_enabled
89
- end
90
- end
91
-
92
- context "with matching mode" do
93
- before(:each) { BotAway.disabled_for :mode => ENV['RAILS_ENV'] }
94
- it_should_be_disabled
95
- end
96
-
97
- context "with not matching mode" do
98
- before(:each) { BotAway.disabled_for :mode => "this_is_not_#{ENV['RAILS_ENV']}" }
99
- it_should_be_enabled
100
- end
101
- end