Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pundit: auhorize Index in nested resources

Using Rails 4.2.4 with Devise (3.5.2) and Pundit (1.0.1). Decent_exposure (2.3.2).

I have a simple nested associaton for User and Idea:

class User < ActiveRecord::Base
has_many :ideas
...

class Idea < ActiveRecord::Base
belongs_to :user
...

In routes.rb

devise_for :users

resources :users do
  resources :ideas
end

Then I am simply trying to disallow access to users/1/ideas if current_user is not the owner of the Ideas (in this example, if current_user.id != 1). I can not figure out how to do it. I am able to show just the current_user Ideas in the Index view with:

[Ideas controller]

def show
  authorize idea
end

[Idea policy]

def show?
  @current_user == @idea.user
end

But how can I prevent a user to simply navigate to other user's Idea index page? I guess that in Ideas controller I should use something like:

def index
  authorize user
end

But then what? How can I send to the User Policy the info regarding the Idea collection? Or should I authorize via the Idea Policy itself?

like image 317
Galen Avatar asked Dec 18 '22 22:12

Galen


1 Answers

Duplicating my response on GitHub here because this gets more traffic.


One way is to create a stub Idea owned by the user to authorize against.

def index
  @user = User::find(params[:user_id])
  idea  = Idea.new(user_id: @user.id)

  authorize idea

  # ...
end

and an index? method in your IdeaPolicy

def index?
  record.user_id = user.id
end

Another way is to change what you're authorizing against. Instead of authorizing against Idea, authorize against the User.

def index
  @user = User::find(params[:user_id])

  authorize @user, :show_ideas?

  # ...
end

and create a new show_ideas? method on your UserPolicy

def show_ideas?
  user.id == record.id
end
like image 85
deefour Avatar answered Jan 02 '23 03:01

deefour