Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby on Rails: How to stop users changing url to view another user's page?

I've got it so that the show view on a customer's page links to all the orders that they have placed. When they click "Show", it takes them to the show view for that order. However, if they were to change the id of the order in the url, they can then see other people's orders. Please can someone help or suggest ways in which I can have it so that if someone was to try and view an order other than the one they have been directed to, they will be redirected to their customer page? I can get the redirect bit working fine, using:

redirect_to customers_path(session[:customer_id])

but how would I get the application to make sure that the customer can only view that order? I can't seem to use the sort of logic where I check that the order id equals the order id in the url, as that will always prove true!

like image 358
ecs Avatar asked Jun 18 '12 20:06

ecs


2 Answers

Assuming than your Order model has some concept of "who owns this order," usually via an integer column called something like user_id, you can check to see if session[:customer_id] is equal to order.user_id (or whatever you call it).

You will generally keep this authorization code in your controllers.

class OrdersController
  ...

  def show
    @order = Order.find params[:id]
    unless session[:customer_id] == @order.user_id
      flash[:notice] = "You don't have access to that order!"
      redirect_to customers_path(session[:customer_id])
      return
    end
  end

  ...
end

As your application gets more complicated, you might look into authorization gems like CanCan to handle this logic.

like image 112
Michelle Tilley Avatar answered Nov 15 '22 21:11

Michelle Tilley


I recommend adding an authorization gem such as CanCan, which lets you set whether the user has access to do certain things (e.g. edit an order, view an order, etc.). This may come in handy in a lot of ways; you may want to have admin pages (for adding new products, say) that customers should never have access to.

Once you have that in place, you can restrict a customer's access so that they can only view or edit their own orders. In CanCan, you create a class called abilities.rb that looks something like:

class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new # guest user (not logged in)
    if user.admin?
      can :manage, :all
    else
      can [:read, :update], Order, :user_id => user.id
    end
  end
end

That bit about can [:read, :update], Order, :user_id => user.id means "the (non-admin) user can read or update an Order if the order.user_id == user.id" (i.e. the current user's id).

like image 41
Jacob Mattison Avatar answered Nov 15 '22 21:11

Jacob Mattison