merb_threshold 0.1.4

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.
@@ -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
+