AshAuthzed (ash_authzed v0.2.0)

Copy Markdown View Source

Standalone Ash Framework extension for Zanzibar / ReBAC authorization backed by Licet (embedded Postgres/Ecto), SpiceDB / Authzed (HTTP via Req), or AshAuthzed.Adapters.Memory (in-memory Licet engine).

Usage

defmodule MyApp.Accounts.User do
  use Ash.Resource,
    domain: MyApp.Accounts,
    data_layer: AshPostgres.DataLayer,
    authorizers: [Ash.Policy.Authorizer],
    extensions: [AshAuthzed]

  authzed do
    object_type "user_profile"
    adapter :licet
    adapter_opts [instance: MyApp.Licet]

    relation :owner, subject_type: "user", subject_id: :id
    relation :platform, static_subject: "platform:main"
    external_role :role, target: "platform:main", subject_type: "user", subject_id: :id

    conditional_wildcard :is_protected_admin,
      subject_type: "user",
      attribute: :role,
      in: [:admin, :super_admin]
  end

  policies do
    policy action(:read) do
      authorize_if rebac_can(:view)
    end

    policy action(:update_profile) do
      authorize_if rebac_can(:edit)
    end
  end
end

Summary

Functions

Builds the adapter options keyword list for a given Ash resource, merging any call-site overrides.

Applies the given .zed or YAML schema (file path or raw string) to the configured ReBAC adapter.

Streams an Ash Resource or Ash.Query in keyset-paginated batches and writes its relationship tuples via AshAuthzed.Adapter.write_tuples/2.

Backfills all AshAuthzed-enabled resources in the given OTP app or domain list.

Returns all ReBAC entities declared in the resource's authzed and rebac DSL sections.

Fetches a configuration option from the resource's authzed or rebac DSL section.

Discovers all Ash resources in the given OTP app (or list of Ash domains) that use the AshAuthzed extension.

Functions

adapter_config(resource, overrides \\ [])

@spec adapter_config(Ash.Resource.t(), keyword()) :: keyword()

Builds the adapter options keyword list for a given Ash resource, merging any call-site overrides.

apply_schema(path_or_text, opts \\ [])

@spec apply_schema(String.t(), keyword()) :: :ok | {:ok, term()} | {:error, term()}

Applies the given .zed or YAML schema (file path or raw string) to the configured ReBAC adapter.

authzed(body)

(macro)

backfill(resource_or_query, opts \\ [])

@spec backfill(Ash.Resource.t() | Ash.Query.t(), keyword()) ::
  {:ok,
   %{
     records: non_neg_integer(),
     operations: non_neg_integer(),
     batches: non_neg_integer()
   }}
  | {:error, term()}

Streams an Ash Resource or Ash.Query in keyset-paginated batches and writes its relationship tuples via AshAuthzed.Adapter.write_tuples/2.

Options

  • :batch_size - Number of records per chunk (default: 500)
  • :reconcile? - Whether to also emit :delete ops for non-matching enum roles (default: true)
  • :dry_run? - If true, computes operations and returns counts without writing to the adapter (default: false)
  • :tenant - Optional tenant passed to Ash.stream!/2
  • :stream_opts - Additional options forwarded to Ash.stream!/2
  • :adapter_opts - Additional options forwarded to AshAuthzed.Adapter.write_tuples/2
  • :on_batch - Optional callback invoked with running stats after each batch

backfill_all(otp_app_or_domains, opts \\ [])

@spec backfill_all(atom() | [Ash.Domain.t()], keyword()) ::
  {:ok, %{optional(Ash.Resource.t()) => map()}}
  | {:error, {Ash.Resource.t(), term()}}

Backfills all AshAuthzed-enabled resources in the given OTP app or domain list.

get_entities(resource)

Returns all ReBAC entities declared in the resource's authzed and rebac DSL sections.

get_opt(resource, key, default \\ nil)

@spec get_opt(Ash.Resource.t(), atom(), term()) :: term()

Fetches a configuration option from the resource's authzed or rebac DSL section.

rebac(body)

(macro)

registered_resources(otp_app)

@spec registered_resources(atom() | [Ash.Domain.t()]) :: [Ash.Resource.t()]

Discovers all Ash resources in the given OTP app (or list of Ash domains) that use the AshAuthzed extension.