In this article, we will create two roles for the users: the Admin role and Normal_User role. Users with the Admin role should have access to create and modify books on the website, while normal_users should only be able to view the books.
We use the Rolify and CanCanCan gems to help us implement authorization. To start this, go into the console and type:
rails g rolify Role User rails generate cancan:ability rake db:migrate
Then go into /app/models/Roles.rb and make sure that it looks like this: https://gist.github.com/mt9304/ef8fd420d43ecdd442e9c418c6667243
Now we can go into our /db/seeds.rb file and add some roles, books, and sample users.
The seeds.rb file should look like this: https://gist.github.com/mt9304/c67f4e862fedfaa01c47e9934f5663c9
Let’s erase our database and start fresh by typing:
rake db:drop db:create db:migrate
We can then run the commands in the seeds.rb file by going into our terminal and typing:
The seeds.rb file are just a list of database related actions that you want to perform to fill up the database with default items. This way you don’t have to go into the Rails console or database to manually enter values each time you want to reset your database. In this seeds file, we created 2 roles, 2 users, and made a loop that created 5 sample book entries.
Opening the Database
You can check to see if these values were entered into the database successfuly by running the following command to open your database:
To browse a table, right click on it and click on Browse Table. The books table should have 5 entries, Roles should have 2, Users 2, and User_Roles.
The ‘roles’ table should include the roles that we created, admin and normal_user. Each of these should be associated with an id such as 1 and 2. Each user in the ‘users’ table should also have an id associated with it. The ‘user_roles’ table should have a column called user_id and role_id. This is the table that lets the application know which users (their ids) are associated with which roles (their ids). In this case, it should say that User with an id of 1 (the admin user we created) should have the role with an id of 1 (the admin role).
Now we can begin to implement authorization by permitting certain actions. Lets start by going into the /app/models/user.rb file and add some role checking functions:
def admin? has_role?(:admin) end def normal_user? has_role?(:normal_user) end
The user.rb file should look like this: https://gist.github.com/mt9304/1d2e6a8bfeeb17719bc54320317b221f
These functions allow use to check if a user has a certain role. We can use this in the /app/models/ability.rb file which helps use define what each user can do on the site. Open up the ability.rb file and edit it so that it looks like this: https://gist.github.com/mt9304/f6aaa6e0b839aaf35450a85105728c14
In this case, we will allow users to view and create new books, admins can manage (create, delete, edit, read) everything, and unauthenticated users will only be able to read. For more information on defining abilities, please visit: https://github.com/CanCanCommunity/cancancan/wiki/Defining-Abilities
Now we just have to go into our /app/controllers/api/books_controller.rb file to make sure our controller is checking for permissions before allowing any actions to be performed. At the top (under class BooksController and above the index method), add the following:
load_and_authorize_resource before_action :authenticate_user!, except: [:index]
The controller should now look like this: https://gist.github.com/mt9304/f8deb96abb3acc0f64d30c47716143e5
The before_action line will direct users to the login screen if they try to access any method in the books controller except for :index. You can test this out by logging out and browsing to localhost:3000/api/books to see the list of books (this URL is the :index function). Now try to visit localhost:3000/api/books/1 (the :show function) and it should redirect you to the login page. Once you login, you should be able to see the particular book with 1 as the id.
After this, let’s open up /app/controllers/application_controller.rb and add these lines into the class:
rescue_from CanCan::AccessDenied do |exception| redirect_to root_url end
This will redirect the user to the home page when they try to do something that their user role is not permitted to do. Now we have a basic authorization process for the website!
Right now we can test out the read/get functions like :index and :show, but we haven’t went over the ways of put and post options (creating, deleting, or editing). We will implement these functions in the next article where we implement React for the front-end of the website.