ScopedPolicy (ScopedPolicy v0.2.1) View Source

Provides a way to scope Bodyguard policy authorize functions.

Bodyguard is a simple library that provides conventions for defining an authorize function that protects boundaries of your application. The function takes three arguments, action, object and params. The action is an atom describing what we are authorizing, the object is usually the logged in user and the params is some value that gives any extra information about the action we are performing.

Although the object is most often the logged in user, for more complicated application it may contain more information. For example, If we imagine an Phoenix application that runs on multiple subdomains, the authorization might depend on the current subdomain. In that case the object could contain both the subdomain and the user:

%{
  subdomain: :portal,
  current_user: some_user
}

or

%{
  subdomain: :app,
  current_user: some_user
}

In this case we may want to have different authorization functions depending on the subdomain.

defmodule MyPolicy do

  # Rules for `portal`
  def authorize(:enter, %{subdomain: :portal, current_user: %{role: role}}, _params)
    when role in [:portal_user],
    do: true

  # Rules for `app`
  def authorize(:enter, %{subdomain: :app, current_user: %{role: role}}, _params)
    when role in [:app_user],
    do: true

end

Although this works fine, this can become noisy when there are a lot of authorization clauses and policy modules.

This module provides a way to scope authorization functions based on their object, as well as to transform (focus) the object for functions within the scope.

For example, the rules above can be written as:

defmodule MyPolicy do

  use ScopedPolicy

  def focus_object(%{current_user: current_user}), do: current_user

  scoped_policy match: %{subdomain: :portal}, focus_object: &MyPolicy.focus_object/1 do
    def authorize(:enter, %{role: role}, _params) when role in [:portal_user], do: true
  end

  # Rules for `app`
  scoped_policy match: %{subdomain: :app}, focus_object: &MyPolicy.focus_object/1 do
    def authorize(:enter, %{role: role}, _params) when role in [:app_user], do: true
  end

end

Link to this section Summary

Functions

Configure a module to use scoped policies.

Define a scoped policy.

Link to this section Functions

Link to this macro

__using__(opts)

View Source (macro)

Configure a module to use scoped policies.

Options

  • :debug - if this is true, output debug information using the Elixir Logger
Link to this macro

scoped_policy(opts, block)

View Source (macro)

Define a scoped policy.

Options

  • :match - the pattern to match against the authorization object. This can either be a single pattern or a list of patterns, any of which can match.

  • :parent_policy - the authorize function is called on this policy module before running this scope. This can be used to build hierarchical policies, or to have a global policy.

  • :focus_object - a captured function that is applied to the object before the authorize functions are called in this scope. This is used to focus the object into the relevant shape within the scope.

  • :allow_all? - this ignores any functions within the scope. The authorization will always suceed.