Current section
Files
Jump to
Current section
Files
lib/auth/bcrypt.ex
defmodule Doorman.Auth.Bcrypt do
@moduledoc """
Provides functions for hashing passwords and authenticating users using
[Comonin.Bcrypt](https://hexdocs.pm/comeonin/Comeonin.Bcrypt.html).
## Usage
In an Ecto model call `use Doorman.Auth.Bcrypt`. This will add two functions
to your module. `hash_password/1` and `authenticate/2`.
You can also pass options to the `use` call to specify which virtual field to
read from and which database field to put the hashed password on.
The default value for `virtual_field` is `password` and the default for
`database_field` is `password_digest`.
## Example
To hash the `passcode` field and save it as `hashed_passcode` you could do
the following:
```
defmodule User do
use Ecto.Schema
use Doorman.Auth.Bcrypt, virtual_field: "passcode",
database_field: "hashed_passcode"
import Ecto.Changeset
def create_changeset(struct, changes) do
struct
|> cast(changes, ~w(email password))
|> hash_password
end
end
```
To authenticate a user in your application, you can use `authenticate/2`:
```
user = Repo.get(User, 1)
User.authenticate(user, "password")
```
"""
alias Comeonin.Bcrypt
defmacro __using__(options) do
options = Map.merge(default_options, Map.new(options))
quote do
def hash_password(changeset) do
password = Ecto.Changeset.get_change(
changeset,
unquote(options[:virtual_field])
)
if password do
hashed_password = Bcrypt.hashpwsalt(password)
changeset
|> Ecto.Changeset.put_change(
unquote(options[:database_field]),
hashed_password
)
else
changeset
end
end
def authenticate(user, password) do
Bcrypt.checkpw(password, user.password_digest)
end
end
end
defp default_options do
%{
virtual_field: :password,
database_field: :password_digest,
}
end
end