canary v1.1.1 Canary.Plugs
Plug functions for loading and authorizing resources for the current request.
The plugs all store data in conn.assigns (in Phoenix applications, keys in conn.assigns can be accessed with @key_name
in templates)
In order to use the plug functions, you must use Canary
.
You must also specify the Ecto repo to use in your configuration:
config :canary, repo: Project.Repo
If you wish, you may also specify the key where Canary will look for the current user record to authorize against:
config :canary, current_user: :some_current_user
You can specify a handler function (in this case, Helpers.handle_unauthorized
) to be called when an action is unauthorized like so:
config :canary, unauthorized_handler: {Helpers, :handle_unauthorized}
or to handle when a resource is not found:
config :canary, not_found_handler: {Helpers, :handle_not_found}
Canary will pass the conn
to the handler function.
Summary
Functions
Authorize the current user for the given resource
Authorize the given resource and then load it if authorization succeeds
Load the given resource
Functions
Authorize the current user for the given resource.
In order to use this function,
1) conn.assigns[Application.get_env(:canary, :current_user, :current_user)]
must be an ecto
struct representing the current user
2) conn.private
must be a map (this should not be a problem unless you explicitly modified it)
If authorization succeeds, sets conn.assigns.authorized
to true.
If authorization fails, sets conn.assigns.authorized
to false.
For the :index
, :new
, and :create
actions, the resource in the Canada.Can
implementation
should be the module name of the model rather than a struct. A struct should be used instead of
the module name only if the :persisted
key is used and you want to override the default
authorization behavior. This can be useful when dealing with nested resources.
For example:
use
def can?(%User{}, :index, Post), do: true
instead of
def can?(%User{}, :index, %Post{}), do: true
or
use
def can?(%User{id: user_id}, :index, %Post{user_id: user_id}), do: true
if you are dealing with a nested resource, such as, “/post/post_id/comments”
Required opts:
:model
- Specifies the module name of the model to authorize access to
Optional opts:
:only
- Specifies which actions to authorize:except
- Specifies which actions for which to skip authorization:preload
- Specifies association(s) to preload:id_name
- Specifies the name of the id inconn.params
, defaults to “id”:id_field
- Specifies the name of the ID field in the database for searching :id_name value, defaults to “id”.:persisted
- Specifies the resource should always be loaded from the database, defaults to false:unauthorized_handler
- Specify a handler function to be called if the action is unauthorized
Examples:
plug :authorize_resource, model: Post
plug :authorize_resource, model: User, preload: :posts
plug :authorize_resource, model: User, only: [:index, :show], preload: :posts
plug :load_resource, model: Post, id_name: "post_id", only: [:index], persisted: true, preload: :comments
plug :load_resource, model: Post, id_name: "slug", id_field: "slug", only: [:show], persisted: true
Authorize the given resource and then load it if authorization succeeds.
If the resource cannot be loaded or authorization fails, conn.assigns.resource_name is set to nil.
The result of the authorization (true/false) is assigned to conn.assigns.authorized.
Also, see the documentation for load_resource/2 and authorize_resource/2.
Required opts:
:model
- Specifies the module name of the model to load resources from
Optional opts:
:as
- Specifies theresource_name
to use:only
- Specifies which actions to authorize:except
- Specifies which actions for which to skip authorization:preload
- Specifies association(s) to preload:id_name
- Specifies the name of the id inconn.params
, defaults to “id”:id_field
- Specifies the name of the ID field in the database for searching :id_name value, defaults to “id”.:unauthorized_handler
- Specify a handler function to be called if the action is unauthorized:not_found_handler
- Specify a handler function to be called if the resource is not found
Note: If both an :unauthorized_handler
and a :not_found_handler
are specified for load_and_authorize_resource
,
and the request meets the criteria for both, the :unauthorized_handler
will be called first.
Examples:
plug :load_and_authorize_resource, model: Post
plug :load_and_authorize_resource, model: User, preload: :posts, as: :the_user
plug :load_and_authorize_resource, model: User, only: [:index, :show], preload: :posts, as: :person
plug :load_and_authorize_resource, model: User, except: [:destroy]
plug :load_and_authorize_resource, model: Post, id_name: "slug", id_field: "slug", only: [:show], persisted: true
Load the given resource.
Load the resource with id given by conn.params["id"]
(or conn.params[opts[:id_name]]
if opts[:id_name]
is specified)
and ecto model given by opts[:model]
into conn.assigns.resource_name
.
resource_name
is either inferred from the model name or specified in the plug declaration with the :as
key.
To infer the resource_name
, the most specific(right most) name in the model’s
module name will be used, converted to underscore case.
For example, load_resource model: Some.Project.BlogPost
will load the resource into
conn.assigns.blog_post
If the resource cannot be fetched, conn.assigns.resource_name
is set
to nil.
By default, when the action is :index
, all records from the specified model will be loaded. This can
be overridden to fetch a single record from the database by using the :persisted
key.
Currently, :new
and :create
actions are ignored, and conn.assigns.resource_name
will be set to nil for these actions. This can be overridden to fetch a single record from the database
by using the :persisted
key.
The :persisted
key can override how a resource is loaded and can be useful when dealing
with nested resources.
Required opts:
:model
- Specifies the module name of the model to load resources from
Optional opts:
:as
- Specifies theresource_name
to use:only
- Specifies which actions to authorize:except
- Specifies which actions for which to skip authorization:preload
- Specifies association(s) to preload:id_name
- Specifies the name of the id inconn.params
, defaults to “id”:id_field
- Specifies the name of the ID field in the database for searching :id_name value, defaults to “id”.:persisted
- Specifies the resource should always be loaded from the database, defaults to false:not_found_handler
- Specify a handler function to be called if the resource is not found
Examples:
plug :load_resource, model: Post
plug :load_resource, model: User, preload: :posts, as: :the_user
plug :load_resource, model: User, only: [:index, :show], preload: :posts, as: :person
plug :load_resource, model: User, except: [:destroy]
plug :load_resource, model: Post, id_name: "post_id", only: [:new, :create], persisted: true
plug :load_resource, model: Post, id_name: "slug", id_field: "slug", only: [:show], persisted: true