#20
Apr 18

Restricting Access

In this second part of the series on administration, you will learn how to lock down the site to keep the public from accessing the administration features.
Download (18.6 MB, 4:32)
alternative download for iPod & Apple TV (8.3 MB, 4:32)
<!-- episodes/index.rhtml -->
<% if admin? %>
  <%= link_to 'New Episode', new_episode_path %>
<% end %>
# controllers/application.rb
helper_method :admin?

protected

def admin?
  false
end

def authorize
  unless admin?
    flash[:error] = "unauthorized access"
    redirect_to home_path
    false
  end
end

# episodes_controller.rb
before_filter :authorize, :except => :index

15 comments:

Maledictus May 26, 2007 at 14:46

Doesn't the before_filter need to return true in the other case in order to normally proceed the request?


Ryan Bates May 26, 2007 at 23:48

Good question. It's not necessary because it continues as normal if it returns nil (which it will if the condition isn't met). The only time it stops is if it returns false.


Jack Wall May 30, 2007 at 15:03

flash[:error] does not work unless it is matched in the view layout, just in case anyone has issues getting the error message to show


Brian Jun 25, 2007 at 20:24

I follow the tutorial but i can login even i type wrong password.

How to fix?


Brian Jun 25, 2007 at 21:59

Hi i added the

<% admin? %>

<% end % >
it works great but when i combine it with the super simple authentication then the "must hidden" is not hidden.

any idea?

thanks


Brian Jun 25, 2007 at 22:10

@ryan bates

hi, i already fix my error.. sorry i didn't see the "==" in the password for the password is equals equals.

now its working and my next step is to connect ito database when i have users table.

Thanks =)


Piotr MÄ…sior Sep 24, 2007 at 13:43

If God would exists it will be you... very thanks for this screencast.

regards


jocelyn Dec 12, 2007 at 00:12

hi ryan,

i was just wondering if you have idea where i can get a dummy's guide for different levels of authorisation.

like some people will be able to CRUD,
some write only, some read only.

i'm very new to RoR sadly

thanks in advance!


cover Dec 25, 2007 at 03:04

@jocelyn

I'd add a string "level" column to each user. In that you could save for e.g "Writer", "Reader", "Editor", "Admin", and others you need. Then when you just need to add some controls as you do for the admin area. For e.g.
if current_user.writer?
<show form to write>
end

and the writer? method would be like this:
def writer?
current_user.level == "Writer"
end

Be aware of the level, if the user can choose her level pay attention she don't select the Admin level.


Jean-Marc Feb 29, 2008 at 15:53

I still have not resolved that question in my mind... if someones accesses a URL they should not, is redirecting the correct action?

I mean, it indicates your application will respond again and again to it.

On one project I did I simply determined to return a 404 (not found) when a protected resource was accessed. Indicating to the client they should not come back to that URI.

You got your thoughts on this dilemma?


Ryan Bates Mar 01, 2008 at 15:36

@Jean, I think returning 404 is an excellent solution, especially if you have a User model setup. You can then fetch resources through the user model and rails will handle the 404 automatically for you. For example, let's say a User has many Projects and you only want the user to have access to his own project. In the controller show action you can do this:

current_user.projects.find(params[:id])

This way the user can only fetch the project he owns. If he doesn't own it, he will receive a 404.


Ches Martin Apr 11, 2008 at 19:08

@Jean and Ryan,

Strictly speaking, you _really_ should be returning a 403 in those cases. There *is* as a resource there, it's just forbidden to that user (or role, or what have you).

The simple way to do this is Rails is:

head :forbidden

Nick Kallen has shown a nice pattern[1] for doing this type of thing consistently across your app, using Rails' rescue_action method.

In reality you might want to override rescue_action_in_public instead -- check the API docs to get more of an idea of how these methods work, like how to make sure you can still render a custom error file.

Thanks for all the great Railscasts, Ryan.

[1] https://blabs.pivotallabs.com/users/nick/blog/articles/272-access-control-permissions-in-rails


dazza Apr 22, 2008 at 07:52

great tips...

I added logged_in? to admin? to stop nil object errors...

def admin?
logged_in? && current_user.login == "admin"
end


dazza Apr 22, 2008 at 18:26

woop...

I keep getting a major loop happening between the before_filter in my root controller...and the app controller authorize function, because if the filter chain is halted due to the admin not being logged in, the redirect is back to my root controller, which then calls the authorize function from the before filter...thus creating a loop...

so to remedy...this, from authorize
I redirect to the /sessions/new which is fine...but now every route /url is redirected there ... even though I have an :except in my before filter

any ideas?

cheers

dion


dazza Apr 22, 2008 at 18:40

fixed...sorry for the spam

before_filter :my_authenticate , :except => [:index, :show]

Add your comment:

(required)

(not displayed)

(SKIP THIS ONE)


(required)

subscribe:
sponsored by:
if you want to help:
required:
Get Quicktime Player