Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs(filters): clarify how to use string maps #1644

Conversation

alexslade
Copy link
Contributor

@alexslade alexslade commented Dec 4, 2024

I personally struggled with the current description. I hope this reduced wording is more explicit, while re-using explanation from Ash.Query.filter_input/2.

Following on from my post here while the iron is hot. If I've misunderstood things I'll remove/correct this PR as needed.

Contributor checklist

  • Bug fixes include regression tests
  • Chores
  • Documentation changes
  • Features include unit/acceptance tests
  • Refactoring
  • Update dependencies

@zachdaniel
Copy link
Contributor

So it's a bit more nuanced than this. It does in fact confirm that any fields referenced are public fields, which is important. When using filter_input, it also annotates any field references as "input?: true", which is used to control various aspects of authorizing a read action. Lets use a simple example where User resource has a policy like

policy :read do
  authorize_if expr(profile_public)
  authorize_if expr(id == ^actor(:id))
end

Additionally, lets imagine they had a field policy like this:

field_policy :id, always() do
  authorize_if expr(profile_public and show_email)
  authorize_if expr(id == ^actor(:id))
end

Then you had a resource called Post which has_many Users.

If they were to do something like this:

User
|> Ash.Query.filter_input(%{user: %{email: %{eq: "foo@bar.com"}}})

The ultimate authorized query would actually look like this (pretty wacky, I know, but this is what it looks like to actually have securely filterable resource interfaces that honor access rules in an app 😄 )

User
|> Ash.Query.filter_input(
  user.profile_public or user.id == ^actor(:id) and (
    if (profile_public and show_email) or user.id == ^actor(:id) do
      user.email
    else
      nil
    end
  )

If you were to just do
Ash.Query.filter(...)

with that same input, the reference would be considered an "internal" reference, and those rules would not be applied. This is how you can write actions that have internal filtering rules independent of user authentication status.

@alexslade alexslade force-pushed the docs-clarify-how-string-maps-are-used-in-filters branch 2 times, most recently from 5ba3c18 to 332b0ab Compare December 6, 2024 19:50
@alexslade
Copy link
Contributor Author

alexslade commented Dec 6, 2024

Thanks for the information @zachdaniel. After seeing Ash.Query.filter_input I figured this docstring could be slimmed down and mostly just refer to it.

If you don't like this, feel free to close the PR.

I personally struggled with the current description. I hope this reduced
wording is more explicit, while re-using explanation from
`Ash.Query.filter_input/2`.
@alexslade alexslade force-pushed the docs-clarify-how-string-maps-are-used-in-filters branch from 332b0ab to 85cf9bb Compare December 6, 2024 19:53
@zachdaniel
Copy link
Contributor

🚀 Thank you for your contribution! 🚀

@zachdaniel zachdaniel merged commit 0ad0d3b into ash-project:main Dec 6, 2024
8 checks passed
@alexslade alexslade deleted the docs-clarify-how-string-maps-are-used-in-filters branch December 6, 2024 19:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants