AshParc
Ash adapter for Parc, the framework-agnostic PARC authorization
contract. AshParc binds Ash's policy DSL to one Parc policy, so a single
declared policy authorizes every action across every resource.
Enforcement points
AshParc names one policy at two points in a resource's policies block:
AshParc.can_perform/2: anAsh.Policy.SimpleCheckgating a write or generic action on the policy's verdict.AshParc.build_request/3: builds theParc.Requestfor a resource-ownedAsh.Policy.FilterCheckthat row-scopes a read.
Both points project the action's arguments and instance attributes into the
request through the :arguments and :attributes options; :context lifts
a chosen argument or attribute into request.context under a normalized key
the preparers and decider read.
Usage
Declare the policy as a Parc.Pipeline (see parc) with
AshParc.ResetAshContext as its first preparer, then gate a write from
the resource's policies block:
policy action(:update) do
authorize_if AshParc.can_perform(MyApp.AuthzPolicy, attributes: [:organization_id])
end
Row-scope a read with a resource-owned Ash.Policy.FilterCheck that runs
the policy and turns the verdict into a filter, and name it the same way:
policy action(:read) do
authorize_if MyApp.Widget.ReadScope
end
That check builds its request with AshParc.build_request/3, and the read
scoping needs
config :ash, policies: [no_filter_static_forbidden_reads?: false]
so a {:deny, _} scopes the read to no rows instead of raising
Ash.Error.Forbidden.
Installation
Add ash_parc to your dependencies in mix.exs:
def deps do
[
{:ash_parc, "~> 0.1"}
]
end
The API reference is at hexdocs.pm/ash_parc.