canner 0.2.2 → 0.3.0
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 +4 -4
- data/README.md +73 -4
- data/lib/canner/version.rb +1 -1
- data/lib/canner.rb +13 -1
- metadata +3 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7b7de0bc3ce06cfa8e719a5b4cd3da5d8847007b
|
4
|
+
data.tar.gz: 25cb560b1410ca7661df5ef6c1baf77c0c5dba7e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e70bd029306bb3c7a4a6d4666d9452320dc7e43c284492173b243e1fbf0d860c0466e7ddc437a6827959a7a5d9e7f173cbf694817380f0f0ec5ff83a688c4aab
|
7
|
+
data.tar.gz: 4e70d8b65ab9f19a2665235dc9f7ed856e002a098648b900ddd9b60288b01f0885b058b0c14fc2175f2e52a0d42037087d34033fb990b893d1281d8ed0295392
|
data/README.md
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
[](https://codeclimate.com/github/jacklin10/canner)
|
4
4
|
[](https://travis-ci.org/jacklin10/canner)
|
5
|
+
[](http://badge.fury.io/rb/canner)
|
5
6
|
|
6
7
|
Canner is an authorization gem heavily modeled after Pundit.
|
7
8
|
|
@@ -130,7 +131,7 @@ Also if your policy changes at some point its a one place fix.
|
|
130
131
|
|
131
132
|
### can?
|
132
133
|
|
133
|
-
You use the can method to determine if the current_user is able to access an action or resource.
|
134
|
+
You use the can? method to determine if the current_user is able to access an action or resource.
|
134
135
|
|
135
136
|
The example above uses a straightforward case statement to determine if the current_user can
|
136
137
|
access the current action or resource.
|
@@ -166,6 +167,70 @@ end
|
|
166
167
|
|
167
168
|
in your base_policy's `can?` method
|
168
169
|
|
170
|
+
### instance_can?
|
171
|
+
|
172
|
+
You use the instance_can? method to determine if the current_user is able to modify a particular instance
|
173
|
+
of an object.
|
174
|
+
|
175
|
+
For example, if a user who belongs to company A wants to edit a particular item they maybe end up here:
|
176
|
+
|
177
|
+
```
|
178
|
+
/items/3/edit
|
179
|
+
```
|
180
|
+
|
181
|
+
Normal stuff. The user changes the item price and moves on.
|
182
|
+
|
183
|
+
But now we have another user who decides they want to see what happens when they manually change the url:
|
184
|
+
|
185
|
+
```
|
186
|
+
/items/13/edit
|
187
|
+
```
|
188
|
+
|
189
|
+
If you don't defend against this the user would be granted access to edit item with id=13 which
|
190
|
+
belongs to a different company.
|
191
|
+
|
192
|
+
The instance_can? method helps in these situations.
|
193
|
+
|
194
|
+
In your items controller for the **edit, update and destroy** methods add something like:
|
195
|
+
|
196
|
+
``` ruby
|
197
|
+
@item = Item.find params[:id]
|
198
|
+
instance_can? :manage, :item, @item
|
199
|
+
```
|
200
|
+
|
201
|
+
Your item_policy.rb will have something like:
|
202
|
+
|
203
|
+
``` ruby
|
204
|
+
def instance_can?(item)
|
205
|
+
case @method
|
206
|
+
when :manage
|
207
|
+
return @current_user.company == item.company
|
208
|
+
else
|
209
|
+
false
|
210
|
+
end
|
211
|
+
end
|
212
|
+
```
|
213
|
+
|
214
|
+
Now if a user attempts to edit an item for another company they will see the canner access denied message.
|
215
|
+
|
216
|
+
Your policy can be more complex if needed. Canner is just a framework so you can get as creative as you want
|
217
|
+
just so long as you eventually return true or false.
|
218
|
+
|
219
|
+
For example, maybe your admin user is allowed to edit any items? You could do something like this:
|
220
|
+
``` ruby
|
221
|
+
def instance_can?(item)
|
222
|
+
case @method
|
223
|
+
when :manage
|
224
|
+
return has_role?(:admin) ? true : @current_user.company == item.company
|
225
|
+
else
|
226
|
+
false
|
227
|
+
end
|
228
|
+
end
|
229
|
+
```
|
230
|
+
|
231
|
+
You can enforce that your methods check for this just like you can for canner_scope or can?.
|
232
|
+
See 'Forcing Controller Authorization'
|
233
|
+
|
169
234
|
### Forcing Controller Authorization
|
170
235
|
|
171
236
|
You are able to force the use of controller authorization with canner.
|
@@ -186,13 +251,17 @@ after_action :ensure_scope, only: :index
|
|
186
251
|
Note the use of only here. You usually won't need the canner_scope on anything except
|
187
252
|
for the index to be strictly enforced.
|
188
253
|
|
189
|
-
|
254
|
+
And finally, if you want to enforce that you are using instance_can? use something like:
|
190
255
|
``` ruby
|
191
|
-
|
256
|
+
after_action :ensure_instance_checking, only: [:edit, :destroy, :update]
|
192
257
|
```
|
193
|
-
|
258
|
+
|
259
|
+
If you would like to skip one of the enforcements for a specific controller add one or all of these:
|
260
|
+
|
194
261
|
``` ruby
|
262
|
+
skip_filter :ensure_scope
|
195
263
|
skip_filter :ensure_auth
|
264
|
+
skip_filter :ensure_instance_checking
|
196
265
|
```
|
197
266
|
|
198
267
|
### Handle Canner Authorization Failures
|
data/lib/canner/version.rb
CHANGED
data/lib/canner.rb
CHANGED
@@ -22,6 +22,7 @@ module Canner
|
|
22
22
|
|
23
23
|
class AuthNotUsedError < StandardError; end
|
24
24
|
class ScopeNotUsedError < StandardError; end
|
25
|
+
class InstanceNotProtectedError < StandardError; end
|
25
26
|
|
26
27
|
def auth_used
|
27
28
|
@auth_used ||= false
|
@@ -31,12 +32,17 @@ module Canner
|
|
31
32
|
@scope_used ||= false
|
32
33
|
end
|
33
34
|
|
35
|
+
def instance_checked
|
36
|
+
@instance_checked ||= false
|
37
|
+
end
|
38
|
+
|
34
39
|
# method_name - The controller action method that you are concerned with access
|
35
40
|
# target_model - Name of the object you are limiting access to. ( :user, :pet, :customer )
|
36
41
|
# target_obj - The instance obj for what you want to test. ( does user 1 have access to company 1?)
|
37
42
|
def instance_can?(method_name, target_model, target_obj)
|
43
|
+
@instance_checked = true
|
38
44
|
policy = canner_policy(method_name, target_model)
|
39
|
-
raise NotAuthorizedError.new("You do not have access to this #{target_model.capitalize}") unless policy.instance_can?(target_obj)
|
45
|
+
raise NotAuthorizedError.new("You do not have access to this #{target_model.to_s.humanize.capitalize}") unless policy.instance_can?(target_obj)
|
40
46
|
true
|
41
47
|
end
|
42
48
|
|
@@ -79,6 +85,12 @@ module Canner
|
|
79
85
|
true
|
80
86
|
end
|
81
87
|
|
88
|
+
def ensure_instance_checking
|
89
|
+
return if devise_controller? rescue false
|
90
|
+
raise AuthNotUsedError.new("Must use instance_can? method or exclude this action from the after_action") unless instance_checked
|
91
|
+
true
|
92
|
+
end
|
93
|
+
|
82
94
|
def canner_policy(method_name, target_model)
|
83
95
|
derive_class_name(target_model).constantize.new(canner_user, method_name, canner_branch)
|
84
96
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: canner
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joe Acklin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-04-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -158,11 +158,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
158
158
|
version: '0'
|
159
159
|
requirements: []
|
160
160
|
rubyforge_project:
|
161
|
-
rubygems_version: 2.4.
|
161
|
+
rubygems_version: 2.4.6
|
162
162
|
signing_key:
|
163
163
|
specification_version: 4
|
164
164
|
summary: Rails Auth
|
165
165
|
test_files:
|
166
166
|
- spec/canner_spec.rb
|
167
167
|
- spec/spec_helper.rb
|
168
|
-
has_rdoc:
|