ufosc/AskAGator

View on GitHub
lib/ask_a_gator/accounts.ex

Summary

Maintainability
Test Coverage
defmodule AskAGator.Accounts do
  @moduledoc """
  The Accounts context.
  """

  import Ecto.Query, warn: false
  alias AskAGator.Repo

  alias AskAGator.Accounts.User

  @doc """
  Returns the list of users.

  ## Examples

      iex> list_users()
      [%User{}, ...]

  """
  def list_users do
    Repo.all(User)
  end

  @doc """
  Gets a single user.

  Raises `Ecto.NoResultsError` if the User does not exist.

  ## Examples

      iex> get_user!(123)
      %User{}

      iex> get_user!(456)
      ** (Ecto.NoResultsError)

  """
  def get_user!(id), do: Repo.get!(User, id)

  @doc """
  Creates a user.

  ## Examples

      iex> create_user(%{field: value})
      {:ok, %User{}}

      iex> create_user(%{field: bad_value})
      {:error, %Ecto.Changeset{}}

  """
  def create_user(attrs \\ %{}) do
    %User{}
    |> User.changeset(attrs)
    |> Repo.insert()
  end

  @doc """
  Updates a user.

  ## Examples

      iex> update_user(user, %{field: new_value})
      {:ok, %User{}}

      iex> update_user(user, %{field: bad_value})
      {:error, %Ecto.Changeset{}}

  """
  def update_user(%User{} = user, attrs) do
    user
    |> User.changeset(attrs)
    |> Repo.update()
  end

  @doc """
  Deletes a User.

  ## Examples

      iex> delete_user(user)
      {:ok, %User{}}

      iex> delete_user(user)
      {:error, %Ecto.Changeset{}}

  """
  def delete_user(%User{} = user) do
    Repo.delete(user)
  end

  @doc """
  Returns an `%Ecto.Changeset{}` for tracking user changes.

  ## Examples

      iex> change_user(user)
      %Ecto.Changeset{source: %User{}}

  """
  def change_user(%User{} = user) do
    User.changeset(user, %{})
  end

  def authenticate_by_email_password(email, password) do
    user = Repo.get_by(User, email: email)
    if user && Bcrypt.verify_pass(password, user.password_hash) do
      {:ok, user}
    else
      {:error, :unauthorized}
    end
  end

  defp verify_old_pass_if_exists(attrs) do
    case Map.fetch(attrs, :old_password) do
      {:ok, old_pass} ->
        if old_pass && String.length(old_pass) > 0 do
          case authenticate_by_email_password(attrs[:email], old_pass) do
            {:ok, _user} ->
              {:ok}
            {:error, :unauthorized} ->
              {:error}
          end
        else
          {:ok}
        end
      :error ->
        {:ok}
    end
  end

  def update_profile(user, attrs) do
    case verify_old_pass_if_exists(attrs) do
      {:ok} ->
        user
        |> User.profile_changeset(attrs)
        |> Repo.update
      {:error} ->
        {:error, :password_mismatch}
    end
  end
end