Bodyguard v2.3.0 Bodyguard.Action

Execute authorized actions in a composable way.

An Action can be built up over the course of a request, providing a means to specify authorization parameters in the steps leading up to actually executing the job.

When authorization fails, there is an opportunity to handle it using a fallback function before returning the final result.

Authorization is performed by deferring to a Bodyguard.Policy.

Fields

  • context – Context for the action
  • policy – Implementation of Bodyguard.Policy behaviour; defaults to the context
  • user – The user to authorize
  • name – The name of the authorized action
  • auth_run? – If an authorization check has been performed
  • auth_result – Result of the authorization check
  • authorized? – If authorization has succeeded (default false)
  • job – Function to execute if authorization passes; signature job(action)
  • fallback – Function to execute if authorization fails; signature fallback(action)
  • assigns – Generic parameters along for the ride

Controller Example

defmodule MyApp.Web.PostController do
  use MyApp.Web, :controller
  import Bodyguard.Action
  alias MyApp.Blog

  action_fallback MyApp.FallbackController
  plug Bodyguard.Plug.BuildAction, context: Blog, user: &get_current_user/1

  def index(conn, _) do
    run conn.assigns.action, fn(action) ->
      posts = Blog.list_posts(action.user)
      render(conn, "index.html", posts: posts)
    end
  end

  defp get_current_user(conn) do
    # ...
  end
end

Verbose Example

import Bodyguard.Action
alias MyApp.Blog

act(Blog)
|> put_user(get_current_user())
|> put_policy(Blog.SomeSpecialPolicy)
|> assign(:drafts, true)
|> authorize(:list_posts)
|> put_job(fn action -> 
  Blog.list_posts(action.user, drafts_only: action.assigns.drafts) 
end)
|> put_fallback(fn _action -> {:error, :not_found} end)
|> run()

Link to this section Summary

Functions

Initialize an Action

Put a new assign

Mark the Action as authorized, regardless of previous authorization

Mark the Action as unauthorized, regardless of previous authorization

Same as authorize/3 but raises on failure

Use the policy to perform authorization

Replace the assigns

Change the context

Change the fallback handler

Change the job to execute

Change the policy

Change the user to authorize

Execute the job, raising on failure

Execute the given job, raising on failure

Execute the Action’s job

Execute the given job

Execute the given job and fallback

Link to this section Types

Link to this type assigns()
assigns() :: %{optional(atom()) => any()}
Link to this type fallback()
fallback() :: (action :: t() -> any())
Link to this type job()
job() :: (action :: t() -> any())
Link to this type t()
t() :: %Bodyguard.Action{
  assigns: assigns(),
  auth_result: Bodyguard.Policy.auth_result() | nil,
  auth_run?: boolean(),
  authorized?: boolean(),
  context: module() | nil,
  fallback: fallback() | nil,
  job: job() | nil,
  name: atom() | nil,
  policy: module() | nil,
  user: any()
}

Link to this section Functions

Link to this function act(context)
act(context :: module()) :: t()

Initialize an Action.

The context is assumed to implement Bodyguard.Policy callbacks. To specify a unique policy, use put_policy/2.

The Action is considered unauthorized by default, until authorization is run.

Link to this function assign(action, key, value)
assign(action :: t(), key :: atom(), value :: any()) :: t()

Put a new assign.

Link to this function force_authorized(action)
force_authorized(action :: t()) :: t()

Mark the Action as authorized, regardless of previous authorization.

Link to this function force_unauthorized(action, error)
force_unauthorized(action :: t(), error :: any()) :: t()

Mark the Action as unauthorized, regardless of previous authorization.

Link to this function permit!(action, name, opts \\ [])
permit!(action :: t(), name :: atom(), opts :: keyword() | assigns()) ::
  t()

Same as authorize/3 but raises on failure.

Link to this function permit(action, name, opts \\ [])
permit(action :: t(), name :: atom(), opts :: keyword() | assigns()) ::
  t()

Use the policy to perform authorization.

The opts are merged in to the Action’s assigns and passed as the params.

See Bodyguard.permit/3 for details.

Link to this function put_assigns(action, assigns)
put_assigns(action :: t(), assigns :: assigns()) :: t()

Replace the assigns.

Link to this function put_context(action, context)
put_context(action :: t(), context :: module()) :: t()

Change the context.

Link to this function put_fallback(action, fallback)
put_fallback(action :: t(), fallback :: fallback() | nil) :: t()

Change the fallback handler.

Link to this function put_job(action, job)
put_job(action :: t(), job :: job() | nil) :: t()

Change the job to execute.

Link to this function put_policy(action, policy)
put_policy(action :: t(), policy :: module()) :: t()

Change the policy.

Link to this function put_user(action, user)
put_user(action :: t(), user :: any()) :: t()

Change the user to authorize.

Link to this function run!(action)
run!(action :: t()) :: any()

Execute the job, raising on failure.

The job must have been previously assigned using put_job/2.

Link to this function run!(action, job)
run!(action :: t(), job :: job()) :: any()

Execute the given job, raising on failure.

Link to this function run(action)
run(action :: t()) :: any()

Execute the Action’s job.

The job must have been previously assigned using put_job/2.

If authorized, the job is run and its value is returned.

If unauthorized, and a fallback has been provided, the fallback is run and its value returned.

Otherwise, the result of the authorization is returned (something like {:error, reason}).

Link to this function run(action, job)
run(action :: t(), job :: job()) :: any()

Execute the given job.

If authorized, the job is run and its value is returned.

If unauthorized, and a fallback has been provided, the fallback is run and its value returned.

Otherwise, the result of the authorization is returned (something like {:error, reason}).

Link to this function run(action, job, fallback)
run(action :: t(), job :: job(), fallback :: fallback()) :: any()

Execute the given job and fallback.

If authorized, the job is run and its value is returned.

If unauthorized, the fallback is run and its value returned.