varvet / pundit

Minimal authorization through OO design and pure Ruby classes
MIT License
8.28k stars 629 forks source link

policy_class and policy usage #740

Open mattzollinhofer opened 2 years ago

mattzollinhofer commented 2 years ago

Basic Issue

If I use a custom policy for authorization (ex: authorize @post, policy_class: SpecialPostPolicy) in my controller how do I use policy(@post) to get the same policy in my view? Here's an example.

Simple Use Case

Controller:

def show
  @user = authorize User.find(params[:id]), policy_class: SpecialPostPolicy
end

View:

<%# This won't use `SpecialPostPolicy`, it'll use `PostPolicy` %>
<% if policy(@post).update? %>
  <%= link_to "Edit post", edit_post_path(@post) %>
<% end %>

Additional Commentary

I believe that in a previous version of Pundit the authorize call would call the policy method that was mixed into the controller it was working in the context of. But when authorization was extracted, I think that link was broken. We'd used that "seam" to be able to override def policy in our controller which allowed both the authorize call and the view to use the same policy. It's unclear to me how to use the same custom policy now. I believe this comment is referring to a related idea.

Burgestrand commented 1 year ago

Hi @mattzollinhofer! I'd be interested in hearing your reaction to the following idea: https://github.com/varvet/pundit/discussions/774

sequielo commented 1 year ago

I believe you should be able to manually instantiate the policy this way:

  <% if SpecialPostPolicy.new(pundit_user, @post).update? %>

Hope this helps for now.

Burgestrand commented 4 months ago

Question on this particular issue, are you looking to specifically get the same instance back, or just the same policy lookup behaviour?

For the latter, the above comment seems sufficient to me: https://github.com/varvet/pundit/issues/740#issuecomment-1599398284