limited 0.0.1
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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +60 -0
- data/Rakefile +1 -0
- data/lib/limited/action.rb +55 -0
- data/lib/limited/config.rb +35 -0
- data/lib/limited/version.rb +3 -0
- data/lib/limited.rb +42 -0
- data/limited.gemspec +29 -0
- data/spec/limited_action_spec.rb +75 -0
- data/spec/limited_config_spec.rb +30 -0
- data/spec/limited_spec.rb +14 -0
- metadata +118 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d9760e85bf1a3b2c89385bdcbd8076ff30e0cbd4
|
4
|
+
data.tar.gz: f1bec62f986e779c66f70a01c06e6e8136de4861
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7c0936a592fd48b030c5bbaac2851fc058c0ba8e4242de3efe0a710704f37e28c7a8dfe86384800095834e9c425eee87453e43972176ca59508b527d719a79ce
|
7
|
+
data.tar.gz: 1e39cf4620ba29bd06a3bf471fb43e52ccfd5592ba2016028b47fbdd2dd6bb6f17c3d4936abcf2edd0d9c8e783a09f97e2dda37a83ab2eb21cead18dd9cc8a27
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Moritz Küttel
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# Limited
|
2
|
+
|
3
|
+
Some utility functions to help you limit some actions in your applications
|
4
|
+
(like logins, contact forms, posting of comments, etc.) to stop spammers
|
5
|
+
to absue your services.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
gem 'limited'
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install limited
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
You need to define your actions somewhere in your application like this:
|
24
|
+
|
25
|
+
Limited.configure do
|
26
|
+
action :name_of_action, 1337
|
27
|
+
action :login, 20
|
28
|
+
action :sending_contact_email, 123
|
29
|
+
end
|
30
|
+
|
31
|
+
The second parameter given to action defines how many times the action
|
32
|
+
can be executed.
|
33
|
+
|
34
|
+
After defining an Action you can directly call a method on the `Limited`
|
35
|
+
module to access your Action like this:
|
36
|
+
|
37
|
+
Limited.name_of_action
|
38
|
+
Limited.login
|
39
|
+
Limited.sending_contact_email
|
40
|
+
|
41
|
+
Here are a few commonly used methods which every Action provides:
|
42
|
+
|
43
|
+
<table>
|
44
|
+
<tr>
|
45
|
+
<td>`executed`</td>
|
46
|
+
<td>Call this method everytime the specified action is being executed</td>
|
47
|
+
</tr>
|
48
|
+
<tr>
|
49
|
+
<td>`limit_reached`</td>
|
50
|
+
<td>Wheter the limit has been reached or not</td>
|
51
|
+
</tr>
|
52
|
+
</table>
|
53
|
+
|
54
|
+
## Contributing
|
55
|
+
|
56
|
+
1. Fork it
|
57
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
58
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
59
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
60
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Limited
|
2
|
+
|
3
|
+
# This class represents an action which
|
4
|
+
# can be executed a limited amount of
|
5
|
+
# times
|
6
|
+
class Action
|
7
|
+
# a symbol for the name of the action
|
8
|
+
attr_reader :name
|
9
|
+
# the amount of times the action can be executed
|
10
|
+
attr_reader :limit
|
11
|
+
# the amount of times the action already has been executed
|
12
|
+
attr_reader :num_executed
|
13
|
+
|
14
|
+
##
|
15
|
+
# :call-seq:
|
16
|
+
# Limited::Action.new(name, limit) -> Limited::Action
|
17
|
+
#
|
18
|
+
# constructor for an action
|
19
|
+
#
|
20
|
+
# === Example
|
21
|
+
#
|
22
|
+
# Limited::Action.new :do_stuff, 1000
|
23
|
+
def initialize(name, limit)
|
24
|
+
raise ArgumentError.new("Limited::Action::name needs to be a Symbol") unless name.is_a?(Symbol)
|
25
|
+
raise ArgumentError.new("Limited::Action::limit needs to be an Integer") unless limit.is_a?(Integer)
|
26
|
+
raise ArgumentError.new("Limited::Action::limit needs to be positive") if limit < 0
|
27
|
+
|
28
|
+
@name = name
|
29
|
+
@limit = limit
|
30
|
+
@num_executed = 0
|
31
|
+
end
|
32
|
+
|
33
|
+
##
|
34
|
+
# returns how many times the action can be executed
|
35
|
+
# until the given limit is reached
|
36
|
+
def num_left
|
37
|
+
@limit - @num_executed
|
38
|
+
end
|
39
|
+
|
40
|
+
##
|
41
|
+
# should be called everytime
|
42
|
+
# the action gets executed
|
43
|
+
# so the internal counter is always up-to-date
|
44
|
+
def executed
|
45
|
+
@num_executed += 1
|
46
|
+
end
|
47
|
+
|
48
|
+
##
|
49
|
+
# wheter the limit of executions
|
50
|
+
# has been exceeded
|
51
|
+
def limit_reached
|
52
|
+
@limit <= @num_executed
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Limited
|
2
|
+
|
3
|
+
# defines all the functions which
|
4
|
+
# can be used to configure
|
5
|
+
# this gem
|
6
|
+
module Config
|
7
|
+
|
8
|
+
##
|
9
|
+
# adds a new limited action to the list of actions
|
10
|
+
# takes the same paramerers as Limited::Action.new
|
11
|
+
#
|
12
|
+
# raises an ArgumentError if the same name
|
13
|
+
# for an action is not unique
|
14
|
+
def self.action(name, limit)
|
15
|
+
action = Limited::Action.new(name, limit)
|
16
|
+
raise ArgumentError.new("action with name :#{name.to_s} has already been added") if Limited.actions.has_key?(name)
|
17
|
+
Limited.actions[name] = action
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
##
|
22
|
+
# executes a block inside Limited::Config
|
23
|
+
# so you can easily access the methods in it
|
24
|
+
# and configure the Limited gem
|
25
|
+
#
|
26
|
+
# === Example
|
27
|
+
#
|
28
|
+
# Limited.configure do
|
29
|
+
# action :sending_contact_email, 50
|
30
|
+
# action :failed_login, 1337
|
31
|
+
# end
|
32
|
+
def self.configure(&block)
|
33
|
+
Config.instance_eval &block
|
34
|
+
end
|
35
|
+
end
|
data/lib/limited.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require "limited/version"
|
2
|
+
require "limited/action"
|
3
|
+
|
4
|
+
module Limited
|
5
|
+
# a hash containing all the
|
6
|
+
# limited actions
|
7
|
+
# the name of the Action is used as key
|
8
|
+
@actions = {}
|
9
|
+
|
10
|
+
##
|
11
|
+
# returns a hash containing all the
|
12
|
+
# limited actions
|
13
|
+
def self.actions
|
14
|
+
@actions
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
##
|
19
|
+
# :call-seq:
|
20
|
+
# Limited.<action_name> -> Limited::Action
|
21
|
+
#
|
22
|
+
# adds the possibility to access
|
23
|
+
# every action directly via Limited.<actionanem>
|
24
|
+
#
|
25
|
+
# === Example
|
26
|
+
#
|
27
|
+
# Limited.configure do
|
28
|
+
# action :some_action, 123
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# Limited.some_action.executed
|
32
|
+
# Limited.some_action.num_left # -> 122
|
33
|
+
def self.method_missing(method_id, *arguments)
|
34
|
+
if @actions.has_key?(method_id)
|
35
|
+
@actions[method_id]
|
36
|
+
else
|
37
|
+
super
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
require "limited/config"
|
data/limited.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'limited/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "limited"
|
8
|
+
spec.version = Limited::VERSION
|
9
|
+
spec.authors = ["Moritz Küttel"]
|
10
|
+
spec.email = ["moritz.kuettel@gmail.com"]
|
11
|
+
spec.description = %q{helps you limiting certain actions to prevent spam/dos}
|
12
|
+
spec.summary = %q{
|
13
|
+
Some utility functions to help you limit some actions in your applications
|
14
|
+
(like logins, contact forms, posting of comments, etc.) to stop spammers
|
15
|
+
to absue your services.}
|
16
|
+
|
17
|
+
spec.homepage = "https://github.com/mkuettel/limited"
|
18
|
+
spec.license = "MIT"
|
19
|
+
|
20
|
+
spec.files = `git ls-files`.split($/)
|
21
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
22
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
23
|
+
spec.require_paths = ["lib"]
|
24
|
+
|
25
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
26
|
+
spec.add_development_dependency "rake"
|
27
|
+
spec.add_development_dependency "rspec"
|
28
|
+
spec.add_development_dependency "debugger"
|
29
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'limited'
|
2
|
+
require 'limited/action'
|
3
|
+
|
4
|
+
describe Limited::Action do
|
5
|
+
before { @action = Limited::Action.new :do_some_stuff, 1337 }
|
6
|
+
subject { @action }
|
7
|
+
|
8
|
+
it { should respond_to(:name) }
|
9
|
+
it { should respond_to(:limit) }
|
10
|
+
it { should respond_to(:num_executed) }
|
11
|
+
it { should respond_to(:num_left) }
|
12
|
+
|
13
|
+
describe "constructor" do
|
14
|
+
it "should take a name" do
|
15
|
+
name = Limited::Action.new(:do_stuff, 15).name
|
16
|
+
name.should eq :do_stuff
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should take a limit" do
|
20
|
+
limit = Limited::Action.new(:do_stuff, 15).limit
|
21
|
+
limit.should eq 15
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "name" do
|
26
|
+
it "should be a symbol" do
|
27
|
+
expect do
|
28
|
+
Limited::Action.new "string", 123
|
29
|
+
end.to raise_error(ArgumentError)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "limit" do
|
34
|
+
it "should be an integer" do
|
35
|
+
expect do
|
36
|
+
Limited::Action.new :asdasd, nil
|
37
|
+
end.to raise_error(ArgumentError)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should be positive" do
|
41
|
+
expect do
|
42
|
+
Limited::Action.new :asdasd, -1
|
43
|
+
end.to raise_error(ArgumentError)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "num_executed" do
|
48
|
+
it "should be initialized to 0" do
|
49
|
+
@action.num_executed.should eq 0
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "executed" do
|
54
|
+
before { @action.executed }
|
55
|
+
it "should increase the num_executed counter" do
|
56
|
+
@action.num_executed.should eq 1
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "limit_reached" do
|
61
|
+
it "should not be reached when intialized" do
|
62
|
+
@action.limit_reached.should be_false
|
63
|
+
end
|
64
|
+
it "should be true when 'executed' has been called 'limit' times" do
|
65
|
+
@action.executed
|
66
|
+
@action.limit_reached.should be_false
|
67
|
+
1335.times { @action.executed }
|
68
|
+
@action.limit_reached.should be_false
|
69
|
+
@action.executed
|
70
|
+
@action.limit_reached.should be_true
|
71
|
+
@action.executed
|
72
|
+
@action.limit_reached.should be_true
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'limited'
|
2
|
+
require 'limited/config'
|
3
|
+
|
4
|
+
describe Limited::Config do
|
5
|
+
it { Limited.should respond_to(:configure) }
|
6
|
+
it { Limited::Config.should respond_to(:action) }
|
7
|
+
|
8
|
+
it "should add an Limited::Action to Limited::actions when calling Limited::Config::action" do
|
9
|
+
expect do
|
10
|
+
Limited::Config.action :new, 123
|
11
|
+
end.to change(Limited, :actions)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should not be possible to add an action with the same name twice" do
|
15
|
+
expect do
|
16
|
+
Limited::Config.action :same_name, 123
|
17
|
+
Limited::Config.action :same_name, 123
|
18
|
+
end.to raise_error(ArgumentError)
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "configure" do
|
22
|
+
it "should be possible to add actions via the Limited::configure method" do
|
23
|
+
expect do
|
24
|
+
Limited.configure do
|
25
|
+
action :some_action, 123
|
26
|
+
end
|
27
|
+
end.to change(Limited, :actions)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
Limited.configure do
|
2
|
+
action :missing_method_test, 13
|
3
|
+
end
|
4
|
+
|
5
|
+
describe Limited do
|
6
|
+
it { Limited.should respond_to(:actions) }
|
7
|
+
|
8
|
+
describe "missing_method calls" do
|
9
|
+
it "should give access to the action object when calling method with its name" do
|
10
|
+
action = Limited.actions[:missing_method_test]
|
11
|
+
Limited.missing_method_test.should eq action
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
metadata
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: limited
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Moritz Küttel
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-06-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: debugger
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: helps you limiting certain actions to prevent spam/dos
|
70
|
+
email:
|
71
|
+
- moritz.kuettel@gmail.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- .gitignore
|
77
|
+
- Gemfile
|
78
|
+
- LICENSE.txt
|
79
|
+
- README.md
|
80
|
+
- Rakefile
|
81
|
+
- lib/limited.rb
|
82
|
+
- lib/limited/action.rb
|
83
|
+
- lib/limited/config.rb
|
84
|
+
- lib/limited/version.rb
|
85
|
+
- limited.gemspec
|
86
|
+
- spec/limited_action_spec.rb
|
87
|
+
- spec/limited_config_spec.rb
|
88
|
+
- spec/limited_spec.rb
|
89
|
+
homepage: https://github.com/mkuettel/limited
|
90
|
+
licenses:
|
91
|
+
- MIT
|
92
|
+
metadata: {}
|
93
|
+
post_install_message:
|
94
|
+
rdoc_options: []
|
95
|
+
require_paths:
|
96
|
+
- lib
|
97
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - '>='
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
requirements: []
|
108
|
+
rubyforge_project:
|
109
|
+
rubygems_version: 2.0.0.rc.2
|
110
|
+
signing_key:
|
111
|
+
specification_version: 4
|
112
|
+
summary: Some utility functions to help you limit some actions in your applications
|
113
|
+
(like logins, contact forms, posting of comments, etc.) to stop spammers to absue
|
114
|
+
your services.
|
115
|
+
test_files:
|
116
|
+
- spec/limited_action_spec.rb
|
117
|
+
- spec/limited_config_spec.rb
|
118
|
+
- spec/limited_spec.rb
|