Packages

Plug based authorization and resource loading. Aimed at Phoenix, but depends only on Plug. MIT license Updated to compile clean with Elixir 1.4

Current section

Files

Jump to
policy_wonk lib enforce.ex
Raw

lib/enforce.ex

defmodule PolicyWonk.Enforce do
@moduledoc """
This turns your policy module into a plug that can be used in a router.
## Usage
The only time you should directly use the `PolicyWonk.Enforce` module is to call
`use PolicyWonk.Enforce` when defining your policy module.
Example policy module:
defmodule MyAppWeb.Policies do
use PolicyWonk.Policy # set up support for policies
use PolicyWonk.Enforce # turn this module into an enforcement plug
def policy( assigns, :current_user ) do
case assigns[:current_user] do
%MyApp.Account.User{} ->
:ok
_ ->
{:error, :current_user}
end
end
def policy_error(conn, :current_user) do
MyAppWeb.ErrorHandlers.unauthenticated(conn, "Must be logged in")
end
end
To enforce your policies as a plug, you can just use the new module you created.
Enforce policies in a router:
pipeline :browser_session do
plug MyAppWeb.Policies, :current_user
plug MyAppWeb.Policies, [:policy_a, :policy_b]
end
"""
# ===========================================================================
defmacro __using__(use_opts) do
quote do
@doc false
def init(policies_or_opts) do
case Keyword.keyword?(policies_or_opts) do
true ->
policies_or_opts
|> Keyword.put_new(:policy_module, unquote(use_opts[:policy_module]) || __MODULE__)
|> PolicyWonk.Enforce.init()
false ->
PolicyWonk.Enforce.init(policy_module: __MODULE__, policies: policies_or_opts)
end
end
@doc false
def call(conn, opts), do: PolicyWonk.Enforce.call(conn, opts)
end
# quote
end
# defmacro
# ===========================================================================
# define a policy enforcement error here
defmodule Error do
@moduledoc false
defexception message: "#{IO.ANSI.red()}Policy endforcement failed#{IO.ANSI.default_color()}\n"
end
# ===========================================================================
@doc false
def init(opts) when is_list(opts), do: do_init(opts[:policy_module], opts[:policies])
defp do_init(nil, _),
do:
raise(
Error,
message: "#{IO.ANSI.red()}Must supply a valid :policy_module#{IO.ANSI.default_color()}"
)
defp do_init(_, []),
do:
raise(
Error,
message:
"#{IO.ANSI.red()}Must supply at least one policy to enforce#{IO.ANSI.default_color()}"
)
defp do_init(policy_module, policies) when is_atom(policy_module) and is_list(policies) do
%{
policy_module: policy_module,
policies: policies
}
end
defp do_init(policy_module, policy) do
do_init(policy_module, [policy])
end
# ----------------------------------------------------------------------------
# ------------------------------------------------------------------------
@doc false
def call(conn, %{policy_module: policy_module, policies: policies}) do
PolicyWonk.Policy.enforce(conn, policy_module, policies)
end
end