sinatra-bouncer 2.0.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +83 -66
- data/RELEASE_NOTES.md +17 -0
- data/lib/sinatra/bouncer/basic_bouncer.rb +34 -55
- data/lib/sinatra/bouncer/rule.rb +105 -21
- data/lib/sinatra/bouncer/version.rb +1 -1
- data/lib/sinatra/bouncer.rb +1 -12
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 849fed52904df15b1cc036685383f197e47aae52bef8283a81decc281fc95660
|
4
|
+
data.tar.gz: 3a3ba41d0d3c2ad70b1c4e48b81558213111d86a750717e2b8f44dea9072ca1f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d63e6a5437ef4d71e7183dce458241a8efaebace1c6f95e77766412f2faf2d5d490107a4e925588509dfb8e73b0c2e3a21064e73aae4cb3f98ae0c8465f19dd5
|
7
|
+
data.tar.gz: ca6d627ae51d9ecf6c88ffa21621117adb3af2eee6c83d14846f8ac7a5aa314f9ce4d2d10c30baf192e4a7c435f750bfb5b9bc3c37ed308ee4a5255a8df0eacf
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -5,35 +5,38 @@ routes are permitted based on your own logic.
|
|
5
5
|
|
6
6
|
## Big Picture
|
7
7
|
|
8
|
-
Bouncer
|
8
|
+
Bouncer's syntax looks like:
|
9
9
|
|
10
10
|
```ruby
|
11
|
-
|
11
|
+
# You can define roles to collect permissions together
|
12
|
+
bouncer.role :admins do
|
13
|
+
current_user&.admin?
|
14
|
+
end
|
15
|
+
|
16
|
+
bouncer.rules do
|
12
17
|
# Routes match based on one or more strings.
|
13
|
-
can get: '/',
|
14
|
-
|
15
|
-
|
18
|
+
anyone.can get: '/',
|
19
|
+
post: ['/user/sign-in',
|
20
|
+
'/user/sign-out']
|
16
21
|
|
17
22
|
# Wildcards match anything directly under that path
|
18
|
-
can get: '/lib/js/*'
|
23
|
+
anyone.can get: '/lib/js/*'
|
19
24
|
|
20
|
-
|
21
|
-
|
22
|
-
post: '/admin/actions/*' do
|
23
|
-
current_user.admin?
|
24
|
-
end
|
25
|
+
admins.can get: '/admin/*',
|
26
|
+
post: '/admin/actions/*'
|
25
27
|
|
26
28
|
# ... etc ...
|
27
29
|
end
|
28
|
-
|
29
30
|
```
|
30
31
|
|
31
|
-
|
32
|
+
### Features
|
32
33
|
|
33
34
|
Here's what this Gem provides:
|
34
35
|
|
35
36
|
* **Block-by-default**
|
36
37
|
* Any route must be explicitly allowed
|
38
|
+
* **Role-Oriented**
|
39
|
+
* The [DSL](https://en.wikipedia.org/wiki/Domain-specific_language) is constructed to be easily readable
|
37
40
|
* **Declarative Syntax**
|
38
41
|
* Straightforward syntax reduces complexity of layered permissions
|
39
42
|
* Keeps permissions together for clarity
|
@@ -44,7 +47,7 @@ Here's what this Gem provides:
|
|
44
47
|
* **Forced Boolean Affirmation**
|
45
48
|
* Condition blocks must explicitly return `true`, avoiding accidental truthy values
|
46
49
|
|
47
|
-
|
50
|
+
### Anti-Features
|
48
51
|
|
49
52
|
Bouncer intentionally does not support some concepts.
|
50
53
|
|
@@ -80,7 +83,7 @@ require 'sinatra/bouncer'
|
|
80
83
|
class MyApp < Sinatra::Base
|
81
84
|
register Sinatra::Bouncer
|
82
85
|
|
83
|
-
rules do
|
86
|
+
bouncer.rules do
|
84
87
|
# ... can statements ...
|
85
88
|
end
|
86
89
|
|
@@ -94,7 +97,7 @@ end
|
|
94
97
|
require 'sinatra'
|
95
98
|
require 'sinatra/bouncer'
|
96
99
|
|
97
|
-
rules do
|
100
|
+
bouncer.rules do
|
98
101
|
# ... can statements ...
|
99
102
|
end
|
100
103
|
|
@@ -103,57 +106,77 @@ end
|
|
103
106
|
|
104
107
|
## Usage
|
105
108
|
|
106
|
-
|
109
|
+
Define roles using the `role` method and provide each one with a condition block. Then call `rules` with a block that
|
110
|
+
uses your defined roles with the `#can` or `#can_sometimes` DSL methods to declare which
|
111
|
+
paths are allowed.
|
107
112
|
|
108
113
|
The rules block is run once as part of the configuration phase but the condition blocks are evaluated in the context of
|
109
|
-
the
|
110
|
-
request, which means you will have access to Sinatra helpers,
|
111
|
-
the `request` object, and `params`.
|
114
|
+
the request handler. This means they have access to Sinatra helpers, the `request` object, and `params`.
|
112
115
|
|
113
116
|
```ruby
|
114
117
|
require 'sinatra'
|
115
118
|
require 'sinatra/bouncer'
|
116
119
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
120
|
+
bouncer.role :members do
|
121
|
+
!current_user.nil?
|
122
|
+
end
|
123
|
+
|
124
|
+
bouncer.role :bots do
|
125
|
+
!request.get_header('X-CUSTOM-BOT').nil?
|
126
|
+
end
|
127
|
+
|
128
|
+
bouncer.rules do
|
129
|
+
# example: always allow GET requests to '/' and '/about'; and POST requests to '/sign-in'
|
130
|
+
anyone.can get: ['/', '/about'],
|
131
|
+
post: '/sign-in'
|
121
132
|
|
122
133
|
# example: logged in users can view (GET) member restricted paths and edit their account (POST)
|
123
|
-
|
124
|
-
|
125
|
-
|
134
|
+
members.can get: '/members/*'
|
135
|
+
members.can_sometimes post: '/members/edit-account' do
|
136
|
+
current_user && current_user.id == params[:id]
|
126
137
|
end
|
127
138
|
|
128
|
-
# example:
|
129
|
-
|
130
|
-
!request.get_header('X-CUSTOM_PROP').nil?
|
131
|
-
end
|
139
|
+
# example: require presence of arbitrary request header in the role condition
|
140
|
+
bots.can get: '/bots/*'
|
132
141
|
end
|
133
142
|
|
134
143
|
# ... Sinatra route declarations as normal ...
|
135
144
|
```
|
136
145
|
|
146
|
+
### Role Declarations
|
147
|
+
|
148
|
+
Roles are declared using the `#role` method in your Sinatra config. Each one must be provided a condition block that
|
149
|
+
must return exactly `true` when the role applies.
|
150
|
+
|
151
|
+
```ruby
|
152
|
+
# let's pretend that current_user is a helper that returns the user from Warden
|
153
|
+
bouncer.role :admins do
|
154
|
+
current_user&.admin?
|
155
|
+
end
|
156
|
+
```
|
157
|
+
|
158
|
+
> **Note:** There is a default role called `anyone` that is always declared for you.
|
159
|
+
|
137
160
|
### HTTP Method and Route Matching
|
138
161
|
|
139
|
-
Both `#can` and `#can_sometimes` accept
|
140
|
-
[HTTP methods](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods) as
|
162
|
+
Both `#can` and `#can_sometimes` accept symbol
|
163
|
+
[HTTP methods](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods) as keys
|
141
164
|
and each key is paired with one or more path strings.
|
142
165
|
|
143
166
|
```ruby
|
144
167
|
# example: single method, single route
|
145
|
-
can get: '/'
|
168
|
+
anyone.can get: '/'
|
146
169
|
|
147
170
|
# example: multiple methods, single route each
|
148
|
-
can get: '/',
|
149
|
-
|
171
|
+
anyone.can get: '/',
|
172
|
+
post: '/blog/action/save'
|
150
173
|
|
151
174
|
# example: multiple methods, multiple routes (using string array syntax)
|
152
|
-
can get: %w[/
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
175
|
+
anyone.can get: %w[/
|
176
|
+
/sign-in
|
177
|
+
/blog/editor],
|
178
|
+
post: %w[/blog/action/save
|
179
|
+
/blog/action/delete]
|
157
180
|
```
|
158
181
|
|
159
182
|
> **Note** Allowing GET implies allowing HEAD, since HEAD is by spec a GET without a response body. The reverse is not
|
@@ -161,55 +184,49 @@ can get: %w[/
|
|
161
184
|
|
162
185
|
#### Wildcards and Special Symbols
|
163
186
|
|
164
|
-
> **Warning** Always be cautious when using wildcards and special symbols to not accidentally open up pathways that
|
165
|
-
> should remain private.
|
166
|
-
|
167
187
|
Provide a wildcard `*` to match any string excluding slash. There is intentionally no syntax for matching wildcards
|
168
188
|
recursively, so nested paths will also need to be declared.
|
169
189
|
|
170
190
|
```ruby
|
171
191
|
# example: match anything directly under the /members/ path
|
172
|
-
can get: '/members/*'
|
192
|
+
members.can get: '/members/*'
|
173
193
|
```
|
174
194
|
|
175
|
-
There
|
176
|
-
|
177
|
-
1. `:any` will match any HTTP method.
|
178
|
-
2. `:all` will match all paths.
|
195
|
+
There is also a special symbol, `:all` that matches all paths. It is intended for rare use
|
196
|
+
with superadmin-type accounts.
|
179
197
|
|
180
198
|
```ruby
|
181
|
-
# this allows
|
182
|
-
can
|
183
|
-
|
184
|
-
# this allows GET on all paths
|
185
|
-
can get: :all
|
199
|
+
# this allows GET on all paths to those in the admin group
|
200
|
+
admins.can get: :all
|
186
201
|
```
|
187
202
|
|
203
|
+
> **Warning** Always be cautious when using wildcards and special symbols to avoid accidentally opening up pathways that
|
204
|
+
> should remain private.
|
205
|
+
|
188
206
|
### Always Allow: `can`
|
189
207
|
|
190
208
|
Any route declared with `#can` will be accepted without further challenge.
|
191
209
|
|
192
210
|
```ruby
|
193
|
-
rules do
|
211
|
+
bouncer.rules do
|
194
212
|
# Anyone can access this path over GET
|
195
|
-
can get: '/login'
|
213
|
+
anyone.can get: '/login'
|
196
214
|
end
|
197
215
|
```
|
198
216
|
|
199
217
|
### Conditionally Allow: `can_sometimes`
|
200
218
|
|
201
|
-
`can_sometimes`
|
202
|
-
|
203
|
-
`can_sometimes` takes a block that will be run once the path is attempted. This block **must return an explicit boolean
|
204
|
-
**
|
205
|
-
(ie. `true` or `false`) to avoid any accidental truthy values creating unwanted access.
|
219
|
+
`can_sometimes` takes a condition block that will be run once the path is attempted. This block **must return an
|
220
|
+
explicit boolean** (ie. `true` or `false`) to avoid any accidental truthy values creating unwanted access.
|
206
221
|
|
207
222
|
```ruby
|
208
|
-
|
209
|
-
|
223
|
+
bouncer.role :users do
|
224
|
+
!current_user.nil?
|
225
|
+
end
|
210
226
|
|
211
|
-
|
212
|
-
|
227
|
+
bouncer.rules do
|
228
|
+
users.can_sometimes post: '/user/save' do
|
229
|
+
current_user.id == params[:id]
|
213
230
|
end
|
214
231
|
end
|
215
232
|
```
|
@@ -217,7 +234,7 @@ end
|
|
217
234
|
### Custom Bounce Behaviour
|
218
235
|
|
219
236
|
The default bounce action is to `halt 403`. Call `bounce_with` with a block to specify your own behaviour. The block is
|
220
|
-
also run in a
|
237
|
+
also run in a Sinatra request handler context, so you can use helpers here as well.
|
221
238
|
|
222
239
|
```ruby
|
223
240
|
require 'sinatra'
|
data/RELEASE_NOTES.md
CHANGED
@@ -19,6 +19,23 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
|
19
19
|
|
20
20
|
* none
|
21
21
|
|
22
|
+
## [3.0.0] - 2023-11-21
|
23
|
+
|
24
|
+
### Major Changes
|
25
|
+
|
26
|
+
* Changed rules DSL to be role-oriented
|
27
|
+
* Removed the `:any` HTTP method wildcard
|
28
|
+
* Changed Sinatra API to require calling methods on bouncer object
|
29
|
+
* eg. `rules do ... end` should now be `bouncer.rules do ... end`
|
30
|
+
|
31
|
+
### Minor Changes
|
32
|
+
|
33
|
+
* none
|
34
|
+
|
35
|
+
### Bugfixes
|
36
|
+
|
37
|
+
* none
|
38
|
+
|
22
39
|
## [2.0.0] - 2023-11-13
|
23
40
|
|
24
41
|
### Major Changes
|
@@ -6,81 +6,60 @@ module Sinatra
|
|
6
6
|
module Bouncer
|
7
7
|
# Core implementation of Bouncer logic
|
8
8
|
class BasicBouncer
|
9
|
-
attr_accessor :
|
10
|
-
|
11
|
-
# Enumeration of HTTP method strings based on:
|
12
|
-
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods
|
13
|
-
# Ignoring CONNECT and TRACE due to rarity
|
14
|
-
HTTP_METHODS = %w[GET HEAD PUT POST DELETE OPTIONS PATCH].freeze
|
15
|
-
|
16
|
-
# Symbol versions of HTTP_METHODS constant
|
17
|
-
#
|
18
|
-
# @see HTTP_METHODS
|
19
|
-
HTTP_METHOD_SYMBOLS = HTTP_METHODS.collect do |http_method|
|
20
|
-
http_method.downcase.to_sym
|
21
|
-
end.freeze
|
22
|
-
|
23
|
-
# Method symbol used to match any method
|
24
|
-
WILDCARD_METHOD = :any
|
9
|
+
attr_accessor :rules_initializer
|
25
10
|
|
26
11
|
def initialize
|
27
|
-
@
|
28
|
-
[]
|
29
|
-
end
|
12
|
+
@rules = []
|
30
13
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
def can(**method_routes)
|
35
|
-
if block_given?
|
36
|
-
hint = 'If you wish to conditionally allow, use #can_sometimes instead.'
|
37
|
-
raise BouncerError, "You cannot provide a block to #can. #{ hint }"
|
14
|
+
role :anyone do
|
15
|
+
true
|
38
16
|
end
|
39
17
|
|
40
|
-
|
41
|
-
|
18
|
+
@rules_initializer = proc {}
|
19
|
+
@bounce_strategy = proc do
|
20
|
+
halt 403
|
42
21
|
end
|
43
22
|
end
|
44
23
|
|
45
|
-
def
|
46
|
-
|
47
|
-
|
48
|
-
raise BouncerError,
|
24
|
+
def rules(&block)
|
25
|
+
instance_exec(&block)
|
26
|
+
@rules.each do |rule|
|
27
|
+
raise BouncerError, 'rules block error: missing #can or #can_sometimes call' if rule.incomplete?
|
49
28
|
end
|
29
|
+
end
|
50
30
|
|
51
|
-
|
52
|
-
|
53
|
-
hint = "Must be one of: #{ HTTP_METHOD_SYMBOLS } or :#{ WILDCARD_METHOD }"
|
54
|
-
raise BouncerError, "'#{ method }' is not a known HTTP method key. #{ hint }"
|
55
|
-
end
|
56
|
-
|
57
|
-
paths = [paths] unless paths.respond_to? :collect
|
31
|
+
def can?(method, path, context)
|
32
|
+
method = method.downcase.to_sym unless method.is_a? Symbol
|
58
33
|
|
59
|
-
|
34
|
+
@rules.any? do |rule|
|
35
|
+
rule.allow? method, path, context
|
60
36
|
end
|
61
37
|
end
|
62
38
|
|
63
|
-
def
|
64
|
-
|
65
|
-
|
66
|
-
# HEAD requests are equivalent to GET requests without response
|
67
|
-
rulesets += @ruleset[:get] if method == :head
|
39
|
+
def bounce_with(&block)
|
40
|
+
@bounce_strategy = block
|
41
|
+
end
|
68
42
|
|
69
|
-
|
43
|
+
def bounce(instance)
|
44
|
+
instance.instance_exec(&@bounce_strategy)
|
45
|
+
end
|
70
46
|
|
71
|
-
|
72
|
-
|
47
|
+
def role(identifier, &block)
|
48
|
+
raise ArgumentError, 'must provide a role identifier to #role' unless identifier
|
49
|
+
raise ArgumentError, 'must provide a role condition block to #role' unless block
|
50
|
+
raise ArgumentError, "role called '#{ identifier }' already defined" if respond_to? identifier
|
73
51
|
|
74
|
-
|
52
|
+
define_singleton_method identifier do
|
53
|
+
add_rule(&block)
|
75
54
|
end
|
76
55
|
end
|
77
56
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
57
|
+
private
|
58
|
+
|
59
|
+
def add_rule(&block)
|
60
|
+
rule = Rule.new(&block)
|
61
|
+
@rules << rule
|
62
|
+
rule
|
84
63
|
end
|
85
64
|
end
|
86
65
|
|
data/lib/sinatra/bouncer/rule.rb
CHANGED
@@ -2,50 +2,122 @@
|
|
2
2
|
|
3
3
|
module Sinatra
|
4
4
|
module Bouncer
|
5
|
-
# Defines a
|
5
|
+
# Defines a RuleSet to be evaluated with each request
|
6
6
|
class Rule
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
# Enumeration of HTTP method strings based on:
|
8
|
+
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods
|
9
|
+
# Ignoring CONNECT and TRACE due to rarity
|
10
|
+
HTTP_METHODS = %w[GET HEAD PUT POST DELETE OPTIONS PATCH].freeze
|
11
|
+
|
12
|
+
# Symbol versions of HTTP_METHODS constant
|
13
|
+
#
|
14
|
+
# @see HTTP_METHODS
|
15
|
+
HTTP_METHOD_SYMBOLS = HTTP_METHODS.collect do |http_method|
|
16
|
+
http_method.downcase.to_sym
|
17
|
+
end.freeze
|
18
|
+
|
19
|
+
def initialize(&block)
|
20
|
+
raise ArgumentError, 'must provide a block to Bouncer::Rule' unless block
|
21
|
+
|
22
|
+
@routes = Hash.new do
|
23
|
+
[]
|
24
|
+
end
|
25
|
+
|
26
|
+
@conditions = [block]
|
27
|
+
end
|
28
|
+
|
29
|
+
def can_sometimes(**method_routes, &block)
|
30
|
+
if method_routes.empty?
|
31
|
+
raise ArgumentError,
|
32
|
+
'must provide a hash where keys are HTTP method symbols and values are one or more path matchers'
|
33
|
+
end
|
34
|
+
|
35
|
+
unless block
|
36
|
+
hint = 'If you wish to always allow, use #can instead.'
|
37
|
+
raise BouncerError, "You must provide a block to #can_sometimes. #{ hint }"
|
38
|
+
end
|
39
|
+
|
40
|
+
method_routes.each do |method, paths|
|
41
|
+
validate_http_method! method
|
42
|
+
|
43
|
+
paths = [paths] unless paths.respond_to? :collect
|
44
|
+
|
45
|
+
@routes[method] += paths.collect { |path| normalize_path path }
|
46
|
+
end
|
47
|
+
|
48
|
+
@conditions << block
|
49
|
+
end
|
12
50
|
|
13
|
-
|
51
|
+
def can(**method_routes)
|
52
|
+
if block_given?
|
53
|
+
hint = 'If you wish to conditionally allow, use #can_sometimes instead.'
|
54
|
+
raise BouncerError, "You cannot provide a block to #can. #{ hint }"
|
14
55
|
end
|
15
56
|
|
16
|
-
|
57
|
+
can_sometimes(**method_routes) do
|
58
|
+
true
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def allow?(method, path, context)
|
63
|
+
match_path?(method, path) && @conditions.all? do |condition|
|
64
|
+
rule_passes?(context, &condition)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def incomplete?
|
69
|
+
@routes.empty?
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def validate_http_method!(method)
|
75
|
+
return if HTTP_METHOD_SYMBOLS.include?(method)
|
76
|
+
|
77
|
+
raise BouncerError, "'#{ method }' is not a known HTTP method key. Must be one of: #{ HTTP_METHOD_SYMBOLS }"
|
17
78
|
end
|
18
79
|
|
19
80
|
# Determines if the path matches the exact path or wildcard.
|
20
81
|
#
|
21
82
|
# @return `true` if the path matches
|
22
|
-
def match_path?(
|
23
|
-
|
83
|
+
def match_path?(method, trial_path)
|
84
|
+
trial_path = normalize_path trial_path
|
24
85
|
|
25
|
-
|
86
|
+
matchers_for(method).any? do |matcher|
|
87
|
+
return true if matcher == :all
|
26
88
|
|
27
|
-
|
28
|
-
|
89
|
+
matcher_parts = matcher.split '/'
|
90
|
+
trial_parts = trial_path.split '/'
|
91
|
+
matches = matcher_parts.length == trial_parts.length
|
29
92
|
|
30
|
-
|
31
|
-
|
32
|
-
|
93
|
+
matcher_parts.each_index do |i|
|
94
|
+
allowed_segment = matcher_parts[i]
|
95
|
+
given_segment = trial_parts[i]
|
33
96
|
|
34
|
-
|
97
|
+
matches &= given_segment == allowed_segment || allowed_segment == '*'
|
98
|
+
end
|
99
|
+
|
100
|
+
matches
|
35
101
|
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def matchers_for(method)
|
105
|
+
matchers = @routes[method]
|
36
106
|
|
37
|
-
|
107
|
+
matchers += @routes[:get] if method == :head
|
108
|
+
|
109
|
+
matchers
|
38
110
|
end
|
39
111
|
|
40
112
|
# Evaluates the rule's block. Defensively prevents truthy values from the block from allowing a route.
|
41
113
|
#
|
42
114
|
# @raise BouncerError when the rule block is a truthy value but not exactly `true`
|
43
115
|
# @return Exactly `true` or `false`, depending on the result of the rule block
|
44
|
-
def rule_passes?(context)
|
45
|
-
ruling = context.instance_exec(
|
116
|
+
def rule_passes?(context, &rule)
|
117
|
+
ruling = context.instance_exec(&rule)
|
46
118
|
|
47
119
|
unless !ruling || ruling.is_a?(TrueClass)
|
48
|
-
source =
|
120
|
+
source = rule.source_location.join(':')
|
49
121
|
msg = <<~ERR
|
50
122
|
Rule block at does not return explicit true/false.
|
51
123
|
Rules must return explicit true or false to prevent accidental truthy values.
|
@@ -57,6 +129,18 @@ module Sinatra
|
|
57
129
|
|
58
130
|
!!ruling
|
59
131
|
end
|
132
|
+
|
133
|
+
def normalize_path(path)
|
134
|
+
if path == :all
|
135
|
+
path
|
136
|
+
else
|
137
|
+
if path.start_with?('/')
|
138
|
+
path
|
139
|
+
else
|
140
|
+
"/#{ path }"
|
141
|
+
end.downcase
|
142
|
+
end
|
143
|
+
end
|
60
144
|
end
|
61
145
|
end
|
62
146
|
end
|
data/lib/sinatra/bouncer.rb
CHANGED
@@ -34,20 +34,9 @@ module Sinatra
|
|
34
34
|
base_class.set :bouncer, BasicBouncer.new
|
35
35
|
|
36
36
|
base_class.before do
|
37
|
-
|
38
|
-
path = request.path.downcase
|
39
|
-
|
40
|
-
settings.bouncer.bounce(self) unless settings.bouncer.can?(http_method, path, self)
|
37
|
+
settings.bouncer.bounce(self) unless settings.bouncer.can?(request.request_method, request.path, self)
|
41
38
|
end
|
42
39
|
end
|
43
|
-
|
44
|
-
def bounce_with(&block)
|
45
|
-
bouncer.bounce_with = block
|
46
|
-
end
|
47
|
-
|
48
|
-
def rules(&block)
|
49
|
-
settings.bouncer.instance_exec(&block)
|
50
|
-
end
|
51
40
|
end
|
52
41
|
|
53
42
|
register Sinatra::Bouncer
|
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:
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tenjin Inc
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2023-11-
|
12
|
+
date: 2023-11-22 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: sinatra
|