View Source Ash.Policy.FilterCheck behaviour (ash v3.4.1)
A type of check that is represented by a filter statement
That filter statement can be templated, currently only supporting {:_actor, field}
which will replace that portion of the filter with the appropriate field value from the actor and
{:_actor, :_primary_key}
which will replace the value with a keyword list of the primary key
fields of an actor to their values, like [id: 1]
. If the actor is not present {:_actor, field}
becomes nil
, and {:_actor, :_primary_key}
becomes false
.
You can customize what the "negative" filter looks like by defining reject/3
. This is important for
filters over related data. For example, given an owner
relationship and a data layer like ash_postgres
where column != NULL
does not evaluate to true (see postgres docs on NULL for more):
# The opposite of
`owner.id == 1`
# in most cases is not
`not(owner.id == 1)`
# because in postgres that would be `NOT (owner.id = NULL)` in cases where there was no owner
# A better opposite would be
`owner.id != 1 or is_nil(owner.id)`
# alternatively
`not(owner.id == 1) or is_nil(owner.id)`
By being able to customize the reject
filter, you can use related filters in your policies. Without it,
they will likely have undesired effects.
Summary
Types
@type context() :: %{ :action => Ash.Resource.Actions.action(), :resource => Ash.Resource.t(), :domain => Ash.Domain.t(), optional(:query) => Ash.Query.t(), optional(:changeset) => Ash.Changeset.t(), optional(:action_input) => Ash.ActionInput.t(), optional(any()) => any() }
@type options() :: Keyword.t()
Callbacks
@callback filter(actor :: term(), context(), options()) :: Keyword.t() | Ash.Expr.t()
@callback reject(actor :: term(), context(), options()) :: Keyword.t() | Ash.Expr.t()