Current section
Files
Jump to
Current section
Files
lib/accountable.ex
defmodule Accountable do
@moduledoc """
Documentation for Accountable.
"""
@supported_tokens ~w(access reset_password)
@spec user_by_credentials(String.t(), String.t()) :: {:ok, struct}
def user_by_credentials(email, password) do
case repo.get_by!(user_schema, email: email) do
%{password_hash: nil} ->
{:error, "Authentication disabled"}
user ->
Argon2.check_pass(user, password)
end
end
def user_by_id(id), do: repo.get(user_schema, id)
def create_user(attributes) do
attributes
|> user_changeset()
|> repo.insert()
end
defp user_changeset(attributes) do
attributes = put_password_hash(attributes)
user_schema.changeset(user_schema.__struct__, attributes)
end
@spec token_for_user(struct, String.t()) :: {atom, String.t()}
def token_for_user(user, type \\ "access") do
with true <- Enum.member?(@supported_tokens, type),
{:ok, token, _claims} <- claims(user) do
{:ok, token}
else
_ ->
{:error, "Unsupported token type"}
end
end
@spec user_by_token(String.t()) :: {:ok, struct} | {:error, any}
def user_by_token(token) do
case Accountable.Guardian.resource_from_token(token, %{"typ" => "access"}) do
{:ok, user, _claims} ->
{:ok, user}
err ->
err
end
end
def put_password_hash(%{password: password} = attrs) do
Map.merge(attrs, Argon2.add_hash(password))
end
def put_password_hash(attrs), do: attrs
def repo, do: Application.get_env(:accountable, :ecto_repo)
def user_schema, do: Application.get_env(:accountable, :user_schema, Accountable.User)
def claims(user) do
claims_fn = Application.get_env(:accountable, :claims, &default_claims/1)
claims_fn.(user)
end
def default_claims(user) do
Accountable.Guardian.encode_and_sign(
user,
%{
"typ" => "access"
}
)
end
end