merb_threshold 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,136 @@
1
+ describe Frequency do
2
+ before(:each) do
3
+ now = Time.now.to_i
4
+ @history = [
5
+ now - 301,
6
+ now - 121,
7
+ now - 61,
8
+ now - 31,
9
+ now - 20
10
+ ]
11
+ end
12
+
13
+ it 'should be able to initialize a frequency' do
14
+ @freq = Frequency.new(5,30,:seconds)
15
+ @freq.should be_an_instance_of(Frequency)
16
+ end
17
+
18
+ it 'should be able to initialize a frequency without the units' do
19
+ @freq1 = Frequency.new 1, 30, :seconds
20
+ @freq2 = Frequency.new 1, 30.seconds
21
+
22
+ @freq1.interval.should be(@freq2.interval)
23
+ @freq1.occurrence.should be(@freq2.occurrence)
24
+ @freq1.units.should == @freq2.units
25
+ @freq1.period.should be(@freq2.period)
26
+ end
27
+
28
+ it 'should create frequencies properly when using floats' do
29
+ @freq = Frequency.new 1, 3.3, :minutes
30
+ @freq.period.to_i == 198
31
+ end
32
+
33
+ it 'should cast the units automatically if not provided' do
34
+ @freq = Frequency.new 5, 5.minutes
35
+ @freq.period.should == 300
36
+ @freq.interval.should == 5.0
37
+ @freq.units.should == :minutes
38
+ end
39
+
40
+ it 'should cast the units automatically if not provided' do
41
+ @freq = Frequency.new 5, 5.hours
42
+ @freq.units.should == :hours
43
+ end
44
+
45
+ it 'should provide #to_s' do
46
+ @freq = Frequency.new 5, 5.minutes
47
+ @freq.to_s == "5 times per 5.0 minutes"
48
+ end
49
+
50
+ it 'should be able to load a list of events' do
51
+ @freq = Frequency.new 5, 5, :minutes
52
+ @freq.load @history
53
+
54
+ @freq.events.length.should be(5)
55
+ end
56
+
57
+ it 'should be able to determine the rate of events over a period in seconds' do
58
+ @freq = Frequency.new 1, 2, :minutes
59
+ @freq.load @history
60
+
61
+ # 3 fall within 2 minutes
62
+ projected_rate = 3 / 120.0
63
+ @freq.rate.should == projected_rate
64
+ end
65
+
66
+ it 'should always determine an event is not permissable when the period is zero' do
67
+ @freq = Frequency.new 1, 0
68
+ @freq2 = Frequency.new 1, 0, :seconds
69
+ @freq3 = Frequency.new 1, 0, :minutes
70
+ @freq4 = Frequency.new 0, 0
71
+
72
+ @freq.permit?.should be(false)
73
+ @freq2.permit?.should be(false)
74
+ @freq3.permit?.should be(false)
75
+ @freq4.permit?.should be(false)
76
+ end
77
+
78
+ it 'should be able to determine if an additional event is permissable' do
79
+ @freq = Frequency.new 1, 2, :minutes
80
+ @freq.load [Time.now.to_i - 30]
81
+ @freq.permit?.should be(false)
82
+
83
+ @freq2 = Frequency.new 5, 5, :minutes
84
+ @freq2.load @history
85
+ @freq2.permit?.should be(true)
86
+ end
87
+
88
+ it 'should be able to add a single event' do
89
+ @freq = Frequency.new 5, 2.minutes
90
+ @freq.add(Time.now.to_i).length.should be(1)
91
+ end
92
+
93
+ it 'should be able to determine if there is no wait for an available resource' do
94
+ @freq = Frequency.new 5, 5.minutes
95
+ @freq.load @history
96
+ @freq.wait.should be(0)
97
+ end
98
+
99
+ it 'should be able to determine the wait time in seconds when unavailable' do
100
+ @freq = Frequency.new 2, 1.minute
101
+ @freq.load @history
102
+
103
+ # Treshold is 1 minute
104
+ # Oldest happend 31 seconds ago
105
+ # in 29 more seconds it will fall out of the period (60 seconds)
106
+ @freq.wait.should be(29)
107
+ end
108
+
109
+ it 'should be able to flush the currently loaded events' do
110
+ @freq = Frequency.new 2, 1.minute
111
+ @freq.load @history
112
+ @freq.respond_to? :flush
113
+ @freq.flush
114
+ @freq.events.should be_empty
115
+ end
116
+
117
+ it 'should be able to load! events' do
118
+ @freq = Frequency.new 2, 1.minute
119
+ @freq.load @history
120
+ @freq.load @history
121
+ @freq.events.length.should be(10)
122
+ @freq.load!([Time.now.to_i])
123
+ @freq.events.length.should be(1)
124
+ end
125
+
126
+ it 'should be able to determine the wait tiem in seconds when unavailable (part 2)' do
127
+ @freq = Frequency.new 2, 1.minute
128
+ @freq.load @history
129
+ @freq.flush
130
+
131
+ @freq.add(Time.now.to_i)
132
+ @freq.add(Time.now.to_i)
133
+
134
+ @freq.wait.should be(60)
135
+ end
136
+ end
@@ -0,0 +1,29 @@
1
+ describe Merb::Threshold::Helpers do
2
+ before do
3
+ class CaptchaController < Merb::Controller
4
+ register_threshold :index
5
+ GhettoSessionStore = {}
6
+
7
+ def session
8
+ GhettoSessionStore[params[:session_id]] ||={}
9
+ GhettoSessionStore[params[:session_id]]
10
+ end
11
+
12
+ def index
13
+ if !permit_access?(:index)
14
+ @partial =File.join(File.expand_path("."),"lib/merb_threshold/templates/recaptcha_partial")
15
+ captcha :partial => @partial, :partial_opts => {:format => :html}
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+ it 'should display a captcha if the threshold is exceeded' do
22
+ @response = dispatch_to(CaptchaController, :index,{
23
+ :session_id=>"display-captcha"
24
+ })
25
+
26
+ @response.should be_successful
27
+ @response.body.should =~ /api.recaptcha/
28
+ end
29
+ end
@@ -0,0 +1,32 @@
1
+ describe Merb::Threshold::Helpers do
2
+ before do
3
+ class WaitController < Merb::Controller
4
+ register_threshold :index, :limit => 1.per(30.seconds)
5
+
6
+ GhettoSessionStore = {}
7
+ def session
8
+ GhettoSessionStore[params[:session_id]] ||={}
9
+ GhettoSessionStore[params[:session_id]]
10
+ end
11
+
12
+ def index
13
+ if !permit_access?(:index)
14
+ wait :partial => File.join(
15
+ File.expand_path("."),"lib/merb_threshold/templates/wait_partial"
16
+ ), :partial_opts => {:format => :html}
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ it 'should display a wait message if the threshold is exceeded' do
23
+ dispatch_to(WaitController, :index,{:session_id=>"display-wait-msg"})
24
+
25
+ @response = dispatch_to(WaitController, :index,{
26
+ :session_id=>"display-wait-msg"
27
+ })
28
+
29
+ @response.should be_successful
30
+ @response.body.should =~ /This resource will be available in 30 seconds/
31
+ end
32
+ end
@@ -0,0 +1,9 @@
1
+ describe Per do
2
+ it 'should provide the per method' do
3
+ 3.should respond_to :per
4
+ end
5
+
6
+ it 'should return a frequency object' do
7
+ 3.per(30.seconds).should be_instance_of(Frequency)
8
+ end
9
+ end
@@ -0,0 +1,35 @@
1
+ include Merb::Threshold
2
+ describe RecaptchaClient do
3
+ it 'should provide API_SERVER' do
4
+ defined?(RecaptchaClient::API_SERVER).should ==('constant')
5
+ end
6
+
7
+ it 'should provide API_SSL_SERVER' do
8
+ defined?(RecaptchaClient::API_SSL_SERVER).should ==('constant')
9
+ end
10
+
11
+ it 'should provide API_VERIFY_SERVER' do
12
+ defined?(RecaptchaClient::API_VERIFY_SERVER).should ==('constant')
13
+ end
14
+
15
+ it 'should provide accessors for a public key' do
16
+ RecaptchaClient.should respond_to :public_key
17
+ RecaptchaClient.should respond_to :public_key=
18
+ RecaptchaClient.public_key = "key"
19
+ RecaptchaClient.public_key.should == "key"
20
+ end
21
+
22
+ it 'should provide accessors for a private key' do
23
+ RecaptchaClient.should respond_to :private_key
24
+ RecaptchaClient.should respond_to :private_key=
25
+ RecaptchaClient.private_key = "key"
26
+ RecaptchaClient.private_key.should == "key"
27
+ end
28
+
29
+ it 'should be able to submit a captcha response' do
30
+ result = RecaptchaClient.solve("127.0.0.1","fake_challenge","fake_response")
31
+ result.should be_instance_of(Array)
32
+ result.first.should be(false)
33
+ result.last.should == ("invalid-site-private-key")
34
+ end
35
+ end
@@ -0,0 +1,56 @@
1
+ require 'rubygems'
2
+ require 'merb-helpers/time_dsl'
3
+
4
+ require 'merb-core'
5
+ require 'merb-core/test'
6
+
7
+ Merb::Config.use do |c|
8
+ c[:use_mutex] = false
9
+ c[:session_store] = 'cookie'
10
+ c[:session_secret_key] = 'f1e532d42a798511504907cf28d9c660fe51ac91'
11
+ c[:session_id_key] = '_merb_threshold_session_id'
12
+ c[:reload_classes] = false
13
+ end
14
+
15
+ Merb::Plugins.config[:merb_threshold] = {
16
+ # TODO remove global catpcha keys
17
+ :public_key => nil,
18
+ :private_key => nil,
19
+ :recaptcha => true,
20
+ :wait_partial => 'shared/wait_partial',
21
+ :captcha_partial => 'shared/recaptcha_partial'
22
+ }
23
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'merb_threshold')
24
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'merb_threshold','frequency')
25
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'merb_threshold','controller','merb_controller')
26
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'merb_threshold','recaptcha_client')
27
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'merb_threshold','helpers','recaptcha_helper')
28
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'merb_threshold','helpers','wait_helper')
29
+
30
+ module Merb
31
+ class Controller
32
+ include Merb::Threshold::Helpers
33
+ end
34
+ end
35
+ Numeric.send :include, Merb::Threshold::Per
36
+
37
+ include Merb::Threshold
38
+
39
+ class Hash
40
+ def to_json
41
+ result = "{"
42
+ result << self.map do |k, v|
43
+ if ! v.is_a?(String)
44
+ "\"#{k}\": #{v}"
45
+ else
46
+ "\"#{k}\": \"#{v}\""
47
+ end
48
+ end.join(", ")
49
+ result << "}"
50
+ end
51
+ end
52
+
53
+
54
+
55
+ RecaptchaClient.public_key = '6LcnNgUAAAAAABrFyM-LuC53axOzHbE27afV4gxP'
56
+ RecaptchaClient.private_key = '6LcnNgUAAAAAAEqnr9HP9ofrChZTcuTjl_0FFnxF'
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: merb_threshold
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.4
5
+ platform: ruby
6
+ authors:
7
+ - Cory O'Daniel
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-02-24 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: merb
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.0.7.1
24
+ version:
25
+ description: Merb plugin that provides resource access rate limits and captcha'ing
26
+ email: contact@coryodaniel.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - README
33
+ - LICENSE
34
+ - TODO
35
+ files:
36
+ - LICENSE
37
+ - README
38
+ - Rakefile
39
+ - TODO
40
+ - lib/merb_threshold
41
+ - lib/merb_threshold/controller
42
+ - lib/merb_threshold/controller/merb_controller.rb
43
+ - lib/merb_threshold/frequency.rb
44
+ - lib/merb_threshold/helpers
45
+ - lib/merb_threshold/helpers/recaptcha_helper.rb
46
+ - lib/merb_threshold/helpers/wait_helper.rb
47
+ - lib/merb_threshold/merbtasks.rb
48
+ - lib/merb_threshold/per.rb
49
+ - lib/merb_threshold/recaptcha_client.rb
50
+ - lib/merb_threshold/templates
51
+ - lib/merb_threshold/templates/_recaptcha_partial.html.erb
52
+ - lib/merb_threshold/templates/_wait_partial.html.erb
53
+ - lib/merb_threshold.rb
54
+ - spec/controller
55
+ - spec/controller/merb_controller_spec.rb
56
+ - spec/frequency_spec.rb
57
+ - spec/helpers
58
+ - spec/helpers/recaptcha_helper_spec.rb
59
+ - spec/helpers/wait_helper_spec.rb
60
+ - spec/per_spec.rb
61
+ - spec/recaptcha_client_spec.rb
62
+ - spec/spec_helper.rb
63
+ has_rdoc: true
64
+ homepage: http://github.com/coryodaniel
65
+ post_install_message:
66
+ rdoc_options: []
67
+
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: "0"
75
+ version:
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: "0"
81
+ version:
82
+ requirements: []
83
+
84
+ rubyforge_project: merb
85
+ rubygems_version: 1.3.1
86
+ signing_key:
87
+ specification_version: 2
88
+ summary: Merb plugin that provides resource access rate limits and captcha'ing
89
+ test_files: []
90
+