sezaru
Ash FilterCheck policy for read and create/update/destroy actions
I have this policy that I use to identify if the user is himself or not:
defmodule Core.Ash.Policies.Self do
@moduledoc false
use Ash.Policy.FilterCheck
@impl Ash.Policy.Check
def describe(opts) do
field = Keyword.get(opts, :field, :id)
"record #{field} matches actor id"
end
@impl Ash.Policy.FilterCheck
def filter(_actor, _context, opts) do
field = Keyword.get(opts, :field, :id)
expr(^ref(field) == ^actor(:id))
end
end
This works fine for read actions, but it will fail for create/update/destroy actions. To fix that I made these changes:
defmodule Core.Ash.Policies.Self do
@moduledoc false
use Ash.Policy.FilterCheck
defoverridable strict_check: 3
@impl Ash.Policy.Check
def describe(opts) do
field = Keyword.get(opts, :field, :id)
"record #{field} matches actor id"
end
@impl Ash.Policy.FilterCheck
def filter(_actor, _context, opts) do
field = Keyword.get(opts, :field, :id)
expr(^ref(field) == ^actor(:id))
end
@impl Ash.Policy.Check
def strict_check(actor, %{changeset: %Ash.Changeset{action_type: :create} = changeset}, opts) do
field = Keyword.get(opts, :field, :id)
{:ok, Ash.Changeset.get_attribute(changeset, field) == actor.id}
end
def strict_check(actor, %{changeset: %Ash.Changeset{} = changeset}, opts) do
field = Keyword.get(opts, :field, :id)
{:ok, Ash.Changeset.get_data(changeset, field) == actor.id}
end
def strict_check(actor, authorizer, opts) do
super(actor, authorizer, opts)
end
end
Now it seems to work fine, but I’m not sure if this is the best way to do that. Any thoughts?
Most Liked
zachdaniel
they should work for update/destroy actions, but not for create actions. I would not suggest using FilterCheck and overriding strict_check, because there are callbacks you need for your version to work consistently around atomic updates. You would want to rework this as a full Ash.Policy.Check module.
I don’t really see how you can have an actor that is creating themselves, but assuming they were creating something else and you wanted to check ownership, you could do:
policy_group some_shared_condition() do
policy action_type(:create) do
authorize_if relating_to_actor(:owner)
end
policy action_type([:read, :update, :destroy]) do
authorize_if relates_to_actor_via(:owner)
end
end
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance








