sphinx v0.1.2 Sphinx.Plugs
Module with convenient plug functions. You might want to import it in
your web.ex
inside controller
scope.
As well as, to make sure all your endpoints have authorization performed,
you may want to include plug :ensure_authorization
in your pipelines.
Summary
Functions
Main plug for authorizing request. Fetches the current resource, authorizes
action, action, and resource with authorizer, then either raises Sphinx.NotAuthorizedError
,
or flags conn
as authorized, setting resource to conn.assigns.resource
Plug for ensuring you’ve performed authorization (or skipped it). If you haven’t
it would raise Sphinx.AuthorizationNotPerformedError
when you respond to conn
Plug for skipping authorization check if you’re using ensure_authorization
.
It’d flag conn
’s authorization status as skipped, and wouldn’t perform
any authorizations or checks afterwards
Functions
Main plug for authorizing request. Fetches the current resource, authorizes
action, action, and resource with authorizer, then either raises Sphinx.NotAuthorizedError
,
or flags conn
as authorized, setting resource to conn.assigns.resource
.
Fetching resource
Sphinx take number of steps to fetch current resource.
First of all, it checks if
:resource_fetcher
option is passed. If it is, it’d be called withconn
and resulting value would be used asresource
.If
:resource_fetcher
hasn’t passed, Sphinx need to know module of resource to fetch it. It can be passed through:model
option, or can be inferred from controller name by removing trailingController
, and then, if required, by removingApi
namespace from it. For example, any of[MyApp.UserController, MyApp.Api.UserController]
infers toMyApp.User
.If action of request is one of
[:index, :create, :new]
(collection actions), authorization would be done using module itself. You can expand this list by passing:collection
option when calling plug.At last, Sphinx gets id of resource from
params
using:id_key
option (by default, it’s “id”), then gets resource from repo calling:repo.get!(model, id)
. So, if your path looks likeusers/:user_id/posts/:id
, and you want to authorize by user, you’d need to pass[id_key: "user_id", model: User]
as options.
Getting actor
By default, actor is taken from :current_user
field of conn
assigns. You can override
this by providing :actor_fetcher
function or {Module, :function_name} pair either in
app’s config or when calling plug. This function would be called with current conn
and
result will be passed to authorizer as an actor.
Action
Action is the name of controller function which handles current request. Common REST actions
are: [:index, :show, :create, :update, :delete]
.
Authorizer
Aithorizer is module for authorizing action with given actor and resource. You can either
pass it when calling :authorize
, or it will be inferred from current controller’s name
by replacing trailing “Controller” with “Authorizer”. For example, if your controller is
MyApp.Api.UserController
, it first tries to load MyApp.Api.UserAuthorizer
, then
MyApp.UserAuthorizer
. Only Api
namespace is dropped from inferring, all other namespaces
are preserved. Example authorizer:
defmodule MyApp.UserAuthorizer do
def authorize?(_, :index, Post), do: true # index is public
def authorize?(%User{id: id}, :update, %Post{author_id: id}), do: true # author can update own posts
def authorize?(_, :update, _),
do: {false, "Post editing limited to post authors only"} # fail with custom reason
def authorize?(_, :delete_all, Post), do: false # fail with default message, see [`Sphinx.NotAuthorizedError`](Sphinx.NotAuthorizedError.html) docs
end
Options
All options are optional if naming conventions are preserved and repo is given in app’s config.
:actor_fetcher
- function/module-function pair to use for getting actor, called with conn.:authorizer
- authorize module to use.:resource_fetcher
- function, or keyword with function values. If given function, all actions will use that function to fetch resource, if given keyword, functions for existing action keys will be used when exists, otherwise default Sphinx fetching is used. Function called with conn, and passes whatever it receives to authorizer as resource.:collection
- atom or list of atoms corresponding to actions, which should authorized by module itself, instead of instance of module. By default,[:index, :new, :create]
actions always authorized by module.:repo
- repo from where Sphinx gets resource. It’s calledget!
function with module, and id as parameters (like Ecto’s Repo).:model
- module of resource for fetching and authorizing with it.:id_key
- key for id param, inconn.params
. By default it’s “id”, by you may want to probably change this for nested resources authorized by parents.:only
- atom or list of atoms to authorize. This should correspond to controller’s action names. Only given actions would be authorized.:except
- atom or list of atoms to exclude from authorizing.
Plug for ensuring you’ve performed authorization (or skipped it). If you haven’t
it would raise Sphinx.AuthorizationNotPerformedError
when you respond to conn
.
Plug for skipping authorization check if you’re using ensure_authorization
.
It’d flag conn
’s authorization status as skipped, and wouldn’t perform
any authorizations or checks afterwards.
Options
:only
- atom or list of atoms to skip. This should correspond to controller’s action names. Only given actions would be skipped.:except
- atom or list of atoms to exclude from skipping.
Examples
defmodule MyApp.UserController do
use MyApp.Web, :controller
plug skip_authorization, only: :index
def index(conn, params) do
...
end
end