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
Current section
Files
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