sinatra-bouncer 0.9 → 1.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.
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