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?
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: