I can not figure out how to authorize the access to an Index view based on the parent resource.
User has_many :ideas
Idea belongs_to :user
resources :users do
resources :ideas
end
Then I do not want a user to navigate to users/1/ideas if the user is not the one with id=1. Other words, if the user is not the ideas owner.
Any help would be very appreciated,
Best
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
Exactly. It works perfectly. I prefer the second approach, more intuitive for me...
I had the same issue with the index action and solved it in the controller. My authorization requires a User to belong to an Organization, and only an Admin who belongs to the same Organization as the User can view the Ideas.
def index
authorize(Idea)
user = User.find_by_uuid(params[:user_id])
# Check the Idea's parent resource outside of the Policy - as the Policy
# only operates on the resource itself (i.e. the Idea).
# @current_user is an Admin
unless user.organization_id == @current_user.organization_id
raise Pundit::NotAuthorizedError
end
# Apply the organization_id scope to be on the safe side.
ideas = policy_scope(user.ideas)
render(json: ideas, status: 200)
end
Most helpful comment
One way is to create a stub
Ideaowned by the user to authorize against.and an
index?method in yourIdeaPolicyAnother way is to change what you're authorizing against. Instead of authorizing against
Idea, authorize against theUser.and create a new
show_ideas?method on yourUserPolicy