Ruby on Rails: How to prevent users from changing the URL to view another user page?

I have it so that the presentation on the client page is associated with all the orders that they placed. When they click "Show," they take them into the view of the view for this order. However, if they were to change the order ID in the URL, they can see other people's orders. Please, can someone help or suggest ways that I can do this so that if someone tried to look at another order, in addition to the one they were sent to, they would be redirected to their customers page? I can make the redirect bit work fine using:

redirect_to customers_path(session[:customer_id]) 

but how can I get the application to make sure that the customer can only view this order? I cannot use logic where I verify that the order ID is equal to the order ID in the URL, as that will always be true!

+5
source share
8 answers

Assuming your order model has the concept of โ€œwho owns this orderโ€, usually through an integer column called something like user_id , you can check if session[:customer_id] order.user_id (or what you call it )

Usually you save 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 becomes more complex, you can learn rights such as CanCan to process this logic.

+12
source

I recommend adding self-censorship of authorization, such as CanCan, which allows you to establish whether a user has access to certain things (for example, edit an order, view the order, etc.). This can come in handy in many ways; you might want to have admin pages (to add new products, say) that customers should never have access to.

Once you do this, you can restrict access to the customer so that they can view or edit their own orders. In CanCan, you create a class called ability.rb that looks something like this:

 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 

This bit about can [:read, :update], Order, :user_id => user.id means that the user (non-admin) can read or update the order if order.user_id == user.id "(that is, the current user ID).

+10
source

A good solution would be to delete the appropriate route and view first. Instead, make some kind of page so that the user can see their own orders.

I'm not sure which custom game you are using, but if you are using Devise, you can write code like this:

 <% current_user.orders.each do |order| %> <%= render order %> <% end %> 

If you want to keep your current view and hierarchy of routes, you can use this code on the user page.

 <% if current_user.eql?(@user) %> <%= # show order history %> <% end %> 

If you are not using Devise, I suppose it may not be too difficult to write the helper method current_user to achieve the same functionality.

+1
source

Minor mod in @BinaryMuse's solution using Devise's current_user helper, conditional and other IF comparison operator (! =).

 def show @order = Order.find params[:id] if current_user.id != @order.user_id flash[:notice] = "MEAN MESSAGE HERE!" redirect_to orders_path(session[:current_user]) return end end 
+1
source

You can also check the authorization plugin. It is better to design it so that you can use other functions. Do not rely on client-side options to find the user's identity. Additional information here: http://www.rubyinside.com/authorization-permissions-plugin-for-rails-154.html

0
source
 (current_user.id == params[:id].to_i || is_writer?) || user_denied 

In my case is_writer? check if user can reorder user_denied - this is a redirect and warning method

0
source

Essentially, you need to create a Rails admin-- or admin for users and add validations to it by setting up administrator roles on these validations--.

 def set_admin end before_action set-admin only :[:destroy, :update] 

when adding admin, set the boolean default to false

0
source

I did this and it works fine, I don't know if this helps:

 def show user = User.find(params[:id]) redirect_to info_page_path unless current_user.id == @user.id end 
-1
source

All Articles