There are parts of your site that you only want certain people to be able to access and I'll use this post to walk through the steps of adding an admin to the MyFLiX site on the Tealeaf Academy Course. I want to give that admin the authority to add a video on the site but regular users should not be able to this.
First up I need to add an admin column to my users table:
rails g migration add_admin_to_users
then write the migration:
class AddAdminToUsers < ActiveRecord::Migration
def change
add_column :users, :admin, :boolean
end
end
followed by rake db:migrate
.
I want this to add the video with the link /admin/add_video
so within routes.rb
I need to add a namespace:
namespace :admin do
get '/add_video', to: 'videos#new'
resources :videos, only: [:create]
end
Name spacing like this is really useful to stop controllers getting too large especially if you have lots of different roles on your site like admin, moderator, etc. With it name spaced each role can have their own controller for the site features you need to protect.
With that done I need a new controller under controllers/admin/videos.rb
which will look like:
class Admin::VideosController < AdminsController
def new
@video = Video.new
end
def create
end
end
Note that I am inheriting from AdminsController
rather than the usual ApplicationController
. The AdminsControlller
will be as follows:
class AdminsController < ApplicationController
before_filter :require_user
before_filter :require_admin
private
def require_admin
unless current_user.admin?
flash[:danger] = "You do not have access to that area."
redirect_to root_path
end
end
end
I already have before_filter :require_user
defined in ApplicationController
but I need to add the require_admin
method. The reason for inheriting from AdminsController
is because I want to ensure that I never forget to add the before filter (very important that ordinary users never access this area) and by inheriting from AdminsController
this will happen automatically so need for me to worry about it.
In addition to the controller I need to add a view file under views/admin/videos/new.html.haml
.
Now I can go to the rails console and make one of my users an admin:
user = User.first
user.update_column(:admin, true)
Obviously there should be tests to back this up and that is mainly straightforward so I didn't cover it but I did learn an interesting feature of testing in this lesson.
In my project I'm using Fabricator to create my user objects like so:
Fabricator(:user) do
email_address { Faker::Internet.email }
password { Faker::Internet.password(6) }
full_name { Faker::Name.name }
admin false
end
and I also use a macro to set the current user in the system:
def set_current_user_session
valid_user = Fabricate(:user)
session[:user_id] = valid_user.id
end
This works well for ordinary users but I need the session to specify that the user is also admin so I used another macro:
def set_current_admin_session
valid_user = Fabricate(:admin)
session[:user_id] = valid_user.id
end
This time I'm fabricating an admin which I do not yet have defined. Interestingly I can make my admin inherit from my user fabricator:
Fabricator(:admin, from: :user) do
admin true
end
This way the admin gets the email_address
, password
and full_name
from user but alters admin
.
That's it for this post, fairly straight forward but handy to know.