Packages
guard
0.1.0
0.19.1
0.19.0
0.18.0
0.17.2
0.17.1
0.17.0
0.16.3
0.16.2
0.16.1
0.16.0
0.15.3
0.15.2
0.15.1
0.15.0
0.14.9
0.14.8
0.14.7
0.14.6
0.14.5
0.14.4
0.14.3
0.14.2
0.14.1
0.14.0
0.13.1
0.13.0
0.12.9
0.12.8
0.12.7
0.12.6
0.12.5
0.12.4
0.12.3
0.12.2
0.12.1
0.12.0
0.11.3
0.11.2
0.11.1
0.11.0
0.10.4
0.10.3
0.10.2
0.10.1
0.10.0
0.9.0
0.8.0
0.7.1
0.7.0
0.6.1
0.6.0
0.5.0
0.4.1
0.4.0
0.3.0
0.2.0
0.1.0
Useful package for dealing with user authentication and signup
Current section
Files
Jump to
Current section
Files
lib/doorman/session.ex
defmodule Doorman.Session do
alias Doorman.{User, Authenticator, Users}
defp has_perm?(user, perm) do
Map.has_key?(user.perms || %{}, perm)
end
defp verify_params(user, params) do
case params do
%{"perm" => perm} ->
if has_perm?(user, perm) do
{:ok, user}
else
{:error, :forbidden}
end
%{"all_perms" => all_perms} ->
if Enum.reduce_while(all_perms, true, fn (perm, acc) ->
if has_perm?(user, perm) do
{:cont, true}
else
{:halt, false}
end
end) do
{:ok, user}
else
{:error, :forbidden}
end
%{"any_perms" => any_perms} ->
if Enum.reduce_while(any_perms, true, fn (perm, acc) ->
if has_perm?(user, perm) do
{:halt, true}
else
{:cont, false}
end
end) do
{:ok, user}
else
{:error, :forbidden}
end
_ -> {:ok, user}
end
end
defp check_password_with_message(user, password, params) do
case check_password(user, password) do
true ->
verify_params(user, params)
_ -> {:error, "wrong_password"}
end
end
defp check_pin_with_message(user, pin, params) do
case Authenticator.use_pin(user, pin) do
{:ok, user} ->
verify_params(user, params)
error -> error
end
end
def authenticate(params = %{"email" => email, "password" => password}) do
user = Users.get_by_email(email)
check_password_with_message(user, password, params)
end
def authenticate(params = %{"username" => username, "password" => password}) do
user = Users.get_by_username(username)
check_password_with_message(user, password, params)
end
def authenticate(params = %{"username" => username, "pin" => pin}) do
user = Users.get_by_username(username)
check_pin_with_message(user, pin, params)
end
def authenticate(params = %{"mobile" => mobile, "pin" => pin}) do
user = Users.get_by(mobile: mobile) || Users.get_by!(requested_mobile: mobile)
case check_pin_with_message(user, pin, params) do
{:ok, user} ->
confirm_user_mobile(user, mobile)
error -> error
end
end
def authenticate(%{"token" => token}) do
case Doorman.Guardian.decode_and_verify(token) do
{:ok, claims} -> user_from_claim(claims)
_ -> {:error, "bad_token"}
end
end
def authenticate({:jwt, jwt}) do
case Doorman.Guardian.decode_and_verify(jwt) do
{:ok, claims} -> user_from_claim(claims)
_ -> {:error, "bad_token"}
end
end
def authenticate(_) do
{:error, "missing_credentials"}
end
defp confirm_user_mobile(%User{} = user, mobile) do
if user.requested_mobile == mobile do
Users.update_user(user, %{mobile: mobile, requested_mobile: nil})
else
{:ok, user}
end
end
defp user_from_claim(claims) do
case claims do
%{"sub" => "User:" <> user_id} ->
case Users.get(user_id) do
nil -> {:error, "bad_claims"}
user -> confirm_user_email(claims, user)
end
_ -> {:error, "bad_claims"}
end
end
defp confirm_user_email(claims, user) do
case Map.get(claims, "typ") do
"login" ->
if user.requested_email != nil && user.requested_email == Map.get(claims, "requested_email") do
Users.update_user(user, %{email: user.requested_email, requested_email: nil})
else
{:ok, user}
end
_ -> {:ok, user}
end
end
defp check_password(user, password) do
case user do
nil -> false
_ -> User.check_password(user, password)
end
end
end