

Bodyguard — Bodyguard v2.4.2

try { if(localStorage.getItem('night-mode') === 'true') document.body.className += ' night-mode'; } catch (e) { }

Bodyguard

=========

[![Module Version](https://img.shields.io/hexpm/v/bodyguard.svg)](https://hex.pm/packages/bodyguard)

[![Hex Docs](https://img.shields.io/badge/hex-docs-lightgreen.svg)](https://hexdocs.pm/bodyguard/)

[![Total Download](https://img.shields.io/hexpm/dt/bodyguard.svg)](https://hex.pm/packages/bodyguard)

[![License](https://img.shields.io/hexpm/l/bodyguard.svg)](https://github.com/schrockwell/bodyguard/blob/master/LICENSE)

[![Last Updated](https://img.shields.io/github/last-commit/schrockwell/bodyguard.svg)](https://github.com/schrockwell/bodyguard/commits/master)

[![tests](https://github.com/schrockwell/bodyguard/actions/workflows/tests.yml/badge.svg)](https://github.com/schrockwell/bodyguard/actions)

Bodyguard protects the context boundaries of your application. 💪

Version 2 was built from the ground-up to integrate nicely with Phoenix contexts. Authorization callbacks are implemented directly on contexts, so permissions can be checked from controllers, views, sockets, tests, and even other contexts.

The [`Bodyguard.Policy`](Bodyguard.Policy.html) behaviour is implemented with a single required callback. Additionally, the [`Bodyguard.Schema`](Bodyguard.Schema.html) behaviour provides a convention for limiting query results per-user.

This is an all-new API, so refer to [the `1.x` branch](https://github.com/schrockwell/bodyguard/tree/1.x) for the earlier readme.

* [Docs](https://hexdocs.pm/bodyguard/) ← complete documentation

* [Hex](https://hex.pm/packages/bodyguard)

* [GitHub](https://github.com/schrockwell/bodyguard)

 Quick Example

----------------

Define authorization rules directly in the context module:

```

# lib/my\_app/blog/blog.ex

defmodule MyApp.Blog do

 @behaviour Bodyguard.Policy

 # Admins can update anything

 def authorize(:update\_post, %{role: :admin} = \_user, \_post), do: :ok

 # Users can update their owned posts

 def authorize(:update\_post, %{id: user\_id} = \_user, %{user\_id: user\_id} = \_post), do: :ok

 # Otherwise, denied

 def authorize(:update\_post, \_user, \_post), do: :error

end

# lib/my\_app\_web/controllers/post\_controller.ex

defmodule MyAppWeb.PostController do

 use MyAppWeb, :controller

 def update(conn, %{"id" => id, "post" => post\_params}) do

 user = conn.assigns.current\_user

 post = MyApp.Blog.get\_post!(id)

 with :ok <- Bodyguard.permit(MyApp.Blog, :update\_post, user, post),

 {:ok, post} <- MyApp.Blog.update\_post(post, post\_params)

 do

 redirect(conn, to: post\_path(conn, :show, post))

 end

 end

end

```

 Policies

-----------

To implement a policy, add `@behaviour Bodyguard.Policy` to a context, then define `authorize(action, user, params)` callbacks, which must return:

* `:ok` or `true` to permit an action

* `:error`, `{:error, reason}`, or `false` to deny an action

Don't use these callbacks directly - instead, go through [`Bodyguard.permit/4`](Bodyguard.html#permit/4). This will convert any keyword-list `params` into a map, and will coerce the callback result into a strict `:ok` or `{:error, reason}` result. The default failure `reason` is `:unauthorized` unless specified otherwise in the callback.

Also provided are [`Bodyguard.permit?/4`](Bodyguard.html#permit?/4) (returns a boolean) and [`Bodyguard.permit!/5`](Bodyguard.html#permit!/5) (raises [`Bodyguard.NotAuthorizedError`](Bodyguard.NotAuthorizedError.html) on failure).

```

# lib/my\_app/blog/blog.ex

defmodule MyApp.Blog do

 @behaviour Bodyguard.Policy

 alias \_\_MODULE\_\_

 # Admin users can do anything

 def authorize(\_, %Blog.User{role: :admin}, \_), do: true

 # Regular users can create posts

 def authorize(:create\_post, \_, \_), do: true

 # Regular users can modify their own posts

 def authorize(action, %Blog.User{id: user\_id}, %Blog.Post{user\_id: user\_id})

 when action in [:update\_post, :delete\_post], do: true

 # Catch-all: deny everything else

 def authorize(\_, \_, \_), do: false

end

```

If you prefer more structure, define a dedicated policy module outside of the context, and use `defdelegate`:

```

# lib/my\_app/blog/blog.ex

defmodule MyApp.Blog do

 defdelegate authorize(action, user, params), to: MyApp.Blog.Policy

end

# lib/my\_app/blog/policy.ex

defmodule MyApp.Blog.Policy do

 @behaviour Bodyguard.Policy

 def authorize(action, user, params), do: # ...

end

```

 Controllers

--------------

Phoenix 1.3 introduces the `action_fallback` controller macro. This is the recommended way to deal with authorization failures. The fallback controller will handle `{:error, reason}` authorization failures.

If you are using the [`Bodyguard.Plug.Authorize`](Bodyguard.Plug.Authorize.html) plug, then you must use its `:fallback` option instead, since the plug pipeline will be halted before the controller action is called.

Typically, authorization failure results in `{:error, :unauthorized}`. If you wish to deny access without leaking the existence of a particular resource, consider returning `{:error, :not_found}` instead, and handle it separately in the fallback controller.

See the section "Overriding `action/2` for custom arguments" in [the Phoenix.Controller docs](https://hexdocs.pm/phoenix/Phoenix.Controller.html) for a clean way to pass in the `user` to each action.

```

# lib/my\_app\_web/controllers/fallback\_controller.ex

defmodule MyAppWeb.FallbackController do

 use MyAppWeb, :controller

 def call(conn, {:error, :unauthorized}) do

 conn

 |> put\_status(:forbidden)

 |> put\_view(MyAppWeb.ErrorView)

 |> render(:"403")

 end

end

```

### 

 Where Should I Perform Checks?

Bodyguard doesn't make any assumptions about where authorization checks are performed. You can do it before calling into the context, or within the context itself. There is a good discussion of the tradeoffs [here](https://dockyard.com/blog/2017/08/01/authorization-for-phoenix-contexts).

 Plugs

--------

* [`Bodyguard.Plug.Authorize`](Bodyguard.Plug.Authorize.html) – perform authorization in the middle of a pipeline

This plug's config utilizes callback functions called getters, which are 1-arity functions that

accept the `conn` and return the appropriate value.

```

# lib/my\_app\_web/controllers/post\_controller.ex

defmodule MyAppWeb.PostController do

 use MyAppWeb, :controller

 # Fetch the post and put into conn assigns

 plug :get\_post when action in [:show]

 # Do the check

 plug Bodyguard.Plug.Authorize,

 policy: MyApp.Blog.Policy,

 action: {Phoenix.Controller, :action\_name},

 user: {MyApp.Authentication, :current\_user},

 params: {\_\_MODULE\_\_, :extract\_post},

 fallback: MyAppWeb.FallbackController

 def show(conn, \_) do

 # Already assigned and authorized

 render(conn, "show.html")

 end

 defp get\_post(conn, \_) do

 assign(conn, :post, MyApp.Posts.get\_post!(conn.params["id"]))

 end

 # Helper for the Authorize plug

 def extract\_post(conn), do: conn.assigns.posts

end

```

See the docs for more information about configuring application-wide defaults for the plug.

 Schema Scopes

----------------

Bodyguard also provides the [`Bodyguard.Schema`](Bodyguard.Schema.html) behaviour to query which items a user can access. Implement it directly on schema modules.

```

# lib/my\_app/blog/post.ex

defmodule MyApp.Blog.Post do

 import Ecto.Query, only: [from: 2]

 @behaviour Bodyguard.Schema

 def scope(query, %MyApp.Blog.User{id: user\_id}, \_) do

 from ms in query, where: ms.user\_id == ^user\_id

 end

end

```

To leverage scopes, the [`Bodyguard.scope/4`](Bodyguard.html#scope/4) helper function (not the callback!) can infer the type of a query and automatically defer to the appropriate callback.

```

# lib/my\_app/blog/blog.ex

defmodule MyApp.Blog do

 def list\_user\_posts(user) do

 MyApp.Blog.Post

 |> Bodyguard.scope(user) # <-- defers to MyApp.Blog.Post.scope/3

 |> where(draft: false)

 |> Repo.all

 end

end

```

 Configuration

----------------

Here is the default library config.

```

config :bodyguard,

 # The second element of the {:error, reason} tuple returned on auth failure

 default\_error: :unauthorized

```

 Testing

----------

Testing is pretty straightforward – use the [`Bodyguard`](Bodyguard.html) top-level API.

```

assert :ok == Bodyguard.permit(MyApp.Blog, :successful\_action, user)

assert {:error, :unauthorized} == Bodyguard.permit(MyApp.Blog, :failing\_action, user)

assert Bodyguard.permit?(MyApp.Blog, :successful\_action, user)

refute Bodyguard.permit?(MyApp.Blog, :failing\_action, user)

error = assert\_raise Bodyguard.NotAuthorizedError, fun ->

 Bodyguard.permit(MyApp.Blog, :failing\_action, user)

end

assert %{status: 403, message: "not authorized"} = error

```

 Installation

---------------

1. Add `:bodyguard` to your list of dependencies:

```

# mix.exs

def deps do

 [

 {:bodyguard, "~> 2.4"}

 ]

end

```

2. Create an error view for handling `403 Forbidden`.

```

# lib/my\_app\_web/views/error\_view.ex

defmodule MyAppWeb.ErrorView do

 use MyAppWeb, :view

 def render("403.html", \_assigns) do

 "Forbidden"

 end

end

```

3. Wire up a [fallback controller](#controllers) to render this error view on `{:error, :unauthorized}`.

4. Add `@behaviour Bodyguard.Policy` to contexts that require authorization, and implement `authorize/3` callbacks.

5. (Optional) Add `@behaviour Bodyguard.Schema` on schemas available for user-scoping, and implement `scope/3` callbacks.

6. (Optional) Edit `my_app_web.ex` and add `import Bodyguard` to controllers, views, channels, etc.

 Alternatives

---------------

Not what you're looking for?

* [Roll your own](https://dockyard.com/blog/2017/08/01/authorization-for-phoenix-contexts)

* [PolicyWonk](https://github.com/boydm/policy_wonk)

* [Canada](https://github.com/jarednorman/canada)

* [Canary](https://github.com/cpjk/canary)

 Community

------------

Join our communities!

* [Slack](https://elixir-lang.slack.com/messages/CHMTNPSEN/)

 License

----------

MIT License, Copyright (c) 2017 Rockwell Schrock

 Acknowledgements

-------------------

Thanks to [Ben Cates](https://github.com/bencates) for helping maintain and mature this library.





Bodyguard — Bodyguard v2.4.2

try { if(localStorage.getItem('night-mode') === 'true') document.body.className += ' night-mode'; } catch (e) { }

Bodyguard (Bodyguard v2.4.2)

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard.ex#L1 "View Source")

===================================================================================================================================

Authorize actions at the boundary of a context.

Please see the [README](readme.html).

[Link to this section](#summary)

 Summary

==========================================

[Types](#types)

----------------

[action()](#t:action/0)

[opts()](#t:opts/0)

[Functions](#functions)

------------------------

[permit(policy, action, user, params \\ [])](#permit/4)

Authorize a user's action.

[permit!(policy, action, user, params \\ [], opts \\ [])](#permit!/5)

The same as [`permit/4`](#permit/4), but raises [`Bodyguard.NotAuthorizedError`](Bodyguard.NotAuthorizedError.html) on

authorization failure.

[permit?(policy, action, user, params \\ [])](#permit?/4)

The same as [`permit/4`](#permit/4), but returns a boolean.

[scope(query, user, params \\ [], opts \\ [])](#scope/4)

Filter a query down to user-accessible items.

[Link to this section](#types)

Types

=====================================

[Link to this type](#t:action/0 "Link to this type")

action()

========

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard.ex#L8 "View Source")

Specs

-----

```

action() :: [atom](https://hexdocs.pm/elixir/typespecs.html#basic-types)() | [String.t](https://hexdocs.pm/elixir/String.html#t:t/0)()

```

[Link to this type](#t:opts/0 "Link to this type")

opts()

======

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard.ex#L9 "View Source")

Specs

-----

```

opts() :: [keyword](https://hexdocs.pm/elixir/typespecs.html#built-in-types)() | %{optional([atom](https://hexdocs.pm/elixir/typespecs.html#basic-types)()) => [any](https://hexdocs.pm/elixir/typespecs.html#basic-types)()}

```

[Link to this section](#functions)

Functions

=============================================

[Link to this function](#permit/4 "Link to this function")

permit(policy, action, user, params \\ [])

==========================================

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard.ex#L24 "View Source")

Specs

-----

```

permit(policy :: [module](https://hexdocs.pm/elixir/typespecs.html#built-in-types)(), action :: [action](#t:action/0)(), user :: [any](https://hexdocs.pm/elixir/typespecs.html#basic-types)(), params :: [any](https://hexdocs.pm/elixir/typespecs.html#basic-types)()) ::

  :ok | {:error, [any](https://hexdocs.pm/elixir/typespecs.html#basic-types)()} | [no\_return](https://hexdocs.pm/elixir/typespecs.html#built-in-types)()

```

Authorize a user's action.

Returns `:ok` on success, and `{:error, reason}` on failure.

If `params` is a keyword list, it is converted to a map before passing down

to the [`Bodyguard.Policy.authorize/3`](Bodyguard.Policy.html#c:authorize/3) callback. Otherwise, `params` is not

changed.

[Link to this function](#permit!/5 "Link to this function")

permit!(policy, action, user, params \\ [], opts \\ [])

=======================================================

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard.ex#L50 "View Source")

Specs

-----

```

permit!(

  policy :: [module](https://hexdocs.pm/elixir/typespecs.html#built-in-types)(),

  action :: [action](#t:action/0)(),

  user :: [any](https://hexdocs.pm/elixir/typespecs.html#basic-types)(),

  params :: [any](https://hexdocs.pm/elixir/typespecs.html#basic-types)(),

  opts :: [opts](#t:opts/0)()

) :: :ok | [no\_return](https://hexdocs.pm/elixir/typespecs.html#built-in-types)()

```

The same as [`permit/4`](#permit/4), but raises [`Bodyguard.NotAuthorizedError`](Bodyguard.NotAuthorizedError.html) on

authorization failure.

Returns `:ok` on success.

If `params` is a keyword list, it is converted to a map before passing down

to the [`Bodyguard.Policy.authorize/3`](Bodyguard.Policy.html#c:authorize/3) callback. Otherwise, `params` is not

changed.

 Options

----------

* `error_message` – a string to describe the error (default "not authorized")

* `error_status` – the HTTP status code to raise with the error (default 403)

[Link to this function](#permit?/4 "Link to this function")

permit?(policy, action, user, params \\ [])

===========================================

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard.ex#L75 "View Source")

Specs

-----

```

permit?(policy :: [module](https://hexdocs.pm/elixir/typespecs.html#built-in-types)(), action :: [action](#t:action/0)(), user :: [any](https://hexdocs.pm/elixir/typespecs.html#basic-types)(), params :: [any](https://hexdocs.pm/elixir/typespecs.html#basic-types)()) ::

  [boolean](https://hexdocs.pm/elixir/typespecs.html#built-in-types)()

```

The same as [`permit/4`](#permit/4), but returns a boolean.

[Link to this function](#scope/4 "Link to this function")

scope(query, user, params \\ [], opts \\ [])

============================================

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard.ex#L113 "View Source")

Specs

-----

```

scope(query :: [any](https://hexdocs.pm/elixir/typespecs.html#basic-types)(), user :: [any](https://hexdocs.pm/elixir/typespecs.html#basic-types)(), params :: [any](https://hexdocs.pm/elixir/typespecs.html#basic-types)(), opts :: [opts](#t:opts/0)()) :: [any](https://hexdocs.pm/elixir/typespecs.html#basic-types)()

```

Filter a query down to user-accessible items.

The `query` is introspected by Bodyguard in an attempt to automatically

determine the schema type. To succeed, `query` must be an atom (schema

module name), an `Ecto.Query`, or a list of structs.

This function exists primarily as a helper to `import` into a context and

gain access to scoping for all schemas.

```

defmodule MyApp.Blog do

 import Bodyguard

 def list\_user\_posts(user) do

 Blog.Post

 |> scope(user) # <-- defers to MyApp.Blog.Post.scope/3

 |> where(draft: false)

 |> Repo.all

 end

end

```

If `params` is a keyword list, it is converted to a map before passing down

to the [`Bodyguard.Schema.scope/3`](Bodyguard.Schema.html#c:scope/3) callback. Otherwise, `params` is not

changed.

#### Options

* `schema` - if the schema of the `query` cannot be determined, you must

manually specify the schema here





Bodyguard.Action — Bodyguard v2.4.2

try { if(localStorage.getItem('night-mode') === 'true') document.body.className += ' night-mode'; } catch (e) { }

Bodyguard.Action (Bodyguard v2.4.2)

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/action.ex#L1 "View Source")

=================================================================================================================================================

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`](Bodyguard.Policy.html).

#### Fields

* `:context` – Context for the action

* `:policy` – Implementation of [`Bodyguard.Policy`](Bodyguard.Policy.html) 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)

 Summary

==========================================

[Types](#types)

----------------

[assigns()](#t:assigns/0)

[fallback()](#t:fallback/0)

[job()](#t:job/0)

[t()](#t:t/0)

[Functions](#functions)

------------------------

[act(context)](#act/1)

Initialize an Action.

[assign(action, key, value)](#assign/3)

Put a new assign.

[force\_authorized(action)](#force_authorized/1)

Mark the Action as authorized, regardless of previous authorization.

[force\_unauthorized(action, error)](#force_unauthorized/2)

Mark the Action as unauthorized, regardless of previous authorization.

[permit(action, name, opts \\ [])](#permit/3)

Use the policy to perform authorization.

[permit!(action, name, opts \\ [])](#permit!/3)

Same as `authorize/3` but raises on failure.

[put\_assigns(action, assigns)](#put_assigns/2)

Replace the assigns.

[put\_context(action, context)](#put_context/2)

Change the context.

[put\_fallback(action, fallback)](#put_fallback/2)

Change the fallback handler.

[put\_job(action, job)](#put_job/2)

Change the job to execute.

[put\_policy(action, policy)](#put_policy/2)

Change the policy.

[put\_user(action, user)](#put_user/2)

Change the user to authorize.

[run(action)](#run/1)

Execute the Action's job.

[run(action, job)](#run/2)

Execute the given job.

[run(action, job, fallback)](#run/3)

Execute the given job and fallback.

[run!(action)](#run!/1)

Execute the job, raising on failure.

[run!(action, job)](#run!/2)

Execute the given job, raising on failure.

[Link to this section](#types)

Types

=====================================

[Link to this type](#t:assigns/0 "Link to this type")

assigns()

=========

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/action.ex#L82 "View Source")

Specs

-----

```

assigns() :: %{required([atom](https://hexdocs.pm/elixir/typespecs.html#basic-types)()) => [any](https://hexdocs.pm/elixir/typespecs.html#basic-types)()}

```

[Link to this type](#t:fallback/0 "Link to this type")

fallback()

==========

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/action.ex#L81 "View Source")

Specs

-----

```

fallback() :: (action :: [t](#t:t/0)() -> [any](https://hexdocs.pm/elixir/typespecs.html#basic-types)())

```

[Link to this type](#t:job/0 "Link to this type")

job()

=====

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/action.ex#L80 "View Source")

Specs

-----

```

job() :: (action :: [t](#t:t/0)() -> [any](https://hexdocs.pm/elixir/typespecs.html#basic-types)())

```

[Link to this type](#t:t/0 "Link to this type")

t()

===

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/action.ex#L84 "View Source")

Specs

-----

```

t() :: %Bodyguard.Action{

  assigns: [assigns](#t:assigns/0)(),

  auth_result: [Bodyguard.Policy.auth\_result](Bodyguard.Policy.html#t:auth_result/0)() | nil,

  auth_run?: [boolean](https://hexdocs.pm/elixir/typespecs.html#built-in-types)(),

  authorized?: [boolean](https://hexdocs.pm/elixir/typespecs.html#built-in-types)(),

  context: [module](https://hexdocs.pm/elixir/typespecs.html#built-in-types)() | nil,

  fallback: [fallback](#t:fallback/0)() | nil,

  job: [job](#t:job/0)() | nil,

  name: [atom](https://hexdocs.pm/elixir/typespecs.html#basic-types)() | nil,

  policy: [module](https://hexdocs.pm/elixir/typespecs.html#built-in-types)() | nil,

  user: [any](https://hexdocs.pm/elixir/typespecs.html#basic-types)()

}

```

[Link to this section](#functions)

Functions

=============================================

[Link to this function](#act/1 "Link to this function")

act(context)

============

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/action.ex#L107 "View Source")

Specs

-----

```

act(context :: [module](https://hexdocs.pm/elixir/typespecs.html#built-in-types)()) :: [t](#t:t/0)()

```

Initialize an Action.

The `context` is assumed to implement [`Bodyguard.Policy`](Bodyguard.Policy.html) callbacks. To

specify a unique policy, use [`put_policy/2`](#put_policy/2).

The Action is considered unauthorized by default, until authorization is

run.

[Link to this function](#assign/3 "Link to this function")

assign(action, key, value)

==========================

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/action.ex#L166 "View Source")

Specs

-----

```

assign(action :: [t](#t:t/0)(), key :: [atom](https://hexdocs.pm/elixir/typespecs.html#basic-types)(), value :: [any](https://hexdocs.pm/elixir/typespecs.html#basic-types)()) :: [t](#t:t/0)()

```

Put a new assign.

[Link to this function](#force_authorized/1 "Link to this function")

force\_authorized(action)

=========================

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/action.ex#L174 "View Source")

Specs

-----

```

force_authorized(action :: [t](#t:t/0)()) :: [t](#t:t/0)()

```

Mark the Action as authorized, regardless of previous authorization.

[Link to this function](#force_unauthorized/2 "Link to this function")

force\_unauthorized(action, error)

==================================

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/action.ex#L182 "View Source")

Specs

-----

```

force_unauthorized(action :: [t](#t:t/0)(), error :: [any](https://hexdocs.pm/elixir/typespecs.html#basic-types)()) :: [t](#t:t/0)()

```

Mark the Action as unauthorized, regardless of previous authorization.

[Link to this function](#permit/3 "Link to this function")

permit(action, name, opts \\ [])

================================

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/action.ex#L196 "View Source")

Specs

-----

```

permit(action :: [t](#t:t/0)(), name :: [atom](https://hexdocs.pm/elixir/typespecs.html#basic-types)(), opts :: [keyword](https://hexdocs.pm/elixir/typespecs.html#built-in-types)() | [assigns](#t:assigns/0)()) :: [t](#t:t/0)()

```

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`](Bodyguard.html#permit/3) for details.

[Link to this function](#permit!/3 "Link to this function")

permit!(action, name, opts \\ [])

=================================

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/action.ex#L224 "View Source")

Specs

-----

```

permit!(action :: [t](#t:t/0)(), name :: [atom](https://hexdocs.pm/elixir/typespecs.html#basic-types)(), opts :: [keyword](https://hexdocs.pm/elixir/typespecs.html#built-in-types)() | [assigns](#t:assigns/0)()) :: [t](#t:t/0)()

```

Same as `authorize/3` but raises on failure.

[Link to this function](#put_assigns/2 "Link to this function")

put\_assigns(action, assigns)

=============================

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/action.ex#L158 "View Source")

Specs

-----

```

put_assigns(action :: [t](#t:t/0)(), assigns :: [assigns](#t:assigns/0)()) :: [t](#t:t/0)()

```

Replace the assigns.

[Link to this function](#put_context/2 "Link to this function")

put\_context(action, context)

=============================

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/action.ex#L117 "View Source")

Specs

-----

```

put_context(action :: [t](#t:t/0)(), context :: [module](https://hexdocs.pm/elixir/typespecs.html#built-in-types)()) :: [t](#t:t/0)()

```

Change the context.

[Link to this function](#put_fallback/2 "Link to this function")

put\_fallback(action, fallback)

===============================

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/action.ex#L149 "View Source")

Specs

-----

```

put_fallback(action :: [t](#t:t/0)(), fallback :: [fallback](#t:fallback/0)() | nil) :: [t](#t:t/0)()

```

Change the fallback handler.

[Link to this function](#put_job/2 "Link to this function")

put\_job(action, job)

=====================

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/action.ex#L141 "View Source")

Specs

-----

```

put_job(action :: [t](#t:t/0)(), job :: [job](#t:job/0)() | nil) :: [t](#t:t/0)()

```

Change the job to execute.

[Link to this function](#put_policy/2 "Link to this function")

put\_policy(action, policy)

===========================

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/action.ex#L125 "View Source")

Specs

-----

```

put_policy(action :: [t](#t:t/0)(), policy :: [module](https://hexdocs.pm/elixir/typespecs.html#built-in-types)()) :: [t](#t:t/0)()

```

Change the policy.

[Link to this function](#put_user/2 "Link to this function")

put\_user(action, user)

=======================

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/action.ex#L133 "View Source")

Specs

-----

```

put_user(action :: [t](#t:t/0)(), user :: [any](https://hexdocs.pm/elixir/typespecs.html#basic-types)()) :: [t](#t:t/0)()

```

Change the user to authorize.

[Link to this function](#run/1 "Link to this function")

run(action)

===========

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/action.ex#L255 "View Source")

Specs

-----

```

run(action :: [t](#t:t/0)()) :: [any](https://hexdocs.pm/elixir/typespecs.html#basic-types)()

```

Execute the Action's job.

The `job` must have been previously assigned using [`put_job/2`](#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/2 "Link to this function")

run(action, job)

================

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/action.ex#L287 "View Source")

Specs

-----

```

run(action :: [t](#t:t/0)(), job :: [job](#t:job/0)()) :: [any](https://hexdocs.pm/elixir/typespecs.html#basic-types)()

```

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/3 "Link to this function")

run(action, job, fallback)

==========================

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/action.ex#L301 "View Source")

Specs

-----

```

run(action :: [t](#t:t/0)(), job :: [job](#t:job/0)(), fallback :: [fallback](#t:fallback/0)()) :: [any](https://hexdocs.pm/elixir/typespecs.html#basic-types)()

```

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.

[Link to this function](#run!/1 "Link to this function")

run!(action)

============

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/action.ex#L315 "View Source")

Specs

-----

```

run!(action :: [t](#t:t/0)()) :: [any](https://hexdocs.pm/elixir/typespecs.html#basic-types)()

```

Execute the job, raising on failure.

The `job` must have been previously assigned using [`put_job/2`](#put_job/2).

[Link to this function](#run!/2 "Link to this function")

run!(action, job)

=================

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/action.ex#L334 "View Source")

Specs

-----

```

run!(action :: [t](#t:t/0)(), job :: [job](#t:job/0)()) :: [any](https://hexdocs.pm/elixir/typespecs.html#basic-types)()

```

Execute the given job, raising on failure.





Bodyguard.NotAuthorizedError — Bodyguard v2.4.2

try { if(localStorage.getItem('night-mode') === 'true') document.body.className += ' night-mode'; } catch (e) { }

Bodyguard.NotAuthorizedError exception (Bodyguard v2.4.2)

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/not_authorized_error.ex#L1 "View Source")

=====================================================================================================================================================================================

Raised when authorization fails.





Bodyguard.Plug — Bodyguard v2.4.2

try { if(localStorage.getItem('night-mode') === 'true') document.body.className += ' night-mode'; } catch (e) { }

Bodyguard.Plug (Bodyguard v2.4.2)

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/plug.ex#L1 "View Source")

=============================================================================================================================================

Work with Actions embedded in connections.

[Link to this section](#summary)

 Summary

==========================================

[Functions](#functions)

------------------------

[put\_action(conn, action, key \\ :action)](#put_action/3)

Assign an Action to the connection.

[update\_action(conn, fun, key \\ :action)](#update_action/3)

Modify the existing Action on the connection, in-place.

[Link to this section](#functions)

Functions

=============================================

[Link to this function](#put_action/3 "Link to this function")

put\_action(conn, action, key \\ :action)

=========================================

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/plug.ex#L16 "View Source")

Specs

-----

```

put_action(conn :: [Plug.Conn.t](https://hexdocs.pm/plug/1.2.0/Plug.Conn.html#t:t/0)(), action :: [Bodyguard.Action.t](Bodyguard.Action.html#t:t/0)(), key :: [atom](https://hexdocs.pm/elixir/typespecs.html#basic-types)()) ::

  [Plug.Conn.t](https://hexdocs.pm/plug/1.2.0/Plug.Conn.html#t:t/0)()

```

Assign an Action to the connection.

Inserts it into `conn.assigns.action`.

[Link to this function](#update_action/3 "Link to this function")

update\_action(conn, fun, key \\ :action)

=========================================

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/plug.ex#L28 "View Source")

Specs

-----

```

update_action(

  conn :: [Plug.Conn.t](https://hexdocs.pm/plug/1.2.0/Plug.Conn.html#t:t/0)(),

  fun :: ([Bodyguard.Action.t](Bodyguard.Action.html#t:t/0)() -> [Bodyguard.Action.t](Bodyguard.Action.html#t:t/0)()),

  key :: [atom](https://hexdocs.pm/elixir/typespecs.html#basic-types)()

) :: [Plug.Conn.t](https://hexdocs.pm/plug/1.2.0/Plug.Conn.html#t:t/0)()

```

Modify the existing Action on the connection, in-place.





Bodyguard.Plug.Authorize — Bodyguard v2.4.2

try { if(localStorage.getItem('night-mode') === 'true') document.body.className += ' night-mode'; } catch (e) { }

Bodyguard.Plug.Authorize (Bodyguard v2.4.2)

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/plug/authorize.ex#L1 "View Source")

=================================================================================================================================================================

Perform authorization in a Plug pipeline.

 Options

----------

* `:policy` *required* - the policy (or context) module

* `:action` *required* - the action, or a getter

* `:user` - the user getter

* `:params` - the params, or a getter, to pass to the authorization callbacks

* `:fallback` - a fallback controller or plug to handle authorization

failure. If specified, the plug is called and then the pipeline is

`halt`ed. If not specified, then [`Bodyguard.NotAuthorizedError`](Bodyguard.NotAuthorizedError.html) raises

directly to the router.

### 

 Option Getters

The options `:action`, `:user`, and `:params` can accept getter functions that are either:

* an anonymous 1-arity function that accepts the `conn` and returns a value

* a `{module, function_name}` tuple specifying an existing function with that same signature

### 

 Default Plug Options

You can provide default options for this plug by simply wrapping your own plug around it.

For example, if you're using Phoenix with Pow for authentication, you might want to specify:

```

defmodule MyAppWeb.Authorize do

 def init(opts) do

 opts

 |> Keyword.put\_new(:action, {Phoenix.Controller, :action\_name})

 |> Keyword.put\_new(:user, {Pow.Plug, :current\_user})

 |> Bodyguard.Plug.Authorize.init()

 end

 def call(conn, opts) do

 Bodyguard.Plug.Authorize.call(conn, opts)

 end

end

```

 Examples

-----------

```

# Raise on failure

plug Bodyguard.Plug.Authorize,

 policy: MyApp.Blog,

 action: &action\_name/1,

 user: {MyApp.Authentication, :current\_user}

# Fallback on failure

plug Bodyguard.Plug.Authorize,

 policy: MyApp.Blog,

 action: &action\_name/1,

 user: {MyApp.Authentication, :current\_user},

 fallback: MyAppWeb.FallbackController

# Params as a function

plug Bodyguard.Plug.Authorize,

 policy: MyApp.Blog,

 action: &action\_name/1,

 user: {MyApp.Authentication, :current\_user},

 params: &get\_params/1

```

[Link to this section](#summary)

 Summary

==========================================

[Functions](#functions)

------------------------

[call(conn, arg)](#call/2)

Callback implementation for [`Plug.call/2`](https://hexdocs.pm/plug/1.2.0/Plug.html#c:call/2).

[init(opts \\ [])](#init/1)

Callback implementation for [`Plug.init/1`](https://hexdocs.pm/plug/1.2.0/Plug.html#c:init/1).

[valid\_getter?(fun)](#valid_getter?/1)

[Link to this section](#functions)

Functions

=============================================

[Link to this function](#call/2 "Link to this function")

call(conn, arg)

===============

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/plug/authorize.ex#L115 "View Source")

Callback implementation for [`Plug.call/2`](https://hexdocs.pm/plug/1.2.0/Plug.html#c:call/2).

[Link to this function](#init/1 "Link to this function")

init(opts \\ [])

================

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/plug/authorize.ex#L72 "View Source")

Callback implementation for [`Plug.init/1`](https://hexdocs.pm/plug/1.2.0/Plug.html#c:init/1).

[Link to this function](#valid_getter?/1 "Link to this function")

valid\_getter?(fun)

===================

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/plug/authorize.ex#L68 "View Source")





Bodyguard.Plug.BuildAction — Bodyguard v2.4.2

try { if(localStorage.getItem('night-mode') === 'true') document.body.className += ' night-mode'; } catch (e) { }

Bodyguard.Plug.BuildAction (Bodyguard v2.4.2)

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/plug/build_action.ex#L1 "View Source")

======================================================================================================================================================================

Construct an Action on the connection.

The action is stored in `conn.assigns.action` for later access (configurable

via the `:key` option).

#### Options

See [`Bodyguard.Action`](Bodyguard.Action.html) for descriptions of these fields.

* `context` - context module

* `policy` - policy module (defaults to context module)

* `fallback` - fallback function

* `assigns` - action assigns

* `user` – can be a 1-arity function (or `{module, function_name}`) that accepts the connection

and returns the user

* `key` - the assign to set. Defaults to `:action`

[Link to this section](#summary)

 Summary

==========================================

[Functions](#functions)

------------------------

[call(conn, opts)](#call/2)

Callback implementation for [`Plug.call/2`](https://hexdocs.pm/plug/1.2.0/Plug.html#c:call/2).

[init(opts \\ [])](#init/1)

Callback implementation for [`Plug.init/1`](https://hexdocs.pm/plug/1.2.0/Plug.html#c:init/1).

[Link to this section](#functions)

Functions

=============================================

[Link to this function](#call/2 "Link to this function")

call(conn, opts)

================

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/plug/build_action.ex#L28 "View Source")

Callback implementation for [`Plug.call/2`](https://hexdocs.pm/plug/1.2.0/Plug.html#c:call/2).

[Link to this function](#init/1 "Link to this function")

init(opts \\ [])

================

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/plug/build_action.ex#L26 "View Source")

Callback implementation for [`Plug.init/1`](https://hexdocs.pm/plug/1.2.0/Plug.html#c:init/1).





Bodyguard.Policy — Bodyguard v2.4.2

try { if(localStorage.getItem('night-mode') === 'true') document.body.className += ' night-mode'; } catch (e) { }

Bodyguard.Policy behaviour (Bodyguard v2.4.2)

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/policy.ex#L1 "View Source")

===========================================================================================================================================================

Where authorization rules live.

Typically the callbacks are designed to be used by [`Bodyguard.permit/4`](Bodyguard.html#permit/4) and

are not called directly.

The only requirement is to implement the [`authorize/3`](#c:authorize/3) callback:

```

defmodule MyApp.MyContext do

 @behaviour Bodyguard.Policy

 def authorize(action, user, params) do

 # Return :ok or true to permit

 # Return :error, {:error, reason}, or false to deny

 end

end

```

To perform authorization checks, use [`Bodyguard.permit/4`](Bodyguard.html#permit/4) and friends:

```

with :ok <- Bodyguard.permit(MyApp.MyContext, :action\_name, user, param: :value) do

 # ...

end

if Bodyguard.permit?(MyApp.MyContext, :action\_name, user, param: :value) do

 # ...

end

Bodyguard.permit!(MyApp.MyContext, :action\_name, user, param: :value)

```

If you want to define the callbacks in another module, you can use

`defdelegate`:

```

defmodule MyApp.MyContext do

 defdelegate authorize(action, user, params), to: Some.Other.Policy

end

```

[Link to this section](#summary)

 Summary

==========================================

[Types](#types)

----------------

[action()](#t:action/0)

[auth\_result()](#t:auth_result/0)

[Callbacks](#callbacks)

------------------------

[authorize(action, user, params)](#c:authorize/3)

Callback to authorize a user's action.

[Link to this section](#types)

Types

=====================================

[Link to this type](#t:action/0 "Link to this type")

action()

========

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/policy.ex#L40 "View Source")

Specs

-----

```

action() :: [atom](https://hexdocs.pm/elixir/typespecs.html#basic-types)() | [String.t](https://hexdocs.pm/elixir/String.html#t:t/0)()

```

[Link to this type](#t:auth_result/0 "Link to this type")

auth\_result()

==============

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/policy.ex#L41 "View Source")

Specs

-----

```

auth_result() :: :ok | :error | {:error, reason :: [any](https://hexdocs.pm/elixir/typespecs.html#basic-types)()} | true | false

```

[Link to this section](#callbacks)

Callbacks

=============================================

[Link to this callback](#c:authorize/3 "Link to this callback")

authorize(action, user, params)

===============================

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/policy.ex#L53 "View Source")

Specs

-----

```

authorize(

  action :: [action](#t:action/0)(),

  user :: [any](https://hexdocs.pm/elixir/typespecs.html#basic-types)(),

  params :: %{required([atom](https://hexdocs.pm/elixir/typespecs.html#basic-types)()) => [any](https://hexdocs.pm/elixir/typespecs.html#basic-types)()} | [any](https://hexdocs.pm/elixir/typespecs.html#basic-types)()

) :: [auth\_result](#t:auth_result/0)()

```

Callback to authorize a user's action.

To permit an action, return `:ok` or `true`. To deny, return `:error`,

`{:error, reason}`, or `false`.

The `action` is whatever user-specified contextual action is being authorized.

It bears no intrinsic relationship to a controller action, and instead should

share a name with a particular function on the context.





Bodyguard.Schema — Bodyguard v2.4.2

try { if(localStorage.getItem('night-mode') === 'true') document.body.className += ' night-mode'; } catch (e) { }

Bodyguard.Schema behaviour (Bodyguard v2.4.2)

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/schema.ex#L1 "View Source")

===========================================================================================================================================================

Specify user-accessible items.

The callbacks are designed to live within your schemas, hidden from the

context boundaries of your application.

All you have to do is implement the [`scope/3`](#c:scope/3) callback on your schema.

What "access" means is up to you, and can be customized on a case-by-case

basis via `params`.

Typically the callbacks are designed to be used by [`Bodyguard.scope/4`](Bodyguard.html#scope/4) and

are not called directly.

If you want to use separate module for scoping, you can use `defdelegate`:

```

defmodule MyApp.MyModel.MySchema do

 defdelegate scope(query, user, params), to: Some.Other.Scope

end

```

[Link to this section](#summary)

 Summary

==========================================

[Callbacks](#callbacks)

------------------------

[scope(query, user, params)](#c:scope/3)

Specify user-accessible items.

[Link to this section](#callbacks)

Callbacks

=============================================

[Link to this callback](#c:scope/3 "Link to this callback")

scope(query, user, params)

==========================

[View Source](https://github.com/schrockwell/bodyguard/blob/v2.4.2/lib/bodyguard/schema.ex#L38 "View Source")

Specs

-----

```

scope(query :: [any](https://hexdocs.pm/elixir/typespecs.html#basic-types)(), user :: [any](https://hexdocs.pm/elixir/typespecs.html#basic-types)(), params :: %{required([atom](https://hexdocs.pm/elixir/typespecs.html#basic-types)()) => [any](https://hexdocs.pm/elixir/typespecs.html#basic-types)()}) ::

  [any](https://hexdocs.pm/elixir/typespecs.html#basic-types)()

```

Specify user-accessible items.

This callback is expected to take a `query` of this schema and filter it

down to results that are only accessible to `user`. Arbitrary `params` may

also be specified.

```

defmodule MyApp.MyModel.MySchema do

 @behaviour Bodyguard.Schema

 import Ecto.Query, only: [from: 2]

 def scope(query, user, \_params) do

 from ms in query, where: ms.user\_id == ^user.id

 end

end

```





API Reference — Bodyguard v2.4.2

try { if(localStorage.getItem('night-mode') === 'true') document.body.className += ' night-mode'; } catch (e) { }

 API Reference Bodyguard v2.4.2

================================

 Modules

----------

[Bodyguard](Bodyguard.html)

Authorize actions at the boundary of a context.

[Bodyguard.Action](Bodyguard.Action.html)

Execute authorized actions in a composable way.

[Bodyguard.NotAuthorizedError](Bodyguard.NotAuthorizedError.html)

Raised when authorization fails.

[Bodyguard.Plug](Bodyguard.Plug.html)

Work with Actions embedded in connections.

[Bodyguard.Plug.Authorize](Bodyguard.Plug.Authorize.html)

Perform authorization in a Plug pipeline.

[Bodyguard.Plug.BuildAction](Bodyguard.Plug.BuildAction.html)

Construct an Action on the connection.

[Bodyguard.Policy](Bodyguard.Policy.html)

Where authorization rules live.

[Bodyguard.Schema](Bodyguard.Schema.html)

Specify user-accessible items.

