README.md in canner-0.2.2 vs README.md in canner-0.3.0
- old
+ new
@@ -1,9 +1,10 @@
## Canner
[![Code Climate](https://codeclimate.com/github/jacklin10/canner/badges/gpa.svg)](https://codeclimate.com/github/jacklin10/canner)
[![Build Status](https://travis-ci.org/jacklin10/canner.svg?branch=master)](https://travis-ci.org/jacklin10/canner)
+[![Gem Version](https://badge.fury.io/rb/canner.svg)](http://badge.fury.io/rb/canner)
Canner is an authorization gem heavily modeled after Pundit.
Canner's intention is to provide you a framework for authorization that has little to no magic.
Your canner policies can be as simple or as complicated as your app requires.
@@ -128,11 +129,11 @@
Also if your policy changes at some point its a one place fix.
### can?
-You use the can method to determine if the current_user is able to access an action or resource.
+You use the can? method to determine if the current_user is able to access an action or resource.
The example above uses a straightforward case statement to determine if the current_user can
access the current action or resource.
The symbols in the when portion of the case match your typical actions in the example but they
@@ -164,10 +165,74 @@
end
```
in your base_policy's `can?` method
+### instance_can?
+
+You use the instance_can? method to determine if the current_user is able to modify a particular instance
+of an object.
+
+For example, if a user who belongs to company A wants to edit a particular item they maybe end up here:
+
+```
+/items/3/edit
+```
+
+Normal stuff. The user changes the item price and moves on.
+
+But now we have another user who decides they want to see what happens when they manually change the url:
+
+```
+/items/13/edit
+```
+
+If you don't defend against this the user would be granted access to edit item with id=13 which
+belongs to a different company.
+
+The instance_can? method helps in these situations.
+
+In your items controller for the **edit, update and destroy** methods add something like:
+
+``` ruby
+@item = Item.find params[:id]
+instance_can? :manage, :item, @item
+```
+
+Your item_policy.rb will have something like:
+
+``` ruby
+def instance_can?(item)
+ case @method
+ when :manage
+ return @current_user.company == item.company
+ else
+ false
+ end
+end
+```
+
+Now if a user attempts to edit an item for another company they will see the canner access denied message.
+
+Your policy can be more complex if needed. Canner is just a framework so you can get as creative as you want
+just so long as you eventually return true or false.
+
+For example, maybe your admin user is allowed to edit any items? You could do something like this:
+``` ruby
+def instance_can?(item)
+ case @method
+ when :manage
+ return has_role?(:admin) ? true : @current_user.company == item.company
+ else
+ false
+ end
+end
+```
+
+You can enforce that your methods check for this just like you can for canner_scope or can?.
+See 'Forcing Controller Authorization'
+
### Forcing Controller Authorization
You are able to force the use of controller authorization with canner.
I recommend you do this so you don't forget to wrap authorization about some of your resources.
@@ -184,16 +249,20 @@
```
Note the use of only here. You usually won't need the canner_scope on anything except
for the index to be strictly enforced.
-If you would like to skip for a particular controller just add:
+And finally, if you want to enforce that you are using instance_can? use something like:
``` ruby
-skip_filter :ensure_scope
+after_action :ensure_instance_checking, only: [:edit, :destroy, :update]
```
-And / Or
+
+If you would like to skip one of the enforcements for a specific controller add one or all of these:
+
``` ruby
+skip_filter :ensure_scope
skip_filter :ensure_auth
+skip_filter :ensure_instance_checking
```
### Handle Canner Authorization Failures
When a user does stumble onto something they don't have access to you'll want to politely