#20 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
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
admin? Method Added To The
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.
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
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).
before_filter above will execute a method called
authorize before any method in our controller is called, except for the
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
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.
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.