#20 Restricting Access
Restricting Access
In the last episode we created links to create, edit and destroy episodes on the ASCIIcasts web site. The links work, but a little too well as they can be clicked by anyone who visits the site.
The episodes list page with the admin links visible to all users.
What we need to do is to restrict the links to only those users who have permission to edit the episodes. We’ll edit our episode partial so that it only renders the edit
and destroy
links if a method called admin?
returns true. (We’ll do the same to the new
link, but not show the code here.)
<li> <p class="episodeId"><%= episode.episode_id %></p> <h3><%= link_to episode.title, episode_path(episode.identifier) %></h3> <p class="summary"><%= episode.summary %></p> <p class="tagList"> Tags: <% episode.tags.each do |tag| %><%= link_to tag.title, tag_path(tag.title) %><% end %> </p> <% if admin? %> <p class="adminActions"> <%= link_to "Edit", edit_episode_path(episode) %> <%= link_to "Destroy", episode_path(episode), :confirm => "Are you sure?", :method => :delete %> </p> <% end %> </li>
The episode partial with the admin?
check wrapping the edit and destroy links.
Next we need to write the admin?
method, but where should it go? As we’re calling the method from a view, the immediately obvious place is in the application helper file, but we would like it to be available in controllers too, so we’ll put in into the application controller instead.
class ApplicationController < ActionController::Base helper_method :admin? protected def admin? false end end
The admin?
Method Added To The ApplicationController
.
For now, our admin?
method will just return false
, (we’ll implement it fully in the next episode). As we also want to use it in our views we’ve used the helper_method
method which makes it available from view code.
Nearly There
Now that we’ve written our admin?
method, our links are now hidden from non-admin users. There is still a problem though: anyone can still visit the admin pages directly and add or edit episodes that way. We can fix this by using a before_filter
.
class EpisodesController < ApplicationController before_filter :authorize, :except => [:index, :show ] def index @episodes = Episode.find(:all) end # show, new, create, edit, update and destroy methods hidden. end
The episodes controller (with the method bodies removed).
The before_filter
above will execute a method called authorize
before any method in our controller is called, except for the index
and show
methods. Now we’ll need to write the authorize
method. We’ll put it into the application controller so that it’s available to all controllers.
class ApplicationController < ActionController::Base helper_method :admin? protected def admin? false end def authorize unless admin? flash[:error] = “Unauthorized access” redirect_to home_path false end end end
The ApplicationController
with the authorize
method added.
The method checks that the user is an administrator and, if not, shows a flash method and redirects to the home page. Finally it returns false
so that no other actions are executed. Now, if we try to visit the new episode page we’re redirected to the home page. Alternatively, if we didn’t want unauthorized users to know the page exists we could throw a 404 (Page Not Found) error instead.
#TODO:
Our admin system is almost there but we still need to implement the admin?
method. We’ll show you how to do this in the next episode.