homeASCIIcasts

20: Restricting Access 

(view original Railscast)

Other translations: It Es Pt Fr

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 it 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.