San Diago
San Diago

Reputation: 1050

Rails: How to produce 404 or redirect upon undesired url exploitation?

I want to hide the urls for editing users and their profiles behind safer and meaningful urls. For instance, I want /user/13/edit to be /settings/account and /user/13/profile/edit to be /settings/profile.

I managed to achieve that, but for that I had to load the user information from the current_user bit from the session. Like so:

# users_controller
def edit
  @user = current_user
end

# profiles_controller
def edit
  @user = current_user
  @profile = @user.profile
end

But now, since I can't compare @user.id from the params with the current_user in the session, how can I stop the old urls (/user/13/edit and /user/13/profile/edit) from being exploitable? They always load the forms for the current user, so there's no harm done, but I'd be more comfortable if they just produced a 404 error or something.

Thanks in advance.

Upvotes: 2

Views: 1511

Answers (2)

Patrick Klingemann
Patrick Klingemann

Reputation: 9014

First of all, your authentication mechanism needs to set the current user.

routes.rb

map.account '/settings/account', :controller => 'user', :action => 'edit' 
map.profile '/settings/profile', :controller => 'user', :action => 'edit_profile'

map.resources :users, :only => [:edit, :update, :show],
              :member => { :edit_profile => :get, :update_profile, :put }

this produces the following routes:

/settings/account         (get)
/settings/profile         (get)
/users/:id                (get, put)
/users/:id/edit           (get)
/users/:id/edit_profile   (get)
/users/:id/update_profile (put)

users_controller.rb

before_filter :redirect_if_unauthorized

def edit
  @user = current_user
end

# profiles_controller
def edit
  @user = current_user
  @profile = @user.profile
end

protected

def redirect_if_unauthorized
  redirect_to some_path if params[:id] or current_user.nil?
end

Obviously some_path does not exist, you will have to create a page/path, etc. to display an error.

With this solution, you never display/manipulate a user based on params[:id], only the current_user saved by your authentication scheme.


I might also suggest looking at the declarative_authorization gem/plugin (Github, Railscast)

Upvotes: 1

the /edit urls still exist because i'm betting you have a map.resources in your routes.rb file for the user model. you can put a line higher than that in your routes.rb file that matches explicitly the edit lines you are looking to re-route and point them wherever you'd like.

Upvotes: 0

Related Questions