policy_wonk v0.2.0 PolicyWonk.Enforce
This the main policy enforcement plug.
Policy Enforcement
The goal of PolicyWonk.Enforce
is to evaluate one or more policies and either halt the plug stack, or allow it to continue.
In a router:
defmodule MyApp.Router do
use MyApp.Web, :router
pipeline :browser_session do
plug PolicyWonk.LoadResource, :current_user
plug PolicyWonk.Enforce, :current_user
end
pipeline :admin do
plug PolicyWonk.Enforce, {:user_permission, "admin"}
end
. . .
In a controller:
defmodule AdminController do
use Phoenix.Controller
plug PolicyWonk.Enforce, {:user_permission, "admin"}
def index(conn, _params) do
send_resp(conn, 200, "OK")
end
end
If any policy returns anything other than :ok
, then the plug stack is halted and given a chance to exit gracefully.
Specifying Policies
The main parameter to the PolicyWonk.Enforce
plug is either a single policy or a list of policies.
plug PolicyWonk.Enforce, :policy_1
plug PolicyWonk.Enforce, [:policy_1, :policy_2]
The “name” of the policy can be pretty much any type you want to pass in to your policy. It doesn’t need to be an atom, although that is very convenient to match on.
These are all valid policy specifiers:
plug PolicyWonk.Enforce, [:policy_1, :policy_2]
plug PolicyWonk.Enforce, {:policy_s, "a string")
plug PolicyWonk.Enforce, %{id: "an_id", data: %{color: "blue"}}
The idea is that you create matching policy functions and rely Elixir’s function matching to select the right one.
def policy( assigns, :policy_1 ) do
:ok
end
def policy( assigns, {:policy_2, name} ) do
IO.inspect name
:ok
end
def policy( assigns, %{id: id, data: %{color: color} ) do
IO.inspect color
:ok
end
Use with Guards
When the PolicyWonk.Enforce
is invoked inside a Phoenix controller, you can add guards against the current action.
plug PolicyWonk.Enforce, :policy_1 when action in [:index]
Handling Policy Failures
If any policy fails, then the PolicyWonk.Enforce
plug calls your policy_error
function with the data returned by the policy and halts the plug stack.
This is where you transform the conn to handle the error gracefully.
Specifying the Policy Module
As discussed in the documentation for PolicyWonk.Policy,
the PolicyWonk.Enforce
plug will look for policies first in your controller (or router) as appropriate. Then in the policy module/s specified in the config block.
If you are using the plug outside phoenix, then just the config block is checked.
You can also specify exactly which module to look in at the time you invoke the plug.
plug PolicyWonk.Enforce, %{policies: [:policy_1], module: MyPoliciesModule}
If you do specify the module, then that is the only one PolicyWonk.Enforce
will look in for policies.
Evaluating Policies Outside of the Plug
You will often want to evaluate policies outside of the plug chain. For example, to show only show UI if the user has permission to see it.
PolicyWonk.Enforce
provides the authorized?
API for just this purpose. It evaluates the policy and returns a simple boolean value indicating success or failure.
There are two ways to access the authorized?
API. The first is to call it directly, specifying the module the policies are in.
The second, prettier, way is to call use PolicyWonk.Enforce
in any modules where you implement policies. This creates a local authorized?
function names the module for you.
defmodule AdminController do
use Phoenix.Controller
use PolicyWonk.Enforce
. . .
def policy(assigns, :is_admin) do
. . .
end
end
defmodule UserController do
use Phoenix.Controller
def show(conn, params) do
if AdminController.authorized?( conn, :is_admin ) do
. . .
else
. . .
end
end
end
Both forms of authorized?
simulate the policy finding found in the plug.
Summary
Functions
Evaluate a policy outside of the plug stack. Returns a simple true/false boolean
indicating
if the policy succeeded or failed. Your policy_error
function is not called in the event of
a failure
Call is used by the plug stack
Initialize an invocation of the plug
Functions
Evaluate a policy outside of the plug stack. Returns a simple true/false boolean
indicating
if the policy succeeded or failed. Your policy_error
function is not called in the event of
a failure.
Parameters
module
A module to look for policies in. If nil, on the config policies will be used.data
Resource data to passed into your policy. If you pass aconn
in, then theassigns
field be extracted and sent to your policy.policies
A list of policies to be evaluated. Can also be a single policy.
Initialize an invocation of the plug.