sinatra-bouncer 0.9 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,24 +1,78 @@
1
- #Bouncer
2
- Simple authorization permissions plug for Sinatra.
3
-
4
- ## Prerequisites
5
- Bouncer requires [Sinatra](http://www.sinatrarb.com/), and [ruby 1.9.3](https://www.ruby-lang.org/en/documentation/installation/).
1
+ #Sinatra::Bouncer
2
+ Simple authorization permissions extension for Sinatra.
6
3
 
7
4
  ## Installation
8
5
 
9
- ###Gemfile
10
- ```
6
+ **Prerequisites**
7
+
8
+ Bouncer requires [Sinatra](http://www.sinatrarb.com/), and [ruby 1.9.3](https://www.ruby-lang.org/en/documentation/installation/).
9
+
10
+ **Gemfile**
11
+ ```ruby
11
12
  gem 'sinatra-bouncer'
12
13
  ```
13
14
 
14
- ### Command Line
15
- ```
15
+ **Command Line**
16
+ ```sh
16
17
  gem install sinatra-bouncer
17
18
  ```
18
19
 
19
20
  ##Usage
21
+ ###Step 1: Require/Register Bouncer
22
+
23
+ **Sinatra Classic**
24
+ ```ruby
25
+ require 'sinatra'
26
+ require 'sinatra/bouncer'
27
+
28
+ # ... routes and other config
20
29
  ```
30
+
31
+ **Modular**
32
+ ```ruby
33
+ require 'sinatra/base'
21
34
  require 'sinatra/bouncer'
22
35
 
23
- register Sinatra::bouncer
24
- ```
36
+ class MyApp < Sinatra::Base
37
+ register Sinatra::Bouncer
38
+
39
+ # ... routes and other config
40
+ end
41
+ ```
42
+
43
+ ###Step 2: Declare Bouncer Rules
44
+
45
+ #### allow
46
+ Bouncer is stored in Sinatra's `settings` object, under `settings.bouncer`.
47
+
48
+ By default, Bouncer will reject any request that either:
49
+ * has no rule associated with it, or
50
+ * has no associated rule that returns `true`
51
+
52
+ Declare rules by calling `bouncer.allow` and providing a rule block. Rule blocks **must return an explicit boolean** (ie. `true` or `false`) to avoid any accidental truthy values creating unwanted access.
53
+
54
+ ```ruby
55
+ bouncer.allow('/user_posts_blog') do
56
+ # calculate and return some boolean result
57
+ end
58
+ ```
59
+
60
+ ####allow(:all)
61
+ `allow(:all)` will match any path.
62
+
63
+ ```ruby
64
+ allow(:all) do
65
+ # assuming a current_user helper to load the user object (like with warden)
66
+ current_user.admin?
67
+ end
68
+ ```
69
+
70
+ ####always_allow
71
+ `always_allow(...)` is shorthand for `allow(..) { true }`.
72
+
73
+ ```ruby
74
+ always_allow('/login') # Anyone can access this path
75
+ ```
76
+
77
+ ###Customization
78
+ The default bounce acion is to `halt 401`. Call `bounce_with` with a block to change that behaviour.
@@ -0,0 +1,107 @@
1
+ #--
2
+ # Copyright (c) 2014 Tenjin Inc.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ module Sinatra
25
+ module Bouncer
26
+ def self.registered(base_class)
27
+ base_class.extend ExtensionMethods
28
+
29
+ base_class.set :bouncer, BasicBouncer.new
30
+
31
+ base_class.before do
32
+ unless settings.bouncer.allows? request.path
33
+ settings.bouncer.bounce(self)
34
+ end
35
+ end
36
+ end
37
+
38
+ module ExtensionMethods
39
+ def bounce_with(&block)
40
+ bouncer.bounce_with = block
41
+ end
42
+ end
43
+
44
+ class BasicBouncer
45
+ attr_accessor :bounce_with
46
+
47
+ def initialize
48
+ @rules = Hash.new do |rules_hash, key|
49
+ rules_hash[key] = []
50
+ end
51
+ end
52
+
53
+ def always_allow(paths)
54
+ self.allow(paths) do
55
+ true
56
+ end
57
+ end
58
+
59
+ def allow(paths, &block)
60
+ unless block
61
+ raise Sinatra::Bouncer::BouncerError.new('You must provide a block to #allow. If you wish to always allow, either return true or use #always_allow instead')
62
+ end
63
+
64
+ paths = [paths] unless paths.is_a? Array
65
+
66
+ paths.each do |path|
67
+ @rules[path] << block
68
+ end
69
+ end
70
+
71
+ def allows?(path)
72
+ rules = @rules[:all] + @rules[path]
73
+
74
+ # rules = @rules[path]
75
+
76
+ rules.any? do |rule_block|
77
+ ruling = rule_block.call
78
+
79
+ if ruling == true || ruling == false
80
+ ruling
81
+ else
82
+ source = rule_block.source_location.join(':')
83
+ raise BouncerError.new("Rule block at does not return explicit true/false.\n\n"+
84
+ "Rules must return explicit true or false to prevent accidental truthy values.\n\n"+
85
+ "Source: #{source}\n")
86
+ end
87
+ end
88
+ end
89
+
90
+ def bounce(instance)
91
+ if bounce_with
92
+ bounce_with.call(instance)
93
+ else
94
+ instance.halt 401
95
+ end
96
+ end
97
+ end
98
+
99
+ class BouncerError < StandardError
100
+
101
+ end
102
+ end
103
+
104
+ if defined? register
105
+ register Bouncer
106
+ end
107
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sinatra-bouncer
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.9'
4
+ version: 1.0.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,8 +10,24 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2015-05-19 00:00:00.000000000 Z
13
+ date: 2015-05-20 00:00:00.000000000 Z
14
14
  dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: sinatra
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ! '>='
29
+ - !ruby/object:Gem::Version
30
+ version: '0'
15
31
  - !ruby/object:Gem::Dependency
16
32
  name: simplecov
17
33
  requirement: !ruby/object:Gem::Requirement
@@ -49,17 +65,17 @@ dependencies:
49
65
  requirement: !ruby/object:Gem::Requirement
50
66
  none: false
51
67
  requirements:
52
- - - ! '>='
68
+ - - ~>
53
69
  - !ruby/object:Gem::Version
54
- version: '0'
70
+ version: 1.3.19
55
71
  type: :development
56
72
  prerelease: false
57
73
  version_requirements: !ruby/object:Gem::Requirement
58
74
  none: false
59
75
  requirements:
60
- - - ! '>='
76
+ - - ~>
61
77
  - !ruby/object:Gem::Version
62
- version: '0'
78
+ version: 1.3.19
63
79
  - !ruby/object:Gem::Dependency
64
80
  name: capybara
65
81
  requirement: !ruby/object:Gem::Requirement
@@ -92,22 +108,6 @@ dependencies:
92
108
  - - ! '>='
93
109
  - !ruby/object:Gem::Version
94
110
  version: '0'
95
- - !ruby/object:Gem::Dependency
96
- name: factory_girl
97
- requirement: !ruby/object:Gem::Requirement
98
- none: false
99
- requirements:
100
- - - ~>
101
- - !ruby/object:Gem::Version
102
- version: '4.0'
103
- type: :development
104
- prerelease: false
105
- version_requirements: !ruby/object:Gem::Requirement
106
- none: false
107
- requirements:
108
- - - ~>
109
- - !ruby/object:Gem::Version
110
- version: '4.0'
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: parallel_tests
113
113
  requirement: !ruby/object:Gem::Requirement
@@ -134,9 +134,7 @@ files:
134
134
  - Gemfile
135
135
  - MIT-LICENSE
136
136
  - README.md
137
- - lib/bouncer.rb
138
- - lib/contexts/roles/.gitkeep
139
- - lib/models/.gitkeep
137
+ - lib/sinatra/bouncer.rb
140
138
  homepage: http://www.tenjin.ca
141
139
  licenses: []
142
140
  post_install_message:
data/lib/bouncer.rb DELETED
@@ -1,37 +0,0 @@
1
- #--
2
- # Copyright (c) 2014 Tenjin Inc.
3
- #
4
- # Permission is hereby granted, free of charge, to any person obtaining
5
- # a copy of this software and associated documentation files (the
6
- # "Software"), to deal in the Software without restriction, including
7
- # without limitation the rights to use, copy, modify, merge, publish,
8
- # distribute, sublicense, and/or sell copies of the Software, and to
9
- # permit persons to whom the Software is furnished to do so, subject to
10
- # the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be
13
- # included in all copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
- # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
- # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
- # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
- # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
- #++
23
-
24
- require 'pathname'
25
- # require 'dirt/core'
26
- # require 'active_support'
27
-
28
- app_dir = Pathname.new(__FILE__).dirname
29
-
30
- # require ALL the files!
31
- Dir["#{app_dir}/**/*.rb"].reject { |f| f.include?('/faces/') || f.include?('/tests/') }.each do |file|
32
- require file
33
- end
34
-
35
- # module Dirt
36
- # PROJECT_ROOT = Pathname.new(File.dirname(__FILE__) + '/..').realpath
37
- # end
File without changes
data/lib/models/.gitkeep DELETED
File without changes