README.md

# Sentinel
Things I wish [Guardian](https://github.com/ueberauth/guardian) included
out of the box. Routing, confirmation emails, password reset emails.
It's really just a thin wrapper on Guardian, and some ground work, but
really, everybody shouldn't have to repeat this themselves when they
build stuff.

Shamelessly borrows from
[Devise](https://github.com/plataformatec/devise) and
[PhoenixTokenAuth](https://github.com/manukall/phoenix_token_auth).

If there are any ways that you feel that this library isn't "functional"
or the code isn't written in "idiomatic Elixir" or whatever see the
`Contributing/Want something new?` section.

## Installation
Here's how to add it to your phoenix project, and things you need to
setup:

```
# mix.exs
{:sentinel, "~> 0.0.5"},

# If you'd like to database back your tokens, and prevent replayability
{:guardian_db, "~> 0.4.0"},

# Add mailman as a peer dependency
#{:mailman, "~> 0.2.1"}
# OR
#{:mailman, github: "Joe-noh/mailman"}
```

### The User Model
Your user model must have at least the following fields, and the
`permissions/1` function must be defined, in order to encode permissions
into your token, currently even if the function is empty, and you don't
plan on using [Guardian
permissions](https://github.com/ueberauth/guardian/#permissions).

```elixir
defmodule MyApp.User do
  use Ecto.Model

  schema "users" do
    field  :email,                       :string     # or :username
    field  :role,                        :string
    field  :hashed_password,             :string
    field  :hashed_confirmation_token,   :string
    field  :confirmed_at,                Ecto.DateTime
    field  :hashed_password_reset_token, :string
    field  :unconfirmed_email,           :string
  end

  @required_fields ~w(email)
  @optional_fields ~w()

  def changeset(model, params \\ :empty) do
    model
    |> cast(params, @required_fields, @optional_fields)
  end

  def permissions(role) do
  end
end
```

### Configure Guardian
Example config:

```
config :guardian, Guardian,
  allowed_algos: ["HS512"], # optional
  verify_module: Guardian.JWT,  # optional
  issuer: "MyApp",
  ttl: { 30, :days },
  verify_issuer: true, # optional
  secret_key: "guardian_sekret",
  serializer: Sentinel.GuardianSerializer,
  hooks: GuardianDb
```

[More info](https://github.com/ueberauth/guardian#installation)

### Configure GuardianDb
```
config :guardian_db, GuardianDb,
  repo: MyApp.Repo
```

The database backing for your tokens:

```elixir
defmodule MyApp.Repo.Migrations.GuardianDb do
  use Ecto.Migration

  def up do
    create table(:guardian_tokens, primary_key: false) do
      add :jti, :string, primary_key: true
      add :typ, :string
      add :aud, :string
      add :iss, :string
      add :sub, :string
      add :exp, :bigint
      add :jwt, :text
      add :claims, :map
      timestamps
    end
  end

  def down do
    drop table(:guardian_tokens)
  end
end
```


[More info](https://github.com/hassox/guardian_db)

### Configure Sentinel
```
config :sentinel,
  app_name: "Test App",
  user_model: MyApp.User,
  email_sender: "test@example.com",
  crypto_provider: Comeonin.Bcrypt,
  auth_handler: Sentinel.AuthHandler, #optional
  repo: MyApp.Repo,
  confirmable: :required, # possible options {:false, :required, :optional},optional config
  endpoint: MyApp.Endpoint,
  router: MyApp.Router,
  user_view: MyApp.UserModel.View
```

### Configure Mailman
```
# Local server example
config :mailman,
  port: 1234

# Mailgun Example
config :mailman,
  port: 587,
  address: "smtp.mailgun.org",
  user_name: System.get_env("MAILGUN_USERNAME"),
  password: System.get_env("MAILGUN_PASSWORD")

# Mandrill Example
config :mailman,
  port: 587,
  address: "smtp.mandrillapp.com",
  user_name: System.get_env("MANDRILL_USERNAME"),
  password: System.get_env("MANDRILL_PASSWORD")
```

[More info](https://github.com/kamilc/mailman/)

### Routes
Add the following to your routes file to add default routes, complete
with protection

```elixir
defmodule MyApp.Router do
  use MyApp.Web, :router
  require Sentinel

  scope "/api" do
    pipe_through :api

    Sentinel.mount
  end
end
```

The generated routes are:

method | path | description
-------|------|------------
POST | /api/users | register
POST | /api/users/:id/confirm | confirm account
POST | /api/sessions | login, will return a token as JSON
DELETE |  /api/sessions | logout, invalidated the users current authentication token
POST | /api/password_resets | request a reset-password-email
POST | /api/password_resets/reset | reset a password
GET  | /api/account               | get information about the current user. at the moment this includes only the email address
PUT  | /api/account               | update the current users email or password

You may run into an issue here if you set the scope to `scope "/api",
MyApp.Router do`. Something to be aware of.

## Overriding the Defaults

### Confirmable
By default users are not required to confirm their account to login. If
you'd like to require confirmation set the `confirmable` configuration
field to `:required`. If you don't want confirmation emails sent, set
the field to `:false`. The default is `:optional`.

### Custom Routes
If you want to customize the routes, or use your own controller
endpoints you can do that by overriding the individual routes shown
below:

```elixir
post  "users",                 Sentinel.Controllers.Users, :create
post  "users/:id/confirm",     Sentinel.Controllers.Users, :confirm
post  "sessions", Sentinel.Controllers.Sessions, :create
delete  "sessions", Sentinel.Controllers.Sessions, :delete
post  "password_resets", Sentinel.Controllers.PasswordResets, :create
post  "password_resets/reset", Sentinel.Controllers.PasswordResets, :reset
get   "account",               Sentinel.Controllers.Account, :show
put   "account",               Sentinel.Controllers.Account, :update
```

### Mailer Customization/I18n
You setup your own email templates to send out by configuring the
`mailman` `html_email_tempaltes` and `text_email_templates` config
variables to point to your own email template directories.

Internationalization is easy. Just make a folder for each langauge under
your email template directory. Pass in the language to your mailer
config

### Auth Error Handler
If you'd like to write your own custom authorization or authentication
handler change the `auth_handler` Sentinel configuration option
to the module name of your handler.

It must define two functions, `unauthorized/2`, and `unauthenticated/2`,
where the first parameter is the connection, and the second is
information about the session.

## Contributing/Want something new?
Create an issue. Preferably with a PR. If you're super awesome
include tests.

As you recall from the license, this is provided as is. I don't make any
money on this, so I do support when I feel like it. That said, I want to
do my best to contribute to the Elixir/Phoenix community, so I'll do
what I can.

Having said that if you bother to put up a PR I'll take a look, and
either merge it, or let you know what needs to change before I do.
Having experienced sending in PRs and never hearing anything about
them, I know it sucks.

## TODO
Ueberauth integration

Add a mix tasks that does all the configuration? and one that includes
the user model and router stuff for a fresh, fresh project.

Mailer subject I18n

## Still on the Roadmap
Session/View vs JWT/API configuration

Multiple Model types (user, admin)

[Devise lockable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Lockable) equivalent

[Devise
trackable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Trackable) equivalent

[Devise
timeout-able](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Timeoutable) equivalent

[Devise enterprise security
addon](https://github.com/phatworx/devise_security_extension) equivalent