ash-project / ash

A declarative, extensible framework for building Elixir applications.
https://www.ash-hq.org
MIT License
1.47k stars 190 forks source link

Hide private fields with field policies. #1287

Closed torepettersen closed 1 day ago

torepettersen commented 1 week ago

Is your feature request related to a problem? Please describe. Currently if you query a resrouce with an interal function, e.g. Ash.read you would be able to see private fields, even if you have added field policies.

attributes do
  attribute :private_field, :string
  attribute :admin_only_field, :string
end

field_policies do
  field_policy :admin_only_field do
    authorize_if actor_attribute_equals(:is_admin, true)
  end
end
iex> Ash.read!(Resource, user: regular_user)
%{
  private_field: "Top secret",
  admin_only_field: #Ash.ForbiddenField<>,
}

Describe the solution you'd like There should therefore be a way to hide private fields, if field policies apply:

attributes do
  attribute :private_field, :string
  attribute :admin_only_field, :string
end

field_policies do
  hide_private? true
  field_policy :admin_only_field do
    authorize_if actor_attribute_equals(:is_admin, true)
  end
end
iex> Ash.read!(Resource, user: regular_user)
%{
  private_field: #Ash.ForbiddenField<>,
  admin_only_field: #Ash.ForbiddenField<>,
}

A global flag, would also be good, so you don't forget to add the field to each field policy:

config :ash, field_policies_hide_private: true

Additional context Helpful conversation on the topic on Elixir forum

zachdaniel commented 1 week ago

Thanks for the proposal! This should be relatively straightforward, as we apply field policies essentially in one place per action type. The global flag also sounds reasonable. PRs welcome!