# Pundit
[![Build Status](](
[![Hex pm](](
[![API Docs](](

Pundit provides a set of helpers which guide you in leveraging regular Elixir methods to
build a simple authorization system.  This library is based heavily on Jonas Nicklas' [Ruby project of the same name](

Simple Elixir functions are defined for a given struct and allow you to encapsulate authentication logic.  You can use
this code within a module that is an Ecto.Schema, but that's not necessary (Ecto isn't required).  The action names are taken from the list
of [actions defined by Phoenix controllers](

## Installation

To install Pundit, just add an entry to your `mix.exs`:

``` elixir
def deps do
    # ...
    {:pundit, "~> 1.0"}

(Check [Hex]( to make sure you're using an up-to-date version number.)

## Usage
Here's a basic example, starting with a simple struct for a `Post`.  A module named `Post.Policy` should be created to
encapsulate all of the access methods (`Pundit` will automatically look for the `<struct module>.Policy` module
to determine the module name to look at for access methods).

To declare an initial set of access functions (`show?`, `edit?`, `delete?`, etc)
which all return `false` (default safe!), just `use` `Pundit.DefaultPolicy`.  You can then override the functions as needed
with the logic necessary to determine whether a user should be able to perform the given action.  In this example, we only
determine whether a user can `edit?` a post, leaving all other functions (like `delete?`) to return the default of `false`.

defmodule Post do
  defstruct [:author, :title, :body, :comments]

  defmodule Policy do
    # This will initialize all the action functions, all of which return false
    # by default. Override them individually to return true when they should,
    # like edit? is overriden below.
    use Pundit.DefaultPolicy

    def edit?(post, user) do ==

post = %Post{author: "Snake Plissken"}
author = %{name: "Snake Plissken"}
# next line is same as Pundit.can?(post, author, :edit?)
# Pundit will just delegate to Post.Policy.edit?(post, user)
if Pundit.edit?(post, author) do
  IO.puts("Can edit!")

if Pundit.delete?(post, author) do
  IO.puts("This line should never be called")

# raise exception if user should be able to do a thing
Pundit.authorize!(post, author, :edit?)

## Scope
You can also provide query scope for a struct (say, if you're using `Ecto.Schema`) for a given user.  For instance,
say our `Post` was an `Ecto` schema.  Our function for scoping all `Post`s to a specific `User` could be to find all
`Post`s that were authored by a user.  For instance:

defmodule Post do
  use Ecto.Schema
  import Ecto.Query, only: [from: 2]

  defmodule Policy do
    use Pundit.DefaultPolicy
    def scope(query, user) do
      from post in query,
        where: post.author_id == ^

user = MyApp.Repo.get(User, 1)
posts = Pundit.scope(Post, user) |> Repo.all()

query = from p in Post, where: p.comment_count > 10
popular_posts = Pundit.scope(query, user) |> Repo.all()

See [the docs]( for more examples.

## Running Tests

To run tests:

$ mix test

## Reporting Issues

Please report all issues [on github](