The interface for an ash authorizer
These will typically be implemented by an extension, but a custom one can be implemented by defining an extension that also adopts this behaviour.
Then you can extend a resource with authorizers: [YourAuthorizer]
Summary
Callbacks
Apply field-level authorization to a list of records that already have values populated in memory, without re-fetching them through a read.
Returns the fields this authorizer may protect at field level for the resource.
Functions
Apply field-level authorization to records that are already in memory, scrubbing any fields the actor isn't allowed to see.
Types
Callbacks
@callback add_calculations(Ash.Query.t() | Ash.Changeset.t(), state(), context()) :: {:ok, Ash.Query.t() | Ash.Changeset.t(), state()} | {:error, Ash.Error.t()}
@callback alter_filter(filter :: Ash.Filter.t(), state(), context()) :: {:ok, Ash.Filter.t()} | {:error, Ash.Error.t()}
@callback alter_results(state(), [Ash.Resource.Record.t()], context()) :: {:ok, [Ash.Resource.Record.t()]} | {:error, Ash.Error.t()}
@callback apply_field_level_auth( resource :: Ash.Resource.t(), records :: [Ash.Resource.Record.t()], opts :: Keyword.t() ) :: {:ok, [Ash.Resource.Record.t()]} | {:error, Ash.Error.t()}
Apply field-level authorization to a list of records that already have values populated in memory, without re-fetching them through a read.
Implementations should walk each record and substitute %Ash.ForbiddenField{}
for any field the actor isn't allowed to see (typically via field policies).
This is the lightweight counterpart to add_calculations/3 + the read
pipeline's field-policy scrubbing — used when you have records in hand and
just need to enforce field-level visibility without running a load.
@callback check(state(), context()) :: :authorized | {:data, [Ash.Resource.Record.t()]} | {:error, :forbidden, state()} | {:error, Ash.Error.t()}
@callback exception(atom(), state()) :: Exception.t()
@callback initial_state( Ash.Resource.t(), Ash.Resource.Record.t(), Ash.Resource.Actions.action(), Ash.Domain.t() ) :: state()
@callback protected_fields(Ash.Resource.t()) :: [atom()]
Returns the fields this authorizer may protect at field level for the resource.
This is metadata for callers that need to know which fields can be hidden by authorization without running an action. Authorizers that do not implement this callback are treated as protecting no fields.
Functions
@spec apply_field_level_auth( Ash.Resource.t(), Ash.Resource.Record.t() | [Ash.Resource.Record.t()], Keyword.t() ) :: {:ok, Ash.Resource.Record.t() | [Ash.Resource.Record.t()]} | {:error, Ash.Error.t()}
Apply field-level authorization to records that are already in memory, scrubbing any fields the actor isn't allowed to see.
Walks each authorizer configured on the resource and invokes its
apply_field_level_auth/3 callback if defined. Returns the records with
forbidden fields replaced by %Ash.ForbiddenField{}.
Use this when you have records in hand (for example, returned from a generic action or constructed in memory) and want field policies applied without driving the records through a full read.
Supported options:
:actor- the actor whose visibility is being checked.:tenant- the tenant the records belong to.:domain- the domain context.