Reputation: 718
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!
Upvotes: 7
Views: 6918
Reputation: 1
Basically you need to create Rails admin-- or admin to users and add validations to it bu setting up admin roles on those validations--
def set_admin
end
before_action set-admin only :[:destroy, :update]
when adding admin set the boolean as false on default
Upvotes: 0
Reputation: 1271
(current_user.id == params[:id].to_i || is_writer?) || user_denied
In my case is_writer? check if the user can modify the order instead user_denied is a method with redirect and alert
Upvotes: 0
Reputation: 95
Slight mod on @BinaryMuse's solution using current_user helper from Devise, the "IF" conditional and different 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
Upvotes: 1
Reputation: 1
You can also check the authorization plugin. Its better to design this so that you can use for other features as well. Do not rely on client side parameters for finding the identity of a user. More information here: http://www.rubyinside.com/authorization-permissions-plugin-for-rails-154.html
Upvotes: 0
Reputation: 51062
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).
Upvotes: 10
Reputation: 159125
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.
Upvotes: 14
Reputation: 173
A good solution would be to delete the corresponding route and view in the first place. Instead, make some sort of page for a user to see his or her own orders.
I'm not sure which user authentication gem you're using, but if you're using Devise, you could write code like this:
<% current_user.orders.each do |order| %>
<%= render order %>
<% end %>
If you wanted to keep your current view and route hierarchy, you could use this code on the user's page.
<% if current_user.eql?(@user) %>
<%= # show order history %>
<% end %>
If not using Devise, I imagine that it can't be too difficult to write a current_user helper method to achieve the same functionality.
Upvotes: 1