Airframe.Policy behaviour (Airframe v0.1.3)

View Source

The Policy behaviour, using macro, and defaults.

Examples

defmodule MyApp.Policy do
  use Airframe.Policy

  def allow(%User{id: user_id}, :update, %{current_user: %User{id: user_id}}), do: true
  def allow(%User{id: user_id}, :update, %{current_user: %User{id: other_id}}), do: false
end

Summary

Callbacks

Checks if the action is allowed on subject by actor.

Functions

Set up the module as an Airframe.Policy.

Checks if the action is allowed on subject for actor by policy.

Checks if the action is allowed on subject for actor by policy.

Callbacks

allow(subject, action, actor)

@callback allow(
  subject :: Airframe.subject(),
  action :: Airframe.action(),
  actor :: Airframe.actor()
) :: boolean() | {:ok, scoped_subject :: any()} | {:error, any()}

Checks if the action is allowed on subject by actor.

Can return plain true/false, or a tuple {:ok, scoped_subject} to still allow the action, while narrowing the scope of the original subject. This is useful if the original subject is an Ecto.Query or similar that can be narrowed down. Can also return {:error, reason :: any()} which will be passed along to the caller.

Functions

__using__(opts)

(macro)

Set up the module as an Airframe.Policy.

Options

  • defer - If provided, it is the module to defer to for policy checking instead of this module.
  • default - If provided, a catch-all allow/3 is appended that always returns this value. This is useful for policies that always allow or deny everything by default. If not provided, the user is responsible for handling all cases in their policy module.

Example

defmodule MyApp.Context do
  # simply
  use Airframe.Policy

  # or if you want to implement `c:Airframe.Policy.allow/3` in a different module:
  use Airframe.Policy, defer: MyApp.Context.Policy
end

check(changeset, action, actor, policy)

@spec check(
  subject :: Airframe.subject(),
  action :: Airframe.action(),
  actor :: Airframe.actor(),
  policy :: Airframe.policy()
) ::
  {:ok, narrowed_subject :: Airframe.subject()}
  | {:error, :unauthorized}
  | {:error, any()}

Checks if the action is allowed on subject for actor by policy.

If the ecto_changeset feature flag is enabled (default: true), this function will return {:error, changeset} if the subject is an Ecto.Changeset and is marked as invalid.

check!(subject, action, actor, policy)

@spec check!(
  subject :: Airframe.subject(),
  action :: Airframe.action(),
  actor :: Airframe.actor(),
  policy :: Airframe.policy()
) :: Airframe.subject() | no_return()

Checks if the action is allowed on subject for actor by policy.

Like check/4, but raises an Airframe.UnauthorizedError if the action is not allowed.