Lievcin
Lievcin

Reputation: 938

Devise and current user

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

Answers (3)

blah
blah

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

rxgx
rxgx

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

Josh Kovach
Josh Kovach

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

Related Questions