- Understand how to create an Ability class.
- Learn how to model permissions in the database.
- Prevent users from accessing certain actions from the controller.
- Prevent users from seeing certain pieces of the view.
We're going to learn how to integrate CanCanCan into a Rails application. Our authorization model for this example will be a message board for secret notes.
- Create a
User
model and migration with attributesname
, aString
- We're setting aside configuring passwords with
has_secure_password
in this lab. To include that would bring in details around managing session etc. which makes CanCanCan harder to understand. In a real application, you want authentication fromhas_secure_password
and BCrypt as well as authorization from CanCanCan.
- Create a
Note
model and migration with attributescontent
, aString
user_id
, an integer pointing to their creatingUser
'sid
.
- Create a
Viewer
model and migrationviewer
is a join betweennotes
andusers
and will thus have their foreign keys (user_id
,note_id
) asInteger
attributes
- Boilerplate code. This lab has certain assumptions, the following should be put into your model definitions
# user.rb
has_many :viewers
has_many :readable, through: :viewers, source: :note
# note.rb
belongs_to :user
has_many :viewers
has_many :readers, through: :viewers, source: :user
-
When we create a new note, we'll want a form that takes in a comma-separated list of usernames which represent who that note is visible to. To make certain operations easier, we want to create two utility methods:
visible_to
- Takes no arguments
- Returns the readers'
name
String
s, joined by a comma (with no space!) visible_to=(comma_string)
- Takes one argument, a
String
, joined by a comma (with possible spaces!) - Assigns readers based on finding the
User
s whose names match the names extracted fromcomma_string
. - Returns the readers'
name
String
s, joined by a comma (with no space!)
- Takes one argument, a
-
You should use the same principles of mass assignment to transfer parameters from the controllers to the model. Use the tests as your guide.
-
Speaking of controllers, create them.
- We'll need a
NotesController
at the very least. - Any other controllers you need to achieve the goal
- We'll need a
-
Add CanCanCan to your Gemfile and
bundle install
-
Generate a skeleton
Ability
model withrails g cancan:ability
- Write authorization rules in the
Ability
model. This is challenging. Consult the documentation here - The rules are a little bit tricky because you have to look through an association to figure out if a user can read a note. You'll want to use a block condition, like this:
- Write authorization rules in the
can :read, Note do |note|
# TODO
end
- To resolve the TODO, think about the following facts
- CanCanCan gives you a
user
variable that's "visible" inside thecan
block - Inside the block you have access to a
note
variable - What's the relationship between a
Note
and aUser
. What associations or methods are present that will help you determine whether theUser
should read theNote
? You can use enumerables or loops to return atruthy
value which tells Rails "permission granted."
- CanCanCan gives you a
Sitepoint - CanCanCan: The Rails Authorization Dance
View Cancan Lab on Learn.co and start learning to code for free.