rack_ip_restrictor 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source "http://rubygems.org"
2
+ gem "activesupport", ">= 2.3.5"
3
+
4
+ # Add dependencies to develop your gem here.
5
+ # Include everything needed to run rake, tests, features, etc.
6
+ group :development do
7
+ gem "rspec", "~> 2.3.0"
8
+ gem "yard", "~> 0.6.0"
9
+ gem "bundler", "~> 1.0.0"
10
+ gem "jeweler", "~> 1.5.2"
11
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,30 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ activesupport (3.0.6)
5
+ diff-lcs (1.1.2)
6
+ git (1.2.5)
7
+ jeweler (1.5.2)
8
+ bundler (~> 1.0.0)
9
+ git (>= 1.2.5)
10
+ rake
11
+ rake (0.8.7)
12
+ rspec (2.3.0)
13
+ rspec-core (~> 2.3.0)
14
+ rspec-expectations (~> 2.3.0)
15
+ rspec-mocks (~> 2.3.0)
16
+ rspec-core (2.3.1)
17
+ rspec-expectations (2.3.0)
18
+ diff-lcs (~> 1.1.2)
19
+ rspec-mocks (2.3.0)
20
+ yard (0.6.7)
21
+
22
+ PLATFORMS
23
+ ruby
24
+
25
+ DEPENDENCIES
26
+ activesupport (>= 2.3.5)
27
+ bundler (~> 1.0.0)
28
+ jeweler (~> 1.5.2)
29
+ rspec (~> 2.3.0)
30
+ yard (~> 0.6.0)
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Alexander Dreher
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,62 @@
1
+ = rack_ip_restrictor
2
+
3
+ Restricts requests to specific IP addresses and ranges for specified paths.
4
+
5
+ == Installation
6
+ Add the following line to your Gemfile
7
+ gem "rack_ip_restrictor"
8
+
9
+ If you want to use it as plugin
10
+ rails plugin install git://github.com/phatworx/rack_ip_restrictor.git
11
+
12
+ == Using
13
+ === Rails 3
14
+ Create an initializer file in +config/initializers+, e.g. +config/initializers/rack_ip_restrictor.rb+ with your configuration. See the documentation for details.
15
+
16
+ Rack::IpRestrictor.configure do
17
+ respond_with [403, {'Content-Type' => 'text/html'}, '']
18
+
19
+ ips_for :test do
20
+ add '127.0.0.1'
21
+ add '127.0.0.2/8'
22
+ end
23
+
24
+ restrict /^\/admin/, '/admin', :only => :test
25
+ end
26
+
27
+ Add the configured middleware in the +config/application.rb+
28
+
29
+ # [...]
30
+ class Application < Rails::Application
31
+ # [...]
32
+ config.middleware.use Rack::IpRestrictor.middleware
33
+ # [...]
34
+ end
35
+ # [...]
36
+
37
+ Start/restart your rails server and see it working.
38
+
39
+ == Features
40
+ TODO
41
+
42
+ == Maintainers
43
+
44
+ * Team Phatworx (http://github.com/phatworx)
45
+ * Alexander Dreher (http://github.com/alexdreher)
46
+ * Marco Scholl (http://github.com/traxanos)
47
+
48
+
49
+ == Contributing to rack_ip_restrictor
50
+
51
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
52
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
53
+ * Fork the project
54
+ * Start a feature/bugfix branch
55
+ * Commit and push until you are happy with your contribution
56
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
57
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
58
+
59
+ == Copyright
60
+
61
+ Copyright (c) 2011 Alexander Dreher. See LICENSE.txt for further details.
62
+
data/Rakefile ADDED
@@ -0,0 +1,38 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ Jeweler::Tasks.new do |gem|
14
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
+ gem.name = "rack_ip_restrictor"
16
+ gem.homepage = "http://github.com/phatworx/rack_ip_restrictor"
17
+ gem.license = "MIT"
18
+ gem.summary = %Q{IP restriction middleware}
19
+ gem.description = %Q{Restricts requests to specific IP addresses and ranges for specified paths}
20
+ gem.email = "team@phatworx.de"
21
+ gem.authors = ["Alexander Dreher"]
22
+ # Include your dependencies below. Runtime dependencies are required when using your gem,
23
+ # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
24
+ # gem.add_runtime_dependency 'jabber4r', '> 0.1'
25
+ # gem.add_development_dependency 'rspec', '> 1.2.3'
26
+ end
27
+ Jeweler::RubygemsDotOrgTasks.new
28
+
29
+ require 'rspec/core'
30
+ require 'rspec/core/rake_task'
31
+ RSpec::Core::RakeTask.new(:spec) do |spec|
32
+ spec.pattern = FileList['spec/**/*_spec.rb']
33
+ end
34
+
35
+ task :default => :spec
36
+
37
+ require 'yard'
38
+ YARD::Rake::YardocTask.new
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'rack_ip_restrictor'
@@ -0,0 +1,55 @@
1
+ module Rack::IpRestrictor
2
+ # Configuration class for the IpRestrictor
3
+ # @example
4
+ # Rack::IpRestrictor.configure do
5
+ # respond_with [403, {'Content-Type' => 'text/html'}, '']
6
+ #
7
+ # ips_for :test do
8
+ # add '127.0.0.1'
9
+ # add '127.0.0.2/8'
10
+ # end
11
+ #
12
+ # restrict /^\/admin/, '/admin', :only => :test
13
+ # end
14
+ # @see README.rdoc
15
+ class Config
16
+ attr_accessor :response, :ip_groups, :restrictions
17
+
18
+ def initialize
19
+ @ip_groups = {}
20
+ @restrictions = []
21
+ @response = [
22
+ 403,
23
+ {'Content-Type' => 'text/html'},
24
+ ''
25
+ ]
26
+ end
27
+
28
+ # Overwrites the default response. Same format as a middleware response.
29
+ #
30
+ # @param [Array<Integer, String, String>] response status, a set of headers, body
31
+ def respond_with(response)
32
+ @response = response
33
+ end
34
+
35
+ # Sets and gets IP addresses for a named group
36
+ #
37
+ # @return [IpGroup] IP addresses for a named group
38
+ def ips_for(name, &block)
39
+ if block_given?
40
+ @ip_groups[name] = IpGroup.new
41
+ @ip_groups[name].instance_eval &block
42
+ @ip_groups[name]
43
+ else
44
+ @ip_groups[name]
45
+ end
46
+ end
47
+
48
+ # Adds a restriction
49
+ # @see Restriction#initialize
50
+ def restrict(*args)
51
+ @restrictions << Restriction.new(*args)
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,29 @@
1
+ module Rack::IpRestrictor
2
+ # Stores and handles groups of IP's added as String, converted into hash of IpAddr
3
+ class IpGroup
4
+
5
+ def initialize
6
+ @addresses = {}
7
+ end
8
+
9
+ # Adds an IP address to the list of addresses as instance of IPAddr
10
+ #
11
+ # @param [String] ip_arg IP address as String
12
+ def add(ip_arg)
13
+ @addresses[ip_arg] = IPAddr.new(ip_arg)
14
+ end
15
+
16
+ # @return [Array] Keys of addresses set
17
+ def ips
18
+ @addresses.keys
19
+ end
20
+
21
+ # @param [IpAddr] remote_addr The IP address of the requester
22
+ def include?(remote_addr)
23
+ @addresses.each do |key, value|
24
+ return true if value.include? remote_addr
25
+ end
26
+ false
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,25 @@
1
+ # Rack middleware
2
+ class Rack::IpRestrictor::Middleware
3
+
4
+ def initialize(app, options={})
5
+ @app = app
6
+ @options = options
7
+ end
8
+
9
+ # Rack middleware call method
10
+ def call(env)
11
+ remote_addr = IPAddr.new(env['REMOTE_ADDR'])
12
+
13
+ Rack::IpRestrictor.config.restrictions.each do |restriction|
14
+ return access_denied unless restriction.validate(env, remote_addr)
15
+ end
16
+
17
+ @app.call(env)
18
+ end
19
+
20
+ private
21
+ # @return [Array] The response array [Status, set of headers, body]
22
+ def access_denied
23
+ Rack::IpRestrictor.config.response
24
+ end
25
+ end
@@ -0,0 +1,58 @@
1
+ module Rack::IpRestrictor
2
+ # Handles restrictions
3
+ class Restriction
4
+
5
+ # Inits a new restriction
6
+ #
7
+ # @example Path as String
8
+ # restrict '/admin', :only => :test
9
+ # @example Path as Regexp
10
+ # restrict /^\/admin/, :only => :test
11
+ # @example List of paths; Strings and Regexps can be combined
12
+ # restrict /^\/admin/, '/internal', '/secret', :only => :test
13
+ #
14
+ # @param [Array<String, Regexp, Hash>] *args
15
+ #
16
+ # @todo Add other options, i.e. an array of IP groups
17
+ # :only => [:test1, :admins]
18
+ def initialize(*args)
19
+ @options = args.extract_options!
20
+
21
+ raise Exception, "invalid argument" unless @options.has_key? :only and @options[:only].is_a? Symbol
22
+
23
+ @paths = args
24
+ @paths.each do |path|
25
+ raise Exception, "invalid path argument" unless path.is_a? String or path.is_a? Regexp
26
+ end
27
+
28
+ end
29
+
30
+ # Validates, if a request (with a remote_address) is allowed to access the requested path
31
+ # @see Middleware#call
32
+ def validate(env, remote_addr)
33
+ @paths.each do |path|
34
+ if concerns_path?(env["PATH_INFO"]) and not concerns_ip?(remote_addr)
35
+ return false
36
+ end
37
+ end
38
+
39
+ true
40
+ end
41
+
42
+ private
43
+
44
+ # @return [Boolean] Is the remote_addr included in a configured IP range?
45
+ def concerns_ip?(remote_addr)
46
+ Rack::IpRestrictor.config.ips_for(@options[:only]).include?(remote_addr)
47
+ end
48
+
49
+ # @return [Boolean] Does the request concern a configured path?
50
+ def concerns_path?(request_path)
51
+ @paths.each do |path|
52
+ return true if path.is_a? String and path == request_path
53
+ return true if path.is_a? Regexp and path =~ request_path
54
+ end
55
+ false
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,30 @@
1
+ require 'ipaddr'
2
+ require 'active_support/core_ext/array/extract_options'
3
+
4
+ # namespace Rack
5
+ module Rack
6
+ # namespace IpRestrictor
7
+ module IpRestrictor
8
+ class << self
9
+ attr_reader :config
10
+
11
+ # @see Config#initialize
12
+ def configure(&block)
13
+ @config = IpRestrictor::Config.new
14
+ @config.instance_eval &block
15
+ end
16
+
17
+ # Rack middleware
18
+ # @return [Middleware] The configured plug & play Rack middleware
19
+ def middleware
20
+ IpRestrictor::Middleware
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ require 'rack_ip_restrictor/ip_group'
27
+ require 'rack_ip_restrictor/middleware'
28
+ require 'rack_ip_restrictor/config'
29
+ require 'rack_ip_restrictor/restriction'
30
+
@@ -0,0 +1,74 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{rack_ip_restrictor}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Alexander Dreher"]
12
+ s.date = %q{2011-04-12}
13
+ s.description = %q{Restricts requests to specific IP addresses and ranges for specified paths}
14
+ s.email = %q{team@phatworx.de}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".rspec",
22
+ "Gemfile",
23
+ "Gemfile.lock",
24
+ "LICENSE.txt",
25
+ "README.rdoc",
26
+ "Rakefile",
27
+ "VERSION",
28
+ "init.rb",
29
+ "lib/rack_ip_restrictor.rb",
30
+ "lib/rack_ip_restrictor/config.rb",
31
+ "lib/rack_ip_restrictor/ip_group.rb",
32
+ "lib/rack_ip_restrictor/middleware.rb",
33
+ "lib/rack_ip_restrictor/restriction.rb",
34
+ "rack_ip_restrictor.gemspec",
35
+ "spec/rack_ip_restrictor_spec.rb",
36
+ "spec/rule_set_spec.rb",
37
+ "spec/spec_helper.rb"
38
+ ]
39
+ s.homepage = %q{http://github.com/phatworx/rack_ip_restrictor}
40
+ s.licenses = ["MIT"]
41
+ s.require_paths = ["lib"]
42
+ s.rubygems_version = %q{1.6.2}
43
+ s.summary = %q{IP restriction middleware}
44
+ s.test_files = [
45
+ "spec/rack_ip_restrictor_spec.rb",
46
+ "spec/rule_set_spec.rb",
47
+ "spec/spec_helper.rb"
48
+ ]
49
+
50
+ if s.respond_to? :specification_version then
51
+ s.specification_version = 3
52
+
53
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
54
+ s.add_runtime_dependency(%q<activesupport>, [">= 2.3.5"])
55
+ s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
56
+ s.add_development_dependency(%q<yard>, ["~> 0.6.0"])
57
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
58
+ s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
59
+ else
60
+ s.add_dependency(%q<activesupport>, [">= 2.3.5"])
61
+ s.add_dependency(%q<rspec>, ["~> 2.3.0"])
62
+ s.add_dependency(%q<yard>, ["~> 0.6.0"])
63
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
64
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
65
+ end
66
+ else
67
+ s.add_dependency(%q<activesupport>, [">= 2.3.5"])
68
+ s.add_dependency(%q<rspec>, ["~> 2.3.0"])
69
+ s.add_dependency(%q<yard>, ["~> 0.6.0"])
70
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
71
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
72
+ end
73
+ end
74
+
@@ -0,0 +1,65 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Rack::IpRestrictor do
4
+ describe "#middleware" do
5
+ subject { Rack::IpRestrictor.middleware }
6
+
7
+ it { should respond_to :new }
8
+
9
+ describe "#new" do
10
+ subject { Rack::IpRestrictor.middleware.new([]) }
11
+ it { should respond_to :call }
12
+ end
13
+ end
14
+
15
+ context "#configure" do
16
+ describe "#ips_for :test" do
17
+ before do
18
+
19
+ Rack::IpRestrictor.configure do
20
+ ips_for :test do
21
+ add '127.0.0.1'
22
+ add '127.0.0.2/8'
23
+ end
24
+ end
25
+
26
+ end
27
+
28
+ it "sould be configured" do
29
+ Rack::IpRestrictor.config.should_not be_nil
30
+ end
31
+
32
+ it "should have one ip groups" do
33
+ Rack::IpRestrictor.config.ip_groups.size.should == 1
34
+ end
35
+
36
+ it "should have 2 ips" do
37
+ Rack::IpRestrictor.config.ips_for(:test).ips.size.should == 2
38
+ end
39
+
40
+ end
41
+
42
+ describe "#restrict '/secret'" do
43
+ before do
44
+
45
+ Rack::IpRestrictor.configure do
46
+ respond_with [404, {'Content-Type' => 'text/html'}, "Not found"]
47
+
48
+ ips_for :test do
49
+ add '127.0.0.1'
50
+ add '127.0.0.2/8'
51
+ end
52
+
53
+ restrict '/test'
54
+ restrict /^\/test/
55
+ restrict ['/test', '/test2']
56
+ end
57
+
58
+ end
59
+
60
+ it "sould be configured" do
61
+ Rack::IpRestrictor.config.should_not be_nil
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,18 @@
1
+ #require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ #
3
+ #describe Rack::IpRestrictor::RuleSet do
4
+ # before { @rule_set = Rack::IpRestrictor::RuleSet.new }
5
+ # subject { @rule_set }
6
+ #
7
+ # it "#ip_group" do
8
+ # @rule_set.ip_group :test do
9
+ #
10
+ # address '127.0.0.1'
11
+ #
12
+ # end
13
+ #
14
+ #
15
+ #
16
+ # end
17
+ #
18
+ #end
@@ -0,0 +1,12 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'rspec'
4
+ require 'rack_ip_restrictor'
5
+
6
+ # Requires supporting files with custom matchers and macros, etc,
7
+ # in ./support/ and its subdirectories.
8
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
9
+
10
+ RSpec.configure do |config|
11
+
12
+ end
metadata ADDED
@@ -0,0 +1,133 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rack_ip_restrictor
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.1.0
6
+ platform: ruby
7
+ authors:
8
+ - Alexander Dreher
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-04-12 00:00:00 +02:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: activesupport
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 2.3.5
24
+ type: :runtime
25
+ prerelease: false
26
+ version_requirements: *id001
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: &id002 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ~>
33
+ - !ruby/object:Gem::Version
34
+ version: 2.3.0
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: *id002
38
+ - !ruby/object:Gem::Dependency
39
+ name: yard
40
+ requirement: &id003 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 0.6.0
46
+ type: :development
47
+ prerelease: false
48
+ version_requirements: *id003
49
+ - !ruby/object:Gem::Dependency
50
+ name: bundler
51
+ requirement: &id004 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ~>
55
+ - !ruby/object:Gem::Version
56
+ version: 1.0.0
57
+ type: :development
58
+ prerelease: false
59
+ version_requirements: *id004
60
+ - !ruby/object:Gem::Dependency
61
+ name: jeweler
62
+ requirement: &id005 !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ~>
66
+ - !ruby/object:Gem::Version
67
+ version: 1.5.2
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: *id005
71
+ description: Restricts requests to specific IP addresses and ranges for specified paths
72
+ email: team@phatworx.de
73
+ executables: []
74
+
75
+ extensions: []
76
+
77
+ extra_rdoc_files:
78
+ - LICENSE.txt
79
+ - README.rdoc
80
+ files:
81
+ - .document
82
+ - .rspec
83
+ - Gemfile
84
+ - Gemfile.lock
85
+ - LICENSE.txt
86
+ - README.rdoc
87
+ - Rakefile
88
+ - VERSION
89
+ - init.rb
90
+ - lib/rack_ip_restrictor.rb
91
+ - lib/rack_ip_restrictor/config.rb
92
+ - lib/rack_ip_restrictor/ip_group.rb
93
+ - lib/rack_ip_restrictor/middleware.rb
94
+ - lib/rack_ip_restrictor/restriction.rb
95
+ - rack_ip_restrictor.gemspec
96
+ - spec/rack_ip_restrictor_spec.rb
97
+ - spec/rule_set_spec.rb
98
+ - spec/spec_helper.rb
99
+ has_rdoc: true
100
+ homepage: http://github.com/phatworx/rack_ip_restrictor
101
+ licenses:
102
+ - MIT
103
+ post_install_message:
104
+ rdoc_options: []
105
+
106
+ require_paths:
107
+ - lib
108
+ required_ruby_version: !ruby/object:Gem::Requirement
109
+ none: false
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ hash: -1851724760224035934
114
+ segments:
115
+ - 0
116
+ version: "0"
117
+ required_rubygems_version: !ruby/object:Gem::Requirement
118
+ none: false
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: "0"
123
+ requirements: []
124
+
125
+ rubyforge_project:
126
+ rubygems_version: 1.6.2
127
+ signing_key:
128
+ specification_version: 3
129
+ summary: IP restriction middleware
130
+ test_files:
131
+ - spec/rack_ip_restrictor_spec.rb
132
+ - spec/rule_set_spec.rb
133
+ - spec/spec_helper.rb