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} <- Accountable.Guardian.encode_and_sign(user, claims) 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() do
%{
"typ" => "access",
"https://hasura.io/jwt/claims": %{
"x-hasura-allowed-roles": ["user"],
"x-hasura-default-role": "user",
"x-hasura-user-id": "1234567890",
"x-hasura-org-id": "123",
"x-hasura-custom": "custom-value"
}
}
end
end