4
votes

I'm using pundit for authorization in a rails app. For some models, I want attribute-level authorization. For example, a normal user is allowed to change his phone number but can't set his status to "administrator".

As recommended in the Pundit docs, I'm using the permitted_attributes for this.

I now want to access these attributes in a view to decide which fields to show or enable in a form. Is there an (elegant) way to do this without essentially repeating the authorized fields there?

1

1 Answers

5
votes

First you may want to add some nice shortcuts in your ApplicationPolicy which lets you check if attributes are permitted:

class ApplicationPolicy 
  #...

  def permits_attributes?(*attrs)
    attrs.keep_if({|a| permits_attribute?(a) }).any?
  end

  def permits_attribute?(attr)
    permitted_attributes.include?(attr)
  end

  # ...
end

You could then create a custom form builder (or a module that extends a form builder):

class MyFormBuilder < ActionView::Helpers::FormBuilder
  def can_fill_in?(attr)
    yield if @template.policy(object).permits_attribute?(attr)
  end
end

<%= form_for(@project, builder: MyFormBuilder) do |f| %>
  <%= f.can_fill_in?(:title) do %>
    <%= f.label :title %>
    <%= f.text_field :title %>
  <% end %>
<% end %>

You can also configure rails to use your custom form builder by default:

ActionView::Base.default_form_builder = MyFormBuilder

See: