Reputation: 938
I've set up Devise to manage the authentication to my app.
I have a Category model in which users create their own categories. User has_many :categories. This model has a user_id attribute, so when someone logs in and goes to categories/index for example, from the controller the query would bring categories using current_user.id to filter out which ones to bring.
So far straight forward and works well, nobody seems to be able to see someone else's categories, but to be honest, unless I'm missing something, this seems a bit insecure. How do I know some hacker will not figure it out and send his own requests modifying the params?
Is this possible or am I being paranoid? Also, I might not be using the functionality properly?
Upvotes: 3
Views: 9825
Reputation: 869
Based on Josh's answer, I just made it into an if else statement. I converted params[:id]
to integer since current_user.id
returns one.
class UsersController < ApplicationController
before_filter :authenticate_owner!
#....
private
def authenticate_owner!
if user_signed_in? && current_user.id == params[:id].to_i
return
else
redirect_to root_url, :notice => "You must have permission to access this page."
end
end
end
Upvotes: 0
Reputation: 5160
I think you have the relationship setup for a one-to-one (one category per user) instead of a one-to-many (many categories per user). If you have a category_id
in the User
model, the following should be your setup.
# in User.rb
belongs_to :category
# in Category.rb
has_many :users
# in CategoriesController
@category = current_user.category
If you want to have multiple categories per user, than I suggest using a link table (as model UserCategory
) with user_id
and category_id
.
# in UserCategory.rb
belongs_to :user
belongs_to :category
# in User.rb
has_many :user_categories
has_many :categories, :through => :user_categories
# in Category.rb
has_many :user_categories
has_many :users, :through => :user_categories
Then, in your Category
controller you can use your code from above to grab all categories by a given user.
# in CategoriesController.rb
@categories = current_user.categories
Upvotes: 1
Reputation: 7749
Provided you're using the proper relationship between users
and categories
, i.e.
# in User.rb
has_many :categories
# in Category.rb
belongs_to :user
you should be able to use something like this in your controller:
@categories = current_user.categories
This way you're using the current user regardless of what parameters may be passed, and it will only get their galleries. You're not searching by a potentially insecure user_id anymore.
If you're worried about someone being able to view a category that isn't theirs, you can add your own private method similar to :authenticate_user!
to make sure that the category being shown or edited actually belongs to the current user, running it in a before_filter like the other one, and redirecting if they don't have permission.
private
def authenticate_owner!
if user_signed_in? && current_user.id == params[:id] # or something similar
return true
end
redirect_to root_url,
:notice => "You must have permission to access this category."
return false
end
Upvotes: 2